diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..e88ed233c --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,91 @@ +{ + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": ["skype", "skype/react"], + "rules": { + "no-console": [ + "error", + { + "allow": [ + "error", + "warn", + "log" + ] + } + ], + + "camelcase": "off", + "@typescript-eslint/camelcase": [ + "error", + { + "allow": [ + "^reactxp_", + "^mixin_", + "^UNSAFE_", + "^Radio_button_" /* Android properties only */ + ] + } + ], + "@typescript-eslint/no-parameter-properties": "off" + }, + "overrides": [ + { + "files": [ + "*.tsx" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off" + } + }, + + { + "files": [ + "ReactXP.ts", + "ModuleInterface.ts" + ], + "rules": { + "no-self-assign": "off", + "prefer-const": "off", + + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/prefer-namespace-keyword": "off" + } + }, + + { + "files": [ + "Easing.ts" + ], + "rules": { + "@typescript-eslint/member-naming": [ + "error", + { + "public": "^[A-Z]\\w+$" + } + ] + } + }, + + { + "files": [ + "*.d.ts" + ], + "rules": { + "@typescript-eslint/prefer-namespace-keyword": "off", + "@typescript-eslint/no-unused-vars": "off" + } + }, + + { + "files": [ + "*/web/Animated.tsx", + "*/native-desktop/RootView.tsx" + ], + "rules": { + "@typescript-eslint/member-naming": "off" + } + } + ] +} diff --git a/.npmignore b/.npmignore index 77b203cea..174f50aae 100644 --- a/.npmignore +++ b/.npmignore @@ -6,3 +6,4 @@ /extensions /docs *.user +.eslintrc \ No newline at end of file diff --git a/.npmrc b/.npmrc index 43c97e719..e69de29bb 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +0,0 @@ -package-lock=false diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..5814d7de5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: node_js + +node_js: + - "node" + +dist: trusty + +sudo: false + +addons: + chrome: stable + +install: + - node --version + - npm --version + - npm i + +script: + - npm run lint + - npm run build + +cache: + directories: + - node_modules diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..3fe9b147a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,43 @@ +# Contributing to ReactXP + +We welcome contributions to ReactXP! This gude provides some tips for a successful contributions. + +For complex changes, we recommend filing a GitHub issue to start a discussion with project maintainers before implementing the change. + +## Pull Requests + +Please make sure the following is done when submitting a pull request: + +1. Fork the repo and create your branch from `master`. +2. If you've added code that should be tested, add test code to the RXPTest sample app. +3. If you've changed APIs, update the documentation files. +4. Ensure the test suite passes. +5. If you haven't already, complete the Contributor License Agreement ("CLA"). + +## Testing Your Change + +To test your change: +1. Rebuild reactxp: `npm i` and `npm run build` +2. Switch to the RXPTest sample directory: `cd ./samples/RXPTest` +3. Update dependencies: `npm i` +4. Copy the locally-built reactxp library: `cp -r ../../dist/* ./node_modules/reactxp/dist` +5. Rebuild the test app: `npm run web-watch` or `npm run rn-watch` +6. If testing the web version: + - for desktop: open the test in the browser: `open ./index.html` and run the test + - for mobile: run `npm run web -- -host YOUR_LOCAL_IP` then on your mobile enter `http://YOUR_LOCAL_IP:8080` +7. If testing one or more RN versions, open the corresponding native project and build and run the test + +## Contributor License Agreement ("CLA") + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +You must sign a Contribution License Agreement (CLA) before your PR will be merged. This is a one-time requirement for Microsoft projects in GitHub. You can read more about [Contribution License Agreements (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) on Wikipedia. You can sign the Microsoft Contribution License Agreement by visiting https://cla.microsoft.com/. Use your GitHub account to login. + +## Issues + +We use GitHub issues to track bugs. + +## Coding Style + +ReactXP is written in TypeScript and uses tslint to help enforce an internally-consistent coding style. Contributions should be consistent with this style. + diff --git a/README.md b/README.md index 39a94f7e9..5b6cac800 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,60 @@ # ReactXP + +[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/Microsoft/reactxp/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/reactxp.svg?style=flat-square)](https://www.npmjs.com/package/reactxp) [![Build Status](https://dev.azure.com/ms/reactxp/_apis/build/status/Microsoft.reactxp?)](https://dev.azure.com/ms/reactxp/_build/latest?definitionId=16) [![Build Status](https://img.shields.io/travis/Microsoft/reactxp/master.svg?style=flat-square)](https://travis-ci.org/Microsoft/reactxp) [![npm downloads](https://img.shields.io/npm/dm/reactxp.svg?style=flat-square)](https://www.npmjs.com/package/reactxp) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/Microsoft/reactxp#contributing) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/msreactxp/Lobby) + + ReactXP is a library for cross-platform app development using React and React Native. +## ReactXP End of Life +The ReactXP library is no longer being maintained and is is considered “end of life”. We recommend alternatives such as [React Native for Web](https://necolas.github.io/react-native-web/docs/). The ReactXP github project will be put into “archive” mode and will remain available in read-only form for the benefit of those who are still using it within older projects, but no new versions will be published. + ## Why ReactXP With React and React Native, your web app can share most of its logic with your iOS and Android apps, but the view layer needs to be implemented separately for each platform. We have taken this a step further and developed a thin cross-platform layer we call ReactXP. If you write your app to this abstraction, you can share your view definitions, styles and animations across multiple target platforms. Of course, you can still provide platform-specific UI variants, but this can be done selectively where desired. ## Getting Started The [samples](/samples) directory contains a minimal “Hello World” app that demonstrates some basic ReactXP functionality. You can use this as a starting point. Just follow the build instructions in the README file. -Nader Dabit has created a helpful [video tutorial](https://medium.com/@dabit3/reactxp-first-look-d3dd1d08febd) that walks you through the steps to build the sample app. +Also included in the samples directory is the [RXPTest app](/samples/RXPTest) which attempts to exercise all of the functionality of ReactXP. It is a good source to consult for sample usage of APIs, components, and props. You can read more about ReactXP and its APIs from the [ReactXP official Documentation](https://microsoft.github.io/reactxp/docs/getting-started.html). +Use the command-line tool called [create-rx-app](https://github.com/a-tarasyuk/create-rx-app) to create a starter project. + +```sh +npm install create-rx-app -g +create-rx-app AppName +``` + +or + +```sh +npx create-rx-app AppName +``` + +By default the project will be created in TypeScript. However if you prefer JavaScript instead, add `--javascript` when creating the project. + +This will create a directory called **AppName** inside the current working directory. Inside **AppName**, this will generate the initial project structure and install all of its dependencies. Once this installation is done, there are some commands you can run in the project directory: + +- `npm run start:web` - runs the Web version of the app in the development mode +- `npm run build:web` - builds the Web version of the app for production to the **dist-web** folder +- `npm run start:ios` - runs the iOS version of the app and attempts to open in the iOS Simulator if you're on a Mac and have it installed +- `npm run start:android` - runs the Android version of the app and attempts to open your app on a connected Android device or emulator +- `npm run start:windows` - runs the Windows version of the app +- `npm start:rn-dev-server` - runs react native (RN) development server + ### Prerequisites -* [Node.Js](https://nodejs.org/) -* [React Native](https://facebook.github.io/react-native/) +* [Node.Js](https://nodejs.org/) ([Setup Instructions](https://nodejs.org/en/download/package-manager/)) +* [React Native](https://facebook.github.io/react-native/) ([Setup Instructions](https://facebook.github.io/react-native/docs/getting-started)) -## Contributing +## ESLint rules -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +> [TSLint will be deprecated some time in 2019](https://github.com/palantir/tslint) + +If you plan to migrate your projects from TSLint to ESlint and want to continue using the [_rules_](https://github.com/microsoft/reactxp/tree/master/src/tslint) to automate search common problems in *ReactXP* usage, you can use [eslint-plugin-reactxp](https://github.com/a-tarasyuk/eslint-plugin-reactxp). + +## Contributing -You must sign a Contribution License Agreement (CLA) before your PR will be merged. This a one-time requirement for Microsoft projects in GitHub. You can read more about [Contribution License Agreements (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) on Wikipedia. You can sign the Microsoft Contribution License Agreement by visiting https://cla.microsoft.com/. Use your GitHub account to login. +We welcome contributions to ReactXP. See the [CONTRIBUTING](./CONTRIBUTING.md) file for how to help out. ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details diff --git a/README_Hindi.md b/README_Hindi.md new file mode 100644 index 000000000..2a0c73a2e --- /dev/null +++ b/README_Hindi.md @@ -0,0 +1,52 @@ +# ReactXP + +[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/Microsoft/reactxp/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/reactxp.svg?style=flat-square)](https://www.npmjs.com/package/reactxp) [![Build Status](https://img.shields.io/travis/Microsoft/reactxp/master.svg?style=flat-square)](https://travis-ci.org/Microsoft/reactxp) [![npm downloads](https://img.shields.io/npm/dm/reactxp.svg?style=flat-square)](https://www.npmjs.com/package/reactxp) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/Microsoft/reactxp#contributing) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/msreactxp/Lobby) + +ReactXP एक क्रॉस-प्लॅटफॉर्म ऍप डेवलपमेंट लाइब्रेरी है जिसमे React और React Native का उपयोग किया जाता है. + +##ReactXP क्यों ? +React और React Native के साथ आपका वेब ऍप, iOS और Android ऍप के साथ ज्यादातर तार्किक शेयर कर सकता है, लेकिन view layer आपको अलग से इम्प्लीमेंट करना होगा हर एक प्लॅटफॉर्म के लिए. हमने एक कदम आगे लेकर एक हल्का क्रॉस-प्लॅटफॉर्म लेयर विकसित किया है जिसे हम ReactXP बुलाते है. अगर आप आपके ऍप को इस abstraction के हिसाब से लिखते है फिर आप आपके view definitions, styles और animations को शेयर कर सकते है मल्टिपल टारगेट प्लेटफॉर्म्स पर. आप प्लेटफार्म स्पेसिफिक UI variants भी प्रदान कर सकते है जैसे आप चुनेंगे जब आपकी मर्ज़ी हो| + +## शुरुआत +दिए हुए [samples](/samples) directory में आपको एक आसान सा “Hello World” ऍप मिलेगा जिसमे ReactXP के बुनियादी कार्यक्षमता दिखाई गई है. आप उससे स्टार्टिंग पॉइंट की तरह प्रयोग कर सकते है. दिए हुए README के सूचनाओं का पालन कर सकते है. + +samples directory[RXPTest app](/samples/RXPTest) में RXPTest ऍप भी दिया गया है जो ReactXP के सारे कार्यक्षमताओं का उपयोग करने का प्रयास करता है. +ये एक अछि सोर्स है APIs, components और props का उपयोग जान्ने के लिए. + +आप ReactXP और उसके APIs के बारे में और पड़ सकते है इस वेबसाइट पर [ReactXP official Documentation](https://microsoft.github.io/reactxp/docs/getting-started.html). + +[create-rx-app](https://github.com/a-tarasyuk/create-rx-app) नाम के कमांड-लाइन टूल का उपयोग करके स्टार्टर प्रोजेक्ट बनाइये. + +```sh +npm install create-rx-app -g +create-rx-app AppName +``` + +अथवा + +```sh +npx create-rx-app AppName +``` +शुरुवात में प्रोजेक्ट TypeScript में उपलब्ध किया जाता hai. लेकिन अगर आपको JavaScript में करना हो तोह प्रोजेक्ट बनाते समय फिर `--javascript` का उपयोग करें. + +ये **AppName** नाम का डायरेक्टरी बनाएगा वर्किंग डायरेक्टरी में. **AppName** के अंदर शुरुवाती प्रोजेक्ट का आकार बना हुआ रहेगा और सारे dependencies इनस्टॉल किये हुए रहेंगे. इंस्टालेशन ख़तम होने के बाद निचे दिए हुए कुछ commands आप रन कर सकते है प्रोजेक्ट डायरेक्टरी में : + +- `npm run start:web` - ऍप के Web version को development mode में run करने के लिए +- `npm run build:web` - ऍप के Web version को बनता है production के लिए **dist-web** फोल्डर में +- `npm run start:ios` - ऍप के iOS version को run करके iOS Simulator में खोलके की कोशिश करता है अगर आप Mac इस्तेमाल कर रहे हो और उसमे इनस्टॉल किया हुआ हो +- `npm run start:android` - ऍप के Android version को run करके आपके ऍप को connected Android device या फिर emulator पर खोलने के कोशिश करता है +- `npm run start:windows` - ऍप के Windows version को run करता है +- `npm start:rn-dev-server` - React native (RN) development server run करता है + +### Prerequisites +* [Node.Js](https://nodejs.org/) ([Setup Instructions](https://nodejs.org/en/download/package-manager/)) +* [React Native](https://facebook.github.io/react-native/) ([Setup Instructions](https://facebook.github.io/react-native/docs/getting-started)) + +## Contributing + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +You must sign a Contribution License Agreement (CLA) before your PR will be merged. This is a one-time requirement for Microsoft projects in GitHub. You can read more about [Contribution License Agreements (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) on Wikipedia. You can sign the Microsoft Contribution License Agreement by visiting https://cla.microsoft.com/. Use your GitHub account to login. + +## License +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..e138ec5d6 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..26502cb9c --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,19 @@ +# Node.js +# Build a general Node.js project with npm. +# Add steps that analyze code, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript + +pool: + vmImage: 'Ubuntu 16.04' + +steps: +- task: NodeTool@0 + inputs: + versionSpec: '8.x' + displayName: 'Install Node.js' + +- script: | + npm ci + npm run lint + npm run build + displayName: 'npm install and build' \ No newline at end of file diff --git a/docs/_data/nav_docs.yml b/docs/_data/nav_docs.yml index f9cddcaf7..c04d59b86 100644 --- a/docs/_data/nav_docs.yml +++ b/docs/_data/nav_docs.yml @@ -86,9 +86,13 @@ title: ImageSvg - id: extensions/navigator title: Navigator + - id: extensions/netinfo + title: NetInfo - id: extensions/restclient title: REST Client - id: extensions/video title: Video - id: extensions/virtuallistview title: VirtualListView + - id: extensions/webview + title: WebView diff --git a/docs/docs/accessibility.md b/docs/docs/accessibility.md index 6ab453455..2dbc3169c 100644 --- a/docs/docs/accessibility.md +++ b/docs/docs/accessibility.md @@ -11,7 +11,7 @@ ReactXP exposes a common way to implement accessibility features across platform A screen reader is an assistive technology available for visually-impaired users. It allows users to navigate through an application by focusing actionable components and announcing the purpose of those components. -ReactXP components [View](components/view), [Button](components/button), [GestureView](components/gestureview) and [TextInput](components/textinput) implement a common set of accessibility-related props described below. +ReactXP components [View](components/view), [Button](components/button), [GestureView](components/gestureview) and [TextInput](components/textinput) implement a common set of accessibility-related props described below. Additional [Accessibility APIs](apis/accessibility) are provided for programmatically invoking the screen reader to announce events. @@ -25,7 +25,7 @@ export enum ImportantForAccessibility { Auto, // Groups all subviews under the view, allowing the screen reader to focus - // just this view; if the accessibilityLabel is specified, it is announced; + // just this view; if the accessibilityLabel is specified, it is announced; // otherwise, the labels of its children are used Yes, @@ -56,6 +56,9 @@ onAccessibilityAction?: (e: SyntheticEvent) => void; // Keyboard tab order tabIndex?: number = undefined; // web only + +// Used to define the current value for a range widget such as a slider, spinbutton or progressbar +ariaValueNow?: number = undefined; // web only ``` diff --git a/docs/docs/animations.md b/docs/docs/animations.md index 0356b7bc8..1b042904c 100644 --- a/docs/docs/animations.md +++ b/docs/docs/animations.md @@ -7,11 +7,11 @@ permalink: docs/animations.html next: accessibility --- -ReactXP supports a powerful animation abstraction. Inidividual style elements (e.g. transforms, opacity, or backgroundColor) can be animated. +ReactXP supports a powerful animation abstraction. Individual style elements (e.g. transforms, opacity, or backgroundColor) can be animated. ## Animatable Components -Three base RX classes can have animatable styles: +Four base RX classes can have animatable styles: * Animated.View @@ -21,7 +21,7 @@ Three base RX classes can have animatable styles: * Animated.TextInput -These component types should be used in place of the normal [View](components/view), [Image](components/image), [Text](components/text) or [TextInput](components/textinput) in the render method. In general, style properties expressed as numeric values or colors can be animated. Properties with text values (e.g. flexDirection or fontWeight) cannot be animated. +These component types should be used in place of the normal [View](components/view), [Image](components/image), [Text](components/text) or [TextInput](components/textinput) in the render method. In general, style properties expressed as numeric values or colors can be animated. Properties with text values (e.g. flexDirection or fontWeight) cannot be animated. ## Animated Values The following example shows how to create animated values with an initial value. Animated values are typically stored as instance variables within a component class. They can also be stored in the state structure. @@ -40,7 +40,7 @@ let interpolatedValue = RX.Animated.interpolate(animatedColorValue, ``` ## Animated Styles -Once an animated value is created, it can be associated with an animated style. +Once an animated value is created, it can be associated with an animated style. Some animated style values are more expensive than others. Some affect the layout of elements (e.g. width, height, top, left), so the layout engine needs to be invoked during each stage of the animations. It's faster to avoid these and stick to styles that don't affect the layout (e.g. opacity and transforms). @@ -83,9 +83,27 @@ let compositeAnimation = RX.Animated.parallel([ { toValue: 0.0, duration: 250, easing: RX.Animated.Easing.InOut() } ), RX.Animated.timing(animatedOpacityValue, - { toValue: 1.1, duration 250, easing: RX.Animated.Easing.Linear() } + { toValue: 1.1, duration: 250, easing: RX.Animated.Easing.Linear() } ) ]); compositeAnimation.start(); ``` + +## Directly Setting Animated Value +The value of an Animated Value can be set directly by calling the method ```setValue```. If this method is called while the value is being animated, the behavior is undefined. Setting the value of an Animated Value directly is faster than using a non-animated style attribute and re-rendering the component with a new attribute value. + +``` javascript +let animatedOpacityValue = RX.Animated.createValue(1.0); + +animatedOpacityValue.setValue(0.0); +``` + +## Web Limitations +ReactXP animation APIs on the web are implemented using DOM style transitions, as opposed to using JavaScript code to drive the animation. This results in much better performance and (in most cases) glitch-free animations, but it imposes some limitations on the use of the animation APIs. +* All active animated values associated with a particular element must share the same timing parameters (duration, easing function, delay, loop) and must be started at the same time. +* Each animated value can be associated with only one animated attribute that is actively running. +* Interpolated values used with startTransition are limited to only two values -- a begin and end value -- and must be specified in increasing order. +* Interpolated values not used with startTransition must have numeric outputValues, since we're interpolating between them ourselves. +* For interpolated values, the starting and ending values of a transition animation must correspond to the two interpolation keys. +* If an animation is stopped, the value will not reflect the intermediate position in the case of transforms and interpolated values. diff --git a/docs/docs/apis/accessibility.md b/docs/docs/apis/accessibility.md index 243ec5f29..8e207c39c 100644 --- a/docs/docs/apis/accessibility.md +++ b/docs/docs/apis/accessibility.md @@ -13,8 +13,11 @@ Sometimes it's important to announce state changes in the app (for example, an i ## Events ``` javascript -// Triggered when a new announcement is ready for the screen reader. -newAnnouncementReadyEvent: SubscribableEvent<(announcement: string) => void>; +// Triggered when the high-contrast setting changes. +highContrastChangedEvent: SubscribableEvent<(isEnabled: boolean) => void>; + +// Triggered when the screen reader setting changes. +screenReaderChangedEvent: SubscribableEvent<(isEnabled: boolean) => void>; ``` ## Methods @@ -25,6 +28,6 @@ announceForAccessibility(announcement: string): void; // Indicates whether a screen reader is currently enabled. isScreenReaderEnabled(): boolean; -// Inidicates whether the OS-level "high-contrast" setting is enabled. +// Indicates whether the OS-level "high-contrast" setting is enabled. isHighContrastEnabled(): boolean; ``` diff --git a/docs/docs/apis/alert.md b/docs/docs/apis/alert.md index 123413e8f..3fbd95a3b 100644 --- a/docs/docs/apis/alert.md +++ b/docs/docs/apis/alert.md @@ -27,25 +27,25 @@ interface AlertButtonSpec { interface AlertModalTheme { // Modal background style bodyStyle?: StyleRuleSet; - + // Style for title text titleTextStyle?: StyleRuleSet; - + // Style for message text messageTextStyle?: StyleRuleSet; - + // Style for button control buttonStyle?: StyleRuleSet; - + // Style applied when hovering over button buttonHoverStyle?: StyleRuleSet; // Style for button text buttonTextStyle?: StyleRuleSet; - + // Override style for cancel button cancelButtonStyle?: StyleRuleSet; - + // Override style for cancel button hover state cancelButtonHoverStyle?: StyleRuleSet; @@ -59,6 +59,14 @@ interface AlertOptions { // Optional theme (web only) theme?: AlertModalTheme; + + // (Android, iOS, and Windows only) + // Optional: the id of the root view this alert is associated with. + // Defaults to the view set by UserInterface.setMainView(). + rootViewId?: string; + + // Optional: Prevent the dialog from being dismissed when pressing away from the dialog + preventDismissOnPress?: boolean; } ``` diff --git a/docs/docs/apis/app.md b/docs/docs/apis/app.md index 0c6ee7ebb..cd53c0f51 100644 --- a/docs/docs/apis/app.md +++ b/docs/docs/apis/app.md @@ -13,16 +13,18 @@ This interface provides core methods associated with the application. It also ex ``` javascript // Indicates whether the app is active or inactive enum AppActivationState { - // App is active and in foreground + // App is running and in foreground Active = 1, - // App is active and in background + // App is running and in background Background = 2, - // App is inactive (not actively running) + // App is inactive + // On RN mobile platforms, it is an intermediate state between when app transitions between foreground and background. + // On desktop platforms, this is currently not being used. Inactive = 3, - // iOS specific activation state for extensions implemented + // iOS specific activation state for extensions implemented // with react-native Extension = 4 } @@ -31,17 +33,12 @@ enum AppActivationState { ## Methods ``` javascript // Initializes the app. This should be one of the first calls made. -// Specifies whether app is running in "debug" mode, typically with +// Specifies whether app is running in "debug" mode, typically with // asserts and unminified code. Also specifies whether in "development" // mode, which can indicate that additional logging or fewer security // checks are appropriate. initialize(debug: boolean, development: boolean): void; -// Indicates whether the app was initialized in debug and/or -// development mode -isDebugMode(): boolean; -isDevelopmentMode(): boolean; - // Returns the current activitation state for the app getActivationState(): AppActivationState; ``` diff --git a/docs/docs/apis/clipboard.md b/docs/docs/apis/clipboard.md index c02c3ee04..a533bb1cf 100644 --- a/docs/docs/apis/clipboard.md +++ b/docs/docs/apis/clipboard.md @@ -11,6 +11,9 @@ This interface provides access to the system's clipboard. ## Methods ``` javascript +// Retrieves the text from the clipboard (not supported on web) +getText(): SyncTasks.Promise; + // Places the specified text on the clipboard setText(text: string): void; ``` diff --git a/docs/docs/apis/input.md b/docs/docs/apis/input.md index 25391fb06..de5d329a2 100644 --- a/docs/docs/apis/input.md +++ b/docs/docs/apis/input.md @@ -16,7 +16,7 @@ This interface provides events that are triggered when specific user input event // Pass true to stop propagation. backButtonEvent: SubscribableEvent<() => boolean>(); -// Triggered when a hardware key up/down event occurs. Events are triggered +// Triggered when a hardware key up/down event occurs. Events are triggered // in the reverse order in which they were registered. Pass true to stop // propagation. keyDownEvent: SubscribableEvent<(e: Types.KeyboardEvent) => boolean>(); diff --git a/docs/docs/apis/international.md b/docs/docs/apis/international.md index d1c9864b0..7afc1abee 100644 --- a/docs/docs/apis/international.md +++ b/docs/docs/apis/international.md @@ -9,7 +9,7 @@ next: apis/linking This interface provides interfaces related to globalization (g11n) and internationalization (i18n). -Some languages read right to left. In such cases, it's preferable for the UI to be "mirrored". Buttons that are on the left side of the screen in left-to-right languages are flipped to the right side of the screen for right-to-left languages. This mirroring is mostly automatic, but some code changes may be required --- for exmaple, to flip icons or images that depend on placement. For more details about React Native's support for right-to-left languages, see this helpful [blog article](https://facebook.github.io/react-native/blog/2016/08/19/right-to-left-support-for-react-native-apps.html). +Some languages read right to left. In such cases, it's preferable for the UI to be "mirrored". Buttons that are on the left side of the screen in left-to-right languages are flipped to the right side of the screen for right-to-left languages. This mirroring is mostly automatic, but some code changes may be required --- for example, to flip icons or images that depend on placement. For more details about React Native's support for right-to-left languages, see this helpful [blog article](https://facebook.github.io/react-native/blog/2016/08/19/right-to-left-support-for-react-native-apps.html). ## Methods ``` javascript diff --git a/docs/docs/apis/linking.md b/docs/docs/apis/linking.md index f82948d57..879f48a11 100644 --- a/docs/docs/apis/linking.md +++ b/docs/docs/apis/linking.md @@ -43,7 +43,7 @@ enum LinkingErrorCode { ## Methods ``` javascript -// Returns the URL that was used to launch tha application +// Returns the URL that was used to launch the application getInitialUrl(): SyncTasks.Promise; // Requests the URL to be opened by the default app for that protocol diff --git a/docs/docs/apis/location.md b/docs/docs/apis/location.md index df5d6312f..3c8852962 100644 --- a/docs/docs/apis/location.md +++ b/docs/docs/apis/location.md @@ -14,7 +14,7 @@ This interface provides access to geolocation data. enum LocationErrorType { // User has not granted the app access to location data PermissionDenied, - + // Geolocation information is not currently available PositionUnavailable, @@ -51,7 +51,7 @@ isAvailable(): boolean; getCurrentPosition(options?: PositionOptions): SyncTasks.Promise; // Requests a callback when the position changes; useful for geofencing -watchPosition(successCallback: LocationSuccessCallback, +watchPosition(successCallback: LocationSuccessCallback, errorCallback?: LocationFailureCallback, options?: PositionOptions): SyncTasks.Promise; diff --git a/docs/docs/apis/modal.md b/docs/docs/apis/modal.md index d53f9fe0d..6ba9cba3f 100644 --- a/docs/docs/apis/modal.md +++ b/docs/docs/apis/modal.md @@ -20,7 +20,7 @@ A modal covers the entire screen but is transparent. Its children define the vis ## Types ``` javascript interface ModalOptions { - // Android & iOS only. + // Android, iOS, and Windows only. // The id of the root view this modal is associated with. // Defaults to the view set by UserInterface.setMainView(); rootViewId?: string; @@ -36,8 +36,8 @@ dismiss(modalId: string); // Removes all modals from the modal stack. dismissAll(); -// Indicates whether the specified modal is in the modal stack. -isDisplayed(modalId: string): boolean; +// Indicates whether the specified modal is in the modal stack. If no id provided indicates if some modal is displayed. +isDisplayed(modalId?: string): boolean; // Pushes the modal onto the modal stack. show(modal: React.ReactElement, modalId: string, options?: ModalOptions); diff --git a/docs/docs/apis/network.md b/docs/docs/apis/network.md index c765cabd1..6d913bf02 100644 --- a/docs/docs/apis/network.md +++ b/docs/docs/apis/network.md @@ -7,32 +7,4 @@ permalink: docs/apis/network.html next: apis/platform --- -This interface provides information about network connectivity. - -## Types -``` javascript -enum DeviceNetworkType { - Unknown, - None, - Wifi, - Mobile2G, - Mobile3G, - Mobile4G -} -``` - -## Methods -``` javascript -// Returns a promise that specifies whether the device currently -// has network connectivity -isConnected(): SyncTasks.Promise; - -// Returns the type of network -getType(): SyncTasks.Promise; -``` - -## Events -``` javascript -// Triggered when the connectivity changes -connectivityChangedEvent: SubscribableEvent<(isConnected: boolean) => void>; -``` +This has been deprecated from ReactXP Core and moved to an extension (reactxp-netinfo) inline with the React Native Lean Core initiative. \ No newline at end of file diff --git a/docs/docs/apis/platform.md b/docs/docs/apis/platform.md index 021bb1c65..1bc58ea43 100644 --- a/docs/docs/apis/platform.md +++ b/docs/docs/apis/platform.md @@ -18,5 +18,8 @@ type PlatformType = 'web' | 'ios' | 'android' | 'windows'; ``` javascript // Returns the platform type getType(): Types.PlatformType; + +// Returns the value in `specifics` for the current platform type. +select(specifics: { [ platform in Types.PlatformType | 'default' ]?: T }): T | undefined; ``` diff --git a/docs/docs/apis/popup.md b/docs/docs/apis/popup.md index 6e4dc551e..68f749e39 100644 --- a/docs/docs/apis/popup.md +++ b/docs/docs/apis/popup.md @@ -11,22 +11,31 @@ A popup is not technically a component. Rather, it's a collection of methods on When a popup is displayed, the caller specifies a PopupOptions structure that includes several callbacks, including a renderPopup method. -Popups by default will not act like a toggle. When Popup.show is called, it will always show the Popup. If a Popup is required to act like a toggle, PopupOptions.dismissIfShown should be set to true. In this case, if Popup.show is called once for a component, it will show the popup. A subsequent call from the same component will dismiss the popup and so on. +Popups by default will not act like a toggle. When Popup.show is called, it will always show the Popup. If a Popup is required to act like a toggle, PopupOptions.dismissIfShown should be set to true. In this case, if Popup.show is called once for a component, it will show the popup. A subsequent call from the same component will dismiss the popup and so on. -The overall dimensions of a popup are assumed to remain constant for the lifetime of the popup. This allows the dimensions to be measured once, and the popup can then be positioned relative to the anchor. +The overall dimensions of a popup are assumed to remain constant for the lifetime of the popup. This allows the dimensions to be measured once, and the popup can then be positioned relative to the anchor. Popups are identified by a caller-specified ID that should be unique. ## Types ``` javascript -type PopupPosition = 'top' | 'right' | 'bottom' | 'left'; +// 'context' mode makes it attempt to behave like a context menu -- defaulting +// to the lower right of the anchor element and working its way around. It is not supported +// with inner positioning and will throw an exception if used there. +type PopupPosition = 'top' | 'right' | 'bottom' | 'left' | 'context'; interface PopupOptions { // Returns a mounted component instance that serves as the // "anchor" for the popup. Often a button. getAnchor: () => React.Component; - // Renders the contents of the popup. + // Renders the contents of the popup. This is called twice. The + // first time it is called, the parameters are all defaults + // (default position and 0 offset and dimensions). This allows + // the popup to be measured and positioned. It is called a second + // time with the position, offset and dimensions specified. This + // allows the method to modify the appearance based on these + // parameters. The dimensions should not be modified, however. renderPopup: (anchorPosition: PopupPosition, anchorOffset: number, popupWidth: number, popupHeight: number) => ReactNode; @@ -41,7 +50,8 @@ interface PopupOptions { // with button and chevron icon. getElementTriggeringPopup?: () => React.Component; - // Called when the popup is dismissed. + // Called when the popup is dismissed. Popup.isDisplayed() will return + // false for the popup being dismissed when this callback runs. onDismiss?: () => void; // Prioritized order of positions. Popup is positioned @@ -56,13 +66,13 @@ interface PopupOptions { // On pressed handler to notify whoever wanted to create the popup // that its anchor has been pressed. // IMPORTANT NOTE: This handler may be called when the component is - // already unmounted as it uses a time delay accommodate + // already unmounted as it uses a time delay accommodate // fade-out animations. onAnchorPressed?: (e: SyntheticEvent) => void; - // Determines if the anchor invoking the popup should behave like a toggle. + // Determines if the anchor invoking the popup should behave like a toggle. // If true, calling Popup.show will show the popup. A subsequent call - // will hide the popup. If false or undefined (default), calling Popup.show + // will hide the popup. If false or undefined (default), calling Popup.show // will always show the popup. dismissIfShown?: boolean; @@ -71,7 +81,13 @@ interface PopupOptions { // default behavior, in which case the popup must be dismissed explicitly. preventDismissOnPress?: boolean; - // Android & iOS only. + // The popup may be left in the DOM after it's dismissed. This is a + // performance optimization to make the popup appear faster when it's shown + // again, intended for popups that tend to be shown repeatedly. Note that + // this is only a hint, so callers shouldn't rely on caching behavior. + cacheable?: boolean; + + // Android, iOS, and Windows only. // The id of the root view this popup is associated with. // Defaults to the view set by UserInterface.setMainView(); rootViewId?: string; @@ -94,6 +110,9 @@ dismissAll(): void; // Displays a popup. Returns true if successful, false if the popup is // already displayed show(options: PopupOptions, popupId: string, showDelay: number = 0): boolean; + +// Indicates whether the specified popup is displayed. If no id provided indicates if some popup is displayed. +isDisplayed(popupId?: string): boolean; ``` ## Sample Usage @@ -115,7 +134,7 @@ onHoverEnd() { displayPopup() { let popupOptions: RX.Types.PopupOptions = { getAnchor: () => { - return this.refs['myButton']; + return this._mountedButton; }, renderPopup: (anchorPosition: Types.PopupPosition, anchorOffset: number, popupWidth: number, popupHeight: number) => { diff --git a/docs/docs/apis/statusbar.md b/docs/docs/apis/statusbar.md index 01ccc8363..103b89b9e 100644 --- a/docs/docs/apis/statusbar.md +++ b/docs/docs/apis/statusbar.md @@ -27,6 +27,6 @@ setNetworkActivityIndicatorVisible(value: boolean): void; // Specifies the background color of the status bar (applies on Android only) setBackgroundColor(color: string, animated: boolean): void; -// Specifies whether the status bar is transluscent or transparent +// Specifies whether the status bar is translucent or transparent setTranslucent(translucent: boolean): void; ``` diff --git a/docs/docs/apis/storage.md b/docs/docs/apis/storage.md index 717d59678..0e99c9227 100644 --- a/docs/docs/apis/storage.md +++ b/docs/docs/apis/storage.md @@ -7,7 +7,7 @@ permalink: docs/apis/storage.html next: apis/userinterface --- -This interface provides a simple key-based local storage mechanism. +This interface provides a simple key-based local storage mechanism. If you need more powerful options to persist data and work with them, consider using ReactXP's [Database Extension](/reactxp/docs/extensions/database). ## Methods ``` javascript diff --git a/docs/docs/apis/userinterface.md b/docs/docs/apis/userinterface.md index ecd56b6e9..9ff4671d9 100644 --- a/docs/docs/apis/userinterface.md +++ b/docs/docs/apis/userinterface.md @@ -27,8 +27,9 @@ setMainView(element: React.ReactElement): void; // Android & iOS only. // Wrapper around RN.AppRegistry.registerComponent(); -// IMPORTANT: Some APIs, e.g. Popup & Modal, require a string `reactxp_rootViewId` -// prop to be set on the component from the native-side. +// IMPORTANT: Some APIs, e.g. Popup & Modal, require a string +// `reactxp_rootViewId` prop to be set on the component from the +// native-side. registerRootView(viewKey: string, getComponentFunc: Function); // Specifies whether custom scrollbars should be enabled (applies @@ -45,38 +46,28 @@ measureLayoutRelativeToWindow(component: React.Component): measureLayoutRelativeToAncestor(component: React.Component, ancestor: React.Component): SyncTasks.Promise; -// Measures the dimension of the full window (or screen, in the case -// of mobile devices); the dimensions can also be obtained for any +// Measures the dimension of window (based on specified root view id or +// defaults to main window or screen, in the case +// of non-windowed platforms); the dimensions can also be obtained for any // view (including your app's top-level view) using the onLayout // callback -measureWindow(): Types.Dimensions; +measureWindow(rootViewId?: string): Types.Dimensions; // Indicates the "size multiplier" for text increase or decrease, which // can be adjusted by users on some platforms; defaults to 1.0 getContentSizeMultiplier(): SyncTasks.Promise; -// Indicates the default maximum "size multiplier" for text increase. -// Defaults to 0 which indicates there is no max. -// Note: Older versions of React Native don’t support this interface. -getMaxContentSizeMultiplier(): SyncTasks.Promise; - -// Sets the default maximum "size multiplier" for text increase. -// Values must be 0 or >=1. The default is 0 which indicates that -// there is no max. -// Note: Older versions of React Native don’t support this interface. -setMaxContentSizeMultiplier(maxContentSizeMultiplier: number): void; - -// Dismisses the on-screen keyboard (applies to mobile only) +// Dismisses the on-screen keyboard (on applicable platforms) dismissKeyboard(): void; // Enables native -> script touch event latency diagnostic events. // When latency greater than latencyThresholdMs is observed, the -// touchLatencyEvent will fire. (applies to mobile only) +// touchLatencyEvent will fire (on applicable platforms). enableTouchLatencyEvents(latencyThresholdMs: number): void; // Returns true if the application is in the keyboard navigation state, // when the user is using Tab key to navigate through the focusable -// elements. (applies to web only) +// elements (on applicable platforms). isNavigatingWithKeyboard(): boolean; ``` @@ -89,12 +80,12 @@ contentSizeMultiplierChangedEvent: SubscribableEvent< // Triggered when enableTouchLatencyEvents has been called and // native -> script touch latency exceeding the threshold has -// been observed. (applies to mobile only) +// been observed (on applicable platforms). touchLatencyEvent: SubscribableEvent< (observedLatencyMs: number) => void>(); -// Triggered when the keyboard navigation state is changed. -// (applies to web only) +// Triggered when the keyboard navigation state is changed +// (on applicable platforms). keyboardNavigationEvent: SubscribableEvent< (isNavigatingWithKeyboard: boolean) => void>(); ``` diff --git a/docs/docs/apis/userpresence.md b/docs/docs/apis/userpresence.md index c7ea25877..b2d5e7b2c 100644 --- a/docs/docs/apis/userpresence.md +++ b/docs/docs/apis/userpresence.md @@ -12,6 +12,7 @@ This interface provides information about whether the user is currently present. # Methods ``` javascript // Indicates whether the user is currently present +// On web platforms, it indicates whether the user has focused on the app and interacted with the app in the last 60 seconds isUserPresent(): boolean; ``` diff --git a/docs/docs/components/activityindicator.md b/docs/docs/components/activityindicator.md index fae7cf383..15314ae7d 100644 --- a/docs/docs/components/activityindicator.md +++ b/docs/docs/components/activityindicator.md @@ -19,6 +19,9 @@ deferTime: number = 0; // Size of indicator (exact sizes are platform-specific) size: 'large' | 'medium' | 'small' | 'tiny'; + +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; ``` ## Styles diff --git a/docs/docs/components/button.md b/docs/docs/components/button.md index 2359743a9..74e68ef54 100644 --- a/docs/docs/components/button.md +++ b/docs/docs/components/button.md @@ -9,34 +9,35 @@ next: components/gestureview Like View, this component is a generic container for other components. However, it adds some additional capabilities -- support for presses or clicks and hovering. -This component supports only one child. If you require multiple child components, wrap them in a View. - ## Props In addition to the [common accessibility props](/reactxp/docs/accessibility.html), the following props are supported. ``` javascript -// Alternate text to display if the image cannot be loaded -// or by screen readers +// Text to be used by screen readers accessibilityLabel: boolean = false; -// Hide the component from screen readers? -accessibilityHidden: boolean = false; - // Traits used to hint screen readers, etc. accessibilityTraits: AccessibilityTrait | AccessibilityTrait[] = undefined; -// Region for accessibility mechanisms -accessibilityLiveRegion: AccessibilityLiveRegion = - undefined; // Android and web only +// It is hard or impossible to tell by a reference to an instance of a component +// from where this component has been instantiated. You can assign this property +// and check instance.props.accessibilityId. For example accessibilityId is used +// in View's FocusArbitrator callback. +accessibilityId: string = undefined; + +// Opacity value the button should animate to on button touch +activeOpacity: number = undefined; // iOS and Android only -// Id of an expandable element revealed by the button. Describes a relation between button and element to screen reader. +// Id of an expandable element revealed by the button. Describes a relation +// between button and element to screen reader. ariaControls: string = undefined; // Web only // Specifies a unique id for an HTML element +// NOTE: This property may be going away in future versions. id: string = undefined; // Web only // Expose the element and/or its children as accessible to Screen readers -importantForAccessibility?: ImportantForAccessibility = ImportantForAccessibility.yes; +importantForAccessibility?: ImportantForAccessibility = ImportantForAccessibility.Yes; // Delay in ms before onLongPress is called delayLongPress: number = 1000; @@ -44,17 +45,39 @@ delayLongPress: number = 1000; // If disabled, touch and mouse input events are ignored disabled: boolean = false; +// By default, opacity of a disabled element is 0.5. This value can be +// overriden with this property +disabledOpacity: number = undefined; + +// Disable default opacity animation on touch of buttons +disableTouchOpacityAnimation: boolean = false; // iOS and Android only + +// Should be focused when the component is mounted, see also View's arbitrateFocus +// property. +// WARNING: autoFocus=true means that this Button's requestFocus() method will be +// called, however calling requestFocus() might have no effect (for example the +// button is disabled), the application has to handle this either while setting +// this property or in the View's FocusArbitrator callback. +autoFocus: boolean = false; + // Called when VoiceOver is on and the user double tapped to // activate a control onAccessibilityTapIOS: (e: SyntheticEvent) => void; // iOS Only -// Called when the user has pressed and held for a specified duration -onLongPress: (e: SyntheticEvent) => void; +// Focus Events +onFocus: (e: FocusEvent) => void = undefined; +onBlur: (e: FocusEvent) => void = undefined; // Called when the mouse cursor enters or leaves the view bounds onHoverStart: (e: SyntheticEvent) => void; onHoverEnd: (e: SyntheticEvent) => void; +// Keyboard Events +onKeyPress: (e: KeyboardEvent) => void = undefined; + +// Called when the user has pressed and held for a specified duration +onLongPress: (e: SyntheticEvent) => void; + // Called when the touch or mouse button is released within the // bounds of the view and the press has not been canceled onPress: (e: SyntheticEvent) => void; @@ -75,16 +98,12 @@ style: ButtonStyleRuleSet | ButtonStyleRuleSet[] = []; // Keyboard tab order tabIndex: number = undefined; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; + // Text for a tooltip title: string = undefined; -// Visual touchfeedback properties -// Disable default opacity animation on touch of buttons -disableTouchOpacityAnimation: boolean = false; // iOS and Android only - -// Opacity value the button should animate to on button touch -activeOpacity: number = undefined; // iOS and Android only - // Background color that will be visible on button touch underlayColor: string = undefined; // iOS and Android only ``` @@ -101,5 +120,20 @@ underlayColor: string = undefined; // iOS and Android only ``` javascript // Sets the accessibility focus to the component. focus(): void; + +// The preferable way to focus the component. When requestFocus() is called, +// the actual focus() will be deferred, and if requestFocus() has been +// called for several components, only one of those components will actually +// get a focus() call. By default, last component for which requestFocus() is +// called will get a focus() call, but you can specify arbitrateFocus property +// of a parent View and provide the callback to decide which one of that View's +// descendants should be focused. This is useful for the accessibility: when +// consecutive focus() calls happen one after another, the next one interrupts +// the screen reader announcement for the previous one and the user gets +// confused. autoFocus property of focusable components also uses requestFocus(). +requestFocus(): void; + +// Blurs the component. +blur(): void; ``` diff --git a/docs/docs/components/gestureview.md b/docs/docs/components/gestureview.md index d42e979f5..c128dd995 100644 --- a/docs/docs/components/gestureview.md +++ b/docs/docs/components/gestureview.md @@ -7,12 +7,22 @@ permalink: docs/components/gestureview.html next: components/image --- -This component provides support for common touch gestures -- tapping, double-tapping, panning, and pinching. It also handles common mouse-based gestures including double clicking and scroll wheel input. +This component provides support for common touch gestures -- tapping, double-tapping, long-pressing, panning, and pinching. It also handles common mouse-based gestures including double clicking and scroll wheel input. Information about pending gestures is returned through event handlers. A caller can specify which gestures they are interested in by specifying those event handlers. For example, if you are interested in double taps and horizontal pans, provide an onDoubleTap and onPanHorizontal handler. ## Props ``` javascript +// Alternate text for screen readers. +accessibilityLabel: string = undefined; + +// Traits used to hint screen readers, etc. +accessibilityTraits: AccessibilityTrait | AccessibilityTrait[] = undefined; + +// Expose the element and/or its children as accessible to Screen readers +importantForAccessibility?: ImportantForAccessibility = + ImportantForAccessibility.Yes; + // Gestures and attributes that apply only to touch inputs onPinchZoom: (gestureState: MultiTouchGestureState) => void = undefined; onRotate: (gestureState: MultiTouchGestureState) => void = undefined; @@ -27,6 +37,15 @@ onPanVertical: (gestureState: PanGestureState) => void = undefined; onPanHorizontal: (gestureState: PanGestureState) => void = undefined; onTap: (gestureState: TapGestureState) => void = undefined; onDoubleTap: (gestureState: TapGestureState) => void = undefined; +onContextMenu: (gestureState: TapGestureState) => void = undefined; +onLongPress: (gestureState: TapGestureState) => void = undefined; + +// Focus Events +onFocus: (e: FocusEvent) => void = undefined; +onBlur: (e: FocusEvent) => void = undefined; + +// Keyboard Events +onKeyPress: (e: KeyboardEvent) => void = undefined; // We can set vertical or horizontal as preferred preferredPan: PreferredPanGesture = undefined; // Horizontal or vertical @@ -39,14 +58,8 @@ panPixelThreshold: number = undefined; // release the responder? Setting true allows release. releaseOnRequest: boolean = false; -// Alternate text for screen readers. -accessibilityLabel: string = undefined; - -// Traits used to hint screen readers, etc. -accessibilityTraits: AccessibilityTrait | AccessibilityTrait[] = undefined; - -// Expose the element and/or its children as accessible to Screen readers -importantForAccessibility?: ImportantForAccessibility = ImportantForAccessibility.Yes; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; ``` ## Styles diff --git a/docs/docs/components/image.md b/docs/docs/components/image.md index c5c0bb201..529fd3ee8 100644 --- a/docs/docs/components/image.md +++ b/docs/docs/components/image.md @@ -11,6 +11,8 @@ This component displays an image, which can come from a local source or from the If child elements are specified, the image acts as a background, and the children are rendered on top of it. +If headers contains 'Cache-Control: max-stale' with no value specified and the image fails to load, the component tries again passing cache: 'only-if-cached' to the underlying native Image (iOS only). This way the app can render otherwise inaccessible stale cached images. + ## Props ``` javascript // Alternate text to display if the image cannot be loaded @@ -21,20 +23,19 @@ accessibilityLabel: string = undefined; headers: { [headerName: string]: string } = undefined; // Called when an error occurs that prevents the image from loading -onError: (e: SyntheticEvent) => void; +onError: (err?: Error) => void; // Called when the image successfully loads -onLoad: (e: SyntheticEvent) => void; +onLoad: (size: Dimensions) => void; // Android-specific resize property resizeMethod: 'auto' | 'resize' | 'scale' = 'auto'; // Android only // Determines how to resize the image if its natural size // does not match the size of the container -resizeMode: 'stretch' | 'contain' | 'cover' | 'auto' | 'repeat' = 'stretch'; - -// Rasterize contents using offscreen bitmap (perf optimization) -shouldRasterizeIOS: boolean = false; // iOS only +// Note: In Web version, 'auto' doesn't scale down image +// if width/height smaller than the original image size +resizeMode: 'stretch' | 'contain' | 'cover' | 'auto' | 'repeat' = 'contain'; // URL to image source: string = undefined; @@ -42,6 +43,9 @@ source: string = undefined; // See below for supported styles style: ImageStyleRuleSet | ImageStyleRuleSet[] = []; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; + // Tooltip for image title: string = undefined; ``` @@ -61,4 +65,18 @@ getNativeHeight(): number; getNativeWidth(): number; ``` - +## Static Methods +```javascript +// Prefetches a remote image and stores it in a cache. This can decrease the +// amount of time it takes when you later want to show the image because the +// image only has to be fetched from the local cache rather than over the +// network. +prefetch(url: string): Promise; + +// Similarly to [prefetch], this method loads a remote image and stores it in +// a cache. If prefetching was successful it will also get image dimensions. It will be +// useful if you need [getNativeHeight] or [getNativeWidth] after image +// was loaded because you will get this info together with prefetching and before +// you actually need to show the image. +getMetadata(url: string): Promise +``` diff --git a/docs/docs/components/link.md b/docs/docs/components/link.md index 3f7d6c470..5976a806c 100644 --- a/docs/docs/components/link.md +++ b/docs/docs/components/link.md @@ -11,16 +11,18 @@ This component displays a hyperlink. On the web, it translates to an <a> t ## Props ``` javascript +// It is hard or impossible to tell by a reference to an instance of a component +// from where this component has been instantiated. You can assign this property +// and check instance.props.accessibilityId. For example accessibilityId is used +// in View's FocusArbitrator callback. +accessibilityId: string = undefined; + // Should fonts be scaled according to system setting? allowFontScaling: boolean = true; // Android and iOS only -// Should the scale multiplier be capped when allowFontScaling is set to true? -// Possible values include the following: -// null/undefined (default) - inheret from parent/global default -// 0 - no max -// >= 1 - sets the maxContentSizeMultiplier of this node to this value -// Note: Older versions of React Native don’t support this interface. -maxContentSizeMultiplier: number = null; // Android and iOS only +// Should be focused when the component is mounted, see also View's arbitrateFocus +// property. +autoFocus: boolean = false; // For non-zero values, truncates with ellipsis if necessary numberOfLines: number = 0; @@ -29,29 +31,38 @@ numberOfLines: number = 0; onHoverStart: (e: SyntheticEvent) => void = undefined; onHoverEnd: (e: SyntheticEvent) => void = undefined; -// Event called when the touch or mouse button is released +// Event called when the touch or mouse button is released // within the bounds of the view and the press has not been canceled onPress: (e: SyntheticEvent, url: string) => void = undefined; -// Event called when a long touch or mouse (> 1000ms) button is released +// Event called when a long touch or mouse (> 1000ms) button is released // within the bounds of the view and the press has not been canceled onLongPress: (e: SyntheticEvent, url:string) => void = undefined; +// Event called when context menu is triggered, either by +// right mouse button click or context menu key +onContextMenu: (e: MouseEvent) => void = undefined; + // Can the link be included in a text selection? selectable: boolean = false; +// See below for supported styles +style: LinkStyleRuleSet | LinkStyleRuleSet[] = []; + +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; + // Text for a tooltip title: string = undefined; // URL to follow for hyperlink url: string; - -// See below for supported styles -style: LinkStyleRuleSet | LinkStyleRuleSet[] = []; ``` ## Styles +[**Text Styles**](/reactxp/docs/styles.html#text-style-attributes) + [**Flexbox Styles**](/reactxp/docs/styles.html#flexbox-style-attributes) [**View Styles**](/reactxp/docs/styles.html#view-style-attributes) @@ -59,5 +70,22 @@ style: LinkStyleRuleSet | LinkStyleRuleSet[] = []; [**Transform Styles**](/reactxp/docs/styles.html#transform-style-attributes) ## Methods -No methods - +``` javascript +// Sets the focus to the component. +focus(): void; + +// The preferable way to focus the component. When requestFocus() is called, +// the actual focus() will be deferred, and if requestFocus() has been +// called for several components, only one of those components will actually +// get a focus() call. By default, last component for which requestFocus() is +// called will get a focus() call, but you can specify arbitrateFocus property +// of a parent View and provide the callback to decide which one of that View's +// descendants should be focused. This is useful for the accessibility: when +// consecutive focus() calls happen one after another, the next one interrupts +// the screen reader announcement for the previous one and the user gets +// confused. autoFocus property of focusable components also uses requestFocus(). +requestFocus(): void; + +// Blurs the component. +blur(): void; +``` diff --git a/docs/docs/components/picker.md b/docs/docs/components/picker.md index 6f6dd17c4..0ac2c696c 100644 --- a/docs/docs/components/picker.md +++ b/docs/docs/components/picker.md @@ -22,18 +22,21 @@ interface PickerPropsItem { // List of items to be displayed in the picker items: PickerPropsItem[] = []; -// Initially-selected item -selectedValue: string; +// 'dialog': Show a modal dialog +// 'dropdown': Shows a dropdown anchored to the picker view +mode: 'dialog' | 'dropdown' = 'dialog'; // Android only // Invoked when the selected value changes onValueChange: (itemValue: string, itemPosition: number) => void; +// Initially-selected item +selectedValue: string; + +// See below for supported styles style: PickerStyleRuleSet | PickerStyleRuleSet[] = []; -// Android only. -// 'dialog': Show a modal dialog. This is the default. -// 'dropdown': Shows a dropdown anchored to the picker view -mode: 'dialog' | 'dropdown'; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; ``` ## Styles @@ -83,14 +86,16 @@ class MyComponent extends RX.Component { render(): JSX.Element { return ( - - { 'How are you feeling? ' } + + + { 'How are you feeling?' } + - + ); } diff --git a/docs/docs/components/scrollview.md b/docs/docs/components/scrollview.md index 3c21a9f82..07c2011d1 100644 --- a/docs/docs/components/scrollview.md +++ b/docs/docs/components/scrollview.md @@ -7,7 +7,7 @@ permalink: docs/components/scrollview.html next: components/text --- -Like a View, this component is a container for other components. However, it supports scrolling (panning) and zooming so it is possible to view larger contents. +Like a View, this component is a container for other components. However, it supports scrolling (panning) and zooming so it is possible to view larger contents. ScrollViews must have a bounded height (or width, if it scrolls horizontally) since its children are of unbounded height (or width). To bound the dimensions of a ScrollView, either set the height/width directly or make sure that its parent's height/width is bounded. @@ -16,30 +16,26 @@ ScrollViews must have a bounded height (or width, if it scrolls horizontally) si // Should scroll bar bounce when user hits the bounds? bounces: boolean = true; // iOS only -// Does it support scrolling in the horizontal and/or vertical directions? +// Controls the scroll direction. When false or undefined, only vertical scroll is enabled, when true, only horizontal scroll is enabled horizontal: boolean = false; -vertical: boolean = true; - -// If the contents are smaller than the view port, should they be justified -// to the top of the view (i.e. flex-start) or the end (flex-end)? -justifyEnd: boolean = false; // When the user scrolls the view, how should the on-screen keyboard react? keyboardDismissMode: 'none' | 'interactive' | 'on-drag'; // Native only // Should the on-screen keyboard remain visible when the user taps // the scroll view? -keyboardShouldPersistTaps: boolean = false; // Native only - -// Maximum scale factor -maximumZoomScale: number = 1.0; - -// Minimum scale factor -minimumZoomScale: number = 1.0; +keyboardShouldPersistTaps: boolean | 'always' | 'never' | 'handled' = 'never'; // Native only // Invoked when the contents of the scroll view change onContentSizeChange: (width: number, height: number) => void = undefined; +// Focus Events +onFocus: (e: FocusEvent) => void = undefined; +onBlur: (e: FocusEvent) => void = undefined; + +// Keyboard Events +onKeyPress: (e: KeyboardEvent) => void = undefined; + // Invoked when view dimensions or position changes onLayout: (e: ViewOnLayoutEvent) => void = undefined; @@ -50,19 +46,31 @@ onScroll: (newScrollTop: number, newScrollLeft: number) => void = undefined; onScrollBeginDrag: () => void = undefined; onScrollEndDrag: () => void = undefined; +// Animation helpers to allow usage of the RN.Animated.Event system through ReactXP. +// AnimatedValue objects hooked up to either (or both) of these properties will be automatically +// hooked into the onScroll handler of the scrollview and .setValue() will be called on them +// with the updated values. On supported platforms, it will use RN.Animated.event() to do +// a native-side/-backed coupled animation. +scrollXAnimatedValue?: RX.Types.AnimatedValue; +scrollYAnimatedValue?: RX.Types.AnimatedValue; + // Android only property to control overScroll mode -overScrollMode?: 'always' | 'always-if-content-scrolls' | 'never'; +overScrollMode?: 'auto' | 'always' | 'never'; // Snap to page boundaries? -pagingEnabled: boolean = false; // iOS only +pagingEnabled: boolean = false; // Android & iOS only snapToInterval: number = undefined; // iOS only // Is scrolling enabled? scrollEnabled: boolean = true; -// how often (in milliseconds) between scroll events? +// Minimum duration (in milliseconds) between scroll events scrollEventThrottle: number = undefined; +// Inset (in pixels) of scroll indicator from top/bottom (vertical) +// or left/right (horizontal) +scrollIndicatorInsets: ScrollIndicatorInsets = undefined; + // If true, this scroll bar scrolls to the top when the user // taps on the status bar. scrollsToTop: boolean = false; // iOS only @@ -73,6 +81,12 @@ showsVerticalScrollIndicator: boolean = [same as horizontal]; // See below for supported styles style: ViewStyleRuleSet | ViewStyleRuleSet[] = []; + +// Windows-only property to control tab navigation inside the view +tabNavigation?: 'local' | 'cycle' | 'once'; + +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; ``` ## Styles @@ -92,12 +106,6 @@ focus(): void; // position. setScrollLeft(scrollLeft: number, animate: boolean): void; setScrollTop(scrollTop: number, animate: boolean): void; - -// Adds a value to the current top or left position (measured in pixels) of the -// viewport within the scroll view. Optionally animates from the current -// position. -addToScrollLeft(deltaLeft: number, animate: boolean): void; -addToScrollTop(deltaTop: number, animate: boolean): void; ``` diff --git a/docs/docs/components/text.md b/docs/docs/components/text.md index a8bef4d71..ba68aef90 100644 --- a/docs/docs/components/text.md +++ b/docs/docs/components/text.md @@ -16,49 +16,62 @@ Another difference between Text and other components is that Text children are n ## Props ``` javascript -// Alternate text to display if the image cannot be loaded -// or by screen readers -accessibilityLabel: string = undefined; - -// Hide the component from screen readers? -accessibilityHidden: boolean = false; - -// Traits used to hint screen readers, etc. -accessibilityTraits: AccessibilityTrait | AccessibilityTrait[] = undefined; - -// Region for accessibility mechanisms -accessibilityLiveRegion: AccessibilityLiveRegion = - undefined; // Android and web only - // Should fonts be scaled according to system setting? allowFontScaling: boolean = true; // Android and iOS only -// Specifies a unique id for an HTML element +// When numberOfLines is set, this prop defines how text will be truncated. +// head: The line is displayed so that the end fits in the container and +// the missing text at the beginning of the line is indicated by an +// ellipsis glyph. e.g., "...wxyz" +// middle: The line is displayed so that the beginning and end fit in +// the container and the missing text in the middle is indicated by an +// ellipsis glyph. "ab...yz" +// tail: The line is displayed so that the beginning fits in the container +// and the missing text at the end of the line is indicated by an ellipsis +// glyph. e.g., "abcd..." +ellipsizeMode: 'head' | 'middle' | 'tail'; // Android & iOS only + +// Specifies a unique id for an HTML element. +// NOTE: This property may be going away in future versions. id: string = undefined; // Web only -// Should the scale multiplier be capped when allowFontScaling is set to true? -// Possible values include the following: -// null/undefined (default) - inheret from parent/global default -// 0 - no max -// >= 1 - sets the maxContentSizeMultiplier of this node to this value -// Note: Older versions of React Native don’t support this interface. -maxContentSizeMultiplier: number = null; // Android and iOS only - -// For non-zero values, truncates with ellipsis if necessary +// Expose the element and/or its children as accessible to Screen readers +importantForAccessibility: ImportantForAccessibility = + ImportantForAccessibility.Yes; + +// It is hard or impossible to tell by a reference to an instance of a component +// from where this component has been instantiated. You can assign this property +// and check instance.props.accessibilityId. For example accessibilityId is used +// in View's FocusArbitrator callback. +accessibilityId: string = undefined; + +// Should be focused when the component is mounted, see also View's arbitrateFocus +// property. +// WARNING: autoFocus=true means that this Text's requestFocus() method will be +// called, however calling requestFocus() for Text might make sense only on mobile +// for the accessibility reasons, on web it has no effect, the application has to +// handle this either while setting this property or in the View's FocusArbitrator +// callback. +autoFocus: boolean = false; + +// For non-zero values, truncates with ellipsis if necessary. Web platform +// doesn't support values greater than 1. Web platform may also not truncate +// properly if text contains line breaks, so it may be necessary to replace +// line breaks before rendering. numberOfLines: number = 0; -// Is the text selectable (affects mouse pointer and copy command) -selectable: boolean = false; - // Mouse & Touch Events onPress?: (e: SyntheticEvent) => void = undefined; onContextMenu?: (e: SyntheticEvent) => void = undefined; +// Is the text selectable (affects mouse pointer and copy command) +selectable: boolean = false; + // See below for supported styles style: TextStyleRuleSet | TextStyleRuleSet[] = []; -// Keyboard tab order -tabIndex: number = undefined; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; ``` ## Styles @@ -75,6 +88,24 @@ tabIndex: number = undefined; ``` javascript // Sets the accessibility focus to the component. focus(): void; + +// The preferable way to focus the component. When requestFocus() is called, +// the actual focus() will be deferred, and if requestFocus() has been +// called for several components, only one of those components will actually +// get a focus() call. By default, last component for which requestFocus() is +// called will get a focus() call, but you can specify arbitrateFocus property +// of a parent View and provide the callback to decide which one of that View's +// descendants should be focused. This is useful for the accessibility: when +// consecutive focus() calls happen one after another, the next one interrupts +// the screen reader announcement for the previous one and the user gets +// confused. autoFocus property of focusable components also uses requestFocus(). +requestFocus(): void; + +// Blurs the component. +blur(): void; + +// When selection is enabled, retrieves the selected text. +getSelectedText(): string; // Windows only ``` ## Sample Usage diff --git a/docs/docs/components/textinput.md b/docs/docs/components/textinput.md index 698fb468f..f9be376d9 100644 --- a/docs/docs/components/textinput.md +++ b/docs/docs/components/textinput.md @@ -15,6 +15,15 @@ It can be used in one of two modes. In the first mode, the contents of the text In addition to the [common accessibility props](/reactxp/docs/accessibility.html), the following props are supported. ``` javascript +// Text to be used by screen readers +accessibilityLabel: boolean = false; + +// It is hard or impossible to tell by a reference to an instance of a component +// from where this component has been instantiated. You can assign this property +// and check instance.props.accessibilityId. For example accessibilityId is used +// in View's FocusArbitrator callback. +accessibilityId: string = undefined; + // Should fonts be scaled according to system setting? allowFontScaling: boolean = true; // Android and iOS only @@ -24,12 +33,23 @@ autoCapitalize: 'none' | 'sentences' | 'words' | 'characters'; // Should auto-correction be applied to contents? autoCorrect: boolean = true; -// Should focus be applied to text input on componentDidMount? +// Should be focused when the component is mounted, see also View's arbitrateFocus +// property. +// WARNING: autoFocus=true means that this TextInput's requestFocus() method will be +// called, however calling requestFocus() might have no effect (for example the +// input is disabled), the application has to handle this either while setting this +// property or in the View's FocusArbitrator callback. autoFocus: boolean = false; // Should focus be lost after submitting? blurOnSubmit: boolean = false; +// iOS and Windows only property for controlling when the clear button +// should appear on the right side of the text view. Default behavior +// dependends on platform: equivalent to 'never' on iOS, and 'always' +// on Windows. +clearButtonMode: 'never' | 'while-editing' | 'unless-editing' | 'always'; + // Initial value that will change when the user starts typing defaultValue: string = undefined; @@ -45,14 +65,6 @@ keyboardAppearance: 'default' | 'light' | 'dark'; // On-screen keyboard type to display keyboardType: 'default' | 'numeric' | 'email-address' | 'number-pad'; -// Should the scale multiplier be capped when allowFontScaling is -// set to true? Possible values include the following: -// null/undefined (default) - inheret from parent/global default -// 0 - no max -// >= 1 - sets the maxContentSizeMultiplier of this node to this value -// Note: Older versions of React Native don’t support this interface. -maxContentSizeMultiplier: number = null; // Android and iOS only - // Maximum character count maxLength: number = undefined; @@ -71,16 +83,17 @@ onFocus: () => void = undefined; // Called on a key event onKeyPress: (e: KeyboardEvent) => void = undefined; -// Called when text is pasted into the control +// Called when text is pasted into the control (not currently +// supported on iOS or Android) onPaste: (e: ClipboardEvent) => void = undefined; // Called when the selection scrolls due to overflow -onScroll: (newScrollTop: number, newScrollLeft: number) => void = undefined; +onScroll: (newScrollLeft: number, newScrollTop: number) => void = undefined; // Called when the selection range or insertion point location changes onSelectionChange: (start: number, end: number) => void = undefined; -// Called when the text input submit button is pressed; invalid if +// Called when the text input submit button is pressed; invalid if // multiline is true onSubmitEditing: () => void = undefined; @@ -102,9 +115,11 @@ spellCheck: boolean = [value of autoCorrect]; // See below for supported styles style: TextInputStyleRuleSet | TextInputStyleRuleSet[] = []; -// Alignment of text within the input box. -textAlign: 'auto' | 'left' | 'right' | 'center' | 'justify'; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; +// Text for a tooltip +title: string = undefined; // If defined, the control value is forced to match this value; // if undefined, control value can be modified by the user @@ -129,9 +144,21 @@ blur(): void; // for setting screen reader focus focus(): void; +// The preferable way to focus the component. When requestFocus() is called, +// the actual focus() will be deferred, and if requestFocus() has been +// called for several components, only one of those components will actually +// get a focus() call. By default, last component for which requestFocus() is +// called will get a focus() call, but you can specify arbitrateFocus property +// of a parent View and provide the callback to decide which one of that View's +// descendants should be focused. This is useful for the accessibility: when +// consecutive focus() calls happen one after another, the next one interrupts +// the screen reader announcement for the previous one and the user gets +// confused. autoFocus property of focusable components also uses requestFocus(). +requestFocus(): void; + // Gives the control accessibility-only focus // E.g. screen reader focus is needed, but popping up of native -// keyboard is undesirable +// keyboard is undesirable setAccessibilityFocus(): void; // Does control currently have focus? diff --git a/docs/docs/components/view.md b/docs/docs/components/view.md index b9f27be70..8fe7d2f22 100644 --- a/docs/docs/components/view.md +++ b/docs/docs/components/view.md @@ -17,9 +17,6 @@ In addition to the [common accessibility props](/reactxp/docs/accessibility.html // If not defined, title prop is used. accessibilityLabel: string = undefined; -// Hide the component from screen readers? -accessibilityHidden: boolean = false; - // Traits used to hint screen readers, etc. accessibilityTraits: AccessibilityTrait | AccessibilityTrait[] = undefined; @@ -27,8 +24,15 @@ accessibilityTraits: AccessibilityTrait | AccessibilityTrait[] = undefined; accessibilityLiveRegion: AccessibilityLiveRegion = undefined; // Android and web only -// Expose the element and/or its children as accessible to Screen readers -importantForAccessibility?: ImportantForAccessibility = Auto; +// It is hard or impossible to tell by a reference to an instance of a component +// from where this component has been instantiated. You can assign this property +// and check instance.props.accessibilityId. For example accessibilityId is used +// in View's FocusArbitrator callback. +accessibilityId: string = undefined; + +// Opacity value the button should animate to, on touch on views that +// have onPress handlers +activeOpacity: number = undefined; // iOS and Android only // Animation of children // - Every child must have a `key`. @@ -38,17 +42,28 @@ animateChildLeave: boolean = false; animateChildMove: boolean = false; // Id of an element that describes the view for screenreader. -ariaLabelledBy: string = undefined; // Web only +ariaLabelledBy?: string = undefined; // Web only + +// A custom role description to be read by the screen readers. +ariaRoleDescription?: string = undefined; // Web only // Block touches for this component and all of its children -blockPointerEvents: boolean = false; // iOS and Android only +blockPointerEvents: boolean = false; + +// Disable default opacity animation on touch on views that have +// onPress handlers +disableTouchOpacityAnimation: boolean = false; // iOS and Android only // Specifies a unique id for an HTML element +// NOTE: This property may be going away in future versions. id: string = undefined; // Web only // Ignore clicks and other mouse events, allowing children or // components behind to receive them -ignorePointerEvents: boolean = false; // web only +ignorePointerEvents: boolean = false; + +// Expose the element and/or its children as accessible to Screen readers +importantForAccessibility?: ImportantForAccessibility = Auto; // When the keyboard navigation is happening, restrict the focusable // elements within this view. Useful for popups and modals, you @@ -62,7 +77,7 @@ ignorePointerEvents: boolean = false; // web only // setFocusRestricted() below. // WARNING: For the sake of performance, this property is readonly and // changing it during the View life cycle will produce an error. -restrictFocusWithin: boolean = false; // web only +restrictFocusWithin: boolean = false; // When the keyboard navigation is happening, do not focus on this view // and on all focusable elements inside this view. See also the companion @@ -71,9 +86,27 @@ restrictFocusWithin: boolean = false; // web only // one list item (and item's internal focusable elements) after another // using the Tab key and implement the switching between the items using // the arrow keys (or using some other behaviour). +// When limitFocusWithin=LimitFocusType.Limited, the View and the focusable +// components inside the View get both tabIndex=-1 and aria-hidden=true. +// When limitFocusWithin=LimitFocusType.Accessible, the View and the focusable +// components inside the View get only tabIndex=-1. // WARNING: For the sake of performance, this property is readonly and // changing it during the View life cycle will produce an error. -limitFocusWithin: boolean = false; // web only +limitFocusWithin: LimitFocusType = LimitFocusType.Unlimited; + +// Should be focused when the component is mounted, see also arbitrateFocus +// property below. +// WARNING: autoFocus=true means that this View's requestFocus() method will be +// called, however calling requestFocus() might have no effect (for example on web +// View is focusable only when tabIndex is specified), the application has to handle +// this either while setting this property or in the View's FocusArbitrator callback. +autoFocus: boolean = false; + +// When multiple components with autoFocus=true inside this View are mounting at +// the same time, and/or multiple components inside this view have received focus() +// call during the same render cycle, this callback will be called so that it's +// possible for the application to decide which one should actually be focused. +arbitrateFocus: FocusArbitrator = undefined; // Additional invisible DOM elements will be added inside the view // to track the size changes that are performed behind our back by @@ -82,6 +115,12 @@ limitFocusWithin: boolean = false; // web only importantForLayout: boolean = false; // web only // Mouse-specific Events +// For drag specific events, if onDragStart is present, the view is draggable. +// onDragStart/onDrag/onDragEnd are source specific events +// onDragEnter/onDragOver/onDragLeave/onDrop are destination specific events +onDragStart: (e: DragEvent) => void = undefined; +onDrag: (e: DragEvent) => void = undefined; +onDragEnd: (e: DragEvent) => void = undefined; onDragEnter: (e: DragEvent) => void = undefined; onDragOver: (e: DragEvent) => void = undefined; onDragLeave: (e: DragEvent) => void = undefined; @@ -95,7 +134,16 @@ onMouseOver: (e: MouseEvent) => void = undefined; onContextMenu: (e: React.SyntheticEvent) => void; onPress: (e: SyntheticEvent) => void = undefined; +// Focus Events +onFocus: (e: FocusEvent) => void = undefined; +onBlur: (e: FocusEvent) => void = undefined; + +// Keyboard Events +onKeyPress: (e: KeyboardEvent) => void = undefined; + // Touch-specific Events +onTouchStartCapture: (e: React.SyntheticEvent) => void = undefined; +onTouchMoveCapture: (e: React.SyntheticEvent) => void = undefined; onLongPress: (e: SyntheticEvent) => void = undefined; onMoveShouldSetResponder: (e: React.SyntheticEvent) => boolean = undefined; @@ -124,6 +172,9 @@ shouldRasterizeIOS: boolean = false; // iOS only // Keyboard tab order tabIndex: number = undefined; +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; + // Text for a tooltip title: string = undefined; @@ -133,15 +184,17 @@ style: ViewStyleRuleSet | ViewStyleRuleSet[] = []; // Should use hardware or software rendering? viewLayerTypeAndroid: 'none' | 'software' | 'hardware'; // Android only property -// Visual touchfeedback properties -// Disable default opacity animation on touch on views that have onPress handlers -disableTouchOpacityAnimation: boolean = false; // iOS and Android only - -// Opacity value the button should animate to, on touch on views that have onPress handlers. -activeOpacity: number = undefined; // iOS and Android only - -// Background color that will be visible on touch on views that have onPress handlers. -underlayColor: string = undefined; // ßiOS and Android only +// Background color that will be visible on touch on views that have onPress +// handlers +underlayColor: string = undefined; // iOS and Android only + +// When true +// - renders children within the safe area boundaries of a device, i.e. with +// padding with ensure the children don't cover navigation bars, +// toolbars etc. +// - Applies a style of { flex: 1, alignSelf: 'stretch' } to this view. +// - Some ViewProps may be ignored. +useSafeInsets: boolean = false; // iOS only ``` ## Styles @@ -153,11 +206,26 @@ underlayColor: string = undefined; // ßiOS and Android only ## Methods ``` javascript -// Sets the accessibility focus to the component. +// Sets the focus to the component. focus(): void; +// The preferable way to focus the component. When requestFocus() is called, +// the actual focus() will be deferred, and if requestFocus() has been +// called for several components, only one of those components will actually +// get a focus() call. By default, last component for which requestFocus() is +// called will get a focus() call, but you can specify arbitrateFocus property +// of a parent View and provide the callback to decide which one of that View's +// descendants should be focused. This is useful for the accessibility: when +// consecutive focus() calls happen one after another, the next one interrupts +// the screen reader announcement for the previous one and the user gets +// confused. autoFocus property of focusable components also uses requestFocus(). +requestFocus(): void; + +// Blurs the component. +blur(): void; + // The focus does not go outside the view with restrictFocusWithin by default, -// setFocusRestricted() allows to turn this restricton off and back on. +// setFocusRestricted() allows to turn this restriction off and back on. setFocusRestricted(restricted: boolean): void; // web only diff --git a/docs/docs/components/webview.md b/docs/docs/components/webview.md index f9b7168db..d0d8718a0 100644 --- a/docs/docs/components/webview.md +++ b/docs/docs/components/webview.md @@ -7,102 +7,4 @@ permalink: docs/components/webview.html next: apis/alert --- -This component displays HTML contents in an embedded browser control. - -To limit the functionality of the browser control, specify one or more sandbox options. For detailed definitions of sandbox flags, refer to the [HTML documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe). - - -## Types -``` javascript -enum WebViewSandboxMode { - None = 0, - AllowForms = 1 << 0, - AllowModals = 1 << 1, - AllowOrientationLock = 1 << 2, - AllowPointerLock = 1 << 3, - AllowPopups = 1 << 4, - AllowPopupsToEscapeSandbox = 1 << 5, - AllowPresentation = 1 << 6, - AllowSameOrigin = 1 << 7, - AllowScripts = 1 << 8, - AllowTopNavigation = 1 << 9 -} - -interface WebViewNavigationState { - canGoBack: boolean; - canGoForward: boolean; - loading: boolean; - url: string; - title: string; -} - -interface WebViewErrorState { - description: string; - domain: string; - code: string; -} -``` - -## Props -``` javascript -// Allow javascript code to call storage methods? -domStorageEnabled: boolean = true; // Native only - -// JavaScript code that is injected into the control and executed -injectedJavaScript: string = undefined; - -// Is JavaScript executed within the control? -javaScriptEnabled: boolean = true; - -// HTTP headers to include when fetching the URL. -headers: { [headerName: string]: string } = undefined; - -// Called when an error occurs that prevents the contents from loading -onError: (e: SyntheticEvent) => void = undefined; // Native only - -// Called when the contents successfully load -onLoad: (e: SyntheticEvent) => void = undefined; - -// Called when the contents start to load -onLoadStart: (e: SyntheticEvent) => void = undefined; // Native only - -// Called when the navigation state changes -onNavigationStateChange: (navigationState: WebViewNavigationState) => void; - -// Flags that restrict behaviors within the control -sandbox: WebViewSandboxMode = None; // Web only - -// Zooms the page contents to fit the available space -scalesPageToFit: boolean = false; - -// Start loading immediately or wait for reload? -startInLoadingState: boolean = true; // Native only - -// See below for supported styles -style: WebViewStyleRuleSet | WebViewStyleRuleSet[] = []; - -// URL to HTML content -url: string = undefined; -``` - -## Styles -No specialized styles - -## Methods -``` javascript -// Navigate back and forward -goBack(); -goForward(); - -// Posts a message to the web control, allowing for communication between -// the app and the JavaScript code running within the web control -// Available only on web -postMessage(message: string, targetOrigin?: string = '*'): void; - -// Force the page to reload -reload(); -``` - - - - +This has been deprecated from ReactXP Core and moved to an extension (reactxp-webview) inline with the React Native Lean Core initiative. diff --git a/docs/docs/extensions.md b/docs/docs/extensions.md index 77d8e457e..33d3e19a3 100644 --- a/docs/docs/extensions.md +++ b/docs/docs/extensions.md @@ -10,12 +10,17 @@ next: components/activityindicator The ReactXP library is designed to be as lightweight as possible, including only those cross-platform APIs and "primitive" components that are required by almost every app. Functionality that is needed less commonly is provided in the form of optional extensions. There are two distinct types of extensions. -1. Additional APIs or "primitive" components that have separate implementations for each of the supported platforms. -2. Higher-level components that contain no platform-specific code but build upon the lower-level primitives to provide new (typically more complex) functionality. +1. Higher-level components that contain no platform-specific code but build upon the lower-level primitives to provide new (typically more complex) functionality. +2. Additional APIs or "primitive" components that have separate implementations for each of the supported platforms. Extensions are published as separate npm packages. They typically start with the prefix "reactxp-". +## Higher-level ReactXP Components + +Using a higher-level component is just like using any other component in React. Because these components are built on cross-platform ReactXP primitives, they also work in a cross-platform manner. + + ## Primitive ReactXP Extensions To use a primitive extension in your app, add it to your package.json like any other npm module. Then import it at the top of the code module where you want to consume it. @@ -43,9 +48,19 @@ class MyVideoPanel extends RX.Component { A new "primitive" extension (either a component or an API namespace) must have a cross-platform interface and a platform-specific implementation of this interface for each of the platforms supported by ReactXP. In some cases, the implementation may be shared between platforms. +An implementation should be provided for each of the supported platforms. Web, iOS and Android are required. React Native for MacOS and Windows are still under development and are currently considered optional, but they may become required in the future. The main implementation file for each platform is named ```index.[platform].js```. For the web, the platform is omitted (that is, the file is named ```index.js```). These implementation files must live at the top level of the extension's published directory, but it is typical for them to simply import code from a ```dist``` directory. -## Higher-level ReactXP Components +Many ReactXP apps are written in TypeScript, so it's highly recommended that all ReactXP extensions provide a type definition file that defines the cross-platform interface to the extension. The extension's ```package.json``` should refer to this type file. For example: ```"types": "dist/MyExtension.d.ts"```. If you are implementing the extension in TypeScript, the compiler can be used to ensure that the implementation for each platform matches the public interface. -Using a higher-level component is just like using any other component in React. Because these components are built on cross-platform ReactXP primitives, they also work in a cross-platform manner. +## Sample Extensions + +Refer to the "Extensions" section of the documentation for a full list of available ReactXP extensions. Some of these are in separate git repositories, and others are in the [extensions](https://github.com/Microsoft/reactxp/tree/master/extensions) directory of the reactxp repository. The [reactxp-video](https://github.com/Microsoft/reactxp/tree/master/extensions/video) extension is a good example of a complete extension that involves native code for each of the supported platforms. To build any of these sample extensions: + +1. Clone the repository. +2. Switch to the top-level directory of the extension (e.g. ```reactxp/extensions/video```). +3. Install the dependent npm packages: ```npm install```. +4. Build the code: ```npm run build```. + +The resulting code will be found in the ```dist``` directory. diff --git a/docs/docs/extensions/database.md b/docs/docs/extensions/database.md index 68a2d9421..1f0840ac6 100644 --- a/docs/docs/extensions/database.md +++ b/docs/docs/extensions/database.md @@ -9,6 +9,6 @@ next: extensions/imagesvg ReactXP provides a [Storage API](/reactxp/docs/apis/storage) for reading and writing simple key/value pairs. Many apps have more complex storage requirements. For this, we developed a no-SQL database wrapper that works on React Native and on browsers. The solution isn't tied to ReactXP, but they work well together. -For more details, refer to the [NoSqlProvider](https://github.com/Microsoft/NoSQLProvider) github site. +For more details, refer to the [NoSqlProvider](https://github.com/Microsoft/NoSQLProvider) GitHub site. To install: ```npm install nosqlprovider``` diff --git a/docs/docs/extensions/imagesvg.md b/docs/docs/extensions/imagesvg.md index 5c302108f..32a6c83b9 100644 --- a/docs/docs/extensions/imagesvg.md +++ b/docs/docs/extensions/imagesvg.md @@ -7,11 +7,12 @@ permalink: docs/extensions/imagesvg.html next: extensions/navigator --- -This component displays a vector image (SVG format), which can come from a local source or from the network. Props control the fill color, stroke color and stroke width. +This component displays a vector image (SVG format). Props control the fill color, stroke color and stroke width. -The path(s) are specified using the standard SVG string format. Paths must be specified in a nested SvgPath component instance. Multiple SvgPath children can be specified, each with different stroke and fill parameters. +The path(s) are specified using the standard SVG string format. Paths must be specified in a nested SvgPath component instance. Multiple SvgPath children can be specified, each with different stroke and fill parameters. SvgRect children +are also supported at this time, with the limited props available in react-native-svg. -To install: ```npm install reactxp-imagesvg``` +To install: ```npm install reactxp-imagesvg``` or ```yarn add reactxp-imagesvg``` ## ImageSvg Props ``` javascript @@ -40,11 +41,10 @@ viewBox: string = undefined; webShadow: boolean = false; // web-specific ``` -## SvgPath Props -``` javascript -// Path definition string -d: string = undefined; +## SvgCommon Props +These props apply to all of the sub-SVG-element types below: +``` javascript // Color and opacity of fill; default values are provided by SVG fillColor: color; fillOpacity: number; @@ -55,30 +55,51 @@ strokeWidth: number; strokeOpacity: number; ``` +## SvgPath Props +``` javascript +// Path definition string +d: string = undefined; +``` + +## SvgRect Props +``` javascript +// Position and dimension information for the rect +x: number; +y: number; +width: number; +height: number; +``` + ## Styles -[**Flexbox Styles**](docs/styles.html#flexbox-style-attributes) +[**Flexbox Styles**](/reactxp/docs/styles.html#flexbox-style-attributes) -[**View Styles**](docs/styles.html#view-style-attributes) +[**View Styles**](/reactxp/docs/styles.html#view-style-attributes) -[**Transform Styles**](docs/styles.html#transform-style-attributes) +[**Transform Styles**](/reactxp/docs/styles.html#transform-style-attributes) ## Methods No methods ## Sample Usage ``` javascript +import { default as RXImageSvg, SvgPath as RXSvgPath, Types as SvgTypes } + from 'reactxp-imagesvg'; + return ( - - + - + + ); ``` diff --git a/docs/docs/extensions/navigator.md b/docs/docs/extensions/navigator.md index d68c59e1b..2bfa05239 100644 --- a/docs/docs/extensions/navigator.md +++ b/docs/docs/extensions/navigator.md @@ -4,18 +4,18 @@ title: Navigator layout: docs category: Extensions permalink: docs/extensions/navigator.html -next: extensions/restclient +next: extensions/netinfo --- This component provides a way for the app to present a virtual stack of "cards", allowing the user to push or pop those cards onto the stack in an animated manner. The caller can control the animation type and direction. -When a new card is presented, the Navitator calls the renderScene method, allowing the caller to render the contents. Cards are identified by "routes", which contain a unique ID and configuration parameters that control the behavior of the transition. +When a new card is presented, the Navigator calls the renderScene method, allowing the caller to render the contents. Cards are identified by "routes", which contain a unique ID and configuration parameters that control the behavior of the transition. When a Navigator is first mounted, the stack is empty. The caller must wait for the mount to complete, then specify the list of routes to present. -The current implementation of Navitator on React Native makes use of the deprecated "Navigator Experimental". We will look at moving away from this implementation to the now-recommended "react-navigation" in the near future. Some of the more advanced interfaces may need to change. These are listed at the end of this article. Use these with caution. +The current implementation of Navigator on React Native makes use of the deprecated "Navigator Experimental". We will look at moving away from this implementation to the now-recommended "react-navigation" in the near future. Some of the more advanced interfaces may need to change. These are listed at the end of this article. Use these with caution. -To install: ```npm install reactxp-navigator``` +To install: ```npm install reactxp-navigation``` ## Types ``` javascript @@ -127,12 +127,12 @@ class App extends RX.Component { ); } - private _onNavigatorRef = (naviator: RX.Navigator) => { + private _onNavigatorRef = (navigator: RX.Navigator) => { // Stash away a reference to the mounted navigator this._navigator = navigator; } - private _renderScene = (route: NavigatorRoute) => { + private _renderScene = (navigatorRoute: NavigatorRoute) => { switch (navigatorRoute.routeId) { case NavigationRouteId.MainPanel: return ( @@ -182,19 +182,19 @@ These types apply only to React Native platforms, and they currently rely on the // Additional options that affect card transitions type CustomNavigatorSceneConfig = { // Optional transition styles - transitionStyle?: (sceneIndex: number, + transitionStyle?: (sceneIndex: number, sceneDimensions: Dimensions) => NavigationTransitionStyleConfig; // Optional overrides for duration, easing, and timing transitionSpec?: NavigationTransitionSpec; - + // Optional cardStyle override cardStyle?: ViewStyleRuleSet; - + // Optionally hide drop shadow hideShadow?: boolean; - + // Optionally flip the visual order of the last two scenes presentBelowPrevious?: boolean; }; @@ -227,7 +227,7 @@ These props apply only to React Native platforms, and they currently rely on the navigateBackCompleted: () => void; // Called when a transition begins; works only -// on native +// on native transitionStarted: (progress?: RX.AnimatedValue, toRouteId?: string, fromRouteId?: string, toIndex?: number, fromIndex?: number) => void = undefined; diff --git a/docs/docs/extensions/netinfo.md b/docs/docs/extensions/netinfo.md new file mode 100644 index 000000000..d0e9f6cd2 --- /dev/null +++ b/docs/docs/extensions/netinfo.md @@ -0,0 +1,65 @@ +--- +id: extensions/netinfo +title: NetInfo +layout: docs +category: Extensions +permalink: docs/extensions/netinfo.html +next: extensions/restclient +--- + +This interface provides information about network connectivity. + +## Types +``` javascript +enum DeviceNetworkType { + Unknown, + None, + Wifi, + Mobile2G, + Mobile3G, + Mobile4G +} +``` + +## Methods +``` javascript +// Returns a promise that specifies whether the device currently +// has network connectivity +isConnected(): SyncTasks.Promise; + +// Returns the type of network +getType(): SyncTasks.Promise; +``` + +## Events +``` javascript +// Triggered when the connectivity changes +connectivityChangedEvent: SubscribableEvent<(isConnected: boolean) => void>; +``` + +## Sample Usage + +``` javascript +private isConnected: boolean; + +constructor() { + // Query the initial connectivity state. + this.isConnected = false; + RXNetInfo.isConnected().then(isConnected => { + this.isConnected = isConnected; + }); + + RXNetInfo.connectivityChangedEvent.subscribe(isConnected => { + // Update the connectivity state. + this.isConnected = isConnected; + }); +} +``` + +## Other Notes + +On Android, the following permission must be added to make use of the network interfaces. + +``` xml + +``` diff --git a/docs/docs/extensions/restclient.md b/docs/docs/extensions/restclient.md index 68b1d8cc2..e2069f902 100644 --- a/docs/docs/extensions/restclient.md +++ b/docs/docs/extensions/restclient.md @@ -11,20 +11,23 @@ ReactXP provides basic [Network APIs](/reactxp/docs/apis/network) for determinin This extension provides a cross-platform mechanism for wrapping a simple REST API. It supports optional retry logic (including exponential backoff). -For more details, refer to the [SimpleRestClients](https://github.com/Microsoft/SimpleRestClients) github site. +For more details, refer to the [SimpleRestClients](https://github.com/Microsoft/SimpleRestClients) GitHub site. -To install: ```npm install simplerestclients``` +To install: ```npm install simplerestclients``` or ```yarn add simplerestclients``` ### Sample Usage ``` javascript -interface User { +import { GenericRestClient, ApiCallOptions } from 'simplerestclients'; +import SyncTasks = require('synctasks'); + +export interface User { id: string; firstName: string; lastName: string; } -class MyRestClient extends GenericRestClient { +export default class MyRestClient extends GenericRestClient { constructor(private _appId: string) { super('https://myhost.com/api/v1/'); } @@ -50,4 +53,4 @@ class MyRestClient extends GenericRestClient { return this.performApiPut('user/' + user.id, user); } } -``` \ No newline at end of file +``` diff --git a/docs/docs/extensions/video.md b/docs/docs/extensions/video.md index 993cba347..79cffd95c 100644 --- a/docs/docs/extensions/video.md +++ b/docs/docs/extensions/video.md @@ -13,7 +13,7 @@ To install: ```npm install reactxp-video``` ## Types ``` javascript -// Used to return progress information in the onProgress callback +// Used to return progress information in the onProgress callback interface VideoProgress { currentTime: number; playableDuration: number; @@ -85,8 +85,8 @@ resizeMode: 'contain'|'cover'|'stretch' = 'contain'; // Displays controls for play, pause, etc. showControls: boolean = false; -// Source of video (URL) -source: string; +// Source of video (URL) or resource `id` as resolved by `require()` for `react-native` targets. +source: string | number; // See below for supported styles style: ViewStyleRuleSet | ViewStyleRuleSet[] = []; diff --git a/docs/docs/extensions/virtuallistview.md b/docs/docs/extensions/virtuallistview.md index c89b3b5e5..62e9f62f5 100644 --- a/docs/docs/extensions/virtuallistview.md +++ b/docs/docs/extensions/virtuallistview.md @@ -4,6 +4,7 @@ title: VirtualListView layout: docs category: Extensions permalink: docs/extensions/virtuallistview.html +next: extensions/webview --- This components supports a vertical list of items within a scrolling area. The visible portion of the list is referred to as the "view port". The list is virtualized, which means that items are rendered only when they are within the view port (or just above or below the view port). @@ -24,7 +25,7 @@ To install: ```npm install reactxp-virtuallistview``` The VirtualListView employs a number of tricks to improve performance. -It uses a technique called "cell recycling" to minimize the number of mounts and unmounts. A cell is a container for a list item. When a cell is no longer visible, it can be temporarily hidden and then reused for the next item that becomes visible. This optimization is most effective when the recycled cell and its contents are used for an item that is similar in content. For this reason, callers need to specify a "template" field to identify similar items. +It uses a technique called "cell recycling" to minimize the number of mounts and unmounts. A cell is a container for a list item. When a cell is no longer visible, it can be temporarily hidden and then reused for the next item that becomes visible. This optimization is most effective when the recycled cell and its contents are used for an item that is similar in content. For this reason, callers need to specify a "template" field to identify similar items. In some cases, disabling cell recycling can be benificial as recycled cells continue their regular react lifecycle even when not visible, which can lead to excessive background re-rendering in some cases. When combining VLV with react libraries (like ReSub) that have subscriptions managed by components can cause this behaviour to manifest. To disable cell recycling on specific cells, exclude the template field from the item descriptor. It also supports "overdraw" to render items above and below the view port. This minimizes chances that the user will scroll to a new portion of the list before new items can be rendered in that area. Overdraw is employed only after the view port is initially filled. This reduces the performance impact of rendering. @@ -86,18 +87,18 @@ class FruitListView extends RX.Component { ); } - private _renderItem(item: FruitListItemInfo, hasFocus?: boolean) { + private _renderItem(details: VirtualListViewCellRenderDetails) { const viewStyle = RX.Styles.createViewStyle({ - height: item.height, + height: details.item.height, backgroundColor: item.template === _headerItemTemplate ? '#ddd' : '#fff', alignItems: 'center' }, false); - + return ( - { item.text } + { details.item.text } ); @@ -118,7 +119,7 @@ interface VirtualListViewItemInfo { // Specifies that the height is not known and needs to be measured // dynamically. This has a big perf overhead because it requires a - // double layout (once offscreen to measure the item). It also + // double layout (once offscreen to measure the item). It also // disables cell recycling. Wherever possible, it should be avoided, // especially for perf-critical views. measureHeight?: boolean; @@ -139,48 +140,68 @@ interface VirtualListViewItemInfo { ## Props ``` javascript - // Ordered list of descriptors for items to display in the list. - itemList: VirtualListViewItemInfo[]; - - // Callback for rendering item when it becomes visible within view port. - renderItem: (item: VirtualListViewItemInfo, hasFocus?: boolean) => - JSX.Element | JSX.Element[]; - - // Optional padding around the scrolling content within the list. - padding?: number; - - // If true, allows each item to overflow its visible cell boundaries; - // by default, item contents are clipped to cell boundaries. - showOverflow?: boolean; - - // Should the list animate additions, removals and moves within the list? - animateChanges?: boolean; - - // By default, VirtualListView re-renders every item during the render. - // Setting this flag to true allows the list view to re-render only - // items from itemList whose descriptor has changed, thus avoiding - // unnecessary rendering. It uses _.isEqual to perform this check. In - // this mode, renderItem should not depend on any external state, only - // on VirtualListViewItemInfo, to render item. - skipRenderIfItemUnchanged?: boolean; - - // Pass-through properties for scroll view. - keyboardDismissMode?: 'none' | 'interactive' | 'on-drag'; - keyboardShouldPersistTaps?: boolean; - disableScrolling?: boolean; - scrollsToTop?: boolean; // iOS only, scroll to top on status bar tap - disableBouncing?: boolean; // iOS only, bounce override - scrollIndicatorInsets?: { top: number, left: number, - bottom: number, right: number }; // iOS only - onScroll?: (scrollTop: number, scrollLeft: number) => void; - - // Logging callback to debug issues related to the VirtualListView. - logInfo?: (textToLog: string) => void; +// Should the list animate additions, removals and moves within the list? +animateChanges?: boolean; + +initialSelectedKey?: string; + +// Ordered list of descriptors for items to display in the list. +itemList: VirtualListViewItemInfo[]; + +// Use this if you want to vertically offset the focused item from the +// top of the viewport when using keyboard nav +keyboardFocusScrollOffset?: number; + +// Logging callback to debug issues related to the VirtualListView. +logInfo?: (textToLog: string) => void; + +// Callback when an item in the VLV is selected +onItemSelected?: (item: ItemInfo) => void; + +// Optional padding around the scrolling content within the list. +padding?: number; + +// Callback for rendering item when it becomes visible within view port. +renderItem: (renderDetails: VirtualListCellRenderDetails) => + JSX.Element | JSX.Element[]; + +// If true, allows each item to overflow its visible cell boundaries; +// by default, item contents are clipped to cell boundaries. +showOverflow?: boolean; + +// By default, VirtualListView re-renders every item during the render. +// Setting this flag to true allows the list view to re-render only +// items from itemList whose descriptor has changed, thus avoiding +// unnecessary rendering. It uses _.isEqual to perform this check. In +// this mode, renderItem should not depend on any external state, only +// on VirtualListViewItemInfo, to render item. +skipRenderIfItemUnchanged?: boolean; + +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; + +// Pass-through properties for scroll view. +keyboardDismissMode?: 'none' | 'interactive' | 'on-drag'; +keyboardShouldPersistTaps?: boolean; +disableScrolling?: boolean; +scrollsToTop?: boolean; // iOS only, scroll to top when user taps on status bar +disableBouncing?: boolean; // iOS only, bounce override +scrollIndicatorInsets?: { top: number, left: number, + bottom: number, right: number }; // iOS only +onLayout?: (e: RX.Types.ViewOnLayoutEvent) => void; +scrollEventThrottle?: number; +onScroll?: (scrollTop: number, scrollLeft: number) => void; +scrollXAnimatedValue?: RX.Types.AnimatedValue; +scrollYAnimatedValue?: RX.Types.AnimatedValue; + ``` ## Methods ``` javascript // Scrolls the view to the specified top value (specified in pixels). scrollToTop(animated = true, top = 0); + +// Sets selection & focus to specified key +selectItemKey(key: string); ``` diff --git a/docs/docs/extensions/webview.md b/docs/docs/extensions/webview.md new file mode 100644 index 000000000..4a871804c --- /dev/null +++ b/docs/docs/extensions/webview.md @@ -0,0 +1,136 @@ +--- +id: extensions/webview +title: WebView +layout: docs +category: Extensions +permalink: docs/extensions/webview.html +--- + +This component displays HTML contents in an embedded browser control. + +To limit the functionality of the browser control, specify one or more sandbox options. For detailed definitions of sandbox flags, refer to the [HTML documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe). + + +## Types +``` javascript +enum WebViewSandboxMode { + None = 0, + AllowForms = 1 << 0, + AllowModals = 1 << 1, + AllowOrientationLock = 1 << 2, + AllowPointerLock = 1 << 3, + AllowPopups = 1 << 4, + AllowPopupsToEscapeSandbox = 1 << 5, + AllowPresentation = 1 << 6, + AllowSameOrigin = 1 << 7, + AllowScripts = 1 << 8, + AllowTopNavigation = 1 << 9, + + // Control https mixed content behavior, never by default + AllowMixedContentAlways = 1 << 10, + AllowMixedContentCompatibilityMode = 1 << 11 +} + +interface WebViewNavigationState { + canGoBack: boolean; + canGoForward: boolean; + loading: boolean; + url: string; + title: string; + readonly navigationType: + | 'click' + | 'formsubmit' + | 'backforward' + | 'reload' + | 'formresubmit' + | 'other'; +} + +interface WebViewErrorState { + description: string; + domain: string; + code: string; +} + +interface WebViewSource { + html: string; + baseUrl?: string; // Native only +} +``` + +## Props +``` javascript +// Allow javascript code to call storage methods? +domStorageEnabled: boolean = true; // Native only + +// JavaScript code that is injected into the control and executed +injectedJavaScript: string = undefined; // Native only + +// Is JavaScript executed within the control? +javaScriptEnabled: boolean = true; + +// Determines whether HTML5 audio and video requires the user to tap them before they start playing. +mediaPlaybackRequiresUserAction: boolean = true; // Native only + +// Determines whether HTML5 videos play inline or use the native full-screen controller. +allowsInlineMediaPlayback: boolean = false; // iOS only + +// HTTP headers to include when fetching the URL. +headers: { [headerName: string]: string } = undefined; + +// Called when an error occurs that prevents the contents from loading +onError: (e: SyntheticEvent) => void = undefined; // Native only + +// Called when the contents successfully load +onLoad: (e: SyntheticEvent) => void = undefined; + +// Called when the contents start to load +onLoadStart: (e: SyntheticEvent) => void = undefined; // Native only + +// Called when a message is posted from within a WebView +onMessage: (e: WebViewMessageEvent) => void = undefined; + +// Called when the navigation state changes +onNavigationStateChange: (navigationState: WebViewNavigationState) => void; // Native only + +// Flags that restrict behaviors within the control +sandbox: WebViewSandboxMode = None; + +// Zooms the page contents to fit the available space; deprecated on +// iOS in RN 0.57 +scalesPageToFit: boolean = false; // Native only + +// HTML to display in webview (if url is not specified) +source: WebViewSource = undefined; + +// Start loading immediately or wait for reload? +startInLoadingState: boolean = true; // Native only + +// See below for supported styles +style: WebViewStyleRuleSet | WebViewStyleRuleSet[] = []; + +// ID that can be used to identify the instantiated element for testing purposes. +testId: string = undefined; + +// URL to HTML content +url: string = undefined; +``` + +## Styles +No specialized styles + +## Methods +``` javascript +// Navigate back and forward +goBack(); +goForward(); + +// Posts a message to the web control, allowing for communication between +// the app and the JavaScript code running within the web control. On native +// platforms, the targetOrigin is ignored. +postMessage(message: string, targetOrigin?: string = '*'): void; + +// Force the page to reload +reload(); +``` + diff --git a/docs/docs/faq.md b/docs/docs/faq.md index 8825f4ec8..cf2f94ed2 100644 --- a/docs/docs/faq.md +++ b/docs/docs/faq.md @@ -40,7 +40,7 @@ ReactXP builds upon React Native. ReactXP's components and APIs are inspired by ReactXP is neither a proper subset nor a proper superset of React Native. It doesn't expose every component provided by React Native. In particular, it doesn't expose any components that are platform-specific (such as PickerIOS or MapView). It also exposes some components and APIs that are not implemented in React Native, such as [GestureView](components/gestureview.html) and [UserPresence](apis/userpresence.html). -Apps that use ReactXP can directly access React Native components and APIs. They can also directly access React DOM elements on the web. But such code will need to include build-time or run-time conditionals to avoid using these components or APIs on platforms where they don't apply. +Apps that use ReactXP can directly access React Native components and APIs. They can also directly access React DOM elements on the web. But such code will need to include build-time or run-time conditionals to avoid using these components or APIs on platforms where they don't apply. All components and APIs exposed through ReactXP are implemented for all supported platforms. In some cases, API calls are no-ops, but they are guaranteed to be implemented. For example, Input.backButtonEvent is a no-op on iOS and the web, and StatusBar APIs are no-ops on the web. Apps that use only ReactXP abstractions can generally avoid per-platform conditional checks. diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index 210124d2c..e150ed7d1 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -9,18 +9,23 @@ redirect_from: - "docs/index.html" --- +## Building Your First ReactXP App + +To create your first ReactXP app, do the following: +1. Clone the ReactXP repo locally: ```git clone https://github.com/microsoft/reactxp```. +2. Open the ```samples``` directory and pick one of the samples and copy its directory to a new location. [Hello-World](https://github.com/Microsoft/reactxp/tree/master/samples/hello-world) provides a bare-bones starting app. [Hello-World-js](https://github.com/Microsoft/reactxp/tree/master/samples/hello-world-js) is a variant of Hello-World written in Javascript rather than TypeScript. [TodoList](https://github.com/Microsoft/reactxp/tree/master/samples/TodoList) is a more complex example and is a more appropriate starting point for production applications. +3. Follow the build instructions for the sample you've chosen. +4. If desired, rename the directory and project files to reflect the name of your app. + +If you want to create a new ReactXP app, use the command-line tool [create-rx-app](https://github.com/a-tarasyuk/create-rx-app). + ## Web Technologies React apps are written using web programming techniques. This documentation assumes that you are already familiar with web programming concepts including the use of JavaScript, the browser DOM, browser event handling, and CSS styling. There are many online tutorials that cover these concepts. -While it is possible to write ReactXP apps in JavaScript, we recommend using TypeScript or Flow instead. These languages add type safety, compile-time error detection, and IntelliSense capabilities to JavaScript. If you are already familiar with JavaScript, it is easy to learn TypeScript. Here is a recommended [TypeScript tutorial](http://www.typescriptlang.org/tutorial/). +While it is possible to write ReactXP apps in JavaScript, we recommend using TypeScript or Flow instead. These languages add type safety, compile-time error detection, and IntelliSense capabilities to JavaScript. If you are already familiar with JavaScript, it is easy to learn TypeScript. Here is a recommended [TypeScript tutorial](http://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html). ## Understanding React -If you are new to React, you should first familiarize yourself with the core concepts. We provide an overview and some [simple examples](react_concepts.html). Also refer to the official [React](http://facebook.github.io/react/) and [React Native](https://facebook.github.io/react-native/) documentation sites. - -## Building Your First ReactXP App - -The "samples" directory contains a minimal "Hello World" app that demonstrates some basic ReactXP functionality. You can use this as a starting point. Just follow the build instructions in the README file. +If you are new to React, you should first familiarize yourself with the core concepts. We provide an overview and some [simple examples](react_concepts.html). Also refer to the official [React](https://reactjs.org/) and [React Native](https://facebook.github.io/react-native/) documentation sites. -Nader Dabit has created a helpful [video tutorial](https://medium.com/@dabit3/reactxp-first-look-d3dd1d08febd) that walks you through the steps to build the sample app. diff --git a/docs/docs/react_concepts.md b/docs/docs/react_concepts.md index d1abde863..c40efed83 100644 --- a/docs/docs/react_concepts.md +++ b/docs/docs/react_concepts.md @@ -55,7 +55,7 @@ We will modify the Hello World example to introduce an optional "userName" prop. ## Styles The example above renders a string using default styles (font, size, color, etc.). You can override style defaults by specifying a "style" prop. In this example, we render bold text on a green background. Note that styles within React (and ReactXP) borrow heavily from CSS. - // By convention, styles are created statically and referenced + // By convention, styles are created statically and referenced // through a private (not exported) _styles object. const _styles = { container: RX.Styles.createViewStyle({ @@ -84,7 +84,7 @@ For more details about style attributes, refer to the [styles](/reactxp/docs/sty ## Layout Directives -React uses flexbox directives for component layout. These directives are specified along with styling information. A number of flexbox tutorials are available online. [Here](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) is one we especially recommend. Using flexbox directives, you can specify the primary layout direction (row or column), justification, alignment, and spacing. +React uses flexbox directives for component layout. These directives are specified along with styling information. A number of flexbox tutorials are available online. [Here](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) is one we especially recommend. Using flexbox directives, you can specify the primary layout direction (row or column), justification, alignment, and spacing. React also adopts the notion of margin and padding from CSS. Margin is the amount of space around a component, and padding is the amount of space between the boundary of the component and its children. @@ -135,7 +135,7 @@ React components can define a *state* object. When this object is updated throug interface StopLightState { // Fields within a state object are usually defined as optional - // (hence the question mark below) because calls to setState + // (hence the question mark below) because calls to setState // typically update only a subset of the fields. isStopped?: boolean; } @@ -162,11 +162,11 @@ React components can define a *state* object. When this object is updated throug render() { // Choose the appropriate style for the current state. - var buttonStyle = this.state.isStopped ? + var buttonStyle = this.state.isStopped ? _styles.redButton : _styles.greenButton; return ( - ); } diff --git a/docs/docs/react_lifecycle.md b/docs/docs/react_lifecycle.md index 104f2fd42..cb3e8fd2e 100644 --- a/docs/docs/react_lifecycle.md +++ b/docs/docs/react_lifecycle.md @@ -39,7 +39,7 @@ In this example, a UserInfoCard component is rendered for each user in a list. E ## Mounting & Unmounting -When React encounters a component spec that has no corresponding node in the current virtual DOM, it inserts the spec into the virtual DOM. It also allocates a corresponding DOM element (in the case of React JS) or native control (in the case of React Native). This is referred to as *mounting* a component. Likewise, when a component instance is removed from the real DOM or native control hierarhcy, it is said to be *unmounted*. Certain methods, such as *setState*, can be called only while a component is mounted. +When React encounters a component spec that has no corresponding node in the current virtual DOM, it inserts the spec into the virtual DOM. It also allocates a corresponding DOM element (in the case of React JS) or native control (in the case of React Native). This is referred to as *mounting* a component. Likewise, when a component instance is removed from the real DOM or native control hierarchy, it is said to be *unmounted*. Certain methods, such as *setState*, can be called only while a component is mounted. The React.Component base class, from which all components derive, defines several methods that are called immediately before and after a component is mounted and before a component is unmounted. Component classes can override these methods if desired. For example, if you want to set the focus to a text input box, this can be done within the componentDidMount method. diff --git a/docs/docs/styles.md b/docs/docs/styles.md index 28a2802e8..9e9dee6c0 100644 --- a/docs/docs/styles.md +++ b/docs/docs/styles.md @@ -24,7 +24,7 @@ Many base components share common subsets of style attributes. For example, almo ## Combining Styles -All of the base components support a *style* prop that can accept a single style or an array of styles. If an array of styles is provided, the styles are combined in such a way that styles with larger indices override styles with smaller indices. Falsy values (false, null, undefined) can also be specified in a style array. This allows for the following common pattern. +All of the base components support a *style* prop that can accept a single style or an array of styles (or a nested array). If an array of styles is provided, the styles are combined in a depth-first manner left to right. Falsy values (false, null, undefined) can also be specified in a style array. This allows for the following common pattern. ``` javascript let buttonTextStyles = [_styles.baseText, this.state.hovering && _styles.hoverText]; @@ -39,7 +39,7 @@ if (this.state.hovering) { } ``` -Within a style array, you can also pass nested arrays. This allows easy manipulation of composite styles. +If "margin" and "padding" attributes are combined with edge-specific attributes (e.g. "marginLeft" or "paddingBottom"), the specific attributes always override the general. This matches the [combining behavior of React Native](https://github.com/necolas/react-native-web/blob/0.10.0/docs/guides/style.md#how-styles-are-resolved) (but differs from CSS). ``` javascript // this.props.style might be undefined, a single style, or a (potentially-nested) @@ -74,7 +74,7 @@ ReactXP adopts the simplified flexbox rules and defaults defined by React Native + While it is possible to specify flexGrow, flexShrink and flexBasis values independently, it is more common to specify the flex parameters using a shortcut called "flex". It accepts an integer value and covers the following common cases. * "flex: 0" implies "flex: 0 0 auto" * "flex: n" (where n is negative) implies "flex: 0 n auto" - * "flex: p" (where p is positive) implies "flex: n 1 auto" + * "flex: p" (where p is positive) implies "flex: p 1 auto" + The default flexDirection is 'column' rather than 'row'. @@ -158,6 +158,10 @@ overflow: 'hidden' | 'visible'; **Borders** ```javascript borderWidth: number; +borderTopWidth: number; +borderRightWidth: number; +borderBottomWidth: number; +borderLeftWidth: number; borderColor: color; borderStyle: 'solid' | 'dotted' | 'dashed' | 'none'; borderRadius: number; // Sets all four border radius attributes; value is animatable @@ -169,6 +173,8 @@ borderTopLeftRadius: number = 0; **Shadows** ```javascript +// NOTE: If applied to a Text element, these properties translate to text shadows, +// not a box shadow. shadowOffset: { height: number; width: number } = { 0, 0 }; shadowRadius: number = 0; shadowColor: color = 'black'; @@ -196,7 +202,6 @@ transform: { scale: number = 0; scaleX: number = 0; scaleY: number = 0; - scaleY: number = 0; translateX: number = 0; translateY: number = 0; } @@ -215,9 +220,9 @@ fontSize: number = undefined; // Shortcut that sets all three font attributes font: { - family: string = undefined; - style: 'normal' | 'italic'; - weight: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | + fontFamily: string = undefined; + fontStyle: 'normal' | 'italic'; + fontWeight: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; } ``` diff --git a/docs/docs/using-reactxp.md b/docs/docs/using-reactxp.md index da25d008d..7bf594213 100644 --- a/docs/docs/using-reactxp.md +++ b/docs/docs/using-reactxp.md @@ -15,4 +15,29 @@ ReactXP assumes that your main web page will have a DOM element container called The main module is assumed to be called "RXApp", and it must be registered as such by the native code. Refer to the sample app for how to register the module in Android and iOS. +## TypeScript Support +ReactXP is written in TypeScript and includes TypeScript type definition (".d.ts") files for the library. + +## TSLint Support + +ReactXP includes several [tslint](https://www.npmjs.com/package/tslint) custom rules that can be used in your project. + +To use these rules, modify your tslint.json file to point to the rules within the reactxp dist directory, as follows. + +``` + "rulesDirectory": [ + "./node_modules/reactxp/dist/tslint" + ] +``` + +The following tslint rules are provided: + +### grouped-import +This rule enforces that all ambient (non-relative) module imports are grouped together and are above the group of relative imports. + +### incorrect-this-props +This rule checks for common errors in referencing ```this.props``` within methods that pass ```props``` as an input parameter. + +### no-unreferenced-styles +This rule detects and reports any unreferenced entries within a ```_styles``` array. diff --git a/docs/img/tests/bulb.jpg b/docs/img/tests/bulb.jpg new file mode 100644 index 000000000..dc96c3d33 Binary files /dev/null and b/docs/img/tests/bulb.jpg differ diff --git a/docs/img/tests/globe.png b/docs/img/tests/globe.png new file mode 100644 index 000000000..be49a8838 Binary files /dev/null and b/docs/img/tests/globe.png differ diff --git a/docs/img/tests/heart.gif b/docs/img/tests/heart.gif new file mode 100644 index 000000000..844a7bd36 Binary files /dev/null and b/docs/img/tests/heart.gif differ diff --git a/docs/versions/version_history.md b/docs/versions/version_history.md index 86004cdac..74bf05d63 100644 --- a/docs/versions/version_history.md +++ b/docs/versions/version_history.md @@ -11,240 +11,578 @@ redirect_from: ## ReactXP Versioning ### Versioning Strategy -A new version of ReactXP will be released a monthly basis (approximately), following the same general update timeline of React Native. Each new version will get its own branch, allowing consumers of the library to take a dependency on a stable code base. +A new version of ReactXP will be released periodically following the same general update timeline of React Native. Each new version will get its own branch, allowing consumers of the library to take a dependency on a stable code base. - -### Version History - -#### Version 0.46.5 of reactxp -_Released 31 Oct 2017_ - -Added Android "mode" prop to Picker. -Added type definitions for RX.Stateless and RX.ComponentBase. -Updated to React 16.0.0 and React-Dom 16.0.0. -Added RX.UserInterface.registerRootView API to allow registration of secondary views. Also added rootViewId option to RX.Modal and RX.Popup so they can be displayed on secondary views. -Fixed bug in focus restoration on web implementation. -Replaced use of deprecated BackAndroid with BackHandler, avoiding deprecation warnings. -Fixed bug in RX.Button RN implementation where opacity was not property restored after changing disabled prop. - -#### Version 0.46.3 of reactxp -_Released 7 Oct 2017_ - -Added missing focus() method to RX.Animated.View interface. -Exported RX.AnimatedImage, RX.AnimatedText, RX.AnimatedTextInput, and RX.AnimatedView. -Added accessibilityLiveRegion prop to ViewProps for Android and web. -Exported explicit types for ShadowOffset, ScrollIndicatorInsets. -Fixed crash in web RootView when clicking on a popup anchor. -Fixed race condition in hover of Button on web. - -#### Version 0.2.2 of reactxp-video -#### Version 1.0.13 of reactxp-navigator -#### Version 0.2.7 of reactxp-imagesvg -#### Version 0.1.6 of reactxp-virtuallistview -_Released 21 Sep 2017_ - -Updated for RN 0.46 compatibility. -Removed custom react.d.ts and react-dom.d.ts files in favor of public versions. - -#### Version 0.46.2 of reactxp -_Released 21 Sep 2017_ - -Added onContextMenu support on web for Text components. -Exposed attributes to make menus and listboxes accessible on web. -Added new RX.Animated.createValue and RX.Animated.interpolate methods. The old way of instantiating a value and creating an interpolation will be deprecated going forward. -Made a breaking change to Alert.show interface - combined optional parameters into an AlertOptions interface. This will allow for better extensibility in the future. -Updated RN dependency to 0.46. -Removed custom react.d.ts and react-dom.d.ts files in favor of public versions. - -#### Version 0.46.0_rc.2 of reactxp -_Released 19 Sep 2017_ - -Changed RX.Link props to make url mandatory. -Added new Alert implementation for web. It now presents a modal-based themable dialog box. -Fixed bug in ScrollView styles from previous release. -Exposed aria-checked property on button type for web. -Added key attribute to KeyboardEvent. -Fixed bug in web code where onScrollBeginDrag and onScrollEndDrag were called unconditionally even if they were undefined. -Enabled strict null checks in TS compiler and fixed a number of bugs that were exposed. - -#### Version 0.46.0_rc.1 of reactxp -_Released 5 Sep 2017_ - -First pre-release version of 0.46. -Removed Navigator component and moved to an extension. -Fixed style definition for ScrollView so it doesn't include child-related flexbox styles, which aren't supported. - -#### Version 0.42.0 of reactxp -_Released 5 Sep 2017_ - -Removed rc from version. - -#### Version 0.42.0_rc.25 of reactxp -_Released 18 Aug 2017_ - -On web, if there's a queued onScroll event when the scroll position is manually set, cancel the onScroll. - -#### Version 0.42.0_rc.24 of reactxp -_Released 9 Aug 2017_ - -Added accessibility support for GestureView. -Fixed bug in web version that prevented animated fontSize from working. - -#### Version 0.42.0_rc.22 of reactxp -_Released 30 July 2017_ - -On RN platforms, initialProps is now passed to the main view. -Added new PopupOptions field preventDismissOnPress that prevents the popup from being dismissed implicitly when the user clicks or taps outside of the popup or the anchor. -Fixed bug in web implementation of TextInput where border styling was not honored. -Fixed bug on Android that allowed presses to background of Modal to go through. - -#### Version 0.42.0_rc.20 of reactxp -_Released 15 July 2017_ - -Updated to TypeScript 2.4, which caught several bugs in the ReactXP code. -Made Styles.combine much more flexible - it now supports arbitrarily nested arrays of styles. -Changed Network API namespace for detecting network type so it's consistent with other ReactXP APIs. Added documentation. - -#### Version 0.1.6 of reactxp-video -_Released 15 July 2017_ - -Updated to TypeScript 2.4 and made changes to work with latest ReactXP core. - -#### Version 0.2.4 of reactxp-imagesvg -_Released 15 July 2017_ - -Updated to TypeScript 2.4 and made changes to work with latest ReactXP core. - -#### Version 0.42.0_rc.18 of reactxp -_Released 13 July 2017_ - -Fixed runtime crash when running web implementation in Electron. -Added a way to provide screen reader focus to TextInput on web. - -#### Version 0.42.0_rc.17 of reactxp -_Released 4 July 2017_ - -Added ability to set accessibility focus for text input controls. -Added support for iOS-specific ActivationState for RN extensions. - -#### Version 0.42.0_rc.16 of reactxp -_Released 30 June 2017_ - -Fixed another bug in handling of default border width on web. -Added setFocusRestricted and setFocusLimited methods and support for nested keyboard focus on web. -Added isNavigatingWithKdyboard method and keyboardNavigationEvent. - - -#### Version 0.42.0_rc.12 of reactxp -_Released 16 June 2017_ - -Added support for new limitFocusWidth prop for constraining keyboard focus. -Fixed bug in handling of mailto URLs on web in the Link component. -Added support for flexGrow, flexShrink, and flexBasis props. - - -#### Version 0.42.0_rc.11 of reactxp -_Released 13 June 2017_ - -Fixed bugs in web implementation of focus manager. -Added new API (enableTouchLatencyEvents) and event (touchLatencyEvent) in UserInterface namespace for detecting delays in touch event handling. -Fixed crash in native implementation of Link component that resulted in uncaught exception for some types of links. -Fixed flexDirection style default for web implementation in Image component. -Fixed inconsistency in handling of borders between web and RN when borderStyle is not specified. +Following semver rules, the major version (the first number in the version string) will be incremented for breaking changes. The minor version (the second number) will be incremented for major new functionality that does not break existing contracts or behaviors. -#### Version 0.42.0_rc.10 of reactxp -_Released 25 May 2017_ - -Added new International API namespace for controlling right-to-left mirroring behavior. - - -#### Version 0.1.2 of reactxp-virtualistview -_Released 23 May 2017_ - -Republished because index files were missing in previous publish. - - -#### Version 0.42.0_rc.9 of reactxp -_Released 17 May 2017_ - -Fixed bug in Navigator that caused crash in hello-world sample. - - -#### Version 0.42.0_rc.8 of reactxp -_Released 16 May 2017_ - -Removed Profiling API namespace and dependency on react-addons-perf. - - -#### Version 0.1.1 of reactxp-virtualistview -_Released 11 May 2017_ - -Republished because "dist" directory was missing in previous publish. - - -#### Version 0.1.2 of reactxp-video -_Released 11 May 2017_ - -Published first version of reactxp-video extension. - - -#### Version 0.2.0 of reactxp-imagesvg -_Released 10 May 2017_ - -Switched from old version of react-native-art-svg to latest version of react-native-svg. - - -#### Version 0.42.0_rc.5 of reactxp -_Released 10 May 2017_ - -Fixed incorrect import path (using wrong case). -Fixed bug in native View implementation - was using stale props. -Added importantForLayout prop on View (web specific). -Fixed bug in native NavigatorExperimentalDelegate - was using wrong props. - - -#### Version 0.42.0_rc.4 of reactxp -_Released 27 Apr 2017_ - -Changed web implementation of Text to prevent copying text to clipboard. -Eliminated the need to specify box-sizing CSS in external CSS file. -Fixed accessibility focus bugs. - - -#### Version 0.42.0_rc.3 of reactxp -_Released 26 Apr 2017_ - -Added onLongPress prop for Link. -Fixed accessibility bug relating to Modal dialogs. - - -#### Version 0.42.0_rc.2 of reactxp -_Released 18 Apr 2017_ - -Added missing box-sizing CSS directives for web. -Fixed bug in native implementation of View related to accessibility. - - -#### Version 0.1.0 of reactxp-imagesvg -_Released 26 Apr 2017_ - -Published first version of reactxp-imagesvg extension. - - -#### Version 0.42.0_rc.1 of reactxp -_Released 9 Apr 2017_ - -Updated project to use recent versions of React (15.5.3) and React Native (0.42.3). - +### Version History -#### Version 0.34.3 of reactxp -_Released 7 Apr 2017_ +#### Version 2.0.0 of reactxp - _30 November 2019_ +* All releases and notes going forward will be tracked on the [Github ReactXP Releases page](https://github.com/microsoft/reactxp/releases) + +#### Version 2.0.0-rc.2 of reactxp-video - _9 October 2019_ +* Updated react-native-video to 4.X + +#### Version 2.0.0-rc.2 of reactxp-webview - _12 September 2019_ +* Upgraded react-native-webview dependency + +#### Version 2.0.0-rc.1 of reactxp - _27 July 2019_ +* Adopted new major version number to reflect breaking changes with netinfo and webview. +* No other functionality since 1.7.0-rc.1 was published. + +#### Version 1.7.0-rc.1 of reactxp-video, reactxp-imagesvg, reactxp-navigation - _14 July 2019_ +* No new functionality, just version and dependency updates. + +#### Version 1.7.0-rc.1 of reactxp - _14 July 2019_ +* #1077: Added longPress support for web. +* #1080: Addes upport for delayLongPress on web. +* #1079: Fixed bug that caused onTouchMove not to trigger on mobile web. +* #1082: Added support on web for onTouchStart, onTouchEnd, and onTouchCancel props for RX.View. +* #1087: Added support on web for onHoverEnd. +* #1059: Improved support for RN 0.59. +* #1089: Added support on web for onTouchMoveCapture and onTouchStartCapture props of RX.View. +* #1098: Fixed bug on web where reference to HTML element was not released properly, resulting in leak. +* #1088: Added support on web for scrollEnabled prop in RX.ScrollView. +* #1098: Fixed bug in handling of images on RN platforms. +* #1118: Fixed bug on web related to pan gestures. +* #1114: Fixed crash on Android relating to TextInput event processing. +* #1102: Fixed bug on web where animated properties were not properly updated if they were interpolated. +* #1117: Added support on web for blockPointerEvents prop on RX.View. +* #1101: Extracted RX.WebView out of ReactXP core into an extension. +* #1091: Fixed bug on web in onPressIn processing where event could get triggered twice. + +#### Version 2.0.0 of reactxp-virtuallistview - _6 Apr 2019_ +* #1073: Removed internal string-based refs with React.RefObject. + +#### Version 1.6.1 of reactxp - _23 Mar 2019_ +* #1062: Fixed TextInput defaultValue not working on native platforms +* #1060: Fixed Ref type. +* #1058: Fixed ref assert on Windows. + +#### Version 1.6.1 of reactxp-video - _23 Mar 2019_ +* #1066: Fixed video extension to support react-native local assets. + +#### Version 1.6.1 of reactxp-navigation - _23 Mar 2019_ +* #1063: Fixed regression in reactxp-navigation. + +#### Version 1.6.0 of reactxp-imagesvg, reactxp-navigation, reactxp-video - _16 Mar 2019_ +* No new features; updated dependencies. + +#### Version 1.6.0 of reactxp - _16 Mar 2019_ +* No new features; updated dependencies. + +#### Version 1.6.0-rc.4 of reactxp - _15 Mar 2019_ +* #1055: Fixed crash due to incompatibilty with newly-released RN 59. + +#### Version 1.6.0-rc.3 of reactxp - _10 Mar 2019_ +* #891: Fixed bad interaction between RX.Clipboard.getText() and iOS Safari. + +#### Version 1.6.0-rc.2 of reactxp - _9 Mar 2019_ +* #1041: Fixed textDecorationStyle and textDecorationColor on web. +* #1042: Fixed transform rotate styles on web so they take a unit (e.g. "deg") for consistency with RN. +* #1040: Fixed auto-dismissing popups on the web. +* #1026: Changed margin and padding style combination rules on web to match RN. + +#### Version 1.6.0-rc.1 of reactxp - _17 Feb 2019_ +* #961: Fixed crash when calling setScrollTop/Left on native version of ScrollView. +* #972: If blurOnSubmit is specified on a TextInput, the code now respects that value. +* #974: Fixed bug in native Button implementation where 'false' style would be passed when disableTouchOpacityAnimation was specified. +* #980: Fixed bug in web implementation of onLongPress. +* #976: Made multiline TextInput growth behavior on web match native. +* #984: Added code to catch exception in web implementation of Storage.setItem method. +* #996: Added stronger typings for ref callbacks. +* #993: Added support for mediaPlaybackRequiresUserAction and allowsInlinedMediaPlayer props for WebView. +* #957: Added context mode to the popup container handling type list. +* #994: Removed msHyphens css property in web implementation of Text. +* #1001: Fixed units for rotateZ translation type for web animations. +* #1004: Fixed bug that resulted in crash when ReactXP ran in node (test) environment. +* #1006: Made selectItemKey scrollTo behaviour configurable - scrolling isn't always desired. +* #1016: View responder events props are now triggered properly. +* #1024: Added more mouse cursor types for web version of GestureView. +* Added support for interpolated animation values that have angle units (e.g. "90deg") on web. + +#### Version 2.0.0-rc.3 of reactxp-virtuallistview - _30 Jan 2019_ +* #1006: Make selectItemKey scrollTo behaviour configurable - scrolling isn't always desired +* #1007: Perf Improvements + +#### Version 2.0.0-rc.2 of reactxp-virtuallistview - _15 Jan 2019_ +* #989: Auto-scroll VLV on mount when initialScrollKey prop is provided +* #989: Fix keyboard scrolling bugs when non-keyboard-navigable items are interspersed with keyboard-navigable items + +#### Version 2.0.0-rc.1 of reactxp-virtuallistview - _11 Jan 2019_ +* #944: Rework VirtualListView for improved accessibility/performance (this contains breaking API changes - see documentation for new API) + +#### Version 1.5.0 of reactxp-imagesvg, reactxp-navigation, reactxp-video, reactxp-virtuallistview - _1 Dec 2018_ +* No new features; updated dependencies. + +#### Version 1.5.0 of reactxp - _1 Dec 2018_ +* #935: Maded ReactXP compatible with React.Fragment. +* #933: Reset VoiceOver queue when app goes inactive or in background (iOS and Windows). +* #939: Added keyboard event mapping for kePress handling in View (Windows and MacOS). +* #941: Updated RX.Animated.InterpolatedValue to allow for chaining interpolations. +* #942: Added key mappings for MacOS and wired onKeyPress for RX.View. +* #943: Added focus and blur calls for RX.Button, RX.Link, RX.Text and RX.View. +* #946: Fixed crashing bug in accessibility for iOS and MacOS. +* #949: Added onFocus, onBlur and onKeyPress support for GestureView. +* #948: Respect negative tabIndex in Button on MacOS. +* #953: Wired up tabIndex prop for web implementation of RX.TextInput. + +#### Version 1.5.0-rc.4 of reactxp - _18 Nov 2018_ +* #909: Eliminated not-prebound callbacks in view resize detector on web (perf improvement). +* #912: Fixed VoiceOver iOS 12 issue. +* #913 and #923: Added key codes that are specific for MacOS. +* #916: Added basic tabindex handling on views for MacOS. +* #920: Removed deep comparison on every button prop change (perf improvement). +* #917: Added onKeyDown support for MacOS ScrollView. +* #922: Removed undocumented and broken (onRN) API: addToScrolLeft and addToScrollTop on RX.ScrollView. +* #928: Fixed bug in _buildInternalProps of View relating to tabIndex. +* #927: Fixed drag support on MacOS. +* Added CONTRIBUTION guide. + +#### Version 1.5.0-rc.1 of reactxp-virtuallistview - _11 Nov 2018_ +* #899: Fix web accessibility +* #902: Mac accessibility improvements (keyboard focus). + +#### Version 1.5.0-rc.3 of reactxp - _11 Nov 2018_ +* #898: Ensure taht onKeyDown/Focus/Blur events are sent from ScrollView. +* #895: On Windows, make FocusManager track View instances with negative tabIndex. +* #901: Optimization on native platforms: when there are no accessibilityTraits, don't create an additional unneeded array. +* #902: Mac accessibility improvements (keyboard focus). + +#### Version 1.5.0-rc.2 of reactxp - _28 Oct 2018_ +* Fixed regression introduced recently in web version of ScrollView. + +#### Version 1.5.0-rc.1 of reactxp - _27 Oct 2018_ +New functionality: +* #848: Added support for RTL (right-to-left) change event on native platforms. +* #843: Added new AlertOption preventDismissOnPress. +* #847: Added support for Animated.Event, which allows animations to be associated with scroll events. +* #868: Added support for placeholder text color on web platform. +Bug fixes: +* #833: Eliminated rerender of app when mousing over popups. +* #846: Disabled mouse gestures in main view when a modal dialog is overlaying the main view. +* #854: Removed draggable="false" in web implementation of View, since this is the default value. +* #853: Emulate cache-control: max stale on iOS. +* #869: Eliminate excess focus calls. +* #877 and #875: Fixed crashes relating to popups due to race condition in unmounting. +* #873: Fixed scroll view focus issue on MacOS. +* Fixed several "hanging promises" that didn't properly deal with error conditions. + +#### Version 1.4.0 of reactxp - _30 Sep 2018_ +* Added the ability to programmatically retrieve the text selection for RX.Text (if selectable attribute is true). Includes test cases in RXPTest sample. +* Added drag and drop capabilities to RX.View (including onDragStart, onDrag, onDragEnd props). Includes test cases in RXPTest sample. + +#### Version 1.4.0-rc.1 of reactxp-navigation - _21 Sep 2018_ +* Changed renderScene to accept a return value of null rather than undefined, making it consistent with other render functions. + +#### Version 1.4.0-rc.2 of reactxp - _15 Sep 2018_ +* Fixed bug #800: If there are only cached popups and no visible one the main remains inaccessible for screen readers. +* Fixed bug #815: Show warning in console if disallowed style combinations appear. + +#### Version 1.4.0-rc.1 of reactxp - _9 Sep 2018_ +* Worked around change in recent versions of RN that removed support for Images with children. +* Changed announceForAccessibility implementation to use Assertive live region type instead of Polite. +* In web implementation of RX.Image, always show the img tag if XHR request option is used. +* Fixed bug #744: On web implementation, styling behavior differed between developmenta nd production. +* Added support for the new React.RefObject variant of ref prop. +* Added support for multi-window apps to RX.Alert. +* Added support for onLongPress to RX.GestureView. +* Fixed bug #793: In web implementation, cursor type was overridden in some cases. +* Added useWebKit prop for native RN.WebView in prep for NR 0.57 on iOS. +* Fixed bug that caused testID not to be set properly for RX.View instances. + +#### Version 1.3.2 of reactxp-imagesvg - _25 Aug 2018_ +* Added support for SvgRect children within SvgImage. + +#### Version 1.3.1 of reactxp-imagesvg - _7 Aug 2018_ +* Fixed bug in native implementation that caused runtime warning every time SvgPath was used. + +#### Version 1.3.2 of reactxp - _2 Aug 2018_ +* Fixed bug #745: WebView.onMessage receives additional props which are not defined in Types.WebViewMessageEvent. +* Fixed bug #746 relating to cursor overrides for buttons on the web implementation. +* Fixed bug #749: Set size attribute of input HTML element to 1. +* Fixed bug #753: isRightMouseButton implementation that works also on Mac. +* Fixed bug #752: Accessibility fix for Clipboard. +* Fixed bug #756: Prevent a crash during onLayout handling on web. +* Fixed bug #761: Update usages of findDOMNode to indicate that it returns null. +* Fixed bug #767: buttonStyles may be undefined; fixed inconsistency in onAccessibilityTapIOS definition for Button and View. +* Fixed regression in Timers.ts. Some environments don't define "global" and use "window" instead for the built-in timer functions. +* Use semver for reactxp dependencies. +* Feature #764: Add support for Android WebView compatibility modes. + +#### Version 1.3.1 of reactxp-virtuallistview - _2 Aug 2018_ +* Added support for testId prop. + +#### Version 1.3.2 of reactxp - _7 Jul 2018_ +* Updated custom tslint rule groupedImportRule to treat imports starting with '@' as relative rather than ambient. +* Made 'auto' a valid resizeMode for images in web implementation. +* Added support for 'title' prop on RX.TextInput. + +#### Version 1.3.0 of reactxp-imagesvg, reactxp-navigation, reactxp-video, reactxp-virtuallistview - _28 Jun 2018_ +* No new features; updated dependencies. + +#### Version 1.3.0 of reactxp - _28 Jun 2018_ +* Added support for function keys in native desktop implmenetations. +* Fixed recent regression that caused a crash when using the web implementation in a non-browser environment like node. +* Reverted change in behavior on web implementation of ActivityState.Inactive. This state is no longer used on the web, as before 1.3.0-rc.4. + +#### Version 1.3.0-rc.6 of reactxp - _25 Jun 2018_ +* Added support for testId prop to all reactxp components. On native, it uses testID. On web, it adds a data-test-id attribute to the node. +* Added three new tslint custom rules that are useful for reactxp projects. + +#### Version 1.3.0-rc.5 of reactxp - _24 Jun 2018_ +* Added missing definition for getMetadata method in RX.Image. +* Implemented RX.International methods for web platform. + +#### Version 1.3.0-rc.4 of reactxp - _19 Jun 2018_ +* Enabled context menu on keyboard input in Windows UWP implementation. +* On web implementation, augmented AppActivityState. Inactive state now indicates that main window is not in focus. +* On web implementation, eliminated dependency on ifvisible library, shrinking the footprint of reactxp. + +#### Version 1.3.0-rc.3 of reactxp - _16 Jun 2018_ +* [Breaking Change] Removed hideDeleteButton prop in RX.TextInput in favor of clearButtonMode prop, which applies to iOS and Windows UWP. + +#### Version 1.3.0-rc.2 of reactxp - _14 Jun 2018_ +* [Breaking Change] Renamed several methods in RX.Animated.ValueListener that were meant to be private. +* Improved screen reader support in Windows UWP implementation. +* On iOS implementation, automatically set decelerationRate to "fast" if snapToInterval is set. +* Added hideDeleteButton prop to RX.TextInput for Windows UWP. + +#### Version 1.3.0-rc.1 of reactxp - _13 Jun 2018_ +* Fixed accessibility issues with screen reader in Windows UWP implementation. +* Removed shouldRasterizeIOS prop on RX.Image. It was never supported in RN, so it was just a no-op. +* Fixed bug in RX.Network.getType() which returned the wrong response if the device was connected to ethernet on Android. + +#### Version 1.3.0-rc.0 of reactxp - _10 Jun 2018_ +* Fixed a few bugs in keyboard focus handling for Windows UWP. +* Web implementation of RX.Image now uses credentials for image fetches if origin header is specified. +* Added support for text shadows in RX.Text (shadowColor, shadowOffset, shadowRadius style attributes). +* Fixed keyboard navigation logic for multi-root-view case. +* Wired up tooltips in web implementation of RX.Button, RX.Image, RX.Link, and RX.View (title prop). +* Extended RX.UserInterface.measureWindow to support multi-root-view case. It now takes an optional rootViewId parameter. +* Added drag and drop handler support for Mac OS. +* Added new static API RX.Image.getMetadata that returns dimensions of an image. +* Avoided the use of the deprecated RN.NetInfo "change" event in favor of "connectionChange" so RN doesn't emit warning. +* Added back parameter to onBlur event handler that was incorrectly removed in version 1.2.x. + +#### Version 1.2.1 of reactxp - _24 May 2018_ +* Wired up onPaste handler for Windows implementation. +* Fixed bug that resulted in cached popups to appear when they shouldn't. +* Fixed bug in web implementation of RX.ScrollView that resulted in incorrect screen reader announcements. + +#### Version 1.2.0 of reactxp-imagesvg, reactxp-navigation, reactxp-video, reactxp-virtuallistview - _22 May 2018_ +* Automatically suppressed system context menu for selectable RX.Text items on Windows if containing view has onContextMenu handler. + +#### Version 1.2.0 of reactxp - _22 May 2018_ +* Automatically suppressed system context menu for selectable RX.Text items on Windows if containing view has onContextMenu handler. + +#### Version 1.1.2-rc.3 of reactxp - _21 May 2018_ +* Fixed bug in RX.Linking.getInitialUrl, which was returning null rather than undefined for the url in some cases. +* Added support for Dilaog trait to trigger yes-dont-hide importantForAccessibility behavior in Windows implementation. +* Fixed UWP accessibility announce to make it act the same way as Android. +* Create correct Animated.TextInput for Windows. + +#### Version 1.1.2-rc.2 of reactxp - _15 May 2018_ +* Improved keyboard focus support. Added focus, blur and requestFocus methods to several existing components. Added new focusArbitrator prop to RX.View, which allows callback to arbitrate between multiple children that are requesting autofocus. +* Fixed bug that caused group view children to be invisible to UI automation. +* Improved keyboard support for Windows implementation. + +#### Version 1.1.2-rc.1 of reactxp - _9 May 2018_ +* Fixed bug in Windows implementation that prevented RX.Input.keyDownEvent from being dispatched. +* Fixed bugs in Windows implementation that reported wrong key codes for keyboard events. +* Fixed focus management for cacheable popups in Windows implementation. +* Fixed type definitions of GestureView, ScrollView and WebView. They were incorrectly extending ViewBase, which pulled in a number of unsupported props. +* Fixed bug that caused cached popups to appear on screen when not appropriate. +* Added onContextMenu prop to GestureView. +* Added accessibility trait for ListItem. +* In Windows implementation, use RNW.Hyperlink for rendering RX.Link. +* Removed "justifyEnd" prop from RX.ScrollView. It was never implemented as documented. +* Added useSafeInsets prop onR X.View to support rendering within safe area on iOS. +* Fixed bug RX.StatusBar.setBarStyle where animated parameter was not properly passed to RN. +* Added onContextMenu to RX.Link. + +#### Version 1.1.1 of reactxp - _13 Apr 2018_ +* Fixed reentrancy issue in popup support. Displaying a popup from within the onDismiss callback was recently broken. +* Added disabledOpacity prop for RX.Button component. +* Improved handling of RX.Clipboard.setText on web. It now properly handles carriage returns. +* Fixed TextInput focusability after focus restriction on Windows. +* Fixed accessibility issue related to voice over on web. + +#### Version 1.0.18 of reactxp-navigation - _10 Apr 2018_ +* Fixed bug in web implementation that caused a problem when popping multiple items from the navigation stack. + +#### Version 0.2.10 of reactxp-imagesvg, 1.0.17 of reactxp-navigation, 0.2.5 of reactxp-video, 0.1.9 of reactxp-virtuallistview - _4 Apr 2018_ +* Rebuilt using reactxp 1.1.0. + +#### Version 1.1.0 of reactxp - _4 Apr 2018_ +* Added workaround to enable the keyboard navigation mode when the screen reader is used. + +#### Version 1.1.0-rc.2 of reactxp - _28 Mar 2018_ +* Fixed bug in web implementation of animation where completion callback was called multiple times in some cases. + +#### Version 1.1.0-rc.1 of reactxp - _26 Mar 2018_ +* Added support for "cacheable" popups. This is useful for popups that involve many views and are costly to recreate from scratch. +* Fixed keyboard handler in RX.Link, it was defferring to base class only when onPress was defined, and that was wrong. +* Fixed bug in native implementation of TextInput where selection was sometimes lost. +* Fixed TextInput reference for focus control on windows. +* Implemented hidden scroll indicators in web/ScrollView. + +#### Version 1.0.2 of reactxp - _16 Mar 2018_ +* Fixed bug in web TextInput implementation that resulted in a console warning with the latest versions of ReactJS. +* Fixed bug in native Button implementation that resulted in corrupted styles. +* Fixed accessibility (screen reader) bug in web implementation. + +#### Version 1.0.1 of reactxp - _5 Mar 2018_ +* Moved event handlers from ViewProps to ViewPropsShared so AnimatedView has them too. +* Fixed recent regression in handling of popups in native implementation. +* Events passed to onPress and onLongPress now include touch or mouse coordinates. + +#### Version 0.2.9 of reactxp-imagesvg, 1.0.16 of reactxp-navigation, 0.2.4 of reactxp-video, 0.1.8 of reactxp-virtuallistview - _2 Mar 2018_ +* Rebuilt using reactxp 1.0.0 and latest typescript compiler version. + +#### Version 1.0.0 of reactxp - _2 Mar 2018_ +* Filled in fields for MouseEvent on web. +* Fixed a few style leaks in web implementation. + +#### Version 1.0.0-rc.1 of reactxp - _28 Feb 2018_ +* Improved accessibility handling for Button. +* Added select() method to RX.Platform namespace to make it easier to implement platform-specific behavior. +* Improved accessibility performance. +* Improved performance by avoiding triggering synchronous layout on web. +* Fixed behavior of onContextMenu. +* Removed unused "type" field from RX.CommonProps interface. +* Updated typescript compiler to 2.7.2 and enabled strictPropertyInitialization. +* Added ability to set limitFocusWithin without automatically setting aria-hidden=true on web. +* Implemented RX.Linking APIs for Windows UWP platform. +* Removed "currentTarget" from SyntheticEvent. +* Added coordinates/modifiers/button information to MouseEvent definition. + +#### Version 1.0.0-alpha.2 of reactxp - _21 Feb 2018_ +* Switched to new versioning scheme that's independent of RN. +* Updated default RN dependency from 0.51.x to 0.53.x, although backward compatibility is maintained. +* Added support for numeric keyboards in mobile browsers. +* Fixed announceForAccessibility API for Mac. +* Added MacOS implementation of Button and Animated. +* Added valuenow attribute for slider role support. +* Fixed bug in web implementation of Animated where it wasn't properly managing listener subscriptions when animated styles were added to (or removed from) an animated component. +* Fix random Android crashes when Talkback is enabled. +* Fixed bug in web animation that caused certain CSS properties not to animate correctly because transition was specifying the attribute using camel case rather than CSS (hyphenated) case. This affected attributes like "backgroundColor". +* Removed parameter from onBlur event. +* Fixed bug in RX.TextInput that affected Windows version: Pass selection in render only after explicitly set. +* Added right-click support for Windows platform. +* Added more accessibility support for Windows platform. +* Use white-space:pre for the aria-live region. + +#### Version 0.51.1 of reactxp - _19 Jan 2018_ +* Fixed regression in native implementation of Animated.View's blur() method. + +#### Version 0.2.3 of reactxp-video, 1.0.15 of reactxp-navigator, 0.2.8 of reactxp-imagesvg, 0.1.7 of reactxp-virtuallistview - _18 Jan 2018_ +* Updated for RN 0.51 compatibility. + +#### Version 0.51.0 of reactxp - _18 Jan 2018_ +* Fixed focusable View condition for VoiceOver in web implementation. +* Exposed web-specific ariaRoleDescription prop to work around other VoiceOver issues. +* Updated RN for Windows UWP dependency. +* Fixed recent regression that broke focus and blur calls in iOS and Android implementations of AnimatedTextInput. + +#### Version 0.51.0-alpha.9 of reactxp - _17 Jan 2018_ +* Removed console error related to animations of values not currently associated with any mounted component. It was too noisy. + +#### Version 0.51.0-alpha.8 of reactxp - _16 Jan 2018_ +* Fixed bug in Windows UWP implementation related to selection ranges in TextInput. +* Fixed screen reader issue in Mac implementation. +* Removed ```textAlign``` prop from TextInput. It was extraneous, since it's already supported as a style attribute. +* Updated Windows UWP dependency to use the latest version of RN for UWP. +* Worked around issue with screen readers on Chrome browsers. +* Added currentTarget field back to SyntheticEvent. +* Added support for "switch" aria type (web implementation). +* Fixed recent regression in web animation code. + +#### Version 0.51.0-alpha.5 of reactxp - _11 Jan 2018_ +* Eliminated limitation within RX.Button where only one child element was allowed. +* Fixed regression where native implementation of RX.View with onPress handler didn't provide touch feedback. + +#### Version 0.51.0-alpha.4 of reactxp - _10 Jan 2018_ +* Added code to native implementation of RX.Network so it works with versions of RN before and after 0.48.x. +* Fixed regression in web implementation of RX.TextInput. +* Fixed bug that caused incorrect behavior of RX.Modal on native platforms. + +#### Version 0.51.0-alpha.2 of reactxp - _9 Jan 2018_ +* Fixed bug in native implementation of RX.ActivityIndicator. It wasn't properly handling the delay prop. +* Added support in web implementation of RX.TextInput for custom keyboard types on mobile web browsers. +* Added focus and keyboard navigation support for native UWP platform. +* Added support for injection of HTML content into RX.WebView. +* Added support for postMessage and onMessage handler in RX.WebView for bidirectional communication. + +#### Version 0.51.0-alpha.1 of reactxp - _6 Jan 2018_ +* Fixed break in device dimension change event due to change in RN. +* Removed use of RX.Button implementation within RX.View for native-common implementation. +* Fixed bug in web implementation of RX.Clipboard.getText. It shouldn't throw. +* Fixed timing bug in web implementation of GestureView. +* Fixed popup positioning for right-to-left languages in native-common implementation. +* Fixed bug in web implementation of TextInput that caused assertion in React. +* Breaking change: Removed 'cursor' prop from RX.Button. It was redundant with the 'cursor' style. +* New feature: RX.Input.key[Up|Down]Event now allow event subscribers to cancel the event. +* New feature: Changed RX.Modal.isDisplayed to accept undefined parameter, in which case it determines whether _any_ modal is displayed. +* New feature: Added RX.Popup.isDisplayed method. +* Reimplemented web implementation of animation APIs. Removed many limitations of previous implementation and fixed several bugs. Documented remaining limitations. +* Fixed bug in web implementation of RX.TextInput that resulted in assertions within React. +* Fixed bug in web implementation of RX.Picker. It wasn't correctly combining styles. +* Added support in web implementation of RX.TextInput for keyboard type (applicable on mobile web browsers). +* Removed use of deprecated RX.NetInfo.fetch method. + +#### Version 0.46.6 of reactxp - _13 Dec 2017_ +* Fixed potential crash in web implementation of RX.ScrollView. +* Fixed bug in UWP implementation of RX.Popup, allowing background to be clickable. +* In web implementation of RX.ScrollView, added support for clicking on scroll bar to adjust position of thumb. +* Added dev warning when using nested RX.Button items. +* Fixed a potential crash in web implementation of RX.GestureView. +* Implemented drag-and-drop support in UWP implementation of RX.View. + +#### Version 0.46.5 of reactxp - _31 Oct 2017_ +* Added Android "mode" prop to Picker. +* Added type definitions for RX.Stateless and RX.ComponentBase. +* Updated to React 16.0.0 and React-Dom 16.0.0. +* Added RX.UserInterface.registerRootView API to allow registration of secondary views. Also added rootViewId option to RX.Modal and RX.Popup so they can be displayed on secondary views. +* Fixed bug in focus restoration on web implementation. +* Replaced use of deprecated BackAndroid with BackHandler, avoiding deprecation warnings. +* Fixed bug in RX.Button RN implementation where opacity was not property restored after changing disabled prop. + +#### Version 0.46.3 of reactxp - _7 Oct 2017_ +* Added missing focus() method to RX.Animated.View interface. +* Exported RX.AnimatedImage, RX.AnimatedText, RX.AnimatedTextInput, and RX.AnimatedView. +* Added accessibilityLiveRegion prop to ViewProps for Android and web. +* Exported explicit types for ShadowOffset, ScrollIndicatorInsets. +* Fixed crash in web RootView when clicking on a popup anchor. +* Fixed race condition in hover of Button on web. + +#### Version 0.2.2 of reactxp-video, 1.0.13 of reactxp-navigator, 0.2.7 of reactxp-imagesvg, 0.1.6 of reactxp-virtuallistview - _21 Sep 2017_ +* Updated for RN 0.46 compatibility. +* Removed custom react.d.ts and react-dom.d.ts files in favor of public versions. + +#### Version 0.46.2 of reactxp - _21 Sep 2017_ +* Added onContextMenu support on web for Text components. +* Exposed attributes to make menus and listboxes accessible on web. +* Added new RX.Animated.createValue and RX.Animated.interpolate methods. The old way of instantiating a value and creating an interpolation will be deprecated going forward. +* Made a breaking change to Alert.show interface - combined optional parameters into an AlertOptions interface. This will allow for better extensibility in the future. +* Updated RN dependency to 0.46. +* Removed custom react.d.ts and react-dom.d.ts files in favor of public versions. + +#### Version 0.46.0_rc.2 of reactxp - _19 Sep 2017_ +* Changed RX.Link props to make url mandatory. +* Added new Alert implementation for web. It now presents a modal-based themable dialog box. +* Fixed bug in ScrollView styles from previous release. +* Exposed aria-checked property on button type for web. +* Added key attribute to KeyboardEvent. +* Fixed bug in web code where onScrollBeginDrag and onScrollEndDrag were called unconditionally even if they were undefined. +* Enabled strict null checks in TS compiler and fixed a number of bugs that were exposed. + +#### Version 0.46.0_rc.1 of reactxp - _5 Sep 2017_ +* First pre-release version of 0.46. +* Removed Navigator component and moved to an extension. +* Fixed style definition for ScrollView so it doesn't include child-related flexbox styles, which aren't supported. + +#### Version 0.42.0 of reactxp - _5 Sep 2017_ +* Removed rc from version. + +#### Version 0.42.0_rc.25 of reactxp - _18 Aug 2017_ +* On web, if there's a queued onScroll event when the scroll position is manually set, cancel the onScroll. + +#### Version 0.42.0_rc.24 of reactxp - _9 Aug 2017_ +* Added accessibility support for GestureView. +* Fixed bug in web version that prevented animated fontSize from working. + +#### Version 0.42.0_rc.22 of reactxp - _30 July 2017_ +* On RN platforms, initialProps is now passed to the main view. +* Added new PopupOptions field preventDismissOnPress that prevents the popup from being dismissed implicitly when the user clicks or taps outside of the popup or the anchor. +* Fixed bug in web implementation of TextInput where border styling was not honored. +* Fixed bug on Android that allowed presses to background of Modal to go through. + +#### Version 0.42.0_rc.20 of reactxp - _15 July 2017_ +* Updated to TypeScript 2.4, which caught several bugs in the ReactXP code. +* Made Styles.combine much more flexible - it now supports arbitrarily nested arrays of styles. +* Changed Network API namespace for detecting network type so it's consistent with other ReactXP APIs. Added documentation. + +#### Version 0.1.6 of reactxp-video - _15 July 2017_ +* Updated to TypeScript 2.4 and made changes to work with latest ReactXP core. + +#### Version 0.2.4 of reactxp-imagesvg - _15 July 2017_ +* Updated to TypeScript 2.4 and made changes to work with latest ReactXP core. + +#### Version 0.42.0_rc.18 of reactxp - _13 July 2017_ +* Fixed runtime crash when running web implementation in Electron. +* Added a way to provide screen reader focus to TextInput on web. + +#### Version 0.42.0_rc.17 of reactxp - _4 July 2017_ +* Added ability to set accessibility focus for text input controls. +* Added support for iOS-specific ActivationState for RN extensions. + +#### Version 0.42.0_rc.16 of reactxp - _30 June 2017_ +* Fixed another bug in handling of default border width on web. +* Added setFocusRestricted and setFocusLimited methods and support for nested keyboard focus on web. +* Added isNavigatingWithKdyboard method and keyboardNavigationEvent. + +#### Version 0.42.0_rc.12 of reactxp - _16 June 2017_ +* Added support for new limitFocusWidth prop for constraining keyboard focus. +* Fixed bug in handling of mailto URLs on web in the Link component. +* Added support for flexGrow, flexShrink, and flexBasis props. + +#### Version 0.42.0_rc.11 of reactxp - _13 June 2017_ +* Fixed bugs in web implementation of focus manager. +* Added new API (enableTouchLatencyEvents) and event (touchLatencyEvent) in UserInterface namespace for detecting delays in touch event handling. +* Fixed crash in native implementation of Link component that resulted in uncaught exception for some types of links. +* Fixed flexDirection style default for web implementation in Image component. +* Fixed inconsistency in handling of borders between web and RN when borderStyle is not specified. + +#### Version 0.42.0_rc.10 of reactxp - _25 May 2017_ +* Added new International API namespace for controlling right-to-left mirroring behavior. + +#### Version 0.1.2 of reactxp-virtualistview - _23 May 2017_ +* Republished because index files were missing in previous publish. + +#### Version 0.42.0_rc.9 of reactxp - _17 May 2017_ +* Fixed bug in Navigator that caused crash in hello-world sample. + +#### Version 0.42.0_rc.8 of reactxp - _16 May 2017_ +* Removed Profiling API namespace and dependency on react-addons-perf. + +#### Version 0.1.1 of reactxp-virtualistview - _11 May 2017_ +* Republished because "dist" directory was missing in previous publish. + +#### Version 0.1.2 of reactxp-video - _11 May 2017_ +* Published first version of reactxp-video extension. + +#### Version 0.2.0 of reactxp-imagesvg - _10 May 2017_ +* Switched from old version of react-native-art-svg to latest version of react-native-svg. + +#### Version 0.42.0_rc.5 of reactxp - _10 May 2017_ +* Fixed incorrect import path (using wrong case). +* Fixed bug in native View implementation - was using stale props. +* Added importantForLayout prop on View (web specific). +* Fixed bug in native NavigatorExperimentalDelegate - was using wrong props. + +#### Version 0.42.0_rc.4 of reactxp - _27 Apr 2017_ +* Changed web implementation of Text to prevent copying text to clipboard. +* Eliminated the need to specify box-sizing CSS in external CSS file. +* Fixed accessibility focus bugs. + +#### Version 0.42.0_rc.3 of reactxp - _26 Apr 2017_ +* Added onLongPress prop for Link. +* Fixed accessibility bug relating to Modal dialogs. + +#### Version 0.42.0_rc.2 of reactxp - _18 Apr 2017_ +* Added missing box-sizing CSS directives for web. +* Fixed bug in native implementation of View related to accessibility. -Added new props to ScrollView. Updated package.json to properly reflect peerDependencies on react and react-native. +#### Version 0.1.0 of reactxp-imagesvg - _26 Apr 2017_ +* Published first version of reactxp-imagesvg extension. +#### Version 0.42.0_rc.1 of reactxp - _9 Apr 2017_ +* Updated project to use recent versions of React (15.5.3) and React Native (0.42.3). -#### Version 0.34.1 of reactxp -_Released 6 Apr 2017_ +#### Version 0.34.3 of reactxp - _7 Apr 2017_ +* Added new props to ScrollView. Updated package.json to properly reflect peerDependencies on react and react-native. -This is the initial public release of the ReactXP core library. It is built against React Native 0.34. We are working on updating it to a newer version of React Native, and this will be released shortly. +#### Version 0.34.1 of reactxp - _6 Apr 2017_ +* This is the initial public release of the ReactXP core library. It is built against React Native 0.34. We are working on updating it to a newer version of React Native, and this will be released shortly. diff --git a/extensions/imagesvg/.eslintrc.json b/extensions/imagesvg/.eslintrc.json new file mode 100644 index 000000000..3ff892a96 --- /dev/null +++ b/extensions/imagesvg/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": ["skype", "skype/react"], + "rules": {}, + "overrides": [ + { + "files": [ + "*.tsx" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off" + } + }, + { + "files": [ + "PluginBaseChecker.ts" + ], + "rules": { + "@typescript-eslint/no-unused-vars": "off" + } + } + ] +} diff --git a/extensions/imagesvg/.gitignore b/extensions/imagesvg/.gitignore index 30efdd65d..0e96de888 100644 --- a/extensions/imagesvg/.gitignore +++ b/extensions/imagesvg/.gitignore @@ -5,6 +5,7 @@ npm-debug.log* # Dependency directories node_modules +package-lock.json # Optional npm cache directory .npm @@ -16,4 +17,3 @@ node_modules *.user .vscode .DS_STORE - diff --git a/extensions/imagesvg/package.json b/extensions/imagesvg/package.json index 57b9a4810..9017e0004 100644 --- a/extensions/imagesvg/package.json +++ b/extensions/imagesvg/package.json @@ -1,26 +1,33 @@ { "name": "reactxp-imagesvg", - "version": "0.2.7", + "version": "2.0.0", "description": "Plugin for ReactXP that provides support for SVG (scalable vector graphics) for all platforms", "author": "ReactXP Team ", "license": "MIT", "scripts": { - "build": "npm run tslint && tsc", - "tslint": "tslint --project tsconfig.json -r tslint.json -r ./node_modules/tslint-microsoft-contrib --fix || true" + "build": "tsc", + "lint": "eslint --ext .ts,.tsx src", + "lint:fix": "npm run lint -- --fix" }, "dependencies": { - "assert": "^1.3.0", - "react-native-svg": "^5.4.0", - "reactxp": "^0.46.2" + "react-native-svg": "^9.13.3" }, "peerDependencies": { - "react-dom": "^15.4.1", - "react-native": "^0.46.0" + "react": "^16.3", + "reactxp": "^2.0.0", + "react-dom": "^16.3", + "react-native": ">=0.57", + "react-native-windows": "^0.57.1" }, "devDependencies": { - "typescript": "^2.4.1", - "tslint": "^5.0.0", - "tslint-microsoft-contrib": "^4.0.1" + "@types/react-native": "^0.60.23", + "@typescript-eslint/eslint-plugin": "2.15.0", + "eslint": "6.8.0", + "eslint-config-skype": "1.5.0", + "eslint-plugin-import": "2.19.1", + "eslint-plugin-react": "7.17.0", + "reactxp": "^2.0.0", + "typescript": "3.7.4" }, "types": "dist/web/PluginBase.d.ts" } diff --git a/extensions/imagesvg/src/android/PluginBase.tsx b/extensions/imagesvg/src/android/PluginBase.tsx index 787d1debf..5080b2ff8 100644 --- a/extensions/imagesvg/src/android/PluginBase.tsx +++ b/extensions/imagesvg/src/android/PluginBase.tsx @@ -1,13 +1,14 @@ /* -* PluginBase.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the Android implementation of the plugin. -*/ + * PluginBase.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Android implementation of the plugin. + */ +import * as Types from '../common/Types'; import ImageSvg from '../native-common/ImageSvg'; import SvgPath from '../native-common/SvgPath'; -import Types = require('../common/Types'); +import SvgRect from '../native-common/SvgRect'; -export { ImageSvg as default, SvgPath, Types }; +export { ImageSvg as default, SvgPath, SvgRect, Types }; diff --git a/extensions/imagesvg/src/common/Interfaces.ts b/extensions/imagesvg/src/common/Interfaces.ts index e5240c653..79c7b2f07 100644 --- a/extensions/imagesvg/src/common/Interfaces.ts +++ b/extensions/imagesvg/src/common/Interfaces.ts @@ -1,14 +1,14 @@ /* -* Interfaces.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Interface exposed by ImageSvg component. -*/ + * Interfaces.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Interface exposed by ImageSvg component. + */ -import React = require('react'); +import * as React from 'react'; -import Types = require('./Types'); +import * as Types from './Types'; export abstract class ImageSvg extends React.Component { } @@ -16,9 +16,13 @@ export abstract class ImageSvg extends React.Component export abstract class SvgPath extends React.Component { } +export abstract class SvgRect extends React.Component { +} + export interface PluginInterface { Types: typeof Types; - + default: typeof ImageSvg; SvgPath: typeof SvgPath; + SvgRect: typeof SvgRect; } diff --git a/extensions/imagesvg/src/common/PluginBaseChecker.ts b/extensions/imagesvg/src/common/PluginBaseChecker.ts index 5d4ac261a..f2b1672fb 100644 --- a/extensions/imagesvg/src/common/PluginBaseChecker.ts +++ b/extensions/imagesvg/src/common/PluginBaseChecker.ts @@ -1,23 +1,21 @@ /* -* PluginBaseChecker.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type check all the pluginbase exports against the desired interface. -*/ + * PluginBaseChecker.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type check all the pluginbase exports against the desired interface. + */ -import Interfaces = require('./Interfaces'); +import * as AndroidPlugin from '../android/PluginBase'; +import * as iOSPlugin from '../ios/PluginBase'; +import * as macOSPlugin from '../macos/PluginBase'; +import * as WebPlugin from '../web/PluginBase'; +import * as WindowsPlugin from '../windows/PluginBase'; -import AndroidPlugin = require('../android/PluginBase'); -import iOSPlugin = require('../ios/PluginBase'); -import macOSPlugin = require('../macos/PluginBase'); -import WebPlugin = require('../web/PluginBase'); -import WindowsPlugin = require('../windows/PluginBase'); +import * as Interfaces from './Interfaces'; -/* tslint:disable:no-unused-variable */ const _typeCheckerAndroid: Interfaces.PluginInterface = AndroidPlugin; const _typeCheckeriOS: Interfaces.PluginInterface = iOSPlugin; const _typeCheckermacOS: Interfaces.PluginInterface = macOSPlugin; const _typeCheckerWeb: Interfaces.PluginInterface = WebPlugin; const _typeCheckerWindows: Interfaces.PluginInterface = WindowsPlugin; -/* tslint:enable:no-unused-variable */ diff --git a/extensions/imagesvg/src/common/Types.ts b/extensions/imagesvg/src/common/Types.ts index d3de2454c..d3560d28a 100644 --- a/extensions/imagesvg/src/common/Types.ts +++ b/extensions/imagesvg/src/common/Types.ts @@ -1,15 +1,17 @@ /* -* Types.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definitions to support the plugin. -*/ + * Types.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type definitions to support the plugin. + */ import { Types as RXTypes } from 'reactxp'; +import * as React from 'react'; export interface ImageSvgStyle extends RXTypes.ViewStyle { } + export declare type ImageSvgStyleRuleSet = RXTypes.StyleRuleSet; export interface SvgCommonProps { @@ -21,7 +23,7 @@ export interface SvgCommonProps { fillOpacity?: number; } -export interface ImageSvgProps extends SvgCommonProps, RXTypes.CommonStyledProps { +export interface ImageSvgProps extends SvgCommonProps, RXTypes.CommonStyledProps { children?: RXTypes.ReactNode; height: number; width: number; @@ -31,6 +33,16 @@ export interface ImageSvgProps extends SvgCommonProps, RXTypes.CommonStyledProps preserveAspectRatio?: string; webShadow?: string; } + export interface SvgPathProps extends SvgCommonProps { d?: string; } + +export interface SvgRectProps extends SvgCommonProps { + width: number; + height: number; + x: number; + y: number; +} + +export class ImageSvg extends React.Component {} diff --git a/extensions/imagesvg/src/common/assert.ts b/extensions/imagesvg/src/common/assert.ts new file mode 100644 index 000000000..46aba16a5 --- /dev/null +++ b/extensions/imagesvg/src/common/assert.ts @@ -0,0 +1,14 @@ +/** + * assert + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + */ +const assert = (cond: any, message?: string | undefined): void => { + if (!cond) { + throw new Error(message || 'Assertion Failed'); + } +}; + +export default assert; diff --git a/extensions/imagesvg/src/ios/PluginBase.tsx b/extensions/imagesvg/src/ios/PluginBase.tsx index 69e3f7133..80f587975 100644 --- a/extensions/imagesvg/src/ios/PluginBase.tsx +++ b/extensions/imagesvg/src/ios/PluginBase.tsx @@ -1,13 +1,14 @@ /* -* PluginBase.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the iOS implementation of the plugin. -*/ + * PluginBase.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the iOS implementation of the plugin. + */ +import * as Types from '../common/Types'; import ImageSvg from '../native-common/ImageSvg'; import SvgPath from '../native-common/SvgPath'; -import Types = require('../common/Types'); +import SvgRect from '../native-common/SvgRect'; -export { ImageSvg as default, SvgPath, Types }; +export { ImageSvg as default, SvgPath, SvgRect, Types }; diff --git a/extensions/imagesvg/src/macos/PluginBase.tsx b/extensions/imagesvg/src/macos/PluginBase.tsx index 69e3f7133..80f587975 100644 --- a/extensions/imagesvg/src/macos/PluginBase.tsx +++ b/extensions/imagesvg/src/macos/PluginBase.tsx @@ -1,13 +1,14 @@ /* -* PluginBase.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the iOS implementation of the plugin. -*/ + * PluginBase.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the iOS implementation of the plugin. + */ +import * as Types from '../common/Types'; import ImageSvg from '../native-common/ImageSvg'; import SvgPath from '../native-common/SvgPath'; -import Types = require('../common/Types'); +import SvgRect from '../native-common/SvgRect'; -export { ImageSvg as default, SvgPath, Types }; +export { ImageSvg as default, SvgPath, SvgRect, Types }; diff --git a/extensions/imagesvg/src/native-common/ImageSvg.tsx b/extensions/imagesvg/src/native-common/ImageSvg.tsx index a2dc19ed5..8327b50ec 100644 --- a/extensions/imagesvg/src/native-common/ImageSvg.tsx +++ b/extensions/imagesvg/src/native-common/ImageSvg.tsx @@ -1,23 +1,21 @@ /** -* ImageSvg.tsx -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* RN-specific implementation of the cross-platform abstraction for -* SVG (scalable vector graphics) images. -*/ + * ImageSvg.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform abstraction for + * SVG (scalable vector graphics) images. + */ -import assert = require('assert'); -import React = require('react'); -import RNSvg = require('react-native-svg'); +import * as React from 'react'; +import * as RNSvg from 'react-native-svg'; -import SvgInterfaces = require('../common/Interfaces'); -import SvgTypes = require('../common/Types'); +import assert from '../common/assert'; +import { ImageSvgProps } from '../common/Types'; -export class ImageSvg extends React.Component { +export class ImageSvg extends React.Component { render() { - - assert.ok(this.props.width && this.props.height, 'The width and height on imagesvg are mandatory.'); + assert(this.props.width && this.props.height, 'The width and height on imagesvg are mandatory.'); if (this.props.width > 0 && this.props.height > 0) { return ( @@ -32,9 +30,9 @@ export class ImageSvg extends React.Component { { this.props.children } ); - } else { - return null; } + + return null; } } diff --git a/extensions/imagesvg/src/native-common/SvgPath.tsx b/extensions/imagesvg/src/native-common/SvgPath.tsx index cdbec63a2..feda5fbcc 100644 --- a/extensions/imagesvg/src/native-common/SvgPath.tsx +++ b/extensions/imagesvg/src/native-common/SvgPath.tsx @@ -1,29 +1,27 @@ /** -* SvgPath.tsx -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* RN-specific implementation of the cross-platform abstraction for -* SVG Path (scalable vector graphics) elements. -*/ + * SvgPath.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform abstraction for + * SVG Path elements. + */ -import React = require('react'); -import RNSvg = require('react-native-svg'); +import * as React from 'react'; +import * as RNSvg from 'react-native-svg'; -import SvgInterfaces = require('../common/Interfaces'); -import SvgTypes = require('../common/Types'); +import { SvgPathProps } from '../common/Types'; -export class SvgPath extends React.Component { +export class SvgPath extends React.Component { render() { return ( ); } diff --git a/extensions/imagesvg/src/native-common/SvgRect.tsx b/extensions/imagesvg/src/native-common/SvgRect.tsx new file mode 100644 index 000000000..42574236e --- /dev/null +++ b/extensions/imagesvg/src/native-common/SvgRect.tsx @@ -0,0 +1,33 @@ +/** + * SvgPath.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform abstraction for + * SVG Rect elements. + */ + +import * as React from 'react'; +import * as RNSvg from 'react-native-svg'; + +import { SvgRectProps } from '../common/Types'; + +export class SvgRect extends React.Component { + render() { + return ( + + ); + } +} + +export default SvgRect; diff --git a/extensions/imagesvg/src/typings/assert.d.ts b/extensions/imagesvg/src/typings/assert.d.ts deleted file mode 100644 index 04f565dd2..000000000 --- a/extensions/imagesvg/src/typings/assert.d.ts +++ /dev/null @@ -1,62 +0,0 @@ -// Type definitions for assert -// Project: https://github.com/defunctzombie/commonjs-assert -// Definitions by: vvakame -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -// Definitions for commonjs-assert match that of node.js' assert module, -// but commonjs-assert is intended to be used as an independent module, -// for instance when making a stand-alone site or app that doesn't have -// access to node modules. For that reason, these definitions define a -// "assert" module. This will conflict with node.d.ts and other assert -// modules such as "power-assert", but a project should realistically -// only be using one of these at a time. - -declare function assert(value:any, message?:string):void; -declare namespace assert { - export class AssertionError implements Error { - name:string; - message:string; - actual:any; - expected:any; - operator:string; - generatedMessage:boolean; - - constructor(options?:{message?: string; actual?: any; expected?: any; operator?: string; stackStartFunction?: Function}); - } - - export function fail(actual?:any, expected?:any, message?:string, operator?:string):void; - - export function ok(value:any, message?:string):void; - - export function equal(actual:any, expected:any, message?:string):void; - - export function notEqual(actual:any, expected:any, message?:string):void; - - export function deepEqual(actual:any, expected:any, message?:string):void; - - export function notDeepEqual(acutal:any, expected:any, message?:string):void; - - export function strictEqual(actual:any, expected:any, message?:string):void; - - export function notStrictEqual(actual:any, expected:any, message?:string):void; - - export var throws:{ - (block:Function, message?:string): void; - (block:Function, error:Function, message?:string): void; - (block:Function, error:RegExp, message?:string): void; - (block:Function, error:(err:any) => boolean, message?:string): void; - }; - - export var doesNotThrow:{ - (block:Function, message?:string): void; - (block:Function, error:Function, message?:string): void; - (block:Function, error:RegExp, message?:string): void; - (block:Function, error:(err:any) => boolean, message?:string): void; - }; - - export function ifError(value:any):void; -} - -declare module "assert" { - export = assert; -} \ No newline at end of file diff --git a/extensions/imagesvg/src/typings/react-native-svg.d.ts b/extensions/imagesvg/src/typings/react-native-svg.d.ts index 564758a67..da4de9cf3 100644 --- a/extensions/imagesvg/src/typings/react-native-svg.d.ts +++ b/extensions/imagesvg/src/typings/react-native-svg.d.ts @@ -1,66 +1,66 @@ /** -* react-native-svg.d.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definition file for the React Native SVG module. -* https://github.com/react-native-community/react-native-svg -*/ + * react-native-svg.d.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type definition file for the React Native SVG module. + * https://github.com/react-native-community/react-native-svg + */ declare module 'react-native-svg' { - import React = require('react'); - import RN = require('react-native'); + import * as React from 'react'; + import * as RN from 'react-native'; type ArrayType = [string] | [number]; interface SvgProps extends RN.ComponentPropsBase { - height?: string, - width?: string, - viewBox?: string, - opacity?: number, + height?: string; + width?: string; + viewBox?: string; + opacity?: number; preserveAspectRatio?: string; style?: RN.StyleRuleSet; } interface BaseProps extends RN.ComponentPropsBase { - fill?: string, //The fill prop refers to the color inside the shape. - fillOpacity?: number, // This prop specifies the opacity of the color or the content the current object is filled with. - stroke?: string, //The stroke prop controls how the outline of a shape appears. - strokeWidth?: number, //The strokeWidth prop specifies the width of the outline on the current object. - strokeOpacity?: number, //The strokeOpacity prop specifies the opacity of the outline on the current object. - x?: number, - y?: number, - strokeLinecap?: string, //oneOf(['butt', 'square', 'round']), - strokeCap?: string, //.oneOf(['butt', 'square', 'round']), - strokeLinejoin?: string, //oneOf(['miter', 'bevel', 'round']), - strokeJoin?: string, //.oneOf(['miter', 'bevel', 'round']), - strokeDasharray?: ArrayType, - scale?: number, //Scale value on the current object. - rotate?: number, //Rotation degree value on the current object. - originX?: number, //Transform originX coordinates for the current object. - originY?: number //Transform originY coordinates for the current object. + fill?: string; // The fill prop refers to the color inside the shape. + fillOpacity?: number; // This prop specifies the opacity of the color or the content the current object is filled with. + stroke?: string; // The stroke prop controls how the outline of a shape appears. + strokeWidth?: number; // The strokeWidth prop specifies the width of the outline on the current object. + strokeOpacity?: number; // The strokeOpacity prop specifies the opacity of the outline on the current object. + x?: number; + y?: number; + strokeLinecap?: string; // oneOf(['butt', 'square', 'round']), + strokeCap?: string; // .oneOf(['butt', 'square', 'round']), + strokeLinejoin?: string; // oneOf(['miter', 'bevel', 'round']), + strokeJoin?: string; // .oneOf(['miter', 'bevel', 'round']), + strokeDasharray?: ArrayType; + scale?: number; // Scale value on the current object. + rotate?: number; // Rotation degree value on the current object. + originX?: number; // Transform originX coordinates for the current object. + originY?: number; // Transform originY coordinates for the current object. } interface TransformProps extends BaseProps { - scaleX: number, - scaleY: number, - transform: number, + scaleX: number; + scaleY: number; + transform: number; } interface PathProps extends BaseProps { - d: string + d: string; } interface RectProps extends BaseProps { - width?: number, - height?: number + width?: number; + height?: number; } interface TextProps extends BaseProps { - textAnchor: ('start' | 'middle' | 'end'), - fontFamily: string, - fontSize: number, + textAnchor: ('start' | 'middle' | 'end'); + fontFamily: string; + fontSize: number; } export class Svg extends React.Component { } diff --git a/extensions/imagesvg/src/typings/react-native.d.ts b/extensions/imagesvg/src/typings/react-native.d.ts deleted file mode 100644 index f6587f177..000000000 --- a/extensions/imagesvg/src/typings/react-native.d.ts +++ /dev/null @@ -1,1091 +0,0 @@ -/** -* react-native.d.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definition file for React Native, based on the React.js definition file -* on https://github.com/borisyankov/DefinitelyTyped. -*/ - -declare module 'react-native' { - // - // React - // ---------------------------------------------------------------------- - - import React = require('react'); - - // BT: Adding ProgressBarAndroid. It's not part of the DefinitelyTyped definitions. - class ProgressBarAndroid extends React.Component {} - - type ReactElement = React.ReactElement; - type ReactNode = React.ReactNode; - - function createElement

( - type: string, - props?: P, - ...children: React.ReactNode[]): React.ReactElement

; - - function cloneElement

( - element: P, - props ?: any - ): React.ReactElement

; - - interface SyntheticEvent extends React.SyntheticEvent {} - - function isValidElement(object: {}): boolean; - function findNodeHandle(componentOrHandle: any): number; - - var Children: React.ReactChildren; - - type PlatformString = 'android'|'ios'|'windows'; - var Platform: { - OS: PlatformString, - Version?: number - }; - - // - // Component base - // ---------------------------------------------------------------------- - - abstract class ReactNativeBaseComponent extends React.Component { - setNativeProps(nativeProps: P): void; - focus(): void; - blur(): void; - measure(callback: ((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void)): void; - measureLayout(relativeToNativeNode: number, onSuccess: ((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void), onFail: () => void): void; - refs: { - [key: string]: ReactNativeBaseComponent; - } - } - - // - // Style rules - // ---------------------------------------------------------------------- - - type StyleRuleSet = Object | Object[]; - - // - // Specific components - // ---------------------------------------------------------------------- - - interface ComponentPropsBase { - ref?: string | ((obj: ReactNativeBaseComponent) => void); - key?: string | number; - } - - interface ComponentPropsStyleBase extends ComponentPropsBase { - style?: StyleRuleSet | StyleRuleSet[]; - } - - interface ImageSource { - uri: string; - headers?: {[header: string]: string}; - } - - interface ImageProps extends ComponentPropsStyleBase { - onLayout?: Function; - resizeMode?: string; - resizeMethod?: string; // android only prop: 'auto' | 'resize' | 'scale' - source?: ImageSource | number; - testID?: string; - - // iOS - accessibilityLabel?: string; - shouldRasterizeIOS?: boolean; - accessible?: boolean; - capInsets?: Object; - defaultSource?: Object; - onError?: Function; - onLoad?: Function; - onLoadEnd?: (e: SyntheticEvent) => void; - onLoadStart?: Function; - onProgress?: Function; - - // Android - fadeDuration?: number; - } - - interface ActivityIndicatorProps extends ComponentPropsBase { - animating?: boolean; - color?: string; - onLayout?: Function; - size?: string; // enum { 'small', 'large' } - } - - interface TextProps extends ComponentPropsStyleBase { - importantForAccessibility?: string; // 'auto' | 'yes' | 'no' | 'no-hide-descendants'; - allowFontScaling?: boolean; - maxContentSizeMultiplier?: number; - children? : React.ReactNode; - numberOfLines? : number; - ellipsizeMode? : 'head' | 'middle' | 'tail' // There's also 'clip' but it is iOS only - onLayout? : Function; - onPress? : Function; - onLongPress? : Function; - selectable? : boolean; // only on android, windows - testID? : string; - - // iOS - suppressHighlighting?: boolean; - - // Android - textBreakStrategy?: 'highQuality' | 'simple'| 'balanced'; - elevation?: number; - } - - export interface PickerProps extends ComponentPropsStyleBase { - - /** - * Callback for when an item is selected. This is called with the - * following parameters: - * - itemValue: the value prop of the item that was selected - * - itemPosition: the index of the selected item in this picker - * @param itemValue - * @param itemPosition - */ - onValueChange?: ( itemValue: any, itemPosition: number ) => void - - /** - * Value matching value of one of the items. - * Can be a string or an integer. - */ - selectedValue?: any - - style?: StyleRuleSet | StyleRuleSet[] - - /** - * Used to locate this view in end-to-end tests. - */ - testId?: string - - ref?: string | ((obj: ReactNativeBaseComponent) => void); - } - - interface TouchableWithoutFeedbackProps extends ComponentPropsBase { - accessibilityComponentType? : string; //enum ( 'none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' ) - accessibilityTraits?: string | string[]; //enum( 'none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text', 'summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn' ) - accessible?: boolean; - importantForAccessibility? : string; //enum( 'auto', 'yes', 'no', 'no-hide-descendants' ) - delayLongPress?: number; - delayPressIn?: number; - delayPressOut?: number; - onLayout?: Function; - onLongPress?: Function; - onPress?: Function; - onPressIn?: Function; - onPressOut?: Function - } - - interface TouchableHighlightProps extends TouchableWithoutFeedbackProps, ComponentPropsStyleBase { - activeOpacity? : number; - children? : React.ReactNode; - onHideUnderlay?: Function; - onShowUnderlay?: Function; - underlayColor? : string; - } - - interface ResponderProps { - onMoveShouldSetResponder? : Function; - onResponderGrant? : Function; - onResponderMove? : Function; - onResponderReject? : Function; - onResponderRelease? : Function; - onResponderTerminate? : Function; - onResponderTerminationRequest? : Function; - onStartShouldSetResponder? : Function; - onStartShouldSetResponderCapture?: Function; - } - - interface ViewOnLayoutEvent { - nativeEvent: { - layout: { - x: number, - y: number, - width: number, - height: number - } - } - } - - type ViewLayerType = 'none' | 'software' | 'hardware'; - - interface CommonAccessibilityProps { - accessibilityLabel? : string; - accessible? : boolean; - onAcccessibilityTap? : Function; - - // android - accessibilityComponentType? : string; //enum ( 'none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' ) - accessibilityLiveRegion? : string; //enum ( 'none', 'polite', 'assertive' ) - importantForAccessibility? : string; //enum( 'auto', 'yes', 'no', 'no-hide-descendants' ) - - // iOS - accessibilityTraits?: string | string[]; //enum( 'none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text', 'summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn' ) - } - - interface ViewProps extends ComponentPropsBase, ResponderProps, ComponentPropsStyleBase, CommonAccessibilityProps { - children? : any; - onLayout? : ((ev: ViewOnLayoutEvent) => void); - onMagicTap? : Function; - pointerEvents? : string; //enum( 'box-none', 'none', 'box-only', 'auto' ); - removeClippedSubviews? : boolean; - testID? : string; - - // android - collapsable? : boolean; - needsOffscreenAlphaCompositing?: boolean; - renderToHardwareTextureAndroid?: boolean; - viewLayerTypeAndroid? : ViewLayerType; - elevation? : number; - - // iOS - onAccessibilityTapIOS?: Function; - shouldRasterizeIOS? : boolean; - } - - interface ScrollViewProps extends ViewProps { - children?: any; - - contentContainerStyle?: StyleRuleSet | StyleRuleSet[]; - horizontal?: boolean; - keyboardDismissMode?: 'none' | 'interactive' | 'on-drag'; - keyboardShouldPersistTaps?: 'always' | 'never' | 'handled'; - onScroll?: Function; - onScrollBeginDrag?: Function; - onScrollEndDrag?: Function; - onContentSizeChange?: (width: number, height: number) => void; - showsHorizontalScrollIndicator?: boolean; - showsVerticalScrollIndicator?: boolean; - removeClippedSubviews?: boolean; - - // iOS - automaticallyAdjustContentInsets?: boolean; - //contentInset?: EdgeInsetsPropType; - //contentOffset?: PointPropType; - bounces?: boolean; - bouncesZoom?: boolean; - alwaysBounceHorizontal?: boolean; - alwaysBounceVertical?: boolean; - centerContent?: boolean; - decelerationRate?: number; - directionalLockEnabled?: boolean; - canCancelContentTouches?: boolean; - maximumZoomScale?: number; - minimumZoomScale?: number; - onScrollAnimationEnd?: Function; - pagingEnabled?: boolean; - scrollEnabled?: boolean; - scrollEventThrottle?: number; - scrollsToTop?: boolean; - stickyHeaderIndices?: [number]; - snapToInterval?: number; - snapToAlignment?: string; // enum( 'start', 'center', 'end' ) - zoomScale?: number; - overScrollMode?: string; //enum( 'always', 'always-if-content-scrolls', 'never' ) - // iOS - scrollIndicatorInsets?: {top: number, left: number, bottom: number, right: number }; - } - - interface ListViewDataSourceCallback { - rowHasChanged: (r1: T, r2: T) => boolean; - } - - interface ListViewDataSource { - new (onAsset: ListViewDataSourceCallback): ListViewDataSource; - cloneWithRows(rowList: T[]): void; - } - - interface ListViewProps extends ScrollViewProps { - dataSource: Object; //PropTypes.instanceOf(ListViewDataSource).isRequired - renderSeparator?: Function; - renderRow: Function; - initialListSize?: number; - onEndReached?: (e: React.SyntheticEvent) => void; - onEndReachedThreshold?: number; - pageSize?: number; - renderFooter?: Function; - renderHeader?: Function; - renderSectionHeader?: Function; - renderScrollComponent: Function; - scrollRenderAheadDistance?: number; - onChangeVisibleRows?: Function; - removeClippedSubviews?: boolean; - } - - interface ModalProps extends ComponentPropsBase { - animationType?: string; // enum( 'none', 'slide', 'fade' ) - onDismiss?: Function; - transparent?: boolean; - onRequestClose: () => void; - } - - interface TextInputProps extends ComponentPropsStyleBase, CommonAccessibilityProps { - autoCapitalize?: string; // enum('none', 'sentences', 'words', 'characters') - autoCorrect?: boolean; - autoFocus?: boolean; - blurOnSubmit?: boolean; - defaultValue?: string; - editable?: boolean; - keyboardType?: string; // enum("default", 'numeric', 'email-address', "ascii-capable", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search') - multiline?: boolean; - onBlur?: ((e: React.FocusEvent) => void); - onKeyPress?: (e: SyntheticEvent) => void; - onChange?: Function; - onChangeText?: ((changedText: string) => void); - onSelectionChange?: ((selection: SyntheticEvent) => void); - onEndEditing?: Function; - onFocus?: ((e: React.FocusEvent) => void); - onLayout?: ((props: { x: number, y: number, width: number, height: number }) => void); - onSubmitEditing?: Function; - onScroll?: Function; - placeholder?: string; - placeholderTextColor?: string; - returnKeyType?: string; // enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') - secureTextEntry?: boolean; - testID?: string; - textAlign?: string; // enum('auto' | 'left' | 'right' | 'center' | 'justify') - allowFontScaling?: boolean; - maxContentSizeMultiplier?: number; - selection?: { start: number, end: number }; - - //iOS and android - selectionColor?: string; - - value: string; - //iOS - clearButtonMode?: string; // enum('never', 'while-editing', 'unless-editing', 'always') - clearTextOnFocus?: boolean; - enablesReturnKeyAutomatically?: boolean; - keyboardAppearance?: string; // enum ('default', 'light', 'dark') - maxLength?: number; - numberOfLines?: number; - selectTextOnFocus?: boolean; - selectionState?: any; // see DocumentSelectionState.js - spellCheck?: boolean; - //android - textAlignVertical?: string; // enum('top', 'center', 'bottom') - textAlignVerticalAndroid?: string; // enum('top', 'center', 'bottom') - textAlignAndroid?: string; - underlineColorAndroid?: string; - disableFullscreenUI?: boolean; - textBreakStrategy?: 'highQuality' | 'simple' | 'balanced'; - } - - interface TextInputState { - currentlyFocusedField(): number; - focusTextInput(textFieldID?: number): void; - blurTextInput(textFieldID?: number): void; - } - - interface WebViewProps extends ComponentPropsStyleBase { - automaticallyAdjustContentInsets?: boolean; - bounces?: boolean; - contentInset?: {top: number, left: number, bottom: number, right: number }; - injectedJavaScript?: string; - javaScriptEnabled?: boolean; - domStorageEnabled?: boolean; - onShouldStartLoadWithRequest?: Function; - onNavigationStateChange?: Function; - onLoad?: (e: SyntheticEvent) => void; - onLoadStart?: Function; - renderError?: Function; - onError?: Function; - renderLoading?: Function; - scalesPageToFit?: boolean; - scrollEnabled?: boolean; - startInLoadingState?: boolean; - source?: { uri: string; method?: string; headers?: Object; body?: string; } | { html: string; baseUrl?: string; }; - } - - interface DatePickerIOSProps extends ComponentPropsStyleBase { - date?: Date; - maximumDate?: Date; - minimumDate?: Date; - minuteInterval?: number; - mode?: string; - timeZoneOffsetInMinutes?: number; - - onDateChange?: (newDate: Date) => void; - } - - class DatePickerIOS extends ReactNativeBaseComponent { - } - - interface DatePickerAndroidProps extends ComponentPropsStyleBase { - date?: Date; - maxDate?: Date; - minDate?: Date; - - onDateChange?: (newDate: Date) => void; - } - - class DatePickerAndroid extends ReactNativeBaseComponent { - static open(options: { date: Date, maxDate: Date, minDate: Date }): Promise; - static dateSetAction: Function; - static dismissedAction: Function; - } - - interface TimePickerAndroidProps extends ComponentPropsStyleBase { - date?: Date; - maxDate?: Date; - minDate?: Date; - - onDateChange?: (newDate: Date) => void; - } - - class TimePickerAndroid extends ReactNativeBaseComponent { - static open(options: { hour: number, minute: number, is24Hour: boolean }): Promise; - static timeSetAction: Function; - static dismissedAction: Function; - } - - type DatePickerAction = { - action: Function; - day: number; - month: number; - year: number; - } - - type TimePickerAction = { - action: Function; - hour: number; - minute: number; - } - - class Image extends ReactNativeBaseComponent { - static prefetch(url: string): Promise; - } - class ActivityIndicator extends ReactNativeBaseComponent { } - class Text extends ReactNativeBaseComponent { } - class Picker extends ReactNativeBaseComponent { - static Item: any; - } - class TouchableHighlight extends ReactNativeBaseComponent { } - class TouchableWithoutFeedback extends ReactNativeBaseComponent { } - class View extends ReactNativeBaseComponent { } - class ScrollView extends ReactNativeBaseComponent { - getInnerViewNode(): number; - // TODO: Define ScrollResponder type - scrollTo(val: { x?: number; y?: number; animated?: boolean; }): void; - scrollBy(val: { deltaX?: number; deltaY?: number; animated?: boolean; }): void; - } - class ListView extends ReactNativeBaseComponent { - static DataSource: ListViewDataSource; - } - class Modal extends ReactNativeBaseComponent { } - class TextInput extends ReactNativeBaseComponent { - static State: TextInputState; - } - class WebView extends ReactNativeBaseComponent { - reload() : void; - goBack() : void; - goForward() : void; - } - - interface ActionSheetOptions { - options: string[]; - cancelButtonIndex?: number; - destructiveButtonIndex?: number; - title?: string; - message?: string; - } - - interface ShareActionSheetOptions { - message?: string; - url?: string; - subject?: string; - excludedActivityTypes?: string[]; - } - - class ActionSheetIOS { - static showActionSheetWithOptions(options: ActionSheetOptions, callback: (buttonIndex: number) => void): void; - static showShareActionSheetWithOptions(options: ShareActionSheetOptions, failureCallback: (error: string) => void, successCallback: (success: boolean, method: string) => void): void; - } - - class BackAndroid { - static addEventListener(eventName: string, callback: () => boolean): void; - static removeEventListener(eventName: string, callback: () => boolean): void; - } - - interface NavigatorIOSRoute { - component: any; - title: string; - passProps?: any; - backButtonTitle?: string; - backButtonIcon?: any; - leftButtonTitle?: string; - leftButtonIcon?: any; - onLeftButtonPress?: () => void; - rightButtonTitle?: string; - rightButtonIcon?: any; - onRightButtonPress?: () => void; - wrapperStyle?: any; - } - - interface NavigatorIOSProps extends ComponentPropsBase { - barTintColor?: string; - initialRoute: NavigatorIOSRoute; - itemWrapperStyle?: StyleRuleSet | StyleRuleSet[]; - navigationBarHidden?: boolean; - shadowHidden?: boolean; - style?:any; - tintColor?: string; - titleTextColor?: string; - translucent?: boolean; - interactivePopGestureEnabled?: boolean; - } - - class StatusBar { - // Native - static setHidden(hidden: boolean, animation?: string): void; //'none'|'fade'|'slide'; - - // iOS - static setBarStyle(barStyle: string, animated: boolean): void; //'default'|'light-content'; - static setNetworkActivityIndicatorVisible(value: boolean): void; - - // Android - static setBackgroundColor(color: string, animated?: boolean): void; - static setTranslucent(translucent: boolean): void; - } - - interface EventSubscription { - remove(): void; - } - - interface NavigatorIOSNavigationContext { - addListener(event: string, callback: (route: NavigatorIOSRoute) => void): EventSubscription; - } - - interface NavigatorIOSState { - observedTopOfStack: number; - requestedTopOfStack: number; - routeStack: NavigatorIOSRoute[]; - } - - class NavigatorIOS extends ReactNativeBaseComponent { - navigationContext: NavigatorIOSNavigationContext; - push(route: NavigatorIOSRoute): void; - pop(): void; - popN(n: number): void; - replace(route: NavigatorIOSRoute): void; - replacePrevious(route: NavigatorIOSRoute): void; - replacePreviousAndPop(route: NavigatorIOSRoute): void; - resetTo(route: NavigatorIOSRoute): void; - popToRoute(route: NavigatorIOSRoute): void; - popToTop(): void; - } - - // StyleSheet - class StyleSheet { - static create(obj: { [key: string]: any }): any; - static flatten: (s: StyleSheet) => { [key: string]: any }; - } - - class AppRegistry { - static registerComponent(appKey: string, getComponentFunc: Function): any; - } - - type CameraRollProps = { - /** - * The number of photos wanted in reverse order of the photo application - * (i.e. most recent first for SavedPhotos). - */ - first: number, - - /** - * A cursor that matches `page_info { end_cursor }` returned from a previous - * call to `getPhotos` - */ - after?: string, - - /** - * Specifies which group types to filter the results to. - */ - groupTypes?: string, // enum { 'Album', 'All', 'Event', 'Faces', 'Library', 'PhotoStream', 'SavedPhotos', // default }, - - /** - * Specifies filter on group names, like 'Recent Photos' or custom album - * titles. - */ - groupName?: string, - - /** - * Specifies filter on asset type - */ - assetType?: string; // enum { 'All', 'Videos', 'Photos', // default }, - - } - - type GetPhotosCallbackPropNode = { - node: { - type: string, - group_name: string, - image: { - uri: string, - height: number, - width: number, - isStored?: boolean, - }, - timestamp: number, - location?: { - latitude?: number, - longitude?: number, - altitude?: number, - heading?: number, - speed?: number, - } - } - } - - type GetPhotosCallbackProps = { - edges: GetPhotosCallbackPropNode[], - page_info: { - has_next_page: boolean, - start_cursor?: string, - end_cursor?: string, - } - } - - class Clipboard { - static setString(content: string): void; - static getString(): Promise; - } - - class CameraRoll { - static saveImageWithTag(tag: string, successCallback: Function, errorCallback: Function): void; - static getPhotos(params: CameraRollProps, callback: ((props: GetPhotosCallbackProps) => void), errorCallback: Function): void; - } - - class Linking { - static getInitialURL(): Promise; - static openURL(url: string): Promise; - static canOpenURL(url: string): Promise; - static addEventListener(type: string, handler: (event: any) => void): void; - static removeEventListener(type: string, handler: (event: any) => void): void; - } - - class AccessibilityInfo { - static fetch: () => Promise; - static addEventListener(type: string, handler: (event: any) => void): void; - static removeEventListener(type: string, handler: (event: any) => void): void; - static announceForAccessibility(announcement: string): void; - static setAccessibilityFocus(reactTag: number): void; - } - - interface AlertButtonSpec { - text?: string; - onPress?: () => void; - style?: string; // enum {default', 'cancel', 'destructive'} - } - - class Alert { - static alert( - title: string, - message?: string, - buttons?: AlertButtonSpec[], - type?: string // enum { 'default', 'plain-text', 'secure-text', 'login-password'} - ): void; - } - - class PushNotificationIOS { - static presentLocalNotification(details: { category: string, alertBody: string, soundName?: string}): void; - static scheduleLocalNotification(details: {alertBody: string, fireDate: Date}): void; - - static getApplicationIconBadgeNumber(callback: (badgeCount:number) => void): void; - static setApplicationIconBadgeNumber(number: number): void; - - static addEventListener(type: string, handler: (event: any) => void): void; - - static requestPermissions(permissions?: {alert?: boolean, badge?: boolean, sound?: boolean}): void; - static abandonPermissions(): void; - static checkPermissions(callback: (permissions: {alert: boolean, badge: boolean, sound: boolean}) => void): void; - - static getInitialNotification(): Promise; - - getMessage(): string; - getSound(): string; - getAlert(): any; - getBadgeCount(): number; - getData(): any; - } - - interface PanResponderGestureState { - stateID: number; - moveX: number; - moveY: number; - x0: number; - y0: number; - dx: number; - dy: number; - vx: number; - vy: number; - numberActiveTouches: number; - } - - interface ResponderSyntheticEvent extends React.SyntheticEvent { - touchHistory: Function; - } - - type PanResponderCreateConfig = { - onMoveShouldSetPanResponder?: (e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean, - onMoveShouldSetPanResponderCapture?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onStartShouldSetPanResponder?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onStartShouldSetPanResponderCapture?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderReject?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderGrant?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderStart?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderEnd?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderRelease?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderMove?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderTerminate?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderTerminationRequest?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onShouldBlockNativeResponder?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), // android only - onStartShouldSetResponderCapture?: (e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void, - - } - - class PanResponder { - static create(config: PanResponderCreateConfig): PanResponder; - panHandlers: ResponderProps; - } - - type DimensionType = { - width: number, - height: number, - scale: number, - fontScale: number, - } - - class Dimensions { - static set(obj: any): boolean; - static get(key: string): DimensionType; - } - - type RCTAppStateData = { app_state: string } - type RCTAppState = { - getCurrentAppState(successCallback: (appStateData: RCTAppStateData) => void, failureCallback: () => void): void; - } - - type FileInput = { - selectImage: Function; - } - - type SnapshotOptions = { - width?: number; - height?: number; - format?: 'png' | 'jpeg'; - quality?: number; - } - - type UIManager = { - measure: Function; - measureInWindow: Function; - measureLayout: Function; - measureLayoutRelativeToParent: Function; - dispatchViewManagerCommand: Function; - - getMaxContentSizeMultiplier: Function; - setMaxContentSizeMultiplier: Function; - - // ios - takeSnapshot: (view: any, options?: SnapshotOptions) => Promise; - - // Android - sendAccessibilityEvent: Function; - } - - type AccessibilityManager = { - getMultiplier: Function; - announceForAccessibility (announcement: string): void; - } - - // We don't use this module, but need to be able to check its existance - type NativeAnimatedModule = { - - }; - - class ImagePickerManager { - showImagePicker: Function; - launchCamera: Function; - launchImageLibrary: Function; - } - - class NativeModules { - static AppState: RCTAppState; - static FileInput: FileInput; - static UIManager: UIManager; - static AccessibilityManager: AccessibilityManager; - static ImagePickerManager: ImagePickerManager; - static Networking: { - clearCookies(callback: (success: boolean) => void): void; - } - static ContextMenuAndroid: { - show(buttons: any, callback: (command: string) => void): void; - } - static NativeAnimation: NativeAnimatedModule; - } - - class AsyncStorage { - static getItem(key: string, callback: (error: any, result: string) => void): void; - static setItem(key: string, value: string, callback: (error: any) => void): void; - static removeItem(key: string, callback: (error: any) => void): void; - static clear(callback: (error: any) => void): void; - } - - class NetInfo { - static isConnected: { - addEventListener: (eventName: string, handler: (isConnected: boolean) => void) => void; - removeEventListener: (eventName: string, handler: (isConnected: boolean) => void) => void; - fetch: () => Promise; - } - static fetch(): Promise; - } - - class Easing { - static bezier(x1: number, y1: number, x2: number, y2: number): ((input: number) => number); - static linear(): ((input: number) => number); - } - - interface AnimationConfig { - isInteraction?: boolean; - useNativeDriver?: boolean; - } - - interface AnimatedTimingConfig extends AnimationConfig { - toValue: number; - duration?: number; - delay?: number - easing?: (input: number) => number; - } - - interface CompositeAnimation { - start(callback?: AnimatedEndCallback): void; - stop: () => void; - } - - type AnimatedEndResult = { finished: boolean }; - type AnimatedEndCallback = (result: AnimatedEndResult) => void; - - module Animated { - function createAnimatedComponent(Component: any, notCollapsable?: boolean): any; - function delay(time: number): CompositeAnimation; - function timing(value: Animated.Value, config: AnimatedTimingConfig): CompositeAnimation; - function parallel(animations: CompositeAnimation[]): CompositeAnimation - function sequence(animations: CompositeAnimation[]): CompositeAnimation - class Value { - constructor(val: number); - setValue(value: number): void; - addListener(callback: any): string; - removeListener(id: string): void; - removeAllListeners(): void; - interpolate(config: any): Value; - } - class View extends ReactNativeBaseComponent { } - class Image extends ReactNativeBaseComponent { } - class Text extends ReactNativeBaseComponent { } - } - - interface IUpdateLayoutAnimationConfig { - duration?: number; - delay?: number; - - springDamping?: number; - initialVelocity?: number; - - type?: string; - } - - interface ICreateLayoutAnimationConfig extends IUpdateLayoutAnimationConfig { - property?: string; - } - - interface ILayoutAnimationConfig { - duration: number; - create?: ICreateLayoutAnimationConfig; - update?: IUpdateLayoutAnimationConfig; - } - - module LayoutAnimation { - function configureNext(config: ILayoutAnimationConfig): void; - - module Types { - var spring: string; - var linear: string; - var easeInEaseOut: string; - var easeIn: string; - var easeOut: string; - var keyboard: string; - } - - module Properties { - var opacity: string; - var scaleXY: string; - } - } - - class DeviceEventSubscription { - remove(): void; - } - - class NativeAppEventEmitter { - static addListener(eventId: string, callback: Function): DeviceEventSubscription; - } - - module DeviceEventEmitter{ - function addListener(name: string, callback: Function): void; - } - - module AppState { - var currentState: string; - function addEventListener(type: string, handler: Function): void; - function removeEventListener(type: string, handler: Function): void; - } - - module AppStateIOS { - var currentState: string; - function addEventListener(type: string, handler: Function): void; - function removeEventListener(type: string, handler: Function): void; - } - - module Touchable { - type RectOffset = { - top: number, - left: number, - right: number, - bottom: number - } - - interface State { - touchable: any - } - - interface TouchableMixin extends React.Mixin { - touchableGetInitialState: () => State - touchableHandleStartShouldSetResponder: () => {} - touchableHandleResponderTerminationRequest: () => {} - touchableHandleResponderGrant: (e: React.SyntheticEvent, dispatchID: string) => {} - touchableHandleResponderMove: (e: React.SyntheticEvent) => {} - touchableHandleResponderRelease: (e: React.SyntheticEvent) => {} - touchableHandleResponderTerminate: (e: React.SyntheticEvent) => {} - touchableHandleActivePressIn?: (e: React.SyntheticEvent) => {} - touchableHandleActivePressOut?: (e: React.SyntheticEvent) => {} - touchableHandlePress?: (e: React.SyntheticEvent) => {} - touchableHandleLongPress?: (e: React.SyntheticEvent) => {} - touchableGetHighlightDelayMS?: () => number - touchableGetPressRectOffset?: () => RectOffset - } - - var Mixin: TouchableMixin; - } - - class EmitterSubscription { - remove(): void; - } - - module Keyboard { - function addListener(eventType: string, listener: Function, context?: any): EmitterSubscription; - function removeAllListeners(eventType: string): void; - function removeSubscription(subscription: EmitterSubscription): void; - } - - module PixelRatio { - /** - * Returns the device pixel density. Some examples: - * - * - PixelRatio.get() === 1 - * - mdpi Android devices (160 dpi) - * - PixelRatio.get() === 1.5 - * - hdpi Android devices (240 dpi) - * - PixelRatio.get() === 2 - * - iPhone 4, 4S - * - iPhone 5, 5c, 5s - * - iPhone 6 - * - xhdpi Android devices (320 dpi) - * - PixelRatio.get() === 3 - * - iPhone 6 plus - * - xxhdpi Android devices (480 dpi) - * - PixelRatio.get() === 3.5 - * - Nexus 6 - **/ - function get(): number; - - /** - * Returns the scaling factor for font sizes. This is the ratio that is used to calculate the - * absolute font size, so any elements that heavily depend on that should use this to do - * calculations. - * - * If a font scale is not set, this returns the device pixel ratio. - * - * Currently this is only implemented on Android and reflects the user preference set in - * Settings > Display > Font size, on iOS it will always return the default pixel ratio. - * @platform android - **/ - function getFontScale(): number; - - /** - * Converts a layout size (dp) to pixel size (px). - * - * Guaranteed to return an integer number. - **/ - function getPixelSizeForLayoutSize(layoutSize: number): number; - - /** - * Rounds a layout size (dp) to the nearest layout size that corresponds to - * an integer number of pixels. For example, on a device with a PixelRatio - * of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to - * exactly (8.33 * 3) = 25 pixels. - **/ - function roundToNearestPixel(layoutSize: number): number; - } - - interface IncrementalProps extends ComponentPropsStyleBase { - onDone?: () => void; - name: string; - children?: any; - } - - interface IncrementalPresenterProps extends ComponentPropsStyleBase { - name: string; - disabled?: boolean; - onDone?: () => void; - onLayout?: (event: Object) => void; - style?: any; - children?: any; - } - - class Incremental extends ReactNativeBaseComponent { - } - - class IncrementalGroup extends ReactNativeBaseComponent{ - } - - class IncrementalPresenter extends ReactNativeBaseComponent { - } - - module JSEventLoopWatchdog { - function install(obj: any): void; - } - - module InteractionManager { - function setDeadline(deadline: number): void; - } - - interface I18nManager { - isRTL: boolean - allowRTL: (allowRTL: boolean) => {} - forceRTL: (forceRTL: boolean) => {} - } - - export var I18nManager: I18nManager; -} - -interface GeoConfiguration { - skipPermissionRequests: boolean; -} - -interface Geolocation { - // React Native addition to navigator.geolocation - setRNConfiguration(config: GeoConfiguration): void; -} - diff --git a/extensions/imagesvg/src/web/ImageSvg.tsx b/extensions/imagesvg/src/web/ImageSvg.tsx index cf3f7ede6..e1d7e7018 100644 --- a/extensions/imagesvg/src/web/ImageSvg.tsx +++ b/extensions/imagesvg/src/web/ImageSvg.tsx @@ -1,29 +1,27 @@ /* -* ImageSvg.tsx -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Web-specific implementation of the cross-platform abstraction for -* SVG (scalable vector graphics) images. -*/ - -import assert = require('assert'); -import React = require('react'); -import ReactDOM = require('react-dom'); + * ImageSvg.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Web-specific implementation of the cross-platform abstraction for + * SVG (scalable vector graphics) images. + */ + +import * as React from 'react'; import { Styles as RXStyles } from 'reactxp'; -import SvgInterfaces = require('../common/Interfaces'); -import SvgTypes = require('../common/Types'); +import assert from '../common/assert'; +import { ImageSvgProps } from '../common/Types'; -export class ImageSvg extends React.Component { +export class ImageSvg extends React.Component { render() { - assert.ok(this.props.width && this.props.height, 'The width and height on imagesvg are mandatory.'); + assert(this.props.width && this.props.height, 'The width and height on imagesvg are mandatory.'); if (this.props.width > 0 && this.props.height > 0) { - let combinedStyles = RXStyles.combine([{ + const combinedStyles = RXStyles.combine([{ display: 'flex', - position: 'relative' - }, this.props.style]) as any; + position: 'relative', + } as any, this.props.style]); if (this.props.fillColor !== undefined) { combinedStyles.fill = this.props.fillColor; @@ -54,10 +52,10 @@ export class ImageSvg extends React.Component { } if (this.props.webShadow) { - let aliases = RXStyles.getCssPropertyAliasesCssStyle(); + const aliases = RXStyles.getCssPropertyAliasesCssStyle(); if (this._isFilterDropShadowSupported()) { - let filterAlias = aliases['filter'] || 'filter'; + const filterAlias = aliases.filter || 'filter'; combinedStyles[filterAlias] = 'drop-shadow(' + this.props.webShadow + ')'; } } diff --git a/extensions/imagesvg/src/web/PluginBase.ts b/extensions/imagesvg/src/web/PluginBase.ts index d2df9068f..fc5ed7bee 100644 --- a/extensions/imagesvg/src/web/PluginBase.ts +++ b/extensions/imagesvg/src/web/PluginBase.ts @@ -1,13 +1,15 @@ /* -* PluginBase.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the Web implementation of the plugin. -*/ + * PluginBase.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Web implementation of the plugin. + */ + +import * as Types from '../common/Types'; import ImageSvg from './ImageSvg'; import SvgPath from './SvgPath'; -import Types = require('../common/Types'); +import SvgRect from './SvgRect'; -export { ImageSvg as default, SvgPath, Types }; +export { ImageSvg as default, SvgPath, SvgRect, Types }; diff --git a/extensions/imagesvg/src/web/SvgPath.tsx b/extensions/imagesvg/src/web/SvgPath.tsx index 988d1ef6a..b154530b0 100644 --- a/extensions/imagesvg/src/web/SvgPath.tsx +++ b/extensions/imagesvg/src/web/SvgPath.tsx @@ -1,18 +1,17 @@ /* -* SvgPath.tsx -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Web-specific implementation of the cross-platform abstraction for -* SVG Path (scalable vector graphics) images. -*/ + * SvgPath.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Web-specific implementation of the cross-platform abstraction for + * SVG Path elements. + */ -import React = require('react'); +import * as React from 'react'; -import SvgInterfaces = require('../common/Interfaces'); -import SvgTypes = require('../common/Types'); +import { SvgPathProps } from '../common/Types'; -export class SvgPath extends React.Component { +export class SvgPath extends React.Component { render() { return ( { + render() { + return ( + + ); + } +} + +export default SvgRect; diff --git a/extensions/imagesvg/src/windows/ImageSvg.tsx b/extensions/imagesvg/src/windows/ImageSvg.tsx index 95c831533..ab526967e 100644 --- a/extensions/imagesvg/src/windows/ImageSvg.tsx +++ b/extensions/imagesvg/src/windows/ImageSvg.tsx @@ -1,20 +1,19 @@ -/** -* ImageSvg.tsx -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* RN-specific implementation of the cross-platform abstraction for -* SVG (scalable vector graphics) images. -*/ +/** + * ImageSvg.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform abstraction for + * SVG (scalable vector graphics) images. + */ -import React = require('react'); +import * as React from 'react'; -import SvgInterfaces = require('../common/Interfaces'); -import SvgTypes = require('../common/Types'); +import { ImageSvgProps } from '../common/Types'; // TODO: #694092 Not implemented -export class ImageSvg extends React.Component { +export class ImageSvg extends React.Component { render(): any { return null; } diff --git a/extensions/imagesvg/src/windows/PluginBase.ts b/extensions/imagesvg/src/windows/PluginBase.ts index 2221dc6b1..0e184f946 100644 --- a/extensions/imagesvg/src/windows/PluginBase.ts +++ b/extensions/imagesvg/src/windows/PluginBase.ts @@ -1,13 +1,15 @@ /* -* PluginBase.ts -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the UWP implementation of the plugin. -*/ + * PluginBase.ts + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the UWP implementation of the plugin. + */ + +import * as Types from '../common/Types'; import ImageSvg from './ImageSvg'; import SvgPath from './SvgPath'; -import Types = require('../common/Types'); +import SvgRect from './SvgRect'; -export { ImageSvg as default, SvgPath, Types }; +export { ImageSvg as default, SvgPath, SvgRect, Types }; diff --git a/extensions/imagesvg/src/windows/SvgPath.tsx b/extensions/imagesvg/src/windows/SvgPath.tsx index 500a93d03..fecabb851 100644 --- a/extensions/imagesvg/src/windows/SvgPath.tsx +++ b/extensions/imagesvg/src/windows/SvgPath.tsx @@ -1,20 +1,19 @@ /* -* SvgPath.tsx -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* RN-specific implementation of the cross-platform abstraction for -* SVG Path (scalable vector graphics) elements. -*/ + * SvgPath.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform abstraction for + * SVG Path elements. + */ -import React = require('react'); +import * as React from 'react'; -import SvgInterfaces = require('../common/Interfaces'); -import SvgTypes = require('../common/Types'); +import { SvgPathProps } from '../common/Types'; // TODO: #694092 Not implemented -export class SvgPath extends React.Component { +export class SvgPath extends React.Component { render(): any { return null; } diff --git a/extensions/imagesvg/src/windows/SvgRect.tsx b/extensions/imagesvg/src/windows/SvgRect.tsx new file mode 100644 index 000000000..efcfe62cf --- /dev/null +++ b/extensions/imagesvg/src/windows/SvgRect.tsx @@ -0,0 +1,22 @@ +/* + * SvgRect.tsx + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform abstraction for + * SVG Rect elements. + */ + +import * as React from 'react'; + +import { SvgRectProps } from '../common/Types'; + +// TODO: #694092 Not implemented + +export class SvgRect extends React.Component { + render(): any { + return null; + } +} + +export default SvgRect; diff --git a/extensions/imagesvg/tsconfig.json b/extensions/imagesvg/tsconfig.json index 97d99717f..b504e8484 100644 --- a/extensions/imagesvg/tsconfig.json +++ b/extensions/imagesvg/tsconfig.json @@ -7,13 +7,12 @@ "target": "es5", "experimentalDecorators": true, "noImplicitAny": true, - "outDir": "dist/" + "outDir": "dist/", + "skipLibCheck": true }, - - "filesGlob": [ - "src/**/*{ts,tsx}" + "include": [ + "src/**/*" ], - "exclude": [ "dist", "node_modules" diff --git a/extensions/navigation/.eslintrc.json b/extensions/navigation/.eslintrc.json new file mode 100644 index 000000000..45914c8c0 --- /dev/null +++ b/extensions/navigation/.eslintrc.json @@ -0,0 +1,43 @@ +{ + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": ["skype", "skype/react"], + "rules": { + "no-console": [ + "error", + { + "allow": [ + "error" + ] + } + ] + }, + "overrides": [ + { + "files": [ + "*.tsx" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off" + } + }, + { + "files": [ + "Navigator.tsx" + ], + "rules": { + "no-duplicate-imports": "off" + } + }, + { + "files": [ + "*.d.ts" + ], + "rules": { + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/member-naming": "off" + } + } + ] +} diff --git a/extensions/navigation/.gitignore b/extensions/navigation/.gitignore index b1866059e..dc65a21e8 100644 --- a/extensions/navigation/.gitignore +++ b/extensions/navigation/.gitignore @@ -1,3 +1,4 @@ dist node_modules .DS_Store +package-lock.json \ No newline at end of file diff --git a/extensions/navigation/README.md b/extensions/navigation/README.md index 0b5b7385b..86adcd77a 100644 --- a/extensions/navigation/README.md +++ b/extensions/navigation/README.md @@ -2,7 +2,7 @@ This module provides cross-platform navigation support [ReactXP](https://microsoft.github.io/reactxp/) library. ## Documentation -For detailed documentation, look [here](https://microsoft.github.io/reactxp/docs/extensions/navigation.html). +For detailed documentation, look [here](https://microsoft.github.io/reactxp/docs/extensions/navigator.html). ### Prerequisites * [ReactXP](https://github.com/microsoft/reactxp/) diff --git a/extensions/navigation/package.json b/extensions/navigation/package.json index 71a6f8471..8aa5fcfe4 100644 --- a/extensions/navigation/package.json +++ b/extensions/navigation/package.json @@ -1,10 +1,11 @@ { "name": "reactxp-navigation", - "version": "1.0.14", + "version": "2.0.0", "description": "Plugin for ReactXP that provides a navigation framework", "scripts": { "build": "tsc", - "tslint": "tslint --project tsconfig.json -r tslint.json --fix || true" + "lint": "eslint --ext .ts,.tsx src", + "lint:fix": "npm run lint -- --fix" }, "repository": { "type": "git", @@ -16,22 +17,30 @@ "react" ], "dependencies": { - "@types/lodash": "^4.14.62", - "@types/node": "^6.0.65", - "assert": "^1.3.0", - "lodash": "^4.17.1", - "rebound": "^0.0.13", - "reactxp-experimental-navigation": "^1.0.11" + "lodash": "^4.17.15", + "rebound": "^0.1.0", + "reactxp-experimental-navigation": "1.0.14" }, "peerDependencies": { - "react": "^0.14.8", - "react-dom": "^15.4.1", - "react-native": "^0.46.0" + "react": "^16.3.0", + "reactxp": "^2.0.0", + "react-dom": "^16.3.0", + "react-native": ">=0.57", + "react-native-windows": "^0.57.1" }, "devDependencies": { - "reactxp": "^0.46.2", - "typescript": "2.4.1", - "tslint": "^5.0.0" + "@types/lodash": "^4.14.149", + "@types/react-dom": "^16.9.4", + "@types/react-native": "^0.60.23", + "@typescript-eslint/eslint-plugin": "2.15.0", + "eslint": "6.8.0", + "eslint-config-skype": "1.5.0", + "eslint-plugin-import": "2.20.0", + "eslint-plugin-react": "7.17.0", + "react": "^16.3.0", + "react-dom": "^16.3.0", + "reactxp": "^2.0.0", + "typescript": "3.7.4" }, "author": "ReactXP Team ", "license": "MIT", diff --git a/extensions/navigation/src/common/Types.ts b/extensions/navigation/src/common/Types.ts index 266ceea62..f6c12f19a 100644 --- a/extensions/navigation/src/common/Types.ts +++ b/extensions/navigation/src/common/Types.ts @@ -1,14 +1,14 @@ /** -* Types.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* Type definitions for reactxp-naviigation extension. -*/ + * Types.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * Type definitions for reactxp-naviigation extension. + */ // Use only for type data -import React = require('react'); -import RX = require('reactxp'); +import * as React from 'react'; +import * as RX from 'reactxp'; export type ReactNode = React.ReactNode; @@ -38,50 +38,52 @@ export interface NavigatorRoute { } // NOTE: Experimental navigator only -export type NavigationTransitionSpec = { +export interface NavigationTransitionSpec { duration?: number; // NOTE: Elastic and bounce easing will not work as expected due to how the navigator interpolates styles easing?: RX.Types.Animated.EasingFunction; -}; +} // NOTE: Experimental navigator only -export type NavigationTransitionStyleConfig = { - // By default input range is defined as [index - 1, index, index + 1]; - // Input and output ranges must contain the same number of elements - inputRange?: number[]; - opacityOutput: number | number[]; - scaleOutput: number | number[]; - translateXOutput: number | number[]; - translateYOutput: number | number[]; -}; +export interface NavigationTransitionStyleConfig { + // By default input range is defined as [index - 1, index, index + 1]; + // Input and output ranges must contain the same number of elements + inputRange?: number[]; + opacityOutput: number | number[]; + scaleOutput: number | number[]; + translateXOutput: number | number[]; + translateYOutput: number | number[]; +} // NOTE: Experimental navigator only -export type CustomNavigatorSceneConfig = { - // Optional transition styles - transitionStyle?: (sceneIndex: number, sceneDimensions: RX.Types.Dimensions) => NavigationTransitionStyleConfig; - // Optional overrides for duration, easing, and timing - transitionSpec?: NavigationTransitionSpec; - // Optional cardStyle override - cardStyle?: RX.Types.ViewStyleRuleSet; - // Optionally hide drop shadow - hideShadow?: boolean; - // Optionally flip the visual order of the last two scenes - presentBelowPrevious?: boolean; -}; +export interface CustomNavigatorSceneConfig { + // Optional transition styles + transitionStyle: (sceneIndex: number, sceneDimensions: RX.Types.Dimensions) => NavigationTransitionStyleConfig; + // Optional overrides for duration, easing, and timing + transitionSpec?: NavigationTransitionSpec; + // Optional cardStyle override + cardStyle?: RX.Types.ViewStyleRuleSet; + // Optionally hide drop shadow + hideShadow?: boolean; + // Optionally flip the visual order of the last two scenes + presentBelowPrevious?: boolean; +} export interface NavigatorProps extends RX.CommonProps { - renderScene: (route: NavigatorRoute) => JSX.Element | undefined; - navigateBackCompleted?: () => void; - // NOTE: Arguments are only passed to transitionStarted by the experimental navigator - transitionStarted?: (progress?: RX.Types.AnimatedValue, - toRouteId?: string, fromRouteId?: string, - toIndex?: number, fromIndex?: number) => void; - transitionCompleted?: () => void; - cardStyle?: RX.Types.ViewStyleRuleSet; - children?: ReactNode; - // Selector of the navigator delegate. Currently make difference only in react-native. - delegateSelector?: NavigatorDelegateSelector; + renderScene: (route: NavigatorRoute) => JSX.Element | null; + navigateBackCompleted?: () => void; + // NOTE: Arguments are only passed to transitionStarted by the experimental navigator + transitionStarted?: (progress?: RX.Types.AnimatedValue, + toRouteId?: string, + fromRouteId?: string, + toIndex?: number, + fromIndex?: number) => void; + transitionCompleted?: () => void; + cardStyle?: RX.Types.ViewStyleRuleSet; + children?: ReactNode; + // Selector of the navigator delegate. Currently make difference only in react-native. + delegateSelector?: NavigatorDelegateSelector; } export enum CommandType { @@ -136,16 +138,16 @@ export abstract class NavigatorDelegate { this._owner.props.navigateBackCompleted(); } - // Indicate that we handled the event. + // Indicate that we handled the event. return true; } return false; - } + }; abstract getRoutes(): NavigatorRoute[]; abstract immediatelyResetRouteStack(nextRouteStack: NavigatorRoute[]): void; - abstract render(): JSX.Element; + abstract render(): JSX.Element | null; abstract processCommand(commandQueue: NavigationCommand[]): void; abstract handleBackPress(): void; } diff --git a/extensions/navigation/src/common/assert.ts b/extensions/navigation/src/common/assert.ts new file mode 100644 index 000000000..46aba16a5 --- /dev/null +++ b/extensions/navigation/src/common/assert.ts @@ -0,0 +1,14 @@ +/** + * assert + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + */ +const assert = (cond: any, message?: string | undefined): void => { + if (!cond) { + throw new Error(message || 'Assertion Failed'); + } +}; + +export default assert; diff --git a/extensions/navigation/src/common/lodashMini.ts b/extensions/navigation/src/common/lodashMini.ts index c67746d67..6c5fce390 100644 --- a/extensions/navigation/src/common/lodashMini.ts +++ b/extensions/navigation/src/common/lodashMini.ts @@ -1,19 +1,17 @@ /** -* lodashMini.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Imports a subset of lodash library needed for ReactXP's implementation. -*/ + * lodashMini.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Imports a subset of lodash library needed for ReactXP's implementation. + */ import assign = require('lodash/assign'); import clone = require('lodash/clone'); import cloneDeep = require('lodash/cloneDeep'); -import findIndex = require('lodash/findIndex'); import flatten = require('lodash/flatten'); import get = require('lodash/get'); -import isArray = require('lodash/isArray'); import isEmpty = require('lodash/isEmpty'); import isEqual = require('lodash/isEqual'); import isNumber = require('lodash/isNumber'); @@ -28,10 +26,8 @@ export { assign, clone, cloneDeep, - findIndex, flatten, get, - isArray, isEmpty, isEqual, isNumber, diff --git a/extensions/navigation/src/native-common/Navigator.tsx b/extensions/navigation/src/native-common/Navigator.tsx index a15aef384..8635155e7 100644 --- a/extensions/navigation/src/native-common/Navigator.tsx +++ b/extensions/navigation/src/native-common/Navigator.tsx @@ -1,32 +1,30 @@ /** -* Navigator.tsx -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Common native implementation for Navigator on mobile. -*/ - -import RN = require('react-native'); -import React = require('react'); -import RX = require('reactxp'); - + * Navigator.tsx + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Common native implementation for Navigator on mobile. + */ +import * as RX from 'reactxp'; + +import * as Types from '../common/Types'; import { Navigator as BaseNavigator, NavigatorDelegate, NavigatorDelegateSelector as DelegateSelector, NavigationCommand, NavigatorState, - CommandType + NavigatorProps, + NavigatorRoute, + CommandType, } from '../common/Types'; import NavigatorExperimentalDelegate from './NavigatorExperimentalDelegate'; -import { NavigatorProps, NavigatorRoute } from '../common/Types'; -import Types = require('../common/Types'); export class DefaultDelegateSelector implements DelegateSelector { getNavigatorDelegate(navigator: BaseNavigator) { - return new NavigatorExperimentalDelegate(navigator); + return new NavigatorExperimentalDelegate(navigator); } } @@ -57,52 +55,52 @@ export class NavigatorImpl extends BaseNavigator { } protected getRoutes(): NavigatorRoute[] { - return this._delegate.getRoutes(); + return this._delegate.getRoutes(); } // Push a new route if initial route doesn't exist - public push(route: NavigatorRoute): void { + push(route: NavigatorRoute): void { this._enqueueCommand({ type: CommandType.Push, param: { - route: route - } + route: route, + }, }); } - public pop(): void { + pop(): void { this._enqueueCommand({ type: CommandType.Pop, - param: {} + param: {}, }); } - public replace(route: NavigatorRoute): void { + replace(route: NavigatorRoute): void { this._enqueueCommand({ type: CommandType.Replace, param: { - route: route - } + route: route, + }, }); } - public replacePrevious(route: NavigatorRoute): void { + replacePrevious(route: NavigatorRoute): void { this._enqueueCommand({ type: CommandType.Replace, param: { route: route, - value: -1 - } + value: -1, + }, }); } // This method replaces the route at the given index of the stack and pops to that index. - public replaceAtIndex(route: NavigatorRoute, index: number): void { - let routes = this.getRoutes(); + replaceAtIndex(route: NavigatorRoute, index: number): void { + const routes = this.getRoutes(); // Pop to index route and then replace if not last one if (index < routes.length - 1) { - let route = routes[index]; + const route = routes[index]; this.popToRoute(route); } @@ -111,34 +109,34 @@ export class NavigatorImpl extends BaseNavigator { } // Reset route stack with default route stack - public immediatelyResetRouteStack(nextRouteStack: NavigatorRoute[]): void { - this._delegate.immediatelyResetRouteStack(nextRouteStack); + immediatelyResetRouteStack(nextRouteStack: NavigatorRoute[]): void { + this._delegate.immediatelyResetRouteStack(nextRouteStack); } - public popToRoute(route: NavigatorRoute): void { + popToRoute(route: NavigatorRoute): void { this._enqueueCommand({ type: CommandType.Pop, param: { - route: route - } + route: route, + }, }); } - public popToTop(): void { + popToTop(): void { this._enqueueCommand({ type: CommandType.Pop, param: { - value: -1 - } + value: -1, + }, }); } - public getCurrentRoutes(): NavigatorRoute[] { + getCurrentRoutes(): NavigatorRoute[] { return this.getRoutes(); } // Render without initial route to get a reference for Navigator object - public render(): JSX.Element { + render(): JSX.Element { return this._delegate.render(); } @@ -152,7 +150,7 @@ export class NavigatorImpl extends BaseNavigator { } } -export import Types = Types; export default NavigatorImpl; export const Navigator = NavigatorImpl; export const NavigatorDelegateSelector = new DefaultDelegateSelector(); +export { Types }; diff --git a/extensions/navigation/src/native-common/NavigatorExperimentalDelegate.tsx b/extensions/navigation/src/native-common/NavigatorExperimentalDelegate.tsx index 5528af198..8ff568984 100644 --- a/extensions/navigation/src/native-common/NavigatorExperimentalDelegate.tsx +++ b/extensions/navigation/src/native-common/NavigatorExperimentalDelegate.tsx @@ -1,25 +1,25 @@ /** -* NavigatorExperimentalDelegate.tsx -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Delegate which encapsulates experimental react-native Navigator experience. -* The main difference of Experimental Navigator is that it uses Animated for navigation animation -* so we can enable useNativeDriver options for those animations. -* -* Currently, Android support on NativeAnimations is more stable and performant than iOS. -* That's why we need to have the ability to pick different implementations for different platforms. -*/ - -import _ = require('../common/lodashMini'); -import assert = require('assert'); -import Navigation = require('reactxp-experimental-navigation'); -import React = require('react'); -import RX = require('reactxp'); -import RN = require('react-native'); - -import { + * NavigatorExperimentalDelegate.tsx + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Delegate which encapsulates experimental react-native Navigator experience. + * The main difference of Experimental Navigator is that it uses Animated for navigation animation + * so we can enable useNativeDriver options for those animations. + * + * Currently, Android support on NativeAnimations is more stable and performant than iOS. + * That's why we need to have the ability to pick different implementations for different platforms. + */ + +import * as React from 'react'; +import * as RN from 'react-native'; +import * as RX from 'reactxp'; +import * as Navigation from 'reactxp-experimental-navigation'; + +import assert from '../common/assert'; +import * as _ from '../common/lodashMini'; +import { CommandType, CustomNavigatorSceneConfig, Navigator, @@ -27,7 +27,7 @@ import { NavigationCommand, NavigatorDelegate, NavigatorRoute, - NavigatorState + NavigatorState, } from '../common/Types'; type NavigationSceneRendererProps = Navigation.NavigationSceneRendererProps; @@ -54,14 +54,12 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { private _state: Navigation.NavigationState; private _transitionSpec: TransitionSpec; - private _navigationInProgress: boolean; constructor(navigator: Navigator) { super(navigator); - const route: NavigationRouteState = { key: '0', route: { routeId: 0, sceneConfigType: 0 }}; - this._state = { index: 0, routes: [ route ] }; + const route: NavigationRouteState = { key: '0', route: { routeId: 0, sceneConfigType: 0 } }; + this._state = { index: 0, routes: [route] }; this._transitionSpec = this._buildTransitionSpec(this._state); - console.log('initial transition spec is:', this._transitionSpec); } getRoutes(): NavigatorRoute[] { @@ -73,54 +71,53 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { // Reset route stack with default route stack immediatelyResetRouteStack(nextRouteStack: NavigatorRoute[]): void { - console.log('Stack state before reset:', this._state); const prevState = this._state; this._state = this._createParentState(nextRouteStack, prevState); this._transitionSpec = this._buildTransitionSpec(this._state); - console.log('Immediate stack reset:', this._state, this._transitionSpec); - this._owner.setState({state: this._state}); + this._owner.setState({ state: this._state }); } // Render without initial route to get a reference for Navigator object render(): JSX.Element { return ( ); } - private _convertCustomTransitionConfig(config: CustomNavigatorSceneConfig | undefined): - Navigation.NavigationCustomTransitionConfig | undefined { + private _convertCustomTransitionConfig( + config: CustomNavigatorSceneConfig | undefined): Navigation.NavigationCustomTransitionConfig | undefined { if (!config) { return undefined; } - let nativeConfig: Navigation.NavigationCustomTransitionConfig = { + const nativeConfig: Navigation.NavigationCustomTransitionConfig = { transitionStyle: config.transitionStyle, - presentBelowPrevious: config.presentBelowPrevious + presentBelowPrevious: config.presentBelowPrevious, }; if (config.transitionSpec) { - let transitionSpec: Navigation.NavigationTransitionSpec = {}; + const transitionSpec: Navigation.NavigationTransitionSpec = {}; if (config.transitionSpec.duration) { transitionSpec.duration = config.transitionSpec.duration; } if (config.transitionSpec.easing) { transitionSpec.easing = config.transitionSpec.easing.function; } - + nativeConfig.transitionSpec = transitionSpec; + } return nativeConfig; @@ -129,11 +126,11 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { private _buildTransitionSpec(state: Navigation.NavigationState): TransitionSpec { const route = (state.routes[state.index] as NavigationRouteState).route; let direction: Navigation.NavigationGestureDirection = 'horizontal'; - let customSceneConfig: Navigation.NavigationCustomTransitionConfig | undefined = undefined; - let enableGesture: boolean = false; - let responseDistance: number = 0; - let hideShadow = route && route.customSceneConfig && route.customSceneConfig.hideShadow; - let cardStyle: RX.Types.ViewStyleRuleSet | undefined = route && route.customSceneConfig + let customSceneConfig: Navigation.NavigationCustomTransitionConfig | undefined; + let enableGesture = false; + let responseDistance = 0; + const hideShadow = route && route.customSceneConfig && route.customSceneConfig.hideShadow; + const cardStyle: RX.Types.ViewStyleRuleSet | undefined = route && route.customSceneConfig ? route.customSceneConfig.cardStyle : undefined; let gestureDistanceSet = false; @@ -162,8 +159,8 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { } break; // Currently we support only right to left animation - //case NavigatorSceneConfigType.FloatFromRight: - //case NavigatorSceneConfigType.FloatFromLeft: + // case NavigatorSceneConfigType.FloatFromRight: + // case NavigatorSceneConfigType.FloatFromLeft: default: break; } @@ -188,34 +185,32 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { private _onTransitionEnd = () => { this._transitionSpec = this._buildTransitionSpec(this._state); - console.log('onTransitionEnd', this._transitionSpec); - this._owner.setState({state: this._state}); + this._owner.setState({ state: this._state }); if (this._owner.props.transitionCompleted) { this._owner.props.transitionCompleted(); } - } + }; private _onTransitionStart = (transitionProps: NavigationTransitionProps, prevTransitionProps?: NavigationTransitionProps) => { - console.log('onTransitionStart', this._transitionSpec); if (this._owner.props.transitionStarted) { const fromIndex = prevTransitionProps && prevTransitionProps.scene ? prevTransitionProps.scene.index : undefined; const toIndex = transitionProps.scene ? transitionProps.scene.index : undefined; const fromRouteId = prevTransitionProps && prevTransitionProps.scene ? prevTransitionProps.scene.route.key : undefined; const toRouteId = transitionProps.scene ? transitionProps.scene.route.key : undefined; this._owner.props.transitionStarted( - transitionProps.position, + transitionProps.position, toRouteId, fromRouteId, - toIndex, + toIndex, fromIndex); } - } + }; // Callback from Navigator.js to RX.Navigator private _renderScene = (props: NavigationSceneRendererProps): JSX.Element => { - let parentState: NavigationState = props.navigationState; - let sceneState: NavigationRouteState = parentState.routes[props.scene.index] as NavigationRouteState; + const parentState: NavigationState = props.navigationState; + const sceneState: NavigationRouteState = parentState.routes[props.scene.index] as NavigationRouteState; // Does the route exist? if (sceneState && sceneState.route) { @@ -225,7 +220,7 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { // No route? Return empty scene. return ; - } + }; handleBackPress(): void { this._owner.pop(); @@ -238,16 +233,16 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { } const previousState: NavigationState = this._state; - let useNewStateAsScene = false; + let useNewStateAsScene = false; + + const command = commandQueue.shift()!; + const route = command.param.route; + const value = command.param.value; - let command = commandQueue.shift()!!!; - let route = command.param.route; - let value = command.param.value; - console.log('processing navigation command:', JSON.stringify(command), 'on stack:', JSON.stringify(this._state)); switch (command.type) { case CommandType.Push: useNewStateAsScene = true; - this._state = StateUtils.push(this._state, this._createState(route!!!)); + this._state = StateUtils.push(this._state, this._createState(route)); break; case CommandType.Pop: @@ -268,10 +263,10 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { case CommandType.Replace: if (value === -1) { this._state = StateUtils.replaceAtIndex(this._state, this._state.routes.length - 2, - this._createState(route!!!)); + this._createState(route)); } else { this._state = StateUtils.replaceAtIndex(this._state, this._state.routes.length - 1, - this._createState(route!!!)); + this._createState(route)); } break; @@ -281,17 +276,14 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { break; } - console.log('stack after execution is:', JSON.stringify(this._state)); - if (previousState !== this._state) { if (useNewStateAsScene) { this._transitionSpec = this._buildTransitionSpec(this._state); } else { this._transitionSpec = this._buildTransitionSpec(previousState); } - console.log('transition spec:', this._transitionSpec, useNewStateAsScene); - this._owner.setState({state: this._state}); + this._owner.setState({ state: this._state }); } } @@ -300,15 +292,15 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { */ private _onNavigateBack = () => { this.onBackPress(); - } + }; private _createState(route: NavigatorRoute): NavigationRouteState { - return { key: route.routeId.toString(), route: route}; + return { key: route.routeId.toString(), route: route }; } private _createParentState(routes: NavigatorRoute[], prevState: NavigationState): NavigationState { const prevRoutes = prevState.routes as NavigationRouteState[]; - let children = _.map(routes, (element, index) => { + const children = _.map(routes, (element: NavigatorRoute, index: number) => { if (prevRoutes.length > index) { const prevRoute = prevRoutes[index]; // Navigator state reducer is a little bit naive, @@ -333,19 +325,19 @@ export class NavigatorExperimentalDelegate extends NavigatorDelegate { } private _popN(state: NavigationState, n: number): NavigationState { - assert.ok(n > 0, 'n < 0 please pass positive value'); + assert(n > 0, 'n < 0 please pass positive value'); const initialRoutes = state.routes; const initialLength = initialRoutes.length; - assert.ok(initialLength >= n, 'navigation stack underflow'); + assert(initialLength >= n, 'navigation stack underflow'); - let result: NavigationState = _.clone(state); + const result: NavigationState = _.clone(state); result.routes = initialRoutes.slice(0, initialLength - n); result.index = initialLength - n - 1; return result; } private _popToRoute(state: NavigationState, route: NavigatorRoute): NavigationState { - let popCount: number = 0; + let popCount = 0; for (let i = state.routes.length - 1; i >= 0; i--) { const child = state.routes[i] as NavigationRouteState; if (route.routeId === child.route.routeId) { diff --git a/extensions/navigation/src/typings/react-native-deprecated-custom-components.d.ts b/extensions/navigation/src/typings/react-native-deprecated-custom-components.d.ts index cf4b22b09..b2a6ac64a 100644 --- a/extensions/navigation/src/typings/react-native-deprecated-custom-components.d.ts +++ b/extensions/navigation/src/typings/react-native-deprecated-custom-components.d.ts @@ -1,5 +1,5 @@ declare module 'react-native-deprecated-custom-components' { - import RN = require('react-native'); + import * as RN from 'react-native'; interface NavigatorProps extends RN.ComponentPropsBase { configureScene?: Function; @@ -7,8 +7,8 @@ declare module 'react-native-deprecated-custom-components' { initialRouteStack?: any[]; navigatorBar?: any; navigator?: Navigator; - onDidFocus?: Function; //deprecated - onWillFocus?: Function; //deprecated + onDidFocus?: Function; // deprecated + onWillFocus?: Function; // deprecated renderScene: Function; sceneStyle?: RN.StyleRuleSet | RN.StyleRuleSet[]; } @@ -21,7 +21,7 @@ declare module 'react-native-deprecated-custom-components' { FloatFromBottom: any; FloatFromBottomAndroid: any; FadeAndroid: any; - HorizontalSwipeJump:any; + HorizontalSwipeJump: any; }; getCurrentRoutes(): any[]; jumpBack(): void; @@ -36,5 +36,4 @@ declare module 'react-native-deprecated-custom-components' { popToRoute(route: any): void; popToTop(): void; } - -} \ No newline at end of file +} diff --git a/extensions/navigation/src/typings/react-native.d.ts b/extensions/navigation/src/typings/react-native.d.ts deleted file mode 100644 index f6587f177..000000000 --- a/extensions/navigation/src/typings/react-native.d.ts +++ /dev/null @@ -1,1091 +0,0 @@ -/** -* react-native.d.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definition file for React Native, based on the React.js definition file -* on https://github.com/borisyankov/DefinitelyTyped. -*/ - -declare module 'react-native' { - // - // React - // ---------------------------------------------------------------------- - - import React = require('react'); - - // BT: Adding ProgressBarAndroid. It's not part of the DefinitelyTyped definitions. - class ProgressBarAndroid extends React.Component {} - - type ReactElement = React.ReactElement; - type ReactNode = React.ReactNode; - - function createElement

( - type: string, - props?: P, - ...children: React.ReactNode[]): React.ReactElement

; - - function cloneElement

( - element: P, - props ?: any - ): React.ReactElement

; - - interface SyntheticEvent extends React.SyntheticEvent {} - - function isValidElement(object: {}): boolean; - function findNodeHandle(componentOrHandle: any): number; - - var Children: React.ReactChildren; - - type PlatformString = 'android'|'ios'|'windows'; - var Platform: { - OS: PlatformString, - Version?: number - }; - - // - // Component base - // ---------------------------------------------------------------------- - - abstract class ReactNativeBaseComponent extends React.Component { - setNativeProps(nativeProps: P): void; - focus(): void; - blur(): void; - measure(callback: ((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void)): void; - measureLayout(relativeToNativeNode: number, onSuccess: ((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void), onFail: () => void): void; - refs: { - [key: string]: ReactNativeBaseComponent; - } - } - - // - // Style rules - // ---------------------------------------------------------------------- - - type StyleRuleSet = Object | Object[]; - - // - // Specific components - // ---------------------------------------------------------------------- - - interface ComponentPropsBase { - ref?: string | ((obj: ReactNativeBaseComponent) => void); - key?: string | number; - } - - interface ComponentPropsStyleBase extends ComponentPropsBase { - style?: StyleRuleSet | StyleRuleSet[]; - } - - interface ImageSource { - uri: string; - headers?: {[header: string]: string}; - } - - interface ImageProps extends ComponentPropsStyleBase { - onLayout?: Function; - resizeMode?: string; - resizeMethod?: string; // android only prop: 'auto' | 'resize' | 'scale' - source?: ImageSource | number; - testID?: string; - - // iOS - accessibilityLabel?: string; - shouldRasterizeIOS?: boolean; - accessible?: boolean; - capInsets?: Object; - defaultSource?: Object; - onError?: Function; - onLoad?: Function; - onLoadEnd?: (e: SyntheticEvent) => void; - onLoadStart?: Function; - onProgress?: Function; - - // Android - fadeDuration?: number; - } - - interface ActivityIndicatorProps extends ComponentPropsBase { - animating?: boolean; - color?: string; - onLayout?: Function; - size?: string; // enum { 'small', 'large' } - } - - interface TextProps extends ComponentPropsStyleBase { - importantForAccessibility?: string; // 'auto' | 'yes' | 'no' | 'no-hide-descendants'; - allowFontScaling?: boolean; - maxContentSizeMultiplier?: number; - children? : React.ReactNode; - numberOfLines? : number; - ellipsizeMode? : 'head' | 'middle' | 'tail' // There's also 'clip' but it is iOS only - onLayout? : Function; - onPress? : Function; - onLongPress? : Function; - selectable? : boolean; // only on android, windows - testID? : string; - - // iOS - suppressHighlighting?: boolean; - - // Android - textBreakStrategy?: 'highQuality' | 'simple'| 'balanced'; - elevation?: number; - } - - export interface PickerProps extends ComponentPropsStyleBase { - - /** - * Callback for when an item is selected. This is called with the - * following parameters: - * - itemValue: the value prop of the item that was selected - * - itemPosition: the index of the selected item in this picker - * @param itemValue - * @param itemPosition - */ - onValueChange?: ( itemValue: any, itemPosition: number ) => void - - /** - * Value matching value of one of the items. - * Can be a string or an integer. - */ - selectedValue?: any - - style?: StyleRuleSet | StyleRuleSet[] - - /** - * Used to locate this view in end-to-end tests. - */ - testId?: string - - ref?: string | ((obj: ReactNativeBaseComponent) => void); - } - - interface TouchableWithoutFeedbackProps extends ComponentPropsBase { - accessibilityComponentType? : string; //enum ( 'none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' ) - accessibilityTraits?: string | string[]; //enum( 'none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text', 'summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn' ) - accessible?: boolean; - importantForAccessibility? : string; //enum( 'auto', 'yes', 'no', 'no-hide-descendants' ) - delayLongPress?: number; - delayPressIn?: number; - delayPressOut?: number; - onLayout?: Function; - onLongPress?: Function; - onPress?: Function; - onPressIn?: Function; - onPressOut?: Function - } - - interface TouchableHighlightProps extends TouchableWithoutFeedbackProps, ComponentPropsStyleBase { - activeOpacity? : number; - children? : React.ReactNode; - onHideUnderlay?: Function; - onShowUnderlay?: Function; - underlayColor? : string; - } - - interface ResponderProps { - onMoveShouldSetResponder? : Function; - onResponderGrant? : Function; - onResponderMove? : Function; - onResponderReject? : Function; - onResponderRelease? : Function; - onResponderTerminate? : Function; - onResponderTerminationRequest? : Function; - onStartShouldSetResponder? : Function; - onStartShouldSetResponderCapture?: Function; - } - - interface ViewOnLayoutEvent { - nativeEvent: { - layout: { - x: number, - y: number, - width: number, - height: number - } - } - } - - type ViewLayerType = 'none' | 'software' | 'hardware'; - - interface CommonAccessibilityProps { - accessibilityLabel? : string; - accessible? : boolean; - onAcccessibilityTap? : Function; - - // android - accessibilityComponentType? : string; //enum ( 'none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' ) - accessibilityLiveRegion? : string; //enum ( 'none', 'polite', 'assertive' ) - importantForAccessibility? : string; //enum( 'auto', 'yes', 'no', 'no-hide-descendants' ) - - // iOS - accessibilityTraits?: string | string[]; //enum( 'none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text', 'summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn' ) - } - - interface ViewProps extends ComponentPropsBase, ResponderProps, ComponentPropsStyleBase, CommonAccessibilityProps { - children? : any; - onLayout? : ((ev: ViewOnLayoutEvent) => void); - onMagicTap? : Function; - pointerEvents? : string; //enum( 'box-none', 'none', 'box-only', 'auto' ); - removeClippedSubviews? : boolean; - testID? : string; - - // android - collapsable? : boolean; - needsOffscreenAlphaCompositing?: boolean; - renderToHardwareTextureAndroid?: boolean; - viewLayerTypeAndroid? : ViewLayerType; - elevation? : number; - - // iOS - onAccessibilityTapIOS?: Function; - shouldRasterizeIOS? : boolean; - } - - interface ScrollViewProps extends ViewProps { - children?: any; - - contentContainerStyle?: StyleRuleSet | StyleRuleSet[]; - horizontal?: boolean; - keyboardDismissMode?: 'none' | 'interactive' | 'on-drag'; - keyboardShouldPersistTaps?: 'always' | 'never' | 'handled'; - onScroll?: Function; - onScrollBeginDrag?: Function; - onScrollEndDrag?: Function; - onContentSizeChange?: (width: number, height: number) => void; - showsHorizontalScrollIndicator?: boolean; - showsVerticalScrollIndicator?: boolean; - removeClippedSubviews?: boolean; - - // iOS - automaticallyAdjustContentInsets?: boolean; - //contentInset?: EdgeInsetsPropType; - //contentOffset?: PointPropType; - bounces?: boolean; - bouncesZoom?: boolean; - alwaysBounceHorizontal?: boolean; - alwaysBounceVertical?: boolean; - centerContent?: boolean; - decelerationRate?: number; - directionalLockEnabled?: boolean; - canCancelContentTouches?: boolean; - maximumZoomScale?: number; - minimumZoomScale?: number; - onScrollAnimationEnd?: Function; - pagingEnabled?: boolean; - scrollEnabled?: boolean; - scrollEventThrottle?: number; - scrollsToTop?: boolean; - stickyHeaderIndices?: [number]; - snapToInterval?: number; - snapToAlignment?: string; // enum( 'start', 'center', 'end' ) - zoomScale?: number; - overScrollMode?: string; //enum( 'always', 'always-if-content-scrolls', 'never' ) - // iOS - scrollIndicatorInsets?: {top: number, left: number, bottom: number, right: number }; - } - - interface ListViewDataSourceCallback { - rowHasChanged: (r1: T, r2: T) => boolean; - } - - interface ListViewDataSource { - new (onAsset: ListViewDataSourceCallback): ListViewDataSource; - cloneWithRows(rowList: T[]): void; - } - - interface ListViewProps extends ScrollViewProps { - dataSource: Object; //PropTypes.instanceOf(ListViewDataSource).isRequired - renderSeparator?: Function; - renderRow: Function; - initialListSize?: number; - onEndReached?: (e: React.SyntheticEvent) => void; - onEndReachedThreshold?: number; - pageSize?: number; - renderFooter?: Function; - renderHeader?: Function; - renderSectionHeader?: Function; - renderScrollComponent: Function; - scrollRenderAheadDistance?: number; - onChangeVisibleRows?: Function; - removeClippedSubviews?: boolean; - } - - interface ModalProps extends ComponentPropsBase { - animationType?: string; // enum( 'none', 'slide', 'fade' ) - onDismiss?: Function; - transparent?: boolean; - onRequestClose: () => void; - } - - interface TextInputProps extends ComponentPropsStyleBase, CommonAccessibilityProps { - autoCapitalize?: string; // enum('none', 'sentences', 'words', 'characters') - autoCorrect?: boolean; - autoFocus?: boolean; - blurOnSubmit?: boolean; - defaultValue?: string; - editable?: boolean; - keyboardType?: string; // enum("default", 'numeric', 'email-address', "ascii-capable", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search') - multiline?: boolean; - onBlur?: ((e: React.FocusEvent) => void); - onKeyPress?: (e: SyntheticEvent) => void; - onChange?: Function; - onChangeText?: ((changedText: string) => void); - onSelectionChange?: ((selection: SyntheticEvent) => void); - onEndEditing?: Function; - onFocus?: ((e: React.FocusEvent) => void); - onLayout?: ((props: { x: number, y: number, width: number, height: number }) => void); - onSubmitEditing?: Function; - onScroll?: Function; - placeholder?: string; - placeholderTextColor?: string; - returnKeyType?: string; // enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') - secureTextEntry?: boolean; - testID?: string; - textAlign?: string; // enum('auto' | 'left' | 'right' | 'center' | 'justify') - allowFontScaling?: boolean; - maxContentSizeMultiplier?: number; - selection?: { start: number, end: number }; - - //iOS and android - selectionColor?: string; - - value: string; - //iOS - clearButtonMode?: string; // enum('never', 'while-editing', 'unless-editing', 'always') - clearTextOnFocus?: boolean; - enablesReturnKeyAutomatically?: boolean; - keyboardAppearance?: string; // enum ('default', 'light', 'dark') - maxLength?: number; - numberOfLines?: number; - selectTextOnFocus?: boolean; - selectionState?: any; // see DocumentSelectionState.js - spellCheck?: boolean; - //android - textAlignVertical?: string; // enum('top', 'center', 'bottom') - textAlignVerticalAndroid?: string; // enum('top', 'center', 'bottom') - textAlignAndroid?: string; - underlineColorAndroid?: string; - disableFullscreenUI?: boolean; - textBreakStrategy?: 'highQuality' | 'simple' | 'balanced'; - } - - interface TextInputState { - currentlyFocusedField(): number; - focusTextInput(textFieldID?: number): void; - blurTextInput(textFieldID?: number): void; - } - - interface WebViewProps extends ComponentPropsStyleBase { - automaticallyAdjustContentInsets?: boolean; - bounces?: boolean; - contentInset?: {top: number, left: number, bottom: number, right: number }; - injectedJavaScript?: string; - javaScriptEnabled?: boolean; - domStorageEnabled?: boolean; - onShouldStartLoadWithRequest?: Function; - onNavigationStateChange?: Function; - onLoad?: (e: SyntheticEvent) => void; - onLoadStart?: Function; - renderError?: Function; - onError?: Function; - renderLoading?: Function; - scalesPageToFit?: boolean; - scrollEnabled?: boolean; - startInLoadingState?: boolean; - source?: { uri: string; method?: string; headers?: Object; body?: string; } | { html: string; baseUrl?: string; }; - } - - interface DatePickerIOSProps extends ComponentPropsStyleBase { - date?: Date; - maximumDate?: Date; - minimumDate?: Date; - minuteInterval?: number; - mode?: string; - timeZoneOffsetInMinutes?: number; - - onDateChange?: (newDate: Date) => void; - } - - class DatePickerIOS extends ReactNativeBaseComponent { - } - - interface DatePickerAndroidProps extends ComponentPropsStyleBase { - date?: Date; - maxDate?: Date; - minDate?: Date; - - onDateChange?: (newDate: Date) => void; - } - - class DatePickerAndroid extends ReactNativeBaseComponent { - static open(options: { date: Date, maxDate: Date, minDate: Date }): Promise; - static dateSetAction: Function; - static dismissedAction: Function; - } - - interface TimePickerAndroidProps extends ComponentPropsStyleBase { - date?: Date; - maxDate?: Date; - minDate?: Date; - - onDateChange?: (newDate: Date) => void; - } - - class TimePickerAndroid extends ReactNativeBaseComponent { - static open(options: { hour: number, minute: number, is24Hour: boolean }): Promise; - static timeSetAction: Function; - static dismissedAction: Function; - } - - type DatePickerAction = { - action: Function; - day: number; - month: number; - year: number; - } - - type TimePickerAction = { - action: Function; - hour: number; - minute: number; - } - - class Image extends ReactNativeBaseComponent { - static prefetch(url: string): Promise; - } - class ActivityIndicator extends ReactNativeBaseComponent { } - class Text extends ReactNativeBaseComponent { } - class Picker extends ReactNativeBaseComponent { - static Item: any; - } - class TouchableHighlight extends ReactNativeBaseComponent { } - class TouchableWithoutFeedback extends ReactNativeBaseComponent { } - class View extends ReactNativeBaseComponent { } - class ScrollView extends ReactNativeBaseComponent { - getInnerViewNode(): number; - // TODO: Define ScrollResponder type - scrollTo(val: { x?: number; y?: number; animated?: boolean; }): void; - scrollBy(val: { deltaX?: number; deltaY?: number; animated?: boolean; }): void; - } - class ListView extends ReactNativeBaseComponent { - static DataSource: ListViewDataSource; - } - class Modal extends ReactNativeBaseComponent { } - class TextInput extends ReactNativeBaseComponent { - static State: TextInputState; - } - class WebView extends ReactNativeBaseComponent { - reload() : void; - goBack() : void; - goForward() : void; - } - - interface ActionSheetOptions { - options: string[]; - cancelButtonIndex?: number; - destructiveButtonIndex?: number; - title?: string; - message?: string; - } - - interface ShareActionSheetOptions { - message?: string; - url?: string; - subject?: string; - excludedActivityTypes?: string[]; - } - - class ActionSheetIOS { - static showActionSheetWithOptions(options: ActionSheetOptions, callback: (buttonIndex: number) => void): void; - static showShareActionSheetWithOptions(options: ShareActionSheetOptions, failureCallback: (error: string) => void, successCallback: (success: boolean, method: string) => void): void; - } - - class BackAndroid { - static addEventListener(eventName: string, callback: () => boolean): void; - static removeEventListener(eventName: string, callback: () => boolean): void; - } - - interface NavigatorIOSRoute { - component: any; - title: string; - passProps?: any; - backButtonTitle?: string; - backButtonIcon?: any; - leftButtonTitle?: string; - leftButtonIcon?: any; - onLeftButtonPress?: () => void; - rightButtonTitle?: string; - rightButtonIcon?: any; - onRightButtonPress?: () => void; - wrapperStyle?: any; - } - - interface NavigatorIOSProps extends ComponentPropsBase { - barTintColor?: string; - initialRoute: NavigatorIOSRoute; - itemWrapperStyle?: StyleRuleSet | StyleRuleSet[]; - navigationBarHidden?: boolean; - shadowHidden?: boolean; - style?:any; - tintColor?: string; - titleTextColor?: string; - translucent?: boolean; - interactivePopGestureEnabled?: boolean; - } - - class StatusBar { - // Native - static setHidden(hidden: boolean, animation?: string): void; //'none'|'fade'|'slide'; - - // iOS - static setBarStyle(barStyle: string, animated: boolean): void; //'default'|'light-content'; - static setNetworkActivityIndicatorVisible(value: boolean): void; - - // Android - static setBackgroundColor(color: string, animated?: boolean): void; - static setTranslucent(translucent: boolean): void; - } - - interface EventSubscription { - remove(): void; - } - - interface NavigatorIOSNavigationContext { - addListener(event: string, callback: (route: NavigatorIOSRoute) => void): EventSubscription; - } - - interface NavigatorIOSState { - observedTopOfStack: number; - requestedTopOfStack: number; - routeStack: NavigatorIOSRoute[]; - } - - class NavigatorIOS extends ReactNativeBaseComponent { - navigationContext: NavigatorIOSNavigationContext; - push(route: NavigatorIOSRoute): void; - pop(): void; - popN(n: number): void; - replace(route: NavigatorIOSRoute): void; - replacePrevious(route: NavigatorIOSRoute): void; - replacePreviousAndPop(route: NavigatorIOSRoute): void; - resetTo(route: NavigatorIOSRoute): void; - popToRoute(route: NavigatorIOSRoute): void; - popToTop(): void; - } - - // StyleSheet - class StyleSheet { - static create(obj: { [key: string]: any }): any; - static flatten: (s: StyleSheet) => { [key: string]: any }; - } - - class AppRegistry { - static registerComponent(appKey: string, getComponentFunc: Function): any; - } - - type CameraRollProps = { - /** - * The number of photos wanted in reverse order of the photo application - * (i.e. most recent first for SavedPhotos). - */ - first: number, - - /** - * A cursor that matches `page_info { end_cursor }` returned from a previous - * call to `getPhotos` - */ - after?: string, - - /** - * Specifies which group types to filter the results to. - */ - groupTypes?: string, // enum { 'Album', 'All', 'Event', 'Faces', 'Library', 'PhotoStream', 'SavedPhotos', // default }, - - /** - * Specifies filter on group names, like 'Recent Photos' or custom album - * titles. - */ - groupName?: string, - - /** - * Specifies filter on asset type - */ - assetType?: string; // enum { 'All', 'Videos', 'Photos', // default }, - - } - - type GetPhotosCallbackPropNode = { - node: { - type: string, - group_name: string, - image: { - uri: string, - height: number, - width: number, - isStored?: boolean, - }, - timestamp: number, - location?: { - latitude?: number, - longitude?: number, - altitude?: number, - heading?: number, - speed?: number, - } - } - } - - type GetPhotosCallbackProps = { - edges: GetPhotosCallbackPropNode[], - page_info: { - has_next_page: boolean, - start_cursor?: string, - end_cursor?: string, - } - } - - class Clipboard { - static setString(content: string): void; - static getString(): Promise; - } - - class CameraRoll { - static saveImageWithTag(tag: string, successCallback: Function, errorCallback: Function): void; - static getPhotos(params: CameraRollProps, callback: ((props: GetPhotosCallbackProps) => void), errorCallback: Function): void; - } - - class Linking { - static getInitialURL(): Promise; - static openURL(url: string): Promise; - static canOpenURL(url: string): Promise; - static addEventListener(type: string, handler: (event: any) => void): void; - static removeEventListener(type: string, handler: (event: any) => void): void; - } - - class AccessibilityInfo { - static fetch: () => Promise; - static addEventListener(type: string, handler: (event: any) => void): void; - static removeEventListener(type: string, handler: (event: any) => void): void; - static announceForAccessibility(announcement: string): void; - static setAccessibilityFocus(reactTag: number): void; - } - - interface AlertButtonSpec { - text?: string; - onPress?: () => void; - style?: string; // enum {default', 'cancel', 'destructive'} - } - - class Alert { - static alert( - title: string, - message?: string, - buttons?: AlertButtonSpec[], - type?: string // enum { 'default', 'plain-text', 'secure-text', 'login-password'} - ): void; - } - - class PushNotificationIOS { - static presentLocalNotification(details: { category: string, alertBody: string, soundName?: string}): void; - static scheduleLocalNotification(details: {alertBody: string, fireDate: Date}): void; - - static getApplicationIconBadgeNumber(callback: (badgeCount:number) => void): void; - static setApplicationIconBadgeNumber(number: number): void; - - static addEventListener(type: string, handler: (event: any) => void): void; - - static requestPermissions(permissions?: {alert?: boolean, badge?: boolean, sound?: boolean}): void; - static abandonPermissions(): void; - static checkPermissions(callback: (permissions: {alert: boolean, badge: boolean, sound: boolean}) => void): void; - - static getInitialNotification(): Promise; - - getMessage(): string; - getSound(): string; - getAlert(): any; - getBadgeCount(): number; - getData(): any; - } - - interface PanResponderGestureState { - stateID: number; - moveX: number; - moveY: number; - x0: number; - y0: number; - dx: number; - dy: number; - vx: number; - vy: number; - numberActiveTouches: number; - } - - interface ResponderSyntheticEvent extends React.SyntheticEvent { - touchHistory: Function; - } - - type PanResponderCreateConfig = { - onMoveShouldSetPanResponder?: (e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean, - onMoveShouldSetPanResponderCapture?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onStartShouldSetPanResponder?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onStartShouldSetPanResponderCapture?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderReject?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderGrant?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderStart?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderEnd?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderRelease?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderMove?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderTerminate?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderTerminationRequest?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onShouldBlockNativeResponder?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), // android only - onStartShouldSetResponderCapture?: (e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void, - - } - - class PanResponder { - static create(config: PanResponderCreateConfig): PanResponder; - panHandlers: ResponderProps; - } - - type DimensionType = { - width: number, - height: number, - scale: number, - fontScale: number, - } - - class Dimensions { - static set(obj: any): boolean; - static get(key: string): DimensionType; - } - - type RCTAppStateData = { app_state: string } - type RCTAppState = { - getCurrentAppState(successCallback: (appStateData: RCTAppStateData) => void, failureCallback: () => void): void; - } - - type FileInput = { - selectImage: Function; - } - - type SnapshotOptions = { - width?: number; - height?: number; - format?: 'png' | 'jpeg'; - quality?: number; - } - - type UIManager = { - measure: Function; - measureInWindow: Function; - measureLayout: Function; - measureLayoutRelativeToParent: Function; - dispatchViewManagerCommand: Function; - - getMaxContentSizeMultiplier: Function; - setMaxContentSizeMultiplier: Function; - - // ios - takeSnapshot: (view: any, options?: SnapshotOptions) => Promise; - - // Android - sendAccessibilityEvent: Function; - } - - type AccessibilityManager = { - getMultiplier: Function; - announceForAccessibility (announcement: string): void; - } - - // We don't use this module, but need to be able to check its existance - type NativeAnimatedModule = { - - }; - - class ImagePickerManager { - showImagePicker: Function; - launchCamera: Function; - launchImageLibrary: Function; - } - - class NativeModules { - static AppState: RCTAppState; - static FileInput: FileInput; - static UIManager: UIManager; - static AccessibilityManager: AccessibilityManager; - static ImagePickerManager: ImagePickerManager; - static Networking: { - clearCookies(callback: (success: boolean) => void): void; - } - static ContextMenuAndroid: { - show(buttons: any, callback: (command: string) => void): void; - } - static NativeAnimation: NativeAnimatedModule; - } - - class AsyncStorage { - static getItem(key: string, callback: (error: any, result: string) => void): void; - static setItem(key: string, value: string, callback: (error: any) => void): void; - static removeItem(key: string, callback: (error: any) => void): void; - static clear(callback: (error: any) => void): void; - } - - class NetInfo { - static isConnected: { - addEventListener: (eventName: string, handler: (isConnected: boolean) => void) => void; - removeEventListener: (eventName: string, handler: (isConnected: boolean) => void) => void; - fetch: () => Promise; - } - static fetch(): Promise; - } - - class Easing { - static bezier(x1: number, y1: number, x2: number, y2: number): ((input: number) => number); - static linear(): ((input: number) => number); - } - - interface AnimationConfig { - isInteraction?: boolean; - useNativeDriver?: boolean; - } - - interface AnimatedTimingConfig extends AnimationConfig { - toValue: number; - duration?: number; - delay?: number - easing?: (input: number) => number; - } - - interface CompositeAnimation { - start(callback?: AnimatedEndCallback): void; - stop: () => void; - } - - type AnimatedEndResult = { finished: boolean }; - type AnimatedEndCallback = (result: AnimatedEndResult) => void; - - module Animated { - function createAnimatedComponent(Component: any, notCollapsable?: boolean): any; - function delay(time: number): CompositeAnimation; - function timing(value: Animated.Value, config: AnimatedTimingConfig): CompositeAnimation; - function parallel(animations: CompositeAnimation[]): CompositeAnimation - function sequence(animations: CompositeAnimation[]): CompositeAnimation - class Value { - constructor(val: number); - setValue(value: number): void; - addListener(callback: any): string; - removeListener(id: string): void; - removeAllListeners(): void; - interpolate(config: any): Value; - } - class View extends ReactNativeBaseComponent { } - class Image extends ReactNativeBaseComponent { } - class Text extends ReactNativeBaseComponent { } - } - - interface IUpdateLayoutAnimationConfig { - duration?: number; - delay?: number; - - springDamping?: number; - initialVelocity?: number; - - type?: string; - } - - interface ICreateLayoutAnimationConfig extends IUpdateLayoutAnimationConfig { - property?: string; - } - - interface ILayoutAnimationConfig { - duration: number; - create?: ICreateLayoutAnimationConfig; - update?: IUpdateLayoutAnimationConfig; - } - - module LayoutAnimation { - function configureNext(config: ILayoutAnimationConfig): void; - - module Types { - var spring: string; - var linear: string; - var easeInEaseOut: string; - var easeIn: string; - var easeOut: string; - var keyboard: string; - } - - module Properties { - var opacity: string; - var scaleXY: string; - } - } - - class DeviceEventSubscription { - remove(): void; - } - - class NativeAppEventEmitter { - static addListener(eventId: string, callback: Function): DeviceEventSubscription; - } - - module DeviceEventEmitter{ - function addListener(name: string, callback: Function): void; - } - - module AppState { - var currentState: string; - function addEventListener(type: string, handler: Function): void; - function removeEventListener(type: string, handler: Function): void; - } - - module AppStateIOS { - var currentState: string; - function addEventListener(type: string, handler: Function): void; - function removeEventListener(type: string, handler: Function): void; - } - - module Touchable { - type RectOffset = { - top: number, - left: number, - right: number, - bottom: number - } - - interface State { - touchable: any - } - - interface TouchableMixin extends React.Mixin { - touchableGetInitialState: () => State - touchableHandleStartShouldSetResponder: () => {} - touchableHandleResponderTerminationRequest: () => {} - touchableHandleResponderGrant: (e: React.SyntheticEvent, dispatchID: string) => {} - touchableHandleResponderMove: (e: React.SyntheticEvent) => {} - touchableHandleResponderRelease: (e: React.SyntheticEvent) => {} - touchableHandleResponderTerminate: (e: React.SyntheticEvent) => {} - touchableHandleActivePressIn?: (e: React.SyntheticEvent) => {} - touchableHandleActivePressOut?: (e: React.SyntheticEvent) => {} - touchableHandlePress?: (e: React.SyntheticEvent) => {} - touchableHandleLongPress?: (e: React.SyntheticEvent) => {} - touchableGetHighlightDelayMS?: () => number - touchableGetPressRectOffset?: () => RectOffset - } - - var Mixin: TouchableMixin; - } - - class EmitterSubscription { - remove(): void; - } - - module Keyboard { - function addListener(eventType: string, listener: Function, context?: any): EmitterSubscription; - function removeAllListeners(eventType: string): void; - function removeSubscription(subscription: EmitterSubscription): void; - } - - module PixelRatio { - /** - * Returns the device pixel density. Some examples: - * - * - PixelRatio.get() === 1 - * - mdpi Android devices (160 dpi) - * - PixelRatio.get() === 1.5 - * - hdpi Android devices (240 dpi) - * - PixelRatio.get() === 2 - * - iPhone 4, 4S - * - iPhone 5, 5c, 5s - * - iPhone 6 - * - xhdpi Android devices (320 dpi) - * - PixelRatio.get() === 3 - * - iPhone 6 plus - * - xxhdpi Android devices (480 dpi) - * - PixelRatio.get() === 3.5 - * - Nexus 6 - **/ - function get(): number; - - /** - * Returns the scaling factor for font sizes. This is the ratio that is used to calculate the - * absolute font size, so any elements that heavily depend on that should use this to do - * calculations. - * - * If a font scale is not set, this returns the device pixel ratio. - * - * Currently this is only implemented on Android and reflects the user preference set in - * Settings > Display > Font size, on iOS it will always return the default pixel ratio. - * @platform android - **/ - function getFontScale(): number; - - /** - * Converts a layout size (dp) to pixel size (px). - * - * Guaranteed to return an integer number. - **/ - function getPixelSizeForLayoutSize(layoutSize: number): number; - - /** - * Rounds a layout size (dp) to the nearest layout size that corresponds to - * an integer number of pixels. For example, on a device with a PixelRatio - * of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to - * exactly (8.33 * 3) = 25 pixels. - **/ - function roundToNearestPixel(layoutSize: number): number; - } - - interface IncrementalProps extends ComponentPropsStyleBase { - onDone?: () => void; - name: string; - children?: any; - } - - interface IncrementalPresenterProps extends ComponentPropsStyleBase { - name: string; - disabled?: boolean; - onDone?: () => void; - onLayout?: (event: Object) => void; - style?: any; - children?: any; - } - - class Incremental extends ReactNativeBaseComponent { - } - - class IncrementalGroup extends ReactNativeBaseComponent{ - } - - class IncrementalPresenter extends ReactNativeBaseComponent { - } - - module JSEventLoopWatchdog { - function install(obj: any): void; - } - - module InteractionManager { - function setDeadline(deadline: number): void; - } - - interface I18nManager { - isRTL: boolean - allowRTL: (allowRTL: boolean) => {} - forceRTL: (forceRTL: boolean) => {} - } - - export var I18nManager: I18nManager; -} - -interface GeoConfiguration { - skipPermissionRequests: boolean; -} - -interface Geolocation { - // React Native addition to navigator.geolocation - setRNConfiguration(config: GeoConfiguration): void; -} - diff --git a/extensions/navigation/src/web/Navigator.tsx b/extensions/navigation/src/web/Navigator.tsx index b858e68fc..826619ab6 100644 --- a/extensions/navigation/src/web/Navigator.tsx +++ b/extensions/navigation/src/web/Navigator.tsx @@ -1,33 +1,31 @@ /* -* Navigator.tsx -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Web specific implementation of Navigator. This is inspired from React.Navigator. -* This component is set with props, which are callback methods. It is primarily driven -* by state updates instigated by its public helpers like immediatelyResetRouteStack, push, -* pop, which update the state and cause transitions. -*/ - -import _ = require('../common/lodashMini'); -import React = require('react'); -import ReactDOM = require('react-dom'); -import RX = require('reactxp'); + * Navigator.tsx + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Web specific implementation of Navigator. This is inspired from React.Navigator. + * This component is set with props, which are callback methods. It is primarily driven + * by state updates instigated by its public helpers like immediatelyResetRouteStack, push, + * pop, which update the state and cause transitions. + */ + +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import * as RX from 'reactxp'; +import * as rebound from 'rebound'; import { Styles, View } from 'reactxp'; -import rebound = require('rebound'); - -import { NavigatorSceneConfigFactory } from './NavigatorSceneConfigFactory'; -import { NavigatorSceneConfig } from './NavigatorSceneConfigFactory'; +import * as _ from '../common/lodashMini'; +import * as Types from '../common/Types'; import { - Navigator as NavigatorBase, NavigatorDelegateSelector as DelegateSelector, + NavigatorState as BaseNavigatorState, + Navigator as NavigatorBase, NavigatorProps, - NavigatorState as BaseNavigatorState } from '../common/Types'; -import Types = require('../common/Types'); +import { NavigatorSceneConfigFactory, NavigatorSceneConfig } from './NavigatorSceneConfigFactory'; // [Bug:506870] Move web navigator to RX animated API export interface SpringSystem { @@ -51,14 +49,14 @@ const _styles = { flex: 1, flexDirection: 'column', alignSelf: 'stretch', - overflow: 'hidden' + overflow: 'hidden', }), defaultSceneStyle: Styles.createViewStyle({ position: 'absolute', left: 0, right: 0, bottom: 0, - top: 0 + top: 0, }), baseScene: Styles.createViewStyle({ position: 'absolute', @@ -66,26 +64,26 @@ const _styles = { left: 0, right: 0, bottom: 0, - top: 0 + top: 0, }), disabledScene: Styles.createViewStyle({ top: 0, bottom: 0, - flex: 1 + flex: 1, }), transitioner: Styles.createViewStyle( { flex: 1, flexDirection: 'column', backgroundColor: 'transparent', overflow: 'hidden', - alignItems: 'stretch' + alignItems: 'stretch', }), sceneStyle: Styles.createViewStyle({ flex: 1, shadowOffset: { height: 0, width: 0 }, shadowRadius: 40, - shadowColor: 'rgba(0, 0, 0, 0.2)' - }) + shadowColor: 'rgba(0, 0, 0, 0.2)', + }), }; // Transition types @@ -129,6 +127,10 @@ export class NavigatorImpl extends NavigatorBase { // Keep a map of all rendered scenes, keyed off their routeId private _renderedSceneMap: { [routeId: number]: JSX.Element } = {}; + // References to mounted components. + private _containerRef: RX.View | null; + private _sceneRefs: { [sceneIndex: string]: RX.View } = {}; + // Save a public reference to the parent navigator if one was given in props. navigatorReference: Navigator; @@ -150,11 +152,11 @@ export class NavigatorImpl extends NavigatorBase { routeStack: [], presentedIndex: 0, transitionFromIndex: undefined, - transitionQueue: [] + transitionQueue: [], }; } - componentWillMount() { + UNSAFE_componentWillMount() { this.springSystem = new rebound.SpringSystem(); this.spring = this.springSystem.createSpring(); this.spring.setRestSpeedThreshold(0.05); @@ -165,7 +167,7 @@ export class NavigatorImpl extends NavigatorBase { }, onSpringAtRest: () => { this._completeTransition(); - } + }, }); } @@ -179,7 +181,7 @@ export class NavigatorImpl extends NavigatorBase { } render() { - let newRenderedSceneMap: { [routeId: number]: JSX.Element } = {}; + const newRenderedSceneMap: { [routeId: number]: JSX.Element } = {}; let scenes: JSX.Element[]; if (this.state.routeStack.length > 0) { @@ -210,7 +212,7 @@ export class NavigatorImpl extends NavigatorBase { > { scenes } @@ -241,12 +243,12 @@ export class NavigatorImpl extends NavigatorBase { const nextStack = activeStack.concat([route]); const destIndex = nextStack.length - 1; const nextAnimationConfigStack: NavigatorSceneConfig [] = activeAnimationConfigStack.concat([ - this._getSceneConfigFromRoute(route) + this._getSceneConfigFromRoute(route), ]); this.setState({ routeStack: nextStack, - sceneConfigStack: nextAnimationConfigStack + sceneConfigStack: nextAnimationConfigStack, }, () => { this._enableScene(destIndex); this._transitionTo(destIndex); @@ -262,9 +264,12 @@ export class NavigatorImpl extends NavigatorBase { routeStack: nextRouteStack, presentedIndex: destIndex, transitionFromIndex: undefined, - transitionQueue: [] + transitionQueue: [], }, () => { this._handleSpringUpdate(); + if (destIndex >= 0) { + this._enableScene(destIndex, true); + } }); } @@ -294,14 +299,14 @@ export class NavigatorImpl extends NavigatorBase { return; } - let nextRouteStack = this.state.routeStack.slice(0, index + 1); - let nextAnimationModeStack = this.state.sceneConfigStack.slice(0, index + 1); + const nextRouteStack = this.state.routeStack.slice(0, index + 1); + const nextAnimationModeStack = this.state.sceneConfigStack.slice(0, index + 1); nextRouteStack[index] = route; nextAnimationModeStack[index] = this._getSceneConfigFromRoute(route); this.setState({ routeStack: nextRouteStack, - sceneConfigStack: nextAnimationModeStack + sceneConfigStack: nextAnimationModeStack, }); } @@ -339,12 +344,20 @@ export class NavigatorImpl extends NavigatorBase { return this.state.routeStack.slice(); } + private _onMountContainer = (comp: RX.View | null) => { + this._containerRef = comp; + }; + private _updateDimensionsCache() { - const transitioner = ReactDOM.findDOMNode(this.refs['transitioner']) as HTMLElement; - this._dimensions = { - width: transitioner.offsetWidth, - height: transitioner.offsetHeight - }; + if (this._containerRef) { + const transitioner = ReactDOM.findDOMNode(this._containerRef) as HTMLElement | null; + if (transitioner) { + this._dimensions = { + width: transitioner.offsetWidth, + height: transitioner.offsetHeight, + }; + } + } } // Helper method to extract Navigator's Scene config from the route @@ -358,8 +371,7 @@ export class NavigatorImpl extends NavigatorBase { // Render a scene for the navigator private _renderNavigatorScene(route: Types.NavigatorRoute, index: number): JSX.Element { - let styles: RX.Types.ViewStyleRuleSet[] = [_styles.baseScene, _styles.sceneStyle, - _styles.defaultSceneStyle]; + const styles: RX.Types.ViewStyleRuleSet[] = [_styles.baseScene, _styles.sceneStyle, _styles.defaultSceneStyle]; if (index !== this.state.presentedIndex) { // update styles @@ -370,7 +382,7 @@ export class NavigatorImpl extends NavigatorBase { return ( this._onMountScene(comp, index) } style={ styles } > { this.props.renderScene(route) } @@ -378,39 +390,54 @@ export class NavigatorImpl extends NavigatorBase { ); } + private _onMountScene(comp: RX.View | null, sceneIndex: number) { + const sceneId = 'scene_' + sceneIndex; + + if (!comp) { + delete this._sceneRefs[sceneId]; + } else { + this._sceneRefs[sceneId] = comp; + } + } + // Push a scene below the others so they don't block touches sent to the presented scenes. private _disableScene(sceneIndex: number) { - if (this.refs['scene_' + sceneIndex]) { - this._setNativeStyles(this.refs['scene_' + sceneIndex], { + const sceneId = 'scene_' + sceneIndex; + + if (this._sceneRefs[sceneId]) { + this._setNativeStyles(this._sceneRefs[sceneId], { opacity: 0, - zIndex: -10 + zIndex: -10, }); } } // Add styles on the scene - At this time, the scene should be mounted and sitting in the // DOM. We are just adding giving styles to this current scene. - private _enableScene(sceneIndex: number) { - let sceneStyle = Styles.combine([_styles.baseScene, _styles.sceneStyle, _styles.defaultSceneStyle]) as any; + private _enableScene(sceneIndex: number, force = false) { + const sceneStyle = Styles.combine([_styles.baseScene, _styles.sceneStyle, _styles.defaultSceneStyle]) as any; // Then restore the top value for this scene. const enabledSceneNativeProps = { style: { - top: sceneStyle['top'], - bottom: sceneStyle['bottom'], - zIndex: 0 - } + top: sceneStyle.top, + bottom: sceneStyle.bottom, + opacity: 1, + zIndex: 0, + transform: '', + }, }; - if (sceneIndex !== this.state.transitionFromIndex && + if (!force && sceneIndex !== this.state.transitionFromIndex && sceneIndex !== this.state.presentedIndex) { // If we are not in a transition from this index, make sure opacity is 0 to prevent the enabled scene from // flashing over the presented scene. (enabledSceneNativeProps.style as any).opacity = 0; } - if (this.refs['scene_' + sceneIndex]) { - this._setNativeStyles(this.refs['scene_' + sceneIndex], enabledSceneNativeProps.style); + const sceneId = 'scene_' + sceneIndex; + if (this._sceneRefs[sceneId]) { + this._setNativeStyles(this._sceneRefs[sceneId], enabledSceneNativeProps.style); } } @@ -422,11 +449,11 @@ export class NavigatorImpl extends NavigatorBase { // If we're already transitioning to another index, queue this one. if (this.state.transitionFromIndex !== undefined) { - let newTransitionQueue = _.cloneDeep(this.state.transitionQueue); + const newTransitionQueue = _.cloneDeep(this.state.transitionQueue); newTransitionQueue.push({ destIndex: destIndex, velocity: velocity, - transitionFinished: cb + transitionFinished: cb, }); // set new transition queue this.setState ({ transitionQueue: newTransitionQueue }); @@ -437,7 +464,7 @@ export class NavigatorImpl extends NavigatorBase { this.setState({ transitionFromIndex: this.state.presentedIndex, presentedIndex: destIndex, - transitionFinished: cb + transitionFinished: cb, }); // Grab the scene config from the route we're leaving. @@ -461,17 +488,17 @@ export class NavigatorImpl extends NavigatorBase { } private _completeTransition() { - let newState: NavigatorState = {}; + const newState: NavigatorState = {}; this.setState({ - transitionFromIndex: undefined + transitionFromIndex: undefined, }); this.spring.setCurrentValue(0).setAtRest(); this._hideScenes(); // Do we have pending transitions? trigger transitions then if (this.state.transitionQueue.length) { - let newTransitionQueue = _.cloneDeep(this.state.transitionQueue); + const newTransitionQueue = _.cloneDeep(this.state.transitionQueue); const queuedTransition = newTransitionQueue.shift(); // add styles on the scene we are about to transition to @@ -481,7 +508,7 @@ export class NavigatorImpl extends NavigatorBase { queuedTransition.destIndex, queuedTransition.velocity, undefined, - queuedTransition.transitionFinished + queuedTransition.transitionFinished, ); if (this.state.transitionFinished) { @@ -523,13 +550,14 @@ export class NavigatorImpl extends NavigatorBase { this._transitionBetween( this.state.transitionFromIndex, this.state.presentedIndex, - this.spring.getCurrentValue() + this.spring.getCurrentValue(), ); } } private _transitionSceneStyle(fromIndex: number, toIndex: number, progress: number, index: number) { - const viewAtIndex = this.refs['scene_' + index]; + const sceneId = 'scene_' + index; + const viewAtIndex = this._sceneRefs[sceneId]; if (viewAtIndex === undefined) { return; } @@ -543,7 +571,7 @@ export class NavigatorImpl extends NavigatorBase { sceneConfig = this.state.sceneConfigStack[sceneConfigIndex - 1]; } - let styleToUse: RX.Types.ViewStyleRuleSet = {}; + const styleToUse: RX.Types.ViewStyleRuleSet = {}; const useFn = index < fromIndex || index < toIndex ? sceneConfig.animationInterpolators.out : sceneConfig.animationInterpolators.into; @@ -592,9 +620,7 @@ export class NavigatorImpl extends NavigatorBase { popIndex, undefined, // default velocity undefined, // no spring jumping - () => { - this._cleanScenesPastIndex(popIndex); - } + () => this._cleanScenesPastIndex(popIndex), ); } @@ -605,7 +631,7 @@ export class NavigatorImpl extends NavigatorBase { if (newStackLength < this.state.routeStack.length) { this.setState({ sceneConfigStack: this.state.sceneConfigStack.slice(0, newStackLength), - routeStack: this.state.routeStack.slice(0, newStackLength) + routeStack: this.state.routeStack.slice(0, newStackLength), }); } } @@ -626,15 +652,17 @@ export class NavigatorImpl extends NavigatorBase { // setNativeProps. private _setNativeStyles(component: React.ReactInstance, currentStyles: any) { // Grab the actual element from the DOM. - let element = ReactDOM.findDOMNode(component) as HTMLElement; - const flatStyles: RX.Types.ViewStyleRuleSet = _.isArray(currentStyles) ? _.flatten(currentStyles) : currentStyles; + const element = ReactDOM.findDOMNode(component) as HTMLElement|null; + if (element) { + const flatStyles: RX.Types.ViewStyleRuleSet = Array.isArray(currentStyles) ? _.flatten(currentStyles) : currentStyles; - // Modify styles - _.assign(element.style, flatStyles); + // Modify styles + _.assign(element.style, flatStyles); + } } } export default NavigatorImpl; export const Navigator = NavigatorImpl; export const NavigatorDelegateSelector: DelegateSelector = undefined; -export import Types = Types; +export { Types }; diff --git a/extensions/navigation/src/web/NavigatorSceneConfigFactory.tsx b/extensions/navigation/src/web/NavigatorSceneConfigFactory.tsx index e1079827b..8f98b1ee0 100644 --- a/extensions/navigation/src/web/NavigatorSceneConfigFactory.tsx +++ b/extensions/navigation/src/web/NavigatorSceneConfigFactory.tsx @@ -1,30 +1,31 @@ /** -* NavigatorSceneConfigFactory.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* NavigatorSceneConfigFactory creates an 'object' of type NavigatorSceneConfig, -* which is consumed by the Navigator. This object contains properties to execute -* spring animation for transition between scenes. NavigatorSceneConfigFactory and -* NavigatorSceneConfig are both exported. -*/ - -import _ = require('../common/lodashMini'); - -import { Types } from 'reactxp'; -import NavigationTypes = require('../common/Types'); + * NavigatorSceneConfigFactory.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * NavigatorSceneConfigFactory creates an 'object' of type NavigatorSceneConfig, + * which is consumed by the Navigator. This object contains properties to execute + * spring animation for transition between scenes. NavigatorSceneConfigFactory and + * NavigatorSceneConfig are both exported. + */ + +import * as RX from 'reactxp'; + +import * as _ from '../common/lodashMini'; +import * as Types from '../common/Types'; // Interpolator type, which accepts a combination of these types and returns a interpolated/calculated result // Interpolator wrapper, which is given as a callback method to Navigator to call the animation interpolator -export type Interpolator = (progress: number, dimension?: Types.Dimensions) => number; -export type InterpolatorWrapper = (previousStyleSet: Types.ViewStyleRuleSet, dimensions: Types.Dimensions, progress: number) => boolean; +export type Interpolator = (progress: number, dimension?: RX.Types.Dimensions) => number; +export type InterpolatorWrapper = (previousStyleSet: RX.Types.ViewStyleRuleSet, + dimensions: RX.Types.Dimensions, progress: number) => boolean; // Interface to define the transition styles for multiple views export interface TransitionStyle { - translateX?: (progress: number, dimension: Types.Dimensions) => string; - translateY?: (progress: number, dimension: Types.Dimensions) => string; - translateZ?: (progress: number, dimension: Types.Dimensions) => string; + translateX?: (progress: number, dimension: RX.Types.Dimensions) => string; + translateY?: (progress: number, dimension: RX.Types.Dimensions) => string; + translateZ?: (progress: number, dimension: RX.Types.Dimensions) => string; // Note: Weird type: Either a 'function type' or a 'number' opacity?: ((progress: number) => number) | number; rotateX?: ((progress: number) => number) | number; @@ -38,78 +39,77 @@ export interface TransitionStyle { // Defined style interpolators for each transition type class SceneConfigStyles { static fadeToTheLeft: TransitionStyle = { - translateX: (t, dimensions) => { return (t * -dimensions.width * 0.3) + 'px'; }, - opacity: 1 + translateX: (t, dimensions) =>(t * -dimensions.width * 0.3) + 'px', + opacity: 1, }; static fadeToTheRight: TransitionStyle = { - translateX: (t, dimensions) => { return (t * dimensions.width * 0.3) + 'px'; }, - opacity: 1 + translateX: (t, dimensions) => (t * dimensions.width * 0.3) + 'px', + opacity: 1, }; static fadeIn: TransitionStyle = { - opacity: t => { return (t); } + opacity: t => t, }; static fadeOut: TransitionStyle = { - opacity: t => { return (1 - t); } + opacity: t => 1 - t, }; static fadeOutToTop: TransitionStyle = { - opacity: t => { return (1 - t); }, - translateY: (t, dimensions) => { return (t * -0.1 * dimensions.height) + 'px'; } + opacity: t => 1 - t, + translateY: (t, dimensions) => (t * -0.1 * dimensions.height) + 'px', }; static toTheLeft: TransitionStyle = { - translateX: (t, dimensions) => { return (t * -dimensions.width) + 'px'; } + translateX: (t, dimensions) => (t * -dimensions.width) + 'px', }; static toTheUp: TransitionStyle = { - translateY: (t, dimensions) => { return (t * -dimensions.height) + 'px'; } + translateY: (t, dimensions) => (t * -dimensions.height) + 'px', }; static toTheDown: TransitionStyle = { - translateY: (t, dimensions) => { return (t * dimensions.height) + 'px'; } + translateY: (t, dimensions) => (t * dimensions.height) + 'px', }; static fromTheRight: TransitionStyle = { opacity: 1, - translateX: (t, dimensions) => { return (dimensions.width - (t * dimensions.width)) + 'px'; } + translateX: (t, dimensions) => (dimensions.width - (t * dimensions.width)) + 'px', }; static fromTheLeft: TransitionStyle = { opacity: 1, - translateX: (t, dimensions) => { return (-dimensions.width + (t * dimensions.width)) + 'px'; } + translateX: (t, dimensions) => (-dimensions.width + (t * dimensions.width)) + 'px', }; static fromTheDown: TransitionStyle = { - translateY: (t, dimensions) => { return (dimensions.height - t * dimensions.height) + 'px'; } + translateY: (t, dimensions) => (dimensions.height - t * dimensions.height) + 'px', }; static fromTheUp: TransitionStyle = { opacity: 1, - translateY: (t, dimensions) => { return (-dimensions.height + t * dimensions.height) + 'px'; } + translateY: (t, dimensions) => (-dimensions.height + t * dimensions.height) + 'px', }; static fromTheFront: TransitionStyle = { opacity: 1, - translateY: (t, dimensions) => { return (dimensions.height - t * dimensions.height) + 'px'; } + translateY: (t, dimensions) => (dimensions.height - t * dimensions.height) + 'px', }; static toTheBack: TransitionStyle = { - scaleX: t => { return (1 - (t * 0.05)); }, - scaleY: t => { return (1 - (t * 0.05)); }, - opacity: 1 + scaleX: t => (1 - (t * 0.05)), + scaleY: t => (1 - (t * 0.05)), + opacity: 1, }; - /* tslint:enable:no-unused-variable */ // CSS requires all transforms to be combined into one transform property. bundleCompoundStyles searches a style // definition for separate transforms and melts it down to a "transform" property. - public static bundleCompoundStyles (styles: TransitionStyle): any { - let transforms: { [name: string]: string | number } = { }; - let remaining: { [name: string]: string | number } = { }; + static bundleCompoundStyles(styles: { [name: string]: string | number }): any { + const transforms: { [name: string]: string | number } = { }; + const remaining: { [name: string]: string | number } = { }; - for (var name in styles) { + for (const name in styles) { if (styles.hasOwnProperty(name)) { switch (name) { case 'translateX': @@ -121,11 +121,11 @@ class SceneConfigStyles { case 'rotateX': case 'rotateY': case 'rotateZ': - transforms[name] = _.get(styles, name); + transforms[name] = styles[name]; break; default: - remaining[name] = _.get(styles, name); + remaining[name] = styles[name]; break; } } @@ -133,7 +133,7 @@ class SceneConfigStyles { // Add transforms into remaining object if (!_.isEmpty(transforms)) { - remaining['transform'] = _.map(transforms, (val, key) => { return key + '(' + val + ')'; }).join(' '); + remaining.transform = _.map(transforms, (val, key) => key + '(' + val + ')').join(' '); } return remaining; @@ -143,37 +143,36 @@ class SceneConfigStyles { // Navigator config class. Navigator works on the instances of this class export class NavigatorSceneConfig { // Rebound spring parameters when transitioning FROM this scene - public springFriction: number = 26; - public springTension: number = 200; + springFriction = 26; + springTension = 200; // Velocity to start at when transitioning without gesture - public defaultTransitionVelocity: number = 1.5; + defaultTransitionVelocity = 1.5; // Returns an object of functions that return a function - public animationInterpolators: { + animationInterpolators: { into: InterpolatorWrapper; out: InterpolatorWrapper; }; - constructor (intoStyle: TransitionStyle, outStyle: TransitionStyle) { + constructor(intoStyle: TransitionStyle, outStyle: TransitionStyle) { // Into, Out interpolators are required to do a scene transition this.animationInterpolators = { into: this._styleInterpolator(intoStyle), - out: this._styleInterpolator(outStyle) + out: this._styleInterpolator(outStyle), }; } // Private method that hangs as a callback on animationInterpolator object // It calculates new styles and updates the previousStyles object sent to decide // if the animation triggered or not in the component that calls it - private _styleInterpolator (styles: TransitionStyle): InterpolatorWrapper { - return (previousStyleSet: Types.ViewStyleRuleSet, dimensions: Types.Dimensions, progress: number): boolean => { + private _styleInterpolator(styles: TransitionStyle): InterpolatorWrapper { + return (previousStyleSet: RX.Types.ViewStyleRuleSet, dimensions: RX.Types.Dimensions, progress: number): boolean => { // Calls the interpolator method for each type and calculates - // const newStyleSet = SceneConfigStyles.bundleCompoundStyles( - _.mapValues(styles, (interpolator: Interpolator | number) => { - return _.isNumber(interpolator) ? interpolator : interpolator(progress, dimensions); - })); + _.mapValues(styles, (interpolator: Interpolator | number) => ( + _.isNumber(interpolator) ? interpolator : interpolator(progress, dimensions) + )) as any); // Check if anything has changed since last frame. if (_.isEqual(previousStyleSet, newStyleSet)) { @@ -181,7 +180,7 @@ export class NavigatorSceneConfig { } // Copy the new props into the previous object. - for (let prop in newStyleSet) { + for (const prop in newStyleSet) { if (newStyleSet.hasOwnProperty(prop)) { _.assign(previousStyleSet, {[prop]: _.get(newStyleSet, prop)}); } @@ -196,21 +195,21 @@ export class NavigatorSceneConfig { export class NavigatorSceneConfigFactory { // Helper method that creates a new Animation config for a scene - public static createConfig (configType: NavigationTypes.NavigatorSceneConfigType): NavigatorSceneConfig { + static createConfig(configType: Types.NavigatorSceneConfigType): NavigatorSceneConfig { switch (configType) { - case NavigationTypes.NavigatorSceneConfigType.FloatFromRight: - return new NavigatorSceneConfig(SceneConfigStyles.fromTheRight, SceneConfigStyles.fadeToTheLeft); + case Types.NavigatorSceneConfigType.FloatFromRight: + return new NavigatorSceneConfig(SceneConfigStyles.fromTheRight, SceneConfigStyles.fadeToTheLeft); - case NavigationTypes.NavigatorSceneConfigType.FloatFromLeft: - return new NavigatorSceneConfig(SceneConfigStyles.fromTheLeft, SceneConfigStyles.fadeToTheRight); + case Types.NavigatorSceneConfigType.FloatFromLeft: + return new NavigatorSceneConfig(SceneConfigStyles.fromTheLeft, SceneConfigStyles.fadeToTheRight); - case NavigationTypes.NavigatorSceneConfigType.FloatFromBottom: + case Types.NavigatorSceneConfigType.FloatFromBottom: return new NavigatorSceneConfig(SceneConfigStyles.fromTheFront, SceneConfigStyles.toTheBack); - case NavigationTypes.NavigatorSceneConfigType.Fade: + case Types.NavigatorSceneConfigType.Fade: return new NavigatorSceneConfig(SceneConfigStyles.fadeIn, SceneConfigStyles.fadeOut); - case NavigationTypes.NavigatorSceneConfigType.FadeWithSlide: + case Types.NavigatorSceneConfigType.FadeWithSlide: return new NavigatorSceneConfig(SceneConfigStyles.fadeIn, SceneConfigStyles.fadeOutToTop); default: diff --git a/extensions/navigation/tsconfig.json b/extensions/navigation/tsconfig.json index 03821897b..81d3784b0 100644 --- a/extensions/navigation/tsconfig.json +++ b/extensions/navigation/tsconfig.json @@ -1,26 +1,23 @@ { "compilerOptions": { + "experimentalDecorators": true, + "noImplicitAny": true, + "skipLibCheck": true, "declaration": true, "noResolve": false, - "jsx": "react", "module": "commonjs", "target": "es5", - "experimentalDecorators": true, - "noImplicitAny": true, - "outDir": "dist/", - "lib": [ - "es5", - "dom" - ] + "outDir": "dist", + "jsx": "react", + "lib": ["es5", "dom"] }, - "filesGlob": [ - "src/**/*{ts,tsx}" + "include": [ + "src/**/*" ], "exclude": [ - "dist", "node_modules", - "website" + "dist" ] } diff --git a/extensions/navigation/tslint.json b/extensions/navigation/tslint.json deleted file mode 100644 index 38255f462..000000000 --- a/extensions/navigation/tslint.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "rules": { - "align": [true, "statements"], - "class-name": true, - "curly": true, - "eofline": true, - "forin": true, - "indent": [true, "spaces"], - "label-position": true, - "max-line-length": [ true, 140 ], - "no-arg": true, - "no-bitwise": false, - "no-consecutive-blank-lines": true, - "no-string-throw": true, - "no-construct": true, - "no-debugger": true, - "no-duplicate-variable": true, - "no-empty": true, - "no-eval": true, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": false, - "no-unused-expression": true, - "one-line": [true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" - ], - "quotemark": [true, "single", "jsx-single"], - "radix": true, - "semicolon": [true, "always"], - "triple-equals": [true, "allow-null-check"], - "variable-name": false, - "whitespace": [true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ] - } -} diff --git a/extensions/netinfo/.eslintrc.json b/extensions/netinfo/.eslintrc.json new file mode 100644 index 000000000..711dab2bf --- /dev/null +++ b/extensions/netinfo/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": ["skype"], + "rules": {}, + "overrides": [ + { + "files": [ + "*.tsx" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off" + } + }, + { + "files": [ + "PluginBaseChecker.ts" + ], + "rules": { + "@typescript-eslint/no-unused-vars": "off" + } + } + ] +} diff --git a/extensions/netinfo/.gitignore b/extensions/netinfo/.gitignore new file mode 100644 index 000000000..ca4806a3a --- /dev/null +++ b/extensions/netinfo/.gitignore @@ -0,0 +1,20 @@ +# Logs +logs +*.log +npm-debug.log* + +# Dependency directories +node_modules +package-lock.json + +# Optional npm cache directory +.npm + +# Build artifacts +**/dist + +# Miscellaneous user files +*.user +.vscode +.DS_STORE + diff --git a/extensions/netinfo/.npmignore b/extensions/netinfo/.npmignore new file mode 100644 index 000000000..85109f294 --- /dev/null +++ b/extensions/netinfo/.npmignore @@ -0,0 +1,5 @@ +/node_modules +/src/.vs +/src/bin +/src/obj +*.user diff --git a/extensions/netinfo/README.md b/extensions/netinfo/README.md new file mode 100644 index 000000000..1c629fa0e --- /dev/null +++ b/extensions/netinfo/README.md @@ -0,0 +1,21 @@ +# reactxp-netinfo +This module provides cross-platform support for detecting network ionformation within the [ReactXP](https://microsoft.github.io/reactxp/) library. This used to be a part of ReactXP core, but was extracted to be a standalone module inline with React Native `Lean Core` initiative. This exists as a standalone module to prevent users of ReactXP from having to link native modules when getting started. + +## Getting Started +This module relies on [@react-native-community/netinfo](https://www.npmjs.com/packages/@react-native-community/netinfo) and will need to be linked into the react-native project. +This can be done by following the linking instructions in the React Native documentation or by running +```react-native link @react-native-community/netinfo``` + +## Documentation +For detailed documentation, look [here](https://microsoft.github.io/reactxp/docs/extensions/netinfo.html). + +### Prerequisites +* [ReactXP](https://github.com/microsoft/reactxp/) + +## Contributing +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +You must sign a Contribution License Agreement (CLA) before your PR will be merged. This a one-time requirement for Microsoft projects in GitHub. You can read more about [Contribution License Agreements (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) on Wikipedia. You can sign the Microsoft Contribution License Agreement by visiting https://cla.microsoft.com/. Use your GitHub account to login. + +## License +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details diff --git a/extensions/netinfo/index.android.js b/extensions/netinfo/index.android.js new file mode 100644 index 000000000..3c29e9213 --- /dev/null +++ b/extensions/netinfo/index.android.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./dist/android/PluginBase.js'); diff --git a/extensions/netinfo/index.ios.js b/extensions/netinfo/index.ios.js new file mode 100644 index 000000000..fb6e2f768 --- /dev/null +++ b/extensions/netinfo/index.ios.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./dist/ios/PluginBase.js'); diff --git a/extensions/netinfo/index.js b/extensions/netinfo/index.js new file mode 100644 index 000000000..37981c96b --- /dev/null +++ b/extensions/netinfo/index.js @@ -0,0 +1,4 @@ +'use strict'; + +// Export web by default. Other platforms have custom index.[platform].js files +module.exports = require('./dist/web/PluginBase.js'); diff --git a/extensions/netinfo/index.macos.js b/extensions/netinfo/index.macos.js new file mode 100644 index 000000000..53dc20057 --- /dev/null +++ b/extensions/netinfo/index.macos.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./dist/macos/PluginBase.js'); \ No newline at end of file diff --git a/extensions/netinfo/index.windows.js b/extensions/netinfo/index.windows.js new file mode 100644 index 000000000..b80a5b5c5 --- /dev/null +++ b/extensions/netinfo/index.windows.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./dist/windows/PluginBase.js'); diff --git a/extensions/netinfo/package.json b/extensions/netinfo/package.json new file mode 100644 index 000000000..d36a03964 --- /dev/null +++ b/extensions/netinfo/package.json @@ -0,0 +1,29 @@ +{ + "name": "reactxp-netinfo", + "version": "2.0.0", + "description": "Plugin for ReactXP that provides information about network connectivity", + "author": "ReactXP Team ", + "license": "MIT", + "scripts": { + "build": "tsc", + "lint": "eslint --ext .ts,.tsx src", + "lint:fix": "npm run lint -- --fix" + }, + "dependencies": { + "@react-native-community/netinfo": "^4.6.1" + }, + "peerDependencies": { + "reactxp": "^2.0.0", + "react-native": ">=0.57", + "react-native-windows": "^0.57.1" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "2.15.0", + "eslint": "6.8.0", + "eslint-config-skype": "1.5.0", + "eslint-plugin-import": "2.19.1", + "reactxp": "^2.0.0", + "typescript": "3.7.4" + }, + "types": "dist/web/PluginBase.d.ts" +} diff --git a/extensions/netinfo/src/android/PluginBase.tsx b/extensions/netinfo/src/android/PluginBase.tsx new file mode 100644 index 000000000..cd74d23a3 --- /dev/null +++ b/extensions/netinfo/src/android/PluginBase.tsx @@ -0,0 +1,13 @@ +/* + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Android implementation of the plugin. + */ + +import * as Types from '../common/Types'; +import NetInfo from '../native-common/NetInfo'; + +export { NetInfo as default, Types }; diff --git a/extensions/netinfo/src/common/Interfaces.ts b/extensions/netinfo/src/common/Interfaces.ts new file mode 100644 index 000000000..665e69f99 --- /dev/null +++ b/extensions/netinfo/src/common/Interfaces.ts @@ -0,0 +1,25 @@ +/* + * Interfaces.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Interface definition for cross-platform ReactXP plugin for gathering network/connectivity + * info. This was extracted from the reactxp core + */ + +import SubscribableEvent from 'subscribableevent'; + +import * as Types from './Types'; + +export abstract class NetInfo { + abstract isConnected(): Promise; + abstract getType(): Promise; + connectivityChangedEvent = new SubscribableEvent<(isConnected: boolean) => void>(); +} + +export interface PluginInterface { + Types: typeof Types; + + default: NetInfo; +} diff --git a/extensions/netinfo/src/common/PluginBaseChecker.ts b/extensions/netinfo/src/common/PluginBaseChecker.ts new file mode 100644 index 000000000..35d090f0a --- /dev/null +++ b/extensions/netinfo/src/common/PluginBaseChecker.ts @@ -0,0 +1,22 @@ +/* + * PluginBaseChecker.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type check all the pluginbase exports against the desired interface. + */ + +import * as AndroidPlugin from '../android/PluginBase'; +import * as iOSPlugin from '../ios/PluginBase'; +import * as macOSPlugin from '../macos/PluginBase'; +import * as WebPlugin from '../web/PluginBase'; +import * as WindowsPlugin from '../windows/PluginBase'; + +import * as Interfaces from './Interfaces'; + +const _typeCheckerAndroid: Interfaces.PluginInterface = AndroidPlugin; +const _typeCheckeriOS: Interfaces.PluginInterface = iOSPlugin; +const _typeCheckermacOS: Interfaces.PluginInterface = macOSPlugin; +const _typeCheckerWeb: Interfaces.PluginInterface = WebPlugin; +const _typeCheckerWindows: Interfaces.PluginInterface = WindowsPlugin; diff --git a/extensions/netinfo/src/common/Types.ts b/extensions/netinfo/src/common/Types.ts new file mode 100644 index 000000000..5aac2037d --- /dev/null +++ b/extensions/netinfo/src/common/Types.ts @@ -0,0 +1,17 @@ +/* + * Types.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type definitions to support the plugin. + */ + +export enum DeviceNetworkType { + Unknown, + None, + Wifi, + Mobile2G, + Mobile3G, + Mobile4G +} diff --git a/extensions/netinfo/src/ios/PluginBase.tsx b/extensions/netinfo/src/ios/PluginBase.tsx new file mode 100644 index 000000000..0d3e7dfbc --- /dev/null +++ b/extensions/netinfo/src/ios/PluginBase.tsx @@ -0,0 +1,13 @@ +/* + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the iOS implementation of the plugin. + */ + +import * as Types from '../common/Types'; +import NetInfo from '../native-common/NetInfo'; + +export { NetInfo as default, Types }; diff --git a/extensions/netinfo/src/macos/PluginBase.tsx b/extensions/netinfo/src/macos/PluginBase.tsx new file mode 100644 index 000000000..e02af00bc --- /dev/null +++ b/extensions/netinfo/src/macos/PluginBase.tsx @@ -0,0 +1,13 @@ +/* + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Mac implementation of the plugin. + */ + +import * as Types from '../common/Types'; +import NetInfo from '../native-common/NetInfo'; + +export { NetInfo as default, Types }; diff --git a/extensions/netinfo/src/native-common/NetInfo.tsx b/extensions/netinfo/src/native-common/NetInfo.tsx new file mode 100644 index 000000000..a3e8efcf0 --- /dev/null +++ b/extensions/netinfo/src/native-common/NetInfo.tsx @@ -0,0 +1,61 @@ +/** + * NetInfo.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Native implementation of network information APIs. + */ + +import * as RNNetInfo from '@react-native-community/netinfo'; + +import * as Types from '../common/Types'; +import * as Interfaces from '../common/Interfaces'; + +export class NetInfo extends Interfaces.NetInfo { + constructor() { + super(); + + const onEventOccurredHandler = (state: RNNetInfo.NetInfoState) => { + this.connectivityChangedEvent.fire(state.isConnected); + }; + + RNNetInfo.addEventListener(onEventOccurredHandler); + } + + isConnected(): Promise { + return RNNetInfo.fetch() + .then((state: RNNetInfo.NetInfoState) => state.isConnected) + .catch(() => Promise.reject('NetInfo.isConnected.fetch() failed')); + } + + getType(): Promise { + return RNNetInfo.fetch().then((state: RNNetInfo.NetInfoState) => NetInfo._getNetworkTypeFromConnectionInfo(state)); + } + + private static _getNetworkTypeFromConnectionInfo(state: RNNetInfo.NetInfoState): Types.DeviceNetworkType { + if (state.type === RNNetInfo.NetInfoStateType.cellular) { + if (state.details === null || state.details.cellularGeneration === null) { + return Types.DeviceNetworkType.Unknown; + } else if (state.details.cellularGeneration === '2g') { + return Types.DeviceNetworkType.Mobile2G; + } else if (state.details.cellularGeneration === '3g') { + return Types.DeviceNetworkType.Mobile3G; + } else if (state.details.cellularGeneration === '4g') { + return Types.DeviceNetworkType.Mobile4G; + } + } else if (state.type === RNNetInfo.NetInfoStateType.wifi ) { + return Types.DeviceNetworkType.Wifi; + } else if (state.type === RNNetInfo.NetInfoStateType.ethernet ) { + return Types.DeviceNetworkType.Wifi; + } else if (state.type === RNNetInfo.NetInfoStateType.wimax ) { + return Types.DeviceNetworkType.Wifi; + } else if (state.type === RNNetInfo.NetInfoStateType.none) { + return Types.DeviceNetworkType.None; + } + + return Types.DeviceNetworkType.Unknown; + } +} + +export default new NetInfo(); diff --git a/extensions/netinfo/src/web/NetInfo.tsx b/extensions/netinfo/src/web/NetInfo.tsx new file mode 100644 index 000000000..3751f1edf --- /dev/null +++ b/extensions/netinfo/src/web/NetInfo.tsx @@ -0,0 +1,37 @@ +/** + * Video.tsx + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Web-specific implementation of the cross-platform Video abstraction. + */ + +import * as Types from '../common/Types'; +import * as Interfaces from '../common/Interfaces'; + +export class NetInfo extends Interfaces.NetInfo { + constructor() { + super(); + + const onEventOccuredHandler = () => { + this.connectivityChangedEvent.fire(navigator.onLine); + }; + + // Avoid accessing window if it's not defined (for test environment). + if (typeof(window) !== 'undefined') { + window.addEventListener('online', onEventOccuredHandler); + window.addEventListener('offline', onEventOccuredHandler); + } + } + + isConnected(): Promise { + return Promise.resolve(navigator.onLine); + } + + getType(): Promise { + return Promise.resolve(Types.DeviceNetworkType.Unknown); + } +} + +export default new NetInfo(); diff --git a/extensions/netinfo/src/web/PluginBase.ts b/extensions/netinfo/src/web/PluginBase.ts new file mode 100644 index 000000000..fd1412136 --- /dev/null +++ b/extensions/netinfo/src/web/PluginBase.ts @@ -0,0 +1,14 @@ +/* + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Web implementation of the plugin. + */ + +import * as Types from '../common/Types'; + +import NetInfo from './NetInfo'; + +export { NetInfo as default, Types }; diff --git a/extensions/netinfo/src/windows/PluginBase.ts b/extensions/netinfo/src/windows/PluginBase.ts new file mode 100644 index 000000000..89b138575 --- /dev/null +++ b/extensions/netinfo/src/windows/PluginBase.ts @@ -0,0 +1,13 @@ +/* + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Windows implementation of the plugin. + */ + +import * as Types from '../common/Types'; +import NetInfo from '../native-common/NetInfo'; + +export { NetInfo as default, Types }; diff --git a/extensions/netinfo/tsconfig.json b/extensions/netinfo/tsconfig.json new file mode 100644 index 000000000..13411a6b8 --- /dev/null +++ b/extensions/netinfo/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strictPropertyInitialization": true, + "experimentalDecorators": true, + "noImplicitReturns": true, + "strictNullChecks": true, + "noImplicitThis": true, + "noImplicitAny": true, + "skipLibCheck": true, + "declaration": true, + "noResolve": false, + "target": "es5", + "module": "commonjs", + "outDir": "dist", + "jsx": "react", + "lib": ["es2015.promise", "es5", "DOM"] + }, + + "include": [ + "src/**/*" + ], + + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/extensions/video/.eslintrc.json b/extensions/video/.eslintrc.json new file mode 100644 index 000000000..3ff892a96 --- /dev/null +++ b/extensions/video/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "parserOptions": { + "project": "./tsconfig.json" + }, + "extends": ["skype", "skype/react"], + "rules": {}, + "overrides": [ + { + "files": [ + "*.tsx" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off" + } + }, + { + "files": [ + "PluginBaseChecker.ts" + ], + "rules": { + "@typescript-eslint/no-unused-vars": "off" + } + } + ] +} diff --git a/extensions/video/.gitignore b/extensions/video/.gitignore index 30efdd65d..ca4806a3a 100644 --- a/extensions/video/.gitignore +++ b/extensions/video/.gitignore @@ -5,6 +5,7 @@ npm-debug.log* # Dependency directories node_modules +package-lock.json # Optional npm cache directory .npm diff --git a/extensions/video/package.json b/extensions/video/package.json index fe1a7a965..35eed01be 100644 --- a/extensions/video/package.json +++ b/extensions/video/package.json @@ -1,27 +1,37 @@ { "name": "reactxp-video", - "version": "0.2.2", + "version": "2.0.0", "description": "Plugin for ReactXP that provides a video player component for all platforms", "author": "ReactXP Team ", "license": "MIT", "scripts": { - "build": "npm run tslint && tsc", - "tslint": "tslint --project tsconfig.json -r tslint.json -r ./node_modules/tslint-microsoft-contrib --fix || true" + "build": "tsc", + "lint": "eslint --ext .ts,.tsx src", + "lint:fix": "npm run lint -- --fix" }, "dependencies": { - "@types/lodash": "^4.14.62", - "lodash": "^4.0.0", - "react-native-video": "^2.0.0", - "reactxp": "^0.46.2" + "lodash": "^4.17.15", + "react-native-video": "^5.0.2" }, "peerDependencies": { - "react-dom": "^15.4.1", - "react-native": "^0.46.0" + "react": "^16.3.0", + "reactxp": "^2.0.0", + "react-dom": "^16.3.0", + "react-native": ">=0.57", + "react-native-windows": "^0.57.1" }, "devDependencies": { - "typescript": "^2.4.1", - "tslint": "^5.0.0", - "tslint-microsoft-contrib": "^4.0.1" + "@types/lodash": "^4.14.149", + "@types/react-dom": "^16.9.4", + "@types/react-native": "^0.60.23", + "@typescript-eslint/eslint-plugin": "2.15.0", + "eslint": "6.8.0", + "eslint-config-skype": "1.5.0", + "eslint-plugin-import": "2.19.1", + "eslint-plugin-react": "7.17.0", + "react": "^16.3.0", + "reactxp": "^2.0.0", + "typescript": "3.7.4" }, "types": "dist/web/PluginBase.d.ts" } diff --git a/extensions/video/src/android/PluginBase.tsx b/extensions/video/src/android/PluginBase.tsx index e36ad4cb3..eae576b75 100644 --- a/extensions/video/src/android/PluginBase.tsx +++ b/extensions/video/src/android/PluginBase.tsx @@ -1,13 +1,13 @@ /* -* PluginBase.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the Android implementation of the plugin. -*/ + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the Android implementation of the plugin. + */ +import * as Types from '../common/Types'; import Video from '../native-common/Video'; -import Types = require('../common/Types'); export { Video as default, Types }; diff --git a/extensions/video/src/common/Interfaces.ts b/extensions/video/src/common/Interfaces.ts index 2726b519e..42583f93a 100644 --- a/extensions/video/src/common/Interfaces.ts +++ b/extensions/video/src/common/Interfaces.ts @@ -1,18 +1,18 @@ /* -* Interfaces.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Interface definition for cross-platform ReactXP plugin for -* display videos and controlling video playback. -*/ + * Interfaces.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Interface definition for cross-platform ReactXP plugin for + * display videos and controlling video playback. + */ -import RX = require('reactxp'); +import * as RX from 'reactxp'; -import Types = require('./Types'); +import * as Types from './Types'; -export abstract class Video extends RX.Component { +export abstract class Video extends RX.Component { abstract seek(position: number): void; abstract play(): void; abstract pause(): void; @@ -21,6 +21,6 @@ export abstract class Video extends RX.Component { export interface PluginInterface { Types: typeof Types; - + default: typeof Video; } diff --git a/extensions/video/src/common/PluginBaseChecker.ts b/extensions/video/src/common/PluginBaseChecker.ts index 55df195e8..35d090f0a 100644 --- a/extensions/video/src/common/PluginBaseChecker.ts +++ b/extensions/video/src/common/PluginBaseChecker.ts @@ -1,24 +1,22 @@ /* -* PluginBaseChecker.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type check all the pluginbase exports against the desired interface. -*/ + * PluginBaseChecker.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type check all the pluginbase exports against the desired interface. + */ -import Interfaces = require('./Interfaces'); +import * as AndroidPlugin from '../android/PluginBase'; +import * as iOSPlugin from '../ios/PluginBase'; +import * as macOSPlugin from '../macos/PluginBase'; +import * as WebPlugin from '../web/PluginBase'; +import * as WindowsPlugin from '../windows/PluginBase'; -import AndroidPlugin = require('../android/PluginBase'); -import iOSPlugin = require('../ios/PluginBase'); -import macOSPlugin = require('../macos/PluginBase'); -import WebPlugin = require('../web/PluginBase'); -import WindowsPlugin = require('../windows/PluginBase'); +import * as Interfaces from './Interfaces'; -/* tslint:disable:no-unused-variable */ const _typeCheckerAndroid: Interfaces.PluginInterface = AndroidPlugin; const _typeCheckeriOS: Interfaces.PluginInterface = iOSPlugin; const _typeCheckermacOS: Interfaces.PluginInterface = macOSPlugin; const _typeCheckerWeb: Interfaces.PluginInterface = WebPlugin; const _typeCheckerWindows: Interfaces.PluginInterface = WindowsPlugin; -/* tslint:enable:no-unused-variable */ diff --git a/extensions/video/src/common/Types.ts b/extensions/video/src/common/Types.ts index df750e28c..8a877b219 100644 --- a/extensions/video/src/common/Types.ts +++ b/extensions/video/src/common/Types.ts @@ -1,12 +1,13 @@ /* -* Types.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definitions to support the plugin. -*/ + * Types.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type definitions to support the plugin. + */ +import * as React from 'react'; import { Types as RXTypes } from 'reactxp'; // Video interfaces from react-native-video @@ -26,8 +27,8 @@ export interface VideoInfo { }; } -export interface VideoProps extends RXTypes.CommonStyledProps { - source: string; +export interface VideoProps extends RXTypes.CommonStyledProps { + source: string | number; accessibilityLabel?: string; showControls?: boolean; preload?: 'auto'|'metadata'|'none'; @@ -45,3 +46,5 @@ export interface VideoProps extends RXTypes.CommonStyledProps void; onProgress?: (progress: VideoProgress) => void; } + +export abstract class Video extends React.Component {} diff --git a/extensions/video/src/ios/PluginBase.tsx b/extensions/video/src/ios/PluginBase.tsx index 0c8008027..2630b7b58 100644 --- a/extensions/video/src/ios/PluginBase.tsx +++ b/extensions/video/src/ios/PluginBase.tsx @@ -1,13 +1,13 @@ -/* -* PluginBase.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the iOS implementation of the plugin. -*/ +/** + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the iOS implementation of the plugin. + */ +import * as Types from '../common/Types'; import Video from '../native-common/Video'; -import Types = require('../common/Types'); export { Video as default, Types }; diff --git a/extensions/video/src/macos/PluginBase.tsx b/extensions/video/src/macos/PluginBase.tsx index 170dd4d4a..a0467893e 100644 --- a/extensions/video/src/macos/PluginBase.tsx +++ b/extensions/video/src/macos/PluginBase.tsx @@ -1,13 +1,13 @@ -/* -* PluginBase.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Base export for the MacOS implementation of the plugin. -*/ +/** + * PluginBase.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Base export for the MacOS implementation of the plugin. + */ +import * as Types from '../common/Types'; import Video from '../native-common/Video'; -import Types = require('../common/Types'); export { Video as default, Types }; diff --git a/extensions/video/src/native-common/Video.tsx b/extensions/video/src/native-common/Video.tsx index 40d4a9be9..5a770d990 100644 --- a/extensions/video/src/native-common/Video.tsx +++ b/extensions/video/src/native-common/Video.tsx @@ -1,18 +1,17 @@ -/* -* Video.tsx -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* RN-specific implementation of the cross-platform Video abstraction. -*/ - -import React = require('react'); +/** + * Video.tsx + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * RN-specific implementation of the cross-platform Video abstraction. + */ + +import * as React from 'react'; +import * as RX from 'reactxp'; import { default as RNVideo, VideoInfo, VideoBufferInfo } from 'react-native-video'; -import RX = require('reactxp'); -import Interfaces = require('../common/Interfaces'); -import Types = require('../common/Types'); +import * as Types from '../common/Types'; export interface VideoState { isPlaying?: boolean; @@ -21,38 +20,34 @@ export interface VideoState { } class Video extends RX.Component { - private _isMounted = false; + private _mountedComponent: RNVideo|null = null; constructor(props: Types.VideoProps) { super(props); this.state = { isPlaying: false, - isMuted: false + isMuted: false, }; } - componentDidMount() { - this._isMounted = true; - } - - componentWillUnmount() { - this._isMounted = false; - } - render() { + const source = typeof this.props.source === 'number' + ? this.props.source + : { uri: this.props.source }; return ( { ); } + private _onMount = (component: any) => { + this._mountedComponent = component as RNVideo; + }; + private _onError = () => { - if (!this._isMounted) { + if (!this._mountedComponent) { return; } if (this.props.onError) { this.props.onError(); } - } + }; private _onLoad = () => { - if (!this._isMounted) { + if (!this._mountedComponent) { return; } @@ -82,10 +81,10 @@ class Video extends RX.Component { if (!this.props.showControls && this.props.onCanPlay) { this.props.onCanPlay(); } - } + }; private _onLoadData = (loadInfo: VideoInfo) => { - if (!this._isMounted) { + if (!this._mountedComponent) { return; } @@ -100,10 +99,10 @@ class Video extends RX.Component { } this.setState({ duration: loadInfo.duration }); - } + }; private _onBuffer = (bufferInfo: VideoBufferInfo) => { - if (!this._isMounted) { + if (!this._mountedComponent) { return; } @@ -116,10 +115,10 @@ class Video extends RX.Component { this.props.onCanPlayThrough(); } } - } + }; private _onEnd = () => { - if (!this._isMounted) { + if (!this._mountedComponent) { return; } @@ -134,14 +133,20 @@ class Video extends RX.Component { if (this.props.onEnded) { this.props.onEnded(); } - } + }; seek(position: number) { - (this.refs['video'] as any).seek(position); + if (this._mountedComponent) { + this._mountedComponent.seek(position); + } } seekPercent(percentage: number) { - (this.refs['video'] as any).seek(this.state.duration * percentage); + if (this._mountedComponent) { + if (this.state.duration) { + this._mountedComponent.seek(this.state.duration * percentage); + } + } } play() { diff --git a/extensions/video/src/typings/node.d.ts b/extensions/video/src/typings/node.d.ts deleted file mode 100644 index b7edca1f7..000000000 --- a/extensions/video/src/typings/node.d.ts +++ /dev/null @@ -1,2079 +0,0 @@ -// Type definitions for Node.js v0.12.0 -// Project: http://nodejs.org/ -// Definitions by: Microsoft TypeScript , DefinitelyTyped -// Definitions: https://github.com/borisyankov/DefinitelyTyped - -/************************************************ -* * -* Node.js v0.12.0 API * -* * -************************************************/ - -// compat for TypeScript 1.5.3 -// if you use with --target es3 or --target es5 and use below definitions, -// use the lib.es6.d.ts that is bundled with TypeScript 1.5.3. -interface MapConstructor {} -interface WeakMapConstructor {} -interface SetConstructor {} -interface WeakSetConstructor {} - -/************************************************ -* * -* GLOBAL * -* * -************************************************/ -declare var process: NodeJS.Process; -declare var global: NodeJS.Global; - -declare var __filename: string; -declare var __dirname: string; - -declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; -declare function clearTimeout(timeoutId: NodeJS.Timer): void; -declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; -declare function clearInterval(intervalId: NodeJS.Timer): void; -declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; -declare function clearImmediate(immediateId: any): void; - -interface NodeRequireFunction { - (id: string): any; -} - -interface NodeRequire extends NodeRequireFunction { - resolve(id:string): string; - cache: any; - extensions: any; - main: any; -} - -declare var require: NodeRequire; - -interface NodeModule { - exports: any; - require: NodeRequireFunction; - id: string; - filename: string; - loaded: boolean; - parent: any; - children: any[]; -} - -declare var module: NodeModule; - -// Same as module.exports -declare var exports: any; -declare var SlowBuffer: { - new (str: string, encoding?: string): Buffer; - new (size: number): Buffer; - new (size: Uint8Array): Buffer; - new (array: any[]): Buffer; - prototype: Buffer; - isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; - concat(list: Buffer[], totalLength?: number): Buffer; -}; - - -// Buffer class -interface Buffer extends NodeBuffer {} - -/** - * Raw data is stored in instances of the Buffer class. - * A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized. - * Valid string encodings: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' - */ -declare var Buffer: { - /** - * Allocates a new buffer containing the given {str}. - * - * @param str String to store in buffer. - * @param encoding encoding to use, optional. Default is 'utf8' - */ - new (str: string, encoding?: string): Buffer; - /** - * Allocates a new buffer of {size} octets. - * - * @param size count of octets to allocate. - */ - new (size: number): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - */ - new (array: Uint8Array): Buffer; - /** - * Allocates a new buffer containing the given {array} of octets. - * - * @param array The octets to store. - */ - new (array: any[]): Buffer; - prototype: Buffer; - /** - * Returns true if {obj} is a Buffer - * - * @param obj object to test. - */ - isBuffer(obj: any): boolean; - /** - * Returns true if {encoding} is a valid encoding argument. - * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' - * - * @param encoding string to test. - */ - isEncoding(encoding: string): boolean; - /** - * Gives the actual byte length of a string. encoding defaults to 'utf8'. - * This is not the same as String.prototype.length since that returns the number of characters in a string. - * - * @param string string to test. - * @param encoding encoding used to evaluate (defaults to 'utf8') - */ - byteLength(string: string, encoding?: string): number; - /** - * Returns a buffer which is the result of concatenating all the buffers in the list together. - * - * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. - * If the list has exactly one item, then the first item of the list is returned. - * If the list has more than one item, then a new Buffer is created. - * - * @param list An array of Buffer objects to concatenate - * @param totalLength Total length of the buffers when concatenated. - * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. - */ - concat(list: Buffer[], totalLength?: number): Buffer; - /** - * The same as buf1.compare(buf2). - */ - compare(buf1: Buffer, buf2: Buffer): number; -}; - -/************************************************ -* * -* GLOBAL INTERFACES * -* * -************************************************/ -declare module NodeJS { - export interface ErrnoException extends Error { - errno?: number; - code?: string; - path?: string; - syscall?: string; - stack?: string; - } - - export interface EventEmitter { - addListener(event: string, listener: Function): EventEmitter; - on(event: string, listener: Function): EventEmitter; - once(event: string, listener: Function): EventEmitter; - removeListener(event: string, listener: Function): EventEmitter; - removeAllListeners(event?: string): EventEmitter; - setMaxListeners(n: number): void; - listeners(event: string): Function[]; - emit(event: string, ...args: any[]): boolean; - } - - export interface ReadableStream extends EventEmitter { - readable: boolean; - read(size?: number): string|Buffer; - setEncoding(encoding: string): void; - pause(): void; - resume(): void; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: string): void; - unshift(chunk: Buffer): void; - wrap(oldStream: ReadableStream): ReadableStream; - } - - export interface WritableStream extends EventEmitter { - writable: boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } - - export interface ReadWriteStream extends ReadableStream, WritableStream {} - - export interface Process extends EventEmitter { - stdout: WritableStream; - stderr: WritableStream; - stdin: ReadableStream; - argv: string[]; - execPath: string; - abort(): void; - chdir(directory: string): void; - cwd(): string; - env: any; - exit(code?: number): void; - getgid(): number; - setgid(id: number): void; - setgid(id: string): void; - getuid(): number; - setuid(id: number): void; - setuid(id: string): void; - version: string; - versions: { - http_parser: string; - node: string; - v8: string; - ares: string; - uv: string; - zlib: string; - openssl: string; - }; - config: { - target_defaults: { - cflags: any[]; - default_configuration: string; - defines: string[]; - include_dirs: string[]; - libraries: string[]; - }; - variables: { - clang: number; - host_arch: string; - node_install_npm: boolean; - node_install_waf: boolean; - node_prefix: string; - node_shared_openssl: boolean; - node_shared_v8: boolean; - node_shared_zlib: boolean; - node_use_dtrace: boolean; - node_use_etw: boolean; - node_use_openssl: boolean; - target_arch: string; - v8_no_strict_aliasing: number; - v8_use_snapshot: boolean; - visibility: string; - }; - }; - kill(pid: number, signal?: string): void; - pid: number; - title: string; - arch: string; - platform: string; - memoryUsage(): { rss: number; heapTotal: number; heapUsed: number; }; - nextTick(callback: Function): void; - umask(mask?: number): number; - uptime(): number; - hrtime(time?:number[]): number[]; - - // Worker - send?(message: any, sendHandle?: any): void; - } - - export interface Global { - Array: typeof Array; - ArrayBuffer: typeof ArrayBuffer; - Boolean: typeof Boolean; - Buffer: typeof Buffer; - DataView: typeof DataView; - Date: typeof Date; - Error: typeof Error; - EvalError: typeof EvalError; - Float32Array: typeof Float32Array; - Float64Array: typeof Float64Array; - Function: typeof Function; - GLOBAL: Global; - Infinity: typeof Infinity; - Int16Array: typeof Int16Array; - Int32Array: typeof Int32Array; - Int8Array: typeof Int8Array; - Intl: typeof Intl; - JSON: typeof JSON; - Map: MapConstructor; - Math: typeof Math; - NaN: typeof NaN; - Number: typeof Number; - Object: typeof Object; - Promise: Function; - RangeError: typeof RangeError; - ReferenceError: typeof ReferenceError; - RegExp: typeof RegExp; - Set: SetConstructor; - String: typeof String; - Symbol: Function; - SyntaxError: typeof SyntaxError; - TypeError: typeof TypeError; - URIError: typeof URIError; - Uint16Array: typeof Uint16Array; - Uint32Array: typeof Uint32Array; - Uint8Array: typeof Uint8Array; - Uint8ClampedArray: Function; - WeakMap: WeakMapConstructor; - WeakSet: WeakSetConstructor; - clearImmediate: (immediateId: any) => void; - clearInterval: (intervalId: NodeJS.Timer) => void; - clearTimeout: (timeoutId: NodeJS.Timer) => void; - console: typeof console; - decodeURI: typeof decodeURI; - decodeURIComponent: typeof decodeURIComponent; - encodeURI: typeof encodeURI; - encodeURIComponent: typeof encodeURIComponent; - escape: (str: string) => string; - eval: typeof eval; - global: Global; - isFinite: typeof isFinite; - isNaN: typeof isNaN; - parseFloat: typeof parseFloat; - parseInt: typeof parseInt; - process: Process; - root: Global; - setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => any; - setInterval: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - setTimeout: (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer; - undefined: typeof undefined; - unescape: (str: string) => string; - gc: () => void; - } - - export interface Timer { - ref() : void; - unref() : void; - } -} - -/** - * @deprecated - */ -interface NodeBuffer { - [index: number]: number; - write(string: string, offset?: number, length?: number, encoding?: string): number; - toString(encoding?: string, start?: number, end?: number): string; - toJSON(): any; - length: number; - equals(otherBuffer: Buffer): boolean; - compare(otherBuffer: Buffer): number; - copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; - slice(start?: number, end?: number): Buffer; - writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; - readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; - readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; - readUInt8(offset: number, noAsset?: boolean): number; - readUInt16LE(offset: number, noAssert?: boolean): number; - readUInt16BE(offset: number, noAssert?: boolean): number; - readUInt32LE(offset: number, noAssert?: boolean): number; - readUInt32BE(offset: number, noAssert?: boolean): number; - readInt8(offset: number, noAssert?: boolean): number; - readInt16LE(offset: number, noAssert?: boolean): number; - readInt16BE(offset: number, noAssert?: boolean): number; - readInt32LE(offset: number, noAssert?: boolean): number; - readInt32BE(offset: number, noAssert?: boolean): number; - readFloatLE(offset: number, noAssert?: boolean): number; - readFloatBE(offset: number, noAssert?: boolean): number; - readDoubleLE(offset: number, noAssert?: boolean): number; - readDoubleBE(offset: number, noAssert?: boolean): number; - writeUInt8(value: number, offset: number, noAssert?: boolean): void; - writeUInt16LE(value: number, offset: number, noAssert?: boolean): void; - writeUInt16BE(value: number, offset: number, noAssert?: boolean): void; - writeUInt32LE(value: number, offset: number, noAssert?: boolean): void; - writeUInt32BE(value: number, offset: number, noAssert?: boolean): void; - writeInt8(value: number, offset: number, noAssert?: boolean): void; - writeInt16LE(value: number, offset: number, noAssert?: boolean): void; - writeInt16BE(value: number, offset: number, noAssert?: boolean): void; - writeInt32LE(value: number, offset: number, noAssert?: boolean): void; - writeInt32BE(value: number, offset: number, noAssert?: boolean): void; - writeFloatLE(value: number, offset: number, noAssert?: boolean): void; - writeFloatBE(value: number, offset: number, noAssert?: boolean): void; - writeDoubleLE(value: number, offset: number, noAssert?: boolean): void; - writeDoubleBE(value: number, offset: number, noAssert?: boolean): void; - fill(value: any, offset?: number, end?: number): void; -} - -/************************************************ -* * -* MODULES * -* * -************************************************/ -declare module "buffer" { - export var INSPECT_MAX_BYTES: number; -} - -declare module "querystring" { - export function stringify(obj: any, sep?: string, eq?: string): string; - export function parse(str: string, sep?: string, eq?: string, options?: { maxKeys?: number; }): any; - export function escape(str: string): string; - export function unescape(str: string): string; -} - -declare module "events" { - export class EventEmitter implements NodeJS.EventEmitter { - static listenerCount(emitter: EventEmitter, event: string): number; - - addListener(event: string, listener: Function): EventEmitter; - on(event: string, listener: Function): EventEmitter; - once(event: string, listener: Function): EventEmitter; - removeListener(event: string, listener: Function): EventEmitter; - removeAllListeners(event?: string): EventEmitter; - setMaxListeners(n: number): void; - listeners(event: string): Function[]; - emit(event: string, ...args: any[]): boolean; - } -} - -declare module "http" { - import * as events from "events"; - import * as net from "net"; - import * as stream from "stream"; - - export interface Server extends events.EventEmitter { - listen(port: number, hostname?: string, backlog?: number, callback?: Function): Server; - listen(port: number, hostname?: string, callback?: Function): Server; - listen(path: string, callback?: Function): Server; - listen(handle: any, listeningListener?: Function): Server; - close(cb?: any): Server; - address(): { port: number; family: string; address: string; }; - maxHeadersCount: number; - } - /** - * @deprecated Use IncomingMessage - */ - export interface ServerRequest extends IncomingMessage { - connection: net.Socket; - } - export interface ServerResponse extends events.EventEmitter, stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - writeContinue(): void; - writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; - writeHead(statusCode: number, headers?: any): void; - statusCode: number; - statusMessage: string; - setHeader(name: string, value: string): void; - sendDate: boolean; - getHeader(name: string): string; - removeHeader(name: string): void; - write(chunk: any, encoding?: string): any; - addTrailers(headers: any): void; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface ClientRequest extends events.EventEmitter, stream.Writable { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - write(chunk: any, encoding?: string): void; - abort(): void; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - export interface IncomingMessage extends events.EventEmitter, stream.Readable { - httpVersion: string; - headers: any; - rawHeaders: string[]; - trailers: any; - rawTrailers: any; - setTimeout(msecs: number, callback: Function): NodeJS.Timer; - /** - * Only valid for request obtained from http.Server. - */ - method?: string; - /** - * Only valid for request obtained from http.Server. - */ - url?: string; - /** - * Only valid for response obtained from http.ClientRequest. - */ - statusCode?: number; - /** - * Only valid for response obtained from http.ClientRequest. - */ - statusMessage?: string; - socket: net.Socket; - } - /** - * @deprecated Use IncomingMessage - */ - export interface ClientResponse extends IncomingMessage { } - - export interface AgentOptions { - /** - * Keep sockets around in a pool to be used by other requests in the future. Default = false - */ - keepAlive?: boolean; - /** - * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. Default = 1000. - * Only relevant if keepAlive is set to true. - */ - keepAliveMsecs?: number; - /** - * Maximum number of sockets to allow per host. Default for Node 0.10 is 5, default for Node 0.12 is Infinity - */ - maxSockets?: number; - /** - * Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. - */ - maxFreeSockets?: number; - } - - export class Agent { - maxSockets: number; - sockets: any; - requests: any; - - constructor(opts?: AgentOptions); - - /** - * Destroy any sockets that are currently in use by the agent. - * It is usually not necessary to do this. However, if you are using an agent with KeepAlive enabled, - * then it is best to explicitly shut down the agent when you know that it will no longer be used. Otherwise, - * sockets may hang open for quite a long time before the server terminates them. - */ - destroy(): void; - } - - export var METHODS: string[]; - - export var STATUS_CODES: { - [errorCode: number]: string; - [errorCode: string]: string; - }; - export function createServer(requestListener?: (request: IncomingMessage, response: ServerResponse) =>void ): Server; - export function createClient(port?: number, host?: string): any; - export function request(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; - export function get(options: any, callback?: (res: IncomingMessage) => void): ClientRequest; - export var globalAgent: Agent; -} - -declare module "cluster" { - import * as child from "child_process"; - import * as events from "events"; - - export interface ClusterSettings { - exec?: string; - args?: string[]; - silent?: boolean; - } - - export class Worker extends events.EventEmitter { - id: string; - process: child.ChildProcess; - suicide: boolean; - send(message: any, sendHandle?: any): void; - kill(signal?: string): void; - destroy(signal?: string): void; - disconnect(): void; - } - - export var settings: ClusterSettings; - export var isMaster: boolean; - export var isWorker: boolean; - export function setupMaster(settings?: ClusterSettings): void; - export function fork(env?: any): Worker; - export function disconnect(callback?: Function): void; - export var worker: Worker; - export var workers: Worker[]; - - // Event emitter - export function addListener(event: string, listener: Function): void; - export function on(event: string, listener: Function): any; - export function once(event: string, listener: Function): void; - export function removeListener(event: string, listener: Function): void; - export function removeAllListeners(event?: string): void; - export function setMaxListeners(n: number): void; - export function listeners(event: string): Function[]; - export function emit(event: string, ...args: any[]): boolean; -} - -declare module "zlib" { - import * as stream from "stream"; - export interface ZlibOptions { chunkSize?: number; windowBits?: number; level?: number; memLevel?: number; strategy?: number; dictionary?: any; } - - export interface Gzip extends stream.Transform { } - export interface Gunzip extends stream.Transform { } - export interface Deflate extends stream.Transform { } - export interface Inflate extends stream.Transform { } - export interface DeflateRaw extends stream.Transform { } - export interface InflateRaw extends stream.Transform { } - export interface Unzip extends stream.Transform { } - - export function createGzip(options?: ZlibOptions): Gzip; - export function createGunzip(options?: ZlibOptions): Gunzip; - export function createDeflate(options?: ZlibOptions): Deflate; - export function createInflate(options?: ZlibOptions): Inflate; - export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; - export function createInflateRaw(options?: ZlibOptions): InflateRaw; - export function createUnzip(options?: ZlibOptions): Unzip; - - export function deflate(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function deflateSync(buf: Buffer, options?: ZlibOptions): any; - export function deflateRaw(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function deflateRawSync(buf: Buffer, options?: ZlibOptions): any; - export function gzip(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function gzipSync(buf: Buffer, options?: ZlibOptions): any; - export function gunzip(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function gunzipSync(buf: Buffer, options?: ZlibOptions): any; - export function inflate(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function inflateSync(buf: Buffer, options?: ZlibOptions): any; - export function inflateRaw(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function inflateRawSync(buf: Buffer, options?: ZlibOptions): any; - export function unzip(buf: Buffer, callback: (error: Error, result: any) =>void ): void; - export function unzipSync(buf: Buffer, options?: ZlibOptions): any; - - // Constants - export var Z_NO_FLUSH: number; - export var Z_PARTIAL_FLUSH: number; - export var Z_SYNC_FLUSH: number; - export var Z_FULL_FLUSH: number; - export var Z_FINISH: number; - export var Z_BLOCK: number; - export var Z_TREES: number; - export var Z_OK: number; - export var Z_STREAM_END: number; - export var Z_NEED_DICT: number; - export var Z_ERRNO: number; - export var Z_STREAM_ERROR: number; - export var Z_DATA_ERROR: number; - export var Z_MEM_ERROR: number; - export var Z_BUF_ERROR: number; - export var Z_VERSION_ERROR: number; - export var Z_NO_COMPRESSION: number; - export var Z_BEST_SPEED: number; - export var Z_BEST_COMPRESSION: number; - export var Z_DEFAULT_COMPRESSION: number; - export var Z_FILTERED: number; - export var Z_HUFFMAN_ONLY: number; - export var Z_RLE: number; - export var Z_FIXED: number; - export var Z_DEFAULT_STRATEGY: number; - export var Z_BINARY: number; - export var Z_TEXT: number; - export var Z_ASCII: number; - export var Z_UNKNOWN: number; - export var Z_DEFLATED: number; - export var Z_NULL: number; -} - -declare module "os" { - export function tmpdir(): string; - export function hostname(): string; - export function type(): string; - export function platform(): string; - export function arch(): string; - export function release(): string; - export function uptime(): number; - export function loadavg(): number[]; - export function totalmem(): number; - export function freemem(): number; - export function cpus(): { model: string; speed: number; times: { user: number; nice: number; sys: number; idle: number; irq: number; }; }[]; - export function networkInterfaces(): any; - export var EOL: string; -} - -declare module "https" { - import * as tls from "tls"; - import * as events from "events"; - import * as http from "http"; - - export interface ServerOptions { - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - crl?: any; - ciphers?: string; - honorCipherOrder?: boolean; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: any; - SNICallback?: (servername: string) => any; - } - - export interface RequestOptions { - host?: string; - hostname?: string; - port?: number; - path?: string; - method?: string; - headers?: any; - auth?: string; - agent?: any; - pfx?: any; - key?: any; - passphrase?: string; - cert?: any; - ca?: any; - ciphers?: string; - rejectUnauthorized?: boolean; - } - - export interface Agent { - maxSockets: number; - sockets: any; - requests: any; - } - export var Agent: { - new (options?: RequestOptions): Agent; - }; - export interface Server extends tls.Server { } - export function createServer(options: ServerOptions, requestListener?: Function): Server; - export function request(options: RequestOptions, callback?: (res: http.IncomingMessage) =>void ): http.ClientRequest; - export function get(options: RequestOptions, callback?: (res: http.IncomingMessage) =>void ): http.ClientRequest; - export var globalAgent: Agent; -} - -declare module "punycode" { - export function decode(string: string): string; - export function encode(string: string): string; - export function toUnicode(domain: string): string; - export function toASCII(domain: string): string; - export var ucs2: ucs2; - interface ucs2 { - decode(string: string): string; - encode(codePoints: number[]): string; - } - export var version: any; -} - -declare module "repl" { - import * as stream from "stream"; - import * as events from "events"; - - export interface ReplOptions { - prompt?: string; - input?: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - terminal?: boolean; - eval?: Function; - useColors?: boolean; - useGlobal?: boolean; - ignoreUndefined?: boolean; - writer?: Function; - } - export function start(options: ReplOptions): events.EventEmitter; -} - -declare module "readline" { - import * as events from "events"; - import * as stream from "stream"; - - export interface ReadLine extends events.EventEmitter { - setPrompt(prompt: string): void; - prompt(preserveCursor?: boolean): void; - question(query: string, callback: Function): void; - pause(): void; - resume(): void; - close(): void; - write(data: any, key?: any): void; - } - export interface ReadLineOptions { - input: NodeJS.ReadableStream; - output: NodeJS.WritableStream; - completer?: Function; - terminal?: boolean; - } - export function createInterface(options: ReadLineOptions): ReadLine; -} - -declare module "vm" { - export interface Context { } - export interface Script { - runInThisContext(): void; - runInNewContext(sandbox?: Context): void; - } - export function runInThisContext(code: string, filename?: string): void; - export function runInNewContext(code: string, sandbox?: Context, filename?: string): void; - export function runInContext(code: string, context: Context, filename?: string): void; - export function createContext(initSandbox?: Context): Context; - export function createScript(code: string, filename?: string): Script; -} - -declare module "child_process" { - import * as events from "events"; - import * as stream from "stream"; - - export interface ChildProcess extends events.EventEmitter { - stdin: stream.Writable; - stdout: stream.Readable; - stderr: stream.Readable; - pid: number; - kill(signal?: string): void; - send(message: any, sendHandle?: any): void; - disconnect(): void; - unref(): void; - } - - export function spawn(command: string, args?: string[], options?: { - cwd?: string; - stdio?: any; - custom?: any; - env?: any; - detached?: boolean; - }): ChildProcess; - export function exec(command: string, options: { - cwd?: string; - stdio?: any; - customFds?: any; - env?: any; - encoding?: string; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - }, callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; - export function exec(command: string, callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; - export function execFile(file: string, - callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; - export function execFile(file: string, args?: string[], - callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; - export function execFile(file: string, args?: string[], options?: { - cwd?: string; - stdio?: any; - customFds?: any; - env?: any; - encoding?: string; - timeout?: number; - maxBuffer?: string; - killSignal?: string; - }, callback?: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; - export function fork(modulePath: string, args?: string[], options?: { - cwd?: string; - env?: any; - encoding?: string; - }): ChildProcess; - export function execSync(command: string, options?: { - cwd?: string; - input?: string|Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - encoding?: string; - }): ChildProcess; - export function execFileSync(command: string, args?: string[], options?: { - cwd?: string; - input?: string|Buffer; - stdio?: any; - env?: any; - uid?: number; - gid?: number; - timeout?: number; - maxBuffer?: number; - killSignal?: string; - encoding?: string; - }): ChildProcess; -} - -declare module "url" { - export interface Url { - href: string; - protocol: string; - auth: string; - hostname: string; - port: string; - host: string; - pathname: string; - search: string; - query: any; // string | Object - slashes: boolean; - hash?: string; - path?: string; - } - - export interface UrlOptions { - protocol?: string; - auth?: string; - hostname?: string; - port?: string; - host?: string; - pathname?: string; - search?: string; - query?: any; - hash?: string; - path?: string; - } - - export function parse(urlStr: string, parseQueryString?: boolean , slashesDenoteHost?: boolean ): Url; - export function format(url: UrlOptions): string; - export function resolve(from: string, to: string): string; -} - -declare module "dns" { - export function lookup(domain: string, family: number, callback: (err: Error, address: string, family: number) =>void ): string; - export function lookup(domain: string, callback: (err: Error, address: string, family: number) =>void ): string; - export function resolve(domain: string, rrtype: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolve(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolve4(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolve6(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolveMx(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolveTxt(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolveSrv(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolveNs(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function resolveCname(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; - export function reverse(ip: string, callback: (err: Error, domains: string[]) =>void ): string[]; -} - -declare module "net" { - import * as stream from "stream"; - - export interface Socket extends stream.Duplex { - // Extended base methods - write(buffer: Buffer): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - write(str: string, encoding?: string, fd?: string): boolean; - - connect(port: number, host?: string, connectionListener?: Function): void; - connect(path: string, connectionListener?: Function): void; - bufferSize: number; - setEncoding(encoding?: string): void; - write(data: any, encoding?: string, callback?: Function): void; - destroy(): void; - pause(): void; - resume(): void; - setTimeout(timeout: number, callback?: Function): void; - setNoDelay(noDelay?: boolean): void; - setKeepAlive(enable?: boolean, initialDelay?: number): void; - address(): { port: number; family: string; address: string; }; - unref(): void; - ref(): void; - - remoteAddress: string; - remoteFamily: string; - remotePort: number; - localAddress: string; - localPort: number; - bytesRead: number; - bytesWritten: number; - - // Extended base methods - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - end(data?: any, encoding?: string): void; - } - - export var Socket: { - new (options?: { fd?: string; type?: string; allowHalfOpen?: boolean; }): Socket; - }; - - export interface Server extends Socket { - listen(port: number, host?: string, backlog?: number, listeningListener?: Function): Server; - listen(path: string, listeningListener?: Function): Server; - listen(handle: any, listeningListener?: Function): Server; - close(callback?: Function): Server; - address(): { port: number; family: string; address: string; }; - maxConnections: number; - connections: number; - } - export function createServer(connectionListener?: (socket: Socket) =>void ): Server; - export function createServer(options?: { allowHalfOpen?: boolean; }, connectionListener?: (socket: Socket) =>void ): Server; - export function connect(options: { allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function connect(port: number, host?: string, connectionListener?: Function): Socket; - export function connect(path: string, connectionListener?: Function): Socket; - export function createConnection(options: { allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; - export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; - export function createConnection(path: string, connectionListener?: Function): Socket; - export function isIP(input: string): number; - export function isIPv4(input: string): boolean; - export function isIPv6(input: string): boolean; -} - -declare module "dgram" { - import * as events from "events"; - - interface RemoteInfo { - address: string; - port: number; - size: number; - } - - interface AddressInfo { - address: string; - family: string; - port: number; - } - - export function createSocket(type: string, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket; - - interface Socket extends events.EventEmitter { - send(buf: Buffer, offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; - bind(port: number, address?: string, callback?: () => void): void; - close(): void; - address(): AddressInfo; - setBroadcast(flag: boolean): void; - setMulticastTTL(ttl: number): void; - setMulticastLoopback(flag: boolean): void; - addMembership(multicastAddress: string, multicastInterface?: string): void; - dropMembership(multicastAddress: string, multicastInterface?: string): void; - } -} - -declare module "fs" { - import * as stream from "stream"; - import * as events from "events"; - - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - } - - interface FSWatcher extends events.EventEmitter { - close(): void; - } - - export interface ReadStream extends stream.Readable { - close(): void; - } - export interface WriteStream extends stream.Writable { - close(): void; - bytesWritten: number; - } - - /** - * Asynchronous rename. - * @param oldPath - * @param newPath - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /** - * Synchronous rename - * @param oldPath - * @param newPath - */ - export function renameSync(oldPath: string, newPath: string): void; - export function truncate(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncate(path: string, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function truncateSync(path: string, len?: number): void; - export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function ftruncateSync(fd: number, len?: number): void; - export function chown(path: string, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chownSync(path: string, uid: number, gid: number): void; - export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchownSync(fd: number, uid: number, gid: number): void; - export function lchown(path: string, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchownSync(path: string, uid: number, gid: number): void; - export function chmod(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmod(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function chmodSync(path: string, mode: number): void; - export function chmodSync(path: string, mode: string): void; - export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fchmodSync(fd: number, mode: number): void; - export function fchmodSync(fd: number, mode: string): void; - export function lchmod(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmod(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function lchmodSync(path: string, mode: number): void; - export function lchmodSync(path: string, mode: string): void; - export function stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function lstat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - export function statSync(path: string): Stats; - export function lstatSync(path: string): Stats; - export function fstatSync(fd: number): Stats; - export function link(srcpath: string, dstpath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function linkSync(srcpath: string, dstpath: string): void; - export function symlink(srcpath: string, dstpath: string, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function symlinkSync(srcpath: string, dstpath: string, type?: string): void; - export function readlink(path: string, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; - export function readlinkSync(path: string): string; - export function realpath(path: string, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; - export function realpath(path: string, cache: {[path: string]: string}, callback: (err: NodeJS.ErrnoException, resolvedPath: string) =>any): void; - export function realpathSync(path: string, cache?: { [path: string]: string }): string; - /* - * Asynchronous unlink - deletes the file specified in {path} - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function unlink(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous unlink - deletes the file specified in {path} - * - * @param path - */ - export function unlinkSync(path: string): void; - /* - * Asynchronous rmdir - removes the directory specified in {path} - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function rmdir(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous rmdir - removes the directory specified in {path} - * - * @param path - */ - export function rmdirSync(path: string): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Asynchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdir(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - /* - * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdirSync(path: string, mode?: number): void; - /* - * Synchronous mkdir - creates the directory specified in {path}. Parameter {mode} defaults to 0777. - * - * @param path - * @param mode - * @param callback No arguments other than a possible exception are given to the completion callback. - */ - export function mkdirSync(path: string, mode?: string): void; - export function readdir(path: string, callback?: (err: NodeJS.ErrnoException, files: string[]) => void): void; - export function readdirSync(path: string): string[]; - export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function closeSync(fd: number): void; - export function open(path: string, flags: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void; - export function open(path: string, flags: string, mode: number, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void; - export function open(path: string, flags: string, mode: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void; - export function openSync(path: string, flags: string, mode?: number): number; - export function openSync(path: string, flags: string, mode?: string): number; - export function utimes(path: string, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimes(path: string, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function utimesSync(path: string, atime: number, mtime: number): void; - export function utimesSync(path: string, atime: Date, mtime: Date): void; - export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function futimesSync(fd: number, atime: number, mtime: number): void; - export function futimesSync(fd: number, atime: Date, mtime: Date): void; - export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function fsyncSync(fd: number): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function write(fd: number, buffer: Buffer, offset: number, length: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; - export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; - export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; - export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param encoding - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFile returns a string; otherwise it returns a Buffer. - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - /* - * Asynchronous readFile - Asynchronously reads the entire contents of a file. - * - * @param fileName - * @param callback - The callback is passed two arguments (err, data), where data is the contents of the file. - */ - export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param encoding - */ - export function readFileSync(filename: string, encoding: string): string; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. - */ - export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; - /* - * Synchronous readFile - Synchronously reads the entire contents of a file. - * - * @param fileName - * @param options An object with optional {encoding} and {flag} properties. If {encoding} is specified, readFileSync returns a string; otherwise it returns a Buffer. - */ - export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; - export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; - export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; - export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; - export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; - export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; - export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; - export function watch(filename: string, options: { persistent?: boolean; }, listener?: (event: string, filename: string) => any): FSWatcher; - export function exists(path: string, callback?: (exists: boolean) => void): void; - export function existsSync(path: string): boolean; - /** Constant for fs.access(). File is visible to the calling process. */ - export var F_OK: number; - /** Constant for fs.access(). File can be read by the calling process. */ - export var R_OK: number; - /** Constant for fs.access(). File can be written by the calling process. */ - export var W_OK: number; - /** Constant for fs.access(). File can be executed by the calling process. */ - export var X_OK: number; - /** Tests a user's permissions for the file specified by path. */ - export function access(path: string, callback: (err: NodeJS.ErrnoException) => void): void; - export function access(path: string, mode: number, callback: (err: NodeJS.ErrnoException) => void): void; - /** Synchronous version of fs.access. This throws if any accessibility checks fail, and does nothing otherwise. */ - export function accessSync(path: string, mode ?: number): void; - export function createReadStream(path: string, options?: { - flags?: string; - encoding?: string; - fd?: string; - mode?: number; - bufferSize?: number; - }): ReadStream; - export function createReadStream(path: string, options?: { - flags?: string; - encoding?: string; - fd?: string; - mode?: string; - bufferSize?: number; - }): ReadStream; - export function createWriteStream(path: string, options?: { - flags?: string; - encoding?: string; - string?: string; - }): WriteStream; -} - -declare module "path" { - - /** - * A parsed path object generated by path.parse() or consumed by path.format(). - */ - export interface ParsedPath { - /** - * The root of the path such as '/' or 'c:\' - */ - root: string; - /** - * The full directory path such as '/home/user/dir' or 'c:\path\dir' - */ - dir: string; - /** - * The file name including extension (if any) such as 'index.html' - */ - base: string; - /** - * The file extension (if any) such as '.html' - */ - ext: string; - /** - * The file name without extension (if any) such as 'index' - */ - name: string; - } - - /** - * Normalize a string path, reducing '..' and '.' parts. - * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. - * - * @param p string path to normalize. - */ - export function normalize(p: string): string; - /** - * Join all arguments together and normalize the resulting path. - * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. - * - * @param paths string paths to join. - */ - export function join(...paths: any[]): string; - /** - * Join all arguments together and normalize the resulting path. - * Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown. - * - * @param paths string paths to join. - */ - export function join(...paths: string[]): string; - /** - * The right-most parameter is considered {to}. Other parameters are considered an array of {from}. - * - * Starting from leftmost {from} paramter, resolves {to} to an absolute path. - * - * If {to} isn't already absolute, {from} arguments are prepended in right to left order, until an absolute path is found. If after using all {from} paths still no absolute path is found, the current working directory is used as well. The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory. - * - * @param pathSegments string paths to join. Non-string arguments are ignored. - */ - export function resolve(...pathSegments: any[]): string; - /** - * Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory. - * - * @param path path to test. - */ - export function isAbsolute(path: string): boolean; - /** - * Solve the relative path from {from} to {to}. - * At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve. - * - * @param from - * @param to - */ - export function relative(from: string, to: string): string; - /** - * Return the directory name of a path. Similar to the Unix dirname command. - * - * @param p the path to evaluate. - */ - export function dirname(p: string): string; - /** - * Return the last portion of a path. Similar to the Unix basename command. - * Often used to extract the file name from a fully qualified path. - * - * @param p the path to evaluate. - * @param ext optionally, an extension to remove from the result. - */ - export function basename(p: string, ext?: string): string; - /** - * Return the extension of the path, from the last '.' to end of string in the last portion of the path. - * If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string - * - * @param p the path to evaluate. - */ - export function extname(p: string): string; - /** - * The platform-specific file separator. '\\' or '/'. - */ - export var sep: string; - /** - * The platform-specific file delimiter. ';' or ':'. - */ - export var delimiter: string; - /** - * Returns an object from a path string - the opposite of format(). - * - * @param pathString path to evaluate. - */ - export function parse(pathString: string): ParsedPath; - /** - * Returns a path string from an object - the opposite of parse(). - * - * @param pathString path to evaluate. - */ - export function format(pathObject: ParsedPath): string; - - export module posix { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } - - export module win32 { - export function normalize(p: string): string; - export function join(...paths: any[]): string; - export function resolve(...pathSegments: any[]): string; - export function isAbsolute(p: string): boolean; - export function relative(from: string, to: string): string; - export function dirname(p: string): string; - export function basename(p: string, ext?: string): string; - export function extname(p: string): string; - export var sep: string; - export var delimiter: string; - export function parse(p: string): ParsedPath; - export function format(pP: ParsedPath): string; - } -} - -declare module "string_decoder" { - export interface NodeStringDecoder { - write(buffer: Buffer): string; - detectIncompleteChar(buffer: Buffer): number; - } - export var StringDecoder: { - new (encoding: string): NodeStringDecoder; - }; -} - -declare module "tls" { - import * as crypto from "crypto"; - import * as net from "net"; - import * as stream from "stream"; - - var CLIENT_RENEG_LIMIT: number; - var CLIENT_RENEG_WINDOW: number; - - export interface TlsOptions { - pfx?: any; //string or buffer - key?: any; //string or buffer - passphrase?: string; - cert?: any; - ca?: any; //string or buffer - crl?: any; //string or string array - ciphers?: string; - honorCipherOrder?: any; - requestCert?: boolean; - rejectUnauthorized?: boolean; - NPNProtocols?: any; //array or Buffer; - SNICallback?: (servername: string) => any; - } - - export interface ConnectionOptions { - host?: string; - port?: number; - socket?: net.Socket; - pfx?: any; //string | Buffer - key?: any; //string | Buffer - passphrase?: string; - cert?: any; //string | Buffer - ca?: any; //Array of string | Buffer - rejectUnauthorized?: boolean; - NPNProtocols?: any; //Array of string | Buffer - servername?: string; - } - - export interface Server extends net.Server { - // Extended base methods - listen(port: number, host?: string, backlog?: number, listeningListener?: Function): Server; - listen(path: string, listeningListener?: Function): Server; - listen(handle: any, listeningListener?: Function): Server; - - listen(port: number, host?: string, callback?: Function): Server; - close(): Server; - address(): { port: number; family: string; address: string; }; - addContext(hostName: string, credentials: { - key: string; - cert: string; - ca: string; - }): void; - maxConnections: number; - connections: number; - } - - export interface ClearTextStream extends stream.Duplex { - authorized: boolean; - authorizationError: Error; - getPeerCertificate(): any; - getCipher: { - name: string; - version: string; - }; - address: { - port: number; - family: string; - address: string; - }; - remoteAddress: string; - remotePort: number; - } - - export interface SecurePair { - encrypted: any; - cleartext: any; - } - - export interface SecureContextOptions { - pfx?: any; //string | buffer - key?: any; //string | buffer - passphrase?: string; - cert?: any; // string | buffer - ca?: any; // string | buffer - crl?: any; // string | string[] - ciphers?: string; - honorCipherOrder?: boolean; - } - - export interface SecureContext { - context: any; - } - - export function createServer(options: TlsOptions, secureConnectionListener?: (cleartextStream: ClearTextStream) =>void ): Server; - export function connect(options: TlsOptions, secureConnectionListener?: () =>void ): ClearTextStream; - export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () =>void ): ClearTextStream; - export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () =>void ): ClearTextStream; - export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; - export function createSecureContext(details: SecureContextOptions): SecureContext; -} - -declare module "crypto" { - export interface CredentialDetails { - pfx: string; - key: string; - passphrase: string; - cert: string; - ca: any; //string | string array - crl: any; //string | string array - ciphers: string; - } - export interface Credentials { context?: any; } - export function createCredentials(details: CredentialDetails): Credentials; - export function createHash(algorithm: string): Hash; - export function createHmac(algorithm: string, key: string): Hmac; - export function createHmac(algorithm: string, key: Buffer): Hmac; - interface Hash { - update(data: any, input_encoding?: string): Hash; - digest(encoding: 'buffer'): Buffer; - digest(encoding: string): any; - digest(): Buffer; - } - interface Hmac { - update(data: any, input_encoding?: string): Hmac; - digest(encoding: 'buffer'): Buffer; - digest(encoding: string): any; - digest(): Buffer; - } - export function createCipher(algorithm: string, password: any): Cipher; - export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; - interface Cipher { - update(data: Buffer): Buffer; - update(data: string, input_encoding?: string, output_encoding?: string): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding: boolean): void; - } - export function createDecipher(algorithm: string, password: any): Decipher; - export function createDecipheriv(algorithm: string, key: any, iv: any): Decipher; - interface Decipher { - update(data: Buffer): Buffer; - update(data: string, input_encoding?: string, output_encoding?: string): string; - final(): Buffer; - final(output_encoding: string): string; - setAutoPadding(auto_padding: boolean): void; - } - export function createSign(algorithm: string): Signer; - interface Signer extends NodeJS.WritableStream { - update(data: any): void; - sign(private_key: string, output_format: string): string; - } - export function createVerify(algorith: string): Verify; - interface Verify extends NodeJS.WritableStream { - update(data: any): void; - verify(object: string, signature: string, signature_format?: string): boolean; - } - export function createDiffieHellman(prime_length: number): DiffieHellman; - export function createDiffieHellman(prime: number, encoding?: string): DiffieHellman; - interface DiffieHellman { - generateKeys(encoding?: string): string; - computeSecret(other_public_key: string, input_encoding?: string, output_encoding?: string): string; - getPrime(encoding?: string): string; - getGenerator(encoding: string): string; - getPublicKey(encoding?: string): string; - getPrivateKey(encoding?: string): string; - setPublicKey(public_key: string, encoding?: string): void; - setPrivateKey(public_key: string, encoding?: string): void; - } - export function getDiffieHellman(group_name: string): DiffieHellman; - export function pbkdf2(password: string, salt: string, iterations: number, keylen: number, callback: (err: Error, derivedKey: Buffer) => any): void; - export function pbkdf2(password: string, salt: string, iterations: number, keylen: number, digest: string, callback: (err: Error, derivedKey: Buffer) => any): void; - export function pbkdf2Sync(password: string, salt: string, iterations: number, keylen: number) : Buffer; - export function pbkdf2Sync(password: string, salt: string, iterations: number, keylen: number, digest: string) : Buffer; - export function randomBytes(size: number): Buffer; - export function randomBytes(size: number, callback: (err: Error, buf: Buffer) =>void ): void; - export function pseudoRandomBytes(size: number): Buffer; - export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) =>void ): void; -} - -declare module "stream" { - import * as events from "events"; - - export interface Stream extends events.EventEmitter { - pipe(destination: T, options?: { end?: boolean; }): T; - } - - export interface ReadableOptions { - highWaterMark?: number; - encoding?: string; - objectMode?: boolean; - } - - export class Readable extends events.EventEmitter implements NodeJS.ReadableStream { - readable: boolean; - constructor(opts?: ReadableOptions); - _read(size: number): void; - read(size?: number): string|Buffer; - setEncoding(encoding: string): void; - pause(): void; - resume(): void; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: string): void; - unshift(chunk: Buffer): void; - wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; - push(chunk: any, encoding?: string): boolean; - } - - export interface WritableOptions { - highWaterMark?: number; - decodeStrings?: boolean; - } - - export class Writable extends events.EventEmitter implements NodeJS.WritableStream { - writable: boolean; - constructor(opts?: WritableOptions); - _write(data: Buffer, encoding: string, callback: Function): void; - _write(data: string, encoding: string, callback: Function): void; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } - - export interface DuplexOptions extends ReadableOptions, WritableOptions { - allowHalfOpen?: boolean; - } - - // Note: Duplex extends both Readable and Writable. - export class Duplex extends Readable implements NodeJS.ReadWriteStream { - writable: boolean; - constructor(opts?: DuplexOptions); - _write(data: Buffer, encoding: string, callback: Function): void; - _write(data: string, encoding: string, callback: Function): void; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } - - export interface TransformOptions extends ReadableOptions, WritableOptions {} - - // Note: Transform lacks the _read and _write methods of Readable/Writable. - export class Transform extends events.EventEmitter implements NodeJS.ReadWriteStream { - readable: boolean; - writable: boolean; - constructor(opts?: TransformOptions); - _transform(chunk: Buffer, encoding: string, callback: Function): void; - _transform(chunk: string, encoding: string, callback: Function): void; - _flush(callback: Function): void; - read(size?: number): any; - setEncoding(encoding: string): void; - pause(): void; - resume(): void; - pipe(destination: T, options?: { end?: boolean; }): T; - unpipe(destination?: T): void; - unshift(chunk: string): void; - unshift(chunk: Buffer): void; - wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; - push(chunk: any, encoding?: string): boolean; - write(buffer: Buffer, cb?: Function): boolean; - write(str: string, cb?: Function): boolean; - write(str: string, encoding?: string, cb?: Function): boolean; - end(): void; - end(buffer: Buffer, cb?: Function): void; - end(str: string, cb?: Function): void; - end(str: string, encoding?: string, cb?: Function): void; - } - - export class PassThrough extends Transform {} -} - -declare module "util" { - export interface InspectOptions { - showHidden?: boolean; - depth?: number; - colors?: boolean; - customInspect?: boolean; - } - - export function format(format: any, ...param: any[]): string; - export function debug(string: string): void; - export function error(...param: any[]): void; - export function puts(...param: any[]): void; - export function print(...param: any[]): void; - export function log(string: string): void; - export function inspect(object: any, showHidden?: boolean, depth?: number, color?: boolean): string; - export function inspect(object: any, options: InspectOptions): string; - export function isArray(object: any): boolean; - export function isRegExp(object: any): boolean; - export function isDate(object: any): boolean; - export function isError(object: any): boolean; - export function inherits(constructor: any, superConstructor: any): void; -} - -declare module "assert" { - function internal (value: any, message?: string): void; - module internal { - export class AssertionError implements Error { - name: string; - message: string; - actual: any; - expected: any; - operator: string; - generatedMessage: boolean; - - constructor(options?: {message?: string; actual?: any; expected?: any; - operator?: string; stackStartFunction?: Function}); - } - - export function fail(actual?: any, expected?: any, message?: string, operator?: string): void; - export function ok(value: any, message?: string): void; - export function equal(actual: any, expected: any, message?: string): void; - export function notEqual(actual: any, expected: any, message?: string): void; - export function deepEqual(actual: any, expected: any, message?: string): void; - export function notDeepEqual(acutal: any, expected: any, message?: string): void; - export function strictEqual(actual: any, expected: any, message?: string): void; - export function notStrictEqual(actual: any, expected: any, message?: string): void; - export var throws: { - (block: Function, message?: string): void; - (block: Function, error: Function, message?: string): void; - (block: Function, error: RegExp, message?: string): void; - (block: Function, error: (err: any) => boolean, message?: string): void; - }; - - export var doesNotThrow: { - (block: Function, message?: string): void; - (block: Function, error: Function, message?: string): void; - (block: Function, error: RegExp, message?: string): void; - (block: Function, error: (err: any) => boolean, message?: string): void; - }; - - export function ifError(value: any): void; - } - - export = internal; -} - -declare module "tty" { - import * as net from "net"; - - export function isatty(fd: number): boolean; - export interface ReadStream extends net.Socket { - isRaw: boolean; - setRawMode(mode: boolean): void; - } - export interface WriteStream extends net.Socket { - columns: number; - rows: number; - } -} - -declare module "domain" { - import * as events from "events"; - - export class Domain extends events.EventEmitter { - run(fn: Function): void; - add(emitter: events.EventEmitter): void; - remove(emitter: events.EventEmitter): void; - bind(cb: (err: Error, data: any) => any): any; - intercept(cb: (data: any) => any): any; - dispose(): void; - - addListener(event: string, listener: Function): Domain; - on(event: string, listener: Function): Domain; - once(event: string, listener: Function): Domain; - removeListener(event: string, listener: Function): Domain; - removeAllListeners(event?: string): Domain; - } - - export function create(): Domain; -} - -declare module "constants" { - export var E2BIG: number; - export var EACCES: number; - export var EADDRINUSE: number; - export var EADDRNOTAVAIL: number; - export var EAFNOSUPPORT: number; - export var EAGAIN: number; - export var EALREADY: number; - export var EBADF: number; - export var EBADMSG: number; - export var EBUSY: number; - export var ECANCELED: number; - export var ECHILD: number; - export var ECONNABORTED: number; - export var ECONNREFUSED: number; - export var ECONNRESET: number; - export var EDEADLK: number; - export var EDESTADDRREQ: number; - export var EDOM: number; - export var EEXIST: number; - export var EFAULT: number; - export var EFBIG: number; - export var EHOSTUNREACH: number; - export var EIDRM: number; - export var EILSEQ: number; - export var EINPROGRESS: number; - export var EINTR: number; - export var EINVAL: number; - export var EIO: number; - export var EISCONN: number; - export var EISDIR: number; - export var ELOOP: number; - export var EMFILE: number; - export var EMLINK: number; - export var EMSGSIZE: number; - export var ENAMETOOLONG: number; - export var ENETDOWN: number; - export var ENETRESET: number; - export var ENETUNREACH: number; - export var ENFILE: number; - export var ENOBUFS: number; - export var ENODATA: number; - export var ENODEV: number; - export var ENOENT: number; - export var ENOEXEC: number; - export var ENOLCK: number; - export var ENOLINK: number; - export var ENOMEM: number; - export var ENOMSG: number; - export var ENOPROTOOPT: number; - export var ENOSPC: number; - export var ENOSR: number; - export var ENOSTR: number; - export var ENOSYS: number; - export var ENOTCONN: number; - export var ENOTDIR: number; - export var ENOTEMPTY: number; - export var ENOTSOCK: number; - export var ENOTSUP: number; - export var ENOTTY: number; - export var ENXIO: number; - export var EOPNOTSUPP: number; - export var EOVERFLOW: number; - export var EPERM: number; - export var EPIPE: number; - export var EPROTO: number; - export var EPROTONOSUPPORT: number; - export var EPROTOTYPE: number; - export var ERANGE: number; - export var EROFS: number; - export var ESPIPE: number; - export var ESRCH: number; - export var ETIME: number; - export var ETIMEDOUT: number; - export var ETXTBSY: number; - export var EWOULDBLOCK: number; - export var EXDEV: number; - export var WSAEINTR: number; - export var WSAEBADF: number; - export var WSAEACCES: number; - export var WSAEFAULT: number; - export var WSAEINVAL: number; - export var WSAEMFILE: number; - export var WSAEWOULDBLOCK: number; - export var WSAEINPROGRESS: number; - export var WSAEALREADY: number; - export var WSAENOTSOCK: number; - export var WSAEDESTADDRREQ: number; - export var WSAEMSGSIZE: number; - export var WSAEPROTOTYPE: number; - export var WSAENOPROTOOPT: number; - export var WSAEPROTONOSUPPORT: number; - export var WSAESOCKTNOSUPPORT: number; - export var WSAEOPNOTSUPP: number; - export var WSAEPFNOSUPPORT: number; - export var WSAEAFNOSUPPORT: number; - export var WSAEADDRINUSE: number; - export var WSAEADDRNOTAVAIL: number; - export var WSAENETDOWN: number; - export var WSAENETUNREACH: number; - export var WSAENETRESET: number; - export var WSAECONNABORTED: number; - export var WSAECONNRESET: number; - export var WSAENOBUFS: number; - export var WSAEISCONN: number; - export var WSAENOTCONN: number; - export var WSAESHUTDOWN: number; - export var WSAETOOMANYREFS: number; - export var WSAETIMEDOUT: number; - export var WSAECONNREFUSED: number; - export var WSAELOOP: number; - export var WSAENAMETOOLONG: number; - export var WSAEHOSTDOWN: number; - export var WSAEHOSTUNREACH: number; - export var WSAENOTEMPTY: number; - export var WSAEPROCLIM: number; - export var WSAEUSERS: number; - export var WSAEDQUOT: number; - export var WSAESTALE: number; - export var WSAEREMOTE: number; - export var WSASYSNOTREADY: number; - export var WSAVERNOTSUPPORTED: number; - export var WSANOTINITIALISED: number; - export var WSAEDISCON: number; - export var WSAENOMORE: number; - export var WSAECANCELLED: number; - export var WSAEINVALIDPROCTABLE: number; - export var WSAEINVALIDPROVIDER: number; - export var WSAEPROVIDERFAILEDINIT: number; - export var WSASYSCALLFAILURE: number; - export var WSASERVICE_NOT_FOUND: number; - export var WSATYPE_NOT_FOUND: number; - export var WSA_E_NO_MORE: number; - export var WSA_E_CANCELLED: number; - export var WSAEREFUSED: number; - export var SIGHUP: number; - export var SIGINT: number; - export var SIGILL: number; - export var SIGABRT: number; - export var SIGFPE: number; - export var SIGKILL: number; - export var SIGSEGV: number; - export var SIGTERM: number; - export var SIGBREAK: number; - export var SIGWINCH: number; - export var SSL_OP_ALL: number; - export var SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number; - export var SSL_OP_CIPHER_SERVER_PREFERENCE: number; - export var SSL_OP_CISCO_ANYCONNECT: number; - export var SSL_OP_COOKIE_EXCHANGE: number; - export var SSL_OP_CRYPTOPRO_TLSEXT_BUG: number; - export var SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number; - export var SSL_OP_EPHEMERAL_RSA: number; - export var SSL_OP_LEGACY_SERVER_CONNECT: number; - export var SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number; - export var SSL_OP_MICROSOFT_SESS_ID_BUG: number; - export var SSL_OP_MSIE_SSLV2_RSA_PADDING: number; - export var SSL_OP_NETSCAPE_CA_DN_BUG: number; - export var SSL_OP_NETSCAPE_CHALLENGE_BUG: number; - export var SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number; - export var SSL_OP_NO_COMPRESSION: number; - export var SSL_OP_NO_QUERY_MTU: number; - export var SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number; - export var SSL_OP_NO_SSLv2: number; - export var SSL_OP_NO_SSLv3: number; - export var SSL_OP_NO_TICKET: number; - export var SSL_OP_NO_TLSv1: number; - export var SSL_OP_NO_TLSv1_1: number; - export var SSL_OP_NO_TLSv1_2: number; - export var SSL_OP_PKCS1_CHECK_1: number; - export var SSL_OP_PKCS1_CHECK_2: number; - export var SSL_OP_SINGLE_DH_USE: number; - export var SSL_OP_SINGLE_ECDH_USE: number; - export var SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number; - export var SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number; - export var SSL_OP_TLS_BLOCK_PADDING_BUG: number; - export var SSL_OP_TLS_D5_BUG: number; - export var SSL_OP_TLS_ROLLBACK_BUG: number; - export var ENGINE_METHOD_DSA: number; - export var ENGINE_METHOD_DH: number; - export var ENGINE_METHOD_RAND: number; - export var ENGINE_METHOD_ECDH: number; - export var ENGINE_METHOD_ECDSA: number; - export var ENGINE_METHOD_CIPHERS: number; - export var ENGINE_METHOD_DIGESTS: number; - export var ENGINE_METHOD_STORE: number; - export var ENGINE_METHOD_PKEY_METHS: number; - export var ENGINE_METHOD_PKEY_ASN1_METHS: number; - export var ENGINE_METHOD_ALL: number; - export var ENGINE_METHOD_NONE: number; - export var DH_CHECK_P_NOT_SAFE_PRIME: number; - export var DH_CHECK_P_NOT_PRIME: number; - export var DH_UNABLE_TO_CHECK_GENERATOR: number; - export var DH_NOT_SUITABLE_GENERATOR: number; - export var NPN_ENABLED: number; - export var RSA_PKCS1_PADDING: number; - export var RSA_SSLV23_PADDING: number; - export var RSA_NO_PADDING: number; - export var RSA_PKCS1_OAEP_PADDING: number; - export var RSA_X931_PADDING: number; - export var RSA_PKCS1_PSS_PADDING: number; - export var POINT_CONVERSION_COMPRESSED: number; - export var POINT_CONVERSION_UNCOMPRESSED: number; - export var POINT_CONVERSION_HYBRID: number; - export var O_RDONLY: number; - export var O_WRONLY: number; - export var O_RDWR: number; - export var S_IFMT: number; - export var S_IFREG: number; - export var S_IFDIR: number; - export var S_IFCHR: number; - export var S_IFLNK: number; - export var O_CREAT: number; - export var O_EXCL: number; - export var O_TRUNC: number; - export var O_APPEND: number; - export var F_OK: number; - export var R_OK: number; - export var W_OK: number; - export var X_OK: number; - export var UV_UDP_REUSEADDR: number; -} diff --git a/extensions/video/src/typings/react-native-video.d.ts b/extensions/video/src/typings/react-native-video.d.ts index 5e519a07b..b399e72f5 100644 --- a/extensions/video/src/typings/react-native-video.d.ts +++ b/extensions/video/src/typings/react-native-video.d.ts @@ -1,18 +1,17 @@ -/* -* react-native-video.d.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definition for the React Native implementation -* of video player: -* https://github.com/brentvatne/react-native-video -*/ +/** + * react-native-video.d.ts + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Type definition for the React Native implementation + * of video player: + * https://github.com/brentvatne/react-native-video + */ declare module 'react-native-video' { - - import React = require('react'); - import RN = require('react-native'); + import * as React from 'react'; + import * as RN from 'react-native'; interface VideoProgress { atValue: number; @@ -41,7 +40,7 @@ declare module 'react-native-video' { // Some versions of react-native-video may not support this option. authToken?: string; - }; + } | number; resizeMode?: string; poster?: string; @@ -57,6 +56,7 @@ declare module 'react-native-video' { controls?: boolean; currentTime?: number; progressUpdateInterval?: number; + useTextureView?: boolean; onLoadStart?: () => void; onLoad?: (info: VideoInfo) => void; onBuffer?: (bufferInfo: VideoBufferInfo) => void; @@ -75,8 +75,10 @@ declare module 'react-native-video' { onAudioFocusChanged?: () => void; onAudioBecomingNoisy?: () => void; - style?: any + style?: any; } - export default class Video extends React.Component { } + export default class Video extends React.Component { + seek(position: number): void; + } } diff --git a/extensions/video/src/typings/react-native.d.ts b/extensions/video/src/typings/react-native.d.ts deleted file mode 100644 index f6587f177..000000000 --- a/extensions/video/src/typings/react-native.d.ts +++ /dev/null @@ -1,1091 +0,0 @@ -/** -* react-native.d.ts -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Type definition file for React Native, based on the React.js definition file -* on https://github.com/borisyankov/DefinitelyTyped. -*/ - -declare module 'react-native' { - // - // React - // ---------------------------------------------------------------------- - - import React = require('react'); - - // BT: Adding ProgressBarAndroid. It's not part of the DefinitelyTyped definitions. - class ProgressBarAndroid extends React.Component {} - - type ReactElement = React.ReactElement; - type ReactNode = React.ReactNode; - - function createElement

( - type: string, - props?: P, - ...children: React.ReactNode[]): React.ReactElement

; - - function cloneElement

( - element: P, - props ?: any - ): React.ReactElement

; - - interface SyntheticEvent extends React.SyntheticEvent {} - - function isValidElement(object: {}): boolean; - function findNodeHandle(componentOrHandle: any): number; - - var Children: React.ReactChildren; - - type PlatformString = 'android'|'ios'|'windows'; - var Platform: { - OS: PlatformString, - Version?: number - }; - - // - // Component base - // ---------------------------------------------------------------------- - - abstract class ReactNativeBaseComponent extends React.Component { - setNativeProps(nativeProps: P): void; - focus(): void; - blur(): void; - measure(callback: ((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void)): void; - measureLayout(relativeToNativeNode: number, onSuccess: ((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void), onFail: () => void): void; - refs: { - [key: string]: ReactNativeBaseComponent; - } - } - - // - // Style rules - // ---------------------------------------------------------------------- - - type StyleRuleSet = Object | Object[]; - - // - // Specific components - // ---------------------------------------------------------------------- - - interface ComponentPropsBase { - ref?: string | ((obj: ReactNativeBaseComponent) => void); - key?: string | number; - } - - interface ComponentPropsStyleBase extends ComponentPropsBase { - style?: StyleRuleSet | StyleRuleSet[]; - } - - interface ImageSource { - uri: string; - headers?: {[header: string]: string}; - } - - interface ImageProps extends ComponentPropsStyleBase { - onLayout?: Function; - resizeMode?: string; - resizeMethod?: string; // android only prop: 'auto' | 'resize' | 'scale' - source?: ImageSource | number; - testID?: string; - - // iOS - accessibilityLabel?: string; - shouldRasterizeIOS?: boolean; - accessible?: boolean; - capInsets?: Object; - defaultSource?: Object; - onError?: Function; - onLoad?: Function; - onLoadEnd?: (e: SyntheticEvent) => void; - onLoadStart?: Function; - onProgress?: Function; - - // Android - fadeDuration?: number; - } - - interface ActivityIndicatorProps extends ComponentPropsBase { - animating?: boolean; - color?: string; - onLayout?: Function; - size?: string; // enum { 'small', 'large' } - } - - interface TextProps extends ComponentPropsStyleBase { - importantForAccessibility?: string; // 'auto' | 'yes' | 'no' | 'no-hide-descendants'; - allowFontScaling?: boolean; - maxContentSizeMultiplier?: number; - children? : React.ReactNode; - numberOfLines? : number; - ellipsizeMode? : 'head' | 'middle' | 'tail' // There's also 'clip' but it is iOS only - onLayout? : Function; - onPress? : Function; - onLongPress? : Function; - selectable? : boolean; // only on android, windows - testID? : string; - - // iOS - suppressHighlighting?: boolean; - - // Android - textBreakStrategy?: 'highQuality' | 'simple'| 'balanced'; - elevation?: number; - } - - export interface PickerProps extends ComponentPropsStyleBase { - - /** - * Callback for when an item is selected. This is called with the - * following parameters: - * - itemValue: the value prop of the item that was selected - * - itemPosition: the index of the selected item in this picker - * @param itemValue - * @param itemPosition - */ - onValueChange?: ( itemValue: any, itemPosition: number ) => void - - /** - * Value matching value of one of the items. - * Can be a string or an integer. - */ - selectedValue?: any - - style?: StyleRuleSet | StyleRuleSet[] - - /** - * Used to locate this view in end-to-end tests. - */ - testId?: string - - ref?: string | ((obj: ReactNativeBaseComponent) => void); - } - - interface TouchableWithoutFeedbackProps extends ComponentPropsBase { - accessibilityComponentType? : string; //enum ( 'none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' ) - accessibilityTraits?: string | string[]; //enum( 'none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text', 'summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn' ) - accessible?: boolean; - importantForAccessibility? : string; //enum( 'auto', 'yes', 'no', 'no-hide-descendants' ) - delayLongPress?: number; - delayPressIn?: number; - delayPressOut?: number; - onLayout?: Function; - onLongPress?: Function; - onPress?: Function; - onPressIn?: Function; - onPressOut?: Function - } - - interface TouchableHighlightProps extends TouchableWithoutFeedbackProps, ComponentPropsStyleBase { - activeOpacity? : number; - children? : React.ReactNode; - onHideUnderlay?: Function; - onShowUnderlay?: Function; - underlayColor? : string; - } - - interface ResponderProps { - onMoveShouldSetResponder? : Function; - onResponderGrant? : Function; - onResponderMove? : Function; - onResponderReject? : Function; - onResponderRelease? : Function; - onResponderTerminate? : Function; - onResponderTerminationRequest? : Function; - onStartShouldSetResponder? : Function; - onStartShouldSetResponderCapture?: Function; - } - - interface ViewOnLayoutEvent { - nativeEvent: { - layout: { - x: number, - y: number, - width: number, - height: number - } - } - } - - type ViewLayerType = 'none' | 'software' | 'hardware'; - - interface CommonAccessibilityProps { - accessibilityLabel? : string; - accessible? : boolean; - onAcccessibilityTap? : Function; - - // android - accessibilityComponentType? : string; //enum ( 'none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' ) - accessibilityLiveRegion? : string; //enum ( 'none', 'polite', 'assertive' ) - importantForAccessibility? : string; //enum( 'auto', 'yes', 'no', 'no-hide-descendants' ) - - // iOS - accessibilityTraits?: string | string[]; //enum( 'none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text', 'summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn' ) - } - - interface ViewProps extends ComponentPropsBase, ResponderProps, ComponentPropsStyleBase, CommonAccessibilityProps { - children? : any; - onLayout? : ((ev: ViewOnLayoutEvent) => void); - onMagicTap? : Function; - pointerEvents? : string; //enum( 'box-none', 'none', 'box-only', 'auto' ); - removeClippedSubviews? : boolean; - testID? : string; - - // android - collapsable? : boolean; - needsOffscreenAlphaCompositing?: boolean; - renderToHardwareTextureAndroid?: boolean; - viewLayerTypeAndroid? : ViewLayerType; - elevation? : number; - - // iOS - onAccessibilityTapIOS?: Function; - shouldRasterizeIOS? : boolean; - } - - interface ScrollViewProps extends ViewProps { - children?: any; - - contentContainerStyle?: StyleRuleSet | StyleRuleSet[]; - horizontal?: boolean; - keyboardDismissMode?: 'none' | 'interactive' | 'on-drag'; - keyboardShouldPersistTaps?: 'always' | 'never' | 'handled'; - onScroll?: Function; - onScrollBeginDrag?: Function; - onScrollEndDrag?: Function; - onContentSizeChange?: (width: number, height: number) => void; - showsHorizontalScrollIndicator?: boolean; - showsVerticalScrollIndicator?: boolean; - removeClippedSubviews?: boolean; - - // iOS - automaticallyAdjustContentInsets?: boolean; - //contentInset?: EdgeInsetsPropType; - //contentOffset?: PointPropType; - bounces?: boolean; - bouncesZoom?: boolean; - alwaysBounceHorizontal?: boolean; - alwaysBounceVertical?: boolean; - centerContent?: boolean; - decelerationRate?: number; - directionalLockEnabled?: boolean; - canCancelContentTouches?: boolean; - maximumZoomScale?: number; - minimumZoomScale?: number; - onScrollAnimationEnd?: Function; - pagingEnabled?: boolean; - scrollEnabled?: boolean; - scrollEventThrottle?: number; - scrollsToTop?: boolean; - stickyHeaderIndices?: [number]; - snapToInterval?: number; - snapToAlignment?: string; // enum( 'start', 'center', 'end' ) - zoomScale?: number; - overScrollMode?: string; //enum( 'always', 'always-if-content-scrolls', 'never' ) - // iOS - scrollIndicatorInsets?: {top: number, left: number, bottom: number, right: number }; - } - - interface ListViewDataSourceCallback { - rowHasChanged: (r1: T, r2: T) => boolean; - } - - interface ListViewDataSource { - new (onAsset: ListViewDataSourceCallback): ListViewDataSource; - cloneWithRows(rowList: T[]): void; - } - - interface ListViewProps extends ScrollViewProps { - dataSource: Object; //PropTypes.instanceOf(ListViewDataSource).isRequired - renderSeparator?: Function; - renderRow: Function; - initialListSize?: number; - onEndReached?: (e: React.SyntheticEvent) => void; - onEndReachedThreshold?: number; - pageSize?: number; - renderFooter?: Function; - renderHeader?: Function; - renderSectionHeader?: Function; - renderScrollComponent: Function; - scrollRenderAheadDistance?: number; - onChangeVisibleRows?: Function; - removeClippedSubviews?: boolean; - } - - interface ModalProps extends ComponentPropsBase { - animationType?: string; // enum( 'none', 'slide', 'fade' ) - onDismiss?: Function; - transparent?: boolean; - onRequestClose: () => void; - } - - interface TextInputProps extends ComponentPropsStyleBase, CommonAccessibilityProps { - autoCapitalize?: string; // enum('none', 'sentences', 'words', 'characters') - autoCorrect?: boolean; - autoFocus?: boolean; - blurOnSubmit?: boolean; - defaultValue?: string; - editable?: boolean; - keyboardType?: string; // enum("default", 'numeric', 'email-address', "ascii-capable", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search') - multiline?: boolean; - onBlur?: ((e: React.FocusEvent) => void); - onKeyPress?: (e: SyntheticEvent) => void; - onChange?: Function; - onChangeText?: ((changedText: string) => void); - onSelectionChange?: ((selection: SyntheticEvent) => void); - onEndEditing?: Function; - onFocus?: ((e: React.FocusEvent) => void); - onLayout?: ((props: { x: number, y: number, width: number, height: number }) => void); - onSubmitEditing?: Function; - onScroll?: Function; - placeholder?: string; - placeholderTextColor?: string; - returnKeyType?: string; // enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') - secureTextEntry?: boolean; - testID?: string; - textAlign?: string; // enum('auto' | 'left' | 'right' | 'center' | 'justify') - allowFontScaling?: boolean; - maxContentSizeMultiplier?: number; - selection?: { start: number, end: number }; - - //iOS and android - selectionColor?: string; - - value: string; - //iOS - clearButtonMode?: string; // enum('never', 'while-editing', 'unless-editing', 'always') - clearTextOnFocus?: boolean; - enablesReturnKeyAutomatically?: boolean; - keyboardAppearance?: string; // enum ('default', 'light', 'dark') - maxLength?: number; - numberOfLines?: number; - selectTextOnFocus?: boolean; - selectionState?: any; // see DocumentSelectionState.js - spellCheck?: boolean; - //android - textAlignVertical?: string; // enum('top', 'center', 'bottom') - textAlignVerticalAndroid?: string; // enum('top', 'center', 'bottom') - textAlignAndroid?: string; - underlineColorAndroid?: string; - disableFullscreenUI?: boolean; - textBreakStrategy?: 'highQuality' | 'simple' | 'balanced'; - } - - interface TextInputState { - currentlyFocusedField(): number; - focusTextInput(textFieldID?: number): void; - blurTextInput(textFieldID?: number): void; - } - - interface WebViewProps extends ComponentPropsStyleBase { - automaticallyAdjustContentInsets?: boolean; - bounces?: boolean; - contentInset?: {top: number, left: number, bottom: number, right: number }; - injectedJavaScript?: string; - javaScriptEnabled?: boolean; - domStorageEnabled?: boolean; - onShouldStartLoadWithRequest?: Function; - onNavigationStateChange?: Function; - onLoad?: (e: SyntheticEvent) => void; - onLoadStart?: Function; - renderError?: Function; - onError?: Function; - renderLoading?: Function; - scalesPageToFit?: boolean; - scrollEnabled?: boolean; - startInLoadingState?: boolean; - source?: { uri: string; method?: string; headers?: Object; body?: string; } | { html: string; baseUrl?: string; }; - } - - interface DatePickerIOSProps extends ComponentPropsStyleBase { - date?: Date; - maximumDate?: Date; - minimumDate?: Date; - minuteInterval?: number; - mode?: string; - timeZoneOffsetInMinutes?: number; - - onDateChange?: (newDate: Date) => void; - } - - class DatePickerIOS extends ReactNativeBaseComponent { - } - - interface DatePickerAndroidProps extends ComponentPropsStyleBase { - date?: Date; - maxDate?: Date; - minDate?: Date; - - onDateChange?: (newDate: Date) => void; - } - - class DatePickerAndroid extends ReactNativeBaseComponent { - static open(options: { date: Date, maxDate: Date, minDate: Date }): Promise; - static dateSetAction: Function; - static dismissedAction: Function; - } - - interface TimePickerAndroidProps extends ComponentPropsStyleBase { - date?: Date; - maxDate?: Date; - minDate?: Date; - - onDateChange?: (newDate: Date) => void; - } - - class TimePickerAndroid extends ReactNativeBaseComponent { - static open(options: { hour: number, minute: number, is24Hour: boolean }): Promise; - static timeSetAction: Function; - static dismissedAction: Function; - } - - type DatePickerAction = { - action: Function; - day: number; - month: number; - year: number; - } - - type TimePickerAction = { - action: Function; - hour: number; - minute: number; - } - - class Image extends ReactNativeBaseComponent { - static prefetch(url: string): Promise; - } - class ActivityIndicator extends ReactNativeBaseComponent { } - class Text extends ReactNativeBaseComponent { } - class Picker extends ReactNativeBaseComponent { - static Item: any; - } - class TouchableHighlight extends ReactNativeBaseComponent { } - class TouchableWithoutFeedback extends ReactNativeBaseComponent { } - class View extends ReactNativeBaseComponent { } - class ScrollView extends ReactNativeBaseComponent { - getInnerViewNode(): number; - // TODO: Define ScrollResponder type - scrollTo(val: { x?: number; y?: number; animated?: boolean; }): void; - scrollBy(val: { deltaX?: number; deltaY?: number; animated?: boolean; }): void; - } - class ListView extends ReactNativeBaseComponent { - static DataSource: ListViewDataSource; - } - class Modal extends ReactNativeBaseComponent { } - class TextInput extends ReactNativeBaseComponent { - static State: TextInputState; - } - class WebView extends ReactNativeBaseComponent { - reload() : void; - goBack() : void; - goForward() : void; - } - - interface ActionSheetOptions { - options: string[]; - cancelButtonIndex?: number; - destructiveButtonIndex?: number; - title?: string; - message?: string; - } - - interface ShareActionSheetOptions { - message?: string; - url?: string; - subject?: string; - excludedActivityTypes?: string[]; - } - - class ActionSheetIOS { - static showActionSheetWithOptions(options: ActionSheetOptions, callback: (buttonIndex: number) => void): void; - static showShareActionSheetWithOptions(options: ShareActionSheetOptions, failureCallback: (error: string) => void, successCallback: (success: boolean, method: string) => void): void; - } - - class BackAndroid { - static addEventListener(eventName: string, callback: () => boolean): void; - static removeEventListener(eventName: string, callback: () => boolean): void; - } - - interface NavigatorIOSRoute { - component: any; - title: string; - passProps?: any; - backButtonTitle?: string; - backButtonIcon?: any; - leftButtonTitle?: string; - leftButtonIcon?: any; - onLeftButtonPress?: () => void; - rightButtonTitle?: string; - rightButtonIcon?: any; - onRightButtonPress?: () => void; - wrapperStyle?: any; - } - - interface NavigatorIOSProps extends ComponentPropsBase { - barTintColor?: string; - initialRoute: NavigatorIOSRoute; - itemWrapperStyle?: StyleRuleSet | StyleRuleSet[]; - navigationBarHidden?: boolean; - shadowHidden?: boolean; - style?:any; - tintColor?: string; - titleTextColor?: string; - translucent?: boolean; - interactivePopGestureEnabled?: boolean; - } - - class StatusBar { - // Native - static setHidden(hidden: boolean, animation?: string): void; //'none'|'fade'|'slide'; - - // iOS - static setBarStyle(barStyle: string, animated: boolean): void; //'default'|'light-content'; - static setNetworkActivityIndicatorVisible(value: boolean): void; - - // Android - static setBackgroundColor(color: string, animated?: boolean): void; - static setTranslucent(translucent: boolean): void; - } - - interface EventSubscription { - remove(): void; - } - - interface NavigatorIOSNavigationContext { - addListener(event: string, callback: (route: NavigatorIOSRoute) => void): EventSubscription; - } - - interface NavigatorIOSState { - observedTopOfStack: number; - requestedTopOfStack: number; - routeStack: NavigatorIOSRoute[]; - } - - class NavigatorIOS extends ReactNativeBaseComponent { - navigationContext: NavigatorIOSNavigationContext; - push(route: NavigatorIOSRoute): void; - pop(): void; - popN(n: number): void; - replace(route: NavigatorIOSRoute): void; - replacePrevious(route: NavigatorIOSRoute): void; - replacePreviousAndPop(route: NavigatorIOSRoute): void; - resetTo(route: NavigatorIOSRoute): void; - popToRoute(route: NavigatorIOSRoute): void; - popToTop(): void; - } - - // StyleSheet - class StyleSheet { - static create(obj: { [key: string]: any }): any; - static flatten: (s: StyleSheet) => { [key: string]: any }; - } - - class AppRegistry { - static registerComponent(appKey: string, getComponentFunc: Function): any; - } - - type CameraRollProps = { - /** - * The number of photos wanted in reverse order of the photo application - * (i.e. most recent first for SavedPhotos). - */ - first: number, - - /** - * A cursor that matches `page_info { end_cursor }` returned from a previous - * call to `getPhotos` - */ - after?: string, - - /** - * Specifies which group types to filter the results to. - */ - groupTypes?: string, // enum { 'Album', 'All', 'Event', 'Faces', 'Library', 'PhotoStream', 'SavedPhotos', // default }, - - /** - * Specifies filter on group names, like 'Recent Photos' or custom album - * titles. - */ - groupName?: string, - - /** - * Specifies filter on asset type - */ - assetType?: string; // enum { 'All', 'Videos', 'Photos', // default }, - - } - - type GetPhotosCallbackPropNode = { - node: { - type: string, - group_name: string, - image: { - uri: string, - height: number, - width: number, - isStored?: boolean, - }, - timestamp: number, - location?: { - latitude?: number, - longitude?: number, - altitude?: number, - heading?: number, - speed?: number, - } - } - } - - type GetPhotosCallbackProps = { - edges: GetPhotosCallbackPropNode[], - page_info: { - has_next_page: boolean, - start_cursor?: string, - end_cursor?: string, - } - } - - class Clipboard { - static setString(content: string): void; - static getString(): Promise; - } - - class CameraRoll { - static saveImageWithTag(tag: string, successCallback: Function, errorCallback: Function): void; - static getPhotos(params: CameraRollProps, callback: ((props: GetPhotosCallbackProps) => void), errorCallback: Function): void; - } - - class Linking { - static getInitialURL(): Promise; - static openURL(url: string): Promise; - static canOpenURL(url: string): Promise; - static addEventListener(type: string, handler: (event: any) => void): void; - static removeEventListener(type: string, handler: (event: any) => void): void; - } - - class AccessibilityInfo { - static fetch: () => Promise; - static addEventListener(type: string, handler: (event: any) => void): void; - static removeEventListener(type: string, handler: (event: any) => void): void; - static announceForAccessibility(announcement: string): void; - static setAccessibilityFocus(reactTag: number): void; - } - - interface AlertButtonSpec { - text?: string; - onPress?: () => void; - style?: string; // enum {default', 'cancel', 'destructive'} - } - - class Alert { - static alert( - title: string, - message?: string, - buttons?: AlertButtonSpec[], - type?: string // enum { 'default', 'plain-text', 'secure-text', 'login-password'} - ): void; - } - - class PushNotificationIOS { - static presentLocalNotification(details: { category: string, alertBody: string, soundName?: string}): void; - static scheduleLocalNotification(details: {alertBody: string, fireDate: Date}): void; - - static getApplicationIconBadgeNumber(callback: (badgeCount:number) => void): void; - static setApplicationIconBadgeNumber(number: number): void; - - static addEventListener(type: string, handler: (event: any) => void): void; - - static requestPermissions(permissions?: {alert?: boolean, badge?: boolean, sound?: boolean}): void; - static abandonPermissions(): void; - static checkPermissions(callback: (permissions: {alert: boolean, badge: boolean, sound: boolean}) => void): void; - - static getInitialNotification(): Promise; - - getMessage(): string; - getSound(): string; - getAlert(): any; - getBadgeCount(): number; - getData(): any; - } - - interface PanResponderGestureState { - stateID: number; - moveX: number; - moveY: number; - x0: number; - y0: number; - dx: number; - dy: number; - vx: number; - vy: number; - numberActiveTouches: number; - } - - interface ResponderSyntheticEvent extends React.SyntheticEvent { - touchHistory: Function; - } - - type PanResponderCreateConfig = { - onMoveShouldSetPanResponder?: (e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean, - onMoveShouldSetPanResponderCapture?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onStartShouldSetPanResponder?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onStartShouldSetPanResponderCapture?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderReject?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderGrant?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderStart?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderEnd?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderRelease?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderMove?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderTerminate?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onPanResponderTerminationRequest?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), - onShouldBlockNativeResponder?: ((e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void | boolean), // android only - onStartShouldSetResponderCapture?: (e: ResponderSyntheticEvent, gestureState: PanResponderGestureState) => void, - - } - - class PanResponder { - static create(config: PanResponderCreateConfig): PanResponder; - panHandlers: ResponderProps; - } - - type DimensionType = { - width: number, - height: number, - scale: number, - fontScale: number, - } - - class Dimensions { - static set(obj: any): boolean; - static get(key: string): DimensionType; - } - - type RCTAppStateData = { app_state: string } - type RCTAppState = { - getCurrentAppState(successCallback: (appStateData: RCTAppStateData) => void, failureCallback: () => void): void; - } - - type FileInput = { - selectImage: Function; - } - - type SnapshotOptions = { - width?: number; - height?: number; - format?: 'png' | 'jpeg'; - quality?: number; - } - - type UIManager = { - measure: Function; - measureInWindow: Function; - measureLayout: Function; - measureLayoutRelativeToParent: Function; - dispatchViewManagerCommand: Function; - - getMaxContentSizeMultiplier: Function; - setMaxContentSizeMultiplier: Function; - - // ios - takeSnapshot: (view: any, options?: SnapshotOptions) => Promise; - - // Android - sendAccessibilityEvent: Function; - } - - type AccessibilityManager = { - getMultiplier: Function; - announceForAccessibility (announcement: string): void; - } - - // We don't use this module, but need to be able to check its existance - type NativeAnimatedModule = { - - }; - - class ImagePickerManager { - showImagePicker: Function; - launchCamera: Function; - launchImageLibrary: Function; - } - - class NativeModules { - static AppState: RCTAppState; - static FileInput: FileInput; - static UIManager: UIManager; - static AccessibilityManager: AccessibilityManager; - static ImagePickerManager: ImagePickerManager; - static Networking: { - clearCookies(callback: (success: boolean) => void): void; - } - static ContextMenuAndroid: { - show(buttons: any, callback: (command: string) => void): void; - } - static NativeAnimation: NativeAnimatedModule; - } - - class AsyncStorage { - static getItem(key: string, callback: (error: any, result: string) => void): void; - static setItem(key: string, value: string, callback: (error: any) => void): void; - static removeItem(key: string, callback: (error: any) => void): void; - static clear(callback: (error: any) => void): void; - } - - class NetInfo { - static isConnected: { - addEventListener: (eventName: string, handler: (isConnected: boolean) => void) => void; - removeEventListener: (eventName: string, handler: (isConnected: boolean) => void) => void; - fetch: () => Promise; - } - static fetch(): Promise; - } - - class Easing { - static bezier(x1: number, y1: number, x2: number, y2: number): ((input: number) => number); - static linear(): ((input: number) => number); - } - - interface AnimationConfig { - isInteraction?: boolean; - useNativeDriver?: boolean; - } - - interface AnimatedTimingConfig extends AnimationConfig { - toValue: number; - duration?: number; - delay?: number - easing?: (input: number) => number; - } - - interface CompositeAnimation { - start(callback?: AnimatedEndCallback): void; - stop: () => void; - } - - type AnimatedEndResult = { finished: boolean }; - type AnimatedEndCallback = (result: AnimatedEndResult) => void; - - module Animated { - function createAnimatedComponent(Component: any, notCollapsable?: boolean): any; - function delay(time: number): CompositeAnimation; - function timing(value: Animated.Value, config: AnimatedTimingConfig): CompositeAnimation; - function parallel(animations: CompositeAnimation[]): CompositeAnimation - function sequence(animations: CompositeAnimation[]): CompositeAnimation - class Value { - constructor(val: number); - setValue(value: number): void; - addListener(callback: any): string; - removeListener(id: string): void; - removeAllListeners(): void; - interpolate(config: any): Value; - } - class View extends ReactNativeBaseComponent { } - class Image extends ReactNativeBaseComponent { } - class Text extends ReactNativeBaseComponent { } - } - - interface IUpdateLayoutAnimationConfig { - duration?: number; - delay?: number; - - springDamping?: number; - initialVelocity?: number; - - type?: string; - } - - interface ICreateLayoutAnimationConfig extends IUpdateLayoutAnimationConfig { - property?: string; - } - - interface ILayoutAnimationConfig { - duration: number; - create?: ICreateLayoutAnimationConfig; - update?: IUpdateLayoutAnimationConfig; - } - - module LayoutAnimation { - function configureNext(config: ILayoutAnimationConfig): void; - - module Types { - var spring: string; - var linear: string; - var easeInEaseOut: string; - var easeIn: string; - var easeOut: string; - var keyboard: string; - } - - module Properties { - var opacity: string; - var scaleXY: string; - } - } - - class DeviceEventSubscription { - remove(): void; - } - - class NativeAppEventEmitter { - static addListener(eventId: string, callback: Function): DeviceEventSubscription; - } - - module DeviceEventEmitter{ - function addListener(name: string, callback: Function): void; - } - - module AppState { - var currentState: string; - function addEventListener(type: string, handler: Function): void; - function removeEventListener(type: string, handler: Function): void; - } - - module AppStateIOS { - var currentState: string; - function addEventListener(type: string, handler: Function): void; - function removeEventListener(type: string, handler: Function): void; - } - - module Touchable { - type RectOffset = { - top: number, - left: number, - right: number, - bottom: number - } - - interface State { - touchable: any - } - - interface TouchableMixin extends React.Mixin { - touchableGetInitialState: () => State - touchableHandleStartShouldSetResponder: () => {} - touchableHandleResponderTerminationRequest: () => {} - touchableHandleResponderGrant: (e: React.SyntheticEvent, dispatchID: string) => {} - touchableHandleResponderMove: (e: React.SyntheticEvent) => {} - touchableHandleResponderRelease: (e: React.SyntheticEvent) => {} - touchableHandleResponderTerminate: (e: React.SyntheticEvent) => {} - touchableHandleActivePressIn?: (e: React.SyntheticEvent) => {} - touchableHandleActivePressOut?: (e: React.SyntheticEvent) => {} - touchableHandlePress?: (e: React.SyntheticEvent) => {} - touchableHandleLongPress?: (e: React.SyntheticEvent) => {} - touchableGetHighlightDelayMS?: () => number - touchableGetPressRectOffset?: () => RectOffset - } - - var Mixin: TouchableMixin; - } - - class EmitterSubscription { - remove(): void; - } - - module Keyboard { - function addListener(eventType: string, listener: Function, context?: any): EmitterSubscription; - function removeAllListeners(eventType: string): void; - function removeSubscription(subscription: EmitterSubscription): void; - } - - module PixelRatio { - /** - * Returns the device pixel density. Some examples: - * - * - PixelRatio.get() === 1 - * - mdpi Android devices (160 dpi) - * - PixelRatio.get() === 1.5 - * - hdpi Android devices (240 dpi) - * - PixelRatio.get() === 2 - * - iPhone 4, 4S - * - iPhone 5, 5c, 5s - * - iPhone 6 - * - xhdpi Android devices (320 dpi) - * - PixelRatio.get() === 3 - * - iPhone 6 plus - * - xxhdpi Android devices (480 dpi) - * - PixelRatio.get() === 3.5 - * - Nexus 6 - **/ - function get(): number; - - /** - * Returns the scaling factor for font sizes. This is the ratio that is used to calculate the - * absolute font size, so any elements that heavily depend on that should use this to do - * calculations. - * - * If a font scale is not set, this returns the device pixel ratio. - * - * Currently this is only implemented on Android and reflects the user preference set in - * Settings > Display > Font size, on iOS it will always return the default pixel ratio. - * @platform android - **/ - function getFontScale(): number; - - /** - * Converts a layout size (dp) to pixel size (px). - * - * Guaranteed to return an integer number. - **/ - function getPixelSizeForLayoutSize(layoutSize: number): number; - - /** - * Rounds a layout size (dp) to the nearest layout size that corresponds to - * an integer number of pixels. For example, on a device with a PixelRatio - * of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to - * exactly (8.33 * 3) = 25 pixels. - **/ - function roundToNearestPixel(layoutSize: number): number; - } - - interface IncrementalProps extends ComponentPropsStyleBase { - onDone?: () => void; - name: string; - children?: any; - } - - interface IncrementalPresenterProps extends ComponentPropsStyleBase { - name: string; - disabled?: boolean; - onDone?: () => void; - onLayout?: (event: Object) => void; - style?: any; - children?: any; - } - - class Incremental extends ReactNativeBaseComponent { - } - - class IncrementalGroup extends ReactNativeBaseComponent{ - } - - class IncrementalPresenter extends ReactNativeBaseComponent { - } - - module JSEventLoopWatchdog { - function install(obj: any): void; - } - - module InteractionManager { - function setDeadline(deadline: number): void; - } - - interface I18nManager { - isRTL: boolean - allowRTL: (allowRTL: boolean) => {} - forceRTL: (forceRTL: boolean) => {} - } - - export var I18nManager: I18nManager; -} - -interface GeoConfiguration { - skipPermissionRequests: boolean; -} - -interface Geolocation { - // React Native addition to navigator.geolocation - setRNConfiguration(config: GeoConfiguration): void; -} - diff --git a/extensions/video/src/web/PluginBase.ts b/extensions/video/src/web/PluginBase.ts index 1b20b52b0..9cf5aee40 100644 --- a/extensions/video/src/web/PluginBase.ts +++ b/extensions/video/src/web/PluginBase.ts @@ -6,7 +6,8 @@ * Base export for the Web implementation of the plugin. */ +import * as Types from '../common/Types'; + import Video from './Video'; -import Types = require('../common/Types'); export { Video as default, Types }; diff --git a/extensions/video/src/web/Video.tsx b/extensions/video/src/web/Video.tsx index 70d588c96..493151405 100644 --- a/extensions/video/src/web/Video.tsx +++ b/extensions/video/src/web/Video.tsx @@ -1,33 +1,35 @@ -/* -* Video.tsx -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT license. -* -* Web-specific implementation of the cross-platform Video abstraction. -*/ +/** + * Video.tsx + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT license. + * + * Web-specific implementation of the cross-platform Video abstraction. + */ + +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import * as RX from 'reactxp'; import extend = require('lodash/extend'); -import React = require('react'); -import RX = require('reactxp'); -import ReactDOM = require('react-dom'); -import Interfaces = require('../common/Interfaces'); -import Types = require('../common/Types'); +import * as Types from '../common/Types'; class Video extends RX.Component { componentDidMount() { // We need to manually install the onEnded handler because. React doesn't support this. - let videoDOM = ReactDOM.findDOMNode(this); - videoDOM.onended = () => { - if (this.props.onEnded) { - this.props.onEnded(); - } - }; + const videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement | null; + if (videoDOM) { + videoDOM.onended = () => { + if (this.props.onEnded) { + this.props.onEnded(); + } + }; + } } componentWillUnmount() { - let videoDOM = ReactDOM.findDOMNode(this); + const videoDOM = ReactDOM.findDOMNode(this) as HTMLVideoElement | null; if (videoDOM) { // Prevent Chrome based browsers to leak video elements videoDOM.src = ''; @@ -36,7 +38,7 @@ class Video extends RX.Component { render() { let combinedStyles = extend(RX.Styles.combine(this.props.style), { - display: 'flex' + display: 'flex', }); if (this.props.resizeMode === 'cover') { @@ -51,70 +53,75 @@ class Video extends RX.Component { WebkitTransform: 'translate(-50%,-50%)', MozTransform: 'translate(-50%,-50%)', msTransform: 'translate(-50%,-50%)', - transform: 'translate(-50%,-50%)' + transform: 'translate(-50%,-50%)', }); } else if (this.props.resizeMode === 'contain') { combinedStyles = extend(combinedStyles, { width: '100%', - height: '100%' + height: '100%', }); } else { combinedStyles = extend(combinedStyles, { width: 'auto', height: 'auto', maxWidth: '100%', - maxHeight: '100%' + maxHeight: '100%', }); } + // The HTML version of video doesn't support numeric-based source + // references, only string-based URIs. + const source = typeof this.props.source === 'string' ? this.props.source : ''; + return (