├── ios ├── Cartfile ├── Cartfile.resolved ├── RNTAztecView │ ├── BlockModel.swift │ ├── RCTAztecView-Bridging-Header.h │ ├── BlockFormatHandler.swift │ ├── RCTAztecViewManager.m │ ├── HeadingBlockFormatHandler.swift │ ├── RCTAztecViewManager.swift │ └── RCTAztecView.swift └── RNTAztecView.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── project.pbxproj ├── example ├── .babelrc ├── app.json ├── ios │ ├── example │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ ├── aztec.imageset │ │ │ │ ├── aztec.png │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── BridgeDelegate.swift │ │ ├── Info.plist │ │ ├── MediaProvider.swift │ │ ├── AppDelegate.swift │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── example-Bridging-Header.h │ ├── exampleTests │ │ ├── Info.plist │ │ └── exampleTests.m │ └── example.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── example.xcscheme ├── index.js ├── android │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── drawable-hdpi │ │ │ │ │ ├── tile.9.png │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values │ │ │ │ │ ├── styles.xml │ │ │ │ │ ├── dimens.xml │ │ │ │ │ ├── fragmentview_strings.xml │ │ │ │ │ ├── colors.xml │ │ │ │ │ ├── strings.xml │ │ │ │ │ ├── template-dimens.xml │ │ │ │ │ └── template-styles.xml │ │ │ │ ├── drawable │ │ │ │ │ └── ic_reorder_black_24dp.xml │ │ │ │ ├── values-sw600dp │ │ │ │ │ ├── template-dimens.xml │ │ │ │ │ └── template-styles.xml │ │ │ │ ├── menu │ │ │ │ │ └── main.xml │ │ │ │ ├── layout │ │ │ │ │ └── activity_main.xml │ │ │ │ └── layout-w720dp │ │ │ │ │ └── activity_main.xml │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── android │ │ │ │ ├── MyFragment.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── common │ │ │ │ └── activities │ │ │ │ └── SampleRNBaseActivity.java │ │ └── build.gradle │ ├── settings.gradle │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── rn-cli.config.js ├── iOS │ └── example.xcodeproj │ │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── package.json ├── App.js ├── editor.js └── content.js ├── index.js ├── .flowconfig ├── android ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── res │ │ ├── drawable-hdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ │ └── ic_launcher.png │ │ └── values │ │ │ ├── bools.xml │ │ │ ├── integers.xml │ │ │ ├── strings.xml │ │ │ └── template-dimens.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── org │ │ └── wordpress │ │ └── mobile │ │ └── ReactNativeAztec │ │ ├── ReactAztecPackage.java │ │ ├── ReactAztecBlurEvent.java │ │ ├── ReactAztecFocusEvent.java │ │ ├── ReactAztecEndEditingEvent.java │ │ ├── ReactAztecFormattingChangeEvent.java │ │ ├── ReactAztecEnterEvent.java │ │ ├── ReactAztecBackSpaceEvent.java │ │ ├── ReactAztecSelectionChangeEvent.java │ │ └── ReactAztecText.java ├── gradlew.bat ├── build.gradle └── gradlew ├── LICENSE.md ├── RNTAztecView.podspec ├── package.json ├── README.md ├── .gitignore ├── src └── AztecView.js ├── MPL-2.0.md └── GPL-2.0.md /ios/Cartfile: -------------------------------------------------------------------------------- 1 | github "wordpress-mobile/AztecEditor-iOS" ~> 1.4 2 | 3 | -------------------------------------------------------------------------------- /ios/Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "wordpress-mobile/AztecEditor-iOS" "1.4.1" 2 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["module:metro-react-native-babel-preset"] 3 | } 4 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "displayName": "example" 4 | } -------------------------------------------------------------------------------- /ios/RNTAztecView/BlockModel.swift: -------------------------------------------------------------------------------- 1 | struct BlockModel { 2 | let tag: String 3 | } 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import RCTAztecView from './src/AztecView'; 2 | 3 | export default RCTAztecView; 4 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | 11 | [strict] 12 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import {AppRegistry} from 'react-native'; 2 | import example from './App'; 3 | 4 | AppRegistry.registerComponent('example', () => example); -------------------------------------------------------------------------------- /android/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/android/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/android/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/android/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/android/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/src/main/res/values/bools.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/src/main/res/values/integers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-hdpi/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/android/app/src/main/res/drawable-hdpi/tile.9.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/aztec.imageset/aztec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/ios/example/Images.xcassets/aztec.imageset/aztec.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/android/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/android/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/android/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wordpress-mobile/react-native-aztec/trunk/example/android/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'example' 2 | 3 | include ':react-native-aztec' 4 | project(':react-native-aztec').projectDir = new File(rootProject.projectDir, '../../android') 5 | 6 | include ':app' 7 | 8 | -------------------------------------------------------------------------------- /example/rn-cli.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | watchFolders: [path.resolve(__dirname, '..')], 5 | resolver: { 6 | providesModuleNodeModules:[ 'react-native', 'react',], 7 | }, 8 | }; -------------------------------------------------------------------------------- /example/iOS/example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This work is dual licensed under the [Mozilla Public License version 2.0 (MPL-2.0)](MPL-2.0.md) or the [GNU General Public License v2.0 or later (GPL-2.0)](GPL-2.0.md). 2 | 3 | You can choose between one of them, or both if you use this work. 4 | -------------------------------------------------------------------------------- /ios/RNTAztecView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/example-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import 6 | #import 7 | #import 8 | -------------------------------------------------------------------------------- /ios/RNTAztecView/RCTAztecView-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import 6 | #import 7 | #import 8 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 08 13:53:18 PDT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 08 13:53:18 PDT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip -------------------------------------------------------------------------------- /example/iOS/example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/RNTAztecView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/iOS/example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/aztec.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "aztec.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/ic_reorder_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /ios/RNTAztecView/BlockFormatHandler.swift: -------------------------------------------------------------------------------- 1 | 2 | /// Classes conforming this protocol are meant to do formatting work over an specific block. 3 | /// It is useful when we need to force an specific typing format that Aztec is not showing by default. 4 | /// 5 | protocol BlockFormatHandler { 6 | 7 | /// Create an instance of a block formatter handler for the given block. 8 | /// If the given block is not compatible, the init will fail. 9 | /// 10 | init?(block: BlockModel) 11 | 12 | /// Set the typing format to an specific one. 13 | /// 14 | func forceTypingFormat(on textView: RCTAztecView) 15 | } 16 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 100dp 20 | -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | Aztec React Native example 20 | -------------------------------------------------------------------------------- /example/ios/example/BridgeDelegate.swift: -------------------------------------------------------------------------------- 1 | import Aztec 2 | import Foundation 3 | 4 | // IMPORTANT: if you're seeing a warning with this import, keep in mind it's marked as a Swift 5 | // bug. I wasn't able to get any of the workarounds to work. 6 | // 7 | // Ref: https://bugs.swift.org/browse/SR-3801 8 | // 9 | import RNTAztecView 10 | 11 | class BridgeDelegate: NSObject, RCTBridgeDelegate { 12 | let sourceURL: URL 13 | let aztecViewManager = RCTAztecViewManager() 14 | 15 | init(sourceURL: URL) { 16 | self.sourceURL = sourceURL 17 | super.init() 18 | } 19 | 20 | func sourceURL(for bridge: RCTBridge!) -> URL! { 21 | return sourceURL 22 | } 23 | 24 | func extraModules(for bridge: RCTBridge!) -> [RCTBridgeModule]! { 25 | return [aztecViewManager] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/fragmentview_strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | Show Log 18 | Hide Log 19 | 20 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | #00BCD4 21 | #00838F 22 | 23 | 24 | -------------------------------------------------------------------------------- /example/ios/exampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecPackage.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class ReactAztecPackage implements ReactPackage { 14 | 15 | @Override 16 | public List createViewManagers(ReactApplicationContext reactContext) { 17 | List views = new ArrayList<>(); 18 | views.add(new ReactAztecManager()); 19 | return views; 20 | } 21 | 22 | @Override 23 | public List createNativeModules(ReactApplicationContext reactContext) { 24 | return Collections.emptyList(); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /RNTAztecView.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = 'RNTAztecView' 7 | s.version = package['version'] 8 | s.summary = 'Aztec editor for React Native' 9 | s.license = package['license'] 10 | s.homepage = 'https://github.com/wordpress-mobile/react-native-aztec' 11 | s.authors = 'Automattic' 12 | s.source = { :git => 'https://github.com/wordpress-mobile/react-native-aztec.git' } 13 | s.source_files = 'ios/RNTAztecView/*.{h,m,swift}' 14 | s.public_header_files = 'ios/RNTAztecView/*.h' 15 | s.requires_arc = true 16 | s.platforms = { :ios => "10.0" } 17 | s.xcconfig = {'OTHER_LDFLAGS' => '-lxml2', 18 | 'HEADER_SEARCH_PATHS' => '/usr/include/libxml2'} 19 | s.dependency 'React' 20 | s.dependency 'WordPress-Aztec-iOS' 21 | 22 | end 23 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-sw600dp/template-dimens.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | @dimen/margin_huge 22 | @dimen/margin_medium 23 | 24 | 25 | -------------------------------------------------------------------------------- /android/src/main/res/values/template-dimens.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 8dp 22 | 16dp 23 | 32dp 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | 23 | 24 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-sw600dp/template-styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | Aztec React Native example 20 | Element 21 | Grid Layout Manager 22 | Linear Layout Manager 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-aztec", 3 | "version": "0.1.5", 4 | "license": "(MPL-2.0 OR GPL-2.0)", 5 | "scripts": { 6 | "install-aztec-ios": "cd ./ios && carthage bootstrap --platform iOS --cache-builds", 7 | "clean": "yarn clean-watchman; yarn clean-node; yarn clean-react; yarn clean-metro; yarn clean-jest;", 8 | "clean-jest": "rm -rf $TMPDIR/jest_*;", 9 | "clean-metro": "rm -rf $TMPDIR/metro-cache-*; rm -rf $TMPDIR/metro-bundler-cache-*;", 10 | "clean-node": "rm -rf node_modules/;", 11 | "clean-react": "rm -rf $TMPDIR/react-*; rm -rf $TMPDIR/react-native-packager-cache-*;", 12 | "clean-watchman": "command -v watchman >/dev/null 2>&1 && watchman watch-del-all;", 13 | "clean:install": "yarn clean && yarn install" 14 | }, 15 | "peerDependencies": { 16 | "react": "16.6.1", 17 | "react-native": "0.57.5" 18 | }, 19 | "dependencies": { 20 | "prop-types": "15.6.0" 21 | }, 22 | "devDependencies": { 23 | "babel-cli": "^6.26.0", 24 | "babel-preset-flow": "^6.23.0", 25 | "flow-bin": "^0.69.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecBlurEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | /** 9 | * Event emitted by Aztec native view when it loses focus. 10 | */ 11 | class ReactAztecBlurEvent extends Event { 12 | 13 | private static final String EVENT_NAME = "topBlur"; 14 | 15 | public ReactAztecBlurEvent(int viewId) { 16 | super(viewId); 17 | } 18 | 19 | @Override 20 | public String getEventName() { 21 | return EVENT_NAME; 22 | } 23 | 24 | @Override 25 | public boolean canCoalesce() { 26 | return false; 27 | } 28 | 29 | @Override 30 | public void dispatch(RCTEventEmitter rctEventEmitter) { 31 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 32 | } 33 | 34 | private WritableMap serializeEventData() { 35 | WritableMap eventData = Arguments.createMap(); 36 | eventData.putInt("target", getViewTag()); 37 | return eventData; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecFocusEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | /** 9 | * Event emitted by Aztec native view when it receives focus. 10 | */ 11 | class ReactAztecFocusEvent extends Event { 12 | 13 | private static final String EVENT_NAME = "topFocus"; 14 | 15 | public ReactAztecFocusEvent(int viewId) { 16 | super(viewId); 17 | } 18 | 19 | @Override 20 | public String getEventName() { 21 | return EVENT_NAME; 22 | } 23 | 24 | @Override 25 | public boolean canCoalesce() { 26 | return false; 27 | } 28 | 29 | @Override 30 | public void dispatch(RCTEventEmitter rctEventEmitter) { 31 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 32 | } 33 | 34 | private WritableMap serializeEventData() { 35 | WritableMap eventData = Arguments.createMap(); 36 | eventData.putInt("target", getViewTag()); 37 | return eventData; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ios/RNTAztecView/RCTAztecViewManager.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface RCT_EXTERN_MODULE(RCTAztecViewManager, NSObject) 4 | 5 | RCT_REMAP_VIEW_PROPERTY(text, contents, NSDictionary) 6 | RCT_EXPORT_VIEW_PROPERTY(onContentSizeChange, RCTBubblingEventBlock) 7 | RCT_EXPORT_VIEW_PROPERTY(onBackspace, RCTBubblingEventBlock) 8 | RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) 9 | RCT_EXPORT_VIEW_PROPERTY(onEnter, RCTBubblingEventBlock) 10 | RCT_EXPORT_VIEW_PROPERTY(onFocus, RCTBubblingEventBlock) 11 | RCT_EXPORT_VIEW_PROPERTY(onBlur, RCTBubblingEventBlock) 12 | RCT_EXPORT_VIEW_PROPERTY(onSelectionChange, RCTDirectEventBlock) 13 | RCT_EXPORT_VIEW_PROPERTY(blockType, NSDictionary) 14 | 15 | RCT_EXPORT_VIEW_PROPERTY(onActiveFormatsChange, RCTBubblingEventBlock) 16 | RCT_EXPORT_VIEW_PROPERTY(onActiveFormatAttributesChange, RCTBubblingEventBlock) 17 | 18 | RCT_EXPORT_VIEW_PROPERTY(placeholder, NSString) 19 | RCT_EXPORT_VIEW_PROPERTY(placeholderTextColor, UIColor) 20 | 21 | RCT_EXTERN_METHOD(applyFormat:(nonnull NSNumber *)node format:(NSString *)format) 22 | RCT_EXTERN_METHOD(setLink:(nonnull NSNumber *)node url:(nonnull NSString *)url title:(nullable NSString *)title) 23 | RCT_EXTERN_METHOD(removeLink:(nonnull NSNumber *)node) 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/template-dimens.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 4dp 22 | 8dp 23 | 16dp 24 | 32dp 25 | 64dp 26 | 27 | 28 | 29 | @dimen/margin_medium 30 | @dimen/margin_medium 31 | 32 | 33 | -------------------------------------------------------------------------------- /ios/RNTAztecView/HeadingBlockFormatHandler.swift: -------------------------------------------------------------------------------- 1 | import Aztec 2 | 3 | struct HeadingBlockFormatHandler: BlockFormatHandler { 4 | private let level: Header.HeaderType 5 | private let paragraphFormatter = HTMLParagraphFormatter(placeholderAttributes: nil) 6 | private let headerFormatter: HeaderFormatter 7 | 8 | init?(block: BlockModel) { 9 | guard let level = HeadingBlockFormatHandler.headerLevel(from: block.tag) else { 10 | return nil 11 | } 12 | self.level = level 13 | headerFormatter = HeaderFormatter(headerLevel: level) 14 | } 15 | 16 | func forceTypingFormat(on textView: RCTAztecView) { 17 | var attributes = textView.typingAttributesSwifted 18 | 19 | attributes = paragraphFormatter.remove(from: attributes) 20 | attributes = headerFormatter.apply(to: attributes, andStore: nil) 21 | 22 | textView.typingAttributesSwifted = attributes 23 | } 24 | 25 | private static func headerLevel(from levelString: String) -> Header.HeaderType? { 26 | switch levelString { 27 | case "h2": 28 | return .h2 29 | case "h3": 30 | return .h3 31 | case "h4": 32 | return .h4 33 | default: 34 | return nil 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | gradlePluginVersion = '3.0.1' 4 | kotlinVersion = '1.2.61' 5 | supportLibVersion = '27.1.1' 6 | tagSoupVersion = '1.2.1' 7 | glideVersion = '3.7.0' 8 | picassoVersion = '2.5.2' 9 | robolectricVersion = '3.5.1' 10 | jUnitVersion = '4.12' 11 | jSoupVersion = '1.10.3' 12 | wordpressUtilsVersion = '1.22' 13 | espressoVersion = '3.0.1' 14 | } 15 | 16 | repositories { 17 | jcenter() 18 | google() 19 | } 20 | 21 | dependencies { 22 | classpath 'com.android.tools.build:gradle:3.1.4' 23 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" 24 | } 25 | 26 | repositories { 27 | jcenter() 28 | } 29 | dependencies { 30 | classpath 'com.android.tools.build:gradle:2.2.3' 31 | 32 | // NOTE: Do not place your application dependencies here; they belong 33 | // in the individual module build.gradle files 34 | } 35 | } 36 | 37 | allprojects { 38 | repositories { 39 | mavenLocal() 40 | jcenter() 41 | maven { 42 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 43 | url "$rootDir/../node_modules/react-native/android" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "Example for running ponies", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node node_modules/react-native/local-cli/cli.js start", 8 | "android": "react-native run-android", 9 | "preinstall": "yarn install-aztec", 10 | "install-aztec": "pushd ../ && (yarn install; popd;)", 11 | "preios": "pushd ../ && (yarn install-aztec-ios; popd;)", 12 | "ios": "react-native run-ios", 13 | "test": "jest", 14 | "clean": "yarn clean-aztec; yarn clean-node; yarn clean-ios;", 15 | "clean-aztec": "pushd ../ && (yarn clean; popd;)", 16 | "clean-ios": "type xcodebuild &> /dev/null && (xcodebuild -project ./ios/example.xcodeproj -alltargets clean && rm -rf ./ios/build);", 17 | "clean-node": "rm -rf node_modules/;", 18 | "clean:install": "yarn clean && yarn install" 19 | }, 20 | "dependencies": { 21 | "react": "16.6.1", 22 | "react-native": "0.57.5" 23 | }, 24 | "devDependencies": { 25 | "metro-react-native-babel-preset": "^0.45.5", 26 | "@babel/core": "^7.1.0", 27 | "babel-core": "^7.0.0-bridge.0", 28 | "babel-jest": "23.6.0", 29 | "babel-plugin-module-resolver": "3.1.1", 30 | "eslint": "4.0.0", 31 | "jest": "23.6.0", 32 | "react-test-renderer": "16.5.0" 33 | }, 34 | "license": "(MPL-2.0 OR GPL-2.0)" 35 | } 36 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 16 | 22 | 23 | 27 | 28 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/layout-w720dp/activity_main.xml: -------------------------------------------------------------------------------- 1 | 16 | 22 | 23 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecEndEditingEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | /** 9 | * Event emitted by AztecText native view when text editing ends, 10 | * because of the user leaving the text input. 11 | */ 12 | class ReactAztecEndEditingEvent extends Event { 13 | 14 | private static final String EVENT_NAME = "topEndEditing"; 15 | 16 | private String mText; 17 | 18 | public ReactAztecEndEditingEvent( 19 | int viewId, 20 | String text) { 21 | super(viewId); 22 | mText = text; 23 | } 24 | 25 | @Override 26 | public String getEventName() { 27 | return EVENT_NAME; 28 | } 29 | 30 | @Override 31 | public boolean canCoalesce() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public void dispatch(RCTEventEmitter rctEventEmitter) { 37 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 38 | } 39 | 40 | private WritableMap serializeEventData() { 41 | WritableMap eventData = Arguments.createMap(); 42 | eventData.putInt("target", getViewTag()); 43 | eventData.putString("text", mText); 44 | return eventData; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecFormattingChangeEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableArray; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.facebook.react.uimanager.events.Event; 7 | import com.facebook.react.uimanager.events.RCTEventEmitter; 8 | 9 | /** 10 | * Event emitted by Aztec native view when it receives focus. 11 | */ 12 | class ReactAztecFormattingChangeEvent extends Event { 13 | 14 | private static final String EVENT_NAME = "topFormatsChanges"; 15 | 16 | private String[] mFormats; 17 | 18 | public ReactAztecFormattingChangeEvent(int viewId, String[] formats) { 19 | super(viewId); 20 | this.mFormats = formats; 21 | } 22 | 23 | @Override 24 | public String getEventName() { 25 | return EVENT_NAME; 26 | } 27 | 28 | @Override 29 | public boolean canCoalesce() { 30 | return false; 31 | } 32 | 33 | @Override 34 | public void dispatch(RCTEventEmitter rctEventEmitter) { 35 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 36 | } 37 | 38 | private WritableMap serializeEventData() { 39 | WritableMap eventData = Arguments.createMap(); 40 | eventData.putInt("target", getViewTag()); 41 | WritableArray newFormats = Arguments.fromArray(mFormats); 42 | eventData.putArray("formats", newFormats); 43 | return eventData; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecEnterEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | /** 9 | * Event emitted by Aztec native view when KEYCODE_ENTER is detected. 10 | */ 11 | class ReactAztecEnterEvent extends Event { 12 | 13 | private static final String EVENT_NAME = "topTextInputEnter"; 14 | 15 | private String mText; 16 | private int mSelectionStart; 17 | private int mSelectionEnd; 18 | 19 | public ReactAztecEnterEvent(int viewId, String text, int selectionStart, int selectionEnd) { 20 | super(viewId); 21 | mText = text; 22 | mSelectionStart = selectionStart; 23 | mSelectionEnd = selectionEnd; 24 | } 25 | 26 | @Override 27 | public String getEventName() { 28 | return EVENT_NAME; 29 | } 30 | 31 | @Override 32 | public boolean canCoalesce() { 33 | return false; 34 | } 35 | 36 | @Override 37 | public void dispatch(RCTEventEmitter rctEventEmitter) { 38 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 39 | } 40 | 41 | private WritableMap serializeEventData() { 42 | WritableMap eventData = Arguments.createMap(); 43 | eventData.putInt("target", getViewTag()); 44 | eventData.putString("text", mText); 45 | eventData.putInt("selectionStart", mSelectionStart); 46 | eventData.putInt("selectionEnd", mSelectionEnd); 47 | return eventData; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecBackSpaceEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.facebook.react.uimanager.events.Event; 6 | import com.facebook.react.uimanager.events.RCTEventEmitter; 7 | 8 | /** 9 | * Event emitted by Aztec native view when Backspace is detected. 10 | */ 11 | class ReactAztecBackspaceEvent extends Event { 12 | 13 | private static final String EVENT_NAME = "topTextInputBackspace"; 14 | 15 | private String mText; 16 | private int mSelectionStart; 17 | private int mSelectionEnd; 18 | 19 | public ReactAztecBackspaceEvent(int viewId, String text, int selectionStart, int selectionEnd) { 20 | super(viewId); 21 | mText = text; 22 | mSelectionStart = selectionStart; 23 | mSelectionEnd = selectionEnd; 24 | } 25 | 26 | @Override 27 | public String getEventName() { 28 | return EVENT_NAME; 29 | } 30 | 31 | @Override 32 | public boolean canCoalesce() { 33 | return false; 34 | } 35 | 36 | @Override 37 | public void dispatch(RCTEventEmitter rctEventEmitter) { 38 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 39 | } 40 | 41 | private WritableMap serializeEventData() { 42 | WritableMap eventData = Arguments.createMap(); 43 | eventData.putInt("target", getViewTag()); 44 | eventData.putString("text", mText); 45 | eventData.putInt("selectionStart", mSelectionStart); 46 | eventData.putInt("selectionEnd", mSelectionEnd); 47 | return eventData; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/template-styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 37 | 38 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecSelectionChangeEvent.java: -------------------------------------------------------------------------------- 1 | package org.wordpress.mobile.ReactNativeAztec; 2 | 3 | import com.facebook.react.bridge.Arguments; 4 | import com.facebook.react.bridge.WritableArray; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.facebook.react.uimanager.events.Event; 7 | import com.facebook.react.uimanager.events.RCTEventEmitter; 8 | 9 | /** 10 | * Event emitted by Aztec native view when selection changes. 11 | */ 12 | class ReactAztecSelectionChangeEvent extends Event { 13 | 14 | private static final String EVENT_NAME = "topSelectionChange"; 15 | 16 | private String mText; 17 | private int mSelectionStart; 18 | private int mSelectionEnd; 19 | 20 | public ReactAztecSelectionChangeEvent(int viewId, String text, int selectionStart, int selectionEnd) { 21 | super(viewId); 22 | mText = text; 23 | mSelectionStart = selectionStart; 24 | mSelectionEnd = selectionEnd; 25 | } 26 | 27 | @Override 28 | public String getEventName() { 29 | return EVENT_NAME; 30 | } 31 | 32 | @Override 33 | public boolean canCoalesce() { 34 | return false; 35 | } 36 | 37 | @Override 38 | public void dispatch(RCTEventEmitter rctEventEmitter) { 39 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); 40 | } 41 | 42 | private WritableMap serializeEventData() { 43 | WritableMap eventData = Arguments.createMap(); 44 | eventData.putInt("target", getViewTag()); 45 | eventData.putString("text", mText); 46 | eventData.putInt("selectionStart", mSelectionStart); 47 | eventData.putInt("selectionEnd", mSelectionEnd); 48 | return eventData; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /example/ios/example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | NSLocationWhenInUseUsageDescription 42 | 43 | NSAppTransportSecurity 44 | 45 | 46 | NSExceptionDomains 47 | 48 | localhost 49 | 50 | NSExceptionAllowsInsecureHTTPLoads 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/android/MyFragment.java: -------------------------------------------------------------------------------- 1 | package com.example.android; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.example.android.common.activities.SampleRNBaseActivity; 11 | import com.facebook.react.ReactInstanceManager; 12 | import com.facebook.react.ReactRootView; 13 | 14 | public class MyFragment extends Fragment { 15 | 16 | private static final String TAG = "MyFragment"; 17 | 18 | private ReactInstanceManager mReactInstanceManager; 19 | 20 | @Override 21 | public void onAttach(Activity activity) { 22 | super.onAttach(activity); 23 | try { 24 | mReactInstanceManager = ((SampleRNBaseActivity) activity).getReactInstanceManager(); 25 | } catch (ClassCastException e) { 26 | throw new ClassCastException(activity.toString() + " must extends SampleRNBaseActivity"); 27 | } 28 | } 29 | 30 | @Override 31 | public void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | } 34 | 35 | @Override 36 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 37 | if (mReactInstanceManager == null) { 38 | try { 39 | mReactInstanceManager = ((SampleRNBaseActivity) getActivity()).getReactInstanceManager(); 40 | } catch (ClassCastException e) { 41 | throw new ClassCastException(getActivity().toString() + " must extends SampleRNBaseActivity"); 42 | } 43 | } 44 | 45 | ReactRootView reactRootView = new ReactRootView(getContext()); 46 | reactRootView.startReactApplication(mReactInstanceManager, "example", null); 47 | return reactRootView; 48 | } 49 | 50 | @Override 51 | public void onSaveInstanceState(Bundle savedInstanceState) { 52 | super.onSaveInstanceState(savedInstanceState); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /example/ios/exampleTests/exampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #define TIMEOUT_SECONDS 600 15 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 16 | 17 | @interface exampleTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation exampleTests 22 | 23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 24 | { 25 | if (test(view)) { 26 | return YES; 27 | } 28 | for (UIView *subview in [view subviews]) { 29 | if ([self findSubviewInView:subview matching:test]) { 30 | return YES; 31 | } 32 | } 33 | return NO; 34 | } 35 | 36 | - (void)testRendersWelcomeScreen 37 | { 38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 40 | BOOL foundElement = NO; 41 | 42 | __block NSString *redboxError = nil; 43 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 44 | if (level >= RCTLogLevelError) { 45 | redboxError = message; 46 | } 47 | }); 48 | 49 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 50 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 51 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 52 | 53 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 54 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 55 | return YES; 56 | } 57 | return NO; 58 | }]; 59 | } 60 | 61 | RCTSetLogFunction(RCTDefaultLogFunction); 62 | 63 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 64 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 65 | } 66 | 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/android/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.example.android; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | import android.view.KeyEvent; 23 | 24 | import com.example.android.common.activities.SampleRNBaseActivity; 25 | 26 | /** 27 | * A simple launcher activity containing a summary sample description, sample log and a custom 28 | * {@link android.support.v4.app.Fragment} which can display a view. 29 | *

30 | * For devices with displays with a width of 720dp or greater, the sample log is always visible, 31 | * on other devices it's visibility is controlled by an item on the Action Bar. 32 | */ 33 | public class MainActivity extends SampleRNBaseActivity { 34 | 35 | public static final String TAG = "MainActivity"; 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.activity_main); 41 | 42 | if (savedInstanceState == null) { 43 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 44 | MyFragment fragment = new MyFragment(); 45 | transaction.replace(R.id.sample_content_fragment, fragment); 46 | transaction.commit(); 47 | } 48 | } 49 | 50 | @Override 51 | public boolean onKeyUp(int keyCode, KeyEvent event) { 52 | if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) { 53 | mReactInstanceManager.showDevOptionsDialog(); 54 | return true; 55 | } 56 | return super.onKeyUp(keyCode, event); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /example/ios/example/MediaProvider.swift: -------------------------------------------------------------------------------- 1 | import Aztec 2 | import Foundation 3 | 4 | class MediaProvider: Aztec.TextViewAttachmentDelegate { 5 | 6 | func textView(_ textView: TextView, attachment: NSTextAttachment, imageAt url: URL, onSuccess success: @escaping (UIImage) -> Void, onFailure failure: @escaping () -> Void) { 7 | 8 | DispatchQueue.main.async { 9 | let image = UIImage(named: "aztec")! 10 | 11 | success(image) 12 | } 13 | } 14 | 15 | func textView(_ textView: TextView, urlFor imageAttachment: ImageAttachment) -> URL? { 16 | return URL(string: "www.google.com") 17 | } 18 | 19 | func textView(_ textView: TextView, placeholderFor attachment: NSTextAttachment) -> UIImage { 20 | return UIImage(named: "aztec")! 21 | } 22 | 23 | func textView(_ textView: TextView, deletedAttachment attachment: MediaAttachment) { 24 | textView.setNeedsDisplay() 25 | } 26 | 27 | func textView(_ textView: TextView, selected attachment: NSTextAttachment, atPosition position: CGPoint) { 28 | } 29 | 30 | func textView(_ textView: TextView, deselected attachment: NSTextAttachment, atPosition position: CGPoint) { 31 | } 32 | 33 | 34 | } 35 | 36 | extension MediaProvider: Aztec.TextViewAttachmentImageProvider { 37 | func textView(_ textView: TextView, shouldRender attachment: NSTextAttachment) -> Bool { 38 | return true 39 | } 40 | 41 | func textView(_ textView: TextView, boundsFor attachment: NSTextAttachment, with lineFragment: CGRect) -> CGRect { 42 | return CGRect(x: 0, y: 0, width: 20, height: 20) 43 | } 44 | 45 | func textView(_ textView: TextView, imageFor attachment: NSTextAttachment, with size: CGSize) -> UIImage? { 46 | let image = UIImage(named: "aztec")! 47 | 48 | return imageWithImage(image: image, scaledToSize: size) 49 | } 50 | 51 | func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{ 52 | UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0); 53 | image.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: newSize.width, height: newSize.height))) 54 | let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()! 55 | UIGraphicsEndImageContext() 56 | return newImage 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-aztec 2 | ## Notice: This repo is no longer maintained. The code from this repo was moved to [the Gutenberg repository](https://github.com/WordPress/gutenberg/tree/trunk/packages/react-native-aztec) and is now maintained there. If you would like to use a Rich Text Editor in your app, please consider using [Gutenberg Mobile](https://github.com/wordpress-mobile/gutenberg-mobile). 3 | 4 | Wrapping Aztec Android and Aztec iOS in a React Native component 5 | 6 | # License 7 | 8 | This work is dual licensed under the [Mozilla Public License version 2.0 (MPL-2.0)](MPL-2.0.md) or the [GNU General Public License v2.0 or later (GPL-2.0)](GPL-2.0.md). 9 | 10 | You can choose between one of them, or both if you use this work. 11 | 12 | ## Android: Run the example app 13 | 14 | Make sure to have an emulator running or an Android device connected, and then: 15 | 16 | ``` 17 | $ cd example/ 18 | $ yarn clean:install 19 | $ yarn android 20 | ``` 21 | 22 | This will build the Android library (via `gradle`) and example app, then launch the main example activity on your connected device and run the Metro bundler at the same time. 23 | 24 | ## iOS: Run the example app 25 | 26 | Before being able to run the Example App, you'll need to install [Carthage](https://github.com/Carthage/Carthage) and the dependencies for this project: 27 | ``` 28 | cd ios 29 | carthage bootstrap --platform iOS 30 | ``` 31 | 32 | Then go back to the root directory of the project and do: 33 | ``` 34 | $ cd example/ 35 | $ yarn clean:install 36 | $ yarn ios 37 | ``` 38 | 39 | This will compile the example project, launch metro, run the simulator and run the app. 40 | 41 | ## FAQ / Troubleshooting 42 | 43 | Q: The example app doesn't run 44 | 45 | A: Make sure you have yarn and babel installed (https://yarnpkg.com/lang/en/docs/install/) 46 | 47 | 48 | Q: The example app gets compiled but ReactNative cannot connect to Metro bundler (I'm on a real device attached through USB) 49 | 50 | A: To debug on the device through USB, remember to revert ports before launching metro: 51 | `adb reverse tcp:8081 tcp:8081` 52 | 53 | 54 | Q: The example app gets compiled but ReactNative shows an error 55 | 56 | A: try running, from the root folder in the project 57 | ``` 58 | $ cd example/ 59 | $ yarn start --reset-cache 60 | ``` 61 | 62 | Open a new shell window and run either of these depending on the platform: 63 | 64 | ``` 65 | $ yarn android 66 | ``` 67 | 68 | or 69 | 70 | ``` 71 | $ yarn ios 72 | ``` 73 | 74 | -------------------------------------------------------------------------------- /ios/RNTAztecView/RCTAztecViewManager.swift: -------------------------------------------------------------------------------- 1 | import Aztec 2 | import Foundation 3 | 4 | @objc (RCTAztecViewManager) 5 | public class RCTAztecViewManager: RCTViewManager { 6 | 7 | public var attachmentDelegate: Aztec.TextViewAttachmentDelegate? 8 | public var imageProvider: Aztec.TextViewAttachmentImageProvider? 9 | 10 | public override static func requiresMainQueueSetup() -> Bool { 11 | return true 12 | } 13 | 14 | @objc 15 | func applyFormat(_ node: NSNumber, format: String) { 16 | executeBlock({ (aztecView) in 17 | aztecView.apply(format: format) 18 | }, onNode: node) 19 | } 20 | 21 | @objc 22 | func removeLink(_ node: NSNumber) { 23 | executeBlock({ (aztecView) in 24 | aztecView.removeLink() 25 | }, onNode: node) 26 | } 27 | 28 | @objc 29 | func setLink(_ node: NSNumber, url: String, title: String?) { 30 | executeBlock({ (aztecView) in 31 | aztecView.setLink(with: url, and: title) 32 | }, onNode: node) 33 | } 34 | 35 | @objc 36 | public override func view() -> UIView { 37 | let view = RCTAztecView( 38 | defaultFont: defaultFont, 39 | defaultParagraphStyle: .default, 40 | defaultMissingImage: UIImage()) 41 | 42 | view.isScrollEnabled = false 43 | 44 | view.textAttachmentDelegate = attachmentDelegate 45 | if let imageProvider = imageProvider { 46 | view.registerAttachmentImageProvider(imageProvider) 47 | } 48 | 49 | return view 50 | } 51 | 52 | func executeBlock(_ block: @escaping (RCTAztecView) -> Void, onNode node: NSNumber) { 53 | self.bridge.uiManager.addUIBlock { (manager, viewRegistry) in 54 | let view = viewRegistry?[node] 55 | guard let aztecView = view as? RCTAztecView else { 56 | return 57 | } 58 | block(aztecView) 59 | } 60 | } 61 | 62 | private var defaultFont: UIFont { 63 | if let font = UIFont(name: "NotoSerif", size: 16) { 64 | return font 65 | } 66 | 67 | let defaultFont = UIFont.systemFont(ofSize: 16) 68 | guard let url = Bundle.main.url(forResource: "NotoSerif-Regular", withExtension: "ttf") else { 69 | return defaultFont 70 | } 71 | CTFontManagerRegisterFontsForURL(url as CFURL, CTFontManagerScope.process, nil) 72 | if let font = UIFont(name: "NotoSerif", size: 16) { 73 | return font 74 | } 75 | 76 | return defaultFont 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X generated file 2 | .DS_Store 3 | 4 | # built application files 5 | *.apk 6 | *.ap_ 7 | 8 | # files for the dex VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Eclipse project files 23 | .settings/ 24 | .classpath 25 | .project 26 | 27 | # Intellij project files 28 | *.iml 29 | *.ipr 30 | *.iws 31 | .idea/ 32 | 33 | # Gradle 34 | .gradle/ 35 | gradle.properties 36 | 37 | # Generated by gradle 38 | crashlytics.properties 39 | 40 | # npm 41 | node_modules/ 42 | 43 | # yarn 44 | yarn-error.log 45 | 46 | ### 47 | ### Starting at this point, the Swift .gitignore rules from https://github.com/github/gitignore/blob/master/Swift.gitignore 48 | ### 49 | 50 | # Xcode 51 | # 52 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 53 | 54 | ## Build generated 55 | build/ 56 | DerivedData/ 57 | 58 | ## Various settings 59 | *.pbxuser 60 | !default.pbxuser 61 | *.mode1v3 62 | !default.mode1v3 63 | *.mode2v3 64 | !default.mode2v3 65 | *.perspectivev3 66 | !default.perspectivev3 67 | xcuserdata/ 68 | 69 | ## Other 70 | *.moved-aside 71 | *.xccheckout 72 | *.xcscmblueprint 73 | 74 | ## Obj-C/Swift specific 75 | *.hmap 76 | *.ipa 77 | *.dSYM.zip 78 | *.dSYM 79 | 80 | ## Playgrounds 81 | timeline.xctimeline 82 | playground.xcworkspace 83 | 84 | # Swift Package Manager 85 | # 86 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 87 | # Packages/ 88 | # Package.pins 89 | # Package.resolved 90 | .build/ 91 | 92 | # CocoaPods 93 | # 94 | # We recommend against adding the Pods directory to your .gitignore. However 95 | # you should judge for yourself, the pros and cons are mentioned at: 96 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 97 | # 98 | Pods/ 99 | 100 | # Carthage 101 | # 102 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 103 | 104 | ios/Carthage 105 | Carthage/Checkouts 106 | Carthage/Build 107 | 108 | # fastlane 109 | # 110 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 111 | # screenshots whenever they are needed. 112 | # For more information about the recommended setup visit: 113 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 114 | 115 | fastlane/report.xml 116 | fastlane/Preview.html 117 | fastlane/screenshots/**/*.png 118 | fastlane/test_output 119 | 120 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {AppRegistry, StyleSheet, TextInput, FlatList, KeyboardAvoidingView, SafeAreaView, Platform} from 'react-native'; 3 | import {example_content} from './content'; 4 | import Editor from './editor' 5 | 6 | const _minHeight = 100; 7 | 8 | const sampleContent = example_content(); 9 | 10 | const elements = [ 11 | {key: '1', text: sampleContent, height: _minHeight}, 12 | {key: '2', text: sampleContent, height: _minHeight}, 13 | {key: '3', text: sampleContent, height: _minHeight}, 14 | {key: '4', text: sampleContent, height: _minHeight}, 15 | {key: '5', text: sampleContent, height: _minHeight}, 16 | {key: '6', text: sampleContent, height: _minHeight}, 17 | ] 18 | 19 | export default class example extends React.Component { 20 | constructor(props) { 21 | super(props); 22 | this.renderItem = this.renderItem.bind(this) 23 | this.renderItemAsTextInput = this.renderItemAsTextInput.bind(this) 24 | this.state = {isShowingText: true, data: elements}; 25 | } 26 | 27 | renderItem( { item } ) { 28 | const key = item.key; 29 | return ( 30 | { 33 | let newHeight = contentSize.height; 34 | const newElements = this.state.data.map( searchItem => { 35 | if (searchItem.key == key) { 36 | return {...searchItem, height: newHeight}; 37 | } else { 38 | return searchItem; 39 | } 40 | }) 41 | this.setState( { data: newElements}) 42 | }} 43 | /> 44 | ) 45 | } 46 | 47 | renderItemAsTextInput( { item } ) { 48 | return ( 52 | ) 53 | } 54 | 55 | render() { 56 | const data = this.state.data; 57 | const mainContent = ( 58 | 59 | 63 | 64 | ); 65 | if (Platform.OS === "ios") { 66 | return ({mainContent}) 67 | } else { 68 | return mainContent 69 | } 70 | } 71 | } 72 | 73 | var styles = StyleSheet.create({ 74 | container: { 75 | flex: 1 76 | }, 77 | aztec_editor: { 78 | minHeight: _minHeight, 79 | margin: 10, 80 | }, 81 | }); 82 | 83 | AppRegistry.registerComponent('example', () => example); 84 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/android/common/activities/SampleRNBaseActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.common.activities; 18 | 19 | import android.os.Bundle; 20 | import android.support.v4.app.FragmentActivity; 21 | 22 | import org.wordpress.mobile.ReactNativeAztec.ReactAztecPackage; 23 | import org.wordpress.mobile.ReactNativeAztec.BuildConfig; 24 | import com.facebook.react.ReactInstanceManager; 25 | import com.facebook.react.common.LifecycleState; 26 | import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; 27 | import com.facebook.react.shell.MainReactPackage; 28 | 29 | /** 30 | * Base launcher activity, to handle most of the common plumbing for samples. 31 | */ 32 | public class SampleRNBaseActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler { 33 | 34 | public static final String TAG = "SampleRNBaseActivity"; 35 | protected ReactInstanceManager mReactInstanceManager; 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | mReactInstanceManager = ReactInstanceManager.builder() 41 | .setApplication(getApplication()) 42 | .setBundleAssetName("index.android.bundle") 43 | .setJSMainModulePath("index") 44 | .addPackage(new MainReactPackage()) 45 | .addPackage(new ReactAztecPackage()) 46 | .setUseDeveloperSupport(BuildConfig.DEBUG) 47 | .setInitialLifecycleState(LifecycleState.RESUMED) 48 | .build(); 49 | } 50 | 51 | public ReactInstanceManager getReactInstanceManager() { 52 | return mReactInstanceManager; 53 | } 54 | 55 | @Override 56 | protected void onPause() { 57 | super.onPause(); 58 | 59 | if (mReactInstanceManager != null) { 60 | mReactInstanceManager.onHostPause(this); 61 | } 62 | } 63 | 64 | @Override 65 | protected void onResume() { 66 | super.onResume(); 67 | 68 | if (mReactInstanceManager != null) { 69 | mReactInstanceManager.onHostResume(this, this); 70 | } 71 | } 72 | 73 | @Override 74 | protected void onDestroy() { 75 | super.onDestroy(); 76 | 77 | if (mReactInstanceManager != null) { 78 | mReactInstanceManager.onHostDestroy(this); 79 | } 80 | } 81 | 82 | @Override 83 | public void invokeDefaultOnBackPressed() { 84 | super.onBackPressed(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /example/ios/example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import UIKit 3 | 4 | @UIApplicationMain 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | 7 | var window: UIWindow? 8 | 9 | let mediaProvider = MediaProvider() 10 | 11 | lazy var bridgeDelegate: BridgeDelegate = { 12 | let sourceURL = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index", fallbackResource: nil)! 13 | return BridgeDelegate(sourceURL: sourceURL) 14 | }() 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 17 | 18 | bridgeDelegate.aztecViewManager.attachmentDelegate = mediaProvider 19 | bridgeDelegate.aztecViewManager.imageProvider = mediaProvider 20 | 21 | let bridge = RCTBridge(delegate: bridgeDelegate, launchOptions: launchOptions) 22 | let rootView = RCTRootView(bridge: bridge, moduleName: "example", initialProperties: nil) 23 | 24 | rootView?.backgroundColor = .white 25 | 26 | window = UIWindow(frame: UIScreen.main.bounds) 27 | 28 | let rootViewController = UIViewController() 29 | 30 | rootViewController.view = rootView 31 | window?.rootViewController = rootViewController 32 | window?.makeKeyAndVisible() 33 | 34 | return true 35 | } 36 | 37 | func applicationWillResignActive(_ application: UIApplication) { 38 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 39 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 40 | } 41 | 42 | func applicationDidEnterBackground(_ application: UIApplication) { 43 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 44 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 45 | } 46 | 47 | func applicationWillEnterForeground(_ application: UIApplication) { 48 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 49 | } 50 | 51 | func applicationDidBecomeActive(_ application: UIApplication) { 52 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 53 | } 54 | 55 | func applicationWillTerminate(_ application: UIApplication) { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /example/editor.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {StyleSheet, Button, View} from 'react-native'; 3 | import AztecView from 'react-native-aztec' 4 | 5 | const _minHeight = 100; 6 | 7 | export default class Editor extends Component { 8 | constructor(props) { 9 | super(props); 10 | this.onFormatPress = this.onFormatPress.bind(this) 11 | this.onActiveFormatsChange = this.onActiveFormatsChange.bind(this) 12 | this.isFormatActive = this.isFormatActive.bind(this) 13 | this.state = { activeFormats: [] }; 14 | } 15 | 16 | onFormatPress( format ) { 17 | const { _aztec } = this.refs; 18 | _aztec.applyFormat(format); 19 | } 20 | 21 | onActiveFormatsChange( formats ) { 22 | this.setState({activeFormats: formats }); 23 | } 24 | 25 | isFormatActive( format ) { 26 | const { activeFormats } = this.state; 27 | console.log(activeFormats); 28 | return activeFormats.indexOf(format) != -1; 29 | } 30 | 31 | render() { 32 | const { item, onContentSizeChange } = this.props; 33 | let myMinHeight = Math.max(_minHeight, item.height); 34 | return ( 35 | 36 | 37 |