Skip to content

Commit 64aabef

Browse files
committed
Release 3.0.0
1 parent 07e3267 commit 64aabef

File tree

101 files changed

+3046
-2718
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+3046
-2718
lines changed

CHANGELOG.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
## 3.0.0 - 30 Jul 2025
2+
3+
- Adds the `onReady` callback to `NutrientView` to make functional component integration easier. (J#HYB-809)
4+
- Updates SDK to Nutrient branding. The new package name is now `@nutrient-sdk/react-native`.
5+
16
## 2.19.1 - 24 Jul 2025
27

3-
- Fixes an issue where `PSPDFKitView` component props were not reliably applied on Android. (J#HYB-836)
8+
- Fixes an issue where `PSPDFKitView` component props weren’t reliably applied on Android. (J#HYB-836)
49

510
## 2.19.0 - 02 Jul 2025
611

@@ -9,8 +14,10 @@
914
- Adds the `iOSDocumentInfoOptions` option to `PDFConfiguration` to customize Document Info tabs on iOS. (J#HYB-826)
1015
- Adds the `setExcludedAnnotations` API to exclude specified annotations completely from selection. (J#HYB-823)
1116
- Adds the `bookmarksChanged` event to `NotificationCenter` to receive bookmark change events. (J#HYB-818)
12-
- Adds the `getBookmarks`, `addBookmarks` and `removeBookmarks` APIs to `PDFDocument` for bookmark management. (J#HYB-818)
13-
- Fixes an issue where the `enterAnnotationCreationMode` API does not honour annotation variant options. (J#HYB-814)
17+
- Adds the `getBookmarks`, `addBookmarks`, and `removeBookmarks` APIs to `PDFDocument` for bookmark management. (J#HYB-818)
18+
- Updates to Nutrient Android SDK 10.4.1.
19+
- Updates to Nutrient iOS SDK 14.10.0.
20+
- Fixes an issue where the `enterAnnotationCreationMode` API does not honor annotation variant options. (J#HYB-814)
1421
- Fixes an issue where the `enterAnnotationCreationMode` API on iOS could not change tools when already active. (J#HYB-815)
1522
- Fixes an issue where `AnnotationsEvent.REMOVED` contained null `name` and `creatorName` properties on Android. (J#HYB-829)
1623

PROJECT_CONTEXT.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Nutrient React Native SDK Project Context
2+
3+
## Project Overview
4+
This is the official Nutrient React Native SDK repository. It provides React Native components and native modules for viewing, annotating, and manipulating PDF documents on iOS and Android platforms.
5+
6+
## Tech Stack
7+
- **React Native**: 0.73+ (supports both Legacy and New Architecture)
8+
- **Nutrient React Native SDK**: Native PDF viewing and annotation library
9+
- **TypeScript**: Primary language for JavaScript/TypeScript code
10+
- **iOS**: Swift/Objective-C native modules
11+
- **Android**: Kotlin/Java native modules
12+
- **Metro**: React Native bundler
13+
14+
## Architecture
15+
- **Architecture Support**: Legacy Bridge. New Architecture (Fabric/TurboModules) coming soon.
16+
- **Native Modules**: Custom Nutrient integration for both platforms
17+
- **View Components**: NutrientView component with native view implementations
18+
- **Event System**: Cross-platform event handling for document and annotation events
19+
20+
## Key Directories
21+
- `/pspdfkit-react-native/`: Main SDK source code
22+
- `/pspdfkit-react-native/src/`: TypeScript source files
23+
- `/pspdfkit-react-native/android/`: Android native implementation
24+
- `/pspdfkit-react-native/ios/`: iOS native implementation
25+
- `/pspdfkit-react-native/samples/Catalog/`: Example app
26+
- `/pspdfkit-react-native/types/`: TypeScript type definitions
27+
28+
## Important Files
29+
- `/pspdfkit-react-native/index.js`: Main SDK entry point and NutrientView component
30+
- `/pspdfkit-react-native/src/configuration/PDFConfiguration.ts`: Configuration options
31+
- `/pspdfkit-react-native/android/src/main/java/com/pspdfkit/react/`: Android native modules
32+
- `/pspdfkit-react-native/ios/RCTPSPDFKit/`: iOS native modules
33+
34+
## Development Conventions
35+
- **TypeScript First**: All new code should use TypeScript
36+
- **Dual Architecture**: Support both Legacy and New Architecture simultaneously
37+
- **Platform Parity**: Ensure iOS and Android implementations are feature-equivalent
38+
- **Event Consistency**: Use consistent event naming across platforms
39+
- **Configuration Objects**: Use strongly-typed configuration objects
40+
41+
## Key Components
42+
- **NutrientView**: Main React Native component for PDF viewing
43+
- **Nutrient**: Native module for document operations
44+
- **PDFConfiguration**: Configuration options for PDF behavior
45+
- **Toolbar**: Customization options for the PDF toolbar
46+
- **Annotation**: Annotation creation and management
47+
48+
## Migration Context
49+
- **Legacy Architecture**: Current bridge-based system
50+
- **New Architecture**: Fabric (rendering) + TurboModules (native modules)
51+
- **Dual Support**: Must maintain compatibility with both architectures
52+
- **Gradual Migration**: Users can opt into New Architecture when ready
53+
54+
## Common Patterns
55+
- **Event Handling**: Use consistent event naming (`onDocumentLoaded`, `onAnnotationTapped`)
56+
- **Configuration**: Pass configuration objects to customize behavior
57+
- **Native Modules**: Use platform-specific implementations with shared interfaces
58+
- **Error Handling**: Consistent error handling across platforms
59+
60+
## Important Notes
61+
- Nutrient is a commercial SDK requiring license keys
62+
- Support both trial mode (with watermarks) and licensed mode
63+
- Maintain backward compatibility during architecture migrations
64+
- Follow Nutrient's native SDK conventions for consistency

README.md

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ This library requires a valid license of the Nutrient SDK. Licenses are per plat
66

77
The Nutrient React Native SDK exposes the most often used APIs from Nutrient. Many of our partners end up forking this repository and adding some custom code to achieve even greater integration with their products, using native code.
88

9-
Windows is not currently supported, please use version [1.24.9](https://github.com/PSPDFKit/react-native/releases/tag/1.24.9) instead.
10-
119
### Nutrient
1210

1311
The [Nutrient SDK](https://nutrient.io/) is a framework that allows you to view, annotate, sign, and fill PDF forms on iOS, Android, Windows, macOS, and Web.
@@ -18,7 +16,7 @@ The [Nutrient SDK](https://nutrient.io/) is a framework that allows you to view,
1816

1917
Nutrient offers support for customers with an active SDK license via https://support.nutrient.io/hc/en-us/requests/new.
2018

21-
Are you evaluating our SDK? That's great, we're happy to help out! The Nutrient React Native SDK is a commercial product and requires the purchase of a license key when used in production. By default, this library will initialize in demo mode, placing a watermark on each PDF and limiting usage to 60 minutes.
19+
Are you evaluating our SDK? That's great, we're happy to help out! The Nutrient React Native SDK is a commercial product and requires the purchase of a license key when used in production. By default, this library will initialize in demo mode, placing a watermark on each PDF and limiting usage to 60 minutes.
2220

2321
To purchase a license for production use, please reach out to us via https://www.nutrient.io/sdk/contact-sales.
2422

@@ -53,7 +51,7 @@ PSPDFKit.setLicenseKey('YOUR_REACT_NATIVE_LICENSE_KEY_GOES_HERE');
5351

5452
### Installation
5553

56-
The Nutrient React Native SDK dependency is installed from the GitHub repository and not the `npm` registry. To install the Nutrient React Native SDK, run `yarn add react-native-pspdfkit@github:PSPDFKit/react-native` in your project directory or `npm install github:PSPDFKit/react-native` if you’re using `npm`.
54+
The Nutrient React Native SDK dependency is installed from the GitHub repository and not the `npm` registry. To install the Nutrient React Native SDK, run `yarn add @nutrient-sdk/react-native` in your project directory or `npm install @nutrient-sdk/react-native` if you’re using `npm`.
5755

5856
### Getting Started
5957

@@ -68,19 +66,19 @@ See our [Getting Started on React Native guide](https://www.nutrient.io/getting-
6866
1. Create the React Native project by running the following command:
6967

7068
```bash
71-
npx react-native init PSPDFKitDemo
69+
npx react-native init NutrientDemo
7270
```
7371

7472
1. In the terminal app, change the location of the current working directory inside the newly created project:
7573

7674
```bash
77-
cd PSPDFKitDemo
75+
cd NutrientDemo
7876
```
7977

8078
1. Add the Nutrient React Native SDK:
8179

8280
```bash
83-
yarn add react-native-pspdfkit@github:PSPDFKit/react-native
81+
yarn add @nutrient-sdk/react-native
8482
```
8583

8684
1. Install all the dependencies for the project:
@@ -101,9 +99,9 @@ See our [Getting Started on React Native guide](https://www.nutrient.io/getting-
10199
allprojects {
102100
repositories {
103101
mavenLocal()
104-
+ maven {
102+
+ maven {
105103
+ url 'https://my.nutrient.io/maven/'
106-
+ }
104+
+ }
107105
}
108106
}
109107
```
@@ -117,7 +115,7 @@ See our [Getting Started on React Native guide](https://www.nutrient.io/getting-
117115
+ compileSdkVersion 35
118116
...
119117
defaultConfig {
120-
applicationId "com.pspdfkitdemo"
118+
applicationId "com.nutrientdemo"
121119
- minSdkVersion rootProject.ext.minSdkVersion
122120
+ minSdkVersion 21
123121
targetSdkVersion rootProject.ext.targetSdkVersion
@@ -158,7 +156,7 @@ See our [Getting Started on React Native guide](https://www.nutrient.io/getting-
158156
1. Open your project’s Workspace in Xcode:
159157

160158
```bash
161-
open PSPDFKitDemo.xcworkspace
159+
open NutrientDemo.xcworkspace
162160
```
163161

164162
1. Make sure the deployment target is set to 16.0 or higher:
@@ -202,19 +200,19 @@ See our [Getting Started on React Native guide](https://www.nutrient.io/getting-
202200
```typescript
203201
import React, {Component} from 'react';
204202
import {Platform} from 'react-native';
205-
import PSPDFKitView from 'react-native-pspdfkit';
203+
import NutrientView from '@nutrient-sdk/react-native';
206204
import { NativeModules } from 'react-native';
207205

208-
const PSPDFKit = NativeModules.PSPDFKit;
209-
PSPDFKit.setLicenseKey(null);
206+
const Nutrient = NativeModules.Nutrient;
207+
Nutrient.setLicenseKey(null);
210208

211209
const DOCUMENT =
212210
Platform.OS === 'ios' ? 'Document.pdf' : 'file:///android_asset/Document.pdf';
213-
export default class PSPDFKitDemo extends Component<{}> {
211+
export default class NutrientDemo extends Component<{}> {
214212
render() {
215-
var pdfRef: React.RefObject<PSPDFKitView> = React.createRef();
213+
var pdfRef: React.RefObject<NutrientView | null> = React.createRef();
216214
return (
217-
<PSPDFKitView
215+
<NutrientView
218216
document={DOCUMENT}
219217
configuration={{
220218
showThumbnailBar: 'scrollable',
@@ -246,7 +244,7 @@ Take a look at the instructions to get started [here](/samples/Catalog/README.md
246244

247245
### Configuration
248246

249-
The behaviour of the `PSPDFKitView` component can be customized using the configuration object. Refer to the [`PDFConfiguration`](https://www.nutrient.io/api/react-native/PDFConfiguration.html) API documentation. The `PDFConfiguration` object can be passed as parameter in when creating the `PSPDFKitView` component, or when using the `PSPDFKit.present()` Native Module API.
247+
The behaviour of the `NutrientView` component can be customized using the configuration object. Refer to the [`PDFConfiguration`](https://www.nutrient.io/api/react-native/PDFConfiguration.html) API documentation. The `PDFConfiguration` object can be passed as parameter in when creating the `NutrientView` component, or when using the `Nutrient.present()` Native Module API.
250248

251249
```typescript
252250
const configuration: PDFConfiguration = {

android/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* build.gradle
33
*
4-
* PSPDFKit
4+
* Nutrient
55
*
66
* Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved.
77
*
@@ -15,7 +15,7 @@
1515
* Contains gradle configuration constants
1616
*/
1717
ext {
18-
PSPDFKIT_VERSION = '10.4.1'
18+
NUTRIENT_VERSION = '10.5.0'
1919
}
2020

2121
buildscript {
@@ -102,7 +102,7 @@ android {
102102
}
103103

104104
dependencies {
105-
api("io.nutrient:nutrient:${PSPDFKIT_VERSION}") {
105+
api("io.nutrient:nutrient:${NUTRIENT_VERSION}") {
106106
exclude group: 'com.google.auto.value', module: 'auto-value'
107107
exclude group: 'androidx.recyclerview', module: 'recyclerview'
108108
}

android/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
-->
1414

1515
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
16-
package="com.pspdfkit.react"
1716
android:versionCode="1"
1817
android:versionName="1.0">
1918

android/src/main/java/com/pspdfkit/react/PDFDocumentModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ class PDFDocumentModule(reactContext: ReactApplicationContext) : ReactContextBas
343343
@ReactMethod fun applyInstantJSON(reference: Int, instantJSON: ReadableMap, promise: Promise) {
344344
try {
345345
this.getDocument(reference)?.document?.let {
346-
val json = (instantJSON.toHashMap() as Map<*, *>?)?.let { it1 -> JSONObject(it1) }
346+
val json = (instantJSON.toHashMap() as? Map<*, *>)?.let { it1 -> JSONObject(it1) }
347347
val dataProvider: DataProvider = DocumentJsonDataProvider(json)
348348
DocumentJsonFormatter.importDocumentJsonAsync(it, dataProvider)
349349
.subscribeOn(Schedulers.io())

android/src/main/java/com/pspdfkit/react/PSPDFKitModule.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void initialize() {
109109

110110
@Override
111111
public String getName() {
112-
return "PSPDFKit";
112+
return "Nutrient";
113113
}
114114

115115
@ReactMethod
@@ -140,37 +140,37 @@ public void present(@NonNull String document, @NonNull ReadableMap configuration
140140

141141
@ReactMethod
142142
public void presentPdf(@NonNull String document, @NonNull ReadableMap configuration, @Nullable Promise promise) {
143-
if (getCurrentActivity() != null) {
143+
if (getReactApplicationContext().getCurrentActivity() != null) {
144144
if (resumedActivity == null) {
145145
// We register an activity lifecycle callback so we can get notified of the current activity.
146-
getCurrentActivity().getApplication().registerActivityLifecycleCallbacks(this);
146+
getReactApplicationContext().getCurrentActivity().getApplication().registerActivityLifecycleCallbacks(this);
147147
}
148-
ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(getCurrentActivity(), configuration);
148+
ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(getReactApplicationContext().getCurrentActivity(), configuration);
149149
// This is an edge case where file scheme is missing.
150150
if (Uri.parse(document).getScheme() == null) {
151151
document = FILE_SCHEME + document;
152152
}
153153

154154
lastPresentPromise = promise;
155-
PdfActivity.showDocument(getCurrentActivity(), Uri.parse(document), configurationAdapter.build());
155+
PdfActivity.showDocument(getReactApplicationContext().getCurrentActivity(), Uri.parse(document), configurationAdapter.build());
156156
}
157157
}
158158

159159
@ReactMethod
160160
public void presentImage(@NonNull String imageDocument, @NonNull ReadableMap configuration, @Nullable Promise promise) {
161-
if (getCurrentActivity() != null) {
161+
if (getReactApplicationContext().getCurrentActivity() != null) {
162162
if (resumedActivity == null) {
163163
// We register an activity lifecycle callback so we can get notified of the current activity.
164-
getCurrentActivity().getApplication().registerActivityLifecycleCallbacks(this);
164+
getReactApplicationContext().getCurrentActivity().getApplication().registerActivityLifecycleCallbacks(this);
165165
}
166-
ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(getCurrentActivity(), configuration);
166+
ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(getReactApplicationContext().getCurrentActivity(), configuration);
167167
// This is an edge case where file scheme is missing.
168168
if (Uri.parse(imageDocument).getScheme() == null) {
169169
imageDocument = FILE_SCHEME + imageDocument;
170170
}
171171

172172
lastPresentPromise = promise;
173-
PdfActivity.showImage(getCurrentActivity(), Uri.parse(imageDocument), configurationAdapter.build());
173+
PdfActivity.showImage(getReactApplicationContext().getCurrentActivity(), Uri.parse(imageDocument), configurationAdapter.build());
174174
}
175175
}
176176

@@ -187,12 +187,12 @@ public void presentInstant(@NonNull ReadableMap documentData, @NonNull ReadableM
187187
return;
188188
}
189189

190-
if (getCurrentActivity() != null) {
190+
if (getReactApplicationContext().getCurrentActivity() != null) {
191191
if (resumedActivity == null) {
192192
// We register an activity lifecycle callback so we can get notified of the current activity.
193-
getCurrentActivity().getApplication().registerActivityLifecycleCallbacks(this);
193+
getReactApplicationContext().getCurrentActivity().getApplication().registerActivityLifecycleCallbacks(this);
194194
}
195-
ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(getCurrentActivity(), configuration);
195+
ConfigurationAdapter configurationAdapter = new ConfigurationAdapter(getReactApplicationContext().getCurrentActivity(), configuration);
196196

197197
lastPresentPromise = promise;
198198

@@ -201,7 +201,7 @@ public void presentInstant(@NonNull ReadableMap documentData, @NonNull ReadableM
201201
@Override
202202
public void run() {
203203
try {
204-
RNInstantPdfActivity.showInstantDocument(getCurrentActivity(), serverUrl, jwt, configurationAdapter.build());
204+
RNInstantPdfActivity.showInstantDocument(getReactApplicationContext().getCurrentActivity(), serverUrl, jwt, configurationAdapter.build());
205205
} catch (Exception e) {
206206
// Could not start instant
207207
}

0 commit comments

Comments
 (0)