diff --git a/.ado/Get-ShellScaling.ps1 b/.ado/Get-ShellScaling.ps1
new file mode 100644
index 00000000000..5f1e6bc9b02
--- /dev/null
+++ b/.ado/Get-ShellScaling.ps1
@@ -0,0 +1,26 @@
+Add-Type @'
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Drawing;
+
+ public class DPI {
+ [DllImport("gdi32.dll")]
+ static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
+
+ public enum DeviceCap {
+ VERTRES = 10,
+ DESKTOPVERTRES = 117
+ }
+
+ public static float scaling() {
+ Graphics g = Graphics.FromHwnd(IntPtr.Zero);
+ IntPtr desktop = g.GetHdc();
+ int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
+ int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
+
+ return (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
+ }
+ }
+'@ -ReferencedAssemblies 'System.Drawing.dll'
+
+[Math]::round([DPI]::scaling(), 2) * 100
\ No newline at end of file
diff --git a/.ado/SetupLocalDumps.cmd b/.ado/SetupLocalDumps.cmd
new file mode 100644
index 00000000000..6afd36134dd
--- /dev/null
+++ b/.ado/SetupLocalDumps.cmd
@@ -0,0 +1,11 @@
+setlocal
+set CRASHDUMPS_FOLDER=%BUILD_ARTIFACTSTAGINGDIRECTORY%\ReactUWPTestAppTreeDump\CrashDumps
+reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /s
+reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\ReactUWPTestApp.exe" /v DumpFolder /t REG_SZ /d %CRASHDUMPS_FOLDER%
+reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\ReactUWPTestApp.exe" /v DumpType /t REG_DWORD /d 2
+if not exist %CRASHDUMPS_FOLDER% (
+ md %CRASHDUMPS_FOLDER%
+) else (
+ del %CRASHDUMPS_FOLDER%\* /s /q
+)
+endlocal
\ No newline at end of file
diff --git a/.ado/publish.yml b/.ado/publish.yml
index 5df81de516a..249427d156a 100644
--- a/.ado/publish.yml
+++ b/.ado/publish.yml
@@ -4,11 +4,17 @@ variables:
- template: variables/msbuild.yml
- template: variables/vs2019.yml
+schedules:
+- cron: "0 0 * * *"
+ displayName: Nightly publish build
+ branches:
+ include:
+ - master
+
trigger:
batch: true
branches:
include:
- - master
- "*-stable"
pr: none
diff --git a/.ado/templates/e2e-test-job.yml b/.ado/templates/e2e-test-job.yml
index e31b4037136..2dfe9f642a6 100644
--- a/.ado/templates/e2e-test-job.yml
+++ b/.ado/templates/e2e-test-job.yml
@@ -23,6 +23,12 @@ jobs:
- template: prepare-env.yml
+ - task: CmdLine@2
+ displayName: Set LocalDumps
+ inputs:
+ script: $(Build.SourcesDirectory)\.ado\SetupLocalDumps.cmd
+ workingDirectory: $(Build.SourcesDirectory)
+
- task: NuGetCommand@2
displayName: NuGet restore - ReactUWPTestApp
inputs:
@@ -34,7 +40,7 @@ jobs:
- task: CmdLine@2
displayName: run-windows
inputs:
- script: react-native run-windows --no-packager --arch ${{ parameters.BuildPlatform }} --release --logging --msbuildprops BaseIntDir=$(BaseIntDir)
+ script: yarn windows --no-packager --arch ${{ parameters.BuildPlatform }} --release --logging --msbuildprops BaseIntDir=$(BaseIntDir)
workingDirectory: packages/E2ETest
- task: PublishBuildArtifacts@1
@@ -74,6 +80,11 @@ jobs:
targetType: 'inline'
script: 'if ((Get-Process React*) -eq $Null) { echo "TestApp is not running"; exit 1}'
+ - task: CmdLine@2
+ displayName: mkdir errorShots
+ inputs:
+ script: mkdir $(Build.SourcesDirectory)\packages\E2ETest\errorShots
+
- task: CmdLine@2
displayName: run e2etest
inputs:
@@ -87,7 +98,28 @@ jobs:
targetFolder: $(Build.StagingDirectory)/ReactUWPTestAppTreeDump
contents: TreeDump\**
condition: succeededOrFailed()
-
+
+ - task: CopyFiles@2
+ displayName: Copy tree dump screenshots
+ inputs:
+ sourceFolder: $(Build.SourcesDirectory)\packages\E2ETest\errorShots
+ targetFolder: $(Build.StagingDirectory)/ReactUWPTestAppTreeDump
+ condition: succeededOrFailed()
+
+ - task: PowerShell@2
+ displayName: "MSInfo32"
+ inputs:
+ targetType: "inline"
+ script: "Start-Process msinfo32 -ArgumentList '/report $(Build.StagingDirectory)\\ReactUWPTestAppTreeDump\\msinfo32.txt' -Wait"
+ condition: failed()
+
+ - task: PowerShell@2
+ displayName: "Get-ShellScaling"
+ inputs:
+ targetType: "inline"
+ script: ". $(Build.SourcesDirectory)\\.ado\\Get-ShellScaling.ps1 > $(Build.StagingDirectory)\\ReactUWPTestAppTreeDump\\scaleFactor.txt"
+ condition: failed()
+
- task: PublishBuildArtifacts@1
displayName: "Publish Artifact:ReactUWPTestAppTreeDump"
inputs:
diff --git a/.ado/templates/react-native-init.yml b/.ado/templates/react-native-init.yml
index 500e00e3f74..d6a92173390 100644
--- a/.ado/templates/react-native-init.yml
+++ b/.ado/templates/react-native-init.yml
@@ -65,7 +65,7 @@ steps:
inputs:
artifactName: TestMSRNNuget.${{ parameters.platform }}.${{ parameters.configuration }}
downloadPath: $(System.DefaultWorkingDirectory)
- condition: eq('true', ${{ parameters.experimentalNugetDependency }})
+ condition: and(succeeded(), eq('true', ${{ parameters.experimentalNugetDependency }}))
- task: CmdLine@2
displayName: Init new project
@@ -84,14 +84,20 @@ steps:
inputs:
targetType: inline
script: |
- Install-Package Microsoft.ReactNative -Source $(System.DefaultWorkingDirectory)/TestMSRNNuget.${{ parameters.platform }}.${{ parameters.configuration }} -Destination $(Agent.BuildDirectory)\testcli\windows\packages
- condition: eq('true', ${{ parameters.experimentalNugetDependency }})
-
- - task: NuGetCommand@2
- displayName: NuGet restore testcli
- inputs:
- command: restore
- restoreSolution: $(Agent.BuildDirectory)\testcli\windows\testcli.sln
+ Install-Package Microsoft.ReactNative -Source $(System.DefaultWorkingDirectory)/TestMSRNNuget.${{ parameters.platform }}.${{ parameters.configuration }} -Destination $(Agent.BuildDirectory)\testcli\localNugets
+ $xml = [xml](gc $(Agent.BuildDirectory)\testcli\windows\Nuget.Config)
+ $newSource = $xml.CreateElement("add");
+ $keyAttr = $xml.CreateAttribute("key");
+ $keyAttr.Value ="PrPublish";
+ $valueAttr = $xml.CreateAttribute("value");
+ $valueAttr.Value ="$(Agent.BuildDirectory)\testcli\localNugets";
+ $newSource.Attributes.Append($keyAttr);
+ $newSource.Attributes.Append($valueAttr);
+ $packageSources = $xml.ChildNodes.Item(1).packageSources;
+ $packageSources.InsertBefore($newSource, $packageSources.FirstChild);
+ $xml.save("$(Agent.BuildDirectory)\testcli\windows\Nuget.Config");
+
+ condition: and(succeeded(), eq('true', ${{ parameters.experimentalNugetDependency }}))
- template: install-SDK.yml
parameters:
@@ -114,34 +120,26 @@ steps:
-Cleanup:$true
condition: and(succeeded(), ${{ parameters.installVsComponents }})
- - task: VSBuild@1
- displayName: VSBuild - testcli
+ # Work around issue of parameters not getting expanded in conditions properly
+ - powershell: |
+ Write-Host "##vso[task.setvariable variable=localConfig]${{ parameters.configuration}}"
+
+ - task: CmdLine@2
+ displayName: Build project (Release)
inputs:
- solution: $(Agent.BuildDirectory)\testcli\windows\testcli.sln
- vsVersion: $(MSBuildVersion) # Optional. Options: latest, 16.0, 15.0, 14.0, 12.0, 4.0
- msbuildArchitecture: $(MSBuildArchitecture) # Optional. Options: x86, x64
- platform: ${{ parameters.platform }} # Optional
- configuration: ${{ parameters.configuration }} # Optional
- clean: false # Optional
- maximumCpuCount: false # Optional
- restoreNugetPackages: false # Optional
- createLogFile: true
- logFileVerbosity: detailed
- msbuildArgs:
- /p:PreferredToolArchitecture=$(MSBuildPreferredToolArchitecture)
- /p:PlatformToolset=$(MSBuildPlatformToolset)
- /p:AppxGeneratePrisForPortableLibrariesEnabled=false
-
- - task: PublishBuildArtifacts@1
- condition: succeededOrFailed()
- timeoutInMinutes: 10
+ script: npx --no-install react-native run-windows --arch ${{ parameters.platform }} --no-launch --no-deploy --logging --release
+ workingDirectory: $(Agent.BuildDirectory)\testcli
+ condition: and(succeeded(), eq('Release', variables['localConfig']))
+
+ - task: CmdLine@2
+ displayName: Build project (Debug)
inputs:
- pathtoPublish: $(Agent.BuildDirectory)/testcli/windows/testcli.sln.log
- artifactName: Detailed Logs for testcli.sln ${{ parameters.platform }} ${{ parameters.configuration }} ${{ parameters.experimentalNugetDependency }}
- publishLocation: 'Container'
+ script: npx --no-install react-native run-windows --arch ${{ parameters.platform }} --no-launch --no-deploy --logging
+ workingDirectory: $(Agent.BuildDirectory)\testcli
+ condition: and(succeeded(), eq('Debug', variables['localConfig']))
- task: CmdLine@2
displayName: Create bundle testcli
inputs:
- script: react-native bundle --entry-file index.js platform windows --bundle-output test.bundle
+ script: npx --no-install react-native bundle --entry-file index.js --platform windows --bundle-output test.bundle
workingDirectory: $(Agent.BuildDirectory)\testcli
diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml
index b425c0dffbd..c38b149984a 100644
--- a/.ado/windows-vs-pr.yml
+++ b/.ado/windows-vs-pr.yml
@@ -11,7 +11,7 @@ variables:
- template: variables/msbuild.yml
- template: variables/vs2019.yml
- name: reactNativeVersion
- value: 0.61.5
+ value: 0.62.2
jobs:
- job: Setup
@@ -259,21 +259,21 @@ jobs:
- task: CmdLine@2
displayName: run-windows (Debug)
inputs:
- script: react-native run-windows --no-packager --no-launch --no-deploy --arch $(BuildPlatform) --logging --msbuildprops BaseIntDir=$(BaseIntDir)
+ script: yarn windows --no-packager --no-launch --no-deploy --arch $(BuildPlatform) --logging --msbuildprops BaseIntDir=$(BaseIntDir)
workingDirectory: packages/microsoft-reactnative-sampleapps
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Debug'))
- task: CmdLine@2
displayName: run-windows (Release)
inputs:
- script: react-native run-windows --no-packager --no-launch --no-deploy --arch $(BuildPlatform) --logging --release --msbuildprops BaseIntDir=$(BaseIntDir)
+ script: yarn windows --no-packager --no-launch --no-deploy --arch $(BuildPlatform) --logging --release --msbuildprops BaseIntDir=$(BaseIntDir)
workingDirectory: packages/microsoft-reactnative-sampleapps
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
- task: CmdLine@2
displayName: Create SampleApp bundle
inputs:
- script: node node_modules/react-native/local-cli/cli.js bundle --entry-file index.windows.js --bundle-output SampleApp.bundle
+ script: yarn bundle-cpp
workingDirectory: packages\microsoft-reactnative-sampleapps
condition: succeeded()
diff --git a/.gitignore b/.gitignore
index 2dfa77403f6..780d8dd9321 100644
--- a/.gitignore
+++ b/.gitignore
@@ -155,4 +155,5 @@ bld/
# OpenCover
*_coverage.xml
-tsdoc-metadata.json
\ No newline at end of file
+tsdoc-metadata.json
+*.dmp
diff --git a/README.md b/README.md
index 58325c7abdb..cbc480fc7b1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
React Native for Windows
+ React Native for Windows
Build native Windows apps with React.
@@ -18,84 +18,52 @@

-[React Native](https://reactnative.dev) enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and [React](https://reactjs.org/). The focus of React Native is on developer efficiency across all the platforms you care about - learn once, write anywhere. Facebook uses React Native in multiple production apps and will continue investing in React Native.
+> See the official [React Native website](https://reactnative.dev/) for an introduction to React Native.
+
+[React Native](https://reactnative.dev) is a framework developed by Facebook that enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and [React](https://reactjs.org/). The focus of React Native is on developer efficiency across all the platforms you care about - learn once, write anywhere.
This repository adds support for the [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads), which allows you to build apps for [all devices supported by Windows 10](https://developer.microsoft.com/en-us/windows/get-started-windows-10) including PCs, tablets, 2-in-1s, Xbox, Mixed reality devices etc.
## Status and roadmap
-
-We are in the process of re-implementing react-native-windows in C++, for better performance, and to better align with the shared C++ react-native core as it evolves. Please see the [Roadmap 2019](https://microsoft.github.io/react-native-windows/blog/2019/07/22/roadmap) blog for details on this effort and investment roadmap for the upcoming months.
-
-Please see the [July 2019 Updates Blog](https://microsoft.github.io/react-native-windows/blog/2019/07/21/updates) for all the latest updates!
-
-## Quick Links
-
-- [Getting Started](#getting-started)
-- [Getting Help](#getting-help)
-- [Documentation](#documentation)
-- [Examples](#examples)
-- [Extending React Native](#extending-react-native)
-- [Opening Issues](#opening-issues)
-- [Contributing](#contributing)
-- [License](#license)
-- [Code of Conduct](#code-of-conduct)
-
-## Introduction
-
-See the official [React Native website](https://reactnative.dev/) for an introduction to React Native.
+[Check out our blog](https://microsoft.github.io/react-native-windows/blog/) If you'd like to stay up to date on the status of React Native for Windows and check out current and past roadmaps, We will post all new releases, updates and general news about the project there.
## System Requirements
-- You can run React Native Windows UWP apps only on Windows 10 devices
- - React Native Windows currently supports Windows 10 SDK >= [15063](https://developer.microsoft.com/en-us/windows/downloads/sdk-archive). See [Windows 10 Compatibility](https://microsoft.github.io/react-native-windows/docs/win10-compat) for version support details.
-- Download [Visual Studio 2017 Community or Greater](https://www.visualstudio.com/downloads/). (Visual Studio 2015 support has been deprecated.)
- - You will need to start Visual Studio after it is installed to do some final setup before it can be used to build or run your React Native Windows application
+You can run React Native Windows UWP apps only on Windows 10 devices.
-*Note*: Development on React Native Windows itself currently requires Visual Studio 2017 or higher. It is not currently supported with VS Code, but work is ongoing as tracked [here](https://github.com/microsoft/vscode-react-native/issues/1007).
-
-## Getting Started
-
-Want to develop a React Native Windows app? Head over to our [Getting Started Guide](https://microsoft.github.io/react-native-windows/docs/getting-started).
-
-## Getting Help
-
-- Chat with us on [Reactiflux](https://discord.gg/0ZcbPKXt5bWJVmUY) in #react-native
-- If it turns out that you may have found a bug, please [open an issue](#opening-issues)
+For a full and detailed list of the system requirements and how to set up your development platform, see our [System Requirements](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies) documentation on our website.
## Documentation
+[React Native already has great documentation](https://reactnative.dev/docs/getting-started.html) and we're working to ensure the React Native Windows is part of that documentation story.
-[React Native already has great documentation](https://reactnative.dev/docs/getting-started.html), and we're working to ensure the React Native Windows is part of that documentation story. Check out the [React documentation](https://reactjs.org/docs/getting-started.html) for further details about the React API in general.
+[React Native for Windows](https://microsoft.github.io/react-native-windows/) has it's own separate documentation site where Windows and Mac specific information, like API docs and blog updates live.
-For information on parity status with Android and iOS, including details on implemented and missing components and modules, along with related issues for missing features from partial implementations, go [here](https://microsoft.github.io/react-native-windows/docs/parity-status).
+## Get Started
+See the [Getting Started Guide](https://microsoft.github.io/react-native-windows/docs/getting-started) on our React Native for Windows website.
-## Extending React Native
+## Need Help?
-- Looking for a component? [JS.coach](https://js.coach/react-native)
-- Fellow developers write and publish React Native modules to npm and open source them on GitHub.
-- Third party modules may be missing Windows support, so reach out to the project owners directly.
-- Making modules helps grow the React Native ecosystem and community. We recommend writing modules for your use cases and sharing them on npm.
-- You should almost never need to modify or fork React Native Windows itself (the ReactNative and ReactNative.Shared project/sources) to create custom controls. The extension points should already exist to do just about anything!
-- Read the guides on [Native Modules for Windows](https://microsoft.github.io/react-native-windows/docs/native-modules).
+Come join us and chat on the [Reactiflux](https://discord.gg/0ZcbPKXt5bWJVmUY) Discord server under in **#react-native**
-## Opening Issues
+If it turns out that you may have found a bug, we would like to hear about it!
-If you encounter a bug with the React Native Windows plugin, we would like to hear about it. Search the [existing issues](https://github.com/microsoft/react-native-windows/issues) and try to make sure your problem doesn’t already exist before opening a new issue. It’s helpful if you include the version of Windows, React Native, React Native Windows plugin, and device family (i.e., mobile, desktop, Xbox, etc.) you’re using. Please include a stack trace and reduced repro case when appropriate, too.
+### Logging Issues
+Search the [existing issues](https://github.com/microsoft/react-native-windows/issues) and try to make sure your problem doesn’t already exist before opening a new issue. If your issue doesn't exist yet, try to make sure you provide as much information as possible to us so we can help you sooner. It’s helpful if you include information like:
-Please use the [appropriate template](https://github.com/microsoft/react-native-windows/issues/new/choose) to file your issues.
+- The version of Windows, React Native, React Native Windows plugin, and device family (i.e., mobile, desktop, Xbox, etc.) where you ran into the issue.
+- A stack trace and reduced repro case when possible.
+- Ensure the [appropriate template](https://github.com/microsoft/react-native-windows/issues/new/choose) is used when filing your issue(s).
-The GitHub issues are intended for bug reports and feature requests. For help and questions with using the React Native Windows plugin please make use of the resources listed in the [Getting Help](#getting-help) section.
+The GitHub issues are intended for bug reports and feature requests. For help and questions with using the React Native Windows plugin please make use of the resources listed our main README's the [Getting Help](https://github.com/microsoft/react-native-windows#getting-help) section.
## Contributing
-
-Make sure to install the [system requirements](#system-requirements). If you just want to get started with developing your own app, read [Getting Started with App Development](#getting-started). You only need to interact with `npm` to use for your app development.
-
-For more information about contributing PRs, see [Contribution Guidelines for react-native-windows](docs/contributing.md)
+See [Contributing guidelines](./docs/contributing.md) for how to setup your fork of the repo and start a PR to contribute to React Native for Windows.
[Good First Task](https://github.com/microsoft/react-native-windows/labels/Good%20First%20Task) and [help wanted](https://github.com/microsoft/react-native-windows/labels/help%20wanted) are great starting points for PRs.
### Examples
-- Using the CLI in the [Getting Started](#getting-started) sections will set you up with a sample React-Native-Windows app that you can begin editing.
+- Using the CLI in the [Getting Started](https://microsoft.github.io/react-native-windows/docs/getting-started) guide will set you up with a sample React Native for Windows app that you can begin editing right away.
- If you're looking for sample code, just browse the RNTester folder in the GitHub web UI
## License
diff --git a/docs/api/react-native-windows.apptheme.md b/docs/api/react-native-windows.apptheme.md
index 60807d1aed2..43ffc937963 100644
--- a/docs/api/react-native-windows.apptheme.md
+++ b/docs/api/react-native-windows.apptheme.md
@@ -7,5 +7,5 @@
Signature:
```typescript
-AppTheme: AppThemeModule
+AppTheme: AppThemeModule | MissingNativeAppThemeShim
```
diff --git a/docs/e2e-testing.md b/docs/e2e-testing.md
index cd4612b2685..83407a939a9 100644
--- a/docs/e2e-testing.md
+++ b/docs/e2e-testing.md
@@ -18,7 +18,7 @@ E2E test app, test library and test cases are in packages/E2ETest/, and they are
# Run E2E test
-- Make sure you have installed [dependencies](./GettingStarted.md#dependencies)
+- Make sure you have installed [dependencies](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies)
## Procedures to setup and run E2E test
diff --git a/package.json b/package.json
index bb27e517de6..5974c76d111 100644
--- a/package.json
+++ b/package.json
@@ -15,11 +15,6 @@
"test": "lerna run test --stream -- --color",
"validate-overrides": "lerna run validate-overrides --stream -- --color"
},
- "husky": {
- "hooks": {
- "pre-commit": "yarn format"
- }
- },
"repository": {
"type": "git",
"url": "git@github.com:microsoft/react-native-windows.git"
@@ -33,7 +28,6 @@
},
"devDependencies": {
"beachball": "^1.13.4",
- "husky": "^3.0.9",
"lerna": "^3.16.1"
},
"resolutions": {
diff --git a/packages/E2ETest/app/ControlStyleTestPage.tsx b/packages/E2ETest/app/ControlStyleTestPage.tsx
index 62686dcf729..9e91fd263ba 100644
--- a/packages/E2ETest/app/ControlStyleTestPage.tsx
+++ b/packages/E2ETest/app/ControlStyleTestPage.tsx
@@ -3,7 +3,8 @@
* Licensed under the MIT License.
*/
-import { Switch, CheckBox, TextInput, View, StyleSheet, Button } from 'react-native';
+ // Bug:4596 Switch
+import { /* Switch, */ CheckBox, TextInput, View, StyleSheet, Button } from 'react-native';
import { DatePicker, Picker } from 'react-native-windows';
import React, { useState } from 'react';
import { SHOWBORDER_ON_CONTROLSTYLE, TREE_DUMP_RESULT } from './Consts';
@@ -56,7 +57,11 @@ export function ControlStyleTestPage() {
return (
-
+ {
+ /*
+ // Bug:4596 Switch
+
+ */}
{
- var previousState = passwordHidden;
- setPasswordHidden(!previousState);
- }
+ var previousState = passwordHidden;
+ setPasswordHidden(!previousState);
+ };
const onPress = () => {
if (userName === 'username' && password === 'password') {
@@ -49,29 +62,42 @@ export function LoginTestPage() {
};
return (
- { setUserName(text.nativeEvent.text) }} />
+ onChange={text => {
+ setUserName(text.nativeEvent.text);
+ }}
+ />
- { setPassword(text.nativeEvent.text) }} />
+ placeholderTextColor="rgba(225,225,225,0.7)"
+ secureTextEntry={passwordHidden}
+ onChange={text => {
+ setPassword(text.nativeEvent.text);
+ }}
+ />
- );
-}
\ No newline at end of file
+
+ );
+}
diff --git a/packages/E2ETest/app/TreeDumpControl.ts b/packages/E2ETest/app/TreeDumpControl.ts
index 9de23d1c93f..8a910e9d0e8 100644
--- a/packages/E2ETest/app/TreeDumpControl.ts
+++ b/packages/E2ETest/app/TreeDumpControl.ts
@@ -4,5 +4,11 @@
* Licensed under the MIT License.
*/
-import { requireNativeComponent } from 'react-native';
-export const TreeDumpControl = requireNativeComponent('TreeDumpControl');
+import { requireNativeComponent, ViewStyle } from 'react-native';
+export const TreeDumpControl = requireNativeComponent<{
+ style: ViewStyle;
+ dumpID: string;
+ uiaID: string;
+ testID: string;
+ additionalProperties?: string[];
+}>('TreeDumpControl');
diff --git a/packages/E2ETest/metro.config.js b/packages/E2ETest/metro.config.js
index fbeeed5942a..a5b5455186f 100644
--- a/packages/E2ETest/metro.config.js
+++ b/packages/E2ETest/metro.config.js
@@ -4,13 +4,9 @@
*
* @format
*/
-const fs = require('fs');
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
-const rnPath = fs.realpathSync(
- path.resolve(require.resolve('react-native/package.json'), '..')
-);
const rnwPath = path.resolve(__dirname, '../../vnext');
module.exports = {
@@ -23,35 +19,15 @@ module.exports = {
],
resolver: {
+ resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver(
+ { windows: 'react-native-windows' }
+ ),
extraNodeModules: {
// Redirect metro to rnwPath instead of node_modules/react-native-windows, since metro doesn't like symlinks
- 'react-native': rnwPath,
'react-native-windows': rnwPath,
},
- // Include the macos platform in addition to the defaults because the fork includes macos, but doesn't declare it
- platforms: ['ios', 'android', 'windesktop', 'windows', 'web', 'macos'],
- // Since there are multiple copies of react-native, we need to ensure that metro only sees one of them
- // This should go away after RN 0.60 when haste is removed
blacklistRE: blacklist([
new RegExp('.*E2ETest/msbuild.*'.replace(/[/\\]/g, '\\/')), // Avoid error EBUSY: resource busy or locked, open 'D:\a\1\s\packages\E2ETest\msbuild.ProjectImports.zip' in pipeline
- new RegExp(`${path.resolve(rnPath)}.*`.replace(/[/\\]/g, '/')),
- new RegExp(
- `${path.resolve(rnwPath, 'ReactCopies').replace(/[/\\]/g, '/')}.*`
- ),
- new RegExp(
- `${path
- .resolve(rnwPath, 'node_modules/react-native')
- .replace(/[/\\]/g, '/')}.*`
- ),
- new RegExp(
- `${path
- .resolve(
- require.resolve('@react-native-community/cli/package.json'),
- '../node_modules/react-native'
- )
- .replace(/[/\\]/g, '/')}.*`
- ),
-
// This stops "react-native run-windows" from causing the metro server to crash if its already running
new RegExp(
`${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`
@@ -59,6 +35,9 @@ module.exports = {
]),
},
transformer: {
+ // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above
+ // Hopefully we can fix the default in the future
+ assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
diff --git a/packages/E2ETest/package.json b/packages/E2ETest/package.json
index d61136dcf4c..f86695a3402 100644
--- a/packages/E2ETest/package.json
+++ b/packages/E2ETest/package.json
@@ -5,15 +5,15 @@
"scripts": {
"build": "just-scripts build",
"clean": "just-scripts clean",
- "postinstall": "node postinstall.js",
"start": "react-native start",
"lint": "just-scripts lint",
"lint:fix": "just-scripts lint:fix",
"watch": "tsc -w",
+ "windows": "react-native run-windows",
"prettier": "prettier --write --loglevel warn \"**/**/*.ts\"",
"e2e": "react-native run-windows --no-launch --logging && npm run e2etest",
"e2ebundle": "npm run bundle && react-native run-windows --no-launch --no-packager --bundle --logging && npm run e2etest",
- "e2etest": "rimraf reports/* && npm run prettier && wdio",
+ "e2etest": "rimraf reports/* && npm run prettier && node run_wdio.js",
"testspec": "npm run prettier && wdio --spec",
"bundle": "just-scripts prepareBundle && react-native bundle --platform windows --entry-file dist/app/index.js --bundle-output windows/ReactUWPTestApp/Bundle/index.windows.bundle --assets-dest windows/ReactUWPTestApp/Bundle",
"buildapp": "react-native run-windows --no-launch --no-packager --no-deploy",
@@ -22,9 +22,10 @@
"deploybundleapp": "react-native run-windows --no-launch --no-packager --no-build --bundle"
},
"dependencies": {
+ "prompt-sync": "^4.2.0",
"react": "16.9.0",
- "react-native": "0.61.5",
- "react-native-windows": "0.0.0-master.31",
+ "react-native": "0.62.2",
+ "react-native-windows": "0.0.0-master.44",
"rnpm-plugin-windows": "^0.6.1"
},
"devDependencies": {
@@ -33,7 +34,7 @@
"@types/jasmine": "2.8.7",
"@types/node": "^10.14.8",
"@types/react": "16.9.0",
- "@types/react-native": "~0.61.5",
+ "@types/react-native": "^0.62.2",
"@wdio/appium-service": "5.12.1",
"@wdio/cli": "5.12.1",
"@wdio/dot-reporter": "5.12.1",
diff --git a/packages/E2ETest/postinstall.js b/packages/E2ETest/postinstall.js
deleted file mode 100644
index ea656da5b18..00000000000
--- a/packages/E2ETest/postinstall.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * The react-native cli getPlugins assumes that all the react-native platform packages
- * are located in node_modules.
- *
- * When in a yarn workspace, the react-native platforms can be hoisted, so we need to
- * add a link to the real location so that getPlugins works correctly.
- *
- * @format
- *
- */
-// @ts-check
-
-const fs = require('fs');
-const path = require('path');
-const os = require('os');
-
-const checkOrCreate_node_modules = () => {
- const p = path.join(__dirname, 'node_modules');
-
- if (!fs.existsSync(p)) {
- fs.mkdirSync(p);
- }
-};
-checkOrCreate_node_modules();
-
-const link = (name, target) => {
- const p = path.join(__dirname, 'node_modules', name);
-
- if (!fs.existsSync(p)) {
- fs.symlinkSync(target, p, os.platform() === 'win32' ? 'junction' : 'dir');
- }
-};
-
-link('react-native-windows', path.resolve(__dirname, '../../vnext'));
-link(
- 'react-native',
- path.resolve(require.resolve('react-native/package.json'), '..'),
-);
-link(
- 'rnpm-plugin-windows',
- path.resolve(require.resolve('rnpm-plugin-windows/package.json'), '..'),
-);
diff --git a/packages/E2ETest/run_wdio.js b/packages/E2ETest/run_wdio.js
new file mode 100644
index 00000000000..56a33f269f5
--- /dev/null
+++ b/packages/E2ETest/run_wdio.js
@@ -0,0 +1,119 @@
+const path = require('path');
+const fs = require('fs');
+const xml2js = require('xml2js');
+const parser = new xml2js.Parser({ attrkey: 'ATTR' });
+const child_process = require('child_process');
+const prompt = require('prompt-sync')();
+
+const specFolder = 'wdio/test';
+
+function GetMetadata(specPath) {
+ const contents = fs.readFileSync(specPath);
+ const metadataTag = '// @metadata ';
+ const metadataStart = contents.indexOf(metadataTag);
+ if (metadataStart != -1) {
+ let metadata = contents
+ .toString()
+ .substr(metadataStart + metadataTag.length)
+ .split(/[\r\n]/)[0];
+ return metadata.split(' ');
+ }
+ return [];
+}
+
+const filters = {
+ SkipCI: specPath => {
+ return process.env.BUILD_QUEUEDBY == 'GitHub';
+ },
+};
+
+// Returns true if the spec is to run.
+// Specs marked SkipCI are excluded from CI (identified by environment variables in the ADO lab)
+function FilterSpec(specPath) {
+ const metadata = GetMetadata(specPath);
+ for (let i = 0; i < metadata.length; i++) {
+ if (filters[metadata[i]](specPath)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function SelectSpecs(folder) {
+ let specs = [];
+ if (process.argv.length > 2) {
+ specs = process.argv.splice(2).map(spec => spec + '.spec.ts');
+ } else {
+ specs = fs.readdirSync(folder).filter(x => x.endsWith('.spec.ts'));
+ }
+ specs = specs.map(spec => path.join(folder, spec)).filter(FilterSpec);
+ return specs;
+}
+
+let opts = SelectSpecs(specFolder);
+console.log(`Selected tests: ${opts}`);
+
+function OverrideHyperV() {
+ const baseboardMfr = child_process
+ .execSync('powershell.exe (gwmi Win32_BaseBoard).Manufacturer')
+ .toString()
+ .replace(/[\r\n]/, '');
+ if (!baseboardMfr.startsWith('Microsoft Corporation')) {
+ console.log(`Not running in HyperV. Mfr = ${baseboardMfr}`);
+ const answer = prompt(
+ 'E2ETest is meant to be run in a HyperV VM. Continue? (Y/N)'
+ );
+ if (answer.toUpperCase() != 'Y') {
+ process.exit(0);
+ }
+ }
+}
+
+OverrideHyperV();
+
+const Launcher = require('@wdio/cli').default;
+
+const wdio = new Launcher('wdio.conf.js', { specs: opts });
+
+function parseLog(logfile) {
+ const xmlString = fs.readFileSync(logfile);
+ let name;
+ parser.parseString(xmlString, (err, res) => {
+ if (!res.testsuites) {
+ name = 'something went wrong';
+ } else {
+ const attr = res.testsuites.testsuite[0].ATTR;
+ if (attr.errors > 0 || attr.failures > 0) {
+ name = attr.name;
+ }
+ }
+ });
+ return name;
+}
+
+function parseLogs() {
+ const reportsDir = path.join(__dirname, 'reports');
+ const logs = fs.readdirSync(reportsDir).filter(x => x.endsWith('.log'));
+ const names = logs
+ .map(x => parseLog(path.join(reportsDir, x)))
+ .filter(x => x != null);
+ return names;
+}
+
+function Process(code) {
+ const failedTests = parseLogs();
+ for (let i = 0; i < failedTests.length; i++) {
+ console.log(`Failed test: ${failedTests[i]}`);
+ }
+ process.exit(code);
+}
+
+wdio.run().then(
+ code => {
+ Process(code);
+ },
+ error => {
+ console.error('Launcher failed to start the test', error.stacktrace);
+ process.exit(1);
+ }
+);
diff --git a/packages/E2ETest/wdio/test/DirectManipulation.spec.ts b/packages/E2ETest/wdio/test/DirectManipulation.spec.ts
index bc609af6a41..6e97bb96599 100644
--- a/packages/E2ETest/wdio/test/DirectManipulation.spec.ts
+++ b/packages/E2ETest/wdio/test/DirectManipulation.spec.ts
@@ -28,6 +28,9 @@ describe('DirectManipulationTest', () => {
result.includes('width=50'),
'measureLayout response has correct width'
);
- assert.ok(result.includes('x=20;'), 'measureLayout response x=20');
+ // https://github.com/microsoft/react-native-windows/issues/4122
+ // Un-comment this when bug 4122 is fixed
+ // E2ETEST_OVERRIDE_4122
+ // assert.ok(result.includes('x=20;'), 'measureLayout response x=20');
});
});
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/App.xaml b/packages/E2ETest/windows/ReactUWPTestApp/App.xaml
index d261251013c..01838c5e2f0 100644
--- a/packages/E2ETest/windows/ReactUWPTestApp/App.xaml
+++ b/packages/E2ETest/windows/ReactUWPTestApp/App.xaml
@@ -5,6 +5,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ReactUWPTestApp">
-
+
+
+
+
+ #409efe
+
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs b/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs
index 65eb5c0a005..0a6a8c61fd0 100644
--- a/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs
+++ b/packages/E2ETest/windows/ReactUWPTestApp/App.xaml.cs
@@ -1,16 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+using Microsoft.ReactNative;
using System;
-using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Navigation;
-using Microsoft.ReactNative;
+using Windows.Foundation;
+using Windows.Graphics.Display;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
-using Windows.Foundation;
namespace ReactUWPTestApp
{
@@ -59,6 +56,16 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
base.OnLaunched(e);
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
ApplicationView.GetForCurrentView().TryResizeView(new Size(800, 600));
+#if !E2ETEST_OVERRIDE_4122
+#error [E2ETest] - There is a bug in Yoga with v142/VS2019 that makes the masters for this app different in Release|x64 than in other platforms.
+#error However we want to test what people will be shipping. As a result, the tree dump output won't match the masters (which have the bug).
+#error You can disable this warning by defining the constant E2ETEST_OVERRIDE_4122 in the project properties page under "Define Constants"
+#error For more information see https://github.com/microsoft/react-native-windows/issues/4122
+#endif
+ if (DisplayInformation.GetForCurrentView().ResolutionScale != ResolutionScale.Scale100Percent)
+ {
+ throw new Exception("A bug requires this app to run at 100% for accurate results - See https://github.com/microsoft/react-native-windows/issues/4619");
+ }
}
}
}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ControlStyleRegularBorder.txt b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ControlStyleRegularBorder.txt
deleted file mode 100644
index 0a979e07969..00000000000
--- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ControlStyleRegularBorder.txt
+++ /dev/null
@@ -1,851 +0,0 @@
-[Microsoft.ReactNative.ViewPanel]
- Background=[NULL]
- BorderBrush=#00000000
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=360
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=800,360
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.ToggleSwitch]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=51,50
- VerticalAlignment=Center
- Visibility=Visible
- Width=51
- [Windows.UI.Xaml.Controls.Grid]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=51,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=154,32
- VerticalAlignment=Top
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,5,0,5
- Padding=0,0,0,0
- RenderSize=52,22
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- Height=20
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=40,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=40
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- Height=20
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=40,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=40
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=20
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=20
- [Windows.UI.Xaml.Shapes.Ellipse]
- Clip=[NULL]
- Height=10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=10,10
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=10
- [Windows.UI.Xaml.Shapes.Ellipse]
- Clip=[NULL]
- Height=10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=10,10
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=10
- [Windows.UI.Xaml.Controls.Primitives.Thumb]
- Background=#33000000
- BorderBrush=#00FFFFFF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=52,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=52,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.CheckBox]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=8,5,0,0
- RenderSize=120,50
- VerticalAlignment=Center
- Visibility=Visible
- Width=32
- [Windows.UI.Xaml.Controls.Grid]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=120,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=32
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,32
- VerticalAlignment=Top
- Visibility=Visible
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- Height=20
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=20,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=20
- [Windows.UI.Xaml.Controls.FontIcon]
- Clip=[NULL]
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=20,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00000000
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,16
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=8,5,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Top
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBox]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- Height=50
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=10,10,10,10
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollViewer]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=1,1,1,1
- Padding=10,10,10,10
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=[NULL]
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=Windows.UI.Xaml.Media.RectangleGeometry
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=0,0,0,0
- RenderSize=778,28
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.FrameworkElement]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=778,28
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Right
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Border]
- Background=#FFE6E6E6
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#B3E1E1E1
- HorizontalAlignment=Stretch
- Margin=1,1,1,1
- Padding=10,10,10,10
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Button]
- Background=#33000000
- BorderBrush=#00FFFFFF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,-2,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.PasswordBox]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- Height=50
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=10,10,10,10
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollViewer]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=1,1,1,1
- Padding=10,10,10,10
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=[NULL]
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=Windows.UI.Xaml.Media.RectangleGeometry
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=0,0,0,0
- RenderSize=778,28
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.FrameworkElement]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=778,28
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Right
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Border]
- Background=#FFE6E6E6
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=1,1,1,1
- Padding=10,10,10,10
- RenderSize=798,48
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.ToggleButton]
- Background=#33000000
- BorderBrush=#00FFFFFF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,-2,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.CalendarDatePicker]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,50
- VerticalAlignment=Center
- Visibility=Visible
- Width=150
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#99000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=12,0,0,2
- RenderSize=90,21
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.FontIcon]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Center
- Margin=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00000000
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ComboBox]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=12,5,0,7
- RenderSize=800,50
- VerticalAlignment=Top
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33E1E1E1
- BorderBrush=#55FF00FF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#FF0078D7
- BorderBrush=#66000000
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=12,5,0,7
- Padding=0,0,0,0
- RenderSize=756,19
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=756,19
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBox]
- Background=#66FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=11,5,32,6
- RenderSize=0,0
- VerticalAlignment=Center
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Border]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Right
- Margin=0,1,1,1
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- Width=30
- [Windows.UI.Xaml.Controls.FontIcon]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Right
- Margin=0,0,10,0
- RenderSize=12,32
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00000000
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.Popup]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=768,0
- VerticalAlignment=Stretch
- Visibility=Visible
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ControlStyleRoundBorder.txt b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ControlStyleRoundBorder.txt
deleted file mode 100644
index d498431e020..00000000000
--- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ControlStyleRoundBorder.txt
+++ /dev/null
@@ -1,851 +0,0 @@
-[Microsoft.ReactNative.ViewPanel]
- Background=[NULL]
- BorderBrush=#00000000
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=360
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=800,360
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.ToggleSwitch]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=51,50
- VerticalAlignment=Center
- Visibility=Visible
- Width=51
- [Windows.UI.Xaml.Controls.Grid]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=51,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=154,32
- VerticalAlignment=Top
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,5,0,5
- Padding=0,0,0,0
- RenderSize=52,22
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- Height=20
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=40,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=40
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- Height=20
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=40,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=40
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=20
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=20
- [Windows.UI.Xaml.Shapes.Ellipse]
- Clip=[NULL]
- Height=10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=10,10
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=10
- [Windows.UI.Xaml.Shapes.Ellipse]
- Clip=[NULL]
- Height=10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=10,10
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=10
- [Windows.UI.Xaml.Controls.Primitives.Thumb]
- Background=#33000000
- BorderBrush=#00FFFFFF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=52,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=52,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.CheckBox]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=8,5,0,0
- RenderSize=120,50
- VerticalAlignment=Center
- Visibility=Visible
- Width=40
- [Windows.UI.Xaml.Controls.Grid]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=120,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=32
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,32
- VerticalAlignment=Top
- Visibility=Visible
- [Windows.UI.Xaml.Shapes.Rectangle]
- Clip=[NULL]
- Height=20
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=20,20
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=20
- [Windows.UI.Xaml.Controls.FontIcon]
- Clip=[NULL]
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=20,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00000000
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#FFFFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=20,16
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=8,5,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Top
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBox]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- Height=50
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=10,10,10,10
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollViewer]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=10,10,10,10
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=[NULL]
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=Windows.UI.Xaml.Media.RectangleGeometry
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=0,0,0,0
- RenderSize=760,10
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.FrameworkElement]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=760,10
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Right
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Border]
- Background=#FFE6E6E6
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#B3E1E1E1
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=10,10,10,10
- RenderSize=780,39
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Button]
- Background=#33000000
- BorderBrush=#00FFFFFF
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=0,10,10,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,-2,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.PasswordBox]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- Height=50
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=10,10,10,10
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollViewer]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=10,10,10,10
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=[NULL]
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ScrollContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=Windows.UI.Xaml.Media.RectangleGeometry
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=0,0,0,0
- RenderSize=760,10
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.FrameworkElement]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=760,10
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=780,30
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Right
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Primitives.ScrollBar]
- Background=#00FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=2,2,2,2
- Foreground=#00FFFFFF
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Border]
- Background=#FFE6E6E6
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=10,10,10,10
- Padding=10,10,10,10
- RenderSize=780,39
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.ToggleButton]
- Background=#33000000
- BorderBrush=#00FFFFFF
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=0,10,10,0
- Foreground=#FF000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,-2,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.CalendarDatePicker]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,50
- VerticalAlignment=Center
- Visibility=Visible
- Width=150
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#99000000
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=12,0,0,2
- RenderSize=90,21
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.FontIcon]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Center
- Margin=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00000000
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=150,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ComboBox]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- Height=50
- HorizontalAlignment=Left
- Margin=0,0,0,0
- Padding=12,5,0,7
- RenderSize=800,50
- VerticalAlignment=Top
- Visibility=Visible
- Width=800
- [Windows.UI.Xaml.Controls.Grid]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#33000000
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Border]
- Background=#FF0078D7
- BorderBrush=#66000000
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,50
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=12,5,0,7
- Padding=0,0,0,0
- RenderSize=756,19
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=756,19
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBox]
- Background=#66FFFFFF
- BorderBrush=#00FFFFFF
- BorderThickness=1,1,1,1
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Foreground=#FF000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=11,5,32,6
- RenderSize=0,0
- VerticalAlignment=Center
- Visibility=Collapsed
- [Windows.UI.Xaml.Controls.Border]
- Background=#00FFFFFF
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Right
- Margin=0,1,1,1
- Padding=0,0,0,0
- RenderSize=0,0
- VerticalAlignment=Stretch
- Visibility=Collapsed
- Width=30
- [Windows.UI.Xaml.Controls.FontIcon]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Right
- Margin=0,0,10,0
- RenderSize=12,32
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Grid]
- Background=#00000000
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,32
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.TextBlock]
- Clip=[NULL]
- Foreground=#CC000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=12,12
- VerticalAlignment=Center
- Visibility=Visible
- [Windows.UI.Xaml.Controls.ContentPresenter]
- Background=[NULL]
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Foreground=#99000000
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=800,0
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.Controls.Primitives.Popup]
- Clip=[NULL]
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=768,0
- VerticalAlignment=Stretch
- Visibility=Visible
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageRTL.txt b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageRTL.txt
deleted file mode 100644
index f90ce43e291..00000000000
--- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageRTL.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-[Windows.UI.Xaml.Controls.Border]
- Background=#FFFFFF00
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- FlowDirection=LeftToRight
- Height=300
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=500,300
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=500
- [Microsoft.ReactNative.ViewPanel]
- Background=[NULL]
- BorderBrush=#00000000
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- FlowDirection=LeftToRight
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=500,300
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.DependencyObject]
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithBorder.txt b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithBorder.txt
deleted file mode 100644
index a9a9072b5b9..00000000000
--- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithBorder.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-[Windows.UI.Xaml.Controls.Border]
- Background=#FFFFFF00
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- Height=300
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=500,300
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=500
- [Microsoft.ReactNative.ViewPanel]
- Background=[NULL]
- BorderBrush=#5500FF00
- BorderThickness=10,10,10,10
- Clip=[NULL]
- CornerRadius=10,10,10,10
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=480,280
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.DependencyObject]
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithoutBorder-Subsequent.txt b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithoutBorder-Subsequent.txt
deleted file mode 100644
index 39971f8b2c1..00000000000
--- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithoutBorder-Subsequent.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-[Windows.UI.Xaml.Controls.Border]
- Background=#FFFFFF00
- BorderBrush=[NULL]
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=300
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- Padding=0,0,0,0
- RenderSize=500,300
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=500
- [Microsoft.ReactNative.ViewPanel]
- Background=[NULL]
- BorderBrush=#00000000
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=500,300
- VerticalAlignment=Stretch
- Visibility=Visible
- [Windows.UI.Xaml.DependencyObject]
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithoutBorder.txt b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithoutBorder.txt
deleted file mode 100644
index 55c2c907c00..00000000000
--- a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/ImageWithoutBorder.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-[Microsoft.ReactNative.ViewPanel]
- Background=#FFFFFF00
- BorderBrush=#00000000
- BorderThickness=0,0,0,0
- Clip=[NULL]
- CornerRadius=0,0,0,0
- Height=300
- HorizontalAlignment=Stretch
- Margin=0,0,0,0
- RenderSize=500,300
- VerticalAlignment=Stretch
- Visibility=Visible
- Width=500
- [Windows.UI.Xaml.DependencyObject]
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json
new file mode 100644
index 00000000000..818fa573d29
--- /dev/null
+++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRegularBorder.json
@@ -0,0 +1,977 @@
+{
+ "XamlType": "Microsoft.ReactNative.ViewPanel",
+ "Background": null,
+ "BorderBrush": "#00000000",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 300,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [800, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.CheckBox",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "Height": 50,
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Padding": "8,5,0,0",
+ "RenderSize": [120, 50],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "Width": 32,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "RootGrid",
+ "Padding": "0,0,0,0",
+ "RenderSize": [120, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 32,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [20, 32],
+ "VerticalAlignment": "Top",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Shapes.Rectangle",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Height": 20,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "NormalRectangle",
+ "RenderSize": [20, 20],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 20
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.FontIcon",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "CheckGlyph",
+ "RenderSize": [20, 32],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00000000",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [20, 32],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [20, 16],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "8,5,0,0",
+ "Name": "ContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Top",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBox",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "Height": 50,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "10,10,10,10",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "BorderElement",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollViewer",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "1,1,1,1",
+ "Name": "ContentElement",
+ "Padding": "10,10,10,10",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": null,
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Root",
+ "Padding": "0,0,0,0",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00FFFFFF",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": "Windows.UI.Xaml.Media.RectangleGeometry",
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "ScrollContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [778, 28],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.FrameworkElement",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [778, 28],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,0,0,0",
+ "Name": "VerticalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "HorizontalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFE6E6E6",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "ScrollBarSeparator",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#B3E1E1E1",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "1,1,1,1",
+ "Name": "PlaceholderTextContentPresenter",
+ "Padding": "10,10,10,10",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Button",
+ "Background": "#33000000",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Name": "DeleteButton",
+ "Padding": "0,0,-2,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.PasswordBox",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "Height": 50,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "10,10,10,10",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "BorderElement",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollViewer",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "1,1,1,1",
+ "Name": "ContentElement",
+ "Padding": "10,10,10,10",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": null,
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Root",
+ "Padding": "0,0,0,0",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00FFFFFF",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": "Windows.UI.Xaml.Media.RectangleGeometry",
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "ScrollContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [778, 28],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.FrameworkElement",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [778, 28],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,0,0,0",
+ "Name": "VerticalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "HorizontalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFE6E6E6",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "ScrollBarSeparator",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#B3E1E1E1",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "1,1,1,1",
+ "Name": "PlaceholderTextContentPresenter",
+ "Padding": "10,10,10,10",
+ "RenderSize": [798, 48],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ToggleButton",
+ "Background": "#33000000",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Name": "RevealButton",
+ "Padding": "0,0,-2,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.CalendarDatePicker",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "Height": 50,
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 50],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "Width": 150,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Root",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Background",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Name": "DateText",
+ "Padding": "12,0,0,2",
+ "RenderSize": [90, 21],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.FontIcon",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Center",
+ "Margin": "0,0,0,0",
+ "Name": "CalendarGlyph",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00000000",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ComboBox",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "Height": 50,
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Padding": "12,5,0,7",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Top",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "LayoutRoot",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33E1E1E1",
+ "BorderBrush": "#55FF00FF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Background",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FF409EFE",
+ "BorderBrush": "#66000000",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "HighlightBackground",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "12,5,0,7",
+ "Name": "ContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [756, 19],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "PlaceholderTextBlock",
+ "Padding": "0,0,0,0",
+ "RenderSize": [756, 19],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBox",
+ "Background": "#66FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "EditableText",
+ "Padding": "11,5,32,6",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Center",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#00FFFFFF",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,1,1,1",
+ "Name": "DropDownOverlay",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed",
+ "Width": 30
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.FontIcon",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,0,10,0",
+ "Name": "DropDownGlyph",
+ "RenderSize": [12, 32],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00000000",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 32],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.Popup",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Popup",
+ "RenderSize": [768, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json
new file mode 100644
index 00000000000..3e26498c954
--- /dev/null
+++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ControlStyleRoundBorder.json
@@ -0,0 +1,977 @@
+{
+ "XamlType": "Microsoft.ReactNative.ViewPanel",
+ "Background": null,
+ "BorderBrush": "#00000000",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 300,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [800, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.CheckBox",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "Height": 50,
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Padding": "8,5,0,0",
+ "RenderSize": [120, 50],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "Width": 40,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "RootGrid",
+ "Padding": "0,0,0,0",
+ "RenderSize": [120, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 32,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [20, 32],
+ "VerticalAlignment": "Top",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Shapes.Rectangle",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Height": 20,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "NormalRectangle",
+ "RenderSize": [20, 20],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 20
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.FontIcon",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "CheckGlyph",
+ "RenderSize": [20, 32],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00000000",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [20, 32],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FFFFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [20, 16],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "8,5,0,0",
+ "Name": "ContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Top",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBox",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "Height": 50,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "10,10,10,10",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "BorderElement",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollViewer",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "ContentElement",
+ "Padding": "10,10,10,10",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": null,
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Root",
+ "Padding": "0,0,0,0",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00FFFFFF",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": "Windows.UI.Xaml.Media.RectangleGeometry",
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "ScrollContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [760, 10],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.FrameworkElement",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [760, 10],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,0,0,0",
+ "Name": "VerticalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "HorizontalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFE6E6E6",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "ScrollBarSeparator",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#B3E1E1E1",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "PlaceholderTextContentPresenter",
+ "Padding": "10,10,10,10",
+ "RenderSize": [780, 39],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Button",
+ "Background": "#33000000",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "0,10,10,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Name": "DeleteButton",
+ "Padding": "0,0,-2,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.PasswordBox",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "Height": 50,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "10,10,10,10",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "BorderElement",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollViewer",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "ContentElement",
+ "Padding": "10,10,10,10",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": null,
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Root",
+ "Padding": "0,0,0,0",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00FFFFFF",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ScrollContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": "Windows.UI.Xaml.Media.RectangleGeometry",
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "ScrollContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [760, 10],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.FrameworkElement",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [760, 10],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [780, 30],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,0,0,0",
+ "Name": "VerticalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ScrollBar",
+ "Background": "#00FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "2,2,2,2",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#00FFFFFF",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "HorizontalScrollBar",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFE6E6E6",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "ScrollBarSeparator",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#B3E1E1E1",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "10,10,10,10",
+ "Name": "PlaceholderTextContentPresenter",
+ "Padding": "10,10,10,10",
+ "RenderSize": [780, 39],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.ToggleButton",
+ "Background": "#33000000",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "0,10,10,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Name": "RevealButton",
+ "Padding": "0,0,-2,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.CalendarDatePicker",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "Height": 50,
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 50],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "Width": 150,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Root",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Background",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Name": "DateText",
+ "Padding": "12,0,0,2",
+ "RenderSize": [90, 21],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.FontIcon",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Center",
+ "Margin": "0,0,0,0",
+ "Name": "CalendarGlyph",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00000000",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [150, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ComboBox",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "Height": 50,
+ "HorizontalAlignment": "Left",
+ "Margin": "0,0,0,0",
+ "Padding": "12,5,0,7",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Top",
+ "Visibility": "Visible",
+ "Width": 800,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "LayoutRoot",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#33000000",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Background",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FF409EFE",
+ "BorderBrush": "#66000000",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "HighlightBackground",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 50],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "12,5,0,7",
+ "Name": "ContentPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [756, 19],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "PlaceholderTextBlock",
+ "Padding": "0,0,0,0",
+ "RenderSize": [756, 19],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBox",
+ "Background": "#66FFFFFF",
+ "BorderBrush": "#00FFFFFF",
+ "BorderThickness": "1,1,1,1",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#FF000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "EditableText",
+ "Padding": "11,5,32,6",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Center",
+ "Visibility": "Collapsed"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#00FFFFFF",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,1,1,1",
+ "Name": "DropDownOverlay",
+ "Padding": "0,0,0,0",
+ "RenderSize": [0, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Collapsed",
+ "Width": 30
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.FontIcon",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Right",
+ "Margin": "0,0,10,0",
+ "Name": "DropDownGlyph",
+ "RenderSize": [12, 32],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Grid",
+ "Background": "#00000000",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 32],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.TextBlock",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#CC000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [12, 12],
+ "VerticalAlignment": "Center",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter",
+ "Background": null,
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Foreground": "#99000000",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "DescriptionPresenter",
+ "Padding": "0,0,0,0",
+ "RenderSize": [800, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ },
+ {
+ "XamlType": "Windows.UI.Xaml.Controls.Primitives.Popup",
+ "Clip": null,
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Name": "Popup",
+ "RenderSize": [768, 0],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json
new file mode 100644
index 00000000000..c00ab2049da
--- /dev/null
+++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageRTL.json
@@ -0,0 +1,38 @@
+{
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFFFFF00",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 300,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [500, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 500,
+ "children": [
+ {
+ "XamlType": "Microsoft.ReactNative.ViewPanel",
+ "Background": null,
+ "BorderBrush": "#00000000",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [500, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.DependencyObject"
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json
new file mode 100644
index 00000000000..753214da826
--- /dev/null
+++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithBorder.json
@@ -0,0 +1,38 @@
+{
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFFFFF00",
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "Height": 300,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [500, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 500,
+ "children": [
+ {
+ "XamlType": "Microsoft.ReactNative.ViewPanel",
+ "Background": null,
+ "BorderBrush": "#5500FF00",
+ "BorderThickness": "10,10,10,10",
+ "Clip": null,
+ "CornerRadius": "10,10,10,10",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [480, 280],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.DependencyObject"
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json
new file mode 100644
index 00000000000..c00ab2049da
--- /dev/null
+++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder-Subsequent.json
@@ -0,0 +1,38 @@
+{
+ "XamlType": "Windows.UI.Xaml.Controls.Border",
+ "Background": "#FFFFFF00",
+ "BorderBrush": null,
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 300,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "Padding": "0,0,0,0",
+ "RenderSize": [500, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 500,
+ "children": [
+ {
+ "XamlType": "Microsoft.ReactNative.ViewPanel",
+ "Background": null,
+ "BorderBrush": "#00000000",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [500, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.DependencyObject"
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json
new file mode 100644
index 00000000000..9406a02556a
--- /dev/null
+++ b/packages/E2ETest/windows/ReactUWPTestApp/Assets/TreeDump/masters/ImageWithoutBorder.json
@@ -0,0 +1,21 @@
+{
+ "XamlType": "Microsoft.ReactNative.ViewPanel",
+ "Background": "#FFFFFF00",
+ "BorderBrush": "#00000000",
+ "BorderThickness": "0,0,0,0",
+ "Clip": null,
+ "CornerRadius": "0,0,0,0",
+ "FlowDirection": "LeftToRight",
+ "Height": 300,
+ "HorizontalAlignment": "Stretch",
+ "Margin": "0,0,0,0",
+ "RenderSize": [500, 300],
+ "VerticalAlignment": "Stretch",
+ "Visibility": "Visible",
+ "Width": 500,
+ "children": [
+ {
+ "XamlType": "Windows.UI.Xaml.DependencyObject"
+ }
+ ]
+}
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj b/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj
index 4c3f53bfa5a..6611c1e40c4 100644
--- a/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj
+++ b/packages/E2ETest/windows/ReactUWPTestApp/ReactUWPTestApp.csproj
@@ -71,7 +71,7 @@
true
bin\x64\Debug\
- DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP;
;2008
full
x64
@@ -81,7 +81,7 @@
bin\x64\Release\
- TRACE;NETFX_CORE;WINDOWS_UWP
+ TRACE;NETFX_CORE;WINDOWS_UWP;E2ETEST_OVERRIDE_4122
true
;2008
pdbonly
@@ -132,7 +132,7 @@
-
+
@@ -176,8 +176,8 @@
- echo WorkingDir %CD%
- npx --no-install yarn run bundle
+ echo WorkingDir %CD%
+ npx --no-install yarn run bundle
diff --git a/packages/E2ETest/windows/ReactUWPTestApp/copyTreeDump.cmd b/packages/E2ETest/windows/ReactUWPTestApp/copyTreeDump.cmd
index 93578825c21..4b40165390b 100644
--- a/packages/E2ETest/windows/ReactUWPTestApp/copyTreeDump.cmd
+++ b/packages/E2ETest/windows/ReactUWPTestApp/copyTreeDump.cmd
@@ -1 +1 @@
-copy %LocalAppData%\Packages\ReactUWPTestApp_kc2bncckyf4ap\LocalState\TreeDump\*.out Assets\TreeDump\*.txt
\ No newline at end of file
+@copy /d %LocalAppData%\Packages\ReactUWPTestApp_kc2bncckyf4ap\LocalState\TreeDump\*.json %~dp0%\Assets\TreeDump\masters\*.json
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs b/packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs
new file mode 100644
index 00000000000..ab558d3f0ee
--- /dev/null
+++ b/packages/E2ETest/windows/TreeDumpLibrary/DefaultVisualTreeLogger.cs
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text;
+using Windows.UI.Xaml;
+
+namespace TreeDumpLibrary
+{
+ public sealed class DefaultVisualTreeLogger : IVisualTreeLogger
+ {
+ public void BeginNode(int indent, string nodeName, DependencyObject obj, bool hasProperties)
+ {
+ AppendLogger(indent, $"[{nodeName}]");
+ }
+
+ public void EndNode(int indent, string nodeName, DependencyObject obj, bool isLast)
+ { // no-op
+ }
+
+ public void LogProperty(int indent, string propertyName, object propertyValue, bool isLast)
+ {
+ AppendLogger(indent, $"{propertyName}={propertyValue}");
+ }
+
+ public override string ToString()
+ {
+ return _logger.ToString();
+ }
+
+ private readonly StringBuilder _logger = new StringBuilder();
+ private void AppendLogger(int indent, string s)
+ {
+ _logger.AppendLine(s.PadLeft(2 * indent + s.Length));
+ }
+
+ public void BeginArray(int indent, string propertyName)
+ { // no-op
+ }
+
+ public void EndArray(int indent, string propertyName)
+ {
+ }
+ }
+}
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs b/packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs
new file mode 100644
index 00000000000..5bcc26823f6
--- /dev/null
+++ b/packages/E2ETest/windows/TreeDumpLibrary/IPropertyValueTranslator.cs
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace TreeDumpLibrary
+{
+ public interface IPropertyValueTranslator
+ {
+ string PropertyValueToString(string propertyName, object propertyObject);
+ }
+}
\ No newline at end of file
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs b/packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs
new file mode 100644
index 00000000000..4cddddc9cb2
--- /dev/null
+++ b/packages/E2ETest/windows/TreeDumpLibrary/IVisualTreeLogger.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Windows.UI.Xaml;
+
+namespace TreeDumpLibrary
+{
+ public interface IVisualTreeLogger
+ {
+ void BeginNode(int indent, string nodeName, DependencyObject obj, bool hasProperties);
+ void EndNode(int indent, string nodeName, DependencyObject obj, bool isLast);
+ void LogProperty(int indent, string propertyName, object propertyValue, bool isLast);
+ string ToString();
+ void BeginArray(int indent, string propertyName);
+ void EndArray(int indent, string propertyName);
+ }
+}
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs b/packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs
new file mode 100644
index 00000000000..7cf52ca97ab
--- /dev/null
+++ b/packages/E2ETest/windows/TreeDumpLibrary/JsonVisualTreeLogger.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text;
+using Windows.UI.Xaml;
+
+namespace TreeDumpLibrary
+{
+ public sealed class JsonVisualTreeLogger : IVisualTreeLogger
+ {
+ private readonly StringBuilder _logger = new StringBuilder();
+ public void BeginArray(int indent, string propertyName)
+ {
+ AppendLogger(indent, $"\"{propertyName}\": [");
+ }
+
+ public void BeginNode(int indent, string nodeName, DependencyObject obj, bool hasProperties)
+ {
+ AppendLogger(indent, "{");
+ LogProperty(indent + 2, "XamlType", JsonPropertyValueTranslator.Quote(nodeName), !hasProperties);
+ }
+
+ public void EndArray(int indent, string propertyName)
+ {
+ AppendLogger(indent, "]");
+ }
+
+ public void EndNode(int indent, string nodeName, DependencyObject obj, bool isLast)
+ {
+ AppendLogger(indent, $"}}{GetDelimiter(isLast)}");
+ }
+
+ private string GetDelimiter(bool isLast)
+ {
+ return isLast ? "" : ",";
+ }
+
+ public void LogProperty(int indent, string propertyName, object propertyValue, bool isLast)
+ {
+ AppendLogger(indent, $"\"{propertyName}\": {propertyValue}{GetDelimiter(isLast)}");
+ }
+
+ public override string ToString()
+ {
+ return _logger.ToString();
+ }
+
+ private void AppendLogger(int indent, string s)
+ {
+ _logger.AppendLine(s.PadLeft(2 * indent + s.Length));
+ }
+ }
+}
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs
index 69681eb5da6..1e12a33264b 100644
--- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs
+++ b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpControlViewManager.cs
@@ -1,19 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-using System.Diagnostics;
-using Windows.UI.Xaml.Media;
-using Windows.UI.Xaml.Controls;
-
using Microsoft.ReactNative;
using Microsoft.ReactNative.Managed;
-using Windows.UI.Xaml;
-using Windows.UI.ViewManagement;
-using System.Threading.Tasks;
using System;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
+using System.Threading.Tasks;
+using Windows.ApplicationModel.DataTransfer;
+using Windows.Data.Json;
using Windows.Storage;
-using System.Collections.Generic;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Documents;
+using Windows.UI.Xaml.Media;
namespace TreeDumpLibrary
{
@@ -32,7 +34,7 @@ public FrameworkElement CreateView()
if (bounds.Width != 800 || bounds.Height != 600)
{
// Dump disabled when window size is not 800x600!
- UpdateResult(false /*matchDump*/, "Window has been resized, dump comparison is only valid at default launch size: 800x600!, current size:" + bounds.ToString());
+ UpdateResult(false /*matchDump*/ , "Window has been resized, dump comparison is only valid at default launch size: 800x600!, current size:" + bounds.ToString());
}
else
{
@@ -45,7 +47,7 @@ public FrameworkElement CreateView()
}
};
- m_textBlock.PointerPressed += (soruce, e) =>
+ m_textBlock.PointerPressed += (source, e) =>
{
if (!m_dumpMatchExpected)
{
@@ -54,7 +56,7 @@ public FrameworkElement CreateView()
m_timer.Stop();
}
m_errStringShowing = true;
- m_textBlock.Text = m_errString;
+ errors.Apply(m_textBlock);
m_textBlock.IsTextSelectionEnabled = true;
}
};
@@ -75,25 +77,18 @@ public void UpdateProperties(FrameworkElement view, IJSValueReader propertyMapRe
{
SetUIAID((TextBlock)view, kvp.Value.AsString());
}
- else if(kvp.Key == "additionalProperties")
+ else if (kvp.Key == "additionalProperties")
{
SetAdditionalProperties(kvp.Value.AsArray());
}
}
}
- IReadOnlyDictionary IViewManagerWithNativeProperties.NativeProps
- {
- get
- {
- return new Dictionary
- {
- { "dumpID", ViewManagerPropertyType.String },
- { "uiaID", ViewManagerPropertyType.String },
- { "additionalProperties", ViewManagerPropertyType.Array }
- };
- }
- }
+ IReadOnlyDictionary IViewManagerWithNativeProperties.NativeProps => new Dictionary
+ { { "dumpID", ViewManagerPropertyType.String },
+ { "uiaID", ViewManagerPropertyType.String },
+ { "additionalProperties", ViewManagerPropertyType.Array }
+ };
public void SetDumpID(TextBlock view, string value)
{
@@ -101,6 +96,7 @@ public void SetDumpID(TextBlock view, string value)
m_dumpMatchExpected = false;
m_dumpExpectedText = null;
m_errString = "";
+ errors = new TreeDumpErrors();
m_errStringShowing = false;
if (m_textBlock != null)
{
@@ -119,7 +115,7 @@ public void SetUIAID(TextBlock view, string value)
public void SetAdditionalProperties(IReadOnlyList additionalProperties)
{
- foreach(var property in additionalProperties)
+ foreach (var property in additionalProperties)
{
m_additionalProperties.Add(property.AsString());
}
@@ -175,55 +171,184 @@ private async Task MatchTreeDumpFromLayoutUpdateAsync()
}
}
- String dumpText = VisualTreeDumper.DumpTree(dumpRoot, m_textBlock /* exclude */, m_additionalProperties);
+ string dumpText = VisualTreeDumper.DumpTree(dumpRoot, m_textBlock /* exclude */ , m_additionalProperties, mode);
if (dumpText != m_dumpExpectedText)
{
await MatchDump(dumpText);
}
}
+ private readonly DumpTreeMode mode = DumpTreeMode.Json;
+
private async Task MatchDump(string dumpText)
{
+ StorageFile masterFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync($@"Assets\{GetMasterFile()}");
if (m_dumpExpectedText == null)
{
try
{
- var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@"Assets\TreeDump\" + m_dumpID + ".txt");
- m_dumpExpectedText = await Windows.Storage.FileIO.ReadTextAsync(file);
+ m_dumpExpectedText = await FileIO.ReadTextAsync(masterFile);
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
- string copyFileName = "TreeDump\\" + m_dumpID + ".txt";
+ string copyFileName = GetMasterFile();
var copyDumpFile = await storageFolder.CreateFileAsync(copyFileName, CreationCollisionOption.ReplaceExisting);
- await Windows.Storage.FileIO.WriteTextAsync(copyDumpFile, m_dumpExpectedText);
+ await FileIO.WriteTextAsync(copyDumpFile, m_dumpExpectedText);
}
catch (IOException)
{
- UpdateResult(false /*matchDump*/, "Tree dump master file not found in testapp package!");
+ UpdateResult(false /*matchDump*/ , "Tree dump master file not found in testapp package!");
}
}
- if (m_dumpExpectedText != dumpText)
+ if (!DumpsAreEqual(m_dumpExpectedText, dumpText))
{
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
- string fileName = "TreeDump\\" + m_dumpID + ".out";
+ string fileName = GetOutputFile();
try
{
StorageFile outFile = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
- await Windows.Storage.FileIO.WriteTextAsync(outFile, dumpText);
- UpdateResult(false /*matchDump*/, "Tree dump file does not match master! See output at " + outFile.Path);
+ await FileIO.WriteTextAsync(outFile, dumpText);
+ UpdateResult(false /*matchDump*/ ,
+ $"Tree dump file does not match master at {masterFile.Path} - See output at {outFile.Path}",
+ GetInlines(masterFile, outFile, m_textBlock));
}
catch (IOException)
{
- UpdateResult(false /*matchDump*/, "Can't write dump output file:" + fileName);
+ UpdateResult(false /*matchDump*/ , "Can't write dump output file:" + fileName);
}
}
else
{
- UpdateResult(true /*matchDump*/, "");
+ UpdateResult(true /*matchDump*/ , "");
+ }
+ }
+
+ private bool DumpsAreEqual(string dumpExpectedText, string dumpText)
+ {
+ if (mode == DumpTreeMode.Default)
+ {
+ return dumpExpectedText == dumpText;
+ }
+ else
+ {
+ JsonValue expected = JsonValue.Parse(dumpExpectedText);
+ JsonValue actual = JsonValue.Parse(dumpText);
+ return JsonComparesEqual(expected, actual);
}
}
- private async void UpdateResult(bool matchDump, string helpText)
+ private bool JsonComparesEqual(IJsonValue expected, IJsonValue actual)
+ {
+ if (expected.ValueType != actual.ValueType)
+ {
+ return false;
+ }
+ switch (expected.ValueType)
+ {
+ case JsonValueType.String:
+ if (expected.GetString() == actual.GetString())
+ {
+ return true;
+ }
+ else { Debug.WriteLine($"Expected {expected.GetString()} got {actual.GetString()}"); return false; }
+ case JsonValueType.Number:
+ return expected.GetNumber() == actual.GetNumber();
+ case JsonValueType.Boolean:
+ return expected.GetBoolean() == actual.GetBoolean();
+ case JsonValueType.Null:
+ return true;
+ case JsonValueType.Array:
+ {
+ var ea = expected.GetArray();
+ var aa = actual.GetArray();
+ if (ea.Count != aa.Count) { return false; }
+ for (uint i = 0; i < ea.Count; i++)
+ {
+ if (!JsonComparesEqual(ea[(int)i], aa[(int)i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ case JsonValueType.Object:
+ {
+ var eo = expected.GetObject();
+ var ao = actual.GetObject();
+ if (eo.Keys.Count != ao.Keys.Count) { return false; }
+ foreach (var key in eo.Keys)
+ {
+ if (!JsonComparesEqual(eo.GetNamedValue(key), ao.GetNamedValue(key)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ default:
+ throw new ArgumentException();
+ }
+ }
+
+ private string GetOutputFile()
+ {
+ return "TreeDump\\" + m_dumpID + (mode == DumpTreeMode.Json ? ".json" : ".out");
+ }
+
+ private string GetMasterFile()
+ {
+ return "TreeDump\\masters\\" + m_dumpID + (mode == DumpTreeMode.Json ? ".json" : ".txt");
+ }
+
+ private static IList GetInlines(StorageFile masterFile, StorageFile outFile, UIElement anchor)
+ {
+ Hyperlink masterLink = new Hyperlink();
+ masterLink.Click += (_1, _2) => { Windows.System.Launcher.LaunchFileAsync(masterFile); };
+ masterLink.Inlines.Add(new Run() { Text = "master" });
+ Hyperlink outLink = new Hyperlink();
+ outLink.Click += (_1, _2) => { Windows.System.Launcher.LaunchFileAsync(outFile); };
+ outLink.Inlines.Add(new Run() { Text = "output" });
+ List inlines = new List()
+ {
+ new Run () { Text = "Tree dump " },
+ outLink,
+ new Run () { Text = " does not match " },
+ masterLink
+ };
+
+ #region Diff support - Replace with LaunchUriAsync when we find the VSCode protocol handler Uri for diffing
+ string code_cmd = Environment.ExpandEnvironmentVariables(@"%UserProfile%\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd");
+ Hyperlink diffLink = new Hyperlink();
+ diffLink.Click += (_1, _2) =>
+ {
+ string commandLine = $"code.cmd --diff \"{masterFile.Path}\" \"{outFile.Path}\"";
+ DataPackage dataPackage = new DataPackage();
+ dataPackage.SetText(commandLine);
+ Clipboard.SetContent(dataPackage);
+ ToolTip toolTip = new ToolTip() { Content = "Copied to clipboard" };
+ ToolTipService.SetToolTip(anchor, toolTip);
+ toolTip.Opened += (_3, _4) =>
+ {
+ var timer = Windows.System.DispatcherQueue.GetForCurrentThread().CreateTimer();
+ timer.IsRepeating = false;
+ timer.Interval = TimeSpan.FromSeconds(1);
+ timer.Tick += (_5, _6) =>
+ {
+ toolTip.IsOpen = false;
+ ToolTipService.SetToolTip(anchor, null);
+ };
+ timer.Start();
+ };
+ toolTip.IsOpen = true;
+ };
+ diffLink.Inlines.Add(new Run() { Text = "copy diff command to clipboard" });
+ inlines.Add(new Run() { Text = " - " });
+ inlines.Add(diffLink);
+ #endregion
+ return inlines;
+ }
+
+ private async void UpdateResult(bool matchDump, string helpText, IList inlines = null)
{
if (matchDump)
{
@@ -233,23 +358,37 @@ private async void UpdateResult(bool matchDump, string helpText)
{
UpdateTextBlockText("TreeDump:Failed, click to see more!");
m_errString += "\r\n" + helpText;
-
- StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
- string fileNameError = "TreeDump\\" + m_dumpID + ".err";
- try
+ errors.Inlines.Clear();
+ if (inlines != null)
{
- StorageFile errFile = await storageFolder.CreateFileAsync(fileNameError, CreationCollisionOption.GenerateUniqueName);
- await Windows.Storage.FileIO.WriteTextAsync(errFile, m_errString);
+ errors.Inlines.AddRange(inlines);
}
- catch (Exception e)
+ else
{
- UpdateTextBlockText("Creat err file failed: " + e.ToString());
+ errors.Inlines.Add(new Run() { Text = helpText });
}
+ errors.Inlines.Add(new LineBreak());
+ await WriteErrorFile();
}
m_dumpMatchExpected = matchDump;
}
+ private async Task WriteErrorFile()
+ {
+ StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
+ string fileNameError = "TreeDump\\" + m_dumpID + ".err";
+ try
+ {
+ StorageFile errFile = await storageFolder.CreateFileAsync(fileNameError, CreationCollisionOption.GenerateUniqueName);
+ await FileIO.WriteTextAsync(errFile, m_errString);
+ }
+ catch (Exception e)
+ {
+ UpdateTextBlockText("Create err file failed: " + e.ToString());
+ }
+ }
+
private void UpdateTextBlockText(string text)
{
if (!m_errStringShowing && m_textBlock.Text != text)
@@ -263,10 +402,28 @@ private void UpdateTextBlockText(string text)
private bool m_dumpMatchExpected = false;
private bool m_errStringShowing = false;
private string m_errString = "";
+ private TreeDumpErrors errors = new TreeDumpErrors();
private string m_uiaID = null;
- private List m_additionalProperties = new List();
+ private readonly List m_additionalProperties = new List();
private DispatcherTimer m_timer = null;
+ }
+
+ internal class TreeDumpErrors
+ {
+ readonly List inlines = new List();
+
+ public List Inlines => inlines;
+ public void Apply(TextBlock textBlock)
+ {
+ textBlock.Text = "";
+ textBlock.Inlines.Clear();
+ foreach (var inline in Inlines)
+ {
+ textBlock.Inlines.Add(inline);
+ }
+ textBlock.Width = 800;
+ }
}
}
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj
index 0b24b8cc6fa..7407afba744 100644
--- a/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj
+++ b/packages/E2ETest/windows/TreeDumpLibrary/TreeDumpLibrary.csproj
@@ -106,6 +106,10 @@
$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\
+
+
+
+
@@ -137,4 +141,4 @@
-->
-
+
\ No newline at end of file
diff --git a/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs b/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs
index d44de541d9a..32a43aa7bd2 100644
--- a/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs
+++ b/packages/E2ETest/windows/TreeDumpLibrary/VisualTreeDumper.cs
@@ -5,38 +5,42 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
+using Windows.Foundation;
using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace TreeDumpLibrary
{
- public sealed class VisualTreeDumper
+ public enum DumpTreeMode
+ {
+ Default,
+ Json
+ }
+
+ public sealed class VisualTreeDumper
{
class Visitor
{
- private DefaultVisualTreeLogger _logger;
+ private readonly IVisualTreeLogger _logger;
private int _indent;
- private DefaultFilter _filter;
- private DefaultPropertyValueTranslator _translator;
- public Visitor(DefaultFilter filter, DefaultPropertyValueTranslator translator, DefaultVisualTreeLogger logger)
+ private readonly DefaultFilter _filter;
+ private readonly IPropertyValueTranslator _translator;
+ public Visitor(DefaultFilter filter, IPropertyValueTranslator translator, IVisualTreeLogger logger)
{
_indent = 0;
_filter = filter;
_translator = translator;
_logger = logger;
}
- public void EndVisitNode(DependencyObject obj)
+ public void EndVisitNode(DependencyObject obj, bool isLast)
{
_indent--;
- _logger.EndNode(_indent, obj.GetType().FullName, obj);
+ _logger.EndNode(_indent, obj.GetType().FullName, obj, isLast);
}
- public void BeginVisitNode(DependencyObject obj)
+ public void BeginVisitNode(DependencyObject obj, bool hasProperties)
{
- _logger.BeginNode(_indent, obj.GetType().FullName, obj);
+ _logger.BeginNode(_indent, obj.GetType().FullName, obj, hasProperties);
_indent++;
}
@@ -55,70 +59,114 @@ public bool ShouldVisitProperty(PropertyInfo propertyInfo)
return _filter.ShouldVisitProperty(propertyInfo.Name);
}
- public void VisitProperty(string propertyName, object value)
+ public void VisitProperty(string propertyName, object value, bool isLast)
{
var v = _translator.PropertyValueToString(propertyName, value);
- if (_filter.ShouldVisitPropertyValue(v))
+ _logger.LogProperty(_indent + 1, propertyName, v, isLast);
+ }
+
+ public void BeginChildren()
+ {
+ _logger.BeginArray(++_indent, "children");
+ }
+
+ public void EndChildren()
+ {
+ _logger.EndArray(_indent--, "children");
+ }
+
+ public bool ShouldVisitPropertyValue(string propertyName, object value)
+ {
+ string s = _translator.PropertyValueToString(propertyName, value);
+ if (propertyName == "Name")
{
- _logger.LogProperty(_indent + 1, propertyName, v);
+ string name = value as string;
+ return !name.StartsWith(":") &&
+ name != "";
}
+ return _filter.ShouldVisitPropertyValue(s);
}
}
- public static string DumpTree(DependencyObject root, DependencyObject excludedNode, IList additionalProperties)
+ public static string DumpTree(DependencyObject root, DependencyObject excludedNode, IList additionalProperties, DumpTreeMode mode)
{
var propertyFilter = new DefaultFilter();
((List)propertyFilter.PropertyNameAllowList).AddRange(additionalProperties);
- Visitor visitor = new Visitor(propertyFilter,
- new DefaultPropertyValueTranslator(),
+ IPropertyValueTranslator translator = (mode == DumpTreeMode.Json ?
+ new JsonPropertyValueTranslator() as IPropertyValueTranslator :
+ new DefaultPropertyValueTranslator());
+ IVisualTreeLogger logger = (mode == DumpTreeMode.Json ?
+ new JsonVisualTreeLogger() as IVisualTreeLogger :
new DefaultVisualTreeLogger());
+ Visitor visitor = new Visitor(propertyFilter, translator, logger);
+
WalkThroughTree(root, excludedNode, visitor);
return visitor.ToString();
}
- private static void WalkThroughProperties(DependencyObject node, Visitor visitor)
+ private static void WalkThroughProperties(DependencyObject node, Visitor visitor, bool hasChildren)
{
if (visitor.ShouldVisitPropertiesForNode(node))
{
- var properties = node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(x => x.Name);
- foreach (var property in properties)
- {
- if (visitor.ShouldVisitProperty(property))
- {
- Object value = null;
+ var properties = (from property in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ where visitor.ShouldVisitProperty(property) &&
+ visitor.ShouldVisitPropertyValue(property.Name,
+ GetObjectProperty(node, property))
+ orderby property.Name
+ select property).ToArray();
- try
- {
- value = property.GetValue(obj: node, index: null);
- }
- catch (Exception e)
- {
- value = "Exception when read " + property.Name + e.ToString();
- }
- visitor.VisitProperty(property.Name, value);
- }
+ for (int i = 0; i < properties.Length; i++)
+ {
+ var property = properties[i];
+ object value = null;
+ value = GetObjectProperty(node, property);
+ bool isLast = (i == properties.Length - 1) && !hasChildren;
+ visitor.VisitProperty(property.Name, value, isLast);
}
}
}
- private static void WalkThroughTree(DependencyObject node, DependencyObject excludedNode, Visitor visitor)
+
+ private static object GetObjectProperty(DependencyObject node, PropertyInfo property)
+ {
+ object value;
+ try
+ {
+ value = property.GetValue(node);
+ }
+ catch (Exception e)
+ {
+ value = "Exception when reading " + property.Name + e.ToString();
+ }
+
+ return value;
+ }
+
+ private static void WalkThroughTree(DependencyObject node, DependencyObject excludedNode, Visitor visitor, bool isLast = true)
{
if (node != null)
{
- visitor.BeginVisitNode(node);
+ // Assume that if we have a UIElement, we'll have some properties
+ visitor.BeginVisitNode(node, node is UIElement);
- WalkThroughProperties(node, visitor);
- for (int i = 0; i < VisualTreeHelper.GetChildrenCount(node); i++)
+ var childrenCount = VisualTreeHelper.GetChildrenCount(node);
+ WalkThroughProperties(node, visitor, childrenCount != 0);
+ if (childrenCount != 0)
{
- var child = VisualTreeHelper.GetChild(node, i);
- if (child != excludedNode)
+ visitor.BeginChildren();
+ for (int i = 0; i < childrenCount; i++)
{
- WalkThroughTree(child, excludedNode, visitor);
+ var child = VisualTreeHelper.GetChild(node, i);
+ if (child != excludedNode)
+ {
+ bool isLastChild = (i == childrenCount - 1);
+ WalkThroughTree(child, excludedNode, visitor, isLastChild);
+ }
}
+ visitor.EndChildren();
}
-
- visitor.EndVisitNode(node);
+ visitor.EndVisitNode(node, isLast);
}
}
}
@@ -128,8 +176,26 @@ public sealed class DefaultFilter
public DefaultFilter()
{
- PropertyNameAllowList = new List {"Foreground", "Background", "Padding", "Margin", "RenderSize", "Visibility", "CornerRadius", "BorderThickness",
- "Width", "Height", "BorderBrush", "VerticalAlignment", "HorizontalAlignment", "Clip", /*"ActualOffset" 19h1*/};
+ PropertyNameAllowList = new List
+ {
+ "Foreground",
+ "Background",
+ "Padding",
+ "Margin",
+ "RenderSize",
+ "Visibility",
+ "CornerRadius",
+ "BorderThickness",
+ "Width",
+ "Height",
+ "BorderBrush",
+ "VerticalAlignment",
+ "HorizontalAlignment",
+ "Clip",
+ "FlowDirection",
+ "Name",
+ /*"ActualOffset" 19h1*/
+ };
}
public bool ShouldVisitPropertyValue(string propertyValue)
@@ -142,7 +208,7 @@ public bool ShouldVisitProperty(string propertyName)
return (PropertyNameAllowList.Contains(propertyName));
}
}
- public sealed class DefaultPropertyValueTranslator
+ public sealed class DefaultPropertyValueTranslator : IPropertyValueTranslator
{
public string PropertyValueToString(string propertyName, object propertyObject)
{
@@ -151,39 +217,48 @@ public string PropertyValueToString(string propertyName, object propertyObject)
return "[NULL]";
}
- var brush = propertyObject as SolidColorBrush;
- if (brush != null)
+ if (propertyObject is SolidColorBrush)
+ {
+ return (propertyObject as SolidColorBrush).Color.ToString();
+ }
+ else if (propertyObject is Size)
{
- return brush.Color.ToString();
+ // comparing doubles is numerically unstable so just compare their integer parts
+ Size size = (Size)propertyObject;
+ return $"{(int)size.Width},{(int)size.Height}";
}
return propertyObject.ToString();
}
}
- public sealed class DefaultVisualTreeLogger
- {
- public void BeginNode(int indent, string nodeName, DependencyObject obj)
- {
- AppendLogger(indent, string.Format("[{0}]", nodeName));
- }
-
- public void EndNode(int indent, string nodeName, DependencyObject obj)
- {
- }
- public void LogProperty(int indent, string propertyName, object propertyValue)
- {
- AppendLogger(indent, string.Format("{0}={1}", propertyName, propertyValue));
- }
-
- public override string ToString()
+ public sealed class JsonPropertyValueTranslator : IPropertyValueTranslator
+ {
+ public string PropertyValueToString(string propertyName, object propertyObject)
{
- return _logger.ToString();
+ if (propertyObject == null)
+ {
+ return "null";
+ }
+ else if (propertyObject is int || propertyObject is bool || propertyObject is double)
+ {
+ return propertyObject.ToString();
+ }
+ else if (propertyObject is SolidColorBrush)
+ {
+ return Quote((propertyObject as SolidColorBrush).Color.ToString());
+ }
+ else if (propertyObject is Size)
+ {
+ // comparing doubles is numerically unstable so just compare their integer parts
+ Size size = (Size)propertyObject;
+ return $"[{(int)size.Width}, {(int)size.Height}]";
+ }
+ return Quote(propertyObject.ToString());
}
- private StringBuilder _logger = new StringBuilder();
- private void AppendLogger(int indent, string s)
+ public static string Quote(string s)
{
- _logger.AppendLine(s.PadLeft(2 * indent + s.Length));
+ return '"' + s.Replace("\"", "\\\"") + '"';
}
}
}
diff --git a/packages/microsoft-reactnative-sampleapps/metro.config.js b/packages/microsoft-reactnative-sampleapps/metro.config.js
index fd0f93293e9..d850032e67a 100644
--- a/packages/microsoft-reactnative-sampleapps/metro.config.js
+++ b/packages/microsoft-reactnative-sampleapps/metro.config.js
@@ -4,13 +4,9 @@
*
* @format
*/
-const fs = require('fs');
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
-const rnPath = fs.realpathSync(
- path.resolve(require.resolve('react-native/package.json'), '..'),
-);
const rnwPath = path.resolve(__dirname, '../../vnext');
module.exports = {
@@ -23,37 +19,17 @@ module.exports = {
],
resolver: {
+ resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver(
+ {windows: 'react-native-windows'},
+ ),
extraNodeModules: {
// Redirect metro to rnwPath instead of node_modules/react-native-windows, since metro doesn't like symlinks
- 'react-native': rnwPath,
'react-native-windows': rnwPath,
},
- // Include the macos platform in addition to the defaults because the fork includes macos, but doesn't declare it
- platforms: ['ios', 'android', 'windesktop', 'windows', 'web', 'macos'],
- // Since there are multiple copies of react-native, we need to ensure that metro only sees one of them
- // This should go away after RN 0.60 when haste is removed
blacklistRE: blacklist([
new RegExp(
'.*microsoft-reactnative-sampleapps/msbuild.*'.replace(/[/\\]/g, '\\/'),
), // Avoid error EBUSY: resource busy or locked, open 'D:\a\1\s\packages\E2ETest\msbuild.ProjectImports.zip' in pipeline
- new RegExp(`${path.resolve(rnPath)}.*`.replace(/[/\\]/g, '/')),
- new RegExp(
- `${path.resolve(rnwPath, 'ReactCopies').replace(/[/\\]/g, '/')}.*`,
- ),
- new RegExp(
- `${path
- .resolve(rnwPath, 'node_modules/react-native')
- .replace(/[/\\]/g, '/')}.*`,
- ),
- new RegExp(
- `${path
- .resolve(
- require.resolve('@react-native-community/cli/package.json'),
- '../node_modules/react-native',
- )
- .replace(/[/\\]/g, '/')}.*`,
- ),
-
// This stops "react-native run-windows" from causing the metro server to crash if its already running
new RegExp(
`${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
@@ -61,6 +37,9 @@ module.exports = {
]),
},
transformer: {
+ // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above
+ // Hopefully we can fix the default in the future
+ assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
diff --git a/packages/microsoft-reactnative-sampleapps/package.json b/packages/microsoft-reactnative-sampleapps/package.json
index d78a5348372..27afe30cf3b 100644
--- a/packages/microsoft-reactnative-sampleapps/package.json
+++ b/packages/microsoft-reactnative-sampleapps/package.json
@@ -7,23 +7,23 @@
"bundle-cpp": "just-scripts prepareBundle && react-native bundle --platform windows --entry-file index.windows.js --bundle-output windows/SampleAppCpp/Bundle/index.windows.bundle --assets-dest windows/SampleAppCpp/Bundle",
"bundle-cs": "just-scripts prepareBundle && react-native bundle --platform windows --entry-file index.windows.js --bundle-output windows/SampleAppCS/Bundle/index.windows.bundle --assets-dest windows/SampleAppCS/Bundle",
"clean": "just-scripts clean",
- "postinstall": "node postinstall.js",
"start": "react-native start",
"lint": "just-scripts lint",
"lint:fix": "just-scripts lint:fix",
- "watch": "tsc -w"
+ "watch": "tsc -w",
+ "windows": "react-native run-windows"
},
"dependencies": {
"react": "16.9.0",
- "react-native": "0.61.5",
- "react-native-windows": "0.0.0-master.31",
+ "react-native": "0.62.2",
+ "react-native-windows": "0.0.0-master.44",
"rnpm-plugin-windows": "^0.6.1"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/runtime": "^7.8.4",
"@types/react": "16.9.0",
- "@types/react-native": "~0.61.5",
+ "@types/react-native": "^0.62.2",
"just-scripts": "^0.36.1",
"metro-react-native-babel-preset": "^0.56.0",
"react-test-renderer": "16.9.0"
diff --git a/packages/microsoft-reactnative-sampleapps/postinstall.js b/packages/microsoft-reactnative-sampleapps/postinstall.js
deleted file mode 100644
index ea656da5b18..00000000000
--- a/packages/microsoft-reactnative-sampleapps/postinstall.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * The react-native cli getPlugins assumes that all the react-native platform packages
- * are located in node_modules.
- *
- * When in a yarn workspace, the react-native platforms can be hoisted, so we need to
- * add a link to the real location so that getPlugins works correctly.
- *
- * @format
- *
- */
-// @ts-check
-
-const fs = require('fs');
-const path = require('path');
-const os = require('os');
-
-const checkOrCreate_node_modules = () => {
- const p = path.join(__dirname, 'node_modules');
-
- if (!fs.existsSync(p)) {
- fs.mkdirSync(p);
- }
-};
-checkOrCreate_node_modules();
-
-const link = (name, target) => {
- const p = path.join(__dirname, 'node_modules', name);
-
- if (!fs.existsSync(p)) {
- fs.symlinkSync(target, p, os.platform() === 'win32' ? 'junction' : 'dir');
- }
-};
-
-link('react-native-windows', path.resolve(__dirname, '../../vnext'));
-link(
- 'react-native',
- path.resolve(require.resolve('react-native/package.json'), '..'),
-);
-link(
- 'rnpm-plugin-windows',
- path.resolve(require.resolve('rnpm-plugin-windows/package.json'), '..'),
-);
diff --git a/packages/override-tools/src/Cli.ts b/packages/override-tools/src/Cli.ts
index 982c4aac7ce..1462c1ec85f 100644
--- a/packages/override-tools/src/Cli.ts
+++ b/packages/override-tools/src/Cli.ts
@@ -188,8 +188,6 @@ async function addOverride(overridePath: string) {
* Remove an override from the manifest
*/
async function removeOverride(overridePath: string) {
- await checkFileExists('override', overridePath);
-
const manifestPath = await FileSearch.findManifest(overridePath);
const manifestDir = path.dirname(manifestPath);
@@ -330,7 +328,7 @@ function printValidationErrors(errors: Array) {
if (filesMissing.length > 0) {
const errorMessage =
- "Found override files that aren't listed in the manifest. Overrides can be added to the manifest by using 'yarn override add ':";
+ "Found override files that aren't listed in the manifest. Overrides can be added to the manifest by using 'yarn override add ' (where override is package relative):";
console.error(chalk.red(errorMessage));
filesMissing.forEach(err => console.error(` - ${err.file}`));
console.error();
@@ -338,7 +336,7 @@ function printValidationErrors(errors: Array) {
if (overridesMissing.length > 0) {
const errorMessage =
- "Found overrides in the manifest that don't exist on disk. Remove existing overrides using 'yarn override remove ':";
+ "Found overrides in the manifest that don't exist on disk. Remove existing overrides using 'yarn override remove ' (where override is package relative):";
console.error(chalk.red(errorMessage));
overridesMissing.forEach(err => console.error(` - ${err.file}`));
console.error();
@@ -346,7 +344,7 @@ function printValidationErrors(errors: Array) {
if (baseFilesNotFound.length > 0) {
const errorMessage =
- "Found overrides whose original files do not exist. Remove existing overrides using 'yarn override remove ':";
+ "Found overrides whose original files do not exist. Remove existing overrides using 'yarn override remove ' (where override is package relative):";
console.error(chalk.red(errorMessage));
baseFilesNotFound.forEach(err => console.error(` - ${err.file}`));
console.error();
@@ -354,7 +352,7 @@ function printValidationErrors(errors: Array) {
if (outOfDateFiles.length > 0) {
const errorMessage =
- "Found overrides whose original files have changed. Upgrade overrides using 'yarn override auto-upgrade ' and 'yarn override manual-upgrade ':";
+ "Found overrides whose original files have changed. Upgrade overrides using 'yarn override auto-upgrade ' and 'yarn override manual-upgrade ' (where manifest is package relative):";
console.error(chalk.red(errorMessage));
outOfDateFiles.forEach(err => console.error(` - ${err.file}`));
console.error();
diff --git a/packages/override-tools/src/Manifest.ts b/packages/override-tools/src/Manifest.ts
index c48a7848ab0..3c362767642 100644
--- a/packages/override-tools/src/Manifest.ts
+++ b/packages/override-tools/src/Manifest.ts
@@ -81,7 +81,7 @@ export default class Manifest {
const baseFile = override.baseFile;
const baseContent = await this.reactRepo.getFileContents(baseFile);
if (baseContent === null) {
- errors.push({type: 'baseFileNotFound', file: override.baseFile});
+ errors.push({type: 'baseFileNotFound', file: override.file});
return;
}
@@ -242,7 +242,8 @@ export default class Manifest {
*/
static hashContent(str: string) {
const hasher = crypto.createHash('sha1');
- hasher.update(str);
+ const normalizedStr = str.replace(/(? {
const expectedError: ValidationError = {
type: 'baseFileNotFound',
- file: 'foo\\bar.js',
+ file: 'aaa\\aaa.windows.js',
};
const testManifest = new Manifest(ourManifestData, ovrRepo, reactRepo);
diff --git a/packages/playground/Samples/mouse.tsx b/packages/playground/Samples/mouse.tsx
index f55251e60b3..455947f7ada 100644
--- a/packages/playground/Samples/mouse.tsx
+++ b/packages/playground/Samples/mouse.tsx
@@ -11,6 +11,7 @@ import {
Text,
GestureResponderEvent,
TouchableHighlight,
+ BackHandler,
} from 'react-native';
export default class Bootstrap extends React.Component<
@@ -32,6 +33,10 @@ export default class Bootstrap extends React.Component<
};
}
+ componentDidMount() {
+ BackHandler.addEventListener('hardwareBackPress', this.back);
+ }
+
render() {
return (
{
+ console.log('hardwareBackPress');
+ return true;
+ };
}
const styles = StyleSheet.create({
diff --git a/packages/playground/Samples/textinput.tsx b/packages/playground/Samples/textinput.tsx
index 53ac5cb107a..f342f158581 100644
--- a/packages/playground/Samples/textinput.tsx
+++ b/packages/playground/Samples/textinput.tsx
@@ -134,7 +134,6 @@ const styles = StyleSheet.create({
},
input: {
margin: 5,
- height: 40,
width: 700,
borderColor: '#7a42f4',
borderWidth: 1,
diff --git a/packages/playground/metro.config.js b/packages/playground/metro.config.js
index f019392ca1c..6a543d2b85b 100644
--- a/packages/playground/metro.config.js
+++ b/packages/playground/metro.config.js
@@ -8,9 +8,6 @@ const fs = require('fs');
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
-const rnPath = fs.realpathSync(
- path.resolve(require.resolve('react-native/package.json'), '..'),
-);
const rnwPath = fs.realpathSync(
path.resolve(require.resolve('react-native-windows/package.json'), '..'),
);
@@ -25,20 +22,14 @@ module.exports = {
],
resolver: {
+ resolveRequest: require('react-native-windows/metro-react-native-platform').reactNativePlatformResolver(
+ {windows: 'react-native-windows'},
+ ),
extraNodeModules: {
- // Redirect react-native to react-native-windows
- 'react-native': rnwPath,
+ // Redirect react-native-windows to avoid symlink (metro doesn't like symlinks)
'react-native-windows': rnwPath,
},
- // Include the macos platform in addition to the defaults because the fork includes macos, but doesn't declare it
- platforms: ['ios', 'android', 'windesktop', 'windows', 'web', 'macos'],
- // Since there are multiple copies of react-native, we need to ensure that metro only sees one of them
- // This should go in RN 0.61 when haste is removed
blacklistRE: blacklist([
- new RegExp(
- `${(path.resolve(rnPath) + path.sep).replace(/[/\\]/g, '/')}.*`,
- ),
-
// This stops "react-native run-windows" from causing the metro server to crash if its already running
new RegExp(
`${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
@@ -46,6 +37,9 @@ module.exports = {
]),
},
transformer: {
+ // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above
+ // Hopefully we can fix the default in the future
+ assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
diff --git a/packages/playground/package.json b/packages/playground/package.json
index 0897e808492..0eb37b69c06 100644
--- a/packages/playground/package.json
+++ b/packages/playground/package.json
@@ -10,14 +10,14 @@
},
"dependencies": {
"react": "16.9.0",
- "react-native": "0.61.5",
- "react-native-windows": "0.0.0-master.31"
+ "react-native": "0.62.2",
+ "react-native-windows": "0.0.0-master.44"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/runtime": "^7.8.4",
"@types/react": "16.9.0",
- "@types/react-native": "~0.61.5",
+ "@types/react-native": "^0.62.2",
"just-scripts": "^0.36.1",
"metro-react-native-babel-preset": "^0.56.0",
"react-test-renderer": "16.9.0",
diff --git a/packages/playground/react-native.config.js b/packages/playground/react-native.config.js
deleted file mode 100644
index fffebf99369..00000000000
--- a/packages/playground/react-native.config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-module.exports = {
- reactNativePath: fs.realpathSync(
- path.resolve(require.resolve('react-native-windows/package.json'), '..'),
- ),
-};
diff --git a/packages/playground/windows/playground-win32.sln b/packages/playground/windows/playground-win32.sln
index 8f15aa41d58..8b30f151e52 100644
--- a/packages/playground/windows/playground-win32.sln
+++ b/packages/playground/windows/playground-win32.sln
@@ -41,6 +41,7 @@ EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\..\..\vnext\Chakra\Chakra.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4
+ ..\..\..\vnext\Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4
..\..\..\vnext\Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4
..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4
EndGlobalSection
diff --git a/packages/playground/windows/playground/MainPage.cpp b/packages/playground/windows/playground/MainPage.cpp
index f39a9df925e..b1e7b1dd4ca 100644
--- a/packages/playground/windows/playground/MainPage.cpp
+++ b/packages/playground/windows/playground/MainPage.cpp
@@ -40,7 +40,7 @@ void MainPage::OnLoadClick(
host.InstanceSettings().UseWebDebugger(x_UseWebDebuggerCheckBox().IsChecked().GetBoolean());
host.InstanceSettings().UseDirectDebugger(x_UseDirectDebuggerCheckBox().IsChecked().GetBoolean());
host.InstanceSettings().DebuggerBreakOnNextLine(x_BreakOnFirstLineCheckBox().IsChecked().GetBoolean());
- host.InstanceSettings().UseFastRefresh(x_BreakOnFirstLineCheckBox().IsChecked().GetBoolean());
+ host.InstanceSettings().UseFastRefresh(x_UseFastRefreshCheckBox().IsChecked().GetBoolean());
host.InstanceSettings().DebuggerPort(static_cast(std::stoi(std::wstring(x_DebuggerPort().Text()))));
// Nudge the ReactNativeHost to create the instance and wrapping context
diff --git a/packages/react-native-win32/.flowconfig b/packages/react-native-win32/.flowconfig
index ff810c24cac..e9e76df4a37 100644
--- a/packages/react-native-win32/.flowconfig
+++ b/packages/react-native-win32/.flowconfig
@@ -10,23 +10,30 @@
; initRNLibraries build step
/Libraries/Alert/Alert.js
/Libraries/Animated/src/nodes/AnimatedInterpolation.js
-/Libraries/Color/normalizeColor.js
-/Libraries/Color/normalizeColorObject.js
/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js
/Libraries/Components/Picker/Picker.js
/Libraries/Components/SafeAreaView/SafeAreaView.js
-/Libraries/Components/StatusBar/StatusBar.js
+/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.js
/Libraries/Components/TextInput/TextInput.js
/Libraries/Components/TextInput/TextInputState.js
+/Libraries/Components/Touchable/TouchableBounce.js
+/Libraries/Components/Touchable/TouchableHighlight.js
/Libraries/Components/Touchable/TouchableNativeFeedback.js
+/Libraries/Components/Touchable/TouchableOpacity.js
+/Libraries/Components/Touchable/TouchableWithoutFeedback.js
/Libraries/Components/View/ReactNativeViewAttributes.js
/Libraries/Components/View/ReactNativeViewViewConfig.js
/Libraries/Core/setUpDeveloperTools.js
+/Libraries/Core/setUpReactDevTools.js
/Libraries/Image/Image.js
+/Libraries/Image/ImageViewNativeComponent.js
/Libraries/Inspector/Inspector.js
/Libraries/Inspector/InspectorOverlay.js
/Libraries/Network/RCTNetworking.js
+/Libraries/Pressability/PressabilityDebug.js
/Libraries/ReactNative/getNativeComponentAttributes.js
+/Libraries/StyleSheet/normalizeColor.js
+/Libraries/StyleSheet/normalizeColorObject.js
/Libraries/StyleSheet/processColor.js
/Libraries/StyleSheet/processColorArray.js
/Libraries/StyleSheet/StyleSheet.js
@@ -39,10 +46,6 @@
/RNTester/js/components/ListExampleShared.js
/RNTester/js/components/RNTesterExampleFilter.js
-; These examples currently uses mac dynamic colors
-/RNTester/js/ActivityIndicatorExample.js
-/RNTester/js/DarkModeExample.js
-
; Schema files are used for turbo-module code generation, but are not bundled.
; We don't yet have the react-native-codegen package they rely on, so supress
; checks for now.
@@ -72,11 +75,6 @@
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
-; Ignore duplicate module providers
-; For RN Apps installed via npm, "Libraries" folder is inside
-; "node_modules/react-native" but in the source repo it is in the root
-.*/Libraries/react-native/React.js
-
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/warning')
.*/node_modules/warning/.*
@@ -102,7 +100,7 @@
../../node_modules/
[libs]
-Libraries/react-native/react-native-interface.js
+interface.js
flow/
[options]
@@ -115,34 +113,10 @@ module.file_ext=.js
module.file_ext=.json
module.file_ext=.win32.js
-module.system=haste
-module.system.haste.use_name_reducers=true
-# keep the following in sync with server/haste/hasteImpl.js
-# get basename
-module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
-# strip .js or .js.flow suffix
-module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
-# strip .ios suffix
-module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
-module.system.haste.name_reducers='^\(.*\)\.macos$' -> '\1'
-module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
-module.system.haste.name_reducers='^\(.*\)\.win32$' -> '\1'
-module.system.haste.name_reducers='^\(.*\)\.windesktop$' -> '\1'
-module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
-module.system.haste.paths.blacklist=/src/.*
-module.system.haste.paths.blacklist=.*/__tests__/.*
-module.system.haste.paths.blacklist=.*/__mocks__/.*
-module.system.haste.paths.whitelist=/Libraries/.*
-module.system.haste.paths.whitelist=/RNTester/.*
-module.system.haste.paths.whitelist=/IntegrationTests/.*
-module.system.haste.paths.blacklist=/Libraries/react-native/react-native-implementation.js
-module.system.haste.paths.blacklist=/Libraries/Animated/src/polyfills/.*
-module.system.haste.paths.blacklist=/Libraries/Image/resolveAssetSource.js
-
munge_underscores=true
-module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
-module.name_mapper='react-native$' -> '/Libraries/react-native/react-native-implementation.js'
+module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/Libraries/Image/RelativeImageStub'
+module.name_mapper='react-native$' -> '/index.js'
module.name_mapper='react-native/\(.*\)' -> '/\1'
suppress_type=$FlowIssue
@@ -153,8 +127,14 @@ suppress_type=$FlowFixMeEmpty
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
+suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_android\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
+suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_android\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
+experimental.well_formed_exports=true
+experimental.types_first=true
+experimental.abstract_locations=true
+
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
@@ -178,4 +158,4 @@ untyped-import
untyped-type-import
[version]
-^0.105.0
\ No newline at end of file
+^0.113.0
\ No newline at end of file
diff --git a/packages/react-native-win32/.gitignore b/packages/react-native-win32/.gitignore
index a16c2e663b4..08468799856 100644
--- a/packages/react-native-win32/.gitignore
+++ b/packages/react-native-win32/.gitignore
@@ -1,7 +1,7 @@
/dist
/flow
-/flow-typed
/index.*
+/interface.*
/IntegrationTests
/jest
/lib
@@ -9,4 +9,4 @@
/RNTester
/RNTester.*
/temp
-/WorkingHeaders
\ No newline at end of file
+/typings-index.*
diff --git a/packages/react-native-win32/CHANGELOG.json b/packages/react-native-win32/CHANGELOG.json
index 498a45f20d7..3c83cf0780f 100644
--- a/packages/react-native-win32/CHANGELOG.json
+++ b/packages/react-native-win32/CHANGELOG.json
@@ -1,6 +1,51 @@
{
"name": "@office-iss/react-native-win32",
"entries": [
+ {
+ "date": "Sat, 18 Apr 2020 00:04:34 GMT",
+ "tag": "@office-iss/react-native-win32_v0.0.0-master.6",
+ "version": "0.0.0-master.6",
+ "comments": {
+ "prerelease": [
+ {
+ "comment": "Implelent Shared StatusBarManagerModule and Do Module Cleanup",
+ "author": "ngerlem@microsoft.com",
+ "commit": "609c18ca016e9e4b5831890bad56309f02280566",
+ "package": "@office-iss/react-native-win32"
+ }
+ ]
+ }
+ },
+ {
+ "date": "Wed, 15 Apr 2020 22:26:36 GMT",
+ "tag": "@office-iss/react-native-win32_v0.0.0-master.5",
+ "version": "0.0.0-master.5",
+ "comments": {
+ "prerelease": [
+ {
+ "comment": "Use a custom resolver wrapper to allow metro to run for multiple platforms at once",
+ "author": "acoates@microsoft.com",
+ "commit": "d53d06aec7ddb8a17480a5e8dc9522e115792a64",
+ "package": "@office-iss/react-native-win32"
+ }
+ ]
+ }
+ },
+ {
+ "date": "Tue, 14 Apr 2020 14:59:17 GMT",
+ "tag": "@office-iss/react-native-win32_v0.0.0-master.4",
+ "version": "0.0.0-master.4",
+ "comments": {
+ "prerelease": [
+ {
+ "comment": "Upgrade to React Native 0.62",
+ "author": "ngerlem@microsoft.com",
+ "commit": "ae37f8e7518f808116ce906a7f7b32f00412612d",
+ "package": "@office-iss/react-native-win32"
+ }
+ ]
+ }
+ },
{
"date": "Thu, 09 Apr 2020 20:28:53 GMT",
"tag": "@office-iss/react-native-win32_v0.0.0-master.3",
diff --git a/packages/react-native-win32/CHANGELOG.md b/packages/react-native-win32/CHANGELOG.md
index 69875971cce..15432ae1647 100644
--- a/packages/react-native-win32/CHANGELOG.md
+++ b/packages/react-native-win32/CHANGELOG.md
@@ -1,9 +1,33 @@
# Change Log - @office-iss/react-native-win32
-This log was last generated on Fri, 03 Apr 2020 18:59:23 GMT and should not be manually modified.
+This log was last generated on Sat, 18 Apr 2020 00:04:34 GMT and should not be manually modified.
+## 0.0.0-master.6
+
+Sat, 18 Apr 2020 00:04:34 GMT
+
+### Changes
+
+- Implelent Shared StatusBarManagerModule and Do Module Cleanup (ngerlem@microsoft.com)
+
+## 0.0.0-master.5
+
+Wed, 15 Apr 2020 22:26:36 GMT
+
+### Changes
+
+- Use a custom resolver wrapper to allow metro to run for multiple platforms at once (acoates@microsoft.com)
+
+## 0.0.0-master.4
+
+Tue, 14 Apr 2020 14:59:17 GMT
+
+### Changes
+
+- Upgrade to React Native 0.62 (ngerlem@microsoft.com)
+
## 0.0.0-master.3
Fri, 03 Apr 2020 18:59:23 GMT
diff --git a/packages/react-native-win32/api-extractor.json b/packages/react-native-win32/api-extractor.json
index 98a562b21a7..2c856a25261 100644
--- a/packages/react-native-win32/api-extractor.json
+++ b/packages/react-native-win32/api-extractor.json
@@ -1,6 +1,6 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
- "mainEntryPointFilePath": "./Libraries/react-native/typings-main.d.ts",
+ "mainEntryPointFilePath": "./typings-index.d.ts",
"docModel": {
"enabled": true
},
diff --git a/packages/react-native-win32/etc/react-native-win32.api.md b/packages/react-native-win32/etc/react-native-win32.api.md
index 5a1a3a6eb99..656bdd6c40c 100644
--- a/packages/react-native-win32/etc/react-native-win32.api.md
+++ b/packages/react-native-win32/etc/react-native-win32.api.md
@@ -51,7 +51,7 @@ export type BasePropsWin32 = {
accessibilityActions?: ReadonlyArray;
};
-// Warning: (ae-forgotten-export) The symbol "IButtonWin32State" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "IButtonWin32State" needs to be exported by the entry point typings-index.d.ts
//
// @public
export class ButtonWin32 extends React_2.Component {
@@ -89,7 +89,7 @@ export interface IButtonWin32Props extends RN.ButtonProps {
style?: RN.StyleProp;
}
-// Warning: (ae-forgotten-export) The symbol "Omit" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "Omit" needs to be exported by the entry point typings-index.d.ts
//
// @public (undocumented)
export interface IButtonWin32Style extends Omit_4 {
@@ -106,7 +106,7 @@ export interface IDimensions {
width: number;
}
-// Warning: (ae-forgotten-export) The symbol "PartiallyRequired" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "PartiallyRequired" needs to be exported by the entry point typings-index.d.ts
//
// @public (undocumented)
export type IHandledKeyboardEvent = PartiallyRequired;
@@ -152,7 +152,7 @@ export interface IPersonaCoinProps extends ViewProps {
presence: PersonaCoinPresence;
// (undocumented)
size: PersonaCoinSize;
- // Warning: (ae-forgotten-export) The symbol "IImageSourceProps" needs to be exported by the entry point typings-main.d.ts
+ // Warning: (ae-forgotten-export) The symbol "IImageSourceProps" needs to be exported by the entry point typings-index.d.ts
//
// (undocumented)
source?: string | IImageSourceProps;
@@ -220,7 +220,7 @@ export type IStateConditions = {
[P in IState]: boolean;
};
-// Warning: (ae-forgotten-export) The symbol "Omit" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "Omit" needs to be exported by the entry point typings-index.d.ts
//
// @public (undocumented)
export interface ITextWin32Props extends Omit_3, BasePropsWin32 {
@@ -302,7 +302,7 @@ export interface ITouchInfo {
touchActive: boolean;
}
-// Warning: (ae-forgotten-export) The symbol "ISignalTransitions" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "ISignalTransitions" needs to be exported by the entry point typings-index.d.ts
//
// @public
export type ITransitions = {
@@ -315,7 +315,7 @@ export interface IViewWin32 {
focus: () => void;
}
-// Warning: (ae-forgotten-export) The symbol "Omit" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "Omit" needs to be exported by the entry point typings-index.d.ts
//
// @public
export interface IViewWin32Props extends Omit_2, BasePropsWin32 {
@@ -425,7 +425,7 @@ export class TextWin32 extends React_2.Component {
// @public (undocumented)
export type TextWin32OmitTypes = RN.TextPropsAndroid & RN.TextPropsIOS & RN.AccessibilityPropsAndroid & Omit_3 & OmittedAccessibilityPropsWin32;
-// Warning: (ae-forgotten-export) The symbol "IInternalTouchableWin32State" needs to be exported by the entry point typings-main.d.ts
+// Warning: (ae-forgotten-export) The symbol "IInternalTouchableWin32State" needs to be exported by the entry point typings-index.d.ts
//
// @public
export class TouchableWin32 extends React_2.Component {
diff --git a/packages/react-native-win32/just-task.js b/packages/react-native-win32/just-task.js
index e56e4b66486..ba25aa659cd 100644
--- a/packages/react-native-win32/just-task.js
+++ b/packages/react-native-win32/just-task.js
@@ -33,7 +33,7 @@ task('apiExtractorUpdate', apiExtractorUpdateTask());
task('apiDocumenter', () => {
require('child_process').execSync(
'npx @microsoft/api-documenter markdown -i temp -o docs/api',
- { stdio: 'inherit' },
+ {stdio: 'inherit'},
);
});
@@ -41,7 +41,7 @@ task('eslint', () => {
return eslintTask();
});
task('eslint:fix', () => {
- return eslintTask({ fix: true });
+ return eslintTask({fix: true});
});
task('copyFlowFiles', () => {
return copyTask(['src/**/*.js'], '.');
@@ -54,7 +54,7 @@ task('initRNLibraries', () => {
});
task('flow-check', () => {
- require('child_process').execSync('npx flow check', { stdio: 'inherit' });
+ require('child_process').execSync('npx flow check', {stdio: 'inherit'});
});
task('ts', () => {
@@ -70,8 +70,8 @@ task('ts', () => {
});
task('clean', () => {
return cleanTask(
- ['dist', 'flow', 'flow-typed', 'jest', 'Libraries', 'RNTester', 'lib'].map(
- p => path.join(process.cwd(), p),
+ ['dist', 'flow', 'jest', 'Libraries', 'RNTester'].map(p =>
+ path.join(process.cwd(), p),
),
);
});
diff --git a/packages/react-native-win32/metro-react-native-platform.js b/packages/react-native-win32/metro-react-native-platform.js
new file mode 100644
index 00000000000..c908a32c52c
--- /dev/null
+++ b/packages/react-native-win32/metro-react-native-platform.js
@@ -0,0 +1,41 @@
+/**
+ * @format
+ */
+const {resolve} = require('metro-resolver');
+
+/**
+ * platformImplementations is a map of platform to npm package that implements that platform
+ *
+ * Ex:
+ * {
+ * windows: 'react-native-windows'
+ * macos: 'react-native-macos'
+ * }
+ */
+function reactNativePlatformResolver(platformImplementations) {
+ return (context, _realModuleName, platform, moduleName) => {
+ let backupResolveRequest = context.resolveRequest;
+ delete context.resolveRequest;
+
+ try {
+ let modifiedModuleName = moduleName;
+ if (platformImplementations[platform]) {
+ if (moduleName === 'react-native') {
+ modifiedModuleName = platformImplementations[platform];
+ } else if (moduleName.startsWith('react-native/')) {
+ modifiedModuleName = `${
+ platformImplementations[platform]
+ }/${modifiedModuleName.slice('react-native/'.length)}`;
+ }
+ }
+ let result = resolve(context, modifiedModuleName, platform);
+ context.resolveRequest = backupResolveRequest;
+ return result;
+ } catch (e) {
+ context.resolveRequest = backupResolveRequest;
+ throw e;
+ }
+ };
+}
+
+module.exports = {reactNativePlatformResolver};
diff --git a/packages/react-native-win32/metro.config.js b/packages/react-native-win32/metro.config.js
index 6b24f49cc0c..c15ae2c5ca5 100644
--- a/packages/react-native-win32/metro.config.js
+++ b/packages/react-native-win32/metro.config.js
@@ -3,14 +3,6 @@
*/
const fs = require('fs');
const path = require('path');
-const blacklist = require('metro-config/src/defaults/blacklist');
-
-const rnPath = fs.realpathSync(
- fs.realpathSync(
- path.resolve(require.resolve('react-native/package.json'), '..'),
- ),
-);
-const rnw32Path = __dirname;
module.exports = {
// WatchFolders is only needed due to the yarn workspace layout of node_modules, we need to watch the symlinked locations separately
@@ -20,36 +12,14 @@ module.exports = {
],
resolver: {
- extraNodeModules: {
- // Redirect react-native and react-native-windows to this folder
- 'react-native': rnw32Path,
- 'react-native-win32': rnw32Path,
- },
- // Include the macos platform in addition to the defaults because the fork includes macos, but doesn't declare it
- platforms: [
- 'ios',
- 'android',
- 'windesktop',
- 'windows',
- 'web',
- 'macos',
- 'win32',
- ],
- // Since there are multiple copies of react-native, we need to ensure that metro only sees one of them
- // This should go away after RN 0.61 when haste is removed
- blacklistRE: blacklist([
- new RegExp(`${path.resolve(rnPath).replace(/[/\\]/g, '/')}.*`),
- new RegExp(
- `${path
- .resolve(
- require.resolve('@react-native-community/cli/package.json'),
- '../node_modules/react-native',
- )
- .replace(/[/\\]/g, '/')}.*`,
- ),
- ]),
+ resolveRequest: require('./metro-react-native-platform').reactNativePlatformResolver(
+ {win32: '@office-iss/react-native-win32'},
+ ),
},
transformer: {
+ // The cli defaults this to a full path to react-native, which bypasses the reactNativePlatformResolver above
+ // Hopefully we can fix the default in the future
+ assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
diff --git a/packages/react-native-win32/package.json b/packages/react-native-win32/package.json
index 5e8ad7cfb8d..9f18e975354 100644
--- a/packages/react-native-win32/package.json
+++ b/packages/react-native-win32/package.json
@@ -1,10 +1,10 @@
{
"name": "@office-iss/react-native-win32",
- "version": "0.0.0-master.3",
+ "version": "0.0.0-master.6",
"description": "Implementation of react native on top of Office's Win32 platform.",
"license": "MIT",
- "main": "./Libraries/react-native/react-native-implementation.win32.js",
- "typings": "./Libraries/react-native/typings-main.d.ts",
+ "main": "./index.win32.js",
+ "typings": "./typings-index.d.ts",
"scripts": {
"build": "just-scripts build",
"bundle": "just-scripts prepareBundle && react-native bundle --platform win32 --entry-file RNTester.js --bundle-output dist/win32/dev/RNTester.bundle --assets-dest dist/win32/dev --sourcemap-output ./dist/win32/dev/sourcemap.js",
@@ -49,20 +49,20 @@
"@types/node": "^12.11.2",
"@types/prop-types": "15.5.1",
"@types/react": "16.9.0",
- "@types/react-native": "~0.61.5",
- "flow-bin": "^0.105.0",
+ "@types/react-native": "^0.62.2",
+ "flow-bin": "^0.113.0",
"jscodeshift": "^0.6.2",
"just-scripts": "^0.36.1",
"react": "16.9.0",
"react-native-windows-override-tools": "^0.0.1",
- "react-native": "0.61.5",
+ "react-native": "0.62.2",
"rimraf": "^3.0.0",
"typescript": "^3.8.3"
},
"peerDependencies": {
"react": "16.9.0",
"react-dom": "16.8.6",
- "react-native": "0.61.5"
+ "react-native": "0.62.2"
},
"beachball": {
"defaultNpmTag": "master",
diff --git a/packages/react-native-win32/react-native.config.js b/packages/react-native-win32/react-native.config.js
index 74538a4cf09..6c2312774ef 100644
--- a/packages/react-native-win32/react-native.config.js
+++ b/packages/react-native-win32/react-native.config.js
@@ -8,8 +8,4 @@ module.exports = {
dependencyConfig: (projectRoot, dependencyParams) => null,
},
},
-
- // *****
- // This is only used when building bundles within react-native-win32.
- reactNativePath: '.',
};
diff --git a/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js b/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js
index 935e8956f96..6ab36927761 100644
--- a/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js
+++ b/packages/react-native-win32/src/Libraries/Alert/Alert.win32.js
@@ -25,11 +25,13 @@ export type Buttons = Array<{
text?: string,
onPress?: ?Function,
style?: AlertButtonStyle,
+ ...
}>;
type Options = {
cancelable?: ?boolean,
onDismiss?: ?() => void,
+ ...
};
/**
diff --git a/packages/react-native-win32/src/Libraries/Animated/src/nodes/AnimatedInterpolation.win32.js b/packages/react-native-win32/src/Libraries/Animated/src/nodes/AnimatedInterpolation.win32.js
index daf3c0961af..b6c9c3eac4f 100644
--- a/packages/react-native-win32/src/Libraries/Animated/src/nodes/AnimatedInterpolation.win32.js
+++ b/packages/react-native-win32/src/Libraries/Animated/src/nodes/AnimatedInterpolation.win32.js
@@ -7,7 +7,9 @@
* @flow
* @format
*/
+
/* eslint no-bitwise: 0 */
+
'use strict';
const AnimatedNode = require('./AnimatedNode');
@@ -15,7 +17,7 @@ const AnimatedWithChildren = require('./AnimatedWithChildren');
const NativeAnimatedHelper = require('../NativeAnimatedHelper');
const invariant = require('invariant');
-const normalizeColor = require('../../../Color/normalizeColor');
+const normalizeColor = require('../../../StyleSheet/normalizeColor');
type ExtrapolateType = 'extend' | 'identity' | 'clamp';
@@ -30,6 +32,7 @@ export type InterpolationConfigType = {
extrapolate?: ExtrapolateType,
extrapolateLeft?: ExtrapolateType,
extrapolateRight?: ExtrapolateType,
+ ...
};
const linear = t => t;
diff --git a/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.win32.js b/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.win32.js
index c91a8d97049..aed6e3ff734 100644
--- a/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/AccessibilityInfo.win32.js
@@ -10,8 +10,6 @@
'use strict';
-import NativeAccessibilityInfo from './NativeAccessibilityInfo';
-
const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter');
// [Windows
@@ -20,6 +18,8 @@ const RCTDeviceEventEmitter = require('../../EventEmitter/RCTDeviceEventEmitter'
const SCREEN_READER_CHANGED_EVENT = 'screenReaderChanged';
// Windows]
+import NativeAccessibilityInfo from './NativeAccessibilityInfo';
+
const REDUCE_MOTION_EVENT = 'reduceMotionDidChange';
const TOUCH_EXPLORATION_EVENT = 'touchExplorationDidChange';
@@ -27,6 +27,7 @@ type ChangeEventName = $Keys<{
change: string,
reduceMotionChanged: string,
screenReaderChanged: string,
+ ...
}>;
const _subscriptions = new Map();
@@ -97,7 +98,10 @@ const AccessibilityInfo = {
*
* Same as `isScreenReaderEnabled`
*/
- get fetch() {
+ get fetch(): () => Promise {
+ console.warn(
+ 'AccessibilityInfo.fetch is deprecated, call Accessibility.isScreenReaderEnabled instead',
+ );
return this.isScreenReaderEnabled;
},
diff --git a/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.win32.js b/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.win32.js
index 3b1fcbdae29..4ce7ce954ba 100644
--- a/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.win32.js
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @flow
+ * @flow strict-local
* @format
*/
diff --git a/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js b/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js
index f6d4cd7a409..c7a621c5054 100644
--- a/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/MaskedView/MaskedViewIOS.win32.js
@@ -2,6 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
* @format
+ * @flow strict-local
*/
'use strict';
diff --git a/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js b/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js
index b748c6db52b..905864aa732 100644
--- a/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/SafeAreaView/SafeAreaView.win32.js
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @flow
+ * @flow strict-local
* @format
*/
@@ -12,7 +12,7 @@ const Platform = require('../../Utilities/Platform');
const React = require('react');
const View = require('../View/View');
-import type {NativeComponent} from '../../Renderer/shims/ReactNative';
+import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {ViewProps} from '../View/ViewPropTypes';
type Props = $ReadOnly<{|
@@ -20,7 +20,10 @@ type Props = $ReadOnly<{|
emulateUnlessSupported?: boolean,
|}>;
-let exported: Class> | Class>;
+let exported: React.AbstractComponent<
+ Props,
+ React.ElementRef>,
+>;
/**
* Renders nested content and automatically applies paddings reflect the portion
@@ -34,37 +37,27 @@ let exported: Class> | Class>;
// [Win32 - Added win32 to if
if (Platform.OS === 'android' || Platform.OS === 'win32') {
// Win32]
- const SafeAreaView = (
- props: Props,
- forwardedRef?: ?React.Ref,
- ) => {
- const {emulateUnlessSupported, ...localProps} = props;
- return ;
- };
-
- const SafeAreaViewRef = React.forwardRef(SafeAreaView);
- SafeAreaViewRef.displayName = 'SafeAreaView';
- exported = ((SafeAreaViewRef: any): Class>);
+ exported = React.forwardRef>>(
+ function SafeAreaView(props, forwardedRef) {
+ const {emulateUnlessSupported, ...localProps} = props;
+ return ;
+ },
+ );
} else {
const RCTSafeAreaViewNativeComponent = require('./RCTSafeAreaViewNativeComponent')
.default;
- const SafeAreaView = (
- props: Props,
- forwardedRef?: ?React.Ref,
- ) => {
- return (
-
- );
- };
-
- const SafeAreaViewRef = React.forwardRef(SafeAreaView);
- SafeAreaViewRef.displayName = 'SafeAreaView';
- exported = ((SafeAreaViewRef: any): Class>);
+ exported = React.forwardRef>>(
+ function SafeAreaView(props, forwardedRef) {
+ return (
+
+ );
+ },
+ );
}
module.exports = exported;
diff --git a/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollView.win32.js b/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollView.win32.js
new file mode 100644
index 00000000000..5f71d0ee231
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/ScrollView/ScrollView.win32.js
@@ -0,0 +1,1236 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @format
+ * @flow strict-local
+ */
+
+'use strict';
+
+const AnimatedImplementation = require('../../Animated/src/AnimatedImplementation');
+const Platform = require('../../Utilities/Platform');
+const React = require('react');
+const ReactNative = require('../../Renderer/shims/ReactNative');
+require('../../Renderer/shims/ReactNative'); // Force side effects to prevent T55744311
+const ScrollResponder = require('../ScrollResponder');
+const ScrollViewStickyHeader = require('./ScrollViewStickyHeader');
+const StyleSheet = require('../../StyleSheet/StyleSheet');
+const View = require('../View/View');
+
+const dismissKeyboard = require('../../Utilities/dismissKeyboard');
+const flattenStyle = require('../../StyleSheet/flattenStyle');
+const invariant = require('invariant');
+const processDecelerationRate = require('./processDecelerationRate');
+const requireNativeComponent = require('../../ReactNative/requireNativeComponent');
+const resolveAssetSource = require('../../Image/resolveAssetSource');
+const splitLayoutProps = require('../../StyleSheet/splitLayoutProps');
+
+import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType';
+import type {PointProp} from '../../StyleSheet/PointPropType';
+import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
+import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
+import type {
+ PressEvent,
+ ScrollEvent,
+ LayoutEvent,
+} from '../../Types/CoreEventTypes';
+import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
+import type {State as ScrollResponderState} from '../ScrollResponder';
+import type {ViewProps} from '../View/ViewPropTypes';
+import type {Props as ScrollViewStickyHeaderProps} from './ScrollViewStickyHeader';
+
+import ScrollViewNativeComponent from './ScrollViewNativeComponent';
+import ScrollContentViewNativeComponent from './ScrollContentViewNativeComponent';
+import AndroidHorizontalScrollViewNativeComponent from './AndroidHorizontalScrollViewNativeComponent';
+import AndroidHorizontalScrollContentViewNativeComponent from './AndroidHorizontalScrollContentViewNativeComponent';
+
+let AndroidScrollView;
+let AndroidHorizontalScrollContentView;
+let AndroidHorizontalScrollView;
+let RCTScrollView;
+let RCTScrollContentView;
+
+if (Platform.OS === 'android') {
+ AndroidScrollView = ScrollViewNativeComponent;
+ AndroidHorizontalScrollView = AndroidHorizontalScrollViewNativeComponent;
+ AndroidHorizontalScrollContentView = AndroidHorizontalScrollContentViewNativeComponent;
+} else { // [Windows] Remove iOS check
+ RCTScrollView = ScrollViewNativeComponent;
+ RCTScrollContentView = ScrollContentViewNativeComponent;
+}
+
+export type ScrollResponderType = {
+ // We'd like to do ...ScrollView here, however Flow doesn't seem
+ // to see the imperative methods of ScrollView that way. Workaround the
+ // issue by specifying them manually.
+ getScrollableNode: $PropertyType,
+ getInnerViewNode: $PropertyType,
+ getInnerViewRef: $PropertyType,
+ getNativeScrollRef: $PropertyType,
+ setNativeProps: $PropertyType,
+ scrollTo: $PropertyType,
+ flashScrollIndicators: $PropertyType,
+ ...typeof ScrollResponder.Mixin,
+ ...
+};
+
+type IOSProps = $ReadOnly<{|
+ /**
+ * Controls whether iOS should automatically adjust the content inset
+ * for scroll views that are placed behind a navigation bar or
+ * tab bar/ toolbar. The default value is true.
+ * @platform ios
+ */
+ automaticallyAdjustContentInsets?: ?boolean,
+ /**
+ * The amount by which the scroll view content is inset from the edges
+ * of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`.
+ * @platform ios
+ */
+ contentInset?: ?EdgeInsetsProp,
+ /**
+ * Used to manually set the starting scroll offset.
+ * The default value is `{x: 0, y: 0}`.
+ * @platform ios
+ */
+ contentOffset?: ?PointProp,
+ /**
+ * When true, the scroll view bounces when it reaches the end of the
+ * content if the content is larger then the scroll view along the axis of
+ * the scroll direction. When false, it disables all bouncing even if
+ * the `alwaysBounce*` props are true. The default value is true.
+ * @platform ios
+ */
+ bounces?: ?boolean,
+ /**
+ * By default, ScrollView has an active pan responder that hijacks panresponders
+ * deeper in the render tree in order to prevent accidental touches while scrolling.
+ * However, in certain occasions (such as when using snapToInterval) in a vertical scrollview
+ * You may want to disable this behavior in order to prevent the ScrollView from blocking touches
+ */
+ disableScrollViewPanResponder?: ?boolean,
+ /**
+ * When true, gestures can drive zoom past min/max and the zoom will animate
+ * to the min/max value at gesture end, otherwise the zoom will not exceed
+ * the limits.
+ * @platform ios
+ */
+ bouncesZoom?: ?boolean,
+ /**
+ * When true, the scroll view bounces horizontally when it reaches the end
+ * even if the content is smaller than the scroll view itself. The default
+ * value is true when `horizontal={true}` and false otherwise.
+ * @platform ios
+ */
+ alwaysBounceHorizontal?: ?boolean,
+ /**
+ * When true, the scroll view bounces vertically when it reaches the end
+ * even if the content is smaller than the scroll view itself. The default
+ * value is false when `horizontal={true}` and true otherwise.
+ * @platform ios
+ */
+ alwaysBounceVertical?: ?boolean,
+ /**
+ * When true, the scroll view automatically centers the content when the
+ * content is smaller than the scroll view bounds; when the content is
+ * larger than the scroll view, this property has no effect. The default
+ * value is false.
+ * @platform ios
+ */
+ centerContent?: ?boolean,
+ /**
+ * The style of the scroll indicators.
+ *
+ * - `'default'` (the default), same as `black`.
+ * - `'black'`, scroll indicator is black. This style is good against a light background.
+ * - `'white'`, scroll indicator is white. This style is good against a dark background.
+ *
+ * @platform ios
+ */
+ indicatorStyle?: ?('default' | 'black' | 'white'),
+ /**
+ * When true, the ScrollView will try to lock to only vertical or horizontal
+ * scrolling while dragging. The default value is false.
+ * @platform ios
+ */
+ directionalLockEnabled?: ?boolean,
+ /**
+ * When false, once tracking starts, won't try to drag if the touch moves.
+ * The default value is true.
+ * @platform ios
+ */
+ canCancelContentTouches?: ?boolean,
+ /**
+ * When set, the scroll view will adjust the scroll position so that the first child that is
+ * currently visible and at or beyond `minIndexForVisible` will not change position. This is
+ * useful for lists that are loading content in both directions, e.g. a chat thread, where new
+ * messages coming in might otherwise cause the scroll position to jump. A value of 0 is common,
+ * but other values such as 1 can be used to skip loading spinners or other content that should
+ * not maintain position.
+ *
+ * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll
+ * to the top after making the adjustment if the user was within the threshold of the top before
+ * the adjustment was made. This is also useful for chat-like applications where you want to see
+ * new messages scroll into place, but not if the user has scrolled up a ways and it would be
+ * disruptive to scroll a bunch.
+ *
+ * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause
+ * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now,
+ * don't re-order the content of any ScrollViews or Lists that use this feature.
+ *
+ * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute
+ * visibility. Occlusion, transforms, and other complexity won't be taken into account as to
+ * whether content is "visible" or not.
+ *
+ * @platform ios
+ */
+ maintainVisibleContentPosition?: ?$ReadOnly<{|
+ minIndexForVisible: number,
+ autoscrollToTopThreshold?: ?number,
+ |}>,
+ /**
+ * The maximum allowed zoom scale. The default value is 1.0.
+ * @platform ios
+ */
+ maximumZoomScale?: ?number,
+ /**
+ * The minimum allowed zoom scale. The default value is 1.0.
+ * @platform ios
+ */
+ minimumZoomScale?: ?number,
+ /**
+ * When true, ScrollView allows use of pinch gestures to zoom in and out.
+ * The default value is true.
+ * @platform ios
+ */
+ pinchGestureEnabled?: ?boolean,
+ /**
+ * This controls how often the scroll event will be fired while scrolling
+ * (as a time interval in ms). A lower number yields better accuracy for code
+ * that is tracking the scroll position, but can lead to scroll performance
+ * problems due to the volume of information being send over the bridge.
+ *
+ * Values between 0 and 17ms indicate 60fps updates are needed and throttling
+ * will be disabled.
+ *
+ * If you do not need precise scroll position tracking, set this value higher
+ * to limit the information being sent across the bridge.
+ *
+ * The default value is zero, which results in the scroll event being sent only
+ * once each time the view is scrolled.
+ *
+ * @platform ios
+ */
+ scrollEventThrottle?: ?number,
+ /**
+ * The amount by which the scroll view indicators are inset from the edges
+ * of the scroll view. This should normally be set to the same value as
+ * the `contentInset`. Defaults to `{0, 0, 0, 0}`.
+ * @platform ios
+ */
+ scrollIndicatorInsets?: ?EdgeInsetsProp,
+ /**
+ * When true, the scroll view can be programmatically scrolled beyond its
+ * content size. The default value is false.
+ * @platform ios
+ */
+ scrollToOverflowEnabled?: ?boolean,
+ /**
+ * When true, the scroll view scrolls to top when the status bar is tapped.
+ * The default value is true.
+ * @platform ios
+ */
+ scrollsToTop?: ?boolean,
+ /**
+ * Fires when the scroll view scrolls to top after the status bar has been tapped
+ * @platform ios
+ */
+ onScrollToTop?: (event: ScrollEvent) => void,
+ /**
+ * When true, shows a horizontal scroll indicator.
+ * The default value is true.
+ */
+ showsHorizontalScrollIndicator?: ?boolean,
+ /**
+ * When `snapToInterval` is set, `snapToAlignment` will define the relationship
+ * of the snapping to the scroll view.
+ *
+ * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical)
+ * - `'center'` will align the snap in the center
+ * - `'end'` will align the snap at the right (horizontal) or bottom (vertical)
+ *
+ * @platform ios
+ */
+ snapToAlignment?: ?('start' | 'center' | 'end'),
+ /**
+ * The current scale of the scroll view content. The default value is 1.0.
+ * @platform ios
+ */
+ zoomScale?: ?number,
+ /**
+ * This property specifies how the safe area insets are used to modify the
+ * content area of the scroll view. The default value of this property is
+ * "never". Available on iOS 11 and later.
+ * @platform ios
+ */
+ contentInsetAdjustmentBehavior?: ?(
+ | 'automatic'
+ | 'scrollableAxes'
+ | 'never'
+ | 'always'
+ ),
+ /**
+ * When true, ScrollView will emit updateChildFrames data in scroll events,
+ * otherwise will not compute or emit child frame data. This only exists
+ * to support legacy issues, `onLayout` should be used instead to retrieve
+ * frame data.
+ * The default value is false.
+ * @platform ios
+ */
+ DEPRECATED_sendUpdatedChildFrames?: ?boolean,
+|}>;
+
+type AndroidProps = $ReadOnly<{|
+ /**
+ * Enables nested scrolling for Android API level 21+.
+ * Nested scrolling is supported by default on iOS
+ * @platform android
+ */
+ nestedScrollEnabled?: ?boolean,
+ /**
+ * Sometimes a scrollview takes up more space than its content fills. When this is
+ * the case, this prop will fill the rest of the scrollview with a color to avoid setting
+ * a background and creating unnecessary overdraw. This is an advanced optimization
+ * that is not needed in the general case.
+ * @platform android
+ */
+ endFillColor?: ?ColorValue,
+ /**
+ * Tag used to log scroll performance on this scroll view. Will force
+ * momentum events to be turned on (see sendMomentumEvents). This doesn't do
+ * anything out of the box and you need to implement a custom native
+ * FpsListener for it to be useful.
+ * @platform android
+ */
+ scrollPerfTag?: ?string,
+ /**
+ * Used to override default value of overScroll mode.
+ *
+ * Possible values:
+ *
+ * - `'auto'` - Default value, allow a user to over-scroll
+ * this view only if the content is large enough to meaningfully scroll.
+ * - `'always'` - Always allow a user to over-scroll this view.
+ * - `'never'` - Never allow a user to over-scroll this view.
+ *
+ * @platform android
+ */
+ overScrollMode?: ?('auto' | 'always' | 'never'),
+ /**
+ * Causes the scrollbars not to turn transparent when they are not in use.
+ * The default value is false.
+ *
+ * @platform android
+ */
+ persistentScrollbar?: ?boolean,
+ /**
+ * Fades out the edges of the the scroll content.
+ *
+ * If the value is greater than 0, the fading edges will be set accordingly
+ * to the current scroll direction and position,
+ * indicating if there is more content to show.
+ *
+ * The default value is 0.
+ *
+ * @platform android
+ */
+ fadingEdgeLength?: ?number,
+|}>;
+
+type VRProps = $ReadOnly<{|
+ /**
+ * Optionally an image can be used for the scroll bar thumb. This will
+ * override the color. While the image is loading or the image fails to
+ * load the color will be used instead. Use an alpha of 0 in the color
+ * to avoid seeing it while the image is loading.
+ *
+ * - `uri` - a string representing the resource identifier for the image, which
+ * should be either a local file path or the name of a static image resource
+ * - `number` - Opaque type returned by something like
+ * `import IMAGE from './image.jpg'`.
+ * @platform vr
+ */
+ scrollBarThumbImage?: ?($ReadOnly<{||}> | number), // Opaque type returned by import IMAGE from './image.jpg'
+|}>;
+
+type StickyHeaderComponentType = React.AbstractComponent<
+ ScrollViewStickyHeaderProps,
+ $ReadOnly<{setNextHeaderY: number => void, ...}>,
+>;
+
+export type Props = $ReadOnly<{|
+ ...ViewProps,
+ ...IOSProps,
+ ...AndroidProps,
+ ...VRProps,
+
+ /**
+ * These styles will be applied to the scroll view content container which
+ * wraps all of the child views. Example:
+ *
+ * ```
+ * return (
+ *
+ *
+ * );
+ * ...
+ * const styles = StyleSheet.create({
+ * contentContainer: {
+ * paddingVertical: 20
+ * }
+ * });
+ * ```
+ */
+ contentContainerStyle?: ?ViewStyleProp,
+ /**
+ * When true, the scroll view stops on the next index (in relation to scroll
+ * position at release) regardless of how fast the gesture is. This can be
+ * used for horizontal pagination when the page is less than the width of
+ * the ScrollView. The default value is false.
+ */
+ disableIntervalMomentum?: ?boolean,
+ /**
+ * A floating-point number that determines how quickly the scroll view
+ * decelerates after the user lifts their finger. You may also use string
+ * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings
+ * for `UIScrollViewDecelerationRateNormal` and
+ * `UIScrollViewDecelerationRateFast` respectively.
+ *
+ * - `'normal'`: 0.998 on iOS, 0.985 on Android (the default)
+ * - `'fast'`: 0.99 on iOS, 0.9 on Android
+ */
+ decelerationRate?: ?('fast' | 'normal' | number),
+ /**
+ * When true, the scroll view's children are arranged horizontally in a row
+ * instead of vertically in a column. The default value is false.
+ */
+ horizontal?: ?boolean,
+ /**
+ * If sticky headers should stick at the bottom instead of the top of the
+ * ScrollView. This is usually used with inverted ScrollViews.
+ */
+ invertStickyHeaders?: ?boolean,
+ /**
+ * Determines whether the keyboard gets dismissed in response to a drag.
+ *
+ * *Cross platform*
+ *
+ * - `'none'` (the default), drags do not dismiss the keyboard.
+ * - `'on-drag'`, the keyboard is dismissed when a drag begins.
+ *
+ * *iOS Only*
+ *
+ * - `'interactive'`, the keyboard is dismissed interactively with the drag and moves in
+ * synchrony with the touch; dragging upwards cancels the dismissal.
+ * On android this is not supported and it will have the same behavior as 'none'.
+ */
+ keyboardDismissMode?: ?// default
+ (| 'none' // cross-platform
+ | 'on-drag'
+ | 'interactive'
+ ), // ios only
+ /**
+ * Determines when the keyboard should stay visible after a tap.
+ *
+ * - `'never'` (the default), tapping outside of the focused text input when the keyboard
+ * is up dismisses the keyboard. When this happens, children won't receive the tap.
+ * - `'always'`, the keyboard will not dismiss automatically, and the scroll view will not
+ * catch taps, but children of the scroll view can catch taps.
+ * - `'handled'`, the keyboard will not dismiss automatically when the tap was handled by
+ * a children, (or captured by an ancestor).
+ * - `false`, deprecated, use 'never' instead
+ * - `true`, deprecated, use 'always' instead
+ */
+ keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | true | false),
+ /**
+ * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop).
+ */
+ onMomentumScrollBegin?: ?(event: ScrollEvent) => void,
+ /**
+ * Called when the momentum scroll ends (scroll which occurs as the ScrollView glides to a stop).
+ */
+ onMomentumScrollEnd?: ?(event: ScrollEvent) => void,
+
+ /**
+ * Fires at most once per frame during scrolling. The frequency of the
+ * events can be controlled using the `scrollEventThrottle` prop.
+ */
+ onScroll?: ?(event: ScrollEvent) => void,
+ /**
+ * Called when the user begins to drag the scroll view.
+ */
+ onScrollBeginDrag?: ?(event: ScrollEvent) => void,
+ /**
+ * Called when the user stops dragging the scroll view and it either stops
+ * or begins to glide.
+ */
+ onScrollEndDrag?: ?(event: ScrollEvent) => void,
+ /**
+ * Called when scrollable content view of the ScrollView changes.
+ *
+ * Handler function is passed the content width and content height as parameters:
+ * `(contentWidth, contentHeight)`
+ *
+ * It's implemented using onLayout handler attached to the content container
+ * which this ScrollView renders.
+ */
+ onContentSizeChange?: (contentWidth: number, contentHeight: number) => void,
+ onKeyboardDidShow?: (event: PressEvent) => void,
+ /**
+ * When true, the scroll view stops on multiples of the scroll view's size
+ * when scrolling. This can be used for horizontal pagination. The default
+ * value is false.
+ *
+ * Note: Vertical pagination is not supported on Android.
+ */
+ pagingEnabled?: ?boolean,
+
+ /**
+ * When false, the view cannot be scrolled via touch interaction.
+ * The default value is true.
+ *
+ * Note that the view can always be scrolled by calling `scrollTo`.
+ */
+ scrollEnabled?: ?boolean,
+ /**
+ * When true, shows a vertical scroll indicator.
+ * The default value is true.
+ */
+ showsVerticalScrollIndicator?: ?boolean,
+ /**
+ * An array of child indices determining which children get docked to the
+ * top of the screen when scrolling. For example, passing
+ * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the
+ * top of the scroll view. This property is not supported in conjunction
+ * with `horizontal={true}`.
+ */
+ stickyHeaderIndices?: ?$ReadOnlyArray,
+ /**
+ * A React Component that will be used to render sticky headers.
+ * To be used together with `stickyHeaderIndices` or with `SectionList`, defaults to `ScrollViewStickyHeader`.
+ * You may need to set this if your sticky header uses custom transforms (eg. translation),
+ * for example when you want your list to have an animated hidable header.
+ */
+ StickyHeaderComponent?: StickyHeaderComponentType,
+ /**
+ * When set, causes the scroll view to stop at multiples of the value of
+ * `snapToInterval`. This can be used for paginating through children
+ * that have lengths smaller than the scroll view. Typically used in
+ * combination with `snapToAlignment` and `decelerationRate="fast"`.
+ *
+ * Overrides less configurable `pagingEnabled` prop.
+ */
+ snapToInterval?: ?number,
+ /**
+ * When set, causes the scroll view to stop at the defined offsets.
+ * This can be used for paginating through variously sized children
+ * that have lengths smaller than the scroll view. Typically used in
+ * combination with `decelerationRate="fast"`.
+ *
+ * Overrides less configurable `pagingEnabled` and `snapToInterval` props.
+ */
+ snapToOffsets?: ?$ReadOnlyArray,
+ /**
+ * Use in conjunction with `snapToOffsets`. By default, the beginning
+ * of the list counts as a snap offset. Set `snapToStart` to false to disable
+ * this behavior and allow the list to scroll freely between its start and
+ * the first `snapToOffsets` offset.
+ * The default value is true.
+ */
+ snapToStart?: ?boolean,
+ /**
+ * Use in conjunction with `snapToOffsets`. By default, the end
+ * of the list counts as a snap offset. Set `snapToEnd` to false to disable
+ * this behavior and allow the list to scroll freely between its end and
+ * the last `snapToOffsets` offset.
+ * The default value is true.
+ */
+ snapToEnd?: ?boolean,
+ /**
+ * Experimental: When true, offscreen child views (whose `overflow` value is
+ * `hidden`) are removed from their native backing superview when offscreen.
+ * This can improve scrolling performance on long lists. The default value is
+ * true.
+ */
+ removeClippedSubviews?: ?boolean,
+ /**
+ * A RefreshControl component, used to provide pull-to-refresh
+ * functionality for the ScrollView. Only works for vertical ScrollViews
+ * (`horizontal` prop must be `false`).
+ *
+ * See [RefreshControl](docs/refreshcontrol.html).
+ */
+ // $FlowFixMe - how to handle generic type without existential operator?
+ refreshControl?: ?React.Element,
+ children?: React.Node,
+|}>;
+
+type State = {|
+ layoutHeight: ?number,
+ ...ScrollResponderState,
+|};
+
+function createScrollResponder(
+ node: React.ElementRef,
+): typeof ScrollResponder.Mixin {
+ const scrollResponder = {...ScrollResponder.Mixin};
+
+ for (const key in scrollResponder) {
+ if (typeof scrollResponder[key] === 'function') {
+ scrollResponder[key] = scrollResponder[key].bind(node);
+ }
+ }
+
+ return scrollResponder;
+}
+
+type ContextType = {|horizontal: boolean|} | null;
+const Context = React.createContext(null);
+const standardHorizontalContext: ContextType = Object.freeze({
+ horizontal: true,
+});
+const standardVerticalContext: ContextType = Object.freeze({horizontal: false});
+
+/**
+ * Component that wraps platform ScrollView while providing
+ * integration with touch locking "responder" system.
+ *
+ * Keep in mind that ScrollViews must have a bounded height in order to work,
+ * since they contain unbounded-height children into a bounded container (via
+ * a scroll interaction). In order to bound the height of a ScrollView, either
+ * set the height of the view directly (discouraged) or make sure all parent
+ * views have bounded height. Forgetting to transfer `{flex: 1}` down the
+ * view stack can lead to errors here, which the element inspector makes
+ * easy to debug.
+ *
+ * Doesn't yet support other contained responders from blocking this scroll
+ * view from becoming the responder.
+ *
+ *
+ * `` vs [``](/react-native/docs/flatlist.html) - which one to use?
+ *
+ * `ScrollView` simply renders all its react child components at once. That
+ * makes it very easy to understand and use.
+ *
+ * On the other hand, this has a performance downside. Imagine you have a very
+ * long list of items you want to display, maybe several screens worth of
+ * content. Creating JS components and native views for everything all at once,
+ * much of which may not even be shown, will contribute to slow rendering and
+ * increased memory usage.
+ *
+ * This is where `FlatList` comes into play. `FlatList` renders items lazily,
+ * just when they are about to appear, and removes items that scroll way off
+ * screen to save memory and processing time.
+ *
+ * `FlatList` is also handy if you want to render separators between your items,
+ * multiple columns, infinite scroll loading, or any number of other features it
+ * supports out of the box.
+ */
+class ScrollView extends React.Component {
+ static Context: React$Context = Context;
+ /**
+ * Part 1: Removing ScrollResponder.Mixin:
+ *
+ * 1. Mixin methods should be flow typed. That's why we create a
+ * copy of ScrollResponder.Mixin and attach it to this._scrollResponder.
+ * Otherwise, we'd have to manually declare each method on the component
+ * class and assign it a flow type.
+ * 2. Mixin methods can call component methods, and access the component's
+ * props and state. So, we need to bind all mixin methods to the
+ * component instance.
+ * 3. Continued...
+ */
+ _scrollResponder: typeof ScrollResponder.Mixin = createScrollResponder(this);
+
+ constructor(props: Props) {
+ super(props);
+
+ /**
+ * Part 2: Removing ScrollResponder.Mixin
+ *
+ * 3. Mixin methods access other mixin methods via dynamic dispatch using
+ * this. Since mixin methods are bound to the component instance, we need
+ * to copy all mixin methods to the component instance. This is also
+ * necessary because getScrollResponder() is a public method that returns
+ * an object that can be used to execute all scrollResponder methods.
+ * Since the object returned from that method is the ScrollView instance,
+ * we need to bind all mixin methods to the ScrollView instance.
+ */
+ for (const key in ScrollResponder.Mixin) {
+ if (
+ typeof ScrollResponder.Mixin[key] === 'function' &&
+ key.startsWith('scrollResponder')
+ ) {
+ // $FlowFixMe - dynamically adding properties to a class
+ (this: any)[key] = ScrollResponder.Mixin[key].bind(this);
+ }
+ }
+
+ /**
+ * Part 3: Removing ScrollResponder.Mixin
+ *
+ * 4. Mixins can initialize properties and use properties on the component
+ * instance.
+ */
+ Object.keys(ScrollResponder.Mixin)
+ .filter(key => typeof ScrollResponder.Mixin[key] !== 'function')
+ .forEach(key => {
+ // $FlowFixMe - dynamically adding properties to a class
+ (this: any)[key] = ScrollResponder.Mixin[key];
+ });
+ }
+
+ _scrollAnimatedValue: AnimatedImplementation.Value = new AnimatedImplementation.Value(
+ 0,
+ );
+ _scrollAnimatedValueAttachment: ?{detach: () => void, ...} = null;
+ _stickyHeaderRefs: Map<
+ string,
+ React.ElementRef,
+ > = new Map();
+ _headerLayoutYs: Map = new Map();
+
+ state: State = {
+ layoutHeight: null,
+ ...ScrollResponder.Mixin.scrollResponderMixinGetInitialState(),
+ };
+
+ UNSAFE_componentWillMount() {
+ this._scrollResponder.UNSAFE_componentWillMount();
+ this._scrollAnimatedValue = new AnimatedImplementation.Value(
+ this.props.contentOffset ? this.props.contentOffset.y : 0,
+ );
+ this._scrollAnimatedValue.setOffset(
+ this.props.contentInset ? this.props.contentInset.top || 0 : 0,
+ );
+ this._stickyHeaderRefs = new Map();
+ this._headerLayoutYs = new Map();
+ }
+
+ UNSAFE_componentWillReceiveProps(nextProps: Props) {
+ const currentContentInsetTop = this.props.contentInset
+ ? this.props.contentInset.top
+ : 0;
+ const nextContentInsetTop = nextProps.contentInset
+ ? nextProps.contentInset.top
+ : 0;
+ if (currentContentInsetTop !== nextContentInsetTop) {
+ this._scrollAnimatedValue.setOffset(nextContentInsetTop || 0);
+ }
+ }
+
+ componentDidMount() {
+ this._updateAnimatedNodeAttachment();
+ }
+
+ componentDidUpdate() {
+ this._updateAnimatedNodeAttachment();
+ }
+
+ componentWillUnmount() {
+ this._scrollResponder.componentWillUnmount();
+ if (this._scrollAnimatedValueAttachment) {
+ this._scrollAnimatedValueAttachment.detach();
+ }
+ }
+
+ setNativeProps(props: {[key: string]: mixed, ...}) {
+ this._scrollViewRef && this._scrollViewRef.setNativeProps(props);
+ }
+
+ /**
+ * Returns a reference to the underlying scroll responder, which supports
+ * operations like `scrollTo`. All ScrollView-like components should
+ * implement this method so that they can be composed while providing access
+ * to the underlying scroll responder's methods.
+ */
+ getScrollResponder(): ScrollResponderType {
+ // $FlowFixMe - overriding type to include ScrollResponder.Mixin
+ return ((this: any): ScrollResponderType);
+ }
+
+ getScrollableNode(): ?number {
+ return ReactNative.findNodeHandle(this._scrollViewRef);
+ }
+
+ getInnerViewNode(): ?number {
+ return ReactNative.findNodeHandle(this._innerViewRef);
+ }
+
+ getInnerViewRef(): ?React.ElementRef> {
+ return this._innerViewRef;
+ }
+
+ getNativeScrollRef(): ?React.ElementRef> {
+ return this._scrollViewRef;
+ }
+
+ /**
+ * Scrolls to a given x, y offset, either immediately or with a smooth animation.
+ *
+ * Example:
+ *
+ * `scrollTo({x: 0, y: 0, animated: true})`
+ *
+ * Note: The weird function signature is due to the fact that, for historical reasons,
+ * the function also accepts separate arguments as an alternative to the options object.
+ * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
+ */
+ scrollTo(
+ options?:
+ | {
+ x?: number,
+ y?: number,
+ animated?: boolean,
+ ...
+ }
+ | number,
+ deprecatedX?: number,
+ deprecatedAnimated?: boolean,
+ ) {
+ let x, y, animated;
+ if (typeof options === 'number') {
+ console.warn(
+ '`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, ' +
+ 'animated: true})` instead.',
+ );
+ y = options;
+ x = deprecatedX;
+ animated = deprecatedAnimated;
+ } else if (options) {
+ y = options.y;
+ x = options.x;
+ animated = options.animated;
+ }
+ this._scrollResponder.scrollResponderScrollTo({
+ x: x || 0,
+ y: y || 0,
+ animated: animated !== false,
+ });
+ }
+
+ /**
+ * If this is a vertical ScrollView scrolls to the bottom.
+ * If this is a horizontal ScrollView scrolls to the right.
+ *
+ * Use `scrollToEnd({animated: true})` for smooth animated scrolling,
+ * `scrollToEnd({animated: false})` for immediate scrolling.
+ * If no options are passed, `animated` defaults to true.
+ */
+ scrollToEnd(options?: ?{animated?: boolean, ...}) {
+ // Default to true
+ const animated = (options && options.animated) !== false;
+ this._scrollResponder.scrollResponderScrollToEnd({
+ animated: animated,
+ });
+ }
+
+ /**
+ * Displays the scroll indicators momentarily.
+ *
+ * @platform ios
+ */
+ flashScrollIndicators() {
+ this._scrollResponder.scrollResponderFlashScrollIndicators();
+ }
+
+ _getKeyForIndex(index, childArray) {
+ const child = childArray[index];
+ return child && child.key;
+ }
+
+ _updateAnimatedNodeAttachment() {
+ if (this._scrollAnimatedValueAttachment) {
+ this._scrollAnimatedValueAttachment.detach();
+ }
+ if (
+ this.props.stickyHeaderIndices &&
+ this.props.stickyHeaderIndices.length > 0
+ ) {
+ this._scrollAnimatedValueAttachment = AnimatedImplementation.attachNativeEvent(
+ this._scrollViewRef,
+ 'onScroll',
+ [{nativeEvent: {contentOffset: {y: this._scrollAnimatedValue}}}],
+ );
+ }
+ }
+
+ _setStickyHeaderRef(
+ key: string,
+ ref: ?React.ElementRef,
+ ) {
+ if (ref) {
+ this._stickyHeaderRefs.set(key, ref);
+ } else {
+ this._stickyHeaderRefs.delete(key);
+ }
+ }
+
+ _onStickyHeaderLayout(index, event, key) {
+ const {stickyHeaderIndices} = this.props;
+ if (!stickyHeaderIndices) {
+ return;
+ }
+ const childArray = React.Children.toArray(this.props.children);
+ if (key !== this._getKeyForIndex(index, childArray)) {
+ // ignore stale layout update
+ return;
+ }
+
+ const layoutY = event.nativeEvent.layout.y;
+ this._headerLayoutYs.set(key, layoutY);
+
+ const indexOfIndex = stickyHeaderIndices.indexOf(index);
+ const previousHeaderIndex = stickyHeaderIndices[indexOfIndex - 1];
+ if (previousHeaderIndex != null) {
+ const previousHeader = this._stickyHeaderRefs.get(
+ this._getKeyForIndex(previousHeaderIndex, childArray),
+ );
+ previousHeader &&
+ previousHeader.setNextHeaderY &&
+ previousHeader.setNextHeaderY(layoutY);
+ }
+ }
+
+ _handleScroll = (e: ScrollEvent) => {
+ if (__DEV__) {
+ if (
+ this.props.onScroll &&
+ this.props.scrollEventThrottle == null &&
+ Platform.OS === 'ios'
+ ) {
+ console.log(
+ 'You specified `onScroll` on a but not ' +
+ '`scrollEventThrottle`. You will only receive one event. ' +
+ 'Using `16` you get all the events but be aware that it may ' +
+ "cause frame drops, use a bigger number if you don't need as " +
+ 'much precision.',
+ );
+ }
+ }
+ if (Platform.OS === 'android') {
+ if (
+ this.props.keyboardDismissMode === 'on-drag' &&
+ this.state.isTouching
+ ) {
+ dismissKeyboard();
+ }
+ }
+ this._scrollResponder.scrollResponderHandleScroll(e);
+ };
+
+ _handleLayout = (e: LayoutEvent) => {
+ if (this.props.invertStickyHeaders === true) {
+ this.setState({layoutHeight: e.nativeEvent.layout.height});
+ }
+ if (this.props.onLayout) {
+ this.props.onLayout(e);
+ }
+ };
+
+ _handleContentOnLayout = (e: LayoutEvent) => {
+ const {width, height} = e.nativeEvent.layout;
+ this.props.onContentSizeChange &&
+ this.props.onContentSizeChange(width, height);
+ };
+
+ _scrollViewRef: ?React.ElementRef> = null;
+ _setScrollViewRef = (ref: ?React.ElementRef>) => {
+ this._scrollViewRef = ref;
+ };
+
+ _innerViewRef: ?React.ElementRef> = null;
+ _setInnerViewRef = (ref: ?React.ElementRef>) => {
+ this._innerViewRef = ref;
+ };
+
+ render(): React.Node | React.Element {
+ let ScrollViewClass;
+ let ScrollContentContainerViewClass;
+ if (Platform.OS === 'android') {
+ if (this.props.horizontal === true) {
+ ScrollViewClass = AndroidHorizontalScrollView;
+ ScrollContentContainerViewClass = AndroidHorizontalScrollContentView;
+ } else {
+ ScrollViewClass = AndroidScrollView;
+ ScrollContentContainerViewClass = View;
+ }
+ } else {
+ ScrollViewClass = RCTScrollView;
+ ScrollContentContainerViewClass = RCTScrollContentView;
+ }
+
+ invariant(
+ ScrollViewClass !== undefined,
+ 'ScrollViewClass must not be undefined',
+ );
+
+ invariant(
+ ScrollContentContainerViewClass !== undefined,
+ 'ScrollContentContainerViewClass must not be undefined',
+ );
+
+ const contentContainerStyle = [
+ this.props.horizontal === true && styles.contentContainerHorizontal,
+ this.props.contentContainerStyle,
+ ];
+ if (__DEV__ && this.props.style !== undefined) {
+ const style = flattenStyle(this.props.style);
+ const childLayoutProps = ['alignItems', 'justifyContent'].filter(
+ prop => style && style[prop] !== undefined,
+ );
+ invariant(
+ childLayoutProps.length === 0,
+ 'ScrollView child layout (' +
+ JSON.stringify(childLayoutProps) +
+ ') must be applied through the contentContainerStyle prop.',
+ );
+ }
+
+ let contentSizeChangeProps = {};
+ if (this.props.onContentSizeChange) {
+ contentSizeChangeProps = {
+ onLayout: this._handleContentOnLayout,
+ };
+ }
+
+ const {stickyHeaderIndices} = this.props;
+ let children = this.props.children;
+
+ if (stickyHeaderIndices != null && stickyHeaderIndices.length > 0) {
+ const childArray = React.Children.toArray(this.props.children);
+
+ children = childArray.map((child, index) => {
+ const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1;
+ if (indexOfIndex > -1) {
+ const key = child.key;
+ const nextIndex = stickyHeaderIndices[indexOfIndex + 1];
+ const StickyHeaderComponent =
+ this.props.StickyHeaderComponent || ScrollViewStickyHeader;
+ return (
+ this._setStickyHeaderRef(key, ref)}
+ nextHeaderLayoutY={this._headerLayoutYs.get(
+ this._getKeyForIndex(nextIndex, childArray),
+ )}
+ onLayout={event => this._onStickyHeaderLayout(index, event, key)}
+ scrollAnimatedValue={this._scrollAnimatedValue}
+ inverted={this.props.invertStickyHeaders}
+ scrollViewHeight={this.state.layoutHeight}>
+ {child}
+
+ );
+ } else {
+ return child;
+ }
+ });
+ }
+ children = (
+
+ {children}
+
+ );
+
+ const hasStickyHeaders =
+ Array.isArray(stickyHeaderIndices) && stickyHeaderIndices.length > 0;
+
+ const contentContainer = (
+ /* $FlowFixMe(>=0.112.0 site=react_native_fb) This comment suppresses an
+ * error found when Flow v0.112 was deployed. To see the error, delete
+ * this comment and run Flow. */
+
+ {children}
+
+ );
+
+ const alwaysBounceHorizontal =
+ this.props.alwaysBounceHorizontal !== undefined
+ ? this.props.alwaysBounceHorizontal
+ : this.props.horizontal;
+
+ const alwaysBounceVertical =
+ this.props.alwaysBounceVertical !== undefined
+ ? this.props.alwaysBounceVertical
+ : !this.props.horizontal;
+
+ const DEPRECATED_sendUpdatedChildFrames = !!this.props
+ .DEPRECATED_sendUpdatedChildFrames;
+
+ const baseStyle =
+ this.props.horizontal === true
+ ? styles.baseHorizontal
+ : styles.baseVertical;
+ const props = {
+ ...this.props,
+ alwaysBounceHorizontal,
+ alwaysBounceVertical,
+ style: [baseStyle, this.props.style],
+ // Override the onContentSizeChange from props, since this event can
+ // bubble up from TextInputs
+ onContentSizeChange: null,
+ onLayout: this._handleLayout,
+ onMomentumScrollBegin: this._scrollResponder
+ .scrollResponderHandleMomentumScrollBegin,
+ onMomentumScrollEnd: this._scrollResponder
+ .scrollResponderHandleMomentumScrollEnd,
+ onResponderGrant: this._scrollResponder
+ .scrollResponderHandleResponderGrant,
+ onResponderReject: this._scrollResponder
+ .scrollResponderHandleResponderReject,
+ onResponderRelease: this._scrollResponder
+ .scrollResponderHandleResponderRelease,
+ onResponderTerminationRequest: this._scrollResponder
+ .scrollResponderHandleTerminationRequest,
+ onScrollBeginDrag: this._scrollResponder
+ .scrollResponderHandleScrollBeginDrag,
+ onScrollEndDrag: this._scrollResponder.scrollResponderHandleScrollEndDrag,
+ onScrollShouldSetResponder: this._scrollResponder
+ .scrollResponderHandleScrollShouldSetResponder,
+ onStartShouldSetResponder: this._scrollResponder
+ .scrollResponderHandleStartShouldSetResponder,
+ onStartShouldSetResponderCapture: this._scrollResponder
+ .scrollResponderHandleStartShouldSetResponderCapture,
+ onTouchEnd: this._scrollResponder.scrollResponderHandleTouchEnd,
+ onTouchMove: this._scrollResponder.scrollResponderHandleTouchMove,
+ onTouchStart: this._scrollResponder.scrollResponderHandleTouchStart,
+ onTouchCancel: this._scrollResponder.scrollResponderHandleTouchCancel,
+ onScroll: this._handleScroll,
+ scrollBarThumbImage: resolveAssetSource(this.props.scrollBarThumbImage),
+ scrollEventThrottle: hasStickyHeaders
+ ? 1
+ : this.props.scrollEventThrottle,
+ sendMomentumEvents:
+ this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd
+ ? true
+ : false,
+ DEPRECATED_sendUpdatedChildFrames,
+ // default to true
+ snapToStart: this.props.snapToStart !== false,
+ // default to true
+ snapToEnd: this.props.snapToEnd !== false,
+ // pagingEnabled is overridden by snapToInterval / snapToOffsets
+ pagingEnabled: Platform.select({
+ // on iOS, pagingEnabled must be set to false to have snapToInterval / snapToOffsets work
+ ios:
+ this.props.pagingEnabled === true &&
+ this.props.snapToInterval == null &&
+ this.props.snapToOffsets == null,
+ // on Android, pagingEnabled must be set to true to have snapToInterval / snapToOffsets work
+ android:
+ this.props.pagingEnabled === true ||
+ this.props.snapToInterval != null ||
+ this.props.snapToOffsets != null,
+ // on Windows, pagingEnabled must be set to false to have snapToInterval / snapToOffsets work
+ windows:
+ this.props.pagingEnabled === true &&
+ this.props.snapToInterval == null &&
+ this.props.snapToOffsets == null,
+ }),
+ };
+
+ const {decelerationRate} = this.props;
+ if (decelerationRate != null) {
+ props.decelerationRate = processDecelerationRate(decelerationRate);
+ }
+
+ const refreshControl = this.props.refreshControl;
+
+ if (refreshControl) {
+ if (Platform.OS === 'ios') {
+ // On iOS the RefreshControl is a child of the ScrollView.
+ // tvOS lacks native support for RefreshControl, so don't include it in that case
+ return (
+
+ {Platform.isTV ? null : refreshControl}
+ {contentContainer}
+
+ );
+ } else if (Platform.OS === 'android') {
+ // On Android wrap the ScrollView with a AndroidSwipeRefreshLayout.
+ // Since the ScrollView is wrapped add the style props to the
+ // AndroidSwipeRefreshLayout and use flex: 1 for the ScrollView.
+ // Note: we should split props.style on the inner and outer props
+ // however, the ScrollView still needs the baseStyle to be scrollable
+ const {outer, inner} = splitLayoutProps(flattenStyle(props.style));
+ return React.cloneElement(
+ refreshControl,
+ {style: [baseStyle, outer]},
+
+ {contentContainer}
+ ,
+ );
+ } else if (Platform.OS === 'windows') {
+ const {outer, inner} = splitLayoutProps(flattenStyle(props.style));
+ return React.cloneElement(
+ refreshControl,
+ {style: [baseStyle, outer]},
+
+ {contentContainer}
+ ,
+ );
+ }
+ }
+ return (
+
+ {contentContainer}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ baseVertical: {
+ flexGrow: 1,
+ flexShrink: 1,
+ flexDirection: 'column',
+ overflow: 'scroll',
+ },
+ baseHorizontal: {
+ flexGrow: 1,
+ flexShrink: 1,
+ flexDirection: 'row',
+ overflow: 'scroll',
+ },
+ contentContainerHorizontal: {
+ flexDirection: 'row',
+ },
+});
+
+module.exports = ScrollView;
diff --git a/packages/react-native-win32/src/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.win32.js b/packages/react-native-win32/src/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.win32.js
new file mode 100644
index 00000000000..d6c5ae97b06
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.win32.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+import type {TurboModule} from '../../TurboModule/RCTExport';
+import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry';
+import type {NativeOrDynamicColorType} from '../../StyleSheet/NativeOrDynamicColorType'; // [Win32]
+
+export interface Spec extends TurboModule {
+ +getConstants: () => {|
+ +HEIGHT: number,
+ +DEFAULT_BACKGROUND_COLOR: number,
+ |};
+ // [Win32 Allow NativeOrDynamicColorType to make Flow happy (this will never be called)
+ +setColor: (
+ color: number | NativeOrDynamicColorType,
+ animated: boolean,
+ ) => void;
+ // Win32]
+ +setTranslucent: (translucent: boolean) => void;
+
+ /**
+ * - statusBarStyles can be:
+ * - 'default'
+ * - 'dark-content'
+ */
+ +setStyle: (statusBarStyle?: ?string) => void;
+ +setHidden: (hidden: boolean) => void;
+}
+
+// [Win32 Change from getEnforcing to get and provide a stub (See #4363). This
+// can be removed once devmain integrates with 0.62 native bits.
+let NativeStausBarManager = TurboModuleRegistry.get('StatusBarManager');
+if (!NativeStausBarManager) {
+ NativeStausBarManager = {
+ getConstants: () => ({HEIGHT: 0, DEFAULT_BACKGROUND_COLOR: 0}),
+ setColor: (
+ color: number | NativeOrDynamicColorType,
+ animated: boolean,
+ ) => {},
+ setTranslucent: (translucent: boolean) => {},
+ setStyle: (statusBarStyle?: ?string) => {},
+ setHidden: (hidden: boolean) => {},
+ };
+}
+
+export default (NativeStausBarManager: Spec);
+// Win32]
diff --git a/packages/react-native-win32/src/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.win32.js b/packages/react-native-win32/src/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.win32.js
new file mode 100644
index 00000000000..d298cae8d71
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.win32.js
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+import type {TurboModule} from '../../TurboModule/RCTExport';
+import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry';
+
+export interface Spec extends TurboModule {
+ +getConstants: () => {|
+ +HEIGHT: number,
+ +DEFAULT_BACKGROUND_COLOR?: number,
+ |};
+
+ // TODO(T47754272) Can we remove this method?
+ +getHeight: (callback: (result: {|height: number|}) => void) => void;
+ +setNetworkActivityIndicatorVisible: (visible: boolean) => void;
+ +addListener: (eventType: string) => void;
+ +removeListeners: (count: number) => void;
+
+ /**
+ * - statusBarStyles can be:
+ * - 'default'
+ * - 'dark-content'
+ * - 'light-content'
+ */
+ +setStyle: (statusBarStyle?: ?string, animated: boolean) => void;
+ /**
+ * - withAnimation can be: 'none' | 'fade' | 'slide'
+ */
+ +setHidden: (hidden: boolean, withAnimation: string) => void;
+}
+
+// [Win32 Do not enforce native module is present
+export default (TurboModuleRegistry.get(
+ 'StatusBarManager',
+): ?Spec);
+// Win32]
diff --git a/packages/react-native-win32/src/Libraries/Components/StatusBar/StatusBar.win32.ts b/packages/react-native-win32/src/Libraries/Components/StatusBar/StatusBar.win32.ts
deleted file mode 100644
index b0f877f19c2..00000000000
--- a/packages/react-native-win32/src/Libraries/Components/StatusBar/StatusBar.win32.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation.
- * Licensed under the MIT license.
- *
- * @format
- */
-'use strict';
-
-// @ts-ignore This file is present after the JS build
-import * as UnimplementedView from '../UnimplementedViews/UnimplementedView';
-import {StatusBarProps} from 'react-native';
-
-class StatusBar extends UnimplementedView {}
-
-export = StatusBar;
diff --git a/packages/react-native-win32/src/Libraries/Components/StatusBar/StatusBarIOS.win32.ts b/packages/react-native-win32/src/Libraries/Components/StatusBar/StatusBarIOS.win32.ts
deleted file mode 100644
index 4ec9e204c68..00000000000
--- a/packages/react-native-win32/src/Libraries/Components/StatusBar/StatusBarIOS.win32.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * This copies what StatusBar.android.js does
- */
-'use strict';
-
-export = null;
diff --git a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.Types.win32.ts b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.Types.win32.ts
index 7e68a5e3f87..cedc19fed51 100644
--- a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.Types.win32.ts
+++ b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.Types.win32.ts
@@ -66,10 +66,3 @@ export type IEditingEvent = NativeSyntheticEvent>;
// TODO: Why do I need this one
export type IPasswordRules = string;
-
-// TODO: Can I get away without this?
-export interface IRCTInput {
- blur(): void;
- focus(): void;
- clear(): void;
-}
diff --git a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx
index 2b923c54b48..39594d5c9cd 100644
--- a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx
+++ b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInput.win32.tsx
@@ -29,19 +29,23 @@ import {
NativeModules,
requireNativeComponent,
TextInputProps,
+ NativeMethods,
} from 'react-native';
import {
IBlurEvent,
IChangeEvent,
IFocusEvent,
- IRCTInput,
} from './TextInput.Types.win32';
const TextAncestor = require('../../Text/TextAncestor');
const TextInputState = require('./TextInputState');
+type RCTTextInputProps = TextInputProps & {
+ text: string;
+};
+
// RCTTextInput is the native component that win32 understands
-const RCTTextInput = requireNativeComponent('RCTTextInput');
+const RCTTextInput = requireNativeComponent('RCTTextInput');
// Adding typings on ViewManagers is problematic as available functionality is not known until
// registration at runtime and would require native and js to always be in sync.
@@ -55,13 +59,13 @@ class TextInput extends React.Component {
private _rafID: number;
- private _inputRef: React.RefObject;
+ private _inputRef: React.RefObject & Readonly>;
private _lastNativeText: string;
private _eventCount = 0;
constructor(props) {
super(props);
- this._inputRef = React.createRef();
+ this._inputRef = React.createRef();
}
/**
diff --git a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js
index 17accd4314c..97c6ead360d 100644
--- a/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/TextInput/TextInputState.win32.js
@@ -4,15 +4,14 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- *
- * This class is responsible for coordinating the "focused"
- * state for TextInputs. All calls relating to the keyboard
- * should be funneled through here
- *
* @format
* @flow strict-local
*/
+// This class is responsible for coordinating the "focused" state for
+// TextInputs. All calls relating to the keyboard should be funneled
+// through here.
+
'use strict';
const Platform = require('../../Utilities/Platform');
@@ -29,17 +28,29 @@ function currentlyFocusedField(): ?number {
return currentlyFocusedID;
}
+function focusField(textFieldID: ?number): void {
+ if (currentlyFocusedID !== textFieldID && textFieldID != null) {
+ currentlyFocusedID = textFieldID;
+ }
+}
+
+function blurField(textFieldID: ?number) {
+ if (currentlyFocusedID === textFieldID && textFieldID != null) {
+ currentlyFocusedID = null;
+ }
+}
+
/**
* @param {number} TextInputID id of the text field to focus
* Focuses the specified text field
* noop if the text field was already focused
*/
function focusTextInput(textFieldID: ?number) {
- if (currentlyFocusedID !== textFieldID && textFieldID !== null) {
- currentlyFocusedID = textFieldID;
+ if (currentlyFocusedID !== textFieldID && textFieldID != null) {
+ focusField(textFieldID);
// [Windows
if (Platform.OS === 'ios' || Platform.OS === 'win32') {
- // Windows]
+ // Windows]
UIManager.focus(textFieldID);
} else if (Platform.OS === 'android') {
UIManager.dispatchViewManagerCommand(
@@ -58,11 +69,11 @@ function focusTextInput(textFieldID: ?number) {
* noop if it wasn't focused
*/
function blurTextInput(textFieldID: ?number) {
- if (currentlyFocusedID === textFieldID && textFieldID !== null) {
- currentlyFocusedID = null;
+ if (currentlyFocusedID === textFieldID && textFieldID != null) {
+ blurField(textFieldID);
// [Windows
if (Platform.OS === 'ios' || Platform.OS === 'win32') {
- // Windows]
+ // Windows]
UIManager.blur(textFieldID);
} else if (Platform.OS === 'android') {
UIManager.dispatchViewManagerCommand(
@@ -113,6 +124,8 @@ function isTextInput(textFieldID: number): boolean {
module.exports = {
currentlyFocusedField,
+ focusField,
+ blurField,
setFocusedTextInput, // TODO(android ISS)
clearFocusedTextInput, // TODO(android ISS)
focusTextInput,
diff --git a/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableBounce.win32.js b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableBounce.win32.js
new file mode 100644
index 00000000000..cc3543ec223
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableBounce.win32.js
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+// [Win32 Remove .js
+import Pressability from '../../Pressability/Pressability';
+import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
+import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
+import TVTouchable from './TVTouchable';
+import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
+// Win32]
+import {Animated, Platform} from 'react-native';
+import * as React from 'react';
+
+type Props = $ReadOnly<{|
+ ...React.ElementConfig,
+
+ onPressAnimationComplete?: ?() => void,
+ onPressWithCompletion?: ?(callback: () => void) => void,
+ releaseBounciness?: ?number,
+ releaseVelocity?: ?number,
+ style?: ?ViewStyleProp,
+
+ hostRef: React.Ref,
+|}>;
+
+type State = $ReadOnly<{|
+ pressability: Pressability,
+ scale: Animated.Value,
+|}>;
+
+class TouchableBounce extends React.Component {
+ _tvTouchable: ?TVTouchable;
+
+ state: State = {
+ pressability: new Pressability({
+ getHitSlop: () => this.props.hitSlop,
+ getLongPressDelayMS: () => {
+ if (this.props.delayLongPress != null) {
+ const maybeNumber = this.props.delayLongPress;
+ if (typeof maybeNumber === 'number') {
+ return maybeNumber;
+ }
+ }
+ return 500;
+ },
+ getPressDelayMS: () => this.props.delayPressIn,
+ getPressOutDelayMS: () => this.props.delayPressOut,
+ getPressRectOffset: () => this.props.pressRetentionOffset,
+ getTouchSoundDisabled: () => this.props.touchSoundDisabled,
+ onBlur: event => {
+ if (Platform.isTV) {
+ this._bounceTo(1, 0.4, 0);
+ }
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (Platform.isTV) {
+ this._bounceTo(0.93, 0.1, 0);
+ }
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onLongPress: event => {
+ if (this.props.onLongPress != null) {
+ this.props.onLongPress(event);
+ }
+ },
+ onPress: event => {
+ const {onPressAnimationComplete, onPressWithCompletion} = this.props;
+ const releaseBounciness = this.props.releaseBounciness ?? 10;
+ const releaseVelocity = this.props.releaseVelocity ?? 10;
+
+ if (onPressWithCompletion != null) {
+ onPressWithCompletion(() => {
+ this.state.scale.setValue(0.93);
+ this._bounceTo(
+ 1,
+ releaseVelocity,
+ releaseBounciness,
+ onPressAnimationComplete,
+ );
+ });
+ return;
+ }
+
+ this._bounceTo(
+ 1,
+ releaseVelocity,
+ releaseBounciness,
+ onPressAnimationComplete,
+ );
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ onPressIn: event => {
+ this._bounceTo(0.93, 0.1, 0);
+ if (this.props.onPressIn != null) {
+ this.props.onPressIn(event);
+ }
+ },
+ onPressOut: event => {
+ this._bounceTo(1, 0.4, 0);
+ if (this.props.onPressOut != null) {
+ this.props.onPressOut(event);
+ }
+ },
+ onResponderTerminationRequest: () =>
+ !this.props.rejectResponderTermination,
+ onStartShouldSetResponder: () => !this.props.disabled,
+ }),
+ scale: new Animated.Value(1),
+ };
+
+ _bounceTo(
+ toValue: number,
+ velocity: number,
+ bounciness: number,
+ callback?: ?() => void,
+ ) {
+ Animated.spring(this.state.scale, {
+ toValue,
+ velocity,
+ bounciness,
+ useNativeDriver: true,
+ }).start(callback);
+ }
+
+ render(): React.Node {
+ // BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
+ // adopting `Pressability`, so preserve that behavior.
+ const {
+ onBlur,
+ onFocus,
+ ...eventHandlersWithoutBlurAndFocus
+ } = this.state.pressability.getEventHandlers();
+
+ return (
+
+ {this.props.children}
+ {__DEV__ ? (
+
+ ) : null}
+
+ );
+ }
+
+ componentDidMount(): void {
+ if (Platform.isTV) {
+ this._tvTouchable = new TVTouchable(this, {
+ getDisabled: () => this.props.disabled === true,
+ onBlur: event => {
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onPress: event => {
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ });
+ }
+ }
+
+ componentWillUnmount(): void {
+ if (Platform.isTV) {
+ if (this._tvTouchable != null) {
+ this._tvTouchable.destroy();
+ }
+ }
+ this.state.pressability.reset();
+ }
+}
+
+module.exports = (React.forwardRef((props, hostRef) => (
+
+)): React.ComponentType<$ReadOnly<$Diff>>);
diff --git a/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableHighlight.win32.js b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableHighlight.win32.js
new file mode 100644
index 00000000000..475bbc09c95
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableHighlight.win32.js
@@ -0,0 +1,384 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+// [Win32 Remove .js
+import Pressability from '../../Pressability/Pressability';
+import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
+import StyleSheet, {type ViewStyleProp} from '../../StyleSheet/StyleSheet';
+import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
+import TVTouchable from './TVTouchable.js';
+import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
+// Win32]
+import Platform from '../../Utilities/Platform';
+import View from '../../Components/View/View';
+import * as React from 'react';
+
+type AndroidProps = $ReadOnly<{|
+ nextFocusDown?: ?number,
+ nextFocusForward?: ?number,
+ nextFocusLeft?: ?number,
+ nextFocusRight?: ?number,
+ nextFocusUp?: ?number,
+|}>;
+
+type IOSProps = $ReadOnly<{|
+ hasTVPreferredFocus?: ?boolean,
+|}>;
+
+type Props = $ReadOnly<{|
+ ...React.ElementConfig,
+ ...AndroidProps,
+ ...IOSProps,
+
+ activeOpacity?: ?number,
+ underlayColor?: ?ColorValue,
+ style?: ?ViewStyleProp,
+ onShowUnderlay?: ?() => void,
+ onHideUnderlay?: ?() => void,
+ testOnly_pressed?: ?boolean,
+
+ hostRef: React.Ref,
+|}>;
+
+type ExtraStyles = $ReadOnly<{|
+ child: ViewStyleProp,
+ underlay: ViewStyleProp,
+|}>;
+
+type State = $ReadOnly<{|
+ pressability: Pressability,
+ extraStyles: ?ExtraStyles,
+|}>;
+
+/**
+ * A wrapper for making views respond properly to touches.
+ * On press down, the opacity of the wrapped view is decreased, which allows
+ * the underlay color to show through, darkening or tinting the view.
+ *
+ * The underlay comes from wrapping the child in a new View, which can affect
+ * layout, and sometimes cause unwanted visual artifacts if not used correctly,
+ * for example if the backgroundColor of the wrapped view isn't explicitly set
+ * to an opaque color.
+ *
+ * TouchableHighlight must have one child (not zero or more than one).
+ * If you wish to have several child components, wrap them in a View.
+ *
+ * Example:
+ *
+ * ```
+ * renderButton: function() {
+ * return (
+ *
+ *
+ *
+ * );
+ * },
+ * ```
+ *
+ *
+ * ### Example
+ *
+ * ```ReactNativeWebPlayer
+ * import React, { Component } from 'react'
+ * import {
+ * AppRegistry,
+ * StyleSheet,
+ * TouchableHighlight,
+ * Text,
+ * View,
+ * } from 'react-native'
+ *
+ * class App extends Component {
+ * constructor(props) {
+ * super(props)
+ * this.state = { count: 0 }
+ * }
+ *
+ * onPress = () => {
+ * this.setState({
+ * count: this.state.count+1
+ * })
+ * }
+ *
+ * render() {
+ * return (
+ *
+ *
+ * Touch Here
+ *
+ *
+ *
+ * { this.state.count !== 0 ? this.state.count: null}
+ *
+ *
+ *
+ * )
+ * }
+ * }
+ *
+ * const styles = StyleSheet.create({
+ * container: {
+ * flex: 1,
+ * justifyContent: 'center',
+ * paddingHorizontal: 10
+ * },
+ * button: {
+ * alignItems: 'center',
+ * backgroundColor: '#DDDDDD',
+ * padding: 10
+ * },
+ * countContainer: {
+ * alignItems: 'center',
+ * padding: 10
+ * },
+ * countText: {
+ * color: '#FF00FF'
+ * }
+ * })
+ *
+ * AppRegistry.registerComponent('App', () => App)
+ * ```
+ *
+ */
+class TouchableHighlight extends React.Component {
+ _hideTimeout: ?TimeoutID;
+ _isMounted: boolean = false;
+ _tvTouchable: ?TVTouchable;
+
+ state: State = {
+ pressability: new Pressability({
+ getHitSlop: () => this.props.hitSlop,
+ getLongPressDelayMS: () => {
+ if (this.props.delayLongPress != null) {
+ const maybeNumber = this.props.delayLongPress;
+ if (typeof maybeNumber === 'number') {
+ return maybeNumber;
+ }
+ }
+ return 500;
+ },
+ getPressDelayMS: () => this.props.delayPressIn,
+ getPressOutDelayMS: () => this.props.delayPressOut,
+ getPressRectOffset: () => this.props.pressRetentionOffset,
+ getTouchSoundDisabled: () => this.props.touchSoundDisabled,
+ onBlur: event => {
+ if (Platform.isTV) {
+ this._hideUnderlay();
+ }
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (Platform.isTV) {
+ this._showUnderlay();
+ }
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onLongPress: event => {
+ if (this.props.onLongPress != null) {
+ this.props.onLongPress(event);
+ }
+ },
+ onPress: event => {
+ if (this._hideTimeout != null) {
+ clearTimeout(this._hideTimeout);
+ }
+ if (!Platform.isTV) {
+ this._showUnderlay();
+ this._hideTimeout = setTimeout(() => {
+ this._hideUnderlay();
+ }, this.props.delayPressOut ?? 0);
+ }
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ onPressIn: event => {
+ if (this._hideTimeout != null) {
+ clearTimeout(this._hideTimeout);
+ this._hideTimeout = null;
+ }
+ this._showUnderlay();
+ if (this.props.onPressIn != null) {
+ this.props.onPressIn(event);
+ }
+ },
+ onPressOut: event => {
+ if (this._hideTimeout == null) {
+ this._hideUnderlay();
+ }
+ if (this.props.onPressOut != null) {
+ this.props.onPressOut(event);
+ }
+ },
+ onResponderTerminationRequest: () =>
+ !this.props.rejectResponderTermination,
+ onStartShouldSetResponder: () => !this.props.disabled,
+ }),
+ extraStyles:
+ this.props.testOnly_pressed === true ? this._createExtraStyles() : null,
+ };
+
+ _createExtraStyles(): ExtraStyles {
+ return {
+ child: {opacity: this.props.activeOpacity ?? 0.85},
+ underlay: {
+ backgroundColor:
+ this.props.underlayColor === undefined
+ ? 'black'
+ : this.props.underlayColor,
+ },
+ };
+ }
+
+ _showUnderlay(): void {
+ if (!this._isMounted || !this._hasPressHandler()) {
+ return;
+ }
+ this.setState({extraStyles: this._createExtraStyles()});
+ if (this.props.onShowUnderlay != null) {
+ this.props.onShowUnderlay();
+ }
+ }
+
+ _hideUnderlay(): void {
+ if (this._hideTimeout != null) {
+ clearTimeout(this._hideTimeout);
+ this._hideTimeout = null;
+ }
+ if (this.props.testOnly_pressed === true) {
+ return;
+ }
+ if (this._hasPressHandler()) {
+ this.setState({extraStyles: null});
+ if (this.props.onHideUnderlay != null) {
+ this.props.onHideUnderlay();
+ }
+ }
+ }
+
+ _hasPressHandler(): boolean {
+ return (
+ this.props.onPress != null ||
+ this.props.onPressIn != null ||
+ this.props.onPressOut != null ||
+ this.props.onLongPress != null
+ );
+ }
+
+ render(): React.Node {
+ const child = React.Children.only(this.props.children);
+
+ // BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
+ // adopting `Pressability`, so preserve that behavior.
+ const {
+ onBlur,
+ onFocus,
+ ...eventHandlersWithoutBlurAndFocus
+ } = this.state.pressability.getEventHandlers();
+
+ return (
+
+ {React.cloneElement(child, {
+ style: StyleSheet.compose(
+ child.props.style,
+ this.state.extraStyles?.child,
+ ),
+ })}
+ {__DEV__ ? (
+
+ ) : null}
+
+ );
+ }
+
+ componentDidMount(): void {
+ this._isMounted = true;
+ if (Platform.isTV) {
+ this._tvTouchable = new TVTouchable(this, {
+ getDisabled: () => this.props.disabled === true,
+ onBlur: event => {
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onPress: event => {
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ });
+ }
+ }
+
+ componentWillUnmount(): void {
+ this._isMounted = false;
+ if (this._hideTimeout != null) {
+ clearTimeout(this._hideTimeout);
+ }
+ if (Platform.isTV) {
+ if (this._tvTouchable != null) {
+ this._tvTouchable.destroy();
+ }
+ }
+ this.state.pressability.reset();
+ }
+}
+
+module.exports = (React.forwardRef((props, hostRef) => (
+
+)): React.ComponentType<$ReadOnly<$Diff>>);
diff --git a/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableOpacity.win32.js b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableOpacity.win32.js
new file mode 100644
index 00000000000..c6acd99289a
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableOpacity.win32.js
@@ -0,0 +1,314 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+// [Win32 Remove ".js"
+import Pressability from '../../Pressability/Pressability';
+import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
+import TVTouchable from './TVTouchable';
+import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
+// Win32]
+import Animated from 'react-native/Libraries/Animated/src/Animated';
+import Easing from 'react-native/Libraries/Animated/src/Easing';
+import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
+import flattenStyle from 'react-native/Libraries/StyleSheet/flattenStyle';
+import Platform from '../../Utilities/Platform';
+import * as React from 'react';
+
+type TVProps = $ReadOnly<{|
+ hasTVPreferredFocus?: ?boolean,
+ nextFocusDown?: ?number,
+ nextFocusForward?: ?number,
+ nextFocusLeft?: ?number,
+ nextFocusRight?: ?number,
+ nextFocusUp?: ?number,
+|}>;
+
+type Props = $ReadOnly<{|
+ ...React.ElementConfig,
+ ...TVProps,
+
+ activeOpacity?: ?number,
+ style?: ?ViewStyleProp,
+
+ hostRef: React.Ref,
+|}>;
+
+type State = $ReadOnly<{|
+ anim: Animated.Value,
+ pressability: Pressability,
+|}>;
+
+/**
+ * A wrapper for making views respond properly to touches.
+ * On press down, the opacity of the wrapped view is decreased, dimming it.
+ *
+ * Opacity is controlled by wrapping the children in an Animated.View, which is
+ * added to the view hierarchy. Be aware that this can affect layout.
+ *
+ * Example:
+ *
+ * ```
+ * renderButton: function() {
+ * return (
+ *
+ *
+ *
+ * );
+ * },
+ * ```
+ * ### Example
+ *
+ * ```ReactNativeWebPlayer
+ * import React, { Component } from 'react'
+ * import {
+ * AppRegistry,
+ * StyleSheet,
+ * TouchableOpacity,
+ * Text,
+ * View,
+ * } from 'react-native'
+ *
+ * class App extends Component {
+ * state = { count: 0 }
+ *
+ * onPress = () => {
+ * this.setState(state => ({
+ * count: state.count + 1
+ * }));
+ * };
+ *
+ * render() {
+ * return (
+ *
+ *
+ * Touch Here
+ *
+ *
+ *
+ * { this.state.count !== 0 ? this.state.count: null}
+ *
+ *
+ *
+ * )
+ * }
+ * }
+ *
+ * const styles = StyleSheet.create({
+ * container: {
+ * flex: 1,
+ * justifyContent: 'center',
+ * paddingHorizontal: 10
+ * },
+ * button: {
+ * alignItems: 'center',
+ * backgroundColor: '#DDDDDD',
+ * padding: 10
+ * },
+ * countContainer: {
+ * alignItems: 'center',
+ * padding: 10
+ * },
+ * countText: {
+ * color: '#FF00FF'
+ * }
+ * })
+ *
+ * AppRegistry.registerComponent('App', () => App)
+ * ```
+ *
+ */
+class TouchableOpacity extends React.Component {
+ _tvTouchable: ?TVTouchable;
+
+ state: State = {
+ anim: new Animated.Value(this._getChildStyleOpacityWithDefault()),
+ pressability: new Pressability({
+ getHitSlop: () => this.props.hitSlop,
+ getLongPressDelayMS: () => {
+ if (this.props.delayLongPress != null) {
+ const maybeNumber = this.props.delayLongPress;
+ if (typeof maybeNumber === 'number') {
+ return maybeNumber;
+ }
+ }
+ return 500;
+ },
+ getPressDelayMS: () => this.props.delayPressIn,
+ getPressOutDelayMS: () => this.props.delayPressOut,
+ getPressRectOffset: () => this.props.pressRetentionOffset,
+ onBlur: event => {
+ if (Platform.isTV) {
+ this._opacityInactive(250);
+ }
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (Platform.isTV) {
+ this._opacityActive(150);
+ }
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onLongPress: event => {
+ if (this.props.onLongPress != null) {
+ this.props.onLongPress(event);
+ }
+ },
+ onPress: event => {
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ onPressIn: event => {
+ this._opacityActive(
+ event.dispatchConfig.registrationName === 'onResponderGrant'
+ ? 0
+ : 150,
+ );
+ if (this.props.onPressIn != null) {
+ this.props.onPressIn(event);
+ }
+ },
+ onPressOut: event => {
+ this._opacityInactive(250);
+ if (this.props.onPressOut != null) {
+ this.props.onPressOut(event);
+ }
+ },
+ onResponderTerminationRequest: () =>
+ !this.props.rejectResponderTermination,
+ onStartShouldSetResponder: () => !this.props.disabled,
+ }),
+ };
+
+ /**
+ * Animate the touchable to a new opacity.
+ */
+ _setOpacityTo(toValue: number, duration: number): void {
+ Animated.timing(this.state.anim, {
+ toValue,
+ duration,
+ easing: Easing.inOut(Easing.quad),
+ useNativeDriver: true,
+ }).start();
+ }
+
+ _opacityActive(duration: number): void {
+ this._setOpacityTo(this.props.activeOpacity ?? 0.2, duration);
+ }
+
+ _opacityInactive(duration: number): void {
+ this._setOpacityTo(this._getChildStyleOpacityWithDefault(), duration);
+ }
+
+ _getChildStyleOpacityWithDefault(): number {
+ const opacity = flattenStyle(this.props.style)?.opacity;
+ return typeof opacity === 'number' ? opacity : 1;
+ }
+
+ render(): React.Node {
+ // BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
+ // adopting `Pressability`, so preserve that behavior.
+ const {
+ onBlur,
+ onFocus,
+ ...eventHandlersWithoutBlurAndFocus
+ } = this.state.pressability.getEventHandlers();
+
+ return (
+
+ {this.props.children}
+ {__DEV__ ? (
+
+ ) : null}
+
+ );
+ }
+
+ componentDidMount(): void {
+ if (Platform.isTV) {
+ this._tvTouchable = new TVTouchable(this, {
+ getDisabled: () => this.props.disabled === true,
+ onBlur: event => {
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onPress: event => {
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ });
+ }
+ }
+
+ componentDidUpdate(prevProps: Props, prevState: State) {
+ if (this.props.disabled !== prevProps.disabled) {
+ this._opacityInactive(250);
+ }
+ }
+
+ componentWillUnmount(): void {
+ if (Platform.isTV) {
+ if (this._tvTouchable != null) {
+ this._tvTouchable.destroy();
+ }
+ }
+ this.state.pressability.reset();
+ }
+}
+
+module.exports = (React.forwardRef((props, hostRef) => (
+
+)): React.ComponentType<$ReadOnly<$Diff>>);
diff --git a/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableWithoutFeedback.win32.js b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableWithoutFeedback.win32.js
new file mode 100644
index 00000000000..8ad6be00003
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Components/Touchable/TouchableWithoutFeedback.win32.js
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow strict-local
+ * @format
+ */
+
+'use strict';
+
+// [Win32 Remove ".js"
+import Pressability from '../../Pressability/Pressability';
+import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
+import TVTouchable from './TVTouchable';
+// Win32]
+import type {
+ AccessibilityActionEvent,
+ AccessibilityActionInfo,
+ AccessibilityRole,
+ AccessibilityState,
+ AccessibilityValue,
+} from '../../Components/View/ViewAccessibility';
+import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType';
+import type {
+ BlurEvent,
+ FocusEvent,
+ LayoutEvent,
+ PressEvent,
+} from '../../Types/CoreEventTypes';
+import Platform from '../../Utilities/Platform';
+import View from '../../Components/View/View';
+import * as React from 'react';
+
+type Props = $ReadOnly<{|
+ accessibilityActions?: ?$ReadOnlyArray,
+ accessibilityElementsHidden?: ?boolean,
+ accessibilityHint?: ?Stringish,
+ accessibilityIgnoresInvertColors?: ?boolean,
+ accessibilityLabel?: ?Stringish,
+ accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'),
+ accessibilityRole?: ?AccessibilityRole,
+ accessibilityState?: ?AccessibilityState,
+ accessibilityValue?: ?AccessibilityValue,
+ accessibilityViewIsModal?: ?boolean,
+ accessible?: ?boolean,
+ children?: ?React.Node,
+ delayLongPress?: ?number,
+ delayPressIn?: ?number,
+ delayPressOut?: ?number,
+ disabled?: ?boolean,
+ focusable?: ?boolean,
+ hitSlop?: ?EdgeInsetsProp,
+ importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'),
+ nativeID?: ?string,
+ onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
+ onBlur?: ?(event: BlurEvent) => mixed,
+ onFocus?: ?(event: FocusEvent) => mixed,
+ onLayout?: ?(event: LayoutEvent) => mixed,
+ onLongPress?: ?(event: PressEvent) => mixed,
+ onPress?: ?(event: PressEvent) => mixed,
+ onPressIn?: ?(event: PressEvent) => mixed,
+ onPressOut?: ?(event: PressEvent) => mixed,
+ pressRetentionOffset?: ?EdgeInsetsProp,
+ rejectResponderTermination?: ?boolean,
+ testID?: ?string,
+ touchSoundDisabled?: ?boolean,
+|}>;
+
+type State = $ReadOnly<{|
+ pressability: Pressability,
+|}>;
+
+const PASSTHROUGH_PROPS = [
+ 'accessibilityActions',
+ 'accessibilityElementsHidden',
+ 'accessibilityHint',
+ 'accessibilityIgnoresInvertColors',
+ 'accessibilityLabel',
+ 'accessibilityLiveRegion',
+ 'accessibilityRole',
+ 'accessibilityState',
+ 'accessibilityValue',
+ 'accessibilityViewIsModal',
+ 'hitSlop',
+ 'importantForAccessibility',
+ 'nativeID',
+ 'onAccessibilityAction',
+ 'onBlur',
+ 'onFocus',
+ 'onLayout',
+ 'testID',
+];
+
+class TouchableWithoutFeedback extends React.Component {
+ _tvTouchable: ?TVTouchable;
+
+ state: State = {
+ pressability: new Pressability({
+ getHitSlop: () => this.props.hitSlop,
+ getLongPressDelayMS: () => {
+ if (this.props.delayLongPress != null) {
+ const maybeNumber = this.props.delayLongPress;
+ if (typeof maybeNumber === 'number') {
+ return maybeNumber;
+ }
+ }
+ return 500;
+ },
+ getPressDelayMS: () => this.props.delayPressIn,
+ getPressOutDelayMS: () => this.props.delayPressOut,
+ getPressRectOffset: () => this.props.pressRetentionOffset,
+ getTouchSoundDisabled: () => this.props.touchSoundDisabled,
+ onBlur: event => {
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onLongPress: event => {
+ if (this.props.onLongPress != null) {
+ this.props.onLongPress(event);
+ }
+ },
+ onPress: event => {
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ onPressIn: event => {
+ if (this.props.onPressIn != null) {
+ this.props.onPressIn(event);
+ }
+ },
+ onPressOut: event => {
+ if (this.props.onPressOut != null) {
+ this.props.onPressOut(event);
+ }
+ },
+ onResponderTerminationRequest: () =>
+ !this.props.rejectResponderTermination,
+ onStartShouldSetResponder: () => !this.props.disabled,
+ }),
+ };
+
+ render(): React.Node {
+ const element = React.Children.only(this.props.children);
+ const children = [element.props.children];
+ if (__DEV__) {
+ if (element.type === View) {
+ children.push(
+ ,
+ );
+ }
+ }
+
+ // BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
+ // adopting `Pressability`, so preserve that behavior.
+ const {
+ onBlur,
+ onFocus,
+ ...eventHandlersWithoutBlurAndFocus
+ } = this.state.pressability.getEventHandlers();
+
+ const elementProps: {[string]: mixed, ...} = {
+ ...eventHandlersWithoutBlurAndFocus,
+ accessible: this.props.accessible !== false,
+ focusable:
+ this.props.focusable !== false && this.props.onPress !== undefined,
+ };
+ for (const prop of PASSTHROUGH_PROPS) {
+ if (this.props[prop] !== undefined) {
+ elementProps[prop] = this.props[prop];
+ }
+ }
+
+ return React.cloneElement(element, elementProps, ...children);
+ }
+
+ componentDidMount(): void {
+ if (Platform.isTV) {
+ this._tvTouchable = new TVTouchable(this, {
+ getDisabled: () => this.props.disabled === true,
+ onBlur: event => {
+ if (this.props.onBlur != null) {
+ this.props.onBlur(event);
+ }
+ },
+ onFocus: event => {
+ if (this.props.onFocus != null) {
+ this.props.onFocus(event);
+ }
+ },
+ onPress: event => {
+ if (this.props.onPress != null) {
+ this.props.onPress(event);
+ }
+ },
+ });
+ }
+ }
+
+ componentWillUnmount(): void {
+ if (Platform.isTV) {
+ if (this._tvTouchable != null) {
+ this._tvTouchable.destroy();
+ }
+ }
+ this.state.pressability.reset();
+ }
+}
+
+module.exports = TouchableWithoutFeedback;
diff --git a/packages/react-native-win32/src/Libraries/Components/View/PlatformViewPropTypes.win32.ts b/packages/react-native-win32/src/Libraries/Components/View/PlatformViewPropTypes.win32.ts
deleted file mode 100644
index a0a8cc12e63..00000000000
--- a/packages/react-native-win32/src/Libraries/Components/View/PlatformViewPropTypes.win32.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * @providesModule PlatformViewPropTypes
- * @flow
- */
-'use strict';
-
-export = {};
diff --git a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js
index 656428f7b06..b580251fb28 100644
--- a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewAttributes.win32.js
@@ -19,8 +19,8 @@ const UIView = {
accessibilityLabel: true,
accessibilityLiveRegion: true,
accessibilityRole: true,
- accessibilityStates: true,
accessibilityState: true,
+ accessibilityValue: true,
accessibilityHint: true,
importantForAccessibility: true,
nativeID: true,
diff --git a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js
index 2733360b24a..0d58f3aaefe 100644
--- a/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js
+++ b/packages/react-native-win32/src/Libraries/Components/View/ReactNativeViewViewConfig.win32.js
@@ -16,8 +16,8 @@ const ReactNativeViewConfig = {
uiViewClassName: 'RCTView',
baseModuleName: null,
Manager: 'ViewManager',
- Commands: ({}: $TEMPORARY$object<{||}>),
- Constants: ({}: $TEMPORARY$object<{||}>),
+ Commands: ({}: {...}),
+ Constants: ({}: {...}),
bubblingEventTypes: {
...ReactNativeViewViewConfigAndroid.bubblingEventTypes,
topBlur: {
@@ -140,8 +140,9 @@ const ReactNativeViewConfig = {
accessibilityLabel: true,
accessibilityLiveRegion: true,
accessibilityRole: true,
- accessibilityStates: true,
+ accessibilityStates: true, // TODO: Can be removed after next release
accessibilityState: true,
+ accessibilityValue: true,
accessibilityViewIsModal: true,
accessible: true,
alignContent: true,
diff --git a/packages/react-native-win32/src/Libraries/Image/Image.win32.js b/packages/react-native-win32/src/Libraries/Image/Image.win32.js
index 330e2f62749..f9d678a9259 100644
--- a/packages/react-native-win32/src/Libraries/Image/Image.win32.js
+++ b/packages/react-native-win32/src/Libraries/Image/Image.win32.js
@@ -7,28 +7,23 @@
* @flow
* @format
*/
+
'use strict';
const DeprecatedImagePropType = require('../DeprecatedPropTypes/DeprecatedImagePropType');
-const NativeModules = require('../BatchedBridge/NativeModules');
const React = require('react');
const ReactNative = require('../Renderer/shims/ReactNative'); // eslint-disable-line no-unused-vars
const StyleSheet = require('../StyleSheet/StyleSheet');
const flattenStyle = require('../StyleSheet/flattenStyle');
-const requireNativeComponent = require('../ReactNative/requireNativeComponent');
const resolveAssetSource = require('./resolveAssetSource');
-const ImageViewManager = NativeModules.ImageViewManager;
-
-// [Windows
-const ImageLoader = NativeModules.ImageLoader; // [Win32 uses ImageLoader for getSize]
-const RCTImageView = requireNativeComponent('RCTImage'); // [Win32] Uses RCTImage instead of RCTImageView
-// Windows]
-
import type {ImageProps as ImagePropsType} from './ImageProps';
import type {ImageStyleProp} from '../StyleSheet/StyleSheet';
+import NativeImageLoaderWin32 from './NativeImageLoaderWin32'; // [Win32] Replace iOS
+
+const RCTImageView = require('./ImageViewNativeComponent');
function getSize(
uri: string,
@@ -37,17 +32,17 @@ function getSize(
) {
//[Win32
/*
- ImageViewManager.getSize(
- uri,
- success,
- failure ||
- function() {
- console.warn('Failed to get size for image: ' + uri);
- },
- );
+ NativeNativeImageLoaderWin32IOS.getSize(uri)
+ .then(([width, height]) => success(width, height))
+ .catch(
+ failure ||
+ function() {
+ console.warn('Failed to get size for image ' + uri);
+ },
+ );
*/
- ImageLoader.getSize(uri, (width: number, height: number, err?: string) => {
+ NativeImageLoaderWin32.getSize(uri, (width: number, height: number, err?: string) => {
if (!err) {
success(width, height);
} else {
@@ -63,11 +58,11 @@ function getSize(
function getSizeWithHeaders(
uri: string,
- headers: {[string]: string},
+ headers: {[string]: string, ...},
success: (width: number, height: number) => void,
failure?: (error: any) => void,
): any {
- return ImageViewManager.getSizeWithHeaders({uri, headers})
+ return NativeImageLoaderWin32.getSizeWithHeaders(uri, headers)
.then(function(sizes) {
success(sizes.width, sizes.height);
})
@@ -80,23 +75,23 @@ function getSizeWithHeaders(
}
function prefetch(url: string): any {
- return ImageViewManager.prefetchImage(url);
+ return NativeImageLoaderWin32.prefetchImage(url);
}
async function queryCache(
urls: Array,
-): Promise<{[string]: 'memory' | 'disk' | 'disk/memory'}> {
- return await ImageViewManager.queryCache(urls);
+): Promise<{[string]: 'memory' | 'disk' | 'disk/memory', ...}> {
+ return await NativeImageLoaderWin32.queryCache(urls);
}
-declare class ImageComponentType extends ReactNative.NativeComponent {
- static getSize: typeof getSize;
- static getSizeWithHeaders: typeof getSizeWithHeaders;
- static prefetch: typeof prefetch;
- static queryCache: typeof queryCache;
- static resolveAssetSource: typeof resolveAssetSource;
- static propTypes: typeof DeprecatedImagePropType;
-}
+type ImageComponentStatics = $ReadOnly<{|
+ getSize: typeof getSize,
+ getSizeWithHeaders: typeof getSizeWithHeaders,
+ prefetch: typeof prefetch,
+ queryCache: typeof queryCache,
+ resolveAssetSource: typeof resolveAssetSource,
+ propTypes: typeof DeprecatedImagePropType,
+|}>;
/**
* A React component for displaying different types of images,
@@ -105,10 +100,7 @@ declare class ImageComponentType extends ReactNative.NativeComponent,
-) => {
+let Image = (props: ImagePropsType, forwardedRef) => {
const source = resolveAssetSource(props.source) || {
uri: undefined,
width: undefined,
@@ -159,7 +151,9 @@ let Image = (
);
};
-Image = React.forwardRef(Image);
+Image = React.forwardRef>(
+ Image,
+);
Image.displayName = 'Image';
/**
@@ -225,7 +219,8 @@ const styles = StyleSheet.create({
},
});
-/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an
- * error found when Flow v0.89 was deployed. To see the error, delete this
- * comment and run Flow. */
-module.exports = (Image: Class);
+module.exports = ((Image: any): React.AbstractComponent<
+ ImagePropsType,
+ React.ElementRef,
+> &
+ ImageComponentStatics);
diff --git a/packages/react-native-win32/src/Libraries/Image/ImageViewNativeComponent.win32.js b/packages/react-native-win32/src/Libraries/Image/ImageViewNativeComponent.win32.js
new file mode 100644
index 00000000000..6174c3ec5a0
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Image/ImageViewNativeComponent.win32.js
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @format
+ * @flow strict-local
+ */
+
+'use strict';
+
+const requireNativeComponent = require('../ReactNative/requireNativeComponent');
+
+import codegenNativeComponent from '../Utilities/codegenNativeComponent';
+
+import type {DangerouslyImpreciseStyle} from '../StyleSheet/StyleSheet';
+import type {ResolvedAssetSource} from './AssetSourceResolver';
+import type {HostComponent} from '../Renderer/shims/ReactNativeTypes';
+import type {ImageProps} from './ImageProps';
+import type {ViewProps} from '../Components/View/ViewPropTypes';
+import type {ImageStyleProp} from '../StyleSheet/StyleSheet';
+import type {ColorValue} from '../StyleSheet/StyleSheetTypes';
+
+type NativeProps = $ReadOnly<{|
+ ...ImageProps,
+ ...ViewProps,
+
+ style?: ImageStyleProp | DangerouslyImpreciseStyle,
+
+ // iOS native props
+ tintColor?: ColorValue,
+
+ // Android native props
+ shouldNotifyLoadEvents?: boolean,
+ src?: ?ResolvedAssetSource | $ReadOnlyArray<{uri: string, ...}>,
+ headers?: ?string,
+ defaultSrc?: ?string,
+ loadingIndicatorSrc?: ?string,
+|}>;
+
+let ImageViewNativeComponent;
+
+if (global.RN$Bridgeless) {
+ ImageViewNativeComponent = codegenNativeComponent(
+ 'RCTImage', // [Win32] Rename RCTImageView to RCTImage
+ );
+} else {
+ ImageViewNativeComponent = requireNativeComponent(
+ 'RCTImage', // [Win32] Rename RCTImageView to RCTImage
+ );
+}
+
+module.exports = (ImageViewNativeComponent: HostComponent);
diff --git a/packages/react-native-win32/src/Libraries/Image/NativeImageLoaderWin32.js b/packages/react-native-win32/src/Libraries/Image/NativeImageLoaderWin32.js
new file mode 100644
index 00000000000..a3cd9baf480
--- /dev/null
+++ b/packages/react-native-win32/src/Libraries/Image/NativeImageLoaderWin32.js
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ * @format
+ */
+
+'use strict';
+
+import type {TurboModule} from '../TurboModule/RCTExport';
+import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
+
+export interface Spec extends TurboModule {
+ +getConstants: () => {||};
+ // [Win32 uses callback instead of promise
+ +getSize: (uri: string, callback: (width: number, height: number, err?: string) => void) => void;
+ // Win32]
+
+ // [Win32 These aren't actually implemented, and will just blow up if called
+ // currently.
+ +getSizeWithHeaders: (
+ uri: string,
+ headers: Object,
+ ) => Promise<{
+ width: number,
+ height: number,
+ ...
+ }>;
+ +prefetchImage: (uri: string) => Promise;
+ +queryCache: (uris: Array) => Promise