Преглед на файлове

compdfkit(rn) - 新增表单列表示例

liuxiaolong преди 2 дни
родител
ревизия
5745f782e9

Файловите разлики са ограничени, защото са твърде много
+ 8 - 0
example/App.tsx


BIN
example/android/app/src/main/assets/annot_test.pdf


BIN
example/android/app/src/main/assets/test_sign_pic.png


+ 10 - 8
example/ios/CompdfkitPdfExample.xcodeproj/project.pbxproj

@@ -17,6 +17,8 @@
 		C9FCF5E32C475A9100CEFDBB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C9FCF5E12C475A9100CEFDBB /* Localizable.strings */; };
 		EC09D8212D3DE887001B2CB3 /* test.xfdf in Resources */ = {isa = PBXBuildFile; fileRef = EC09D8202D3DE886001B2CB3 /* test.xfdf */; };
 		EC4EF3572D36664A00EEA52B /* extraFonts in Resources */ = {isa = PBXBuildFile; fileRef = EC4EF3562D36664A00EEA52B /* extraFonts */; };
+		EC9B30142D7AB9CD004E62E0 /* annot_test.pdf in Resources */ = {isa = PBXBuildFile; fileRef = EC9B30132D7AB9CD004E62E0 /* annot_test.pdf */; };
+		EC9B30162D7AC832004E62E0 /* test_sign_pic.png in Resources */ = {isa = PBXBuildFile; fileRef = EC9B30152D7AC832004E62E0 /* test_sign_pic.png */; };
 		ECF47E9D2BDF6D3300E7456A /* PDF_Document.pdf in Resources */ = {isa = PBXBuildFile; fileRef = ECF47E9C2BDF6D3300E7456A /* PDF_Document.pdf */; };
 /* End PBXBuildFile section */
 
@@ -52,6 +54,8 @@
 		C9FCF5E42C475AB600CEFDBB /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		EC09D8202D3DE886001B2CB3 /* test.xfdf */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = test.xfdf; sourceTree = "<group>"; };
 		EC4EF3562D36664A00EEA52B /* extraFonts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = extraFonts; path = ../android/app/src/main/assets/extraFonts; sourceTree = "<group>"; };
+		EC9B30132D7AB9CD004E62E0 /* annot_test.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = annot_test.pdf; sourceTree = "<group>"; };
+		EC9B30152D7AC832004E62E0 /* test_sign_pic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_sign_pic.png; sourceTree = "<group>"; };
 		ECF47E9C2BDF6D3300E7456A /* PDF_Document.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = PDF_Document.pdf; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
@@ -128,6 +132,8 @@
 		83CBB9F61A601CBA00E9B192 = {
 			isa = PBXGroup;
 			children = (
+				EC9B30152D7AC832004E62E0 /* test_sign_pic.png */,
+				EC9B30132D7AB9CD004E62E0 /* annot_test.pdf */,
 				EC09D8202D3DE886001B2CB3 /* test.xfdf */,
 				EC4EF3562D36664A00EEA52B /* extraFonts */,
 				ECF47E9C2BDF6D3300E7456A /* PDF_Document.pdf */,
@@ -259,10 +265,12 @@
 			files = (
 				81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
 				EC4EF3572D36664A00EEA52B /* extraFonts in Resources */,
+				EC9B30142D7AB9CD004E62E0 /* annot_test.pdf in Resources */,
 				C9FCF5E32C475A9100CEFDBB /* Localizable.strings in Resources */,
 				13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
 				ECF47E9D2BDF6D3300E7456A /* PDF_Document.pdf in Resources */,
 				EC09D8212D3DE887001B2CB3 /* test.xfdf in Resources */,
+				EC9B30162D7AC832004E62E0 /* test_sign_pic.png in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -639,10 +647,7 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					" ",
-				);
+				OTHER_LDFLAGS = "$(inherited)  ";
 				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
 				USE_HERMES = true;
@@ -715,10 +720,7 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					" ",
-				);
+				OTHER_LDFLAGS = "$(inherited)  ";
 				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
 				USE_HERMES = true;

BIN
example/ios/annot_test.pdf


BIN
example/ios/test_sign_pic.png


+ 1 - 0
example/package.json

@@ -17,6 +17,7 @@
     "react-native": "0.74.0",
     "react-native-document-picker": "^9.1.0",
     "react-native-fs": "^2.20.0",
+    "react-native-image-picker": "^8.2.0",
     "react-native-popup-menu": "^0.16.1",
     "react-native-safe-area-context": "^4.10.7",
     "react-native-screens": "^3.32.0",

+ 1 - 110
example/src/CPDFAnnotationsExample.tsx

@@ -57,14 +57,7 @@ const CPDFAnnotationsExampleScreen = () => {
         'Import Annotations 1',
         'Import Annotations 2',
         'Export Annotations',
-        'Get Annotations',
-        'Get Widgets',
-        'Import Widgets',
-        'Export Widgets',
-        'TextWidget Set Text',
-        'CheckboxWidget Set Checked',
-        'Radiobutton Set Checked',
-        'SignatureWidget image signature'
+        'Get Annotations'
     ];
 
     const handleMenuItemPress = async (action: string) => {
@@ -117,32 +110,6 @@ const CPDFAnnotationsExampleScreen = () => {
                 const exportXfdfFilePath = await pdfReaderRef.current?._pdfDocument.exportAnnotations();
                 console.log('ComPDFKitRN exportAnnotations:', exportXfdfFilePath);
                 break;
-            case 'Import Widgets':
-                const pickerResult = DocumentPicker.pick({
-                    type: [DocumentPicker.types.allFiles],
-                    copyTo: 'cachesDirectory'
-                });
-                pickerResult.then(async (res) => {
-                    const file = res[0];
-
-                    console.log('fileUri:', file?.uri);
-                    console.log('fileCopyUri:', file?.fileCopyUri);
-                    console.log('fileType:', file?.type);
-                    const path = file!!.fileCopyUri!!
-                    if (!path?.endsWith('xml') && !path?.endsWith('xfdf')) {
-                        console.log('ComPDFKitRN please select xfdf format file');
-                        return;
-                    }
-                    console.log('ComPDFKitRN importWidget, filePath:', path);
-                    const importWidgetResult = await pdfReaderRef.current?._pdfDocument.importWidgets(path);
-                    console.log('ComPDFKitRN importWidget:', importWidgetResult);
-                })
-
-                break;
-            case 'Export Widgets':
-                const exportWidgetsPath = await pdfReaderRef.current?._pdfDocument.exportWidgets();
-                console.log('ComPDFKitRN exportWidgets:', exportWidgetsPath)
-                break;
             case 'openDocument':
                 const document = await ComPDFKit.pickFile();
                 if (document) {
@@ -158,82 +125,6 @@ const CPDFAnnotationsExampleScreen = () => {
                     console.log(JSON.stringify(annotations, null, 2));
                 }
                 break;
-            case 'Get Widgets':
-                const pageCount1 = await pdfReaderRef!.current!._pdfDocument.getPageCount();
-                for (let i = 0; i < pageCount1; i++) {
-                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
-                    const widgets = await page?.getWidgets();
-                    console.log(`ComPDFKitRN-widgets length of page ${i}:`, widgets?.length);
-                    console.log(JSON.stringify(widgets, null, 2));
-                }
-                break;
-            case 'TextWidget Set Text': {
-                const pageCount = await pdfReaderRef!.current!._pdfDocument.getPageCount();
-                for (let i = 0; i < pageCount; i++) {
-                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
-                    const widgets = await page?.getWidgets();
-                    const textWidget = widgets?.find(widget => widget.type === CPDFWidgetType.TEXT_FIELD) as CPDFTextWidget
-                    if (textWidget) {
-                        console.log(JSON.stringify(textWidget, null, 2))
-                        await textWidget?.setText('Hello World');
-                        await textWidget?.updateAp();
-                        console.log('ComPDFKitRN-TextWidget Set Text:', textWidget.text);
-                        return;
-                    }
-                }
-                break;
-            }
-            case 'CheckboxWidget Set Checked': {
-                const pageCount = await pdfReaderRef!.current!._pdfDocument.getPageCount();
-                for (let i = 0; i < pageCount; i++) {
-                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
-                    const widgets = await page?.getWidgets();
-                    const checkboxWidget = widgets?.find(widget => widget.type === CPDFWidgetType.CHECKBOX) as CPDFCheckboxWidget;
-                    if (checkboxWidget) {
-                        await checkboxWidget?.setChecked(!checkboxWidget.isChecked);
-                        await checkboxWidget?.updateAp();
-                        return;
-                    }
-                }
-                break;
-            }
-            case 'Radiobutton Set Checked': {
-                const pageCount = await pdfReaderRef!.current!._pdfDocument.getPageCount();
-                for (let i = 0; i < pageCount; i++) {
-                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
-                    const widgets = await page?.getWidgets();
-                    const radiobuttonWidget = widgets?.find(widget => widget.type === CPDFWidgetType.RADIO_BUTTON) as CPDFRadiobuttonWidget;
-                    if (radiobuttonWidget) {
-                        await radiobuttonWidget?.setChecked(!radiobuttonWidget.isChecked);
-                        console.log('ComPDFKitRN-Radiobutton Set Checked:', radiobuttonWidget.isChecked);
-                        await radiobuttonWidget?.updateAp();
-                        return;
-                    }
-                }
-                break;
-            }
-            case 'SignatureWidget image signature':{
-                const pageCount = await pdfReaderRef!.current!._pdfDocument.getPageCount();
-                for (let i = 0; i < pageCount; i++) {
-                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
-                    const widgets = await page?.getWidgets();
-                    const signatureWidget = widgets?.find(widget => widget.type === CPDFWidgetType.SIGNATURES_FIELDS) as CPDFSignatureWidget;
-                    if (signatureWidget) {
-                        
-                        const pickerResult = DocumentPicker.pick({
-                            type: [DocumentPicker.types.images],
-                            copyTo: 'cachesDirectory'
-                        });
-                        pickerResult.then(async (res) => {
-                            const file = res[0];
-                            const path = file!!.fileCopyUri!!
-                            await signatureWidget?.addImageSignature(path);
-                        })
-                        return;
-                    }
-                }
-                break;
-            }
             default:
                 break;
         }

+ 435 - 0
example/src/CPDFWidgetsExample.tsx

@@ -0,0 +1,435 @@
+/**
+ * Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+import React, { useState, useRef } from 'react';
+import { Image, Modal, Platform, ScrollView, StyleSheet, Switch, Text, TextInput, TouchableOpacity, View } from 'react-native';
+import { CPDFReaderView, ComPDFKit, CPDFToolbarAction, CPDFWidgetType, CPDFTextWidget, CPDFRadiobuttonWidget, CPDFSignatureWidget, CPDFWidget } from '@compdfkit_pdf_sdk/react_native';
+import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
+import { HeaderBackButton } from '@react-navigation/elements';
+import { MenuProvider, Menu, MenuTrigger, MenuOptions, MenuOption } from 'react-native-popup-menu';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import DocumentPicker from 'react-native-document-picker';
+import { launchImageLibrary } from 'react-native-image-picker';
+
+type RootStackParamList = {
+    CPDFWidgetExample: { document?: string };
+};
+
+type CPDFWidgetsExampleScreenRouteProp = RouteProp<
+    RootStackParamList,
+    'CPDFWidgetExample'
+>;
+
+const CPDFWidgetsExampleScreen = () => {
+
+    const pdfReaderRef = useRef<CPDFReaderView>(null);
+
+    const navigation = useNavigation();
+
+    const route = useRoute<CPDFWidgetsExampleScreenRouteProp>();
+
+    const [widgetsModalVisible, setWidgetsModalVisible] = useState(false);
+
+    const [textEditModalVisible, setTextEditModalVisible] = useState(false);
+
+    const [widgetData, setWidgetData] = useState<CPDFWidget[]>([]);
+
+    const [text, setText] = useState('');
+
+    const [currentEditingWidgetIndex, setCurrentEditingWidgetIndex] = useState<number | null>(null);
+
+    const [samplePDF] = useState(
+        route.params?.document || (Platform.OS === 'android'
+            ? 'file:///android_asset/annot_test.pdf'
+            : 'annot_test.pdf')
+    );
+
+    const menuOptions = [
+        'openDocument',
+        'Import Widgets',
+        'Export Widgets',
+        'Get Widgets',
+    ];
+
+    const handleMenuItemPress = async (action: string) => {
+        switch (action) {
+            case 'openDocument':
+                const document = await ComPDFKit.pickFile();
+                if (document) {
+                    await pdfReaderRef.current?._pdfDocument.open(document);
+                }
+                break;
+            case 'Import Widgets':
+                const pickerResult = DocumentPicker.pick({
+                    type: [DocumentPicker.types.allFiles],
+                    copyTo: 'cachesDirectory'
+                });
+                pickerResult.then(async (res) => {
+                    const file = res[0];
+
+                    console.log('fileUri:', file?.uri);
+                    console.log('fileCopyUri:', file?.fileCopyUri);
+                    console.log('fileType:', file?.type);
+                    const path = file!!.fileCopyUri!!
+                    if (!path?.endsWith('xml') && !path?.endsWith('xfdf')) {
+                        console.log('ComPDFKitRN please select xfdf format file');
+                        return;
+                    }
+                    console.log('ComPDFKitRN importWidget, filePath:', path);
+                    const importWidgetResult = await pdfReaderRef.current?._pdfDocument.importWidgets(path);
+                    console.log('ComPDFKitRN importWidget:', importWidgetResult);
+                })
+
+                break;
+            case 'Export Widgets':
+                const exportWidgetsPath = await pdfReaderRef.current?._pdfDocument.exportWidgets();
+                console.log('ComPDFKitRN exportWidgets:', exportWidgetsPath)
+                break;
+
+            case 'Get Annotations':
+                const pageCount = await pdfReaderRef!.current!._pdfDocument.getPageCount();
+                for (let i = 0; i < pageCount; i++) {
+                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
+                    const annotations = await page?.getAnnotations();
+                    console.log(`ComPDFKitRN-annotations pageIndex ${i}:`);
+                    console.log(JSON.stringify(annotations, null, 2));
+                }
+                break;
+            case 'Get Widgets':
+                const pageCount1 = await pdfReaderRef!.current!._pdfDocument.getPageCount();
+                let allWidgets: CPDFWidget[] = [];
+                for (let i = 0; i < pageCount1; i++) {
+                    const page = pdfReaderRef?.current?._pdfDocument.pageAtIndex(i);
+                    const widgets = await page?.getWidgets();
+                    if (widgets) {
+                        allWidgets = allWidgets.concat(widgets);
+                    }
+                    console.log(JSON.stringify(widgets, null, 2));
+                }
+                setWidgetData(allWidgets);
+                setWidgetsModalVisible(true);
+                break;
+            default:
+                break;
+        }
+    };
+
+    const handleBack = () => {
+        navigation.goBack();
+    };
+
+    const renderToolbar = () => {
+        return (
+            <View style={styles.toolbar}>
+                <HeaderBackButton onPress={handleBack} />
+                <Text style={styles.toolbarTitle}>Widgets Example</Text>
+                <Menu>
+                    <MenuTrigger>
+                        <Image source={require('../assets/more.png')} style={{ width: 24, height: 24, marginEnd: 8 }} />
+                    </MenuTrigger>
+
+                    <MenuOptions>
+                        {menuOptions.map((option, index) => (
+                            <MenuOption key={index} onSelect={() => handleMenuItemPress(option)}>
+                                <Text style={styles.menuOption}>{option}</Text>
+                            </MenuOption>
+                        ))}
+                    </MenuOptions>
+                </Menu>
+            </View>
+        );
+    };
+
+    const widgetItem = (index: number, widget: CPDFWidget) => {
+        return (
+            <TouchableOpacity key={index} onPress={async () => {
+                await pdfReaderRef?.current?.setDisplayPageIndex(widget.page);
+                setWidgetsModalVisible(false);
+            }}>
+                <View style={{ width: '100%' }}>
+                    <View style={{ flexDirection: 'row' }}>
+                        <Text style={styles.widgetItem}>Title: </Text>
+                        <Text style={styles.widgetBody}>{widget.title}</Text>
+                    </View>
+                    <View style={{ flexDirection: 'row' }}>
+                        <Text style={styles.widgetItem}>Type: </Text>
+                        <Text style={styles.widgetBody}>{widget.type.toUpperCase()}</Text>
+                    </View>
+                    <View style={{ flexDirection: 'row' }}>
+                        <Text style={styles.widgetItem}>PageIndex: </Text>
+                        <Text style={styles.widgetBody}>{widget.page}</Text>
+                    </View>
+
+                    {widget.type === CPDFWidgetType.TEXT_FIELD && (
+                        <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
+                            <Text style={styles.widgetBody}>{(widget as CPDFTextWidget).text}</Text>
+                            <TouchableOpacity style={{ paddingHorizontal: 16, paddingVertical:4}} onPress={async () => {
+                                setCurrentEditingWidgetIndex(index);
+                                setTextEditModalVisible(true);
+                            }}>
+                                <Text style={styles.closeButtonText}>Edit</Text>
+                            </TouchableOpacity>
+                        </View>
+                    )}
+                    {(widget.type === CPDFWidgetType.RADIO_BUTTON || widget.type == CPDFWidgetType.CHECKBOX) && (
+                        <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
+                            <Text style={styles.widgetItem}>isChecked:</Text>
+                            <Switch
+                                thumbColor={(widget as CPDFRadiobuttonWidget).isChecked ? '#1460F3' : 'white'}
+                                trackColor={{ false: '#E0E0E0', true: '#1460F34D' }}
+                                value={(widget as CPDFRadiobuttonWidget).isChecked} onValueChange={async () => {
+                                    const updatedWidgetData = [...widgetData];
+
+                                    if ((widget as CPDFRadiobuttonWidget).type === CPDFWidgetType.RADIO_BUTTON || (widget as CPDFRadiobuttonWidget).type === CPDFWidgetType.CHECKBOX) {
+                                        const updatedWidget = widget as CPDFRadiobuttonWidget;
+                                        const newChecked = !updatedWidget.isChecked;
+                                        // change RadioButtonWidget or CPDFCheckboxWidget checked status;
+                                        await updatedWidget.setChecked(newChecked);
+                                        // update appearance
+                                        await updatedWidget.updateAp();
+
+                                        updatedWidgetData[index] = { ...widget, isChecked: newChecked };
+                                        setWidgetData(updatedWidgetData);
+                                    }
+                                }} />
+                        </View>
+                    )}
+                    {widget.type === CPDFWidgetType.SIGNATURES_FIELDS && (
+                        <View style={{ flexDirection: 'row', justifyContent: 'flex-end' }}>
+                            <TouchableOpacity style={{ paddingVertical:4}} onPress={async () => {
+                                const signatureWidget = widget as CPDFSignatureWidget;
+                                launchImageLibrary({
+                                    mediaType:'photo'
+                                }, async res => {
+                                    if( res.didCancel){
+                                        return false;
+                                    }
+                                    const path = res.assets?.[0]?.uri;
+                                    const signResult = await signatureWidget?.addImageSignature(path!);
+                                    if(signResult){
+                                        setWidgetsModalVisible(false);
+                                    }
+                                    return true;
+                                })
+                            }}>
+                                <Text style={styles.closeButtonText}>Signature</Text>
+                            </TouchableOpacity>
+                        </View>
+                    )}
+                    <View style={{ flex: 1, height: 1.5, backgroundColor: 'gray', opacity: 0.2, marginVertical: 5 }} />
+                </View>
+            </TouchableOpacity>
+        );
+    }
+
+    return (
+        <MenuProvider>
+            <SafeAreaView style={{ flex: 1 }}>
+                <View style={{ flex: 1 }}>
+                    {renderToolbar()}
+                    <CPDFReaderView
+                        ref={pdfReaderRef}
+                        document={samplePDF}
+                        configuration={ComPDFKit.getDefaultConfig({
+                            toolbarConfig: {
+                                iosLeftBarAvailableActions: [
+                                    CPDFToolbarAction.THUMBNAIL
+                                ]
+                            }
+                        })} />
+                </View>
+                <Modal visible={widgetsModalVisible} transparent={true} animationType="slide">
+                    <View style={styles.modalContainer}>
+                        <View style={styles.modalContent}>
+                            <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
+                                <Text style={styles.modalTitle}>Forms List</Text>
+                                <TouchableOpacity onPress={() => setWidgetsModalVisible(false)} style={styles.closeButton}>
+                                    <Text style={styles.closeButtonText}>Close</Text>
+                                </TouchableOpacity>
+                            </View>
+                            <ScrollView>
+                                {widgetData.map((widget, index) => (
+                                    widgetItem(index, widget)
+                                ))}
+                            </ScrollView>
+                        </View>
+                    </View>
+                </Modal>
+
+                <Modal visible={textEditModalVisible} transparent={true} animationType="fade">
+                    <View style={styles.editTextModalContainer}>
+                        <View style={styles.editTextModalContent}>
+                            <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
+                                <Text style={styles.modalTitle}>Edit Text</Text>
+                            </View>
+
+                            <TextInput
+                                style={styles.inputField}
+                                value={text}
+                                onChangeText={(newText) => setText(newText)}
+                                placeholder="Enter text here"
+                                multiline={true}
+                                numberOfLines={4}
+                            />
+
+                            <View style={styles.buttonContainer}>
+                                <TouchableOpacity onPress={() => {
+                                    setTextEditModalVisible(false);
+                                }} style={styles.button}>
+                                    <Text style={styles.buttonText}>Cancel</Text>
+                                </TouchableOpacity>
+                                <TouchableOpacity onPress={async () => {
+                                    if (currentEditingWidgetIndex !== null && currentEditingWidgetIndex !== undefined) {
+                                    const updatedWidgetData = [...widgetData];
+                                    const widget = updatedWidgetData[currentEditingWidgetIndex];
+
+                                    console.log(JSON.stringify(widget, null, 2));
+                                    if(widget === undefined) {
+                                        return;
+                                    }
+                                    if (widget.type === CPDFWidgetType.TEXT_FIELD) {
+                                        const textWidget = widget as CPDFTextWidget;
+
+                                        try {
+                                            // change textFields text
+                                            await textWidget.setText(text);
+                                            await textWidget.updateAp();
+
+                                            if (updatedWidgetData[currentEditingWidgetIndex]) {
+                                                (updatedWidgetData[currentEditingWidgetIndex] as CPDFTextWidget).text = text;
+                                            }
+                                            setWidgetData(updatedWidgetData);
+                                        } catch (error) {
+                                            console.error("Failed to update text widget:", error);
+                                        }
+                                    }
+                                    setTextEditModalVisible(false);
+                                }
+                                }} style={styles.button}>
+                                    <Text style={styles.buttonText}>Confirm</Text>
+
+                                </TouchableOpacity>
+                            </View>
+                        </View>
+                    </View>
+                </Modal>
+
+            </SafeAreaView>
+        </MenuProvider>
+    );
+
+
+};
+
+
+
+const styles = StyleSheet.create({
+    toolbar: {
+        height: 56,
+        flexDirection: 'row',
+        alignItems: 'center',
+        justifyContent: 'flex-start',
+        backgroundColor: '#FAFCFF',
+        paddingHorizontal: 4,
+    },
+    toolbarButton: {
+        padding: 8,
+    },
+    toolbarTitle: {
+        flex: 1,
+        color: 'black',
+        fontSize: 16,
+        fontWeight: 'bold',
+        marginStart: 8
+    },
+    menuOption: {
+        padding: 8,
+        fontSize: 14,
+        color: 'black',
+    },
+    modalContainer: {
+        flex: 1,
+        justifyContent: 'flex-end',
+        backgroundColor: 'rgba(3, 3, 3, 0.2)',
+    },
+    modalContent: {
+        width: '100%',
+        maxHeight: '60%',
+        backgroundColor: 'white',
+        padding: 16,
+        borderTopLeftRadius: 10,
+        borderTopRightRadius: 10,
+    },
+    modalTitle: {
+        fontSize: 18,
+        fontWeight: '700',
+        marginBottom: 10,
+        color: 'black'
+    },
+    widgetItem: {
+        fontSize: 14,
+        paddingVertical: 5,
+        fontWeight: '500',
+        color: 'black'
+    },
+    widgetBody: {
+        fontSize: 14,
+        paddingVertical: 5,
+
+    },
+    closeButton: {
+        paddingVertical: 4,
+        paddingHorizontal: 8,
+        marginEnd: 8,
+    },
+    closeButtonText: {
+        color: '#007BFF',
+        fontSize: 14,
+    },
+    editTextModalContainer: {
+        flex: 1,
+        justifyContent: 'center',
+        alignItems: 'center',
+        backgroundColor: 'rgba(3, 3, 3, 0.2)',
+    },
+    editTextModalContent: {
+        width: '80%',
+        backgroundColor: 'white',
+        padding: 16,
+        borderRadius: 10
+    },
+    inputField: {
+        height: 100,
+        borderColor: 'gray',
+        borderWidth: 1,
+        borderRadius: 5,
+        padding: 10,
+        marginBottom: 20,
+        textAlignVertical: 'top',
+    },
+    buttonContainer: {
+        flexDirection: 'row',
+        justifyContent: 'flex-end',
+    },
+    button: {
+        paddingVertical: 10,
+        paddingHorizontal: 20,
+        borderRadius: 5,
+        marginTop: 10,
+    },
+    buttonText: {
+        color: '#1460F3',
+        fontSize: 16,
+    },
+});
+
+export default CPDFWidgetsExampleScreen;
+
+
+

+ 10 - 2
example/src/examples.tsx

@@ -79,13 +79,21 @@ const uiConpomentExamples = [
     {
         key: 'item6',
         title: 'Annotations Example',
-        description: 'Demonstrate how to implement annotation functionality using the CPDFReaderView UI component, including adding, editing, and deleting annotations.',
+        description: 'Demonstrate annotation functionality in CPDFReaderView, including adding, editing, and deleting.',
         action: (component: any)  => {
             component.props.navigation.navigate('CPDFAnnotationsExample');
         }
     },
     {
         key: 'item7',
+        title: 'Widgets Example',
+        description: 'Demonstrate form functionality in CPDFReaderView, including retrieving, modifying, importing, and exporting data.',
+        action: (component: any)  => {
+            component.props.navigation.navigate('CPDFWidgetsExample');
+        }
+    },
+    {
+        key: 'item8',
         title: 'Security Example',
         description: 'This example shows how to set passwords, watermarks, etc.',
         action: (component: any)  => {
@@ -93,7 +101,7 @@ const uiConpomentExamples = [
         }
     },
     {
-        key: 'item8',
+        key: 'item9',
         title: 'Pages Example',
         description: 'This example demonstrates PDF page related operations, such as inserting and splitting PDF documents.',
         action: (component: any)  => {

+ 3 - 6
ios/RCTDocumentManager.m

@@ -234,15 +234,13 @@ RCT_EXTERN_METHOD(setWidgetIsChecked:(NSInteger)tag
                   withPage:(NSInteger) page
                   withUuid:(NSString *) uuid
                   withIsChecked:(BOOL)isChecked
-                  withResolver:(RCTPromiseResolveBlock)resolve
-                  withRejecter:(RCTPromiseRejectBlock)reject)
+                  )
 
 RCT_EXTERN_METHOD(setTextWidgetText:(NSInteger)tag
                   withPage:(NSInteger) page
                   withUuid:(NSString *) uuid
                   withText:(NSString *)text
-                  withResolver:(RCTPromiseResolveBlock)resolve
-                  withRejecter:(RCTPromiseRejectBlock)reject)
+                  )
 
 RCT_EXTERN_METHOD(addWidgetImageSignature:(NSInteger)tag
                   withPage:(NSInteger) page
@@ -255,8 +253,7 @@ RCT_EXTERN_METHOD(addWidgetImageSignature:(NSInteger)tag
 RCT_EXTERN_METHOD(updateAp:(NSInteger)tag
                   withPage:(NSInteger) page
                   withUuid:(NSString *) uuid
-                  withResolver:(RCTPromiseResolveBlock)resolve
-                  withRejecter:(RCTPromiseRejectBlock)reject)
+                  )
 
 RCT_EXTERN_METHOD(reloadPages:(NSInteger)tag
                   withResolver:(RCTPromiseResolveBlock)resolve

+ 6 - 6
ios/RCTDocumentManager.swift

@@ -569,16 +569,16 @@ class RCTDocumentManager: NSObject, RCTBridgeModule {
         }
     }
     
-    @objc(setWidgetIsChecked: withPage: withUuid: withIsChecked: withResolver: withRejecter:)
-    func setWidgetIsChecked(forCPDFViewTag tag : Int, page: Int, uuid: String, isChecked: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+    @objc(setWidgetIsChecked: withPage: withUuid: withIsChecked: )
+    func setWidgetIsChecked(forCPDFViewTag tag : Int, page: Int, uuid: String, isChecked: Bool) {
         DispatchQueue.main.async {
             let reader = self.readerView()
             reader.setWidgetIsChecked(forCPDFViewTag: tag, pageIndex: page, uuid: uuid, isChecked: isChecked)
         }
     }
     
-    @objc(setTextWidgetText: withPage: withUuid: withText: withResolver: withRejecter:)
-    func setTextWidgetText(forCPDFViewTag tag : Int, page: Int, uuid: String, text: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+    @objc(setTextWidgetText: withPage: withUuid: withText:)
+    func setTextWidgetText(forCPDFViewTag tag : Int, page: Int, uuid: String, text: String) {
         DispatchQueue.main.async {
             let reader = self.readerView()
             reader.setTextWidgetText(forCPDFViewTag: tag, pageIndex: page, uuid: uuid, text: text)
@@ -596,8 +596,8 @@ class RCTDocumentManager: NSObject, RCTBridgeModule {
         }
     }
     
-    @objc(updateAp: withPage: withUuid: withResolver: withRejecter:)
-    func updateAp(forCPDFViewTag tag : Int, page: Int, uuid: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+  @objc(updateAp: withPage: withUuid:)
+    func updateAp(forCPDFViewTag tag : Int, page: Int, uuid: String) {
         DispatchQueue.main.async {
             let reader = self.readerView()
             reader.updateAp(forCPDFViewTag: tag, pageIndex: page, uuid: uuid)

+ 2 - 16
src/annotation/form/CPDFCheckboxWidget.tsx

@@ -7,6 +7,7 @@
  * This notice may not be removed from this file.
  */
 
+import { CPDFRadiobuttonWidget } from "./CPDFRadiobuttonWidget";
 import { CPDFWidget } from "./CPDFWidget";
 import { NativeModules, findNodeHandle } from 'react-native';
 const { CPDFViewManager } = NativeModules;
@@ -14,26 +15,11 @@ const { CPDFViewManager } = NativeModules;
 /**
  * Class representing a checkbox form widget, storing basic information about the checkbox form.
  */
-export class CPDFCheckboxWidget extends CPDFWidget {
-
-    /**
-     * The checked state of the checkbox.
-     */
-    isChecked: boolean;
+export class CPDFCheckboxWidget extends CPDFRadiobuttonWidget {
 
     constructor(viewerRef : any, params: Partial<CPDFCheckboxWidget>) {
         super(viewerRef, params);
         this.isChecked = params.isChecked ?? false;
     }
-
-    setChecked = async (isChecked: boolean): Promise<void> => {
-        const tag = findNodeHandle(this._viewerRef);
-        if (tag != null) {
-             await CPDFViewManager.setWidgetIsChecked(tag, this.page, this.uuid, isChecked)
-             this.isChecked = isChecked;
-             return;
-        }
-        return Promise.reject(new Error('Unable to find the native view reference'));
-    }
 }
 

+ 1 - 1
src/annotation/form/CPDFTextWidget.tsx

@@ -33,7 +33,7 @@ export class CPDFTextWidget extends CPDFWidget {
 
     setText = async (text: string): Promise<void> => {
         const tag = findNodeHandle(this._viewerRef);
-        if (tag != null) {
+        if (tag) {
             try {
                 await CPDFViewManager.setTextWidgetText(tag, this.page, this.uuid, text);
                 this.text = text;

+ 7 - 2
src/annotation/form/CPDFWidget.tsx

@@ -73,8 +73,13 @@ export class CPDFWidget {
 
     updateAp = () : Promise<void> => {
         const tag = findNodeHandle(this._viewerRef);
-        if (tag != null) {
-            return CPDFViewManager.updateAp(tag, this.page, this.uuid);
+        if (tag) {
+            try {
+                return CPDFViewManager.updateAp(tag, this.page, this.uuid);
+            } catch (error) {
+                console.log(error);
+            }
+            
         }
         return Promise.reject(new Error('Unable to find the native view reference'));
     }