├── .buckconfig ├── .flowconfig ├── .git-blame-ignore-revs ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .prettierrc.js ├── .rubocop.yml ├── .watchmanconfig ├── ACKNOWLEDGEMENTS.md ├── CHANGELOG.md ├── LICENSE ├── License-Evaluation.pdf ├── README.md ├── android ├── .classpath ├── .project ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── pspdfkit │ │ ├── react │ │ ├── AnnotationConfigurationAdaptor.kt │ │ ├── ConfigurationAdapter.java │ │ ├── MainActivity.java │ │ ├── MainApplication.java │ │ ├── NutrientNotificationCenter.kt │ │ ├── PDFDocumentModule.kt │ │ ├── PSPDFKitModule.java │ │ ├── PSPDFKitPackage.java │ │ ├── RNInstantPdfActivity.java │ │ ├── RNProcessor.java │ │ ├── ReactPdfViewManager.java │ │ ├── TestingModule.java │ │ ├── ToolbarMenuItemsAdapter.java │ │ ├── annotations │ │ │ └── ReactAnnotationPresetConfiguration.kt │ │ ├── events │ │ │ ├── CustomAnnotationContextualMenuItemTappedEvent.kt │ │ │ ├── CustomToolbarButtonTappedEvent.kt │ │ │ ├── PdfViewAnnotationChangedEvent.java │ │ │ ├── PdfViewAnnotationTappedEvent.java │ │ │ ├── PdfViewDataReturnedEvent.java │ │ │ ├── PdfViewDocumentLoadFailedEvent.java │ │ │ ├── PdfViewDocumentLoadedEvent.java │ │ │ ├── PdfViewDocumentSaveFailedEvent.java │ │ │ ├── PdfViewDocumentSavedEvent.java │ │ │ ├── PdfViewNavigationButtonClickedEvent.java │ │ │ └── PdfViewStateChangedEvent.java │ │ ├── helper │ │ │ ├── AnnotationUtils.kt │ │ │ ├── ColorHelper.java │ │ │ ├── ConversionHelpers.java │ │ │ ├── DocumentJsonDataProvider.java │ │ │ ├── FormUtils.kt │ │ │ ├── JsonUtilities.java │ │ │ ├── MeasurementsHelper.kt │ │ │ ├── PSPDFKitUtils.kt │ │ │ ├── RNConfigurationHelper.java │ │ │ ├── RNFileHelper.java │ │ │ └── RemoteDocumentDownloader.kt │ │ └── menu │ │ │ ├── AnnotationContextualToolbarGroupingRule.java │ │ │ ├── ContextualToolbarMenuItemConfig.kt │ │ │ └── ReactGroupingRule.java │ │ └── views │ │ ├── MenuItemListener.kt │ │ ├── PdfView.java │ │ ├── PdfViewDocumentListener.java │ │ ├── PdfViewModeController.java │ │ ├── ReactMainToolbar.java │ │ ├── ReactPdfUiFragment.java │ │ └── ToolbarMenuItemListener.kt │ └── res │ ├── drawable │ └── pspdf__ic_navigation_arrow.xml │ ├── layout │ └── pspdf__toolbar_main.xml │ └── values │ └── attrs.xml ├── article-header.png ├── babel.config.js ├── documentation ├── configuration-options.md ├── jsdoc-assets │ ├── css │ │ ├── components │ │ │ ├── _code.css │ │ │ ├── _dash.css │ │ │ ├── _grid.css │ │ │ ├── _header.css │ │ │ ├── _main-content.css │ │ │ ├── _nav-sub.css │ │ │ ├── _scaffolding.css │ │ │ ├── _search.css │ │ │ └── _sidebar.css │ │ ├── highlight.css │ │ └── jsdoc-stock.css │ ├── img │ │ ├── dash.png │ │ ├── favicon.ico │ │ └── nutrient.svg │ ├── js │ │ ├── jazzy.js │ │ └── jquery.min.js │ └── vendor │ │ └── bootstrap │ │ ├── css │ │ ├── bootstrap.css │ │ └── bootstrap.css.map │ │ └── js │ │ └── bootstrap.js ├── jsdoc-layout.tmpl └── jsdoc.md ├── eslint.config.mjs ├── index.js ├── ios ├── RCTPSPDFKit.xcodeproj │ └── project.pbxproj └── RCTPSPDFKit │ ├── Converters │ ├── AnnotationConfigurationsConvertor.swift │ ├── PspdfkitMeasurementConvertor.swift │ ├── RCTConvert+FormElement.swift │ ├── RCTConvert+FormField.swift │ ├── RCTConvert+PSPDFAnnotation.h │ ├── RCTConvert+PSPDFAnnotation.m │ ├── RCTConvert+PSPDFAnnotationChange.h │ ├── RCTConvert+PSPDFAnnotationChange.m │ ├── RCTConvert+PSPDFAnnotationFlags.swift │ ├── RCTConvert+PSPDFAnnotationToolbarConfiguration.h │ ├── RCTConvert+PSPDFAnnotationToolbarConfiguration.m │ ├── RCTConvert+PSPDFAnnotationType.swift │ ├── RCTConvert+PSPDFConfiguration.h │ ├── RCTConvert+PSPDFConfiguration.m │ ├── RCTConvert+PSPDFDocument.h │ ├── RCTConvert+PSPDFDocument.m │ ├── RCTConvert+PSPDFEditMenuAppearance.swift │ ├── RCTConvert+PSPDFImageSaveMode.swift │ ├── RCTConvert+PSPDFViewMode.h │ ├── RCTConvert+PSPDFViewMode.m │ ├── RCTConvert+UIBarButtonItem.h │ └── RCTConvert+UIBarButtonItem.m │ ├── Helpers │ ├── AIAConfig.swift │ ├── RemoteDocumentDownloader.swift │ └── SessionStorage.swift │ ├── InstantDocumentInfo.swift │ ├── InstantDocumentViewController.swift │ ├── NSExceptionError.swift │ ├── NutrientNotificationCenter.swift │ ├── PDFDocumentManager.m │ ├── PDFDocumentManager.swift │ ├── RCTPSPDFKit-Bridging-Header.h │ ├── RCTPSPDFKitManager.h │ ├── RCTPSPDFKitManager.m │ ├── RCTPSPDFKitView.h │ ├── RCTPSPDFKitView.m │ ├── RCTPSPDFKitViewManager.h │ ├── RCTPSPDFKitViewManager.m │ ├── RNConfigurationHelper.swift │ ├── RNFileHelper.swift │ ├── RNProcessor.m │ ├── RNProcessor.swift │ └── UIColor.swift ├── jsdoc.json ├── lib ├── annotations │ ├── Annotation.js │ └── AnnotationModels.js ├── configuration │ ├── AIAssistantConfiguration.js │ └── PDFConfiguration.js ├── document │ ├── PDFDocument.js │ └── PDFPageInfo.js ├── forms │ ├── FormElement.js │ ├── FormField.js │ └── Forms.js ├── measurements │ └── Measurements.js ├── notification-center │ └── NotificationCenter.js └── toolbar │ └── Toolbar.js ├── package.json ├── rake.out ├── react-native-pspdfkit.podspec ├── samples ├── Catalog │ ├── .buckconfig │ ├── .editorconfig │ ├── .flowconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .node-version │ ├── .prettierrc.js │ ├── .ruby-version │ ├── .watchmanconfig │ ├── Catalog.tsx │ ├── ExamplesNavigationMenu.tsx │ ├── README.md │ ├── __tests__ │ │ └── App-test.js │ ├── android │ │ ├── .project │ │ ├── app │ │ │ ├── .classpath │ │ │ ├── .project │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── pspdfkit │ │ │ │ │ └── rn │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ ├── example_annotation_icon.xml │ │ │ │ └── example_toolbar_icon.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-ldpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── playstore-icon.png │ │ │ │ └── values │ │ │ │ ├── colors.xml │ │ │ │ ├── ids.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── app.json │ ├── assets │ │ ├── logo-flat.png │ │ ├── logo-flat@2x.png │ │ └── logo-flat@3x.png │ ├── babel.config.js │ ├── components │ │ ├── linkButton.tsx │ │ ├── primaryButton.tsx │ │ └── urlInput.tsx │ ├── configuration │ │ └── Constants.ts │ ├── eslint.config.mjs │ ├── examples │ │ ├── AIAssistant.tsx │ │ ├── AnnotationPresetCustomization.tsx │ │ ├── AnnotationProcessing.tsx │ │ ├── CustomFontPicker.tsx │ │ ├── EventListeners.tsx │ │ ├── GeneratePDF.tsx │ │ ├── GeneratePDFMenu.tsx │ │ ├── GetConfiguration.tsx │ │ ├── HiddenToolbar.tsx │ │ ├── HomeScreen.tsx │ │ ├── InstantSynchronization.tsx │ │ ├── ManualSave.tsx │ │ ├── Measurement.tsx │ │ ├── OpenImageDocument.tsx │ │ ├── OpenRemoteDocument.tsx │ │ ├── PSPDFKitViewComponent.tsx │ │ ├── PasswordProtectedDocument.tsx │ │ ├── ProgrammaticAnnotations.tsx │ │ ├── ProgrammaticFormFilling.tsx │ │ ├── SaveAs.tsx │ │ ├── SplitPDF.tsx │ │ ├── StateChange.tsx │ │ ├── ToolbarCustomization.tsx │ │ └── XFDF.tsx │ ├── helpers │ │ ├── AIAssistant │ │ │ └── AIAssistantHelper.ts │ │ ├── BaseExampleAutoHidingHeaderComponent.tsx │ │ ├── ExampleDocumentConfiguration.ts │ │ ├── FileHelper.ts │ │ ├── FileSystemHelpers.ts │ │ ├── ImageHelper.ts │ │ ├── NavigationHelper.ts │ │ ├── PSPDFKit.ts │ │ └── api │ │ │ ├── ApiClient.ts │ │ │ ├── ApiConfig.ts │ │ │ └── ApiRequest.ts │ ├── index.js │ ├── ios │ │ ├── .xcode.env │ │ ├── Catalog.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Catalog.xcscheme │ │ ├── Catalog.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── Catalog │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.mm │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── appicon_1024.png │ │ │ │ │ ├── appicon_120.png │ │ │ │ │ ├── appicon_152.png │ │ │ │ │ ├── appicon_167.png │ │ │ │ │ ├── appicon_180.png │ │ │ │ │ ├── appicon_20.png │ │ │ │ │ ├── appicon_29.png │ │ │ │ │ ├── appicon_40.png │ │ │ │ │ ├── appicon_58.png │ │ │ │ │ ├── appicon_60.png │ │ │ │ │ ├── appicon_76.png │ │ │ │ │ ├── appicon_80.png │ │ │ │ │ └── appicon_87.png │ │ │ │ ├── Contents.json │ │ │ │ ├── example_annotation_icon.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── bolt-100.png │ │ │ │ │ ├── bolt-25.png │ │ │ │ │ └── bolt-50.png │ │ │ │ └── example_toolbar_icon.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── key-100.png │ │ │ │ │ ├── key-25.png │ │ │ │ │ └── key-50.png │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ ├── PrivacyInfo.xcprivacy │ │ │ └── main.m │ │ ├── CatalogTests │ │ │ ├── CatalogTests.m │ │ │ └── Info.plist │ │ ├── Podfile │ │ ├── Podfile.lock │ │ ├── _xcode.env │ │ └── rake.out │ ├── metro.config.js │ ├── package.json │ ├── styles │ │ └── styles.js │ ├── tsconfig.json │ ├── windows │ │ └── Catalog │ │ │ └── ReactAssets │ │ │ └── .gitignore │ └── yarn.lock ├── NativeCatalog │ └── android │ │ └── app │ │ └── debug.keystore └── PDFs │ ├── Form_example.pdf │ ├── JKHF-AnnualReport.pdf │ ├── JohnAppleseed.p12 │ ├── JohnAppleseed.p7c │ ├── Measurements.pdf │ ├── PSPDFKit_Image_Example.jpg │ ├── PSPDFKit_Image_Example.tiff │ ├── PSPDFKit_Quickstart_Guide.pdf │ ├── PSPDFKit_Quickstart_Guide_Password.pdf │ ├── Resource_Depletion.pdf │ └── XFDFTest.xfdf ├── screenshots ├── changeVersionSDK.png ├── deployment-target.png ├── drag-and-drop-document.png ├── view-controller-based-status-bar-appearance.png ├── windowsAddExistingProject.PNG ├── windowsAddReferences.PNG └── windowsSelectPSPDFKit+UWP.PNG ├── src ├── annotations │ ├── Annotation.ts │ └── AnnotationModels.ts ├── configuration │ ├── AIAssistantConfiguration.ts │ └── PDFConfiguration.ts ├── document │ ├── PDFDocument.ts │ └── PDFPageInfo.ts ├── forms │ ├── FormElement.ts │ ├── FormField.ts │ └── Forms.ts ├── measurements │ └── Measurements.ts ├── notification-center │ └── NotificationCenter.ts └── toolbar │ └── Toolbar.ts ├── tsconfig-types.json ├── tsconfig.json ├── tsconfig.tsbuildinfo ├── types-scripts ├── append.js ├── fix-code-tags.js └── native-modules.ts ├── types ├── index.d.ts ├── index.d.ts.map └── tsconfig-types.tsbuildinfo └── yarn.lock /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/Libraries/react-native/react-native-interface.js 21 | node_modules/react-native/flow 22 | flow/ 23 | 24 | [options] 25 | emoji=true 26 | 27 | module.system=haste 28 | 29 | munge_underscores=true 30 | 31 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 32 | 33 | suppress_type=$FlowIssue 34 | suppress_type=$FlowFixMe 35 | suppress_type=$FixMe 36 | 37 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 38 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 40 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 41 | 42 | unsafe.enable_getters_and_setters=true 43 | 44 | [version] 45 | ^0.49.1 -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Updates header copyright year to 2021. 2 | 6a71db92c343a70f9a021886ae0af40b5dbf9423 3 | # Adds copyright header to files without it. 4 | 77e2f5f79e6eaf3e0bb2a32efdf660c6b91f58d5 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Details 2 | 3 | # Acceptance Criteria 4 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Details 2 | 3 | # Acceptance Criteria 4 | 5 | - [ ] When approved, right before merging, rebase with master and increment the package version in `package.json`, `package-lock.json`, `samples/Catalog/package.json`, `samples/Catalog/yarn.lock`, `samples/NativeCatalog/package.json`, and `samples/NativeCatalog/yarn.lock` (see example commit: https://github.com/PSPDFKit/react-native/pull/403/commits/b32b4edd97ee9b49c51c8b932e2bf477744c2b24). 6 | - [ ] Create a new release (and tag) with the new package version (see https://github.com/PSPDFKit/react-native/releases). 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | android/app/libs 43 | *.keystore 44 | 45 | PSPDFKit/PSPDFKit.framework 46 | PSPDFKit/PSPDFKitUI.framework 47 | PSPDFKit/PSPDFKit.xcframework 48 | PSPDFKit/PSPDFKitUI.xcframework 49 | 50 | # UWP license file 51 | samples/Catalog/windows/Catalog/License.xaml 52 | 53 | #Jsdoc 54 | jsdoc/ 55 | 56 | .fake 57 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | PSPDFKit/ 2 | samples/ 3 | interal/ 4 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: true, 3 | bracketSameLine: false, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | arrowParens: 'avoid', 7 | endOfLine: 'auto', 8 | printWidth: 80, 9 | tabWidth: 2, 10 | }; 11 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: ../../.rubocop.yml 2 | 3 | Naming/FileName: 4 | Enabled: false 5 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": [ 3 | ".git", 4 | "node_modules", 5 | "samples", 6 | "ios/build", 7 | "PSPDFKit", 8 | "internal" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | All items and source code Copyright © 2010-2025 PSPDFKit GmbH. 2 | 3 | The Nutrient SDK is a commercial product and requires a license to be used. 4 | 5 | See License-Evaluation.pdf if you are evaluating the demo. 6 | -------------------------------------------------------------------------------- /License-Evaluation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/License-Evaluation.pdf -------------------------------------------------------------------------------- /android/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android____ created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | 25 | 1666692500644 26 | 27 | 30 28 | 29 | org.eclipse.core.resources.regexFilterMatcher 30 | node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MainActivity.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react; 15 | 16 | import com.facebook.react.ReactActivity; 17 | 18 | public class MainActivity extends ReactActivity { 19 | 20 | /** 21 | * Returns the name of the main component registered from JavaScript. 22 | * This is used to schedule rendering of the component. 23 | */ 24 | @Override 25 | protected String getMainComponentName() { 26 | return "PSPDFKit"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/MainApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MainApplication.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react; 15 | 16 | import android.app.Application; 17 | 18 | import com.facebook.react.ReactApplication; 19 | import com.facebook.react.ReactNativeHost; 20 | import com.facebook.react.ReactPackage; 21 | import com.facebook.react.shell.MainReactPackage; 22 | import com.facebook.soloader.SoLoader; 23 | 24 | import java.util.Arrays; 25 | import java.util.List; 26 | 27 | public class MainApplication extends Application implements ReactApplication { 28 | 29 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 30 | @Override 31 | public boolean getUseDeveloperSupport() { 32 | return BuildConfig.DEBUG; 33 | } 34 | 35 | @Override 36 | protected List getPackages() { 37 | return Arrays.asList( 38 | new MainReactPackage(), 39 | new PSPDFKitPackage() 40 | ); 41 | } 42 | }; 43 | 44 | @Override 45 | public ReactNativeHost getReactNativeHost() { 46 | return mReactNativeHost; 47 | } 48 | 49 | @Override 50 | public void onCreate() { 51 | super.onCreate(); 52 | SoLoader.init(this, /* native exopackage */ false); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/PSPDFKitPackage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPDFKitPackage.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react; 15 | 16 | import android.app.Application; 17 | 18 | import com.facebook.react.ReactPackage; 19 | import com.facebook.react.bridge.JavaScriptModule; 20 | import com.facebook.react.bridge.NativeModule; 21 | import com.facebook.react.bridge.ReactApplicationContext; 22 | import com.facebook.react.uimanager.ViewManager; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.List; 27 | 28 | public class PSPDFKitPackage implements ReactPackage { 29 | 30 | @Override 31 | public List createNativeModules(ReactApplicationContext reactContext) { 32 | List modules = new ArrayList<>(); 33 | modules.add(new PSPDFKitModule(reactContext)); 34 | modules.add(new TestingModule(reactContext)); 35 | modules.add(new RNProcessor(reactContext)); 36 | modules.add(new PDFDocumentModule(reactContext)); 37 | return modules; 38 | } 39 | 40 | @Override 41 | public List createViewManagers(ReactApplicationContext reactContext) { 42 | List viewManagers = new ArrayList<>(); 43 | viewManagers.add(new ReactPdfViewManager()); 44 | return viewManagers; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/RNInstantPdfActivity.java: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react; 2 | 3 | /// Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 4 | /// 5 | /// THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 6 | /// AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 7 | /// UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 8 | /// This notice may not be removed from this file. 9 | /// 10 | 11 | import android.util.Log; 12 | 13 | import androidx.annotation.NonNull; 14 | 15 | import com.pspdfkit.document.PdfDocument; 16 | import com.pspdfkit.instant.document.InstantPdfDocument; 17 | import com.pspdfkit.instant.exceptions.InstantException; 18 | import com.pspdfkit.instant.ui.InstantPdfActivity; 19 | 20 | public class RNInstantPdfActivity extends InstantPdfActivity { 21 | 22 | @Override 23 | public void onDocumentLoaded(@NonNull PdfDocument document) { 24 | super.onDocumentLoaded(document); 25 | } 26 | 27 | @Override 28 | public void onSyncError(@NonNull InstantPdfDocument instantDocument, @NonNull InstantException error) { 29 | super.onSyncError(instantDocument, error); 30 | } 31 | 32 | @Override 33 | public void onSyncFinished(@NonNull InstantPdfDocument instantDocument) { 34 | super.onSyncFinished(instantDocument); 35 | Log.d("RNInstant::::::", "onSyncFinished: "); 36 | } 37 | 38 | @Override 39 | public void onSyncStarted(@NonNull InstantPdfDocument instantDocument) { 40 | super.onSyncStarted(instantDocument); 41 | Log.d("RNInstant::::::", "onSyncStarted: "); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/TestingModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * TestingModule.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react; 15 | 16 | import androidx.annotation.NonNull; 17 | 18 | import com.facebook.react.bridge.ReactApplicationContext; 19 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 20 | import com.facebook.react.bridge.ReactMethod; 21 | 22 | import java.util.HashMap; 23 | 24 | public class TestingModule extends ReactContextBaseJavaModule { 25 | 26 | private static final HashMap values = new HashMap<>(); 27 | 28 | public TestingModule(ReactApplicationContext reactContext) { 29 | super(reactContext); 30 | } 31 | 32 | @Override 33 | public String getName() { 34 | return "TestingModule"; 35 | } 36 | 37 | @ReactMethod 38 | public void setValue(@NonNull String key, @NonNull String value) { 39 | synchronized (values) { 40 | values.put(key, value); 41 | values.notifyAll(); 42 | } 43 | } 44 | 45 | public static void resetValues() { 46 | synchronized (values) { 47 | values.clear(); 48 | } 49 | } 50 | 51 | public static String getValue(@NonNull String key) throws InterruptedException { 52 | synchronized (values) { 53 | if (!values.containsKey(key)) { 54 | values.wait(60000); 55 | if (!values.containsKey(key)) { 56 | throw new IllegalArgumentException("Key " + key + " was not found. Got: " + values.toString()); 57 | } 58 | } 59 | return values.get(key); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/annotations/ReactAnnotationPresetConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.annotations 2 | 3 | import com.pspdfkit.annotations.AnnotationType 4 | import com.pspdfkit.annotations.configuration.AnnotationConfiguration 5 | import com.pspdfkit.ui.special_mode.controller.AnnotationTool 6 | import com.pspdfkit.ui.special_mode.controller.AnnotationToolVariant 7 | 8 | data class ReactAnnotationPresetConfiguration(val type: AnnotationType?, 9 | val annotationTool: AnnotationTool?, 10 | val variant: AnnotationToolVariant?, 11 | val configuration: AnnotationConfiguration) -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/CustomAnnotationContextualMenuItemTappedEvent.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.events 2 | 3 | import androidx.annotation.IdRes 4 | import com.facebook.react.bridge.Arguments 5 | import com.facebook.react.uimanager.events.Event 6 | import com.facebook.react.uimanager.events.RCTEventEmitter 7 | 8 | class CustomAnnotationContextualMenuItemTappedEvent: Event { 9 | private var buttonId: String? = null 10 | 11 | constructor(@IdRes viewId: Int, buttonId: String) : super(viewId) { 12 | 13 | this.buttonId = buttonId 14 | } 15 | 16 | override fun getEventName(): String { 17 | return EVENT_NAME 18 | } 19 | 20 | override fun dispatch(rctEventEmitter: RCTEventEmitter) { 21 | val eventData = Arguments.createMap() 22 | eventData.putString("id", buttonId) 23 | rctEventEmitter.receiveEvent(viewTag, eventName, eventData) 24 | } 25 | 26 | companion object { 27 | @kotlin.jvm.JvmField 28 | var EVENT_NAME = "customAnnotationContextualMenuItemTapped" 29 | } 30 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/CustomToolbarButtonTappedEvent.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.events 2 | 3 | import androidx.annotation.IdRes 4 | import com.facebook.react.bridge.Arguments 5 | import com.facebook.react.uimanager.events.Event 6 | import com.facebook.react.uimanager.events.RCTEventEmitter 7 | 8 | class CustomToolbarButtonTappedEvent: Event { 9 | 10 | private var buttonId: String? = null 11 | 12 | constructor(@IdRes viewId: Int, buttonId: String) : super(viewId) { 13 | this.buttonId = buttonId 14 | } 15 | 16 | override fun getEventName(): String { 17 | return EVENT_NAME 18 | } 19 | 20 | override fun dispatch(rctEventEmitter: RCTEventEmitter) { 21 | val eventData = Arguments.createMap() 22 | eventData.putString("id", buttonId) 23 | rctEventEmitter.receiveEvent(viewTag, eventName, eventData) 24 | } 25 | 26 | companion object { 27 | @kotlin.jvm.JvmField 28 | var EVENT_NAME = "customToolbarButtonTapped" 29 | } 30 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/PdfViewAnnotationTappedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PdfViewAnnotationTappedEvent.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.events; 15 | 16 | import androidx.annotation.IdRes; 17 | import androidx.annotation.NonNull; 18 | 19 | import com.facebook.react.bridge.Arguments; 20 | import com.facebook.react.bridge.WritableMap; 21 | import com.facebook.react.uimanager.events.Event; 22 | import com.facebook.react.uimanager.events.RCTEventEmitter; 23 | import com.pspdfkit.annotations.Annotation; 24 | import com.pspdfkit.annotations.AnnotationType; 25 | import com.pspdfkit.annotations.WidgetAnnotation; 26 | import com.pspdfkit.forms.FormElement; 27 | import com.pspdfkit.react.helper.AnnotationUtils; 28 | import com.pspdfkit.react.helper.JsonUtilities; 29 | 30 | import org.json.JSONException; 31 | import org.json.JSONObject; 32 | 33 | import java.util.Map; 34 | 35 | /** 36 | * Event sent by the {@link com.pspdfkit.views.PdfView} when an annotation was selected. 37 | */ 38 | public class PdfViewAnnotationTappedEvent extends Event { 39 | 40 | public static final String EVENT_NAME = "pdfViewAnnotationTapped"; 41 | 42 | @NonNull 43 | private final Annotation annotation; 44 | 45 | public PdfViewAnnotationTappedEvent(@IdRes int viewId, @NonNull Annotation annotation) { 46 | super(viewId); 47 | this.annotation = annotation; 48 | } 49 | 50 | @Override 51 | public String getEventName() { 52 | return EVENT_NAME; 53 | } 54 | 55 | @Override 56 | public void dispatch(RCTEventEmitter rctEventEmitter) { 57 | try { 58 | String rawInstantJson = annotation.toInstantJson(); 59 | if (rawInstantJson != null && !rawInstantJson.equals("null")) { 60 | Map annotationMap = AnnotationUtils.processAnnotation(annotation); 61 | WritableMap eventData = Arguments.makeNativeMap(annotationMap); 62 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); 63 | } 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadFailedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PdfViewDocumentLoadFailedEvent.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.events; 15 | 16 | import androidx.annotation.IdRes; 17 | import androidx.annotation.NonNull; 18 | 19 | import com.facebook.react.bridge.Arguments; 20 | import com.facebook.react.bridge.WritableMap; 21 | import com.facebook.react.uimanager.events.Event; 22 | import com.facebook.react.uimanager.events.RCTEventEmitter; 23 | 24 | /** 25 | * Event sent by the {@link com.pspdfkit.views.PdfView} when the document load failed. 26 | */ 27 | public class PdfViewDocumentLoadFailedEvent extends Event { 28 | 29 | public static final String EVENT_NAME = "pdfViewDocumentLoadFailed"; 30 | 31 | private final String error; 32 | 33 | public PdfViewDocumentLoadFailedEvent(@IdRes int viewId, @NonNull String error) { 34 | super(viewId); 35 | this.error = error; 36 | } 37 | 38 | @Override 39 | public String getEventName() { 40 | return EVENT_NAME; 41 | } 42 | 43 | @Override 44 | public void dispatch(RCTEventEmitter rctEventEmitter) { 45 | WritableMap eventData = Arguments.createMap(); 46 | eventData.putString("error", error); 47 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentLoadedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PdfViewDocumentSavedEvent.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.events; 15 | 16 | import androidx.annotation.IdRes; 17 | 18 | import com.facebook.react.bridge.Arguments; 19 | import com.facebook.react.bridge.WritableMap; 20 | import com.facebook.react.uimanager.events.Event; 21 | import com.facebook.react.uimanager.events.RCTEventEmitter; 22 | 23 | /** 24 | * Event sent by the {@link com.pspdfkit.views.PdfView} when the document was saved. 25 | */ 26 | public class PdfViewDocumentLoadedEvent extends Event { 27 | 28 | public static final String EVENT_NAME = "pdfViewDocumentLoaded"; 29 | 30 | public PdfViewDocumentLoadedEvent(@IdRes int viewId) { 31 | super(viewId); 32 | } 33 | 34 | @Override 35 | public String getEventName() { 36 | return EVENT_NAME; 37 | } 38 | 39 | @Override 40 | public void dispatch(RCTEventEmitter rctEventEmitter) { 41 | WritableMap eventData = Arguments.createMap(); 42 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSaveFailedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PdfViewDocumentSaveFailedEvent.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.events; 15 | 16 | import androidx.annotation.IdRes; 17 | import androidx.annotation.NonNull; 18 | 19 | import com.facebook.react.bridge.Arguments; 20 | import com.facebook.react.bridge.WritableMap; 21 | import com.facebook.react.uimanager.events.Event; 22 | import com.facebook.react.uimanager.events.RCTEventEmitter; 23 | 24 | /** 25 | * Event sent by the {@link com.pspdfkit.views.PdfView} when the document save failed. 26 | */ 27 | public class PdfViewDocumentSaveFailedEvent extends Event { 28 | 29 | public static final String EVENT_NAME = "pdfViewDocumentSaveFailed"; 30 | 31 | private final String error; 32 | 33 | public PdfViewDocumentSaveFailedEvent(@IdRes int viewId, @NonNull String error) { 34 | super(viewId); 35 | this.error = error; 36 | } 37 | 38 | @Override 39 | public String getEventName() { 40 | return EVENT_NAME; 41 | } 42 | 43 | @Override 44 | public void dispatch(RCTEventEmitter rctEventEmitter) { 45 | WritableMap eventData = Arguments.createMap(); 46 | eventData.putString("error", error); 47 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/PdfViewDocumentSavedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PdfViewDocumentSavedEvent.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.events; 15 | 16 | import androidx.annotation.IdRes; 17 | 18 | import com.facebook.react.bridge.Arguments; 19 | import com.facebook.react.bridge.WritableMap; 20 | import com.facebook.react.uimanager.events.Event; 21 | import com.facebook.react.uimanager.events.RCTEventEmitter; 22 | 23 | /** 24 | * Event sent by the {@link com.pspdfkit.views.PdfView} when the document was saved. 25 | */ 26 | public class PdfViewDocumentSavedEvent extends Event { 27 | 28 | public static final String EVENT_NAME = "pdfViewDocumentSaved"; 29 | 30 | public PdfViewDocumentSavedEvent(@IdRes int viewId) { 31 | super(viewId); 32 | } 33 | 34 | @Override 35 | public String getEventName() { 36 | return EVENT_NAME; 37 | } 38 | 39 | @Override 40 | public void dispatch(RCTEventEmitter rctEventEmitter) { 41 | WritableMap eventData = Arguments.createMap(); 42 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/events/PdfViewNavigationButtonClickedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PdfViewNavigationButtonClickedEvent.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.events; 15 | 16 | import androidx.annotation.IdRes; 17 | 18 | import com.facebook.react.bridge.Arguments; 19 | import com.facebook.react.bridge.WritableMap; 20 | import com.facebook.react.uimanager.events.Event; 21 | import com.facebook.react.uimanager.events.RCTEventEmitter; 22 | 23 | /** 24 | * Event sent by the {@link com.pspdfkit.views.PdfView} when navigation button was clicked. 25 | */ 26 | public class PdfViewNavigationButtonClickedEvent extends Event { 27 | 28 | public static final String EVENT_NAME = "pdfViewNavgigationButtonClicked"; 29 | 30 | public PdfViewNavigationButtonClickedEvent(@IdRes int viewId) { 31 | super(viewId); 32 | } 33 | 34 | @Override 35 | public String getEventName() { 36 | return EVENT_NAME; 37 | } 38 | 39 | @Override 40 | public void dispatch(RCTEventEmitter rctEventEmitter) { 41 | WritableMap eventData = Arguments.createMap(); 42 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/helper/AnnotationUtils.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.helper 2 | 3 | import com.pspdfkit.annotations.Annotation 4 | import com.pspdfkit.annotations.AnnotationType 5 | import com.pspdfkit.annotations.WidgetAnnotation 6 | import org.json.JSONObject 7 | 8 | object AnnotationUtils { 9 | @JvmStatic 10 | fun processAnnotation(annotation: Annotation): Map { 11 | return try { 12 | val instantJson = JSONObject(annotation.toInstantJson()) 13 | val annotationMap = JsonUtilities.jsonObjectToMap(instantJson) 14 | // Keeping the uuid and isRequired props for backwards compatibility 15 | annotationMap["uuid"] = annotation.uuid 16 | if (annotation.type == AnnotationType.WIDGET) { 17 | val widgetAnnotation: WidgetAnnotation = annotation as WidgetAnnotation 18 | widgetAnnotation.formElement?.let { formElement -> 19 | annotationMap["formElement"] = FormUtils.formElementToJSON(formElement) 20 | annotationMap["isRequired"] = widgetAnnotation.formElement?.isRequired 21 | } 22 | } 23 | annotationMap 24 | } catch (e: Exception) { 25 | e.printStackTrace() 26 | emptyMap() 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/helper/ColorHelper.java: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.helper; 2 | 3 | /* 4 | * PSPDFKitPackage.java 5 | * 6 | * PSPDFKit 7 | * 8 | * Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 9 | * 10 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 11 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 12 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 13 | * This notice may not be removed from this file. 14 | */ 15 | 16 | import android.graphics.Color; 17 | 18 | public class ColorHelper { 19 | public static int rgb(String color) { 20 | try{ 21 | String splitStr = color.substring(color.indexOf('(') + 1, color.indexOf(')')); 22 | String[] components = splitStr.split(","); 23 | 24 | int[] colorValues = new int[components.length]; 25 | for (int i = 0; i < components.length; i++) { 26 | double channelColor = Double.parseDouble(components[i].trim()); 27 | if(channelColor > 1) { 28 | colorValues[i] = Integer.parseInt(components[i].trim()); 29 | continue; 30 | } 31 | colorValues[i] = (int)(channelColor * 255); 32 | } 33 | 34 | return Color.rgb(colorValues[0], colorValues[1], colorValues[2]); 35 | } catch(Exception ex) { 36 | return Color.parseColor("#FFFFFF"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/helper/DocumentJsonDataProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DocumentJsonDataProvider.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.helper; 15 | 16 | import androidx.annotation.NonNull; 17 | import androidx.annotation.Nullable; 18 | 19 | import com.pspdfkit.document.providers.DataProvider; 20 | 21 | import org.json.JSONObject; 22 | 23 | import java.nio.charset.Charset; 24 | 25 | /** 26 | * {@link DataProvider} that is used when adding document instant json. 27 | */ 28 | public class DocumentJsonDataProvider implements DataProvider { 29 | 30 | private final byte[] jsonData; 31 | 32 | public DocumentJsonDataProvider(JSONObject documentJson) { 33 | jsonData = documentJson.toString().getBytes(Charset.forName("UTF-8")); 34 | } 35 | 36 | @NonNull 37 | @Override 38 | public byte[] read(long size, long offset) { 39 | return jsonData; 40 | } 41 | 42 | @Override 43 | public long getSize() { 44 | return jsonData.length; 45 | } 46 | 47 | @NonNull 48 | @Override 49 | public String getUid() { 50 | return "Json Data"; 51 | } 52 | 53 | @Nullable 54 | @Override 55 | public String getTitle() { 56 | return "Json Data"; 57 | } 58 | 59 | @Override 60 | public void release() { 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/helper/JsonUtilities.java: -------------------------------------------------------------------------------- 1 | /* 2 | * JsonUtilities.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.helper; 15 | 16 | import org.json.JSONArray; 17 | import org.json.JSONException; 18 | import org.json.JSONObject; 19 | 20 | import java.util.ArrayList; 21 | import java.util.HashMap; 22 | import java.util.Iterator; 23 | import java.util.List; 24 | import java.util.Map; 25 | 26 | public class JsonUtilities { 27 | 28 | /** 29 | * Converts the given {@link JSONObject} to a {@link Map}. 30 | */ 31 | public static Map jsonObjectToMap(JSONObject object) throws JSONException { 32 | Map map = new HashMap<>(object.length()); 33 | 34 | Iterator keysItr = object.keys(); 35 | while (keysItr.hasNext()) { 36 | String key = keysItr.next(); 37 | Object value = object.get(key); 38 | 39 | if (value instanceof JSONArray) { 40 | value = toList((JSONArray) value); 41 | } else if (value instanceof JSONObject) { 42 | value = jsonObjectToMap((JSONObject) value); 43 | } else if ( value == JSONObject.NULL) { 44 | value = null; 45 | } 46 | map.put(key, value); 47 | } 48 | return map; 49 | } 50 | 51 | private static List toList(JSONArray array) throws JSONException { 52 | List list = new ArrayList<>(array.length()); 53 | for (int i = 0; i < array.length(); i++) { 54 | Object value = array.get(i); 55 | if (value instanceof JSONArray) { 56 | value = toList((JSONArray) value); 57 | } else if (value instanceof JSONObject) { 58 | value = jsonObjectToMap((JSONObject) value); 59 | } else if ( value == JSONObject.NULL) { 60 | value = null; 61 | } 62 | list.add(value); 63 | } 64 | return list; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/helper/PSPDFKitUtils.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.helper 2 | 3 | import android.content.Context 4 | import java.io.File 5 | import java.util.Locale 6 | 7 | 8 | class PSPDFKitUtils { 9 | companion object { 10 | 11 | private val SUPPORTED_IMAGE_TYPES = arrayOf( 12 | ".jpg", 13 | ".png", 14 | ".jpeg", 15 | ".tif", 16 | ".tiff" 17 | ) 18 | 19 | @JvmStatic 20 | public fun isValidImage(path: String): Boolean { 21 | val file = File(path) 22 | for (extension in SUPPORTED_IMAGE_TYPES) { 23 | if (file.name.lowercase(Locale.getDefault()).endsWith(extension)) { 24 | return true 25 | } 26 | } 27 | return false 28 | } 29 | 30 | @JvmStatic 31 | public fun isValidPdf(path: String): Boolean { 32 | val file = File(path) 33 | return file.name.lowercase(Locale.getDefault()).endsWith(".pdf") 34 | } 35 | 36 | @JvmStatic 37 | public fun getCustomResourceId(resName: String, type: String, context: Context): Int { 38 | return context.resources.getIdentifier(resName, type, context.packageName) 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/helper/RNFileHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * PSPDFKitPackage.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.react.helper; 15 | 16 | import android.content.Context; 17 | import android.os.Environment; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.annotation.Nullable; 21 | 22 | import com.facebook.react.bridge.Promise; 23 | import com.facebook.react.bridge.ReadableMap; 24 | 25 | import java.io.File; 26 | import java.util.Locale; 27 | 28 | public class RNFileHelper { 29 | static public @Nullable 30 | File getFilePath(Context context, @NonNull ReadableMap configuration, Promise callback) { 31 | @Nullable String filePath = configuration.getString("filePath"); 32 | if (filePath != null) { 33 | if (!hasPdfExtension(filePath)) { 34 | filePath += ".pdf"; 35 | } 36 | return new File(filePath); 37 | } 38 | 39 | @Nullable String name = configuration.getString("name"); 40 | if (name == null) { 41 | callback.reject("E_NEW_MISSING_NAME", "Pls provide name for document"); 42 | return null; 43 | } 44 | 45 | boolean folderExists = true; 46 | 47 | File folder = new File(context.getFilesDir() + 48 | File.separator); 49 | if (!folder.exists()) { 50 | folderExists = folder.mkdir(); 51 | } 52 | 53 | if (!folderExists) { 54 | callback.reject("E_MISSING_FOLDER", "Cannot create documents folder"); 55 | return null; 56 | } 57 | filePath = folder.getAbsolutePath() + System.getProperty("file.separator") + name; 58 | if (!hasPdfExtension(filePath)) { 59 | filePath += ".pdf"; 60 | } 61 | return new File(filePath); 62 | } 63 | 64 | static public String getTemporaryDirectory(Context context) { 65 | File tempFolder = new File(context.getFilesDir() + File.separator); 66 | if (!tempFolder.exists()) { 67 | //noinspection ResultOfMethodCallIgnored 68 | tempFolder.mkdir(); 69 | } 70 | return tempFolder.getAbsolutePath(); 71 | } 72 | 73 | public static void deleteExistingFileIfNeeded(File outputFile, @NonNull ReadableMap configuration, Promise callback) { 74 | boolean shouldOverride = configuration.getBoolean("override"); 75 | if (outputFile.exists() && !shouldOverride) { 76 | callback.reject("E_FILE_EXISTS", "File with the same name already exists"); 77 | } 78 | } 79 | 80 | public static Boolean hasPdfExtension(String filePath) { 81 | return filePath.substring(filePath.length() - 4).toLowerCase(Locale.ROOT).equals(".pdf"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/menu/AnnotationContextualToolbarGroupingRule.java: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.menu; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | 6 | import com.pspdfkit.ui.toolbar.ContextualToolbarMenuItem; 7 | import com.pspdfkit.ui.toolbar.grouping.presets.AnnotationEditingToolbarGroupingRule; 8 | import com.pspdfkit.ui.toolbar.grouping.presets.MenuItem; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | public class AnnotationContextualToolbarGroupingRule extends AnnotationEditingToolbarGroupingRule { 12 | 13 | List menuItems; 14 | 15 | public AnnotationContextualToolbarGroupingRule(@NonNull Context context, @NonNull List menuItems) { 16 | super(context); 17 | this.menuItems = menuItems; 18 | } 19 | 20 | @NonNull 21 | @Override 22 | public List getGroupPreset(int capacity, int itemsCount) { 23 | List groupPreset = 24 | new ArrayList<>(super.getGroupPreset(capacity - 1, itemsCount - 1)); 25 | for (ContextualToolbarMenuItem menuItem : menuItems) { 26 | groupPreset.add(new MenuItem(menuItem.getId())); 27 | } 28 | return groupPreset; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/react/menu/ContextualToolbarMenuItemConfig.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.react.menu 2 | 3 | import com.pspdfkit.ui.toolbar.ContextualToolbarMenuItem 4 | import com.pspdfkit.views.ToolbarMenuItemListener 5 | 6 | class ContextualToolbarMenuItemConfig(menuItems: List, retain: Boolean = true, listener: ToolbarMenuItemListener) { 7 | val annotationSelectionMenuItems: List 8 | val retainSuggestedMenuItems: Boolean 9 | val toolbarMenuItemListener: ToolbarMenuItemListener 10 | 11 | init { 12 | annotationSelectionMenuItems = menuItems 13 | retainSuggestedMenuItems = retain 14 | toolbarMenuItemListener = listener 15 | } 16 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/views/MenuItemListener.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.views 2 | 3 | import android.content.Context 4 | import android.util.Log 5 | import android.view.MenuItem 6 | import androidx.annotation.NonNull 7 | import com.facebook.react.uimanager.events.EventDispatcher 8 | import com.pspdfkit.react.events.CustomToolbarButtonTappedEvent 9 | 10 | class MenuItemListener: MenuItem.OnMenuItemClickListener { 11 | 12 | private var parent: PdfView? = null 13 | private var eventDispatcher: EventDispatcher? = null 14 | private var context: Context? = null; 15 | 16 | constructor(parent: PdfView, eventDispatcher: EventDispatcher, context: Context) { 17 | this.parent = parent 18 | this.eventDispatcher = eventDispatcher 19 | this.context = context 20 | } 21 | 22 | override fun onMenuItemClick(menuItem: MenuItem): Boolean { 23 | val resourceName: String? = context?.resources?.getResourceEntryName(menuItem.itemId) 24 | if (resourceName != null) { 25 | parent?.let { CustomToolbarButtonTappedEvent(it.id, resourceName) } 26 | ?.let { eventDispatcher!!.dispatchEvent(it) } 27 | } 28 | return false 29 | } 30 | } -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/views/ReactMainToolbar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ReactMainToolbar.java 3 | * 4 | * PSPDFKit 5 | * 6 | * Copyright © 2021-2025 PSPDFKit GmbH. All rights reserved. 7 | * 8 | * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 9 | * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 10 | * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 11 | * This notice may not be removed from this file. 12 | */ 13 | 14 | package com.pspdfkit.views; 15 | 16 | import android.content.Context; 17 | import android.util.AttributeSet; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.annotation.Nullable; 21 | 22 | import com.pspdfkit.ui.toolbar.MainToolbar; 23 | 24 | /** Custom toolbar that allows us to force a visibility. */ 25 | public class ReactMainToolbar extends MainToolbar { 26 | 27 | private @Nullable Integer forcedVisibility; 28 | 29 | public ReactMainToolbar(@NonNull Context context) { 30 | super(context); 31 | } 32 | 33 | public ReactMainToolbar(@NonNull Context context, @Nullable AttributeSet attrs) { 34 | super(context, attrs); 35 | } 36 | 37 | public ReactMainToolbar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 38 | super(context, attrs, defStyleAttr); 39 | } 40 | 41 | /** 42 | * Sets a forced visibility that will override all future calls to {@link #setVisibility(int)}. The visibility will also immediately be applied. 43 | * 44 | * @param visibility The visibility to force or {@code null} to not force any specific visibility. 45 | */ 46 | public void setForcedVisibility(@Nullable final Integer visibility) { 47 | forcedVisibility = visibility; 48 | if (forcedVisibility != null) { 49 | setVisibility(forcedVisibility); 50 | } 51 | } 52 | 53 | @Override 54 | public void setVisibility(int visibility) { 55 | if (forcedVisibility == null) { 56 | super.setVisibility(visibility); 57 | } else { 58 | super.setVisibility(forcedVisibility); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android/src/main/java/com/pspdfkit/views/ToolbarMenuItemListener.kt: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.views 2 | 3 | import android.content.Context 4 | import com.facebook.react.uimanager.events.EventDispatcher 5 | import com.pspdfkit.react.events.CustomAnnotationContextualMenuItemTappedEvent 6 | import com.pspdfkit.ui.toolbar.ContextualToolbar 7 | import com.pspdfkit.ui.toolbar.ContextualToolbarMenuItem 8 | 9 | class ToolbarMenuItemListener: ContextualToolbar.OnMenuItemClickListener { 10 | 11 | private var parent: PdfView? = null 12 | private var eventDispatcher: EventDispatcher? = null 13 | private var context: Context? = null 14 | private var resourceIds: List = ArrayList() 15 | 16 | constructor(parent: PdfView, eventDispatcher: EventDispatcher, context: Context) { 17 | this.parent = parent 18 | this.eventDispatcher = eventDispatcher 19 | this.context = context 20 | } 21 | 22 | fun setResourceIds(resIds: List) { 23 | this.resourceIds = resIds 24 | } 25 | 26 | override fun onToolbarMenuItemClick(toolbar: ContextualToolbar<*>, menuItem: ContextualToolbarMenuItem): Boolean { 27 | // Check if the selected item is part of the custom items list 28 | if (this.resourceIds.contains(menuItem.id)) { 29 | val resourceName: String? = context?.resources?.getResourceEntryName(menuItem.id) 30 | if (resourceName != null) { 31 | parent?.let { CustomAnnotationContextualMenuItemTappedEvent(it.id, resourceName) } 32 | ?.let { eventDispatcher!!.dispatchEvent(it) } 33 | } 34 | return true 35 | } 36 | return false 37 | } 38 | } -------------------------------------------------------------------------------- /android/src/main/res/drawable/pspdf__ic_navigation_arrow.xml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/src/main/res/layout/pspdf__toolbar_main.xml: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /android/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /article-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/article-header.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /documentation/configuration-options.md: -------------------------------------------------------------------------------- 1 | ### Configuration Options 2 | 3 | Here's the complete list of configuration options supported by each platform. Note that some options are only supported on a single platform — that's because of differences in the behavior of both of these platforms. Options that work on only one platform are prefixed with the appropriate platform name: `android` or `iOS`. 4 | 5 | This list has now moved to the React Native API Reference. See the available configuration options here: https://pspdfkit.com/api/react-native/PDFConfiguration.html -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_code.css: -------------------------------------------------------------------------------- 1 | pre, 2 | code { 3 | font: 4 | 12px Menlo, 5 | monospace; 6 | color: #777; 7 | word-break: break-word; 8 | margin: 0; 9 | } 10 | 11 | pre { 12 | margin: 1em 0; 13 | display: table; 14 | } 15 | 16 | pre code { 17 | white-space: pre; 18 | } 19 | 20 | p code, 21 | li code { 22 | background-color: #eee; 23 | padding: 2px 4px; 24 | border-radius: 4px; 25 | } 26 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_dash.css: -------------------------------------------------------------------------------- 1 | .dash-link { 2 | float: right; 3 | display: block; 4 | background: #EFEBE7; 5 | color: #fff; 6 | padding: 2px 6px; 7 | line-height: 20px; 8 | } 9 | 10 | .dash-link:hover { 11 | color: #fff; 12 | } 13 | 14 | .dash-link img { 15 | width: 20px; 16 | height: 20px; 17 | margin-right: 5px; 18 | } 19 | 20 | html.dash .dash-link { 21 | display: none; 22 | } 23 | 24 | html.dash .container-col-sidebar, 25 | html.dash .nav-sub { 26 | display: none; 27 | } 28 | 29 | html.dash .container-col-content, 30 | html.dash .main-content { 31 | width: 100% !important; 32 | height: 100% !important; 33 | display: block !important; 34 | border: none; 35 | } 36 | 37 | html.dash .height-container { 38 | display: block; 39 | } 40 | 41 | html.dash .item .token { 42 | margin-left: 0; 43 | } 44 | 45 | html.dash .content-wrapper { 46 | width: auto; 47 | } 48 | 49 | html.dash .pointer-container { 50 | display: none; 51 | } 52 | 53 | html.dash .height-container .section { 54 | background: #fff; 55 | } 56 | 57 | html.dash h3 { 58 | margin: 0; 59 | } 60 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_grid.css: -------------------------------------------------------------------------------- 1 | .col-xs-12 { 2 | padding-left: 0; 3 | padding-right: 0; 4 | } 5 | 6 | @media (min-width: 768px) { 7 | .col-xs-12 { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_header.css: -------------------------------------------------------------------------------- 1 | .header { 2 | background: #EFEBE7; 3 | } 4 | 5 | .nav-bar { 6 | font-family: 'Canal Medium', Helvetica, Arial, sans-serif; 7 | background: #EFEBE7; 8 | font-weight: 400; 9 | line-height: 29.05px; 10 | color: #000000; 11 | text-align: center; 12 | max-width: 1700px; 13 | margin: 0 auto; 14 | display: flex; 15 | 16 | height: 62px; 17 | justify-content: center; 18 | } 19 | 20 | .nav-bar .nav-brand { 21 | margin: auto; 22 | } 23 | 24 | .nav-bar .nav-block { 25 | display: flex; 26 | list-style: none; 27 | margin-right: 0; 28 | padding: 0; 29 | } 30 | 31 | .nav-bar .nav-block-first { 32 | width: 60vw; 33 | max-width: 500px; 34 | margin-right: auto; 35 | } 36 | 37 | .nav-bar .nav-block-last { 38 | width: 30vw; 39 | max-width: 300px; 40 | margin-left: auto; 41 | justify-content: flex-end; 42 | } 43 | 44 | .nav-bar .nav-item { 45 | margin: 0 1vw; 46 | border-top: 5px solid transparent; 47 | padding-top: 15.8833px; 48 | } 49 | 50 | .nav-bar .nav-item.active { 51 | border-top-color: #C2B8AE; 52 | } 53 | 54 | .nav-bar .nav-item.active > .nav-link { 55 | color: #C2B8AE; 56 | } 57 | 58 | .nav-bar .nav-link { 59 | white-space: nowrap; 60 | font-size: 14.3px; 61 | color: #000000; 62 | margin: 0; 63 | padding: 0; 64 | } 65 | 66 | .nav-bar .nav-link:hover { 67 | text-decoration: none; 68 | color: #C2B8AE; 69 | } 70 | 71 | .nav-bar .nav-form { 72 | margin-top: 10px; 73 | } 74 | 75 | .nav-bar .nav-btn { 76 | margin-top: -6.35px; 77 | padding-bottom: 4.76667px; 78 | padding-left: 12.7px; 79 | padding-right: 12.7px; 80 | padding-top: 6.35px; 81 | border-radius: 4.76667px; 82 | display: block; 83 | } 84 | 85 | .nav-bar .nav-btn { 86 | background: #C2B8AE; 87 | color: #fff; 88 | } 89 | 90 | .nav-bar .nav-text { 91 | padding-top: 1.1rem; 92 | } 93 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_nav-sub.css: -------------------------------------------------------------------------------- 1 | .nav-sub, 2 | .nav-sub * { 3 | box-sizing: border-box; 4 | } 5 | 6 | .nav-sub .container { 7 | max-width: 1140px; 8 | margin: 0 auto; 9 | padding: 0 15px; 10 | width: 100%; 11 | } 12 | 13 | .nav-sub .d-flex { 14 | height: 39px; 15 | margin: 15.88px 0; 16 | display: flex; 17 | align-items: center; 18 | } 19 | 20 | @media (min-width: 768px) { 21 | .nav-sub .ml-lg-auto { 22 | margin-left: auto; 23 | } 24 | } 25 | 26 | .nav-sub .nav-breadcrumb { 27 | padding: 0; 28 | margin: 0; 29 | background: 0; 30 | } 31 | 32 | .nav-sub .nav { 33 | display: flex; 34 | list-style: none; 35 | padding: 0; 36 | margin: 0; 37 | } 38 | 39 | .nav-sub .nav li { 40 | padding-bottom: 0; 41 | } 42 | 43 | .nav-sub .nav a { 44 | padding: 8px 16px; 45 | } 46 | 47 | .nav-sub .nav li:last-child a { 48 | padding-right: 0; 49 | } 50 | 51 | .nav-sub a { 52 | font-family: 53 | Canal Regular, 54 | Helvetica, 55 | Arial, 56 | sans-serif; 57 | font-size: 13.2px; 58 | color: #49505780; 59 | } 60 | 61 | .nav-sub a:hover { 62 | background: none !important; 63 | text-decoration: none; 64 | } 65 | 66 | .nav-sub .nav-link:hover, 67 | .nav-sub .nav-link.active, 68 | .nav-sub .breadcrumb-item:hover { 69 | color: #21b0cc; 70 | } 71 | 72 | .nav-sub .breadcrumb-item + .breadcrumb-item::before { 73 | display: inline-block; 74 | padding-right: 0.5rem; 75 | padding-left: 0.5rem; 76 | color: #49505780; 77 | content: '/'; 78 | } 79 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_scaffolding.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #EFEBE7; 3 | font-family: 'Canal Book', Helvetica, Arial, sans-serif; 4 | font-size: 14px; 5 | line-height: 1.7; 6 | word-wrap: break-word; 7 | } 8 | 9 | h1, 10 | h2, 11 | h3 { 12 | font-family: 'Canal Medium'; 13 | margin-top: 0.8em; 14 | margin-bottom: 0.3em; 15 | font-weight: 300; 16 | } 17 | 18 | h1 { 19 | font-size: 2.5em; 20 | } 21 | 22 | h2 { 23 | font-size: 2em; 24 | border-bottom: 1px solid #e2e2e2; 25 | margin-bottom: 10px; 26 | padding-bottom: 10px; 27 | } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; 33 | } 34 | 35 | h5 { 36 | font-size: 1.1em; 37 | } 38 | 39 | h6 { 40 | font-size: 1.1em; 41 | color: $code_color; 42 | } 43 | 44 | ul { 45 | padding-left: 15px; 46 | } 47 | 48 | ul > li { 49 | line-height: 1.8; 50 | } 51 | 52 | .section-name { 53 | color: rgba(128, 128, 128, 1); 54 | display: block; 55 | font-size: 22px; 56 | font-weight: 300; 57 | margin-bottom: 15px; 58 | } 59 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_search.css: -------------------------------------------------------------------------------- 1 | .form-search .form-group { 2 | position: relative; 3 | } 4 | 5 | /* Typeahead */ 6 | 7 | .tt-input { 8 | width: 300px; 9 | min-height: 40px; 10 | padding-left: 15px; 11 | border-radius: 30px; 12 | } 13 | 14 | .tt-menu { 15 | line-height: 1.4; 16 | } 17 | 18 | .tt-hint { 19 | color: #ccc; 20 | } 21 | 22 | .tt-highlight { 23 | font-weight: 500; 24 | } 25 | 26 | .tt-spinner { 27 | position: absolute; 28 | right: 10px; 29 | top: 10px; 30 | opacity: 0; 31 | } 32 | 33 | .tt-spinner.in { 34 | opacity: 1; 35 | } 36 | 37 | .tt-suggestion span { 38 | display: table-cell; 39 | white-space: nowrap; 40 | max-width: 300px; 41 | overflow: hidden; 42 | text-overflow: ellipsis; 43 | } 44 | 45 | .tt-suggestion .doc-parent-name { 46 | width: 100%; 47 | text-align: right; 48 | font-weight: normal; 49 | font-size: 13px; 50 | color: #666; 51 | } 52 | 53 | .tt-suggestion:hover, 54 | .tt-suggestion.tt-cursor { 55 | cursor: pointer; 56 | background-color: #0097cf; 57 | color: #fff; 58 | } 59 | 60 | .tt-suggestion:hover .doc-parent-name, 61 | .tt-suggestion.tt-cursor .doc-parent-name { 62 | color: #fff; 63 | } 64 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/css/components/_sidebar.css: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | overflow-y: auto; 3 | overflow-x: hidden; 4 | word-wrap: normal; 5 | background: #fff; 6 | border-bottom: 1px solid #e2e2e2; 7 | border-radius: 0.3rem; 8 | } 9 | 10 | @media (min-width: 992px) { 11 | .sidebar { 12 | height: calc(100vh - 150px); 13 | border-radius: 25px; 14 | } 15 | } 16 | 17 | .sidebar a { 18 | text-overflow: ellipsis; 19 | max-width: 100%; 20 | overflow: hidden; 21 | display: block; 22 | padding-right: 20px; 23 | } 24 | 25 | .nav-groups { 26 | list-style-type: none; 27 | padding-left: 0; 28 | } 29 | 30 | .nav-groups-select { 31 | background: #f7fcfc; 32 | padding: 15px; 33 | } 34 | 35 | @media (min-width: 768px) { 36 | .nav-groups-select { 37 | background: none; 38 | } 39 | } 40 | 41 | .nav-group-name { 42 | border-bottom: 1px solid #e2e2e2; 43 | font-size: 1.1em; 44 | padding: 15px 0 15px 20px; 45 | color: #333; 46 | } 47 | 48 | .nav-group-tasks { 49 | margin-top: 5px; 50 | padding-left: 0; 51 | } 52 | 53 | .nav-group-name.active .nav-group-tasks { 54 | display: block; 55 | } 56 | 57 | .nav-group-task { 58 | font-size: 0.9em; 59 | list-style-type: none; 60 | } 61 | 62 | .nav-group-task a { 63 | color: #888; 64 | } 65 | 66 | .nav-group-task a.active { 67 | color: black; 68 | } 69 | -------------------------------------------------------------------------------- /documentation/jsdoc-assets/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/documentation/jsdoc-assets/img/dash.png -------------------------------------------------------------------------------- /documentation/jsdoc-assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/documentation/jsdoc-assets/img/favicon.ico -------------------------------------------------------------------------------- /documentation/jsdoc.md: -------------------------------------------------------------------------------- 1 | ## Nutrient React Native SDK 2 | 3 | The [Nutrient React Native SDK](https://www.nutrient.io/) is a framework that allows you to view, annotate, sign, and fill PDF forms on iOS, Android, Windows, macOS, and Web. 4 | 5 | [Nutrient Collaboration](https://www.nutrient.io/sdk/solutions/collaboration) adds real-time collaboration features to seamlessly share, edit, and annotate PDF documents. 6 | 7 | This library requires a valid license of the Nutrient SDK. Licenses are per platform. 8 | 9 | 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. 10 | 11 | Windows is not currently supported, please use the previous version [1.24.9](https://github.com/PSPDFKit/react-native/releases/tag/1.24.9) instead. 12 | 13 | ## Support, Issues and License Questions 14 | 15 | PSPDFKit offers support for customers with an active SDK license via . 16 | 17 | Are you evaluating our SDK? That's great, we're happy to help out! PSPDFKit 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. 18 | 19 | To purchase a license for production use, please reach out to us via . 20 | 21 | ## Troubleshooting 22 | 23 | For Troubleshooting common issues you might encounter when setting up PSPDFKit for React Native, please refer to the [Troubleshooting](https://www.nutrient.io/guides/react-native/troubleshoot/) section. 24 | 25 | ## License 26 | 27 | This project can be used for evaluation or if you have a valid Nutrient license. 28 | All items and source code Copyright © 2010-2025 PSPDFKit GmbH. 29 | 30 | See [LICENSE](https://github.com/PSPDFKit/react-native/blob/master/LICENSE) for details. 31 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import simpleImportSort from "eslint-plugin-simple-import-sort"; 2 | import path from "node:path"; 3 | import { fileURLToPath } from "node:url"; 4 | import js from "@eslint/js"; 5 | import { FlatCompat } from "@eslint/eslintrc"; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = path.dirname(__filename); 9 | const compat = new FlatCompat({ 10 | baseDirectory: __dirname, 11 | recommendedConfig: js.configs.recommended, 12 | allConfig: js.configs.all 13 | }); 14 | 15 | export default [{ 16 | ignores: ["./android", "./ios", "./assets", "./node_modules/**/*.js"], 17 | }, ...compat.extends("eslint:recommended", "plugin:react/recommended", "@react-native"), { 18 | plugins: { 19 | "simple-import-sort": simpleImportSort, 20 | }, 21 | 22 | languageOptions: { 23 | ecmaVersion: 12, 24 | sourceType: "module", 25 | 26 | parserOptions: { 27 | parser: "@babel/eslint-parser", 28 | requireConfigFile: false, 29 | 30 | ecmaFeatures: { 31 | jsx: true, 32 | }, 33 | }, 34 | }, 35 | 36 | rules: { 37 | "react/no-string-refs": 0, 38 | "no-alert": 0, 39 | "simple-import-sort/imports": 2, 40 | }, 41 | }]; -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+FormField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | import Foundation 11 | import React 12 | 13 | @objc extension RCTConvert { 14 | 15 | @objc public static func formFieldToJSON(_ formField: PDFFormField) -> Dictionary { 16 | 17 | var formFieldDictionary = Dictionary() 18 | 19 | formFieldDictionary["type"] = RCTConvert.formFieldTypeToString(formField.type) 20 | formFieldDictionary["name"] = formField.name 21 | formFieldDictionary["fullyQualifiedName"] = formField.fullyQualifiedName 22 | formFieldDictionary["mappingName"] = formField.mappingName 23 | formFieldDictionary["alternateFieldName"] = formField.alternateFieldName 24 | formFieldDictionary["isEditable"] = formField.isEditable 25 | formFieldDictionary["isReadOnly"] = formField.isReadOnly 26 | formFieldDictionary["isRequired"] = formField.isRequired 27 | formFieldDictionary["isNoExport"] = formField.isNoExport 28 | formFieldDictionary["defaultValue"] = formField.defaultValue 29 | formFieldDictionary["exportValue"] = formField.exportValue 30 | formFieldDictionary["value"] = formField.value 31 | formFieldDictionary["calculationOrderIndex"] = formField.calculationOrderIndex 32 | formFieldDictionary["dirty"] = formField.dirty 33 | 34 | return formFieldDictionary 35 | } 36 | 37 | @objc public static func formFieldTypeToString(_ type: PDFFormField.Kind) -> String { 38 | 39 | switch type { 40 | case .checkBox: 41 | "checkBox" 42 | case .comboBox: 43 | "comboBox" 44 | case .listBox: 45 | "listBox" 46 | case .pushButton: 47 | "pushButton" 48 | case .radioButton: 49 | "radioButton" 50 | case .signature: 51 | "signature" 52 | case .text: 53 | "text" 54 | case .unknown: 55 | "unknown" 56 | default: 57 | "unknown" 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (PSPDFAnnotation) 15 | 16 | + (NSArray *)instantJSONFromAnnotations:(NSArray *) annotations error:(NSError **)error; 17 | + (NSDictionary *)instantJSONFromFormElement:(PSPDFFormElement *)formElement error:(NSError **)error; 18 | + (PSPDFAnnotationType)annotationTypeFromInstantJSONType:(NSString *)type; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (PSPDFAnnotationChange) 15 | 16 | + (PSPDFAnnotationChange)PSPDFAnnotationChange:(NSString *)annotationChange; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationChange.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import "RCTConvert+PSPDFAnnotationChange.h" 11 | 12 | @implementation RCTConvert (PSPDFAnnotationChange) 13 | 14 | + (PSPDFAnnotationChange)PSPDFAnnotationChange:(NSString *)annotationChange { 15 | if ([annotationChange isEqualToString:@"flatten"]) { 16 | return PSPDFAnnotationChangeFlatten; 17 | } else if ([annotationChange isEqualToString:@"remove"]) { 18 | return PSPDFAnnotationChangeRemove; 19 | } else if ([annotationChange isEqualToString:@"embed"]) { 20 | return PSPDFAnnotationChangeEmbed; 21 | } else if ([annotationChange isEqualToString:@"print"]) { 22 | return PSPDFAnnotationChangePrint; 23 | } else { 24 | return PSPDFAnnotationChangeEmbed; 25 | } 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationFlags.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | import Foundation 11 | import React 12 | 13 | @objc extension RCTConvert { 14 | 15 | @objc(parseAnnotationFlags:) public static func parseAnnotationFlags(flags: Array) -> UInt { 16 | 17 | var updatedFlags: UInt = 0; 18 | 19 | for (flag) in flags { 20 | switch (flag) { 21 | case "hidden": 22 | updatedFlags |= Annotation.Flag.hidden.rawValue 23 | case "invisible": 24 | updatedFlags |= Annotation.Flag.invisible.rawValue 25 | case "locked": 26 | updatedFlags |= Annotation.Flag.locked.rawValue 27 | case "lockedContents": 28 | updatedFlags |= Annotation.Flag.lockedContents.rawValue 29 | case "print": 30 | updatedFlags |= Annotation.Flag.print.rawValue 31 | case "readOnly": 32 | updatedFlags |= Annotation.Flag.readOnly.rawValue 33 | case "noView": 34 | updatedFlags |= Annotation.Flag.noView.rawValue 35 | default: 36 | break 37 | } 38 | } 39 | return updatedFlags 40 | } 41 | 42 | @objc(convertAnnotationFlags:) public static func convertAnnotationFlags(flags: UInt) -> Array { 43 | 44 | var stringFlags = Array() 45 | 46 | if ((flags & Annotation.Flag.hidden.rawValue) != 0) { 47 | stringFlags.append("hidden") 48 | } 49 | if ((flags & Annotation.Flag.invisible.rawValue) != 0) { 50 | stringFlags.append("invisible") 51 | } 52 | if ((flags & Annotation.Flag.locked.rawValue) != 0) { 53 | stringFlags.append("locked") 54 | } 55 | if ((flags & Annotation.Flag.lockedContents.rawValue) != 0) { 56 | stringFlags.append("lockedContents") 57 | } 58 | if ((flags & Annotation.Flag.print.rawValue) != 0) { 59 | stringFlags.append("print") 60 | } 61 | if ((flags & Annotation.Flag.readOnly.rawValue) != 0) { 62 | stringFlags.append("readOnly") 63 | } 64 | if ((flags & Annotation.Flag.noView.rawValue) != 0) { 65 | stringFlags.append("noView") 66 | } 67 | return stringFlags 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotationToolbarConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (PSPDFAnnotationToolbarConfiguration) 15 | 16 | + (PSPDFAnnotationToolbarConfiguration *)PSPDFAnnotationToolbarConfiguration:(id)json; 17 | + (PSPDFAnnotationString)PSPDFAnnotationStringFromName:(NSString *)name; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (PSPDFConfiguration) 15 | 16 | + (PSPDFConfiguration *)PSPDFConfiguration:(id)json; 17 | 18 | // When reading configuration options, we check not only for the given configuration string, 19 | // but also for a string with the `iOS` prefix. For instance if the user enters 20 | // `iOSPageScrollDirection`, it is considered a valid string equal to `pageScrollDirection`. 21 | // This method will remove the iOS prefix from all the dictionary keys. 22 | // 23 | // When documenting, we always prefer configuration option strings: 24 | // 25 | // - No prefix : If the key works for both iOS and Android. 26 | // - `android` prefix : If the key works only for Android. 27 | // - `iOS` prefix : If the key works only for iOS. 28 | + (NSDictionary *)processConfigurationOptionsDictionaryForPrefix:(NSDictionary *)dictionary; 29 | 30 | + (NSDictionary *)convertConfiguration:(PSPDFViewController *)viewController; 31 | 32 | @end 33 | 34 | @interface PSPDFConfigurationBuilder (RNAdditions) 35 | 36 | - (void)setupFromJSON:(id)json; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (PSPDFDocument) 15 | 16 | + (PSPDFDocument *)PSPDFDocument:(NSString *)string; 17 | + (PSPDFDocument *)PSPDFDocument:(NSString *)urlString remoteDocumentConfig:(NSDictionary *)remoteDocumentConfig; 18 | + (NSURL*)parseURL:(NSString*)urlString; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFEditMenuAppearance.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | import Foundation 11 | import React 12 | 13 | @objc extension RCTConvert { 14 | 15 | @objc public static func PSPDFEditMenuAppearance(_ appearance: String) -> EditMenuAppearance { 16 | 17 | switch (appearance) { 18 | case "horizontalBar": 19 | return .horizontalBar 20 | case "contextMenu": 21 | return .contextMenu 22 | default: 23 | return .horizontalBar 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFImageSaveMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | import Foundation 11 | import React 12 | 13 | @objc extension RCTConvert { 14 | 15 | @objc public static func PSPDFImageSaveMode(_ saveMode: String) -> ImageDocument.SaveMode { 16 | 17 | switch (saveMode) { 18 | case "flatten": 19 | return .flatten 20 | case "flattenAndEmbed": 21 | return .flattenAndEmbed 22 | default: 23 | return .flatten 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (PSPDFViewMode) 15 | 16 | + (PSPDFViewMode)PSPDFViewMode:(NSString *)viewMode; 17 | + (NSString *)PSPDFViewModeString:(PSPDFViewMode)viewMode; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFViewMode.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import "RCTConvert+PSPDFViewMode.h" 11 | 12 | @implementation RCTConvert (PSPDFViewMode) 13 | 14 | + (PSPDFViewMode)PSPDFViewMode:(NSString *)viewMode { 15 | if ([viewMode isEqualToString:@"document"]) { 16 | return PSPDFViewModeDocument; 17 | } else if ([viewMode isEqualToString:@"thumbnails"]) { 18 | return PSPDFViewModeThumbnails; 19 | } else if ([viewMode isEqualToString:@"documentEditor"]) { 20 | return PSPDFViewModeDocumentEditor;; 21 | } else { 22 | return PSPDFViewModeDocument; 23 | } 24 | } 25 | 26 | + (NSString *)PSPDFViewModeString:(PSPDFViewMode)viewMode { 27 | if (viewMode == PSPDFViewModeDocument) { 28 | return @"document"; 29 | } else if (viewMode == PSPDFViewModeThumbnails) { 30 | return @"thumbnails"; 31 | } else if (viewMode == PSPDFViewModeDocumentEditor) { 32 | return @"documentEditor"; 33 | } else { 34 | return @"document"; 35 | } 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Converters/RCTConvert+UIBarButtonItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | @import PSPDFKit; 12 | @import PSPDFKitUI; 13 | 14 | @interface RCTConvert (UIBarButtonItem) 15 | 16 | + (NSString *)stringBarButtonItemFrom:(UIBarButtonItem *)barButtonItem forViewController:(PSPDFViewController *)pdfController; 17 | + (UIBarButtonItem *)uiBarButtonItemFrom:(NSString *)barButtonItem forViewController:(PSPDFViewController *)pdfController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Helpers/AIAConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AIAConfig.swift 3 | // PSPDFKit 4 | // 5 | // Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 6 | // 7 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 8 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 9 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 10 | // This notice may not be removed from this file. 11 | // 12 | 13 | import Foundation 14 | 15 | @objc public class AIAConfig: NSObject { 16 | 17 | @objc public static func processAIAConfig(_ config: PDFConfigurationBuilder, aiaConfig: Dictionary) { 18 | 19 | if let serverURL = aiaConfig["serverURL"], let jwt = aiaConfig["jwt"], let sessionID = aiaConfig["sessionID"], let serverURLParsed = URL(string: serverURL) { 20 | 21 | let aiaConfiguration = AIAssistantConfiguration(serverURL: serverURLParsed, jwt: jwt, sessionID: sessionID, userID: aiaConfig["userID"] == nil ? nil : aiaConfig["userID"]) 22 | config.aiAssistantConfiguration = aiaConfiguration 23 | } else { 24 | print("Failed to set AIA Configuration.") 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Helpers/RemoteDocumentDownloader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | import Foundation 11 | 12 | @objc public class RemoteDocumentDownloader: NSObject, URLSessionDelegate, URLSessionDownloadDelegate { 13 | 14 | @objc public let progress = Progress(totalUnitCount: 100) 15 | let downloadProgress = Progress(totalUnitCount: 1) 16 | let moveProgress = Progress(totalUnitCount: 1) 17 | 18 | let destinationFileURL: URL 19 | let remoteURL: URL 20 | 21 | var session: URLSession? 22 | var task: URLSessionDownloadTask? 23 | 24 | @objc public init(remoteURL: URL, destinationFileURL: URL, cleanup: Bool) { 25 | self.remoteURL = remoteURL 26 | self.destinationFileURL = destinationFileURL 27 | 28 | super.init() 29 | 30 | if (cleanup) { 31 | self.cleanup() 32 | } 33 | 34 | // Download the file using URLSession API. 35 | let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main) 36 | self.session = session 37 | let task = session.downloadTask(with: remoteURL) 38 | self.task = task 39 | task.resume() 40 | 41 | progress.addChild(downloadProgress, withPendingUnitCount: 99) 42 | progress.addChild(moveProgress, withPendingUnitCount: 1) 43 | } 44 | 45 | func cleanup() { 46 | do { 47 | task?.cancel() 48 | session?.invalidateAndCancel() 49 | try FileManager().removeItem(at: destinationFileURL) 50 | } catch { 51 | print(error) 52 | } 53 | } 54 | 55 | public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 56 | try? FileManager().moveItem(at: location, to: destinationFileURL) 57 | // We must ensure that the complete progress (`progress`) only completes when the file is already at its final location. 58 | moveProgress.completedUnitCount = moveProgress.totalUnitCount 59 | } 60 | 61 | public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { 62 | downloadProgress.totalUnitCount = totalBytesExpectedToWrite 63 | downloadProgress.completedUnitCount = totalBytesWritten 64 | } 65 | 66 | public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { 67 | if let error { 68 | print(error.localizedDescription) 69 | // Complete the progress. 70 | progress.completedUnitCount = progress.totalUnitCount 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/Helpers/SessionStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SessionStorage.swift 3 | // PSPDFKit 4 | // 5 | // Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 6 | // 7 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 8 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 9 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 10 | // This notice may not be removed from this file. 11 | // 12 | 13 | import Foundation 14 | 15 | @objc public class SessionStorage: NSObject { 16 | 17 | @objc public enum CallbackType: Int { 18 | case onDocumentLoaded 19 | } 20 | 21 | var annotationContextualMenuItems: NSDictionary! 22 | var barButtonItems: NSMutableDictionary! 23 | var closeButtonAttributes: NSDictionary! 24 | var pendingCallbacks: NSMutableArray! 25 | 26 | override public init() { 27 | annotationContextualMenuItems = [:] 28 | barButtonItems = [:] 29 | closeButtonAttributes = [:] 30 | pendingCallbacks = [] 31 | super .init() 32 | } 33 | 34 | @objc public func setAnnotationContextualMenuItems(_ items: NSDictionary) { 35 | annotationContextualMenuItems = items 36 | } 37 | 38 | @objc public func getAnnotationContextualMenuItems() -> NSDictionary { 39 | return annotationContextualMenuItems 40 | } 41 | 42 | @objc public func addBarButtonItem(_ object: UIBarButtonItem, key: NSString) { 43 | barButtonItems.setObject(object, forKey: key) 44 | } 45 | 46 | @objc public func getBarButtonItems() -> NSDictionary { 47 | return barButtonItems 48 | } 49 | 50 | @objc public func setCloseButtonAttributes(_ items: NSDictionary) { 51 | closeButtonAttributes = items 52 | } 53 | 54 | @objc public func getCloseButtonAttributes() -> NSDictionary { 55 | return closeButtonAttributes 56 | } 57 | 58 | @objc public func addPendingCallback(_ type: CallbackType) { 59 | pendingCallbacks.add(type.rawValue) 60 | } 61 | 62 | @objc public func removePendingCallback(_ type: CallbackType) { 63 | pendingCallbacks.remove(type.rawValue) 64 | } 65 | 66 | @objc public func getPendingCallbacks() -> NSArray { 67 | return pendingCallbacks 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/InstantDocumentInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InstantDocumentInfo.swift 3 | // PSPDFKit 4 | // 5 | // Copyright © 2017-2025 PSPDFKit GmbH. All rights reserved. 6 | // 7 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 8 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 9 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 10 | // This notice may not be removed from this file. 11 | // 12 | 13 | import Foundation 14 | 15 | // The response from the PSPDFKit for Web examples server API that may be used to load a document layer with Instant. 16 | @objc 17 | public class InstantDocumentInfo: NSObject{ 18 | let serverURL: URL 19 | let jwt: String 20 | 21 | @objc public init(serverURL: URL, jwt: String) { 22 | self.serverURL = serverURL 23 | self.jwt = jwt 24 | } 25 | } 26 | 27 | extension InstantDocumentInfo { 28 | enum JSONKeys: String { 29 | case serverUrl, documentId, jwt 30 | } 31 | 32 | convenience init?(json: Any) { 33 | guard let dictionary = json as? [String: Any], 34 | let serverUrlString = dictionary[JSONKeys.serverUrl.rawValue] as? String, 35 | let serverURL = URL(string: serverUrlString), 36 | let jwt = dictionary[JSONKeys.jwt.rawValue] as? String else { 37 | return nil 38 | } 39 | 40 | self.init(serverURL: serverURL, jwt: jwt) 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/NSExceptionError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSExceptionError.swift 3 | // react-native-pspdfkit 4 | // 5 | // Created by Predrag Jevtic on 10/10/22. 6 | // 7 | 8 | import Foundation 9 | 10 | public struct NSExceptionError: Swift.Error { 11 | 12 | public let exception: NSException 13 | 14 | public init(exception: NSException) { 15 | self.exception = exception 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/RCTPSPDFKit-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import "RCTBridgeModule.h" 11 | #import "RCTEventEmitter.h" 12 | 13 | // Helper to pass ObjC exceptions nicely to Swift / RN 14 | NS_INLINE NSException * _Nullable ExecuteWithObjCExceptionHandling(void(NS_NOESCAPE^_Nonnull tryBlock)(void)) { 15 | @try { 16 | tryBlock(); 17 | } 18 | @catch (NSException *exception) { 19 | return exception; 20 | } 21 | return nil; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/RCTPSPDFKitManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2016-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | @interface RCTPSPDFKitManager: RCTEventEmitter 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/RCTPSPDFKitViewManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | 12 | @interface RCTPSPDFKitViewManager : RCTViewManager 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/RNFileHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | import Foundation 11 | 12 | struct RNFileHelper { 13 | static func documentPath() -> URL? { 14 | let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 15 | let documentsDirectory = paths[0] 16 | return documentsDirectory 17 | } 18 | 19 | static func getFilePath(_ configuration: [String: Any] = [:], onError: @escaping RCTPromiseRejectBlock) -> URL? { 20 | if 21 | let filePath = configuration["filePath"] as? String, 22 | !filePath.isEmpty, 23 | let filePathURL = URL(string: filePath) { 24 | 25 | return filePathURL 26 | } 27 | 28 | if 29 | let name = configuration["name"] as? String, 30 | let documentPath = documentPath() { 31 | 32 | let filePathURL = URL(string: documentPath.absoluteString + "\(name)")?.appendingPathExtension("pdf") 33 | if let outputFileUrl = filePathURL { 34 | return outputFileUrl 35 | } 36 | } 37 | 38 | onError("E_MISSING_PATH_DOCUMENT_NAME", "Please provide either document path or name", invalidFileError()) 39 | 40 | return nil 41 | } 42 | 43 | static func invalidFileError () -> NSError { 44 | return NSError(domain: "PSPDFKit", code: 200, userInfo: nil) 45 | } 46 | 47 | static func deleteExistingFileIfNeeded(filePath: URL?, configuration: [String: Any]) { 48 | let fileManager = FileManager.default 49 | let override = configuration["override"] as? Bool ?? false 50 | 51 | if override, let filePathURL = filePath { 52 | do { 53 | try fileManager.removeItem(at: filePathURL) 54 | 55 | } catch { 56 | print("E_NO_DOCUMENT_FOUND: Could not delete file, probably didn't exist") 57 | } 58 | } 59 | } 60 | 61 | static func getTemporaryDirectory() -> String? { 62 | return URL(fileURLWithPath: NSTemporaryDirectory()).absoluteString 63 | } 64 | 65 | static func updateFileNameIfNeeded(_ outputFileURL: URL) -> URL { 66 | if String(outputFileURL.absoluteString.suffix(4)) != ".pdf", 67 | let updatedURL = URL(string: outputFileURL.absoluteString + ".pdf") { 68 | return updatedURL 69 | } 70 | 71 | return outputFileURL 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ios/RCTPSPDFKit/RNProcessor.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018-2025 PSPDFKit GmbH. All rights reserved. 3 | // 4 | // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW 5 | // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT. 6 | // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. 7 | // This notice may not be removed from this file. 8 | // 9 | 10 | #import 11 | #import "React/RCTBridgeModule.h" 12 | #import "React/RCTEventEmitter.h" 13 | #import 14 | 15 | @interface RCT_EXTERN_MODULE(RNProcessor, RCTEventEmitter) 16 | RCT_EXTERN_METHOD(generateBlankPDF: (NSDictionary *)configuration onSuccess: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 17 | RCT_EXTERN_METHOD(generatePDFFromHtmlString: (NSDictionary *)configuration html: (NSString*)html onSuccess: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 18 | RCT_EXTERN_METHOD(generatePDFFromHtmlURL: (NSDictionary *)configuration htmlURL: (NSString*)html onSuccess: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 19 | RCT_EXTERN_METHOD(getTemporaryDirectory: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 20 | RCT_EXTERN_METHOD(generatePDFFromTemplate: (NSDictionary *)configuration onSuccess: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 21 | RCT_EXTERN_METHOD(generatePDFFromImages: (NSDictionary *)configuration onSuccess: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 22 | RCT_EXTERN_METHOD(generatePDFFromDocuments: (NSDictionary *)configuration onSuccess: (RCTPromiseResolveBlock)resolve onError: (RCTPromiseRejectBlock)reject); 23 | @end 24 | -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "recurseDepth": 10, 3 | "source": { 4 | "include": ["index.js", "./lib/"], 5 | "includePattern": ".js$", 6 | "excludePattern": "(node_modules/|docs)" 7 | }, 8 | "tags": { 9 | "allowUnknownTags": ["component"] 10 | }, 11 | "templates": { 12 | "default": { 13 | "layoutFile": "documentation/jsdoc-layout.tmpl", 14 | "staticFiles": { 15 | "include": ["documentation/jsdoc-assets/"] 16 | } 17 | }, 18 | "cleverLinks": true, 19 | "monospaceLinks": true 20 | }, 21 | "opts": { 22 | "destination": "./jsdoc", 23 | "recurse": true, 24 | "readme": "documentation/jsdoc.md" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/configuration/AIAssistantConfiguration.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @typedef AIAssistantConfiguration 4 | * @memberof AIAssistantConfiguration 5 | * @property { string } jwt The JSON Web Token used for authentication with your instance of the Nutrient AI Assistant server. 6 | * @property { string } serverUrl Base HTTP URL where your instance of the Nutrient AI Assistant server can be reached. 7 | * @property { string } sessionID A unique identifier for the chat session, which can be used to recall a session in the future. 8 | * @property { string } [userID] An optional user identifier to associate with the session. This will be used to tag session history for user management. 9 | */ 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | exports.AIAssistantConfiguration = void 0; 12 | /** 13 | * @class AIAssistantConfiguration 14 | */ 15 | var AIAssistantConfiguration = /** @class */ (function () { 16 | function AIAssistantConfiguration() { 17 | } 18 | return AIAssistantConfiguration; 19 | }()); 20 | exports.AIAssistantConfiguration = AIAssistantConfiguration; 21 | -------------------------------------------------------------------------------- /lib/document/PDFPageInfo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.PDFPageInfo = void 0; 4 | /** 5 | * @interface PDFPageInfo 6 | */ 7 | var PDFPageInfo = /** @class */ (function () { 8 | function PDFPageInfo() { 9 | } 10 | return PDFPageInfo; 11 | }()); 12 | exports.PDFPageInfo = PDFPageInfo; 13 | (function (PDFPageInfo) { 14 | /** 15 | * The rotation of the page. 16 | * @readonly 17 | * @enum {string} PDFRotation 18 | */ 19 | PDFPageInfo.PDFRotation = { 20 | /** 21 | * The page is displayed without rotation. 22 | */ 23 | ROTATION0: 0, 24 | /** 25 | * The page is displayed 90 degrees clockwise. 26 | */ 27 | ROTATION90: 90, 28 | /** 29 | * The page is displayed upside-down. 30 | */ 31 | ROTATION180: 180, 32 | /** 33 | * The page is displayed 90 degrees counterclockwise. 34 | */ 35 | ROTATION270: 270, 36 | }; 37 | })(PDFPageInfo || (exports.PDFPageInfo = PDFPageInfo = {})); 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-pspdfkit", 3 | "version": "2.18.0", 4 | "description": "Nutrient React Native SDK", 5 | "keywords": [ 6 | "react native", 7 | "pspdfkit", 8 | "pdf" 9 | ], 10 | "homepage": "https://github.com/PSPDFKit/react-native", 11 | "bugs": { 12 | "email": "support@pspdfkit.com" 13 | }, 14 | "license": "SEE LICENSE IN LICENSE", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/PSPDFKit/react-native.git" 18 | }, 19 | "types": "types/index.d.ts", 20 | "scripts": { 21 | "start": "node node_modules/react-native/local-cli/cli.js start", 22 | "format": "prettier \"{samples/**/*.{md,js},*.{md,js}}\" --write", 23 | "lint": "npx eslint --ignore-pattern *.js", 24 | "docs": "rm -rf jsdoc && jsdoc -c jsdoc.json", 25 | "postdocs": "node types-scripts/fix-code-tags.js", 26 | "generate-types": "npx -p typescript tsc --build tsconfig-types.json", 27 | "append": "node types-scripts/append.js", 28 | "build": "npx -p typescript tsc --build tsconfig.json", 29 | "build-and-generate-types": "rm -rf types lib && npm run build && npm run generate-types && npm run append", 30 | "copy-types-and-lib": "cd samples/Catalog/node_modules/react-native-pspdfkit && rm -rf index.js lib src types && cd ../../../../ && cp -rf index.js lib src types samples/Catalog/node_modules/react-native-pspdfkit/", 31 | "dev-build": "npm run build-and-generate-types && npm run docs && npm run copy-types-and-lib" 32 | }, 33 | "peerDependencies": { 34 | "@types/react": ">=17.0.0", 35 | "prop-types": "^15.8.1", 36 | "react": ">=17.0.0", 37 | "react-native": ">=0.66.0" 38 | }, 39 | "devDependencies": { 40 | "@babel/core": "^7.26.10", 41 | "@babel/eslint-parser": "^7.26.10", 42 | "@babel/runtime": "^7.26.10", 43 | "@eslint/eslintrc": "^3.2.0", 44 | "@eslint/js": "^9.16.0", 45 | "@react-native/eslint-config": "^0.78.0", 46 | "@react-native/metro-config": "^0.78.0", 47 | "@tsconfig/react-native": "^3.0.0", 48 | "@types/react": ">=17.0.0", 49 | "babel-jest": "^29.5.0", 50 | "eslint": "^9.16.0", 51 | "eslint-plugin-ft-flow": "^2.0.3", 52 | "eslint-plugin-simple-import-sort": "^10.0.0", 53 | "jest": "^29.5.0", 54 | "jsdoc": "^4.0.2", 55 | "metro-react-native-babel-preset": "0.77.0", 56 | "prettier": "^2.8.8", 57 | "react-native-codegen": "^0.71.5", 58 | "typescript": "^5.1.3" 59 | }, 60 | "engines": { 61 | "node": ">=16" 62 | }, 63 | "files": [ 64 | "ios/", 65 | "android/", 66 | "lib/", 67 | "src/", 68 | "types/", 69 | "windows/", 70 | "babel.config.js", 71 | "index.js", 72 | "react-native-pspdfkit.podspec", 73 | "tsconfig-types.json", 74 | "tsconfig.json", 75 | "package.json", 76 | "License-Evaluation.pdf" 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /rake.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/rake.out -------------------------------------------------------------------------------- /react-native-pspdfkit.podspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 6 | 7 | Pod::Spec.new do |s| 8 | s.name = "react-native-pspdfkit" 9 | s.version = package["version"] 10 | s.summary = "React Native PDF Library by PSPDFKit." 11 | s.documentation_url = "https://pspdfkit.com/guides/react-native" 12 | s.license = package["license"] 13 | s.description = <<-DESC 14 | A high-performance viewer, extensive annotation and document editing tools, digital signatures, and more. 15 | DESC 16 | s.authors = { "PSPDFKit GmbH" => "support@pspdfkit.com" } 17 | s.homepage = "https://pspdfkit.com/guides/react-native/" 18 | s.platform = :ios, "16.0" 19 | s.module_name = "PSPDFKitReactNativeiOS" 20 | s.source = { git: "https://github.com/PSPDFKit/react-native" } 21 | s.source_files = "ios/*.{xcodeproj}", "ios/RCTPSPDFKit/*.{h,m,swift}", "ios/RCTPSPDFKit/Converters/*.{h,m,swift}", "ios/RCTPSPDFKit/Helpers/*.{h,m,swift}" 22 | s.dependency("React") 23 | s.dependency("PSPDFKit", "14.8.0") 24 | s.dependency("Instant", "14.8.0") 25 | s.frameworks = "UIKit" 26 | end 27 | -------------------------------------------------------------------------------- /samples/Catalog/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /samples/Catalog/.editorconfig: -------------------------------------------------------------------------------- 1 | # Windows files 2 | [*.bat] 3 | end_of_line = crlf 4 | -------------------------------------------------------------------------------- /samples/Catalog/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; Flow doesn't support platforms 12 | .*/Libraries/Utilities/LoadingView.js 13 | 14 | [untyped] 15 | .*/node_modules/@react-native-community/cli/.*/.* 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/interface.js 21 | node_modules/react-native/flow/ 22 | 23 | [options] 24 | emoji=true 25 | 26 | exact_by_default=true 27 | 28 | module.file_ext=.js 29 | module.file_ext=.json 30 | module.file_ext=.ios.js 31 | 32 | munge_underscores=true 33 | 34 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 35 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 36 | 37 | suppress_type=$FlowIssue 38 | suppress_type=$FlowFixMe 39 | suppress_type=$FlowFixMeProps 40 | suppress_type=$FlowFixMeState 41 | 42 | [lints] 43 | sketchy-null-number=warn 44 | sketchy-null-mixed=warn 45 | sketchy-number=warn 46 | untyped-type-import=warn 47 | nonstrict-import=warn 48 | deprecated-type=warn 49 | unsafe-getters-setters=warn 50 | unnecessary-invariant=warn 51 | signature-verification-failure=warn 52 | 53 | [strict] 54 | deprecated-type 55 | nonstrict-import 56 | sketchy-null 57 | unclear-type 58 | unsafe-getters-setters 59 | untyped-import 60 | untyped-type-import 61 | 62 | [version] 63 | ^0.149.0 64 | -------------------------------------------------------------------------------- /samples/Catalog/.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows files should use crlf line endings 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /samples/Catalog/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | /ios/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | .fake 66 | ./.watchman-cookie* 67 | -------------------------------------------------------------------------------- /samples/Catalog/.node-version: -------------------------------------------------------------------------------- 1 | 18.0.0 2 | -------------------------------------------------------------------------------- /samples/Catalog/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: true, 3 | bracketSameLine: false, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | arrowParens: 'avoid', 7 | endOfLine: 'auto', 8 | printWidth: 80, 9 | tabWidth: 2, 10 | }; 11 | -------------------------------------------------------------------------------- /samples/Catalog/.ruby-version: -------------------------------------------------------------------------------- 1 | 3.3.1 2 | -------------------------------------------------------------------------------- /samples/Catalog/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /samples/Catalog/README.md: -------------------------------------------------------------------------------- 1 | ## Catalog 2 | 3 | The project contains a large set of sample code, which illustrates how to set up and customize PSPDFKit for various use cases. You can run the Catalog app on Android and iOS. 4 | 5 | ### Running the Catalog on Android 6 | 7 | #### Requirements 8 | 9 | - A [development environment](https://reactnative.dev/docs/environment-setup) for running React Native projects using the React Native CLI (not the Expo CLI). 10 | - The [latest stable version of Android Studio](https://developer.android.com/studio). 11 | - The [Android NDK](https://developer.android.com/studio/projects/install-ndk). 12 | - An [Android Virtual Device](https://developer.android.com/studio/run/managing-avds.html) or a hardware device. 13 | 14 | #### Getting Started 15 | 16 | 1. Clone the repository: `git clone https://github.com/PSPDFKit/react-native.git` 17 | 2. Step into the Catalog project's directory: `cd react-native/samples/Catalog` 18 | 3. Install dependencies: `yarn install` 19 | 4. The Catalog app is now ready to launch: `react-native run-android` 20 | 21 | ### Running the Catalog on iOS 22 | 23 | #### Requirements 24 | 25 | - A [development environment](https://reactnative.dev/docs/environment-setup) for running React Native projects using the React Native CLI (not the Expo CLI). 26 | - The latest [stable version of Xcode](https://apps.apple.com/us/app/xcode/id497799835?mt=12). 27 | - The [latest stable version of CocoaPods](https://github.com/CocoaPods/CocoaPods/releases). If you don’t already have CocoaPods installed, follow the [CocoaPods installation guide](https://guides.cocoapods.org/using/getting-started.html#installation) to install CocoaPods on your Mac. 28 | 29 | #### Getting Started 30 | 31 | 1. Clone the repository: `git clone https://github.com/PSPDFKit/react-native.git` 32 | 2. Step into the Catalog project's directory: `cd react-native/samples/Catalog` 33 | 3. Install dependencies: `yarn install` 34 | 4. Go to the iOS folder: `cd iOS` 35 | 5. Install the iOS pods: `pod install` 36 | 6. Go back to the Catalog directory: `cd ..` 37 | 7. The Catalog app is now ready to launch: `react-native run-ios` 38 | 39 | ### Troubleshooting 40 | 41 | **Note:** If you get an error about `config.h` not being found check out [this blog post](https://tuntunir.blogspot.com/2018/02/react-native-fatal-error-configh-file.html) for information on how to fix it. 42 | -------------------------------------------------------------------------------- /samples/Catalog/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | // import React from 'react'; 6 | 7 | // Note: test renderer must be required after react-native. 8 | // import renderer from 'react-test-renderer'; 9 | // import Catalog from '../Catalog'; 10 | 11 | it('renders correctly', () => { 12 | // add tests here 13 | }); 14 | -------------------------------------------------------------------------------- /samples/Catalog/android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Catalog-android 4 | Project android_ created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | 19 | 0 20 | 21 | 30 22 | 23 | org.eclipse.core.resources.regexFilterMatcher 24 | node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | 25 | 1666692500645 26 | 27 | 30 28 | 29 | org.eclipse.core.resources.regexFilterMatcher 30 | node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/java/com/pspdfkit/rn/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.rn; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "Catalog"; 17 | } 18 | 19 | /** 20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link 21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React 22 | * (aka React 18) with two boolean flags. 23 | */ 24 | @Override 25 | protected ReactActivityDelegate createReactActivityDelegate() { 26 | return new DefaultReactActivityDelegate( 27 | this, 28 | getMainComponentName(), 29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 30 | DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled 31 | // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). 32 | DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/java/com/pspdfkit/rn/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.pspdfkit.rn; 2 | 3 | import android.app.Application; 4 | 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 10 | import com.facebook.react.defaults.DefaultReactNativeHost; 11 | import com.facebook.react.shell.MainReactPackage; 12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping; 13 | import com.facebook.soloader.SoLoader; 14 | import com.rnfs.RNFSPackage; 15 | 16 | import java.io.IOException; 17 | import java.util.Arrays; 18 | import java.util.List; 19 | 20 | public class MainApplication extends Application implements ReactApplication { 21 | protected List getPackages() { 22 | return Arrays.asList( 23 | new MainReactPackage(), 24 | new RNFSPackage() 25 | ); 26 | } 27 | 28 | 29 | private final ReactNativeHost mReactNativeHost = 30 | new DefaultReactNativeHost(this) { 31 | @Override 32 | public boolean getUseDeveloperSupport() { 33 | return BuildConfig.DEBUG; 34 | } 35 | 36 | @Override 37 | protected List getPackages() { 38 | @SuppressWarnings("UnnecessaryLocalVariable") 39 | List packages = new PackageList(this).getPackages(); 40 | // Packages that cannot be autolinked yet can be added manually here, for example: 41 | // packages.add(new MyReactNativePackage()); 42 | return packages; 43 | } 44 | 45 | @Override 46 | protected String getJSMainModuleName() { 47 | return "index"; 48 | } 49 | 50 | @Override 51 | protected boolean isNewArchEnabled() { 52 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 53 | } 54 | 55 | @Override 56 | protected Boolean isHermesEnabled() { 57 | return BuildConfig.IS_HERMES_ENABLED; 58 | } 59 | }; 60 | 61 | @Override 62 | public ReactNativeHost getReactNativeHost() { 63 | return mReactNativeHost; 64 | } 65 | 66 | @Override 67 | public void onCreate() { 68 | super.onCreate(); 69 | try { 70 | SoLoader.init(this, OpenSourceMergedSoMapping.INSTANCE); 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } 74 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 75 | // If you opted-in for the New Architecture, we load the native entry point for this app. 76 | DefaultNewArchitectureEntryPoint.load(); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/drawable/example_annotation_icon.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/drawable/example_toolbar_icon.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/mipmap-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/mipmap-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/playstore-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/app/src/main/res/playstore-icon.png -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #4537DE 4 | #2B1CC1 5 | 6 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Catalog 3 | 4 | -------------------------------------------------------------------------------- /samples/Catalog/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /samples/Catalog/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | minSdkVersion = 24 6 | compileSdkVersion = 35 7 | targetSdkVersion = 34 8 | 9 | ndkVersion = "26.1.10909125" 10 | kotlinVersion = "2.0.21" 11 | } 12 | repositories { 13 | google() 14 | mavenCentral() 15 | } 16 | 17 | dependencies { 18 | classpath("com.android.tools.build:gradle:8.6.0") 19 | classpath("com.facebook.react:react-native-gradle-plugin") 20 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") 21 | 22 | // NOTE: Do not place your application dependencies here; they belong 23 | // in the individual module build.gradle files 24 | } 25 | } 26 | 27 | allprojects { 28 | repositories { 29 | google() 30 | mavenLocal() 31 | mavenCentral() 32 | maven { 33 | url 'https://my.nutrient.io/maven/' 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /samples/Catalog/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Disable configuration cache as it can cause issues with React Native 28 | org.gradle.configuration-cache=false 29 | 30 | # Use this property to specify which architecture you want to build. 31 | # You can also override it from the CLI using 32 | # ./gradlew -PreactNativeArchitectures=x86_64 33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 34 | 35 | # Use this property to enable support to the new architecture. 36 | # This will allow you to use TurboModules and the Fabric render in 37 | # your application. You should enable this flag either if you want 38 | # to write custom TurboModules/Fabric components OR use libraries that 39 | # are providing them. 40 | newArchEnabled=false 41 | 42 | # Use this property to enable or disable the Hermes JS engine. 43 | # If set to false, you will be using JSC instead. 44 | hermesEnabled=true 45 | -------------------------------------------------------------------------------- /samples/Catalog/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/Catalog/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Sep 04 23:57:44 SAST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip 5 | networkTimeout=10000 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /samples/Catalog/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /samples/Catalog/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | 5 | rootProject.name = 'Catalog' 6 | include ':app' 7 | includeBuild('../node_modules/@react-native/gradle-plugin') 8 | 9 | include ':react-native-fs' 10 | project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android') 11 | -------------------------------------------------------------------------------- /samples/Catalog/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Catalog", 3 | "displayName": "Catalog" 4 | } 5 | -------------------------------------------------------------------------------- /samples/Catalog/assets/logo-flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/assets/logo-flat.png -------------------------------------------------------------------------------- /samples/Catalog/assets/logo-flat@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/assets/logo-flat@2x.png -------------------------------------------------------------------------------- /samples/Catalog/assets/logo-flat@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSPDFKit/react-native/401df05507669a89a84f054bb0fb898e9f36daa1/samples/Catalog/assets/logo-flat@3x.png -------------------------------------------------------------------------------- /samples/Catalog/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /samples/Catalog/components/linkButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TouchableOpacity, StyleSheet, Text } from 'react-native'; 3 | import { pspdfkitColor } from '../configuration/Constants'; 4 | 5 | const LinkButton = ({ title = '', style = {}, onPress = () => {} }) => { 6 | return ( 7 | 12 | {title} 13 | 14 | ); 15 | }; 16 | 17 | export default LinkButton; 18 | 19 | const styles = StyleSheet.create({ 20 | button: { 21 | padding: 10, 22 | backgroundColor: 'transparent', 23 | }, 24 | link: { 25 | color: pspdfkitColor, 26 | fontSize: 18, 27 | fontWeight: '500', 28 | }, 29 | }); 30 | -------------------------------------------------------------------------------- /samples/Catalog/components/primaryButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Text, TouchableOpacity, StyleSheet } from 'react-native'; 3 | import { pspdfkitColor } from '../configuration/Constants'; 4 | 5 | const PrimaryButton = ({ title = '', onPress = () => {}, style = {} }) => { 6 | return ( 7 | 12 | {title} 13 | 14 | ); 15 | }; 16 | 17 | export default PrimaryButton; 18 | 19 | const styles = StyleSheet.create({ 20 | primaryButton: { 21 | backgroundColor: pspdfkitColor, 22 | alignItems: 'center', 23 | borderRadius: 4, 24 | marginTop: 5, 25 | }, 26 | primaryButtonText: { 27 | color: 'white', 28 | padding: 10, 29 | fontSize: 17, 30 | textAlign: 'center', 31 | fontWeight: '500', 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /samples/Catalog/components/urlInput.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Modal, StyleSheet, Text, TextInput, View } from 'react-native'; 3 | 4 | import LinkButton from './linkButton'; 5 | import PrimaryButton from './primaryButton'; 6 | 7 | const UrlInput = ({ 8 | shouldRender = false, 9 | // @ts-ignore 10 | onCancel, 11 | placeholder = '', 12 | // @ts-ignore 13 | onConnect, 14 | defaultURL = '', 15 | }) => { 16 | const [urlText, setUrlText] = useState(defaultURL); 17 | 18 | return ( 19 | 24 | 25 | 26 | Enter Document URL 27 | setUrlText(text)} 30 | defaultValue={urlText} 31 | style={styles.input} 32 | placeholderTextColor="#999" 33 | /> 34 | 35 | 40 | onConnect(urlText)} 43 | /> 44 | 45 | 46 | 47 | 48 | ); 49 | }; 50 | 51 | export default UrlInput; 52 | 53 | const styles = StyleSheet.create({ 54 | modalContainer: { 55 | backgroundColor: 'rgba(0,0,0,0.8)', 56 | flex: 1, 57 | justifyContent: 'center', 58 | }, 59 | contentView: { 60 | backgroundColor: 'white', 61 | width: '80%', 62 | marginBottom: 100, 63 | borderRadius: 5, 64 | padding: 15, 65 | paddingBottom: 0, 66 | alignSelf: 'center', 67 | }, 68 | input: { 69 | fontSize: 18, 70 | height: 40, 71 | paddingBottom: 3, 72 | borderBottomWidth: 2, 73 | borderColor: '#cfcfcf', 74 | marginBottom: 10, 75 | }, 76 | footer: { 77 | flexDirection: 'row', 78 | alignItems: 'center', 79 | justifyContent: 'flex-end', 80 | paddingBottom: 15, 81 | }, 82 | // @ts-ignore 83 | linkButton: { container: { marginRight: 10 } }, 84 | title: { 85 | fontSize: 19, 86 | height: 25, 87 | marginBottom: 15, 88 | }, 89 | }); 90 | -------------------------------------------------------------------------------- /samples/Catalog/configuration/Constants.ts: -------------------------------------------------------------------------------- 1 | // Document names 2 | import { Platform } from 'react-native'; 3 | import fileSystem from 'react-native-fs'; 4 | 5 | const tiffImageName = 'PSPDFKit_Image_Example.tiff'; 6 | export const formDocumentName = 'Form_example.pdf'; 7 | const measurementsName = 'Measurements.pdf'; 8 | export const exampleDocumentName = 'PSPDFKit_Quickstart_Guide.pdf'; 9 | export const exampleAIName = 'Resource_Depletion.pdf'; 10 | export const examplePasswordDocumentName = 'PSPDFKit_Quickstart_Guide_Password.pdf'; 11 | export const exampleReportName = 'JKHF-AnnualReport.pdf'; 12 | export const exampleXFDFName = 'XFDFTest.xfdf'; 13 | 14 | export const exampleImage = 'PSPDFKit_Image_Example.jpg'; 15 | export const exampleImagePath = 16 | Platform.OS === 'ios' 17 | ? 'PDFs/' + exampleImage 18 | : 'file:///android_asset/' + exampleImage; 19 | 20 | // Document paths 21 | export const formDocumentPath = 22 | Platform.OS === 'ios' 23 | ? 'PDFs/' + formDocumentName 24 | : 'file:///android_asset/' + formDocumentName; 25 | 26 | export const exampleDocumentPath = 27 | Platform.OS === 'ios' 28 | ? 'PDFs/' + exampleDocumentName 29 | : 'file:///android_asset/' + exampleDocumentName; 30 | 31 | export const examplePasswordDocumentPath = 32 | Platform.OS === 'ios' 33 | ? 'PDFs/' + examplePasswordDocumentName 34 | : 'file:///android_asset/' + examplePasswordDocumentName; 35 | 36 | export const exampleReportPath = 37 | Platform.OS === 'ios' 38 | ? 'PDFs/' + exampleReportName 39 | : 'file:///android_asset/' + exampleReportName; 40 | 41 | export const exampleXFDFPath = 42 | Platform.OS === 'ios' 43 | ? 'PDFs/' + exampleXFDFName 44 | : 'file:///android_asset/' + exampleXFDFName; 45 | 46 | export const exampleAIPath = 47 | Platform.OS === 'ios' 48 | ? 'PDFs/' + exampleAIName 49 | : 'file:///android_asset/' + exampleAIName; 50 | 51 | export const tiffImagePath = 52 | Platform.OS === 'ios' 53 | ? 'PDFs/' + tiffImageName 54 | : 'file:///android_asset/' + tiffImageName; 55 | 56 | export const measurementsDocument = 57 | Platform.OS === 'ios' 58 | ? 'PDFs/' + measurementsName 59 | : 'file:///android_asset/' + measurementsName; 60 | 61 | export const pspdfkitColor = '#267AD4'; 62 | 63 | export const writableDocumentPath = 64 | Platform.OS === 'ios' 65 | ? fileSystem.DocumentDirectoryPath + '/' + exampleDocumentName 66 | : 'file://' + fileSystem.DocumentDirectoryPath + '/' + exampleDocumentName; 67 | 68 | export const writableFormDocumentPath = 69 | Platform.OS === 'ios' 70 | ? fileSystem.DocumentDirectoryPath + '/' + formDocumentName 71 | : 'file://' + fileSystem.DocumentDirectoryPath + '/' + formDocumentName; 72 | 73 | export const writableXFDFPath = 74 | Platform.OS === 'ios' 75 | ? fileSystem.DocumentDirectoryPath + '/' + exampleXFDFName 76 | : 'file://' + fileSystem.DocumentDirectoryPath + '/' + exampleXFDFName; 77 | -------------------------------------------------------------------------------- /samples/Catalog/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import simpleImportSort from "eslint-plugin-simple-import-sort"; 2 | import path from "node:path"; 3 | import { fileURLToPath } from "node:url"; 4 | import js from "@eslint/js"; 5 | import { FlatCompat } from "@eslint/eslintrc"; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = path.dirname(__filename); 9 | const compat = new FlatCompat({ 10 | baseDirectory: __dirname, 11 | recommendedConfig: js.configs.recommended, 12 | allConfig: js.configs.all 13 | }); 14 | 15 | export default [{ 16 | ignores: ["./android", "./ios", "./assets", "./node_modules/**/*.js"], 17 | }, ...compat.extends("@react-native"), { 18 | plugins: { 19 | "simple-import-sort": simpleImportSort, 20 | }, 21 | 22 | rules: { 23 | "react/no-string-refs": "off", 24 | "no-alert": "off", 25 | "react-native/no-inline-styles": "off", 26 | "simple-import-sort/imports": "error", 27 | }, 28 | }]; -------------------------------------------------------------------------------- /samples/Catalog/examples/CustomFontPicker.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { processColor, View } from 'react-native'; 3 | import PSPDFKitView from 'react-native-pspdfkit'; 4 | 5 | import { exampleDocumentPath, pspdfkitColor } from '../configuration/Constants'; 6 | import { BaseExampleAutoHidingHeaderComponent } from '../helpers/BaseExampleAutoHidingHeaderComponent'; 7 | import { hideToolbar } from '../helpers/NavigationHelper'; 8 | 9 | export class CustomFontPicker extends BaseExampleAutoHidingHeaderComponent { 10 | pdfRef: React.RefObject; 11 | 12 | constructor(props: any) { 13 | super(props); 14 | const { navigation } = this.props; 15 | this.pdfRef = React.createRef(); 16 | hideToolbar(navigation); 17 | } 18 | 19 | override render() { 20 | return ( 21 | 22 | 42 | 43 | ); 44 | } 45 | } 46 | const styles = { 47 | flex: { flex: 1 }, 48 | pdfColor: { flex: 1, color: pspdfkitColor }, 49 | }; 50 | -------------------------------------------------------------------------------- /samples/Catalog/examples/GeneratePDF.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { processColor, View } from 'react-native'; 3 | import PSPDFKitView from 'react-native-pspdfkit'; 4 | 5 | import { pspdfkitColor } from '../configuration/Constants'; 6 | import { BaseExampleAutoHidingHeaderComponent } from '../helpers/BaseExampleAutoHidingHeaderComponent'; 7 | 8 | export class GeneratePDF extends BaseExampleAutoHidingHeaderComponent { 9 | pdfRef: React.RefObject; 10 | 11 | constructor(props: any) { 12 | super(props); 13 | this.pdfRef = React.createRef(); 14 | } 15 | 16 | override render() { 17 | const { route } = this.props; 18 | const { fullPath } = route.params; 19 | 20 | return ( 21 | 22 | 30 | 31 | ); 32 | } 33 | } 34 | 35 | const styles = { 36 | flex: { flex: 1 }, 37 | pdfColor: { flex: 1, color: pspdfkitColor }, 38 | }; 39 | -------------------------------------------------------------------------------- /samples/Catalog/examples/GeneratePDFMenu.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | FlatList, 4 | Image, 5 | NativeModules, 6 | Text, 7 | TouchableHighlight, 8 | View, 9 | } from 'react-native'; 10 | 11 | import { pspdfkitColor } from '../configuration/Constants'; 12 | 13 | const PSPDFKit = NativeModules.PSPDFKit; 14 | import { generatePDFMenu } from '../ExamplesNavigationMenu'; 15 | import styles from '../styles/styles'; 16 | 17 | class GeneratePDFMenu extends Component { 18 | override render() { 19 | return ( 20 | 21 | 22 | 26 | {PSPDFKit.versionString} 27 | 28 | 36 | 37 | ); 38 | } 39 | 40 | _renderSeparator = () => { 41 | return ; 42 | } 43 | 44 | _renderRow = ({ item }: { item: any }) => { 45 | return ( 46 | { 48 | item.action(this); 49 | }} 50 | style={styles.rowContent} 51 | underlayColor={pspdfkitColor} 52 | > 53 | 54 | {item?.name} 55 | {item?.description} 56 | 57 | 58 | ); 59 | }; 60 | } 61 | 62 | export default GeneratePDFMenu; 63 | -------------------------------------------------------------------------------- /samples/Catalog/examples/GetConfiguration.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Alert, Button, processColor, View } from 'react-native'; 3 | import PSPDFKitView, { PDFConfiguration } from 'react-native-pspdfkit'; 4 | 5 | import { 6 | pspdfkitColor, 7 | exampleDocumentPath, 8 | } from '../configuration/Constants'; 9 | import { BaseExampleAutoHidingHeaderComponent } from '../helpers/BaseExampleAutoHidingHeaderComponent'; 10 | import { PSPDFKit } from '../helpers/PSPDFKit'; 11 | 12 | export class GetConfiguration extends BaseExampleAutoHidingHeaderComponent { 13 | pdfRef: React.RefObject; 14 | 15 | constructor(props: any) { 16 | super(props); 17 | this.pdfRef = React.createRef(); 18 | } 19 | 20 | override render() { 21 | return ( 22 | 23 | 39 | 40 | 41 |