diff --git a/.ado/compliance.yml b/.ado/compliance.yml
index 3831667368b..415cf0e0ba5 100644
--- a/.ado/compliance.yml
+++ b/.ado/compliance.yml
@@ -6,10 +6,10 @@ parameters:
default:
Medium:
name: rnw-pool-4-microsoft
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Large:
name: rnw-pool-8-microsoft
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
- name: forceCodeQL
displayName: Force CodeQL to rebuild databases
type: boolean
diff --git a/.ado/continuous.yml b/.ado/continuous.yml
index 9d916c4ddf9..f20e680ad11 100644
--- a/.ado/continuous.yml
+++ b/.ado/continuous.yml
@@ -13,13 +13,13 @@ parameters:
default:
Small:
name: rnw-pool-2
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Medium:
name: rnw-pool-4
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Large:
name: rnw-pool-8
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
stages:
- template: stages.yml
diff --git a/.ado/jobs/macos-tests.yml b/.ado/jobs/macos-tests.yml
index e18ab775dbf..d6c57809455 100644
--- a/.ado/jobs/macos-tests.yml
+++ b/.ado/jobs/macos-tests.yml
@@ -14,6 +14,7 @@ jobs:
- template: ../templates/prepare-js-env.yml
parameters:
agentImage: HostedImage
+ fixupCommands: false
- script: yarn test
displayName: yarn test
diff --git a/.ado/jobs/node-tests.yml b/.ado/jobs/node-tests.yml
index 2ca57e4495d..ef1167cefa2 100644
--- a/.ado/jobs/node-tests.yml
+++ b/.ado/jobs/node-tests.yml
@@ -12,7 +12,7 @@ parameters:
- name: versions
type: object
- default: [18]
+ default: [22]
jobs:
- ${{ each nodeVersion in parameters.versions }}:
diff --git a/.ado/jobs/setup.yml b/.ado/jobs/setup.yml
index 2a22ebf0103..adcfab566c3 100644
--- a/.ado/jobs/setup.yml
+++ b/.ado/jobs/setup.yml
@@ -14,6 +14,11 @@ jobs:
pool: {vmImage: ubuntu-latest}
steps:
+ - task: UseNode@1
+ inputs:
+ version: '22.14.0'
+ displayName: 'Use Node.js 22.14.0'
+
- template: ../templates/checkout-full.yml
parameters:
persistCredentials: true # Git creds needed for beachball
diff --git a/.ado/publish.yml b/.ado/publish.yml
index b5663b3c8f7..dafc177afd4 100644
--- a/.ado/publish.yml
+++ b/.ado/publish.yml
@@ -22,10 +22,10 @@ parameters:
default:
Medium:
name: rnw-pool-4-microsoft
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Large:
name: rnw-pool-8-microsoft
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
- name: desktopBuildMatrix
type: object
diff --git a/.ado/scripts/npmAddUser.js b/.ado/scripts/npmAddUser.js
index d8e77ee4099..c9f7f769f5e 100644
--- a/.ado/scripts/npmAddUser.js
+++ b/.ado/scripts/npmAddUser.js
@@ -2,6 +2,9 @@
// @ts-check
const child_process = require("child_process");
+const fs = require("fs");
+const path = require("path");
+const os = require("os");
const username = process.argv[2];
const password = process.argv[3];
@@ -23,18 +26,54 @@ if (!email) {
process.exit(1);
}
-const child = child_process.exec(`npm adduser${registry? (' --registry ' + registry) :''}` );
-
-child.stdout.on("data", d => {
- const data = d.toString();
- process.stdout.write(d + "\n");
- if (data.match(/username/i)) {
- child.stdin.write(username + "\n");
- } else if (data.match(/password/i)) {
- child.stdin.write(password + "\n");
- } else if (data.match(/email/i)) {
- child.stdin.write(email + "\n");
- } else if (data.match(/logged in as/i)) {
- child.stdin.end();
- }
+const registryUrl = registry || "http://localhost:4873";
+
+// First set the registry
+console.log(`Setting npm registry to ${registryUrl}`);
+const setRegistry = child_process.spawnSync('npm', ['config', 'set', 'registry', registryUrl], {
+ stdio: 'inherit',
+ shell: true
});
+
+if (setRegistry.status !== 0) {
+ console.error('Failed to set registry');
+ process.exit(1);
+}
+
+// Create auth token for verdaccio
+const authString = Buffer.from(`${username}:${password}`).toString('base64');
+const registryPath = registryUrl.replace(/^https?:/, '');
+
+// Set auth in npm config
+console.log('Setting authentication...');
+const setAuth = child_process.spawnSync('npm', ['config', 'set', `${registryPath}/:_auth`, authString], {
+ stdio: 'inherit',
+ shell: true
+});
+
+if (setAuth.status !== 0) {
+ console.error('Failed to set auth');
+ process.exit(1);
+}
+
+// Set email
+const setEmail = child_process.spawnSync('npm', ['config', 'set', 'email', email], {
+ stdio: 'inherit',
+ shell: true
+});
+
+// Verify authentication
+console.log('Verifying authentication...');
+const whoami = child_process.spawnSync('npm', ['whoami', '--registry', registryUrl], {
+ encoding: 'utf8',
+ shell: true
+});
+
+if (whoami.status === 0 && whoami.stdout.trim()) {
+ console.log(`Logged in as ${whoami.stdout.trim()} on ${registryUrl}`);
+ process.exit(0);
+} else {
+ console.error('Authentication verification failed');
+ if (whoami.stderr) console.error('Error:', whoami.stderr);
+ process.exit(1);
+}
diff --git a/.ado/templates/prepare-js-env.yml b/.ado/templates/prepare-js-env.yml
index 46dd12a4cf4..7719c91f5dc 100644
--- a/.ado/templates/prepare-js-env.yml
+++ b/.ado/templates/prepare-js-env.yml
@@ -5,17 +5,20 @@ parameters:
values:
- ManagedImage
- HostedImage
-
+ - name: fixupCommands
+ type: boolean
+ default: true
steps:
- ${{ if eq(parameters.agentImage, 'HostedImage') }}:
- task: NodeTool@0
displayName: Set Node Version
inputs:
- versionSpec: '18.x'
+ versionSpec: '22.x'
- template: yarn-install.yml
parameters:
agentImage: ${{ parameters.agentImage }}
+ fixupCommands: ${{ parameters.fixupCommands }}
- script: yarn build
displayName: yarn build
diff --git a/.ado/templates/yarn-install.yml b/.ado/templates/yarn-install.yml
index 74d3d6757dc..03da09b8b1f 100644
--- a/.ado/templates/yarn-install.yml
+++ b/.ado/templates/yarn-install.yml
@@ -8,6 +8,9 @@ parameters:
values:
- ManagedImage
- HostedImage
+- name: fixupCommands
+ type: boolean
+ default: true
steps:
# When using our own images, prefer the machine-installed version of
@@ -21,3 +24,6 @@ steps:
- ${{ else }}:
- script: npx --yes midgard-yarn@1.23.34 --ignore-scripts --frozen-lockfile --cwd ${{ parameters.workingDirectory }}
displayName: midgard-yarn (faster yarn install)
+
+ - ${{ if eq(parameters.fixupCommands, true) }}:
+ - script: npx -y yarn-fix-bin-cmds@1.0.3 --path vnext/node_modules/.bin
diff --git a/.ado/windows-vs-pr-secure.yml b/.ado/windows-vs-pr-secure.yml
index 6ae1ac5c4c1..3601bce96c8 100644
--- a/.ado/windows-vs-pr-secure.yml
+++ b/.ado/windows-vs-pr-secure.yml
@@ -16,13 +16,13 @@ parameters:
default:
Small:
name: rnw-pool-2
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Medium:
name: rnw-pool-4
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Large:
name: rnw-pool-8
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
stages:
- template: stages.yml
diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml
index d4ba949f7a7..ae79db81131 100644
--- a/.ado/windows-vs-pr.yml
+++ b/.ado/windows-vs-pr.yml
@@ -16,13 +16,13 @@ parameters:
default:
Small:
name: rnw-pool-2
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Medium:
name: rnw-pool-4
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
Large:
name: rnw-pool-8
- demands: ImageOverride -equals rnw-img-vs2022-node18
+ demands: ImageOverride -equals rnw-img-vs2022-node22
stages:
- template: stages.yml
diff --git a/.unbroken_exclusions b/.unbroken_exclusions
index ebdbc8ea753..1e736d3db8f 100644
--- a/.unbroken_exclusions
+++ b/.unbroken_exclusions
@@ -2,6 +2,7 @@ URL not found https://docs.github.com/pull-requests/collaborating-with-pull-requ
URL not found https://docs.github.com/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks while parsing CONTRIBUTING.md (HTTP 403)
URL not found https://docs.github.com/get-started/quickstart while parsing CONTRIBUTING.md (HTTP 403)
File not found edge:/inspect while parsing packages/playground/README_composition.md
+File not found ./edge:/inspect while parsing packages/playground/README_composition.md
!**/node_modules
!vnext/packages
!vnext/ReactCopies
diff --git a/change/@office-iss-react-native-win32-ec84cc30-559c-4cb8-ae7b-94815d6f195a.json b/change/@office-iss-react-native-win32-ec84cc30-559c-4cb8-ae7b-94815d6f195a.json
new file mode 100644
index 00000000000..1a4a618de95
--- /dev/null
+++ b/change/@office-iss-react-native-win32-ec84cc30-559c-4cb8-ae7b-94815d6f195a.json
@@ -0,0 +1,7 @@
+{
+ "type": "patch",
+ "comment": "Bump flow-bin",
+ "packageName": "@office-iss/react-native-win32",
+ "email": "30809111+acoates-ms@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/@react-native-windows-cli-e061ce36-6ba5-4936-9e88-d2d10574fc2f.json b/change/@react-native-windows-cli-e061ce36-6ba5-4936-9e88-d2d10574fc2f.json
new file mode 100644
index 00000000000..ce4b52cc810
--- /dev/null
+++ b/change/@react-native-windows-cli-e061ce36-6ba5-4936-9e88-d2d10574fc2f.json
@@ -0,0 +1,7 @@
+{
+ "type": "patch",
+ "comment": "Upgrade dotnet version",
+ "packageName": "@react-native-windows/cli",
+ "email": "30809111+acoates-ms@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-1efdb03b-a0af-4ffa-a274-a0c43f757681.json b/change/react-native-windows-1efdb03b-a0af-4ffa-a274-a0c43f757681.json
new file mode 100644
index 00000000000..a4bd58f9a3b
--- /dev/null
+++ b/change/react-native-windows-1efdb03b-a0af-4ffa-a274-a0c43f757681.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "updated ellipsis to respect tail and clip behaviour , for head , middle follow defaulty tail behaviour",
+ "packageName": "react-native-windows",
+ "email": "74712637+iamAbhi-916@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-1ff7a358-a5fe-45d6-8df4-ecd913ae9509.json b/change/react-native-windows-1ff7a358-a5fe-45d6-8df4-ecd913ae9509.json
new file mode 100644
index 00000000000..0bc83ccc34c
--- /dev/null
+++ b/change/react-native-windows-1ff7a358-a5fe-45d6-8df4-ecd913ae9509.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "PointerEvent fixes",
+ "packageName": "react-native-windows",
+ "email": "30809111+acoates-ms@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-262555bf-8b8f-4511-b814-9ed70a0cb8b4.json b/change/react-native-windows-262555bf-8b8f-4511-b814-9ed70a0cb8b4.json
new file mode 100644
index 00000000000..23ab17fba1e
--- /dev/null
+++ b/change/react-native-windows-262555bf-8b8f-4511-b814-9ed70a0cb8b4.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "Implementation of adjustFontSizeToFit for Text in Fabric",
+ "packageName": "react-native-windows",
+ "email": "kvineeth@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-4046d3e2-cc00-459e-b62d-4489b3ef14d1.json b/change/react-native-windows-4046d3e2-cc00-459e-b62d-4489b3ef14d1.json
new file mode 100644
index 00000000000..d16b5587b17
--- /dev/null
+++ b/change/react-native-windows-4046d3e2-cc00-459e-b62d-4489b3ef14d1.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "[Fabric] Fix for Text and TextInput focus issue with screen readers.",
+ "packageName": "react-native-windows",
+ "email": "kvineeth@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-47643b4d-f7e0-4d08-9fa1-f3612b5a39db.json b/change/react-native-windows-47643b4d-f7e0-4d08-9fa1-f3612b5a39db.json
new file mode 100644
index 00000000000..9d8c311271e
--- /dev/null
+++ b/change/react-native-windows-47643b4d-f7e0-4d08-9fa1-f3612b5a39db.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "TextInput should capture mouse on mouse down",
+ "packageName": "react-native-windows",
+ "email": "30809111+acoates-ms@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-595c068c-640d-4645-a3e4-d6d23bf99c79.json b/change/react-native-windows-595c068c-640d-4645-a3e4-d6d23bf99c79.json
new file mode 100644
index 00000000000..91ab9678287
--- /dev/null
+++ b/change/react-native-windows-595c068c-640d-4645-a3e4-d6d23bf99c79.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "[Fabric] Implement maxFontSizeMultiplier in Text Input",
+ "packageName": "react-native-windows",
+ "email": "54227869+anupriya13@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-82bcd92e-18b7-42d0-b6f0-dc428b565d5d.json b/change/react-native-windows-82bcd92e-18b7-42d0-b6f0-dc428b565d5d.json
new file mode 100644
index 00000000000..96c1bac678b
--- /dev/null
+++ b/change/react-native-windows-82bcd92e-18b7-42d0-b6f0-dc428b565d5d.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "[Fabric] Implementation of accessibilityDescription",
+ "packageName": "react-native-windows",
+ "email": "kvineeth@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-99f88013-45df-4134-99df-b0fb86dc5e88.json b/change/react-native-windows-99f88013-45df-4134-99df-b0fb86dc5e88.json
new file mode 100644
index 00000000000..88a4d392a1f
--- /dev/null
+++ b/change/react-native-windows-99f88013-45df-4134-99df-b0fb86dc5e88.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "Implement SpellCheck and AutoCorrect for TextInput",
+ "packageName": "react-native-windows",
+ "email": "54227869+anupriya13@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-ab19ebb9-8059-4b42-81a2-08dbc6639dfc.json b/change/react-native-windows-ab19ebb9-8059-4b42-81a2-08dbc6639dfc.json
new file mode 100644
index 00000000000..bdcd92c1c5c
--- /dev/null
+++ b/change/react-native-windows-ab19ebb9-8059-4b42-81a2-08dbc6639dfc.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "updated adjustsFontSizeToFit textlayout to nullptr",
+ "packageName": "react-native-windows",
+ "email": "74712637+iamAbhi-916@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-b21e071e-d9f2-45d1-92d6-b65b6246555b.json b/change/react-native-windows-b21e071e-d9f2-45d1-92d6-b65b6246555b.json
new file mode 100644
index 00000000000..c3022810b3e
--- /dev/null
+++ b/change/react-native-windows-b21e071e-d9f2-45d1-92d6-b65b6246555b.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "adding UIA event handler changes for navigator",
+ "packageName": "react-native-windows",
+ "email": "protikbiswas100@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-b47cf142-681b-41f5-8ac6-d07b04f55165.json b/change/react-native-windows-b47cf142-681b-41f5-8ac6-d07b04f55165.json
new file mode 100644
index 00000000000..8bf6a73898e
--- /dev/null
+++ b/change/react-native-windows-b47cf142-681b-41f5-8ac6-d07b04f55165.json
@@ -0,0 +1,7 @@
+{
+ "type": "none",
+ "comment": "Added support for selectionColor for textInput",
+ "packageName": "react-native-windows",
+ "email": "74712637+iamAbhi-916@users.noreply.github.com",
+ "dependentChangeType": "none"
+}
diff --git a/change/react-native-windows-bcf77be5-d1cd-4b1a-9756-3de4607890e5.json b/change/react-native-windows-bcf77be5-d1cd-4b1a-9756-3de4607890e5.json
new file mode 100644
index 00000000000..6ebe164b659
--- /dev/null
+++ b/change/react-native-windows-bcf77be5-d1cd-4b1a-9756-3de4607890e5.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "[Fabric] Raising UIA Event if Toggle State Changes in Switch Component",
+ "packageName": "react-native-windows",
+ "email": "kvineeth@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-c4bfd448-6ad1-4e13-a027-b84c8a29a5e4.json b/change/react-native-windows-c4bfd448-6ad1-4e13-a027-b84c8a29a5e4.json
new file mode 100644
index 00000000000..575e08fca39
--- /dev/null
+++ b/change/react-native-windows-c4bfd448-6ad1-4e13-a027-b84c8a29a5e4.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": " Changes for updating accessibilityValue prop in UIA",
+ "packageName": "react-native-windows",
+ "email": "kvineeth@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json b/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json
new file mode 100644
index 00000000000..f68dfc5830b
--- /dev/null
+++ b/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "ITextProvider Implementation",
+ "packageName": "react-native-windows",
+ "email": "34109996+chiaramooney@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-db520a88-144d-4212-8c94-89bf7aa0fbff.json b/change/react-native-windows-db520a88-144d-4212-8c94-89bf7aa0fbff.json
new file mode 100644
index 00000000000..1654012e887
--- /dev/null
+++ b/change/react-native-windows-db520a88-144d-4212-8c94-89bf7aa0fbff.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "Added fix for AutoFocus",
+ "packageName": "react-native-windows",
+ "email": "hmalothu@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/react-native-windows-f1078f0f-499f-408a-acd3-e969096b6dea.json b/change/react-native-windows-f1078f0f-499f-408a-acd3-e969096b6dea.json
new file mode 100644
index 00000000000..8921202ec9e
--- /dev/null
+++ b/change/react-native-windows-f1078f0f-499f-408a-acd3-e969096b6dea.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "[Fabric] Implement onContentSizeChange in TextInput",
+ "packageName": "react-native-windows",
+ "email": "54227869+anupriya13@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/package.json b/package.json
index 277fd78adbd..8c22dbbdf45 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"doc": "doxysaurus --config vnext/doxysaurus.json",
"format": "format-files -i -style=file",
"format:verify": "format-files -i -style=file -verify",
- "postinstall": "yarn build",
+ "postinstall": "npx -y yarn-fix-bin-cmds --path vnext\\node_modules\\.bin && yarn build",
"spellcheck": "npx cspell",
"test": "lage test --verbose",
"validate-overrides": "react-native-platform-override validate"
diff --git a/packages/@office-iss/react-native-win32/package.json b/packages/@office-iss/react-native-win32/package.json
index 3eb9a904a26..eb0beacb61a 100644
--- a/packages/@office-iss/react-native-win32/package.json
+++ b/packages/@office-iss/react-native-win32/package.json
@@ -81,7 +81,7 @@
"@types/prop-types": "15.7.1",
"@types/react": "^18.2.6",
"eslint": "^8.19.0",
- "flow-bin": "^0.217.2",
+ "flow-bin": "^0.228.0",
"jscodeshift": "^0.14.0",
"just-scripts": "^1.3.3",
"prettier": "2.8.8",
diff --git a/packages/@react-native-windows/cli/src/commands/healthCheck/healthCheckList.ts b/packages/@react-native-windows/cli/src/commands/healthCheck/healthCheckList.ts
index 1cf697bfe9f..4c2b7d56552 100644
--- a/packages/@react-native-windows/cli/src/commands/healthCheck/healthCheckList.ts
+++ b/packages/@react-native-windows/cli/src/commands/healthCheck/healthCheckList.ts
@@ -14,5 +14,5 @@ export const HealthCheckList = [
[true, 'VSUWP', 'Visual Studio 2022 (>= 17.11.0) & req. components'],
[true, 'Node', 'Node.js (LTS, >= 18.0)'],
[true, 'Yarn', 'Yarn'],
- [true, 'DotNetCore', '.NET SDK (LTS, = 6.0)'],
+ [true, 'DotNetCore', '.NET SDK (LTS, = 8.0)'],
];
diff --git a/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx b/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx
index 2c3ffef60bb..39761f9f94f 100644
--- a/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx
+++ b/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx
@@ -24,6 +24,17 @@ class AccessibilityBaseExample extends React.Component {
style={{width: 50, height: 50, backgroundColor: 'blue'}}
accessibilityLabel="A blue box"
accessibilityHint="A hint for the blue box."
+ accessibilityLevel={1}
+ accessibilityItemType="comment"
+ accessibilityAccessKey="accessKey"
+ accessibilityDescription="Sample Description"
+ accessibilityAnnotation={{
+ typeID: 'Comment',
+ typeName: 'Check Comment',
+ author: 'Clint Westwood',
+ dateTime: '3/19/2025 1:03 PM',
+ }}
+ testID="accessibility-base-view-1"
/>
The following has accessible and accessibilityLabel:
{
await app.waitUntil(
async () => {
await searchBox.setValue(input);
- return (await searchBox.getText()) === input;
+ if (input === '') {
+ return (await searchBox.getText()) === 'Search...';
+ } else {
+ return (await searchBox.getText()) === input;
+ }
},
{
interval: 1500,
diff --git a/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts b/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts
index 6993b7c8898..962cfda5420 100644
--- a/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts
+++ b/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts
@@ -45,7 +45,7 @@ describe('Pressable Tests', () => {
await app.waitUntil(
async () => {
await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']);
- return (await searchBox.getText()) === '';
+ return (await searchBox.getText()) === 'Search...';
},
{
interval: 1500,
@@ -84,7 +84,7 @@ describe('Pressable Tests', () => {
await app.waitUntil(
async () => {
await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']);
- return (await searchBox.getText()) === '';
+ return (await searchBox.getText()) === 'Search...';
},
{
interval: 1500,
@@ -118,7 +118,7 @@ describe('Pressable Tests', () => {
await app.waitUntil(
async () => {
await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']);
- return (await searchBox.getText()) === '';
+ return (await searchBox.getText()) === 'Search...';
},
{
interval: 1500,
@@ -152,7 +152,7 @@ describe('Pressable Tests', () => {
await app.waitUntil(
async () => {
await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']);
- return (await searchBox.getText()) === '';
+ return (await searchBox.getText()) === 'Search...';
},
{
interval: 1500,
@@ -181,7 +181,7 @@ describe('Pressable Tests', () => {
await app.waitUntil(
async () => {
await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']);
- return (await searchBox.getText()) === '';
+ return (await searchBox.getText()) === 'Search...';
},
{
interval: 1500,
@@ -210,7 +210,7 @@ describe('Pressable Tests', () => {
await app.waitUntil(
async () => {
await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']);
- return (await searchBox.getText()) === '';
+ return (await searchBox.getText()) === 'Search...';
},
{
interval: 1500,
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap
index b70e1b1ac77..41968769ec3 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap
@@ -17,6 +17,7 @@ exports[`Accessibility Tests Components can store range data by setting the min,
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "The View's (accessibilityRole == adjustable, ie. Slider) properties should be the following according to UIA: Min- 5Max- 125Now- 10",
+ "TextRangePattern.GetText": "The View's (accessibilityRole == adjustable, ie. Slider) properties should be the following according to UIA: Min- 5Max- 125Now- 10",
},
],
},
@@ -73,6 +74,7 @@ exports[`Accessibility Tests Components can store value data by setting the text
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "The View's properties should be the following according to UIA: Text- testText",
+ "TextRangePattern.GetText": "The View's properties should be the following according to UIA: Text- testText",
},
],
},
@@ -129,6 +131,7 @@ exports[`Accessibility Tests Elements can set accessibilityState:selected to fal
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Unselected",
+ "TextRangePattern.GetText": "Unselected",
},
],
},
@@ -187,6 +190,7 @@ exports[`Accessibility Tests Elements can set accessibilityState:selected to tru
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Selected",
+ "TextRangePattern.GetText": "Selected",
},
],
},
@@ -252,6 +256,7 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Unselected",
+ "TextRangePattern.GetText": "Unselected",
},
],
},
@@ -267,6 +272,7 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Unselected",
+ "TextRangePattern.GetText": "Unselected",
},
],
},
@@ -282,6 +288,7 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Unselected",
+ "TextRangePattern.GetText": "Unselected",
},
],
},
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap
index 88c0c104b4c..2fb2a911fef 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap
@@ -16,6 +16,7 @@ exports[`Button Tests Buttons can be disabled 1`] = `
"IsEnabled": false,
"LocalizedControlType": "text",
"Name": "Submit Application",
+ "TextRangePattern.GetText": "Submit Application",
},
],
},
@@ -163,6 +164,7 @@ exports[`Button Tests Buttons can have accessibility labels 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Submit Application",
+ "TextRangePattern.GetText": "Submit Application",
},
],
},
@@ -311,6 +313,7 @@ exports[`Button Tests Buttons can have accessibility props 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Submit Application",
+ "TextRangePattern.GetText": "Submit Application",
},
],
},
@@ -442,6 +445,7 @@ exports[`Button Tests Buttons can have accessibility states 1`] = `
"IsEnabled": false,
"LocalizedControlType": "text",
"Name": "Submit Application",
+ "TextRangePattern.GetText": "Submit Application",
},
],
},
@@ -589,6 +593,7 @@ exports[`Button Tests Buttons can have custom colors 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Cancel Application",
+ "TextRangePattern.GetText": "Cancel Application",
},
],
},
@@ -851,6 +856,7 @@ exports[`Button Tests Buttons can have custom focusable and accessible props 2`]
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Button with focusable=false",
+ "TextRangePattern.GetText": "Button with focusable=false",
},
],
},
@@ -1100,6 +1106,7 @@ exports[`Button Tests Buttons can have flexbox styling 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Cancel",
+ "TextRangePattern.GetText": "Cancel",
},
],
},
@@ -1115,6 +1122,7 @@ exports[`Button Tests Buttons can have flexbox styling 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Submit",
+ "TextRangePattern.GetText": "Submit",
},
],
},
@@ -1426,6 +1434,7 @@ exports[`Button Tests Buttons can have flexbox styling with three buttons 1`] =
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Cancel",
+ "TextRangePattern.GetText": "Cancel",
},
],
},
@@ -1441,6 +1450,7 @@ exports[`Button Tests Buttons can have flexbox styling with three buttons 1`] =
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Save For Later",
+ "TextRangePattern.GetText": "Save For Later",
},
],
},
@@ -1456,6 +1466,7 @@ exports[`Button Tests Buttons can have flexbox styling with three buttons 1`] =
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Submit",
+ "TextRangePattern.GetText": "Submit",
},
],
},
@@ -1896,6 +1907,7 @@ exports[`Button Tests Buttons have default styling 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Submit Application",
+ "TextRangePattern.GetText": "Submit Application",
},
],
},
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap
index da3f507c5fe..02e656b38f7 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap
@@ -13,6 +13,7 @@ exports[`Home UIA Tree Dump APIs Tab 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "APIs",
+ "TextRangePattern.GetText": "APIs",
},
],
},
@@ -113,30 +114,35 @@ exports[`Home UIA Tree Dump Accessibility 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Accessibility",
+ "TextRangePattern.GetText": "Accessibility",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples of using Accessibility APIs.",
+ "TextRangePattern.GetText": "Examples of using Accessibility APIs.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -258,30 +264,35 @@ exports[`Home UIA Tree Dump Accessibility Windows 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Accessibility Windows",
+ "TextRangePattern.GetText": "Accessibility Windows",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Usage of accessibility properties.",
+ "TextRangePattern.GetText": "Usage of accessibility properties.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -403,30 +414,35 @@ exports[`Home UIA Tree Dump AccessibilityInfo 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "AccessibilityInfo",
+ "TextRangePattern.GetText": "AccessibilityInfo",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples of using AccessibilityInfo APIs.",
+ "TextRangePattern.GetText": "Examples of using AccessibilityInfo APIs.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -548,30 +564,35 @@ exports[`Home UIA Tree Dump ActivityIndicator 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ActivityIndicator",
+ "TextRangePattern.GetText": "ActivityIndicator",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Animated loading indicators.",
+ "TextRangePattern.GetText": "Animated loading indicators.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -693,30 +714,35 @@ exports[`Home UIA Tree Dump Alerts 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Alerts",
+ "TextRangePattern.GetText": "Alerts",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Alerts display a concise and informative message and prompt the user to make a decision.",
+ "TextRangePattern.GetText": "Alerts display a concise and informative message and prompt the user to make a decision.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -838,30 +864,35 @@ exports[`Home UIA Tree Dump Animated - Gratuitous App 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Animated - Gratuitous App",
+ "TextRangePattern.GetText": "Animated - Gratuitous App",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Bunch of Animations - tap a circle to open a view with more animations, or longPress and drag to reorder circles.",
+ "TextRangePattern.GetText": "Bunch of Animations - tap a circle to open a view with more animations, or longPress and drag to reorder circles.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -983,30 +1014,35 @@ exports[`Home UIA Tree Dump Animated 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Animated",
+ "TextRangePattern.GetText": "Animated",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Library designed to make animations fluid, powerful, and painless to build and maintain.",
+ "TextRangePattern.GetText": "Library designed to make animations fluid, powerful, and painless to build and maintain.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -1128,30 +1164,35 @@ exports[`Home UIA Tree Dump AppState 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "AppState",
+ "TextRangePattern.GetText": "AppState",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "app background status",
+ "TextRangePattern.GetText": "app background status",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -1273,30 +1314,35 @@ exports[`Home UIA Tree Dump Appearance 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Appearance",
+ "TextRangePattern.GetText": "Appearance",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Light and dark user interface examples.",
+ "TextRangePattern.GetText": "Light and dark user interface examples.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -1418,30 +1464,35 @@ exports[`Home UIA Tree Dump Border 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Border",
+ "TextRangePattern.GetText": "Border",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demonstrates some of the border styles available to Views.",
+ "TextRangePattern.GetText": "Demonstrates some of the border styles available to Views.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -1563,30 +1614,35 @@ exports[`Home UIA Tree Dump Button 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Button",
+ "TextRangePattern.GetText": "Button",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Simple React Native button component.",
+ "TextRangePattern.GetText": "Simple React Native button component.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -1707,6 +1763,7 @@ exports[`Home UIA Tree Dump Components Tab 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Components",
+ "TextRangePattern.GetText": "Components",
},
],
},
@@ -1847,30 +1904,35 @@ exports[`Home UIA Tree Dump Composition Bugs Example 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Composition Bugs Example",
+ "TextRangePattern.GetText": "Composition Bugs Example",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "See bugs in UI.Composition driven native animations",
+ "TextRangePattern.GetText": "See bugs in UI.Composition driven native animations",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -1992,30 +2054,35 @@ exports[`Home UIA Tree Dump Crash 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Crash",
+ "TextRangePattern.GetText": "Crash",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Crash examples.",
+ "TextRangePattern.GetText": "Crash examples.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -2137,30 +2204,35 @@ exports[`Home UIA Tree Dump Cxx TurboModule 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Cxx TurboModule",
+ "TextRangePattern.GetText": "Cxx TurboModule",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Usage of Cxx TurboModule",
+ "TextRangePattern.GetText": "Usage of Cxx TurboModule",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -2282,30 +2354,35 @@ exports[`Home UIA Tree Dump DevSettings 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "DevSettings",
+ "TextRangePattern.GetText": "DevSettings",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Customize the development settings",
+ "TextRangePattern.GetText": "Customize the development settings",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -2427,30 +2504,35 @@ exports[`Home UIA Tree Dump Dimensions 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Dimensions",
+ "TextRangePattern.GetText": "Dimensions",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Dimensions of the viewport",
+ "TextRangePattern.GetText": "Dimensions of the viewport",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -2572,30 +2654,35 @@ exports[`Home UIA Tree Dump Display:none Style 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Display:none Style",
+ "TextRangePattern.GetText": "Display:none Style",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Style prop which will collapse the element in XAML tree.",
+ "TextRangePattern.GetText": "Style prop which will collapse the element in XAML tree.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -2717,30 +2804,35 @@ exports[`Home UIA Tree Dump Fabric Native Component 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Fabric Native Component",
+ "TextRangePattern.GetText": "Fabric Native Component",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Sample Fabric Native Component that sizes based on max desired size of native XAML contained within",
+ "TextRangePattern.GetText": "Sample Fabric Native Component that sizes based on max desired size of native XAML contained within",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -2862,30 +2954,35 @@ exports[`Home UIA Tree Dump Fabric Native Component Yoga 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Fabric Native Component Yoga",
+ "TextRangePattern.GetText": "Fabric Native Component Yoga",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Sample Fabric Native Component that places native XAML inside a container sized by yoga",
+ "TextRangePattern.GetText": "Sample Fabric Native Component that places native XAML inside a container sized by yoga",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3007,30 +3104,35 @@ exports[`Home UIA Tree Dump Fast Path Texts 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Fast Path Texts",
+ "TextRangePattern.GetText": "Fast Path Texts",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples of performant fast path texts, turn on IsTextPerformanceVisualizationEnabled to visualize examples",
+ "TextRangePattern.GetText": "Examples of performant fast path texts, turn on IsTextPerformanceVisualizationEnabled to visualize examples",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3152,30 +3254,35 @@ exports[`Home UIA Tree Dump FlatList 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "FlatList",
+ "TextRangePattern.GetText": "FlatList",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Performant, scrollable list of data.",
+ "TextRangePattern.GetText": "Performant, scrollable list of data.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ListView",
+ "TextRangePattern.GetText": "ListView",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3297,30 +3404,35 @@ exports[`Home UIA Tree Dump Flyout 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Flyout",
+ "TextRangePattern.GetText": "Flyout",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Displays content on top of existing content, within the bounds of the application window.",
+ "TextRangePattern.GetText": "Displays content on top of existing content, within the bounds of the application window.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3442,30 +3554,35 @@ exports[`Home UIA Tree Dump Glyph UWP 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Glyph UWP",
+ "TextRangePattern.GetText": "Glyph UWP",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Usage of Glyph control.",
+ "TextRangePattern.GetText": "Usage of Glyph control.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3587,30 +3704,35 @@ exports[`Home UIA Tree Dump Image 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Image",
+ "TextRangePattern.GetText": "Image",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Base component for displaying different types of images.",
+ "TextRangePattern.GetText": "Base component for displaying different types of images.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3732,30 +3854,35 @@ exports[`Home UIA Tree Dump Keyboard 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Keyboard",
+ "TextRangePattern.GetText": "Keyboard",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demonstrates usage of the "Keyboard" static API",
+ "TextRangePattern.GetText": "Demonstrates usage of the "Keyboard" static API",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -3877,30 +4004,35 @@ exports[`Home UIA Tree Dump Keyboard 2`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Keyboard",
+ "TextRangePattern.GetText": "Keyboard",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demonstrates usage of the "Keyboard" static API",
+ "TextRangePattern.GetText": "Demonstrates usage of the "Keyboard" static API",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4022,30 +4154,35 @@ exports[`Home UIA Tree Dump Keyboard Focus Example 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Keyboard Focus Example",
+ "TextRangePattern.GetText": "Keyboard Focus Example",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demo of keyboard focus.",
+ "TextRangePattern.GetText": "Demo of keyboard focus.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4167,30 +4304,35 @@ exports[`Home UIA Tree Dump Keyboard extension Example 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Keyboard extension Example",
+ "TextRangePattern.GetText": "Keyboard extension Example",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demo of keyboard properties.",
+ "TextRangePattern.GetText": "Demo of keyboard properties.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4312,30 +4454,35 @@ exports[`Home UIA Tree Dump Layout - Flexbox 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Layout - Flexbox",
+ "TextRangePattern.GetText": "Layout - Flexbox",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples of using the flexbox API to layout views.",
+ "TextRangePattern.GetText": "Examples of using the flexbox API to layout views.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4457,30 +4604,35 @@ exports[`Home UIA Tree Dump Layout Events 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Layout Events",
+ "TextRangePattern.GetText": "Layout Events",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples that show how Layout events can be used to measure view size and position.",
+ "TextRangePattern.GetText": "Examples that show how Layout events can be used to measure view size and position.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4602,30 +4754,35 @@ exports[`Home UIA Tree Dump Legacy Native Module 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy Native Module",
+ "TextRangePattern.GetText": "Legacy Native Module",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Usage of legacy Native Module",
+ "TextRangePattern.GetText": "Usage of legacy Native Module",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4747,30 +4904,35 @@ exports[`Home UIA Tree Dump LegacyControlStyleTest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "LegacyControlStyleTest",
+ "TextRangePattern.GetText": "LegacyControlStyleTest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy e2e test for Control Styles",
+ "TextRangePattern.GetText": "Legacy e2e test for Control Styles",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -4892,30 +5054,35 @@ exports[`Home UIA Tree Dump LegacyImageTest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "LegacyImageTest",
+ "TextRangePattern.GetText": "LegacyImageTest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy e2e test for Image",
+ "TextRangePattern.GetText": "Legacy e2e test for Image",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5037,30 +5204,35 @@ exports[`Home UIA Tree Dump LegacyLoginTest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "LegacyLoginTest",
+ "TextRangePattern.GetText": "LegacyLoginTest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy e2e test for TextInput with password",
+ "TextRangePattern.GetText": "Legacy e2e test for TextInput with password",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5182,30 +5354,35 @@ exports[`Home UIA Tree Dump LegacySelectableTextTest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "LegacySelectableTextTest",
+ "TextRangePattern.GetText": "LegacySelectableTextTest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy e2e test for selectable Text hit testing",
+ "TextRangePattern.GetText": "Legacy e2e test for selectable Text hit testing",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5327,30 +5504,35 @@ exports[`Home UIA Tree Dump LegacyTextHitTestTest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "LegacyTextHitTestTest",
+ "TextRangePattern.GetText": "LegacyTextHitTestTest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy e2e test for Text hit testing",
+ "TextRangePattern.GetText": "Legacy e2e test for Text hit testing",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5472,30 +5654,35 @@ exports[`Home UIA Tree Dump LegacyTextInputTest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "LegacyTextInputTest",
+ "TextRangePattern.GetText": "LegacyTextInputTest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Legacy e2e test for TextInput",
+ "TextRangePattern.GetText": "Legacy e2e test for TextInput",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5617,30 +5804,35 @@ exports[`Home UIA Tree Dump Linking 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Linking",
+ "TextRangePattern.GetText": "Linking",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Shows how to use Linking to open URLs.",
+ "TextRangePattern.GetText": "Shows how to use Linking to open URLs.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5762,30 +5954,35 @@ exports[`Home UIA Tree Dump Modal 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Modal",
+ "TextRangePattern.GetText": "Modal",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Component for presenting modal views.",
+ "TextRangePattern.GetText": "Component for presenting modal views.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -5907,30 +6104,35 @@ exports[`Home UIA Tree Dump Mouse Click Events 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Mouse Click Events",
+ "TextRangePattern.GetText": "Mouse Click Events",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Tests that mouse click events work on intended components",
+ "TextRangePattern.GetText": "Tests that mouse click events work on intended components",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6052,30 +6254,35 @@ exports[`Home UIA Tree Dump Mouse Events 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Mouse Events",
+ "TextRangePattern.GetText": "Mouse Events",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Tests that mouse events can be observed",
+ "TextRangePattern.GetText": "Tests that mouse events can be observed",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6197,30 +6404,35 @@ exports[`Home UIA Tree Dump Native Animated Example 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Native Animated Example",
+ "TextRangePattern.GetText": "Native Animated Example",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Test out Native Animations",
+ "TextRangePattern.GetText": "Test out Native Animations",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6342,30 +6554,35 @@ exports[`Home UIA Tree Dump New App Screen 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "New App Screen",
+ "TextRangePattern.GetText": "New App Screen",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Displays the content of the new app screen",
+ "TextRangePattern.GetText": "Displays the content of the new app screen",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6487,30 +6704,35 @@ exports[`Home UIA Tree Dump PanResponder Sample 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "PanResponder Sample",
+ "TextRangePattern.GetText": "PanResponder Sample",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Shows the Use of PanResponder to provide basic gesture handling",
+ "TextRangePattern.GetText": "Shows the Use of PanResponder to provide basic gesture handling",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6632,30 +6854,35 @@ exports[`Home UIA Tree Dump Performance API Examples 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Performance API Examples",
+ "TextRangePattern.GetText": "Performance API Examples",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Shows the performance API provided in React Native",
+ "TextRangePattern.GetText": "Shows the performance API provided in React Native",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6777,30 +7004,35 @@ exports[`Home UIA Tree Dump Performance Comparison Examples 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Performance Comparison Examples",
+ "TextRangePattern.GetText": "Performance Comparison Examples",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Compare performance with bad and good examples. Use React DevTools to highlight re-renders is recommended.",
+ "TextRangePattern.GetText": "Compare performance with bad and good examples. Use React DevTools to highlight re-renders is recommended.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -6922,30 +7154,35 @@ exports[`Home UIA Tree Dump PlatformColor 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "PlatformColor",
+ "TextRangePattern.GetText": "PlatformColor",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples that show how PlatformColors may be used in an app.",
+ "TextRangePattern.GetText": "Examples that show how PlatformColors may be used in an app.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7067,30 +7304,35 @@ exports[`Home UIA Tree Dump Pointer Events 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pointer Events",
+ "TextRangePattern.GetText": "Pointer Events",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demonstrates the use of the pointerEvents prop of a View to control how touches should be handled.",
+ "TextRangePattern.GetText": "Demonstrates the use of the pointerEvents prop of a View to control how touches should be handled.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7212,30 +7454,35 @@ exports[`Home UIA Tree Dump Popup 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Popup",
+ "TextRangePattern.GetText": "Popup",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Displays content on top of existing content, within the bounds of the application window.",
+ "TextRangePattern.GetText": "Displays content on top of existing content, within the bounds of the application window.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7357,30 +7604,35 @@ exports[`Home UIA Tree Dump Pressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressable",
+ "TextRangePattern.GetText": "Pressable",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Component for making views pressable.",
+ "TextRangePattern.GetText": "Component for making views pressable.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7502,30 +7754,35 @@ exports[`Home UIA Tree Dump RTLExample 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "RTLExample",
+ "TextRangePattern.GetText": "RTLExample",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Examples to show how to apply components to RTL layout.",
+ "TextRangePattern.GetText": "Examples to show how to apply components to RTL layout.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7647,30 +7904,35 @@ exports[`Home UIA Tree Dump ScrollView 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ScrollView",
+ "TextRangePattern.GetText": "ScrollView",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Component that enables scrolling through child components",
+ "TextRangePattern.GetText": "Component that enables scrolling through child components",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7792,30 +8054,35 @@ exports[`Home UIA Tree Dump ScrollViewAnimated 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ScrollViewAnimated",
+ "TextRangePattern.GetText": "ScrollViewAnimated",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Component that is animated when ScrollView is offset.",
+ "TextRangePattern.GetText": "Component that is animated when ScrollView is offset.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -7937,30 +8204,35 @@ exports[`Home UIA Tree Dump ScrollViewSimpleExample 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ScrollViewSimpleExample",
+ "TextRangePattern.GetText": "ScrollViewSimpleExample",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Component that enables scrolling through child components.",
+ "TextRangePattern.GetText": "Component that enables scrolling through child components.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -8077,6 +8349,7 @@ exports[`Home UIA Tree Dump Search Bar 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Search...",
+ "TextRangePattern.GetText": "Search...",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -8191,30 +8464,35 @@ exports[`Home UIA Tree Dump SectionList 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "SectionList",
+ "TextRangePattern.GetText": "SectionList",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Performant, scrollable list of data.",
+ "TextRangePattern.GetText": "Performant, scrollable list of data.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ListView",
+ "TextRangePattern.GetText": "ListView",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -8336,30 +8614,35 @@ exports[`Home UIA Tree Dump Share 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Share",
+ "TextRangePattern.GetText": "Share",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Share data with other Apps.",
+ "TextRangePattern.GetText": "Share data with other Apps.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -8481,30 +8764,35 @@ exports[`Home UIA Tree Dump SwipeableCard 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "SwipeableCard",
+ "TextRangePattern.GetText": "SwipeableCard",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Example of a swipeable card with scrollable content to test PanResponder and JSResponderHandler interaction.",
+ "TextRangePattern.GetText": "Example of a swipeable card with scrollable content to test PanResponder and JSResponderHandler interaction.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -8626,30 +8914,35 @@ exports[`Home UIA Tree Dump Switch 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Switch",
+ "TextRangePattern.GetText": "Switch",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Native boolean input",
+ "TextRangePattern.GetText": "Native boolean input",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -8771,30 +9064,35 @@ exports[`Home UIA Tree Dump Text 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Text",
+ "TextRangePattern.GetText": "Text",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Base component for rendering styled text.",
+ "TextRangePattern.GetText": "Base component for rendering styled text.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -8916,30 +9214,35 @@ exports[`Home UIA Tree Dump TextInput 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "TextInput",
+ "TextRangePattern.GetText": "TextInput",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Single and multi-line text inputs.",
+ "TextRangePattern.GetText": "Single and multi-line text inputs.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9061,30 +9364,35 @@ exports[`Home UIA Tree Dump TextInputs with key prop 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "TextInputs with key prop",
+ "TextRangePattern.GetText": "TextInputs with key prop",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Periodically render large number of TextInputs with key prop without a Runtime Error",
+ "TextRangePattern.GetText": "Periodically render large number of TextInputs with key prop without a Runtime Error",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Other",
+ "TextRangePattern.GetText": "Other",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9206,30 +9514,35 @@ exports[`Home UIA Tree Dump Timers 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Timers",
+ "TextRangePattern.GetText": "Timers",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "A demonstration of Timers in React Native.",
+ "TextRangePattern.GetText": "A demonstration of Timers in React Native.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9351,30 +9664,35 @@ exports[`Home UIA Tree Dump Touchable* and onPress 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Touchable* and onPress",
+ "TextRangePattern.GetText": "Touchable* and onPress",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Touchable and onPress examples.",
+ "TextRangePattern.GetText": "Touchable and onPress examples.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9496,30 +9814,35 @@ exports[`Home UIA Tree Dump TransferProperties 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "TransferProperties",
+ "TextRangePattern.GetText": "TransferProperties",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Some tests that change the backing XAML element to see if transfer properties is working.",
+ "TextRangePattern.GetText": "Some tests that change the backing XAML element to see if transfer properties is working.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9641,30 +9964,35 @@ exports[`Home UIA Tree Dump Transforms 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Transforms",
+ "TextRangePattern.GetText": "Transforms",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "View transforms",
+ "TextRangePattern.GetText": "View transforms",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9786,30 +10114,35 @@ exports[`Home UIA Tree Dump TransparentHitTestExample 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "TransparentHitTestExample",
+ "TextRangePattern.GetText": "TransparentHitTestExample",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Transparent view receiving touch events",
+ "TextRangePattern.GetText": "Transparent view receiving touch events",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -9931,30 +10264,35 @@ exports[`Home UIA Tree Dump TurboModule 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "TurboModule",
+ "TextRangePattern.GetText": "TurboModule",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Usage of TurboModule",
+ "TextRangePattern.GetText": "Usage of TurboModule",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -10076,30 +10414,35 @@ exports[`Home UIA Tree Dump View 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "View",
+ "TextRangePattern.GetText": "View",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic building block of all UI, examples that demonstrate some of the many styles available.",
+ "TextRangePattern.GetText": "Basic building block of all UI, examples that demonstrate some of the many styles available.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -10221,30 +10564,35 @@ exports[`Home UIA Tree Dump WebSocket 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "WebSocket",
+ "TextRangePattern.GetText": "WebSocket",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "WebSocket API",
+ "TextRangePattern.GetText": "WebSocket API",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -10366,30 +10714,35 @@ exports[`Home UIA Tree Dump XAML 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "XAML",
+ "TextRangePattern.GetText": "XAML",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Usage of react-native-xaml controls",
+ "TextRangePattern.GetText": "Usage of react-native-xaml controls",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "UI",
+ "TextRangePattern.GetText": "UI",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
@@ -10511,30 +10864,35 @@ exports[`Home UIA Tree Dump XMLHttpRequest 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "XMLHttpRequest",
+ "TextRangePattern.GetText": "XMLHttpRequest",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Example that demonstrates upload and download requests using XMLHttpRequest.",
+ "TextRangePattern.GetText": "Example that demonstrates upload and download requests using XMLHttpRequest.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Basic",
+ "TextRangePattern.GetText": "Basic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "iOS",
+ "TextRangePattern.GetText": "iOS",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Android",
+ "TextRangePattern.GetText": "Android",
},
],
},
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap
index ce6e3103926..c42747b7cf3 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap
@@ -7,6 +7,7 @@ exports[`LegacySelectableTextTest DoubleClickWhenNotSelectable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 2 times.",
+ "TextRangePattern.GetText": "Pressed: 2 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -30,6 +31,7 @@ exports[`LegacySelectableTextTest DoubleClickWhenSelectable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 2 times.",
+ "TextRangePattern.GetText": "Pressed: 2 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -53,6 +55,7 @@ exports[`LegacySelectableTextTest PressableWhenNotSelectable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -76,6 +79,7 @@ exports[`LegacySelectableTextTest PressableWhenSelectable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap
index 7e960e55cf3..7053c9e22c3 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap
@@ -7,6 +7,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 2 times.",
+ "TextRangePattern.GetText": "Pressed: 2 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -30,6 +31,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextPressableEdgeCaseNotPressable 1`
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -53,6 +55,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextSeparateRunsEdgeCasePressable 1`
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -76,6 +79,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextSeparateRunsPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 2 times.",
+ "TextRangePattern.GetText": "Pressed: 2 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -99,6 +103,7 @@ exports[`LegacyTextHitTestTest InsertedVirtualTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -122,6 +127,7 @@ exports[`LegacyTextHitTestTest LTRTextInRTLFlowPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -145,6 +151,7 @@ exports[`LegacyTextHitTestTest MultilineRTLTextEdgeCaseNotPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -168,6 +175,7 @@ exports[`LegacyTextHitTestTest MultilineRTLTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 2 times.",
+ "TextRangePattern.GetText": "Pressed: 2 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -191,6 +199,7 @@ exports[`LegacyTextHitTestTest MultilineTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -214,6 +223,7 @@ exports[`LegacyTextHitTestTest RTLTextInRTLFlowPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -237,6 +247,7 @@ exports[`LegacyTextHitTestTest RTLTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -260,6 +271,7 @@ exports[`LegacyTextHitTestTest TextPressableWithVirtualText 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -283,6 +295,7 @@ exports[`LegacyTextHitTestTest ToggleVirtualTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -306,6 +319,7 @@ exports[`LegacyTextHitTestTest VirtualTextPressable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressed: 1 times.",
+ "TextRangePattern.GetText": "Pressed: 1 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -328,7 +342,8 @@ exports[`LegacyTextHitTestTest WrappedLTRInRTLFlowEdgeCaseNotPressable 1`] = `
"AutomationId": "pressed-state",
"ControlType": 50020,
"LocalizedControlType": "text",
- "Name": "Pressed: 1 times.",
+ "Name": "Pressed: 0 times.",
+ "TextRangePattern.GetText": "Pressed: 0 times.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap
index c0322d06b38..f0208b453be 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap
@@ -7,6 +7,8 @@ exports[`LegacyTextInputTest Click on TextInput to focus 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "onFocus
+",
+ "TextRangePattern.GetText": "onFocus
",
},
"Component Tree": {
@@ -32,6 +34,9 @@ exports[`LegacyTextInputTest Click on multiline TextInput to move focus away fro
"LocalizedControlType": "text",
"Name": "onBlur
onFocus
+",
+ "TextRangePattern.GetText": "onBlur
+onFocus
",
},
"Component Tree": {
@@ -98,6 +103,50 @@ onKeyPress key: a
onFocus
onBlur
onFocus
+",
+ "TextRangePattern.GetText": "onChange text: a
+onSelectionChange range: 1,1
+onKeyPress key: a
+onChange text:
+onSelectionChange range: 0,0
+onFocus
+onBlur
+onSubmitEditing text: abc
+onChange text: abc
+onSelectionChange range: 3,3
+onKeyPress key: c
+onChange text: ab
+onSelectionChange range: 2,2
+onKeyPress key: b
+onChange text: a
+onSelectionChange range: 1,1
+onKeyPress key: a
+onChange text:
+onSelectionChange range: 0,0
+onChange text: def
+onSelectionChange range: 3,3
+onKeyPress key: f
+onChange text: de
+onSelectionChange range: 2,2
+onKeyPress key: e
+onChange text: d
+onSelectionChange range: 1,1
+onKeyPress key: d
+onChange text:
+onSelectionChange range: 0,0
+onChange text: abc
+onSelectionChange range: 3,3
+onKeyPress key: c
+onChange text: ab
+onSelectionChange range: 2,2
+onKeyPress key: b
+onChange text: a
+onChange text: a
+onSelectionChange range: 1,1
+onKeyPress key: a
+onFocus
+onBlur
+onFocus
",
},
"Component Tree": {
@@ -109,7 +158,7 @@ onFocus
"Visual Tree": {
"Comment": "textinput-log",
"Offset": "0, 0, 0",
- "Size": "998, 820",
+ "Size": "998, 616",
"Visual Type": "SpriteVisual",
},
}
@@ -134,6 +183,20 @@ onKeyPress key: a
onFocus
onBlur
onFocus
+",
+ "TextRangePattern.GetText": "onChange text: abc
+onSelectionChange range: 3,3
+onKeyPress key: c
+onChange text: ab
+onSelectionChange range: 2,2
+onKeyPress key: b
+onChange text: a
+onChange text: a
+onSelectionChange range: 1,1
+onKeyPress key: a
+onFocus
+onBlur
+onFocus
",
},
"Component Tree": {
@@ -193,6 +256,43 @@ onKeyPress key: a
onFocus
onBlur
onFocus
+",
+ "TextRangePattern.GetText": "onSubmitEditing text: abc
+onChange text: abc
+onSelectionChange range: 3,3
+onKeyPress key: c
+onChange text: ab
+onSelectionChange range: 2,2
+onKeyPress key: b
+onChange text: a
+onSelectionChange range: 1,1
+onKeyPress key: a
+onChange text:
+onSelectionChange range: 0,0
+onChange text: def
+onSelectionChange range: 3,3
+onKeyPress key: f
+onChange text: de
+onSelectionChange range: 2,2
+onKeyPress key: e
+onChange text: d
+onSelectionChange range: 1,1
+onKeyPress key: d
+onChange text:
+onSelectionChange range: 0,0
+onChange text: abc
+onSelectionChange range: 3,3
+onKeyPress key: c
+onChange text: ab
+onSelectionChange range: 2,2
+onKeyPress key: b
+onChange text: a
+onChange text: a
+onSelectionChange range: 1,1
+onKeyPress key: a
+onFocus
+onBlur
+onFocus
",
},
"Component Tree": {
@@ -204,7 +304,7 @@ onFocus
"Visual Tree": {
"Comment": "textinput-log",
"Offset": "0, 0, 0",
- "Size": "998, 690",
+ "Size": "998, 616",
"Visual Type": "SpriteVisual",
},
}
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap
index cc6cccbd4fb..a1b66b73e0e 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap
@@ -13,6 +13,7 @@ exports[`Pressable Tests Pressables can be disabled, disabled = {false} 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Enabled Pressable",
+ "TextRangePattern.GetText": "Enabled Pressable",
},
],
},
@@ -65,6 +66,7 @@ exports[`Pressable Tests Pressables can be disabled, disabled = {true} 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Disabled Pressable",
+ "TextRangePattern.GetText": "Disabled Pressable",
},
],
},
@@ -119,6 +121,7 @@ exports[`Pressable Tests Pressables can change style when pressed 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Me",
+ "TextRangePattern.GetText": "Press Me",
},
],
},
@@ -168,6 +171,7 @@ exports[`Pressable Tests Pressables can change text on press/rest, state rest 1`
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Me",
+ "TextRangePattern.GetText": "Press Me",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -191,6 +195,7 @@ exports[`Pressable Tests Pressables can change text on press/rest, state rest 2`
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "onPress",
+ "TextRangePattern.GetText": "onPress",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -220,6 +225,7 @@ exports[`Pressable Tests Pressables can have advanced borders 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Outside This View",
+ "TextRangePattern.GetText": "Press Outside This View",
},
],
},
@@ -275,6 +281,7 @@ exports[`Pressable Tests Pressables can have delayed event handlers 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Me",
+ "TextRangePattern.GetText": "Press Me",
},
],
},
@@ -325,12 +332,14 @@ exports[`Pressable Tests Pressables can have delayed event handlers 2`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "pressOut",
+ "TextRangePattern.GetText": "pressOut",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "pressIn",
+ "TextRangePattern.GetText": "pressIn",
},
],
},
@@ -443,6 +452,7 @@ exports[`Pressable Tests Pressables can have event handlers 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Me",
+ "TextRangePattern.GetText": "Press Me",
},
],
},
@@ -494,24 +504,28 @@ exports[`Pressable Tests Pressables can have event handlers 2`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "pressOut",
+ "TextRangePattern.GetText": "pressOut",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "press",
+ "TextRangePattern.GetText": "press",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "pressIn",
+ "TextRangePattern.GetText": "pressIn",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "hover in",
+ "TextRangePattern.GetText": "hover in",
},
],
},
@@ -655,6 +669,7 @@ exports[`Pressable Tests Pressables can have hit slop functionality 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Outside This View",
+ "TextRangePattern.GetText": "Press Outside This View",
},
],
},
@@ -1059,6 +1074,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressable with accessible=true and focusable=true",
+ "TextRangePattern.GetText": "Pressable with accessible=true and focusable=true",
},
],
},
@@ -1067,6 +1083,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressable with accessible=false",
+ "TextRangePattern.GetText": "Pressable with accessible=false",
},
{
"AutomationId": "",
@@ -1078,6 +1095,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressable with focusable=false",
+ "TextRangePattern.GetText": "Pressable with focusable=false",
},
],
},
@@ -1086,6 +1104,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressable with accessible=false and focusable=false",
+ "TextRangePattern.GetText": "Pressable with accessible=false and focusable=false",
},
],
},
@@ -1265,6 +1284,7 @@ exports[`Pressable Tests Pressables can have tooltips 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Pressable with ToolTip "Pressable"",
+ "TextRangePattern.GetText": "Pressable with ToolTip "Pressable"",
},
],
},
@@ -1315,6 +1335,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "View #1, front is visible, back is hidden.",
+ "TextRangePattern.GetText": "View #1, front is visible, back is hidden.",
},
{
"AutomationId": "",
@@ -1327,6 +1348,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Front",
+ "TextRangePattern.GetText": "Front",
},
],
},
@@ -1341,6 +1363,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Back (You should not see this)",
+ "TextRangePattern.GetText": "Back (You should not see this)",
},
],
},
@@ -1349,6 +1372,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "View #2, front is hidden, back is visible.",
+ "TextRangePattern.GetText": "View #2, front is hidden, back is visible.",
},
{
"AutomationId": "",
@@ -1361,6 +1385,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Front (You should not see this)",
+ "TextRangePattern.GetText": "Front (You should not see this)",
},
],
},
@@ -1375,6 +1400,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Back",
+ "TextRangePattern.GetText": "Back",
},
],
},
@@ -1598,6 +1624,7 @@ exports[`Pressable Tests Text can have pressable behavior 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Text has built-in onPress handling",
+ "TextRangePattern.GetText": "Text has built-in onPress handling",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -1621,6 +1648,7 @@ exports[`Pressable Tests Text can have pressable behavior 2`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "2x text onPress",
+ "TextRangePattern.GetText": "2x text onPress",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap
index a7ba4d2a645..f3bb0cfe118 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap
@@ -13,6 +13,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to bottom butto
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Scroll to bottom",
+ "TextRangePattern.GetText": "Scroll to bottom",
},
],
},
@@ -68,6 +69,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to end button 1
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Scroll to end",
+ "TextRangePattern.GetText": "Scroll to end",
},
],
},
@@ -123,6 +125,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to start button
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Scroll to start",
+ "TextRangePattern.GetText": "Scroll to start",
},
],
},
@@ -178,6 +181,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to top button 1
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Scroll to top",
+ "TextRangePattern.GetText": "Scroll to top",
},
],
},
@@ -233,6 +237,7 @@ exports[`ScrollView Tests ScrollViews has flash scroll indicators 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Flash scroll indicators",
+ "TextRangePattern.GetText": "Flash scroll indicators",
},
],
},
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap
index a4705382ab9..ac66934effe 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap
@@ -7,6 +7,7 @@ exports[`Text Tests Padding can be added to Text 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "This text is indented by 10px padding on all sides.",
+ "TextRangePattern.GetText": "This text is indented by 10px padding on all sides.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -17,7 +18,7 @@ exports[`Text Tests Padding can be added to Text 1`] = `
"Visual Tree": {
"Comment": "text-padding",
"Offset": "0, 0, 0",
- "Size": "834, 39",
+ "Size": "834, 40",
"Visual Type": "SpriteVisual",
},
}
@@ -30,6 +31,7 @@ exports[`Text Tests Text can be restricted to one line 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Maximum of one line no matter now much I write here. If I keep writing it'll just truncate after one line. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus felis eget augue condimentum suscipit. Suspendisse hendrerit, libero aliquet malesuada tempor, urna nibh consectetur tellus, vitae efficitur quam erat non mi. Maecenas vitae eros sit amet quam vestibulum porta sed sit amet tellus. Fusce quis lectus congue, fringilla arcu id, luctus urna. Cras sagittis ornare mauris sit amet dictum. Vestibulum feugiat laoreet fringilla. Vivamus ac diam vehicula felis venenatis sagittis vitae ultrices elit. Curabitur libero augue, laoreet quis orci vitae, congue euismod massa. Aenean nec odio sed urna vehicula fermentum non a magna. Quisque ut commodo neque, eget eleifend odio. Sed sit amet lacinia sem. Suspendisse in metus in purus scelerisque vestibulum. Nam metus dui, efficitur nec metus non, tincidunt pharetra sapien. Praesent id convallis metus, ut malesuada arcu. Quisque quam libero, pharetra eu tellus ac, aliquam fringilla erat. Quisque tempus in lorem ac suscipit.",
+ "TextRangePattern.GetText": "Maximum of one line no matter now much I write here. If I keep writing it'll just truncate after one line. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus felis eget augue condimentum suscipit. Suspendisse hendrerit, libero aliquet malesuada tempor, urna nibh consectetur tellus, vitae efficitur quam erat non mi. Maecenas vitae eros sit amet quam vestibulum porta sed sit amet tellus. Fusce quis lectus congue, fringilla arcu id, luctus urna. Cras sagittis ornare mauris sit amet dictum. Vestibulum feugiat laoreet fringilla. Vivamus ac diam vehicula felis venenatis sagittis vitae ultrices elit. Curabitur libero augue, laoreet quis orci vitae, congue euismod massa. Aenean nec odio sed urna vehicula fermentum non a magna. Quisque ut commodo neque, eget eleifend odio. Sed sit amet lacinia sem. Suspendisse in metus in purus scelerisque vestibulum. Nam metus dui, efficitur nec metus non, tincidunt pharetra sapien. Praesent id convallis metus, ut malesuada arcu. Quisque quam libero, pharetra eu tellus ac, aliquam fringilla erat. Quisque tempus in lorem ac suscipit.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -40,7 +42,7 @@ exports[`Text Tests Text can be restricted to one line 1`] = `
"Visual Tree": {
"Comment": "text-one-line",
"Offset": "0, 0, 0",
- "Size": "834, 19",
+ "Size": "834, 20",
"Visual Type": "SpriteVisual",
},
}
@@ -53,6 +55,7 @@ exports[`Text Tests Text can be selectable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "This text is selectable if you click-and-hold, and will offer the native Android selection menus.",
+ "TextRangePattern.GetText": "This text is selectable if you click-and-hold, and will offer the native Android selection menus.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -63,7 +66,7 @@ exports[`Text Tests Text can be selectable 1`] = `
"Visual Tree": {
"Comment": "text-selectable",
"Offset": "0, 0, 0",
- "Size": "834, 20",
+ "Size": "834, 19",
"Visual Type": "SpriteVisual",
},
}
@@ -76,6 +79,7 @@ exports[`Text Tests Text can have a color 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Red color",
+ "TextRangePattern.GetText": "Red color",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -86,7 +90,7 @@ exports[`Text Tests Text can have a color 1`] = `
"Visual Tree": {
"Comment": "text-color",
"Offset": "0, 0, 0",
- "Size": "834, 20",
+ "Size": "834, 19",
"Visual Type": "SpriteVisual",
},
}
@@ -99,6 +103,7 @@ exports[`Text Tests Text can have a customized selection color 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "This text will have a orange highlight on selection.",
+ "TextRangePattern.GetText": "This text will have a orange highlight on selection.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -109,7 +114,7 @@ exports[`Text Tests Text can have a customized selection color 1`] = `
"Visual Tree": {
"Comment": "text-selection-color",
"Offset": "0, 0, 0",
- "Size": "834, 19",
+ "Size": "834, 20",
"Visual Type": "SpriteVisual",
},
}
@@ -122,6 +127,7 @@ exports[`Text Tests Text can have a size 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Size 23",
+ "TextRangePattern.GetText": "Size 23",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -132,7 +138,7 @@ exports[`Text Tests Text can have a size 1`] = `
"Visual Tree": {
"Comment": "text-size",
"Offset": "0, 0, 0",
- "Size": "834, 32",
+ "Size": "834, 31",
"Visual Type": "SpriteVisual",
},
}
@@ -145,6 +151,7 @@ exports[`Text Tests Text can have an outer color 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "(Normal text,(R)red(G)green(B)blue(C)cyan(M)magenta(Y)yellow(K)black(and bold(and tiny bold italic blue(and tiny normal blue))))",
+ "TextRangePattern.GetText": "(Normal text,(R)red(G)green(B)blue(C)cyan(M)magenta(Y)yellow(K)black(and bold(and tiny bold italic blue(and tiny normal blue))))",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -155,7 +162,7 @@ exports[`Text Tests Text can have an outer color 1`] = `
"Visual Tree": {
"Comment": "text-outer-color",
"Offset": "0, 0, 0",
- "Size": "834, 20",
+ "Size": "834, 19",
"Visual Type": "SpriteVisual",
},
}
@@ -168,6 +175,7 @@ exports[`Text Tests Text can have decoration lines: Solid Line Through 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Solid line-through",
+ "TextRangePattern.GetText": "Solid line-through",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -191,6 +199,7 @@ exports[`Text Tests Text can have decoration lines: Underline 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Solid underline",
+ "TextRangePattern.GetText": "Solid underline",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -201,7 +210,7 @@ exports[`Text Tests Text can have decoration lines: Underline 1`] = `
"Visual Tree": {
"Comment": "text-decoration-underline",
"Offset": "0, 0, 0",
- "Size": "834, 20",
+ "Size": "834, 19",
"Visual Type": "SpriteVisual",
},
}
@@ -214,6 +223,7 @@ exports[`Text Tests Text can have shadows 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Demo text shadow",
+ "TextRangePattern.GetText": "Demo text shadow",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -224,7 +234,7 @@ exports[`Text Tests Text can have shadows 1`] = `
"Visual Tree": {
"Comment": "text-shadow",
"Offset": "0, 0, 0",
- "Size": "834, 27",
+ "Size": "834, 28",
"Visual Type": "SpriteVisual",
},
}
@@ -237,6 +247,7 @@ exports[`Text Tests Text can wrap 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "The text should wrap if it goes on multiple lines. See, this is going to the next line. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus felis eget augue condimentum suscipit. Suspendisse hendrerit, libero aliquet malesuada tempor, urna nibh consectetur tellus, vitae efficitur quam erat non mi. Maecenas vitae eros sit amet quam vestibulum porta sed sit amet tellus. Fusce quis lectus congue, fringilla arcu id, luctus urna. Cras sagittis ornare mauris sit amet dictum. Vestibulum feugiat laoreet fringilla. Vivamus ac diam vehicula felis venenatis sagittis vitae ultrices elit. Curabitur libero augue, laoreet quis orci vitae, congue euismod massa. Aenean nec odio sed urna vehicula fermentum non a magna. Quisque ut commodo neque, eget eleifend odio. Sed sit amet lacinia sem. Suspendisse in metus in purus scelerisque vestibulum. Nam metus dui, efficitur nec metus non, tincidunt pharetra sapien. Praesent id convallis metus, ut malesuada arcu. Quisque quam libero, pharetra eu tellus ac, aliquam fringilla erat. Quisque tempus in lorem ac suscipit.",
+ "TextRangePattern.GetText": "The text should wrap if it goes on multiple lines. See, this is going to the next line. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dapibus felis eget augue condimentum suscipit. Suspendisse hendrerit, libero aliquet malesuada tempor, urna nibh consectetur tellus, vitae efficitur quam erat non mi. Maecenas vitae eros sit amet quam vestibulum porta sed sit amet tellus. Fusce quis lectus congue, fringilla arcu id, luctus urna. Cras sagittis ornare mauris sit amet dictum. Vestibulum feugiat laoreet fringilla. Vivamus ac diam vehicula felis venenatis sagittis vitae ultrices elit. Curabitur libero augue, laoreet quis orci vitae, congue euismod massa. Aenean nec odio sed urna vehicula fermentum non a magna. Quisque ut commodo neque, eget eleifend odio. Sed sit amet lacinia sem. Suspendisse in metus in purus scelerisque vestibulum. Nam metus dui, efficitur nec metus non, tincidunt pharetra sapien. Praesent id convallis metus, ut malesuada arcu. Quisque quam libero, pharetra eu tellus ac, aliquam fringilla erat. Quisque tempus in lorem ac suscipit.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap
index 72173d3a1c2..7ed479a2935 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap
@@ -7,6 +7,8 @@ exports[`TextInput Tests Multi-line TextInputs can enable text selection (Impera
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "multiline text selection
+can also be changed imperatively",
"ValuePattern.Value": "multiline text selection
can also be changed imperatively",
},
@@ -84,6 +86,8 @@ exports[`TextInput Tests Multi-line TextInputs can enable text selection 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "multiline text selection
+can also be changed",
"ValuePattern.Value": "multiline text selection
can also be changed",
},
@@ -161,6 +165,7 @@ exports[`TextInput Tests Single-line TextInputs can enable text selection (Imper
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "text selection can be changed imperatively",
"ValuePattern.Value": "text selection can be changed imperatively",
},
"Component Tree": {
@@ -237,6 +242,7 @@ exports[`TextInput Tests Single-line TextInputs can enable text selection 1`] =
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "text selection can be changed",
"ValuePattern.Value": "text selection can be changed",
},
"Component Tree": {
@@ -315,6 +321,7 @@ exports[`TextInput Tests Text have cursorColor 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "cursorColor={"green"}",
+ "TextRangePattern.GetText": "Hello World",
"ValuePattern.Value": "Hello World",
},
"Component Tree": {
@@ -503,6 +510,7 @@ exports[`TextInput Tests TextInputs can autocomplete, address country 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "postal-address-country",
+ "TextRangePattern.GetText": "postal-address-country",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -580,6 +588,7 @@ exports[`TextInput Tests TextInputs can autocomplete, country 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "country",
+ "TextRangePattern.GetText": "country",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -657,6 +666,7 @@ exports[`TextInput Tests TextInputs can autocomplete, one-time-code 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "one-time-code",
+ "TextRangePattern.GetText": "one-time-code",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -734,6 +744,7 @@ exports[`TextInput Tests TextInputs can autocomplete, sms-otp 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "sms-otp",
+ "TextRangePattern.GetText": "sms-otp",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -809,6 +820,7 @@ exports[`TextInput Tests TextInputs can autogrow 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "small small small small small small",
"ValuePattern.Value": "small small small small small small",
},
"Component Tree": {
@@ -847,6 +859,7 @@ exports[`TextInput Tests TextInputs can be editable 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "editable text input using editable prop",
+ "TextRangePattern.GetText": "editable text input using editable prop",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -922,6 +935,7 @@ exports[`TextInput Tests TextInputs can be multiline, bottomright alignment 1`]
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "multiline with children, aligned bottom-right",
"ValuePattern.Value": "multiline with children, aligned bottom-right",
},
"Component Tree": {
@@ -960,6 +974,7 @@ exports[`TextInput Tests TextInputs can be multiline, center alignment 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "multiline, aligned center",
+ "TextRangePattern.GetText": "multiline, aligned center",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -997,6 +1012,7 @@ exports[`TextInput Tests TextInputs can be multiline, topleft alignment 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "multiline, aligned top-left",
+ "TextRangePattern.GetText": "multiline, aligned top-left",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -1032,6 +1048,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^",
"ValuePattern.Value": "Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^",
},
"Component Tree": {
@@ -1070,6 +1087,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 2 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "uneditable text input using editable prop",
+ "TextRangePattern.GetText": "uneditable text input using editable prop",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -1287,6 +1305,7 @@ exports[`TextInput Tests TextInputs can enable spellcheck 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Type text to test spell check functionality.",
+ "TextRangePattern.GetText": "Type text to test spell check functionality.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -1322,6 +1341,7 @@ exports[`TextInput Tests TextInputs can have a background color 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -1398,6 +1418,7 @@ exports[`TextInput Tests TextInputs can have a color 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -1474,6 +1495,7 @@ exports[`TextInput Tests TextInputs can have a font family 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -1550,6 +1572,7 @@ exports[`TextInput Tests TextInputs can have a font size 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -1626,6 +1649,7 @@ exports[`TextInput Tests TextInputs can have a font style 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -1702,6 +1726,7 @@ exports[`TextInput Tests TextInputs can have a font weight 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -1778,6 +1803,7 @@ exports[`TextInput Tests TextInputs can have attributed text 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Hello",
"ValuePattern.Value": "Hello",
},
"Component Tree": {
@@ -1856,6 +1882,7 @@ exports[`TextInput Tests TextInputs can have caretHidden 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "caretHidden={true}",
+ "TextRangePattern.GetText": "Hello World",
"ValuePattern.Value": "Hello World",
},
"Component Tree": {
@@ -1894,6 +1921,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, Compile 1`
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyLabel: Compile",
+ "TextRangePattern.GetText": "returnKeyLabel: Compile",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -1931,6 +1959,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, React Nati
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyLabel: React Native",
+ "TextRangePattern.GetText": "returnKeyLabel: React Native",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -1968,6 +1997,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, done 1`] =
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: done",
+ "TextRangePattern.GetText": "returnKeyType: done",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2005,6 +2035,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, go 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: go",
+ "TextRangePattern.GetText": "returnKeyType: go",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2042,6 +2073,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, next 1`] =
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: next",
+ "TextRangePattern.GetText": "returnKeyType: next",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2079,6 +2111,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, none 1`] =
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: none",
+ "TextRangePattern.GetText": "returnKeyType: none",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2116,6 +2149,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, previous 1`
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: previous",
+ "TextRangePattern.GetText": "returnKeyType: previous",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2153,6 +2187,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, search 1`]
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: search",
+ "TextRangePattern.GetText": "returnKeyType: search",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2190,6 +2225,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, send 1`] =
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "returnKeyType: send",
+ "TextRangePattern.GetText": "returnKeyType: send",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2227,6 +2263,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=-1
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "letterSpacing = -1",
+ "TextRangePattern.GetText": "letterSpacing = -1",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2264,6 +2301,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=0
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "letterSpacing = 0",
+ "TextRangePattern.GetText": "letterSpacing = 0",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2301,6 +2339,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=2
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "letterSpacing = 2",
+ "TextRangePattern.GetText": "letterSpacing = 2",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2338,6 +2377,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=9
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "letterSpacing = 9",
+ "TextRangePattern.GetText": "letterSpacing = 9",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2469,6 +2509,7 @@ exports[`TextInput Tests TextInputs can have customized letter spacing 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -2545,6 +2586,7 @@ exports[`TextInput Tests TextInputs can have customized line height 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Hel",
"ValuePattern.Value": "Hel",
},
"Component Tree": {
@@ -2623,6 +2665,7 @@ exports[`TextInput Tests TextInputs can have inline images 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "This has drawableLeft set",
+ "TextRangePattern.GetText": "This has drawableLeft set",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2660,6 +2703,7 @@ exports[`TextInput Tests TextInputs can have inline images, drawable props not s
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "This does not have drawable props set",
+ "TextRangePattern.GetText": "This does not have drawable props set",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2697,6 +2741,7 @@ exports[`TextInput Tests TextInputs can have inline images, drawableLeft and dra
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "This has drawableLeft and drawablePadding set",
+ "TextRangePattern.GetText": "This has drawableLeft and drawablePadding set",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2734,6 +2779,7 @@ exports[`TextInput Tests TextInputs can have shadows 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "shadowColor: purple",
+ "TextRangePattern.GetText": "shadowColor: purple",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2769,6 +2815,7 @@ exports[`TextInput Tests TextInputs can have text decoration lines 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -2845,6 +2892,7 @@ exports[`TextInput Tests TextInputs can have text shadows 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "He",
"ValuePattern.Value": "He",
},
"Component Tree": {
@@ -2923,6 +2971,7 @@ exports[`TextInput Tests TextInputs can propagate events 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Click inside the box to observe events being fired.",
+ "TextRangePattern.GetText": "Click inside the box to observe events being fired.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -2960,6 +3009,7 @@ exports[`TextInput Tests TextInputs can register press events 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Click inside the box to observe events being fired.",
+ "TextRangePattern.GetText": "Click inside the box to observe events being fired.",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3222,6 +3272,7 @@ exports[`TextInput Tests TextInputs can set their readOnly prop to false 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "editable text input using readOnly prop",
+ "TextRangePattern.GetText": "editable text input using readOnly prop",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3299,6 +3350,7 @@ exports[`TextInput Tests TextInputs can set their readOnly prop to true 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "uneditable text input using readOnly prop",
+ "TextRangePattern.GetText": "uneditable text input using readOnly prop",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3409,6 +3461,7 @@ exports[`TextInput Tests TextInputs have a custom background color 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Same BackgroundColor as View ",
"ValuePattern.Value": "Same BackgroundColor as View ",
},
"Component Tree": {
@@ -3445,6 +3498,7 @@ exports[`TextInput Tests TextInputs have a custom highlight color 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Selection Color is red",
"ValuePattern.Value": "Selection Color is red",
},
"Component Tree": {
@@ -3483,6 +3537,7 @@ exports[`TextInput Tests TextInputs have a custom placeholder text color 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Red placeholder text color",
+ "TextRangePattern.GetText": "Red placeholder text color",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3518,6 +3573,7 @@ exports[`TextInput Tests TextInputs have a custom text color 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Green Text",
"ValuePattern.Value": "Green Text",
},
"Component Tree": {
@@ -3556,6 +3612,7 @@ exports[`TextInput Tests TextInputs have a custom underline color 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Blue underline color",
+ "TextRangePattern.GetText": "Blue underline color",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3593,6 +3650,7 @@ exports[`TextInput Tests TextInputs have a default placeholder text color 1`] =
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Default placeholder text color",
+ "TextRangePattern.GetText": "Default placeholder text color",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3628,6 +3686,7 @@ exports[`TextInput Tests TextInputs have a default text color 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Default color text",
"ValuePattern.Value": "Default color text",
},
"Component Tree": {
@@ -3666,6 +3725,7 @@ exports[`TextInput Tests TextInputs have a default underline color 1`] = `
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "Default underline color",
+ "TextRangePattern.GetText": "Default underline color",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3701,6 +3761,7 @@ exports[`TextInput Tests TextInputs support secure entry 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "iloveturtles",
"ValuePattern.Value": "iloveturtles",
},
"Component Tree": {
@@ -3739,6 +3800,7 @@ exports[`TextInput Tests TextInputs support secure entry, with placeholder text
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "color is supported too",
+ "TextRangePattern.GetText": "color is supported too",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3776,6 +3838,7 @@ exports[`TextInput Tests TextInputs with set height and padding from theme 1`] =
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
"Name": "If you set height, beware of padding set from themes",
+ "TextRangePattern.GetText": "If you set height, beware of padding set from themes",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
@@ -3811,6 +3874,7 @@ exports[`TextInput Tests Uncontrolled TextInput 1`] = `
"ControlType": 50004,
"IsKeyboardFocusable": true,
"LocalizedControlType": "edit",
+ "TextRangePattern.GetText": "Hello World!",
"ValuePattern.Value": "Hello World!",
},
"Component Tree": {
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap
index 34526e4305c..6f0bff23477 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap
@@ -7,6 +7,7 @@ exports[`Touchable Tests Text components can be tappable 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Text has built-in onPress handling",
+ "TextRangePattern.GetText": "Text has built-in onPress handling",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ParagraphComponentView",
@@ -36,6 +37,7 @@ exports[`Touchable Tests TouchableWithoutFeedback components should not give vis
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Tap Here For No Feedback!",
+ "TextRangePattern.GetText": "Tap Here For No Feedback!",
},
],
},
@@ -87,6 +89,7 @@ exports[`Touchable Tests Touchables can contain a Text component 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Tap Here For Custom Highlight!",
+ "TextRangePattern.GetText": "Tap Here For Custom Highlight!",
},
],
},
@@ -188,6 +191,7 @@ exports[`Touchable Tests Touchables can delay events 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Me",
+ "TextRangePattern.GetText": "Press Me",
},
],
},
@@ -239,6 +243,7 @@ exports[`Touchable Tests Touchables can enable a hit slop region 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Outside This View",
+ "TextRangePattern.GetText": "Press Outside This View",
},
],
},
@@ -295,6 +300,7 @@ exports[`Touchable Tests Touchables can register feedback events 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press Me",
+ "TextRangePattern.GetText": "Press Me",
},
],
},
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap
index 6e7c1fec89f..e05ea882571 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap
@@ -41,6 +41,7 @@ exports[`View Tests Views can have a nativeid 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "A View with a nativeID "native-id-view"",
+ "TextRangePattern.GetText": "A View with a nativeID "native-id-view"",
},
],
},
@@ -93,30 +94,35 @@ exports[`View Tests Views can have a z-index 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ZIndex -1",
+ "TextRangePattern.GetText": "ZIndex -1",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Tap to flip sorting order",
+ "TextRangePattern.GetText": "Tap to flip sorting order",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ZIndex 0",
+ "TextRangePattern.GetText": "ZIndex 0",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ZIndex 1",
+ "TextRangePattern.GetText": "ZIndex 1",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "ZIndex 2",
+ "TextRangePattern.GetText": "ZIndex 2",
},
],
},
@@ -328,6 +334,7 @@ exports[`View Tests Views can have aria-labels 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Blue background",
+ "TextRangePattern.GetText": "Blue background",
},
],
},
@@ -384,36 +391,42 @@ exports[`View Tests Views can have backface visibility 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "View #1, front is visible, back is hidden.",
+ "TextRangePattern.GetText": "View #1, front is visible, back is hidden.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Front",
+ "TextRangePattern.GetText": "Front",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Back (You should not see this)",
+ "TextRangePattern.GetText": "Back (You should not see this)",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "View #2, front is hidden, back is visible.",
+ "TextRangePattern.GetText": "View #2, front is hidden, back is visible.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Front (You should not see this)",
+ "TextRangePattern.GetText": "Front (You should not see this)",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Back",
+ "TextRangePattern.GetText": "Back",
},
],
},
@@ -630,6 +643,7 @@ exports[`View Tests Views can have background color 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Blue background",
+ "TextRangePattern.GetText": "Blue background",
},
],
},
@@ -686,12 +700,14 @@ exports[`View Tests Views can have border styles 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Dashed border style",
+ "TextRangePattern.GetText": "Dashed border style",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Dotted border style",
+ "TextRangePattern.GetText": "Dotted border style",
},
],
},
@@ -875,6 +891,7 @@ exports[`View Tests Views can have borders 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "5px blue border",
+ "TextRangePattern.GetText": "5px blue border",
},
],
},
@@ -975,12 +992,14 @@ exports[`View Tests Views can have customized accessibility 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "A View with accessibility values.",
+ "TextRangePattern.GetText": "A View with accessibility values.",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Current Number of Accessibility Taps: 0",
+ "TextRangePattern.GetText": "Current Number of Accessibility Taps: 0",
},
],
},
@@ -1065,42 +1084,49 @@ exports[`View Tests Views can have customized opacity 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 0",
+ "TextRangePattern.GetText": "Opacity 0",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 0.1",
+ "TextRangePattern.GetText": "Opacity 0.1",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 0.3",
+ "TextRangePattern.GetText": "Opacity 0.3",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 0.5",
+ "TextRangePattern.GetText": "Opacity 0.5",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 0.7",
+ "TextRangePattern.GetText": "Opacity 0.7",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 0.9",
+ "TextRangePattern.GetText": "Opacity 0.9",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Opacity 1",
+ "TextRangePattern.GetText": "Opacity 1",
},
],
},
@@ -1387,24 +1413,28 @@ exports[`View Tests Views can have customized pasdding and margins 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "5px padding",
+ "TextRangePattern.GetText": "5px padding",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "5px margin",
+ "TextRangePattern.GetText": "5px margin",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "5px margin and padding,",
+ "TextRangePattern.GetText": "5px margin and padding,",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "widthAutonomous=true",
+ "TextRangePattern.GetText": "widthAutonomous=true",
},
],
},
@@ -1731,6 +1761,7 @@ exports[`View Tests Views can have display: none 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Press to toggle \`display: none\`",
+ "TextRangePattern.GetText": "Press to toggle \`display: none\`",
},
],
},
@@ -2069,42 +2100,49 @@ exports[`View Tests Views can have insets 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "inset 10",
+ "TextRangePattern.GetText": "inset 10",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "insetBlock 5",
+ "TextRangePattern.GetText": "insetBlock 5",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "insetBlockEnd 5",
+ "TextRangePattern.GetText": "insetBlockEnd 5",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "insetBlockStart 5",
+ "TextRangePattern.GetText": "insetBlockStart 5",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "insetInline 5",
+ "TextRangePattern.GetText": "insetInline 5",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "insetInlineEnd 5",
+ "TextRangePattern.GetText": "insetInlineEnd 5",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "insetInlineStart 5",
+ "TextRangePattern.GetText": "insetInlineStart 5",
},
],
},
@@ -2798,18 +2836,21 @@ exports[`View Tests Views can have layout conformance 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Unset",
+ "TextRangePattern.GetText": "Unset",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Classic",
+ "TextRangePattern.GetText": "Classic",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Strict",
+ "TextRangePattern.GetText": "Strict",
},
],
},
@@ -3014,18 +3055,21 @@ exports[`View Tests Views can have logical border colors 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "borderBlockColor orange",
+ "TextRangePattern.GetText": "borderBlockColor orange",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "borderBlockStartColor purple",
+ "TextRangePattern.GetText": "borderBlockStartColor purple",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "borderBlockEndColor green",
+ "TextRangePattern.GetText": "borderBlockEndColor green",
},
],
},
@@ -3342,18 +3386,21 @@ exports[`View Tests Views can have offscreen alpha compositing 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Blobs",
+ "TextRangePattern.GetText": "Blobs",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Same blobs, but their shared container have 0.5 opacity",
+ "TextRangePattern.GetText": "Same blobs, but their shared container have 0.5 opacity",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "Tap to deactivate needsOffscreenAlphaCompositing",
+ "TextRangePattern.GetText": "Tap to deactivate needsOffscreenAlphaCompositing",
},
],
},
@@ -3540,18 +3587,21 @@ exports[`View Tests Views can have overflow 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "undefined",
+ "TextRangePattern.GetText": "undefined",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "hidden",
+ "TextRangePattern.GetText": "hidden",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "visible",
+ "TextRangePattern.GetText": "visible",
},
],
},
@@ -5350,18 +5400,21 @@ exports[`View Tests Views can have tooltips 1`] = `
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "This Parent View has tooltip "Parent View"",
+ "TextRangePattern.GetText": "This Parent View has tooltip "Parent View"",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "This view has tooltip "Child View 1"",
+ "TextRangePattern.GetText": "This view has tooltip "Child View 1"",
},
{
"AutomationId": "",
"ControlType": 50020,
"LocalizedControlType": "text",
"Name": "This view has tooltip "Child View 2"",
+ "TextRangePattern.GetText": "This view has tooltip "Child View 2"",
},
],
},
diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap
index d450e0df189..dc3d41610ac 100644
--- a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap
+++ b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap
@@ -8,8 +8,20 @@ exports[`snapshotAllPages Accessibility Windows 1`] = `
The following has accessibilityLabel and accessibilityHint:
The following has accessible and accessibilityLabel:
@@ -30301,8 +30314,10 @@ exports[`snapshotAllPages LegacyTextInputTest 1`] = `
testID="textinput-field"
/>
Release();
}
+ // Dump ITextRangeProvider Information
+ winrt::com_ptr textPattern;
+ hr = pTarget->GetCurrentPattern(UIA_TextPatternId, reinterpret_cast(textPattern.put()));
+ if (SUCCEEDED(hr) && textPattern) {
+ winrt::com_ptr textRangePattern;
+ hr = textPattern->get_DocumentRange(textRangePattern.put());
+ if (SUCCEEDED(hr) && textRangePattern) {
+ textRangePattern->GetText(20, &text);
+ if (SUCCEEDED(hr)) {
+ InsertStringValueIfNotEmpty(result, L"TextRangePattern.GetText", text);
+ }
+ }
+ }
+
+ ::SysFreeString(text);
::SysFreeString(value);
}
@@ -464,6 +480,7 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
int sizeOfSet = 0;
LiveSetting liveSetting = LiveSetting::Off;
BSTR itemStatus;
+ BSTR description = nullptr;
pTarget->get_CurrentAutomationId(&automationId);
pTarget->get_CurrentControlType(&controlType);
@@ -481,6 +498,11 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
pTarget4->get_CurrentLiveSetting(&liveSetting);
pTarget4->Release();
}
+ IUIAutomationElement6 *pTarget6;
+ hr = pTarget->QueryInterface(__uuidof(IUIAutomationElement6), reinterpret_cast(&pTarget6));
+ if (SUCCEEDED(hr) && pTarget6) {
+ pTarget6->get_CurrentFullDescription(&description);
+ }
result.Insert(L"AutomationId", winrt::Windows::Data::Json::JsonValue::CreateStringValue(automationId));
result.Insert(L"ControlType", winrt::Windows::Data::Json::JsonValue::CreateNumberValue(controlType));
InsertStringValueIfNotEmpty(result, L"HelpText", helpText);
@@ -493,6 +515,7 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
InsertIntValueIfNotDefault(result, L"SizeofSet", sizeOfSet);
InsertLiveSettingValueIfNotDefault(result, L"LiveSetting", liveSetting);
InsertStringValueIfNotEmpty(result, L"ItemStatus", itemStatus);
+ InsertStringValueIfNotEmpty(result, L"Description", description);
DumpUIAPatternInfo(pTarget, result);
IUIAutomationElement *pChild;
@@ -513,6 +536,7 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
::SysFreeString(localizedControlType);
::SysFreeString(name);
::SysFreeString(itemStatus);
+ ::SysFreeString(description);
return result;
}
diff --git a/packages/playground/Samples/text.tsx b/packages/playground/Samples/text.tsx
index 54ce125b651..08fe7bf4cfd 100644
--- a/packages/playground/Samples/text.tsx
+++ b/packages/playground/Samples/text.tsx
@@ -12,6 +12,21 @@ export default class Bootstrap extends React.Component {
return (
Welcome to React Native!
+
+ Click here : This is a text with a tooltip.
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
+ ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
+ aliquip ex ea commodo consequat.
+
+
);
}
@@ -24,6 +39,13 @@ const styles = StyleSheet.create({
alignItems: 'center',
backgroundColor: '#C5CCFF',
},
+ container2: {
+ backgroundColor: 'lightcoral',
+ padding: 10,
+ marginBottom: 10,
+ width: 500,
+ height: 100,
+ },
welcome: {
fontSize: 20,
textAlign: 'center',
diff --git a/packages/playground/Samples/textinput.tsx b/packages/playground/Samples/textinput.tsx
index 8f0c2f69001..390d5cb17e7 100644
--- a/packages/playground/Samples/textinput.tsx
+++ b/packages/playground/Samples/textinput.tsx
@@ -14,6 +14,7 @@ import {
View,
KeyboardAvoidingView,
ScrollView,
+ TouchableWithoutFeedback,
} from 'react-native';
import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
@@ -49,6 +50,7 @@ export default class Bootstrap extends React.Component<{}, any> {
state = {
passwordHidden: true,
text: '',
+ endEditingText: '',
};
onPressShowPassword = () => {
@@ -56,155 +58,232 @@ export default class Bootstrap extends React.Component<{}, any> {
this.setState({passwordHidden: !previousState});
};
+ handleEndEditing = (event: any) => {
+ const text = event.nativeEvent.text;
+ this.setState({endEditingText: text});
+ console.log('Text input focus lost:', text);
+ };
+
+ getHeightAndWidth = (height: number, width: number) => {
+ console.log(' onContentSizeChange height: ' + height + ' width: ' + width);
+ };
+
render() {
let textInputRef: TextInput | null;
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- (textInputRef = ref)}
- onFocus={() => setTimeout(() => textInputRef?.blur(), 5000)}
- placeholder={'blurs after 5 seconds'}
- style={styles.input}
- />
- {
- this.setState({text});
- }}
- value={this.state.text}
- selectionColor="red"
- maxLength={10}
- keyboardType="numeric"
- />
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ this.getHeightAndWidth(
+ event.nativeEvent.contentSize.height,
+ event.nativeEvent.contentSize.width,
+ )
+ }
+ placeholder={'MultiLine - content size change'}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (textInputRef = ref)}
+ onFocus={() => setTimeout(() => textInputRef?.blur(), 5000)}
+ placeholder={'blurs after 5 seconds'}
+ style={styles.input}
+ />
+ {
+ this.setState({text});
+ }}
+ value={this.state.text}
+ selectionColor="red"
+ maxLength={10}
+ keyboardType="numeric"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
}
diff --git a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj
index b9fb3cd9861..75d63c6ae89 100644
--- a/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj
+++ b/vnext/Microsoft.ReactNative.IntegrationTests/Microsoft.ReactNative.IntegrationTests.vcxproj
@@ -15,7 +15,7 @@
false
Windows Store
10.0
- 10.0.22000.0
+ 10.0.22621.0
true
None
diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/Microsoft.ReactNative.Managed.CodeGen.UnitTests.csproj b/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/Microsoft.ReactNative.Managed.CodeGen.UnitTests.csproj
index 0d393a8ee72..d0570dd146c 100644
--- a/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/Microsoft.ReactNative.Managed.CodeGen.UnitTests.csproj
+++ b/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/Microsoft.ReactNative.Managed.CodeGen.UnitTests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
x64
win-x64
false
diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/packages.lock.json b/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/packages.lock.json
index a6f8253b027..b30300df4cc 100644
--- a/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/packages.lock.json
+++ b/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 1,
"dependencies": {
- "net6.0": {
+ "net8.0": {
"coverlet.collector": {
"type": "Direct",
"requested": "[3.1.2, )",
@@ -1610,7 +1610,7 @@
}
}
},
- "net6.0/win-x64": {
+ "net8.0/win-x64": {
"Microsoft.Win32.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj b/vnext/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj
index 47a02c0f43f..6b18c3aeecb 100644
--- a/vnext/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj
+++ b/vnext/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj
@@ -3,7 +3,7 @@
Exe
- net6.0
+ net8.0
x64;x86;ARM64
win-x86;win-x64
diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml b/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml
index 1fbe6792278..c6c28996632 100644
--- a/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml
+++ b/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml
@@ -6,7 +6,7 @@
FileSystem
Debug
x64
- net6.0
+ net8.0
$(OutDir)publish
win-x64
true
diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml b/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml
index db7d34845e9..373853ddc0e 100644
--- a/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml
+++ b/vnext/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml
@@ -6,7 +6,7 @@
FileSystem
Release
x64
- net6.0
+ net8.0
$(OutDir)publish
win-x64
true
diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen/packages.lock.json b/vnext/Microsoft.ReactNative.Managed.CodeGen/packages.lock.json
index 88fa3e2a9ab..6854d1fe363 100644
--- a/vnext/Microsoft.ReactNative.Managed.CodeGen/packages.lock.json
+++ b/vnext/Microsoft.ReactNative.Managed.CodeGen/packages.lock.json
@@ -1,7 +1,7 @@
{
"version": 1,
"dependencies": {
- "net6.0": {
+ "net8.0": {
"Humanizer": {
"type": "Direct",
"requested": "[2.14.1, )",
@@ -1507,7 +1507,7 @@
}
}
},
- "net6.0/win-x64": {
+ "net8.0/win-x64": {
"Microsoft.Win32.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -2350,7 +2350,7 @@
}
}
},
- "net6.0/win-x86": {
+ "net8.0/win-x86": {
"Microsoft.Win32.Primitives": {
"type": "Transitive",
"resolved": "4.3.0",
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp
index 7553f2cf2b2..1b23f41d129 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp
@@ -787,7 +787,7 @@ struct CompScrollerVisual : winrt::implements<
m_horizontal ? TTypeRedirects::InteractionSourceMode::Disabled
: TTypeRedirects::InteractionSourceMode::EnabledWithInertia);
m_visualInteractionSource.ManipulationRedirectionMode(
- TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadAndPointerWheel);
+ TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadOnly);
} else {
m_visualInteractionSource.PositionXSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
m_visualInteractionSource.PositionYSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp
index 50b9e6a6bed..44aa7662eda 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp
@@ -1,6 +1,8 @@
#include "pch.h"
#include "CompositionDynamicAutomationProvider.h"
#include
+#include
+#include
#include
#include
#include
@@ -26,6 +28,13 @@ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
if (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value()) {
AddSelectionItemsToContainer(this);
}
+
+ if (strongView.try_as() ||
+ strongView.try_as()) {
+ m_textProvider = winrt::make(
+ strongView.as(), this)
+ .try_as();
+ }
}
CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
@@ -253,6 +262,17 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
AddRef();
}
+ if (patternId == UIA_TextPatternId &&
+ (strongView.try_as() ||
+ strongView.try_as())) {
+ m_textProvider.as().copy_to(pRetVal);
+ }
+
+ if (patternId == UIA_TextPattern2Id &&
+ strongView.try_as()) {
+ m_textProvider.as().copy_to(pRetVal);
+ }
+
return S_OK;
}
@@ -527,6 +547,29 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
: SysAllocString(L"");
break;
}
+ case UIA_LevelPropertyId: {
+ pRetVal->vt = VT_I4;
+ pRetVal->lVal = props->accessibilityLevel;
+ break;
+ }
+ case UIA_AccessKeyPropertyId: {
+ pRetVal->vt = VT_BSTR;
+ auto accessKey = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityAccessKey.value_or(""));
+ pRetVal->bstrVal = SysAllocString(accessKey.c_str());
+ break;
+ }
+ case UIA_ItemTypePropertyId: {
+ pRetVal->vt = VT_BSTR;
+ auto itemtype = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityItemType.value_or(""));
+ pRetVal->bstrVal = SysAllocString(itemtype.c_str());
+ break;
+ }
+ case UIA_FullDescriptionPropertyId: {
+ pRetVal->vt = VT_BSTR;
+ auto desc = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityDescription.value_or(""));
+ pRetVal->bstrVal = SysAllocString(desc.c_str());
+ break;
+ }
}
return hr;
@@ -769,7 +812,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Expand() {
if (!strongView)
return UIA_E_ELEMENTNOTAVAILABLE;
+
DispatchAccessibilityAction(m_view, "expand");
+
return S_OK;
}
@@ -778,7 +823,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Collapse() {
if (!strongView)
return UIA_E_ELEMENTNOTAVAILABLE;
+
DispatchAccessibilityAction(m_view, "collapse");
+
return S_OK;
}
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h
index 22ff59e209d..9ec8774755c 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h
@@ -89,6 +89,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
private:
::Microsoft::ReactNative::ReactTaggedView m_view;
+ winrt::com_ptr m_textProvider;
std::vector> m_selectionItems;
// Non-null when this UIA node is the peer of a ContentIslandComponentView.
winrt::Microsoft::UI::Content::ChildSiteLink m_childSiteLink{nullptr};
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp
index 8b5f12b04df..f46f6496f3c 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp
@@ -9,7 +9,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -637,17 +636,6 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
auto eventPathViews = GetTouchableViewsInPathToRoot(targetView);
- // Over
- if (targetView != nullptr && previousTargetTag != targetView.Tag()) {
- bool shouldEmitOverEvent =
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerOver);
- const auto eventEmitter = winrt::get_self(targetView)
- ->eventEmitterAtPoint(event.offsetPoint);
- if (shouldEmitOverEvent && eventEmitter != nullptr) {
- eventEmitter->onPointerOver(event);
- }
- }
-
// Entering
// We only want to emit events to JS if there is a view that is currently listening to said event
@@ -664,7 +652,6 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
auto componentView = *itComponentView;
bool shouldEmitEvent = componentView != nullptr &&
(hasParentEnterListener ||
- IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::PointerEnter) ||
IsViewListeningToEvent(componentView, facebook::react::WindowsViewEvents::Offset::MouseEnter));
if (std::find(currentlyHoveredViews.begin(), currentlyHoveredViews.end(), componentView) ==
@@ -674,16 +661,12 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
m_context, componentView.Tag(), pointerPoint, keyModifiers);
winrt::get_self(componentView)
->OnPointerEntered(args);
-
if (shouldEmitEvent) {
const auto eventEmitter =
winrt::get_self(componentView)
->eventEmitter();
- if (eventEmitter) {
- eventEmitter->onPointerEnter(event);
- if (IsMousePointerEvent(event)) {
- eventEmitter->onMouseEnter(event);
- }
+ if (eventEmitter && IsMousePointerEvent(event)) {
+ eventEmitter->onMouseEnter(event);
}
}
}
@@ -696,26 +679,13 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
// Call the underlaying pointer handler
handler(eventPathViews);
- // Out
- if (previousTargetTag != -1 && previousTargetTag != (targetView ? targetView.Tag() : -1)) {
- bool shouldEmitOutEvent =
- IsAnyViewInPathListeningToEvent(currentlyHoveredViews, facebook::react::ViewEvents::Offset::PointerOut);
- const auto eventEmitter =
- winrt::get_self(prevTargetView)->eventEmitter();
- if (shouldEmitOutEvent && eventEmitter != nullptr) {
- eventEmitter->onPointerOut(event);
- }
- }
-
// Leaving
// pointerleave events need to be emitted from the deepest target to the root but
// we also need to efficiently keep track of if a view has a parent which is listening to the leave events,
// so we first iterate from the root to the target, collecting the views which need events fired for, of which
// we reverse iterate (now from target to root), actually emitting the events.
- std::vector
- viewsToEmitJSLeaveEventsTo; // NSMutableOrderedSet *viewsToEmitLeaveEventsTo =
- // [NSMutableOrderedSet orderedSet];
+ std::vector viewsToEmitJSLeaveEventsTo;
std::vector viewsToEmitLeaveEventsTo;
@@ -723,14 +693,11 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
bool hasParentLeaveListener = false;
for (auto itComponentView = currentlyHoveredViews.rbegin(); itComponentView != currentlyHoveredViews.rend();
- itComponentView++) { // for (RCTReactTaggedView *taggedView in [currentlyHoveredViews
- // reverseObjectEnumerator])
- // {
+ itComponentView++) {
auto componentView = *itComponentView;
bool shouldEmitJSEvent = componentView != nullptr &&
(hasParentLeaveListener ||
- IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::PointerLeave) ||
IsViewListeningToEvent(componentView, facebook::react::WindowsViewEvents::Offset::MouseLeave));
if (std::find(eventPathViews.begin(), eventPathViews.end(), componentView) == eventPathViews.end()) {
@@ -755,17 +722,13 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
}
for (auto itComponentView = viewsToEmitJSLeaveEventsTo.rbegin(); itComponentView != viewsToEmitJSLeaveEventsTo.rend();
- itComponentView++) { // for (UIView *componentView in [viewsToEmitJSLeaveEventsTo
- // reverseObjectEnumerator]) {
+ itComponentView++) {
auto componentView = *itComponentView;
const auto eventEmitter =
winrt::get_self(componentView)->eventEmitter();
- if (eventEmitter) {
- eventEmitter->onPointerLeave(event);
- if (IsMousePointerEvent(event)) {
- eventEmitter->onMouseLeave(event);
- }
+ if (eventEmitter && IsMousePointerEvent(event)) {
+ eventEmitter->onMouseLeave(event);
}
}
@@ -815,41 +778,41 @@ void CompositionEventHandler::SetCursor(facebook::react::Cursor cursor, HCURSOR
case facebook::react::Cursor::Pointer:
type = winrt::Windows::UI::Core::CoreCursorType::Hand;
break;
- /* -- Additional cursors not added in core until later version
- case facebook::react::Cursor::Help:
- type = winrt::Windows::UI::Core::CoreCursorType::Help;
- break;
- case facebook::react::Cursor::NotAllowed:
- type = winrt::Windows::UI::Core::CoreCursorType::UniversalNo;
- break;
- case facebook::react::Cursor::Wait:
- type = winrt::Windows::UI::Core::CoreCursorType::Wait;
- break;
- case facebook::react::Cursor::Move:
- type = winrt::Windows::UI::Core::CoreCursorType::SizeAll;
- break;
- case facebook::react::Cursor::NESWResize:
- type = winrt::Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest;
- break;
- case facebook::react::Cursor::NSResize:
- type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthSouth;
- break;
- case facebook::react::Cursor::NWSEResize:
- type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast;
- break;
- case facebook::react::Cursor::EWResize:
- type = winrt::Windows::UI::Core::CoreCursorType::SizeWestEast;
- break;
- case facebook::react::Cursor::Text:
- type = winrt::Windows::UI::Core::CoreCursorType::IBeam;
- break;
- case facebook::react::Cursor::Progress:
- type = winrt::Windows::UI::Core::CoreCursorType::Wait; // IDC_APPSTARTING not mapped to CoreCursor?
- break;
- case facebook::react::Cursor::Crosshair:
- type = winrt::Windows::UI::Core::CoreCursorType::Cross;
- break;
- */
+ /*
+ case facebook::react::Cursor::Help:
+ type = winrt::Windows::UI::Core::CoreCursorType::Help;
+ break;
+ case facebook::react::Cursor::NotAllowed:
+ type = winrt::Windows::UI::Core::CoreCursorType::UniversalNo;
+ break;
+ case facebook::react::Cursor::Wait:
+ type = winrt::Windows::UI::Core::CoreCursorType::Wait;
+ break;
+ case facebook::react::Cursor::Move:
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeAll;
+ break;
+ case facebook::react::Cursor::NESWResize:
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest;
+ break;
+ case facebook::react::Cursor::NSResize:
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthSouth;
+ break;
+ case facebook::react::Cursor::NWSEResize:
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast;
+ break;
+ case facebook::react::Cursor::EWResize:
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeWestEast;
+ break;
+ case facebook::react::Cursor::Text:
+ type = winrt::Windows::UI::Core::CoreCursorType::IBeam;
+ break;
+ case facebook::react::Cursor::Progress:
+ type = winrt::Windows::UI::Core::CoreCursorType::Wait; // IDC_APPSTARTING not mapped to CoreCursor?
+ break;
+ case facebook::react::Cursor::Crosshair:
+ type = winrt::Windows::UI::Core::CoreCursorType::Cross;
+ break;
+ */
default:
break;
}
@@ -880,7 +843,7 @@ void CompositionEventHandler::SetCursor(facebook::react::Cursor cursor, HCURSOR
case facebook::react::Cursor::Pointer:
idc = IDC_HAND;
break;
- /* -- Additional cursors not added in core until later version
+ /*
case facebook::react::Cursor::Help:
idc = IDC_HELP;
break;
@@ -1064,21 +1027,48 @@ void CompositionEventHandler::onPointerMoved(
facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData(ptScaled, ptLocal);
- auto handler = [&targetView,
- &pointerEvent](std::vector &eventPathViews) {
+ // check if this pointer corresponds to active touch that has a responder
+ auto activeTouch = m_activeTouches.find(pointerId);
+ bool isActiveTouch = activeTouch != m_activeTouches.end() && activeTouch->second.eventEmitter != nullptr;
+
+ auto handler = [&, targetView, pointerEvent, isActiveTouch](
+ std::vector &eventPathViews) {
const auto eventEmitter = targetView
? winrt::get_self(targetView)
->eventEmitterAtPoint(pointerEvent.offsetPoint)
- : nullptr;
- bool hasMoveEventListeners =
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) ||
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture);
- if (eventEmitter != nullptr && hasMoveEventListeners) {
+ : RootComponentView().eventEmitterAtPoint(pointerEvent.offsetPoint);
+
+ if (eventEmitter != nullptr) {
eventEmitter->onPointerMove(pointerEvent);
+ } else {
+ ClearAllHoveredForPointer(pointerEvent);
}
};
HandleIncomingPointerEvent(pointerEvent, targetView, pointerPoint, keyModifiers, handler);
+
+ if (isActiveTouch) {
+ // For active touches with responders, also dispatch through touch event system
+ UpdateActiveTouch(activeTouch->second, ptScaled, ptLocal);
+ DispatchTouchEvent(TouchEventType::Move, pointerId, pointerPoint, keyModifiers);
+ }
+ }
+}
+
+void CompositionEventHandler::ClearAllHoveredForPointer(const facebook::react::PointerEvent &pointerEvent) noexcept {
+ // special case if we have no target
+ // PointerEventsProcessor requires move events to keep track of the hovered components in core.
+ // It also treats a onPointerLeave event as a special case that removes the hover state of all currently hovered
+ // events. If we get null for the targetView, that means that the mouse is no over any components, so we have no
+ // element to send the move event to. However we need to send something so that any previously hovered elements
+ // are no longer hovered.
+ auto children = RootComponentView().Children();
+ if (auto size = children.Size()) {
+ auto firstChild = children.GetAt(0);
+ if (auto childEventEmitter =
+ winrt::get_self(firstChild)->eventEmitter()) {
+ childEventEmitter->onPointerLeave(pointerEvent);
+ }
}
}
@@ -1104,7 +1094,9 @@ void CompositionEventHandler::onPointerExited(
facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData(ptScaled, ptLocal);
- auto handler = [](std::vector &eventPathViews) {};
+ auto handler = [&](std::vector &eventPathViews) {
+ ClearAllHoveredForPointer(pointerEvent);
+ };
HandleIncomingPointerEvent(pointerEvent, nullptr, pointerPoint, keyModifiers, handler);
}
@@ -1392,12 +1384,7 @@ void CompositionEventHandler::DispatchTouchEvent(
activeTouch.eventEmitter->onPointerDown(pointerEvent);
break;
case TouchEventType::Move: {
- bool hasMoveEventListeners =
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) ||
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture);
- if (hasMoveEventListeners) {
- activeTouch.eventEmitter->onPointerMove(pointerEvent);
- }
+ activeTouch.eventEmitter->onPointerMove(pointerEvent);
break;
}
case TouchEventType::End:
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h
index be9cfa44b79..acddeac866f 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h
@@ -14,7 +14,6 @@
#include
#include
#include
-#include "Utils/BatchingEventEmitter.h"
namespace winrt {
using namespace Windows::UI;
@@ -99,6 +98,7 @@ class CompositionEventHandler : public std::enable_shared_from_this &)> handler);
+ void ClearAllHoveredForPointer(const facebook::react::PointerEvent &pointerEvent) noexcept;
struct ActiveTouch {
facebook::react::Touch touch;
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp
new file mode 100644
index 00000000000..ef997fe0ae4
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp
@@ -0,0 +1,115 @@
+#include "pch.h"
+#include
+#include
+#include
+#include
+#include "CompositionTextRangeProvider.h"
+#include "RootComponentView.h"
+#include "UiaHelpers.h"
+
+namespace winrt::Microsoft::ReactNative::implementation {
+
+CompositionTextProvider::CompositionTextProvider(
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
+ CompositionDynamicAutomationProvider *parentProvider) noexcept
+ : m_view{componentView} {
+ m_parentProvider.copy_from(parentProvider);
+ EnsureTextRangeProvider();
+}
+
+void CompositionTextProvider::EnsureTextRangeProvider() {
+ auto strongView = m_view.view();
+
+ if (!strongView)
+ return;
+
+ if (!m_textRangeProvider) {
+ m_textRangeProvider =
+ winrt::make(
+ strongView.as(), m_parentProvider.get())
+ .try_as();
+ }
+}
+
+HRESULT __stdcall CompositionTextProvider::get_DocumentRange(ITextRangeProvider **pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+ auto strongView = m_view.view();
+
+ if (!strongView)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (m_textRangeProvider == nullptr)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ m_textRangeProvider.copy_to(pRetVal);
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextProvider::get_SupportedTextSelection(SupportedTextSelection *pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+ auto strongView = m_view.view();
+
+ if (!strongView)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (strongView.try_as()) {
+ *pRetVal = SupportedTextSelection_Single;
+ } else if (
+ auto textView =
+ strongView.try_as()) {
+ auto props = std::static_pointer_cast(textView->props());
+ if (props == nullptr)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ *pRetVal = props->isSelectable ? SupportedTextSelection_Single : SupportedTextSelection_None;
+ } else {
+ *pRetVal = SupportedTextSelection_None;
+ }
+
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextProvider::GetSelection(SAFEARRAY **pRetVal) {
+ // no-op
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0);
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextProvider::GetVisibleRanges(SAFEARRAY **pRetVal) {
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
+ if (m_textRangeProvider == nullptr)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ LONG pos = 0;
+ return SafeArrayPutElement(*pRetVal, &pos, m_textRangeProvider.get());
+}
+
+HRESULT __stdcall CompositionTextProvider::RangeFromChild(
+ IRawElementProviderSimple *childElement,
+ ITextRangeProvider **pRetVal) {
+ // no-op
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextProvider::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) {
+ // no-op
+ if (m_textRangeProvider == nullptr)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ m_textRangeProvider.copy_to(pRetVal);
+ return S_OK;
+}
+HRESULT __stdcall CompositionTextProvider::GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) {
+ // no-op
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextProvider::RangeFromAnnotation(
+ IRawElementProviderSimple *annotationElement,
+ ITextRangeProvider **pRetVal) {
+ // no-op
+ *pRetVal = nullptr;
+ return S_OK;
+}
+} // namespace winrt::Microsoft::ReactNative::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h
new file mode 100644
index 00000000000..cb68ad7bfe9
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace winrt::Microsoft::ReactNative::implementation {
+
+class CompositionTextProvider : public winrt::implements {
+ public:
+ CompositionTextProvider(
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
+ CompositionDynamicAutomationProvider *parentProvider) noexcept;
+
+ // inherited via ITextProvider
+ virtual HRESULT __stdcall get_DocumentRange(ITextRangeProvider **pRetVal) override;
+ virtual HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *pRetVal) override;
+ virtual HRESULT __stdcall GetSelection(SAFEARRAY **pRetVal) override;
+ virtual HRESULT __stdcall GetVisibleRanges(SAFEARRAY **pRetVal) override;
+ virtual HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal)
+ override;
+ virtual HRESULT __stdcall RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) override;
+
+ // inherited via ITextProvider2
+ virtual HRESULT __stdcall GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) override;
+ virtual HRESULT __stdcall RangeFromAnnotation(
+ IRawElementProviderSimple *annotationElement,
+ ITextRangeProvider **pRetVal) override;
+
+ void EnsureTextRangeProvider();
+
+ private:
+ ::Microsoft::ReactNative::ReactTaggedView m_view;
+ winrt::com_ptr m_textRangeProvider;
+ winrt::com_ptr m_parentProvider;
+};
+
+} // namespace winrt::Microsoft::ReactNative::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp
new file mode 100644
index 00000000000..e2260913e15
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp
@@ -0,0 +1,319 @@
+#include "pch.h"
+#include "CompositionTextRangeProvider.h"
+#include
+#include
+#include
+#include
+#include
+#include "RootComponentView.h"
+#include "UiaHelpers.h"
+
+namespace winrt::Microsoft::ReactNative::implementation {
+
+CompositionTextRangeProvider::CompositionTextRangeProvider(
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
+ CompositionDynamicAutomationProvider *parentProvider) noexcept
+ : m_view{componentView} {
+ m_parentProvider.copy_from(parentProvider);
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::Clone(ITextRangeProvider **pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+
+ auto clone = winrt::make(
+ m_view.view().as(), m_parentProvider.get());
+ *pRetVal = clone.detach();
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+ if (range == nullptr) {
+ *pRetVal = FALSE;
+ return S_OK;
+ }
+
+ // Try to cast to our type , considering provider only supports a single range per view
+ auto other = dynamic_cast(range);
+ if (other && other->m_view.view() == m_view.view()) {
+ *pRetVal = TRUE;
+ } else {
+ *pRetVal = FALSE;
+ }
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::CompareEndpoints(
+ TextPatternRangeEndpoint endpoint,
+ ITextRangeProvider *targetRange,
+ TextPatternRangeEndpoint targetEndpoint,
+ int *pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+
+ // For a single-range provider, always equal:
+ *pRetVal = 0;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit) {
+ // no-op
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::FindAttribute(
+ TEXTATTRIBUTEID attributeId,
+ VARIANT val,
+ BOOL backward,
+ ITextRangeProvider **pRetVal) {
+ // no-op
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::FindText(
+ BSTR text,
+ BOOL backward,
+ BOOL ignoreCase,
+ ITextRangeProvider **pRetVal) {
+ // no-op
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+ auto strongView = m_view.view();
+
+ if (!strongView)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ auto props = std::static_pointer_cast(
+ winrt::get_self(strongView)->props());
+
+ auto textinputProps = std::static_pointer_cast(
+ winrt::get_self(strongView)->props());
+
+ auto isTextInput =
+ strongView.try_as();
+
+ if (props == nullptr)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (attributeId == UIA_BackgroundColorAttributeId) {
+ pRetVal->vt = VT_I4;
+ pRetVal->lVal = (*props->backgroundColor).AsColorRefWithAlpha();
+ } else if (attributeId == UIA_CapStyleAttributeId) {
+ pRetVal->vt = VT_I4;
+ auto fontVariant = facebook::react::FontVariant::Default;
+ auto textTransform = facebook::react::TextTransform::None;
+ if (props->textAttributes.fontVariant.has_value()) {
+ fontVariant = props->textAttributes.fontVariant.value();
+ }
+ if (props->textAttributes.textTransform.has_value()) {
+ textTransform = props->textAttributes.textTransform.value();
+ }
+ if (fontVariant == facebook::react::FontVariant::SmallCaps) {
+ pRetVal->lVal = CapStyle_SmallCap;
+ } else if (textTransform == facebook::react::TextTransform::Capitalize) {
+ pRetVal->lVal = CapStyle_Titling;
+ } else if (textTransform == facebook::react::TextTransform::Lowercase) {
+ pRetVal->lVal = CapStyle_None;
+ } else if (textTransform == facebook::react::TextTransform::Uppercase) {
+ pRetVal->lVal = CapStyle_AllCap;
+ }
+ } else if (attributeId == UIA_FontNameAttributeId) {
+ pRetVal->vt = VT_BSTR;
+ auto fontName = props->textAttributes.fontFamily;
+ if (fontName.empty()) {
+ fontName = "Segoe UI";
+ }
+ std::wstring wfontName(fontName.begin(), fontName.end());
+ pRetVal->bstrVal = SysAllocString(wfontName.c_str());
+ } else if (attributeId == UIA_FontSizeAttributeId) {
+ pRetVal->vt = VT_R8;
+ pRetVal->dblVal = props->textAttributes.fontSize;
+ } else if (attributeId == UIA_FontWeightAttributeId) {
+ if (props->textAttributes.fontWeight.has_value()) {
+ pRetVal->vt = VT_I4;
+ pRetVal->lVal = static_cast(props->textAttributes.fontWeight.value());
+ }
+ } else if (attributeId == UIA_ForegroundColorAttributeId) {
+ pRetVal->vt = VT_I4;
+ pRetVal->lVal = (*props->textAttributes.foregroundColor).AsColorRefWithAlpha();
+ } else if (attributeId == UIA_IsItalicAttributeId) {
+ pRetVal->vt = VT_BOOL;
+ pRetVal->boolVal = (props->textAttributes.fontStyle.has_value() &&
+ props->textAttributes.fontStyle.value() == facebook::react::FontStyle::Italic)
+ ? VARIANT_TRUE
+ : VARIANT_FALSE;
+ } else if (attributeId == UIA_IsReadOnlyAttributeId) {
+ pRetVal->vt = VT_BOOL;
+ pRetVal->boolVal = isTextInput ? textinputProps->editable ? VARIANT_FALSE : VARIANT_TRUE : VARIANT_TRUE;
+ } else if (attributeId == UIA_HorizontalTextAlignmentAttributeId) {
+ pRetVal->vt = VT_I4;
+ auto textAlign = facebook::react::TextAlignment::Center;
+ if (props->textAttributes.alignment.has_value()) {
+ textAlign = props->textAttributes.alignment.value();
+ }
+ if (textAlign == facebook::react::TextAlignment::Left) {
+ pRetVal->lVal = HorizontalTextAlignment_Left;
+ } else if (textAlign == facebook::react::TextAlignment::Right) {
+ pRetVal->lVal = HorizontalTextAlignment_Right;
+ } else if (textAlign == facebook::react::TextAlignment::Center) {
+ pRetVal->lVal = HorizontalTextAlignment_Centered;
+ } else if (textAlign == facebook::react::TextAlignment::Justified) {
+ pRetVal->lVal = HorizontalTextAlignment_Justified;
+ } else if (textAlign == facebook::react::TextAlignment::Natural) {
+ pRetVal->lVal = HorizontalTextAlignment_Left;
+ }
+ } else if (attributeId == UIA_StrikethroughColorAttributeId) {
+ if (props->textAttributes.textDecorationLineType.has_value() &&
+ (props->textAttributes.textDecorationLineType.value() ==
+ facebook::react::TextDecorationLineType::Strikethrough ||
+ props->textAttributes.textDecorationLineType.value() ==
+ facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
+ pRetVal->vt = VT_I4;
+ pRetVal->lVal = (*props->textAttributes.textDecorationColor).AsColorRefWithAlpha();
+ }
+ } else if (attributeId == UIA_StrikethroughStyleAttributeId) {
+ if (props->textAttributes.textDecorationLineType.has_value() &&
+ (props->textAttributes.textDecorationLineType.value() ==
+ facebook::react::TextDecorationLineType::Strikethrough ||
+ props->textAttributes.textDecorationLineType.value() ==
+ facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
+ pRetVal->vt = VT_I4;
+ auto style = props->textAttributes.textDecorationStyle.value();
+ pRetVal->lVal = GetTextDecorationLineStyle(style);
+ }
+ } else if (attributeId == UIA_UnderlineColorAttributeId) {
+ if (props->textAttributes.textDecorationLineType.has_value() &&
+ (props->textAttributes.textDecorationLineType.value() == facebook::react::TextDecorationLineType::Underline ||
+ props->textAttributes.textDecorationLineType.value() ==
+ facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
+ pRetVal->vt = VT_I4;
+ pRetVal->lVal = (*props->textAttributes.textDecorationColor).AsColorRefWithAlpha();
+ }
+ } else if (attributeId == UIA_UnderlineStyleAttributeId) {
+ if (props->textAttributes.textDecorationLineType.has_value() &&
+ (props->textAttributes.textDecorationLineType.value() == facebook::react::TextDecorationLineType::Underline ||
+ props->textAttributes.textDecorationLineType.value() ==
+ facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
+ pRetVal->vt = VT_I4;
+ auto style = props->textAttributes.textDecorationStyle.value();
+ pRetVal->lVal = GetTextDecorationLineStyle(style);
+ }
+ }
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+ UiaRect rect;
+ auto hr = m_parentProvider->get_BoundingRectangle(&rect);
+ if (FAILED(hr))
+ return hr;
+ *pRetVal = SafeArrayCreateVector(VT_R8, 0, 4);
+ double *pData = nullptr;
+ hr = SafeArrayAccessData(*pRetVal, reinterpret_cast(&pData));
+ if (FAILED(hr))
+ return hr;
+ pData[0] = rect.left;
+ pData[1] = rect.top;
+ pData[2] = rect.width;
+ pData[3] = rect.height;
+ hr = SafeArrayUnaccessData(*pRetVal);
+ if (FAILED(hr))
+ return hr;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::GetChildren(SAFEARRAY **pRetVal) {
+ // no-op
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0);
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal) {
+ // no-op
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::GetText(int maxLength, BSTR *pRetVal) {
+ if (pRetVal == nullptr)
+ return E_POINTER;
+ auto strongView = m_view.view();
+
+ if (!strongView)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ auto paragraphView =
+ strongView.try_as();
+ std::string text = "";
+ if (paragraphView) {
+ text = paragraphView->DefaultAccessibleName();
+ } else {
+ auto textInputView =
+ strongView.try_as();
+ if (textInputView) {
+ text = textInputView->getAccessiblityValue().value().empty() ? textInputView->DefaultAccessibleName()
+ : textInputView->getAccessiblityValue().value();
+ } else {
+ return UIA_E_NOTSUPPORTED;
+ }
+ }
+
+ std::wstring wtext(text.begin(), text.end());
+ *pRetVal = SysAllocString(wtext.c_str());
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::Move(TextUnit unit, int count, int *pRetVal) {
+ // no-op
+ *pRetVal = 0;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::MoveEndpointByRange(
+ TextPatternRangeEndpoint endpoint,
+ ITextRangeProvider *targetRange,
+ TextPatternRangeEndpoint targetEndpoint) {
+ // no-op
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::MoveEndpointByUnit(
+ TextPatternRangeEndpoint endpoint,
+ TextUnit unit,
+ int count,
+ int *pRetVal) {
+ // no-op
+ *pRetVal = 0;
+ return S_OK;
+}
+
+HRESULT __stdcall CompositionTextRangeProvider::ScrollIntoView(BOOL alignToTop) {
+ // no-op
+ return S_OK;
+}
+
+// All the below methods should be implemented once the selection comes for paragraph and TextInput
+
+HRESULT __stdcall CompositionTextRangeProvider::AddToSelection() {
+ // no-op
+ return S_OK;
+}
+HRESULT __stdcall CompositionTextRangeProvider::RemoveFromSelection() {
+ // no-op
+ return S_OK;
+}
+HRESULT __stdcall CompositionTextRangeProvider::Select() {
+ // no-op
+ return S_OK;
+}
+
+} // namespace winrt::Microsoft::ReactNative::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h
new file mode 100644
index 00000000000..18ec13688bf
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace winrt::Microsoft::ReactNative::implementation {
+
+class CompositionTextRangeProvider : public winrt::implements {
+ public:
+ CompositionTextRangeProvider(
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
+ CompositionDynamicAutomationProvider *parentProvider) noexcept;
+
+ // inherited via ITextRangeProvider
+ virtual HRESULT __stdcall Clone(ITextRangeProvider **pRetVal) override;
+ virtual HRESULT __stdcall Compare(ITextRangeProvider *range, BOOL *pRetVal) override;
+ virtual HRESULT __stdcall CompareEndpoints(
+ TextPatternRangeEndpoint endpoint,
+ ITextRangeProvider *targetRange,
+ TextPatternRangeEndpoint targetEndpoint,
+ int *pRetVal) override;
+ virtual HRESULT __stdcall ExpandToEnclosingUnit(TextUnit unit) override;
+ virtual HRESULT __stdcall FindAttribute(
+ TEXTATTRIBUTEID attributeId,
+ VARIANT val,
+ BOOL backward,
+ ITextRangeProvider **pRetVal) override;
+ virtual HRESULT __stdcall FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal) override;
+ virtual HRESULT __stdcall GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal) override;
+ virtual HRESULT __stdcall GetBoundingRectangles(SAFEARRAY **pRetVal) override;
+ virtual HRESULT __stdcall GetChildren(SAFEARRAY **pRetVal) override;
+ virtual HRESULT __stdcall GetEnclosingElement(IRawElementProviderSimple **pRetVal) override;
+ virtual HRESULT __stdcall GetText(int maxLength, BSTR *pRetVal) override;
+ virtual HRESULT __stdcall Move(TextUnit unit, int count, int *pRetVal) override;
+ virtual HRESULT __stdcall MoveEndpointByRange(
+ TextPatternRangeEndpoint endpoint,
+ ITextRangeProvider *targetRange,
+ TextPatternRangeEndpoint targetEndpoint) override;
+ virtual HRESULT __stdcall MoveEndpointByUnit(
+ TextPatternRangeEndpoint endpoint,
+ TextUnit unit,
+ int count,
+ int *pRetVal) override;
+ virtual HRESULT __stdcall ScrollIntoView(BOOL alignToTop) override;
+ virtual HRESULT __stdcall AddToSelection() override;
+ virtual HRESULT __stdcall RemoveFromSelection() override;
+ virtual HRESULT __stdcall Select() override;
+
+ private:
+ ::Microsoft::ReactNative::ReactTaggedView m_view;
+ winrt::com_ptr m_parentProvider;
+};
+
+} // namespace winrt::Microsoft::ReactNative::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp
index 672029efac0..d64b09764b7 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp
@@ -780,6 +780,53 @@ void ComponentView::updateAccessibilityProps(
oldViewProps.accessibilityLiveRegion,
newViewProps.accessibilityLiveRegion);
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(), UIA_LevelPropertyId, oldViewProps.accessibilityLevel, newViewProps.accessibilityLevel);
+
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(),
+ UIA_AccessKeyPropertyId,
+ oldViewProps.accessibilityAccessKey,
+ newViewProps.accessibilityAccessKey);
+
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(),
+ UIA_ItemTypePropertyId,
+ oldViewProps.accessibilityItemType,
+ newViewProps.accessibilityItemType);
+
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(),
+ UIA_FullDescriptionPropertyId,
+ oldViewProps.accessibilityDescription,
+ newViewProps.accessibilityDescription);
+
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(),
+ UIA_ValueValuePropertyId,
+ oldViewProps.accessibilityValue.text,
+ newViewProps.accessibilityValue.text);
+
+ // Handle expand/collapse state changes
+ if (oldViewProps.accessibilityState.has_value() != newViewProps.accessibilityState.has_value() ||
+ (oldViewProps.accessibilityState.has_value() && newViewProps.accessibilityState.has_value() &&
+ oldViewProps.accessibilityState->expanded != newViewProps.accessibilityState->expanded)) {
+ auto oldExpanded =
+ oldViewProps.accessibilityState.has_value() && oldViewProps.accessibilityState->expanded.has_value()
+ ? oldViewProps.accessibilityState->expanded.value()
+ : false;
+ auto newExpanded =
+ newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->expanded.has_value()
+ ? newViewProps.accessibilityState->expanded.value()
+ : false;
+
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(),
+ UIA_ExpandCollapseExpandCollapseStatePropertyId,
+ static_cast(winrt::Microsoft::ReactNative::implementation::GetExpandCollapseState(oldExpanded)),
+ static_cast(winrt::Microsoft::ReactNative::implementation::GetExpandCollapseState(newExpanded)));
+ }
+
if ((oldViewProps.accessibilityState.has_value() && oldViewProps.accessibilityState->selected.has_value()) !=
((newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->selected.has_value()))) {
auto compProvider =
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp
index 0f90896ccd8..aea0b365893 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp
@@ -64,6 +64,14 @@ void ParagraphComponentView::updateProps(
updateTextAlignment(newViewProps.textAttributes.alignment);
}
+ if (oldViewProps.paragraphAttributes.ellipsizeMode != newViewProps.paragraphAttributes.ellipsizeMode) {
+ m_textLayout = nullptr;
+ }
+
+ if (oldViewProps.paragraphAttributes.adjustsFontSizeToFit != newViewProps.paragraphAttributes.adjustsFontSizeToFit) {
+ m_textLayout = nullptr;
+ }
+
Super::updateProps(props, oldProps);
}
@@ -73,7 +81,7 @@ void ParagraphComponentView::updateState(
const auto &newState = *std::static_pointer_cast(state);
m_attributedStringBox = facebook::react::AttributedStringBox(newState.getData().attributedString);
- m_paragraphAttributes = {}; // TODO
+ m_paragraphAttributes = facebook::react::ParagraphAttributes(newState.getData().paragraphAttributes);
m_textLayout = nullptr;
}
@@ -97,7 +105,7 @@ void ParagraphComponentView::FinalizeUpdates(
facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPoint(
facebook::react::Point pt) noexcept {
- if (m_attributedStringBox.getValue().getFragments().size()) {
+ if (m_attributedStringBox.getValue().getFragments().size() && m_textLayout) {
BOOL isTrailingHit = false;
BOOL isInside = false;
DWRITE_HIT_TEST_METRICS metrics;
@@ -120,35 +128,8 @@ facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPo
void ParagraphComponentView::updateTextAlignment(
const std::optional &fbAlignment) noexcept {
+ // Reset text layout to force recreation with new alignment
m_textLayout = nullptr;
- if (!m_textLayout)
- return;
-
- DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
- if (fbAlignment) {
- switch (*fbAlignment) {
- case facebook::react::TextAlignment::Center:
- alignment = DWRITE_TEXT_ALIGNMENT_CENTER;
- break;
- case facebook::react::TextAlignment::Justified:
- alignment = DWRITE_TEXT_ALIGNMENT_JUSTIFIED;
- break;
- case facebook::react::TextAlignment::Left:
- alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
- break;
- case facebook::react::TextAlignment::Right:
- alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
- break;
- // TODO use LTR values
- case facebook::react::TextAlignment::Natural:
- alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
- break;
- default:
- assert(false);
- }
- }
- // TODO
- // m_textFormat->SetTextAlignment(alignment);
}
void ParagraphComponentView::OnRenderingDeviceLost() noexcept {
@@ -160,7 +141,6 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
// TODO
// updateTextAlignment(paragraphProps.textAttributes.alignment);
-
if (!m_textLayout) {
facebook::react::LayoutConstraints constraints;
constraints.maximumSize.width =
@@ -168,7 +148,38 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
constraints.maximumSize.height =
m_layoutMetrics.frame.size.height - m_layoutMetrics.contentInsets.top - m_layoutMetrics.contentInsets.bottom;
- facebook::react::TextLayoutManager::GetTextLayout(m_attributedStringBox, {} /*TODO*/, constraints, m_textLayout);
+ facebook::react::TextLayoutManager::GetTextLayout(
+ m_attributedStringBox, m_paragraphAttributes, constraints, m_textLayout);
+
+ // Apply text alignment after creating the text layout
+ if (m_textLayout) {
+ const auto &props = paragraphProps();
+ DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
+ if (props.textAttributes.alignment) {
+ switch (*props.textAttributes.alignment) {
+ case facebook::react::TextAlignment::Center:
+ alignment = DWRITE_TEXT_ALIGNMENT_CENTER;
+ break;
+ case facebook::react::TextAlignment::Justified:
+ alignment = DWRITE_TEXT_ALIGNMENT_JUSTIFIED;
+ break;
+ case facebook::react::TextAlignment::Left:
+ alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
+ break;
+ case facebook::react::TextAlignment::Right:
+ alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
+ break;
+ case facebook::react::TextAlignment::Natural:
+ alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
+ break;
+ default:
+ alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
+ break;
+ }
+ }
+ winrt::check_hresult(m_textLayout->SetTextAlignment(alignment));
+ }
+
requireNewBrush = true;
}
@@ -270,9 +281,7 @@ void ParagraphComponentView::DrawText() noexcept {
d2dDeviceContext->Clear(
viewProps()->backgroundColor ? theme()->D2DColor(*viewProps()->backgroundColor)
: D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
-
const auto &props = paragraphProps();
-
RenderText(
*d2dDeviceContext,
*m_textLayout,
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp
index 129211ebf05..7a79a2a7e88 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp
@@ -9,6 +9,7 @@
#include
#include "CompositionDynamicAutomationProvider.h"
#include "RootComponentView.h"
+#include "UiaHelpers.h"
namespace winrt::Microsoft::ReactNative::Composition::implementation {
@@ -80,6 +81,16 @@ void SwitchComponentView::updateProps(
m_visualUpdateRequired = true;
}
+ if (oldViewProps.value != newViewProps.value) {
+ if (UiaClientsAreListening()) {
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
+ EnsureUiaProvider(),
+ UIA_ToggleToggleStatePropertyId,
+ oldViewProps.value ? ToggleState_On : ToggleState_Off,
+ newViewProps.value ? ToggleState_On : ToggleState_Off);
+ }
+ }
+
Super::updateProps(props, oldProps);
}
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
index 16821339afd..0ceb92f0b3a 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
@@ -14,6 +14,7 @@
#include
#include
#include
+#include "../Composition.Input.h"
#include "../CompositionHelpers.h"
#include "../RootComponentView.h"
#include "JSValueReader.h"
@@ -212,15 +213,14 @@ struct CompTextHost : public winrt::implements {
//@cmember Get mouse capture
void TxSetCapture(BOOL fCapture) override {
- // assert(false);
- // TODO capture?
- /*
+ auto mousePointer = winrt::make(
+ winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse, 1 /* 1 is Mouse PointerId*/);
+
if (fCapture) {
- ::SetCapture(m_hwndHost);
+ m_outer->CapturePointer(mousePointer);
} else {
- ::ReleaseCapture();
+ m_outer->ReleasePointerCapture(mousePointer);
}
- */
}
//@cmember Set the focus to the text window
@@ -319,20 +319,30 @@ struct CompTextHost : public winrt::implements {
return (*m_outer->windowsTextInputProps().textAttributes.foregroundColor).AsColorRefNoAlpha();
// cr = 0x000000FF;
break;
-
case COLOR_WINDOW:
if (m_outer->viewProps()->backgroundColor)
return (*m_outer->viewProps()->backgroundColor).AsColorRefNoAlpha();
break;
- // case COLOR_HIGHLIGHT:
- // cr = RGB(0, 0, 255);
- // cr = 0x0000ffFF;
- // break;
- // case COLOR_HIGHLIGHTTEXT:
- // cr = RGB(255, 0, 0);
- // cr = 0xFFFFFFFF;
- // break;
+ case COLOR_HIGHLIGHT:
+ if (m_outer->windowsTextInputProps().selectionColor)
+ return (*m_outer->windowsTextInputProps().selectionColor).AsColorRefNoAlpha();
+ break;
+
+ case COLOR_HIGHLIGHTTEXT:
+ // For selected text color, we use the same color as the selection background
+ // or the text color if selection color is not specified
+ if (m_outer->windowsTextInputProps().selectionColor) {
+ // Calculate appropriate text color based on selection background
+ auto selectionColor = (*m_outer->windowsTextInputProps().selectionColor).AsColorRefNoAlpha();
+ // Use white text for dark selection, black text for light selection
+ int r = GetRValue(selectionColor);
+ int g = GetGValue(selectionColor);
+ int b = GetBValue(selectionColor);
+ int brightness = (r * 299 + g * 587 + b * 114) / 1000;
+ return brightness > 125 ? RGB(0, 0, 0) : RGB(255, 255, 255);
+ }
+ break;
// case COLOR_GRAYTEXT:
// cr = RGB(128, 128, 128);
@@ -463,6 +473,13 @@ struct CompTextHost : public winrt::implements {
WindowsTextInputComponentView *m_outer;
};
+int WINAPI
+AutoCorrectOffCallback(LANGID langid, const WCHAR *pszBefore, WCHAR *pszAfter, LONG cchAfter, LONG *pcchReplaced) {
+ wcsncpy_s(pszAfter, cchAfter, pszBefore, _TRUNCATE);
+ *pcchReplaced = static_cast(wcslen(pszAfter));
+ return ATP_CHANGE;
+}
+
facebook::react::AttributedString WindowsTextInputComponentView::getAttributedString() const {
// Use BaseTextShadowNode to get attributed string from children
@@ -986,7 +1003,10 @@ void WindowsTextInputComponentView::updateProps(
if (!facebook::react::floatEquality(
oldTextInputProps.textAttributes.fontSize, newTextInputProps.textAttributes.fontSize) ||
(oldTextInputProps.textAttributes.allowFontScaling != newTextInputProps.textAttributes.allowFontScaling) ||
- oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight) {
+ oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight ||
+ !facebook::react::floatEquality(
+ oldTextInputProps.textAttributes.letterSpacing, newTextInputProps.textAttributes.letterSpacing) ||
+ oldTextInputProps.textAttributes.fontFamily != newTextInputProps.textAttributes.fontFamily) {
m_propBitsMask |= TXTBIT_CHARFORMATCHANGE;
m_propBits |= TXTBIT_CHARFORMATCHANGE;
}
@@ -1051,6 +1071,23 @@ void WindowsTextInputComponentView::updateProps(
m_propBits |= TXTBIT_PARAFORMATCHANGE;
}
+ // Please note: spellcheck performs both red lines and autocorrect as per windows behaviour
+ bool shouldUpdateSpellCheck =
+ (!oldProps || (oldTextInputProps.spellCheck != newTextInputProps.spellCheck) ||
+ (oldTextInputProps.autoCorrect != newTextInputProps.autoCorrect));
+
+ if (shouldUpdateSpellCheck) {
+ bool effectiveSpellCheck = newTextInputProps.spellCheck || newTextInputProps.autoCorrect;
+ updateSpellCheck(effectiveSpellCheck);
+ }
+ if (!oldProps || oldTextInputProps.autoCorrect != newTextInputProps.autoCorrect) {
+ updateAutoCorrect(newTextInputProps.autoCorrect);
+ }
+
+ if (oldTextInputProps.selectionColor != newTextInputProps.selectionColor) {
+ m_needsRedraw = true;
+ }
+
UpdatePropertyBits();
}
@@ -1136,6 +1173,49 @@ void WindowsTextInputComponentView::updateLayoutMetrics(
m_imgHeight = newHeight;
}
+std::pair WindowsTextInputComponentView::GetContentSize() const noexcept {
+ if (!m_textServices)
+ return {0.0f, 0.0f};
+
+ // Get a device context for measurement
+ HDC hdc = GetDC(nullptr);
+ if (!hdc)
+ return {0.0f, 0.0f};
+
+ // Use the layout width as the constraint (always multiline)
+ float availableWidth = m_layoutMetrics.frame.size.width;
+ float scale = m_layoutMetrics.pointScaleFactor;
+ float dpi = m_layoutMetrics.pointScaleFactor * GetDpiForSystem();
+ constexpr float HIMETRIC_PER_INCH = 2540.0f;
+
+ SIZE extentHimetric = {
+ static_cast(availableWidth * scale * HIMETRIC_PER_INCH / dpi),
+ static_cast(std::numeric_limits::max() * HIMETRIC_PER_INCH / dpi)};
+
+ SIZE naturalSize = {0, 0};
+
+ HRESULT hr = m_textServices->TxGetNaturalSize(
+ DVASPECT_CONTENT,
+ hdc,
+ nullptr,
+ nullptr,
+ static_cast(TXTNS_FITTOCONTENTWSP),
+ reinterpret_cast(&extentHimetric),
+ &naturalSize.cx,
+ &naturalSize.cy);
+
+ ReleaseDC(nullptr, hdc);
+
+ if (FAILED(hr)) {
+ return {0.0f, 0.0f};
+ }
+
+ float contentWidth = static_cast(naturalSize.cx) / scale;
+ float contentHeight = static_cast(naturalSize.cy) / scale;
+
+ return {contentWidth, contentHeight};
+}
+
// When we are notified by RichEdit that the text changed, we need to notify JS
void WindowsTextInputComponentView::OnTextUpdated() noexcept {
auto data = m_state->getData();
@@ -1154,6 +1234,13 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
onChangeArgs.text = GetTextFromRichEdit();
onChangeArgs.eventCount = ++m_nativeEventCount;
emitter->onChange(onChangeArgs);
+ if (windowsTextInputProps().multiline) {
+ auto [contentWidth, contentHeight] = GetContentSize();
+ facebook::react::WindowsTextInputEventEmitter::OnContentSizeChange onContentSizeChangeArgs;
+ onContentSizeChangeArgs.contentSize.width = contentWidth;
+ onContentSizeChangeArgs.contentSize.height = contentHeight;
+ emitter->onContentSizeChange(onContentSizeChangeArgs);
+ }
}
if (m_uiaProvider) {
@@ -1228,6 +1315,13 @@ void WindowsTextInputComponentView::onMounted() noexcept {
m_propBits |= TXTBIT_CHARFORMATCHANGE;
}
InternalFinalize();
+
+ // Handle autoFocus property - focus the component when mounted if autoFocus is true
+ if (windowsTextInputProps().autoFocus) {
+ if (auto root = rootComponentView()) {
+ root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
+ }
+ }
}
std::optional WindowsTextInputComponentView::getAccessiblityValue() noexcept {
@@ -1272,9 +1366,12 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
// set font size -- 15 to convert twips to pt
const auto &props = windowsTextInputProps();
- float fontSize = m_fontSizeMultiplier *
+ float fontSize =
(std::isnan(props.textAttributes.fontSize) ? facebook::react::TextAttributes::defaultTextAttributes().fontSize
: props.textAttributes.fontSize);
+
+ fontSize *= m_fontSizeMultiplier;
+
// TODO get fontSize from props.textAttributes, or defaultTextAttributes, or fragment?
cfNew.dwMask |= CFM_SIZE;
cfNew.yHeight = static_cast(fontSize * 15);
@@ -1545,4 +1642,39 @@ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
}
}
+void WindowsTextInputComponentView::updateLetterSpacing(float letterSpacing) noexcept {
+ CHARFORMAT2W cf = {};
+ cf.cbSize = sizeof(CHARFORMAT2W);
+ cf.dwMask = CFM_SPACING;
+ cf.sSpacing = static_cast(letterSpacing * 20); // Convert to TWIPS
+
+ LRESULT res;
+
+ // Apply to all existing text like placeholder
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_ALL, reinterpret_cast(&cf), &res));
+
+ // Apply to future text input
+ winrt::check_hresult(
+ m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION, reinterpret_cast(&cf), &res));
+}
+
+void WindowsTextInputComponentView::updateAutoCorrect(bool enable) noexcept {
+ LRESULT lresult;
+ winrt::check_hresult(m_textServices->TxSendMessage(
+ EM_SETAUTOCORRECTPROC, enable ? 0 : reinterpret_cast(AutoCorrectOffCallback), 0, &lresult));
+}
+
+void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
+ LRESULT currentLangOptions;
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_GETLANGOPTIONS, 0, 0, ¤tLangOptions));
+
+ DWORD newLangOptions = static_cast(currentLangOptions);
+ if (enable) {
+ newLangOptions |= IMF_SPELLCHECKING;
+ }
+
+ LRESULT lresult;
+ winrt::check_hresult(
+ m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
+}
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h
index 155fe5e6492..1f547f29b6a 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h
@@ -97,6 +97,7 @@ struct WindowsTextInputComponentView
void UpdateText(const std::string &str) noexcept;
void OnTextUpdated() noexcept;
void OnSelectionChanged(LONG start, LONG end) noexcept;
+ std::pair GetContentSize() const noexcept;
std::string GetTextFromRichEdit() const noexcept;
void updateCursorColor(
const facebook::react::SharedColor &cursorColor,
@@ -110,6 +111,10 @@ struct WindowsTextInputComponentView
const std::string &previousCapitalizationType,
const std::string &newcapitalizationType) noexcept;
+ void updateLetterSpacing(float letterSpacing) noexcept;
+ void updateAutoCorrect(bool value) noexcept;
+ void updateSpellCheck(bool value) noexcept;
+
winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
winrt::Microsoft::ReactNative::Composition::Experimental::IDrawingSurfaceBrush m_drawingSurface{nullptr};
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp
index ea4e4e28b74..c3b13344ec8 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp
@@ -24,6 +24,7 @@ WindowsTextInputProps::WindowsTextInputProps(
*/
allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
+ autoCorrect(convertRawProp(context, rawProps, "autoCorrect", sourceProps.autoCorrect, {true})),
clearTextOnFocus(convertRawProp(context, rawProps, "clearTextOnFocus", sourceProps.clearTextOnFocus, {false})),
editable(convertRawProp(context, rawProps, "editable", sourceProps.editable, {true})),
maxLength(convertRawProp(context, rawProps, "maxLength", sourceProps.maxLength, {0})),
@@ -36,7 +37,7 @@ WindowsTextInputProps::WindowsTextInputProps(
selection(convertRawProp(context, rawProps, "selection", sourceProps.selection, {})),
selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
selectTextOnFocus(convertRawProp(context, rawProps, "selectTextOnFocus", sourceProps.selectTextOnFocus, {false})),
- spellCheck(convertRawProp(context, rawProps, "spellCheck", sourceProps.spellCheck, {false})),
+ spellCheck(convertRawProp(context, rawProps, "spellCheck", sourceProps.spellCheck, {true})),
text(convertRawProp(context, rawProps, "text", sourceProps.text, {})),
mostRecentEventCount(
convertRawProp(context, rawProps, "mostRecentEventCount", sourceProps.mostRecentEventCount, {0})),
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h
index 6ad4f239894..2004eaca55a 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h
@@ -97,6 +97,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
setProp(const PropsParserContext &context, RawPropsPropNameHash hash, const char *propName, RawValue const &value);
bool allowFontScaling{true};
+ bool autoCorrect{true};
bool clearTextOnFocus{false};
bool editable{true};
int maxLength{0};
@@ -108,7 +109,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
CompWindowsTextInputSelectionStruct selection{};
SharedColor selectionColor{};
bool selectTextOnFocus{false};
- bool spellCheck{false};
+ bool spellCheck{true};
std::string text{};
int mostRecentEventCount{0};
bool secureTextEntry{false};
diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp
index 4739ca7ff5a..e40181fe21f 100644
--- a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp
@@ -166,6 +166,24 @@ void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, bool old
UiaRaiseAutomationPropertyChangedEvent(spProviderSimple.get(), propId, CComVariant(oldValue), CComVariant(newValue));
}
+void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, int oldValue, int newValue) noexcept {
+ auto spProviderSimple = provider.try_as();
+
+ if (spProviderSimple == nullptr || oldValue == newValue || !WasUiaPropertyAdvised(spProviderSimple, propId))
+ return;
+
+ UiaRaiseAutomationPropertyChangedEvent(spProviderSimple.get(), propId, CComVariant(oldValue), CComVariant(newValue));
+}
+
+void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, long oldValue, long newValue) noexcept {
+ auto spProviderSimple = provider.try_as();
+
+ if (spProviderSimple == nullptr || oldValue == newValue || !WasUiaPropertyAdvised(spProviderSimple, propId))
+ return;
+
+ UiaRaiseAutomationPropertyChangedEvent(spProviderSimple.get(), propId, CComVariant(oldValue), CComVariant(newValue));
+}
+
void UpdateUiaProperty(
winrt::IInspectable provider,
PROPERTYID propId,
@@ -180,6 +198,16 @@ void UpdateUiaProperty(
spProviderSimple.get(), propId, CComVariant(oldValue.c_str()), CComVariant(newValue.c_str()));
}
+void UpdateUiaProperty(
+ winrt::IInspectable provider,
+ PROPERTYID propId,
+ const std::optional &oldValue,
+ const std::optional &newValue) noexcept {
+ std::string oldData = oldValue.value_or("");
+ std::string newData = newValue.value_or("");
+ UpdateUiaProperty(provider, propId, oldData, newData);
+}
+
long GetLiveSetting(const std::string &liveRegion) noexcept {
if (liveRegion == "polite") {
return LiveSetting::Polite;
@@ -254,4 +282,18 @@ ToggleState GetToggleState(const std::optional
#include
+#include
#include
#include
@@ -22,14 +23,36 @@ HRESULT UiaGetBoundingRectangleHelper(::Microsoft::ReactNative::ReactTaggedView
HRESULT UiaSetFocusHelper(::Microsoft::ReactNative::ReactTaggedView &view) noexcept;
-void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, bool oldValue, bool newValue) noexcept;
+void UpdateUiaProperty(
+ winrt::Windows::Foundation::IInspectable provider,
+ PROPERTYID propId,
+ bool oldValue,
+ bool newValue) noexcept;
+
+void UpdateUiaProperty(
+ winrt::Windows::Foundation::IInspectable provider,
+ PROPERTYID propId,
+ int oldValue,
+ int newValue) noexcept;
+
+void UpdateUiaProperty(
+ winrt::Windows::Foundation::IInspectable provider,
+ PROPERTYID propId,
+ long oldValue,
+ long newValue) noexcept;
void UpdateUiaProperty(
- winrt::IInspectable provider,
+ winrt::Windows::Foundation::IInspectable provider,
PROPERTYID propId,
const std::string &oldValue,
const std::string &newValue) noexcept;
+void UpdateUiaProperty(
+ winrt::Windows::Foundation::IInspectable provider,
+ PROPERTYID propId,
+ const std::optional &oldValue,
+ const std::optional &newValue) noexcept;
+
long GetLiveSetting(const std::string &liveRegion) noexcept;
void DispatchAccessibilityAction(::Microsoft::ReactNative::ReactTaggedView &view, const std::string &action) noexcept;
@@ -41,4 +64,6 @@ void AddSelectionItemsToContainer(CompositionDynamicAutomationProvider *provider
void RemoveSelectionItemsFromContainer(CompositionDynamicAutomationProvider *provider) noexcept;
ToggleState GetToggleState(const std::optional &state) noexcept;
+
+TextDecorationLineStyle GetTextDecorationLineStyle(facebook::react::TextDecorationStyle style) noexcept;
} // namespace winrt::Microsoft::ReactNative::implementation
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp
index 091e0c52f48..eecc9ac1703 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp
@@ -38,20 +38,38 @@ void HostPlatformViewEventEmitter::onBlur() const {
#pragma mark - Mouse Events
-void HostPlatformViewEventEmitter::onMouseEnter(PointerEvent const &pointerEvent) const {
+void HostPlatformViewEventEmitter::onMouseEnter(MouseEvent const &pointerEvent) const {
dispatchEvent(
"mouseEnter",
- std::make_shared(pointerEvent),
+ std::make_shared(pointerEvent),
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
-void HostPlatformViewEventEmitter::onMouseLeave(PointerEvent const &pointerEvent) const {
+void HostPlatformViewEventEmitter::onMouseLeave(MouseEvent const &pointerEvent) const {
dispatchEvent(
"mouseLeave",
- std::make_shared(pointerEvent),
+ std::make_shared(pointerEvent),
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
+#pragma mark - Touch Events
+
+void HostPlatformViewEventEmitter::onPressIn(GestureResponderEvent event) const {
+ dispatchEvent("pressIn", [event](jsi::Runtime &runtime) {
+ auto payload = jsi::Object(runtime);
+ auto nativeEvent = jsi::Object(runtime);
+ nativeEvent.setProperty(runtime, "target", static_cast(event.target));
+ nativeEvent.setProperty(runtime, "pageX", event.pagePoint.x);
+ nativeEvent.setProperty(runtime, "pageY", event.pagePoint.y);
+ nativeEvent.setProperty(runtime, "locationX", event.offsetPoint.x);
+ nativeEvent.setProperty(runtime, "locationY", event.offsetPoint.y);
+ nativeEvent.setProperty(runtime, "timestamp", event.timestamp);
+ nativeEvent.setProperty(runtime, "identifier", event.identifier);
+ payload.setProperty(runtime, "nativeEvent", nativeEvent);
+ return payload;
+ });
+}
+
} // namespace facebook::react
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h
index 95913ef2eb0..4c2d132ec57 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h
@@ -5,9 +5,18 @@
#include
#include "KeyEvent.h"
+#include "MouseEvent.h"
namespace facebook::react {
+struct GestureResponderEvent {
+ Tag target;
+ Point pagePoint;
+ Point offsetPoint;
+ double timestamp;
+ int identifier;
+};
+
class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
public:
using BaseViewEventEmitter::BaseViewEventEmitter;
@@ -24,8 +33,12 @@ class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
#pragma mark - Mouse Events
- void onMouseEnter(PointerEvent const &pointerEvent) const;
- void onMouseLeave(PointerEvent const &pointerEvent) const;
+ void onMouseEnter(MouseEvent const &pointerEvent) const;
+ void onMouseLeave(MouseEvent const &pointerEvent) const;
+
+#pragma mark - Touch Events
+
+ virtual void onPressIn(GestureResponderEvent event) const;
};
-} // namespace facebook::react
+} // namespace facebook::react
\ No newline at end of file
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp
index dfdb20cdc49..4fa1294707f 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp
@@ -39,6 +39,26 @@ HostPlatformViewProps::HostPlatformViewProps(
CoreFeatures::enablePropIteratorSetter
? sourceProps.accessibilitySetSize
: convertRawProp(context, rawProps, "accessibilitySetSize", sourceProps.accessibilitySetSize, 0)),
+ accessibilityLevel(
+ CoreFeatures::enablePropIteratorSetter
+ ? sourceProps.accessibilityLevel
+ : convertRawProp(context, rawProps, "accessibilityLevel", sourceProps.accessibilityLevel, 0)),
+ accessibilityItemType(
+ CoreFeatures::enablePropIteratorSetter
+ ? sourceProps.accessibilityItemType
+ : convertRawProp(context, rawProps, "accessibilityItemType", sourceProps.accessibilityItemType, {})),
+ accessibilityAccessKey(
+ CoreFeatures::enablePropIteratorSetter
+ ? sourceProps.accessibilityAccessKey
+ : convertRawProp(context, rawProps, "accessibilityAccessKey", sourceProps.accessibilityAccessKey, {})),
+ accessibilityDescription(
+ CoreFeatures::enablePropIteratorSetter ? sourceProps.accessibilityDescription
+ : convertRawProp(
+ context,
+ rawProps,
+ "accessibilityDescription",
+ sourceProps.accessibilityDescription,
+ {})),
accessibilityLiveRegion(
CoreFeatures::enablePropIteratorSetter ? sourceProps.accessibilityLiveRegion
: convertRawProp(
@@ -83,6 +103,10 @@ void HostPlatformViewProps::setProp(
RAW_SET_PROP_SWITCH_CASE_BASIC(focusable);
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityPosInSet);
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilitySetSize);
+ RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLevel);
+ RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityItemType);
+ RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityAccessKey);
+ RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityDescription);
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLiveRegion);
RAW_SET_PROP_SWITCH_CASE_BASIC(keyDownEvents);
RAW_SET_PROP_SWITCH_CASE_BASIC(keyUpEvents);
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h
index 885dd8cbf18..f38e14ced23 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h
@@ -27,6 +27,10 @@ class HostPlatformViewProps : public BaseViewProps {
int accessibilityPosInSet{0};
int accessibilitySetSize{0};
std::string accessibilityLiveRegion{"none"};
+ int accessibilityLevel{0};
+ std::optional accessibilityItemType{};
+ std::optional accessibilityAccessKey{};
+ std::optional accessibilityDescription{};
// std::optional overflowAnchor{};
std::optional tooltip{};
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h
new file mode 100644
index 00000000000..68ebfe073d0
--- /dev/null
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include
+
+namespace facebook::react {
+
+struct MouseEvent : public PointerEvent {
+ MouseEvent(PointerEvent &event) : PointerEvent(event){};
+
+ // We override the type so that it is not recorded as a PointerType,
+ // otherwise PointerEventsProcessor gets confused by the Windows specific MouseEvents
+ EventPayloadType getType() const override {
+ return static_cast(-1);
+ };
+};
+
+} // namespace facebook::react
\ No newline at end of file
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp
index 0b866b6e3ea..6654669d6e0 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp
@@ -19,7 +19,7 @@ namespace facebook::react {
void TextLayoutManager::GetTextLayout(
AttributedStringBox attributedStringBox,
ParagraphAttributes paragraphAttributes,
- LayoutConstraints layoutConstraints,
+ Size size,
winrt::com_ptr &spTextLayout) noexcept {
if (attributedStringBox.getValue().isEmpty())
return;
@@ -43,10 +43,7 @@ void TextLayoutManager::GetTextLayout(
static_cast(DWRITE_FONT_WEIGHT_REGULAR))),
style,
DWRITE_FONT_STRETCH_NORMAL,
- (outerFragment.textAttributes.allowFontScaling.value_or(true) &&
- !std::isnan(outerFragment.textAttributes.fontSizeMultiplier))
- ? (outerFragment.textAttributes.fontSizeMultiplier * outerFragment.textAttributes.fontSize)
- : outerFragment.textAttributes.fontSize,
+ outerFragment.textAttributes.fontSize,
L"",
spTextFormat.put()));
@@ -95,11 +92,44 @@ void TextLayoutManager::GetTextLayout(
str.c_str(), // The string to be laid out and formatted.
static_cast(str.size()), // The length of the string.
spTextFormat.get(), // The text format to apply to the string (contains font information, etc).
- layoutConstraints.maximumSize.width, // The width of the layout box.
- layoutConstraints.maximumSize.height, // The height of the layout box.
+ size.width, // The width of the layout box.
+ size.height, // The height of the layout box.
spTextLayout.put() // The IDWriteTextLayout interface pointer.
));
+ // Apply max width constraint and ellipsis trimming to ensure consistency with rendering
+ DWRITE_TEXT_METRICS metrics;
+ winrt::check_hresult(spTextLayout->GetMetrics(&metrics));
+
+ if (metrics.width > size.width) {
+ spTextLayout->SetMaxWidth(size.width);
+ }
+
+ // Apply DWRITE_TRIMMING for ellipsizeMode
+ DWRITE_TRIMMING trimming = {};
+ winrt::com_ptr ellipsisSign;
+
+ switch (paragraphAttributes.ellipsizeMode) {
+ case facebook::react::EllipsizeMode::Tail:
+ trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
+ break;
+ case facebook::react::EllipsizeMode::Clip:
+ trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
+ break;
+ default:
+ trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; // Default to tail behavior
+ break;
+ }
+
+ // Use DWriteFactory to create the ellipsis trimming sign
+ if (trimming.granularity != DWRITE_TRIMMING_GRANULARITY_NONE) {
+ auto dwriteFactory = Microsoft::ReactNative::DWriteFactory();
+ HRESULT hr = dwriteFactory->CreateEllipsisTrimmingSign(spTextLayout.get(), ellipsisSign.put());
+ if (SUCCEEDED(hr)) {
+ spTextLayout->SetTrimming(&trimming, ellipsisSign.get());
+ }
+ }
+
unsigned int position = 0;
unsigned int length = 0;
for (const auto &fragment : fragments) {
@@ -121,11 +151,7 @@ void TextLayoutManager::GetTextLayout(
attributes.fontWeight.value_or(static_cast(DWRITE_FONT_WEIGHT_REGULAR))),
range));
winrt::check_hresult(spTextLayout->SetFontStyle(fragmentStyle, range));
- winrt::check_hresult(spTextLayout->SetFontSize(
- (attributes.allowFontScaling.value_or(true) && !std::isnan(attributes.fontSizeMultiplier))
- ? (attributes.fontSizeMultiplier * attributes.fontSize)
- : attributes.fontSize,
- range));
+ winrt::check_hresult(spTextLayout->SetFontSize(attributes.fontSize, range));
if (!isnan(attributes.letterSpacing)) {
winrt::check_hresult(
@@ -136,6 +162,18 @@ void TextLayoutManager::GetTextLayout(
}
}
+void TextLayoutManager::GetTextLayout(
+ AttributedStringBox attributedStringBox,
+ ParagraphAttributes paragraphAttributes,
+ LayoutConstraints layoutConstraints,
+ winrt::com_ptr &spTextLayout) noexcept {
+ if (attributedStringBox.getValue().isEmpty())
+ return;
+
+ GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize, spTextLayout);
+}
+
+// measure entire text (inluding attachments)
TextMeasurement TextLayoutManager::measure(
AttributedStringBox attributedStringBox,
ParagraphAttributes paragraphAttributes,
@@ -198,25 +236,6 @@ TextMeasurement TextLayoutManager::measureCachedSpannableById(
return {};
}
-LinesMeasurements TextLayoutManager::measureLines(
- AttributedString attributedString,
- ParagraphAttributes paragraphAttributes,
- Size size) const {
- assert(false);
- return {};
-}
-
-std::shared_ptr TextLayoutManager::getHostTextStorage(
- AttributedString attributedString,
- ParagraphAttributes paragraphAttributes,
- LayoutConstraints layoutConstraints) const {
- return nullptr;
-}
-
-void *TextLayoutManager::getNativeTextLayoutManager() const {
- return (void *)this;
-}
-
Microsoft::ReactNative::TextTransform ConvertTextTransform(std::optional const &transform) {
if (transform) {
switch (transform.value()) {
@@ -232,10 +251,92 @@ Microsoft::ReactNative::TextTransform ConvertTextTransform(std::optional spTextLayout;
+
+ GetTextLayout(AttributedStringBox(attributedString), paragraphAttributes, size, spTextLayout);
+
+ if (spTextLayout) {
+ std::vector lineMetrics;
+ uint32_t actualLineCount;
+ spTextLayout->GetLineMetrics(nullptr, 0, &actualLineCount);
+ lineMetrics.resize(static_cast(actualLineCount));
+ winrt::check_hresult(spTextLayout->GetLineMetrics(lineMetrics.data(), actualLineCount, &actualLineCount));
+ uint32_t startRange = 0;
+ const auto count = (paragraphAttributes.maximumNumberOfLines > 0)
+ ? std::min(static_cast(paragraphAttributes.maximumNumberOfLines), actualLineCount)
+ : actualLineCount;
+ for (uint32_t i = 0; i < count; ++i) {
+ UINT32 actualHitTestCount = 0;
+ spTextLayout->HitTestTextRange(
+ startRange,
+ lineMetrics[i].length,
+ 0, // x
+ 0, // y
+ NULL,
+ 0, // metrics count
+ &actualHitTestCount);
+
+ // Allocate enough room to return all hit-test metrics.
+ std::vector hitTestMetrics(actualHitTestCount);
+ spTextLayout->HitTestTextRange(
+ startRange,
+ lineMetrics[i].length,
+ 0, // x
+ 0, // y
+ &hitTestMetrics[0],
+ static_cast(hitTestMetrics.size()),
+ &actualHitTestCount);
+
+ float width = 0;
+ for (auto tm : hitTestMetrics) {
+ width += tm.width;
+ }
+
+ std::string str;
+ for (const auto &fragment : attributedString.getFragments()) {
+ str = str +
+ winrt::to_string(Microsoft::ReactNative::TransformableText::TransformText(
+ winrt::hstring{Microsoft::Common::Unicode::Utf8ToUtf16(fragment.string)},
+ ConvertTextTransform(fragment.textAttributes.textTransform)));
+ }
+
+ lineMeasurements.emplace_back(LineMeasurement(
+ str.substr(startRange, lineMetrics[i].length),
+ {{hitTestMetrics[0].left, hitTestMetrics[0].top}, // origin
+ {width, lineMetrics[i].height}},
+ 0.0f, // TODO descender
+ 0.0f, // TODO: capHeight
+ 0.0f, // TODO ascender
+ 0.0f // TODO: xHeight
+ ));
+
+ startRange += lineMetrics[i].length;
+ }
+ }
+
+ return lineMeasurements;
+}
+
+std::shared_ptr TextLayoutManager::getHostTextStorage(
+ AttributedString attributedString,
+ ParagraphAttributes paragraphAttributes,
+ LayoutConstraints layoutConstraints) const {
+ return nullptr;
+}
+
+void *TextLayoutManager::getNativeTextLayoutManager() const {
+ return (void *)this;
+}
+
winrt::hstring TextLayoutManager::GetTransformedText(AttributedStringBox const &attributedStringBox) {
winrt::hstring result{};
for (const auto &fragment : attributedStringBox.getValue().getFragments()) {
diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h
index f89c8308baa..65e22c511b3 100644
--- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h
+++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h
@@ -74,10 +74,22 @@ class TextLayoutManager {
LayoutConstraints layoutConstraints,
winrt::com_ptr &spTextLayout) noexcept;
+ static void GetTextLayoutByAdjustingFontSizeToFit(
+ AttributedStringBox attributedStringBox,
+ const ParagraphAttributes ¶graphAttributes,
+ LayoutConstraints layoutConstraints,
+ winrt::com_ptr &spTextLayout,
+ TextMeasurement::Attachments &attachments) noexcept;
+
#pragma endregion
private:
static winrt::hstring GetTransformedText(AttributedStringBox const &attributedStringBox);
+ static void GetTextLayout(
+ AttributedStringBox attributedString,
+ ParagraphAttributes paragraphAttributes,
+ Size size,
+ winrt::com_ptr &spTextLayout) noexcept;
ContextContainer::Shared m_contextContainer;
#pragma warning(push)
diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters
index ad0c2b22282..ab5621fe167 100644
--- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters
+++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters
@@ -123,9 +123,6 @@
Modules
-
- Modules
-
Views\Image
@@ -292,6 +289,7 @@
+
diff --git a/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj b/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj
index 24369463cac..54884ec0edf 100644
--- a/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj
+++ b/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj
@@ -17,7 +17,7 @@
false
Windows Store
10.0
- 10.0.22000.0
+ 10.0.22621.0
true
None
diff --git a/vnext/PropertySheets/External/Microsoft.ReactNative.WindowsSdk.Default.props b/vnext/PropertySheets/External/Microsoft.ReactNative.WindowsSdk.Default.props
index b3873f7bccc..0b3424d52f2 100644
--- a/vnext/PropertySheets/External/Microsoft.ReactNative.WindowsSdk.Default.props
+++ b/vnext/PropertySheets/External/Microsoft.ReactNative.WindowsSdk.Default.props
@@ -12,20 +12,20 @@
See https://microsoft.github.io/react-native-windows/docs/win10-compat
-->
- 10.0.19041.0
+ 10.0.22621.0
10.0.17763.0
- 10.0.22000.0
+ 10.0.22621.0
10.0.18362.0
- 10.0.19041.0
+ 10.0.22621.0
10.0.17763.0
- 10.0.22000.0
+ 10.0.22621.0
10.0.17763.0
diff --git a/vnext/Scripts/Tfs/Start-TestServers.ps1 b/vnext/Scripts/Tfs/Start-TestServers.ps1
index f3f5d515c86..1a385042ef5 100644
--- a/vnext/Scripts/Tfs/Start-TestServers.ps1
+++ b/vnext/Scripts/Tfs/Start-TestServers.ps1
@@ -16,7 +16,8 @@ Write-Host "Starting packager"
Set-Location -Path "$PSScriptRoot\..\.."
-Start-Process npm -PassThru `
+$npmCmd = (Get-Command npm.cmd -ErrorAction Stop).Source
+Start-Process $npmCmd -PassThru `
-NoNewWindow `
-WorkingDirectory "$PSScriptRoot\..\.." `
-ArgumentList "run start" `
diff --git a/vnext/Scripts/rnw-dependencies.ps1 b/vnext/Scripts/rnw-dependencies.ps1
index 8bf3f797b56..01e182dcc8f 100644
--- a/vnext/Scripts/rnw-dependencies.ps1
+++ b/vnext/Scripts/rnw-dependencies.ps1
@@ -1,3 +1,4 @@
+
# Troubleshoot RNW dependencies
param(
[switch]$Install = $false,
@@ -65,32 +66,31 @@ $vsComponents = @('Microsoft.Component.MSBuild',
'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
'Microsoft.VisualStudio.ComponentGroup.UWP.Support',
'Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core',
- 'Microsoft.VisualStudio.Component.Windows10SDK.19041');
+ 'Microsoft.VisualStudio.Component.Windows10SDK.19041',
+ 'Microsoft.VisualStudio.Component.Windows11SDK.22621');
# UWP.VC is not needed to build the projects with msbuild, but the VS IDE requires it.
if (!($tagsToInclude.Contains('buildLab'))) {
$vsComponents += 'Microsoft.VisualStudio.ComponentGroup.UWP.VC';
}
-# Windows11SDK is only needed for the more experimental composition projects using newer WinAppSDK versions
-if ($tagsToInclude.Contains('rnwDev')) {
- $vsComponents += 'Microsoft.VisualStudio.Component.Windows11SDK.22000';
-}
-
$vsWorkloads = @('Microsoft.VisualStudio.Workload.ManagedDesktop',
'Microsoft.VisualStudio.Workload.NativeDesktop',
'Microsoft.VisualStudio.Workload.Universal');
$vsAll = ($vsComponents + $vsWorkloads);
+# The minimum winget version to check for
+$wingetver = "1.7.11261";
+
# The minimum VS version to check for
# Note: For install to work, whatever min version you specify here must be met by the current package available on winget.
$vsver = "17.11.0";
# The exact .NET SDK version to check for
-$dotnetver = "6.0";
+$dotnetver = "8.0";
# Version name of the winget package
-$wingetDotNetVer = "6";
+$wingetDotNetVer = "8";
$v = [System.Environment]::OSVersion.Version;
if ($env:Agent_BuildDirectory) {
@@ -127,7 +127,7 @@ function Get-VSPathPropertyForEachInstall {
[String[]]$paths = ($output | Where-Object { (Test-Path $_) });
return $paths;
}
-
+
return $null;
}
@@ -187,26 +187,26 @@ function GetVSChannelAndProduct {
param(
[string]$VsWhere
)
-
+
if ($VsWhere) {
$channelId = & $VsWhere -version $vsver -property channelId;
$productId = & $VsWhere -version $vsver -property productId;
-
+
# Channel/product not found, check one more time for pre-release
if (($channelId -eq $null) -or ($productId -eq $null)) {
$channelId = & $VsWhere -version $vsver -property channelId -prerelease;
$productId = & $VsWhere -version $vsver -property productId -prerelease;
}
-
+
return $channelId, $productId;
}
-
+
return $null, $null;
}
function InstallVS {
$vsWhere = Get-VSWhere;
-
+
$channelId, $productId = GetVSChannelAndProduct -VsWhere $vsWhere
if (($vsWhere -eq $null) -or ($channelId -eq $null) -or ($productId -eq $null)) {
@@ -223,7 +223,7 @@ function InstallVS {
$channelId, $productId = GetVSChannelAndProduct -VsWhere $vsWhere
}
-
+
# Final check before attempting install
if (($vsWhere -eq $null) -or ($channelId -eq $null) -or ($productId -eq $null)) {
throw "Unable to find or install a compatible version of Visual Studio >= ($vsver).";
@@ -240,8 +240,9 @@ function CheckNode {
try {
$nodeVersion = (Get-Command node -ErrorAction Stop).Version;
Write-Verbose "Node version found: $nodeVersion";
- $v = $nodeVersion.Major;
- return ($v -ge 18) -and (($v % 2) -eq 0);
+ $major = $nodeVersion.Major;
+ $minor = $nodeVersion.Minor;
+ return ($major -gt 22) -or (($major -eq 22) -and ($minor -ge 14));
} catch { Write-Debug $_ }
Write-Verbose "Node not found.";
@@ -331,7 +332,7 @@ function InstallCppWinRT_VSIX {
$url = "https://marketplace.visualstudio.com/_apis/public/gallery/publishers/CppWinRTTeam/vsextensions/cppwinrt101804264/2.0.210304.5/vspackage";
Write-Verbose "Downloading CppWinRT VSIX from $url";
Invoke-WebRequest -UseBasicParsing $url -OutFile $env:TEMP\Microsoft.Windows.CppWinRT.vsix;
-
+
$vsWhere = Get-VSWhere;
if ($vsWhere -eq $null) {
return;
@@ -437,10 +438,10 @@ $requirements = @(
},
@{
Id=[CheckId]::Node;
- Name = 'Node.js (LTS, >= 18.0)';
+ Name = 'Node.js (LTS, >= 22.0)';
Tags = @('appDev');
Valid = { CheckNode; }
- Install = { WinGetInstall OpenJS.NodeJS.LTS "18.16.1" };
+ Install = { WinGetInstall OpenJS.NodeJS.LTS "22.14.0" };
HasVerboseOutput = $true;
},
@{
@@ -517,18 +518,30 @@ $requirements = @(
}
);
+function InstallWinGet {
+ Write-Verbose "Updating WinGet version...";
+ Invoke-WebRequest -Uri https://aka.ms/getwinget -OutFile "$env:TEMP\winget.msixbundle";
+ Add-AppPackage -ForceApplicationShutdown $env:TEMP\winget.msixbundle;
+ Remove-Item $env:TEMP\winget.msixbundle;
+}
+
function EnsureWinGetForInstall {
Write-Verbose "Checking for WinGet...";
try {
# Check if winget.exe is in PATH
if (Get-Command "winget.exe" -CommandType Application -ErrorAction Ignore) {
Write-Verbose "WinGet found in PATH.";
- return;
+ Write-Verbose "Validating WinGet version...";
+ $wingetverfound = & winget -v;
+ if ([System.Version]$wingetverfound.Substring(1) -ge [System.Version]$wingetver ){
+ Write-Verbose "WinGet version found: $wingetverfound";
+ return;
+ }
}
+ InstallWinGet;
+ $installedwingetver = & winget -v;
+ Write-Verbose "WinGet version installed: $installedwingetver";
} catch { Write-Debug $_ }
-
- Write-Host "WinGet is required to install dependencies. See https://learn.microsoft.com/en-us/windows/package-manager/winget/ for more information.";
- throw "WinGet needed to install.";
}
function WinGetInstall {
@@ -546,7 +559,7 @@ function WinGetInstall {
& winget install "$wingetPackage" --accept-source-agreements --accept-package-agreements
}
}
-
+
function IsElevated {
return [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544");
}
diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems
index 448ee7e5331..e2b22cc5b6a 100644
--- a/vnext/Shared/Shared.vcxitems
+++ b/vnext/Shared/Shared.vcxitems
@@ -64,6 +64,12 @@
true
+
+ true
+
+
+ true
+
true
$(ReactNativeWindowsDir)Microsoft.ReactNative\ReactNativeIsland.idl
diff --git a/vnext/Shared/Shared.vcxitems.filters b/vnext/Shared/Shared.vcxitems.filters
index ae70481500e..cefd80d5ff1 100644
--- a/vnext/Shared/Shared.vcxitems.filters
+++ b/vnext/Shared/Shared.vcxitems.filters
@@ -215,6 +215,12 @@
Source Files\Fabric\Composition
+
+ Source Files\Fabric\Composition
+
+
+ Source Files\Fabric\Composition
+
Source Files\Fabric\Composition
@@ -325,6 +331,8 @@
+
+
diff --git a/vnext/package.json b/vnext/package.json
index 81a6c2ba747..42dbf5b43be 100644
--- a/vnext/package.json
+++ b/vnext/package.json
@@ -77,7 +77,7 @@
"@types/react": "^18.2.6",
"eslint": "^8.19.0",
"eslint-plugin-prettier": "^4.2.1",
- "flow-bin": "^0.217.2",
+ "flow-bin": "^0.228.0",
"jscodeshift": "^0.14.0",
"just-scripts": "^1.3.3",
"prettier": "2.8.8",
diff --git a/vnext/src-win/Libraries/Components/View/View.windows.js b/vnext/src-win/Libraries/Components/View/View.windows.js
index 2706b4a5c90..d1bef838b42 100644
--- a/vnext/src-win/Libraries/Components/View/View.windows.js
+++ b/vnext/src-win/Libraries/Components/View/View.windows.js
@@ -38,6 +38,7 @@ const View: React.AbstractComponent<
accessibilityLabel,
accessibilityLabelledBy,
accessibilityLevel, // Windows
+ accessibilityDescription, //Windows
accessibilityLiveRegion,
accessibilityPosInSet, // Windows
accessibilitySetSize, // Windows
@@ -49,6 +50,7 @@ const View: React.AbstractComponent<
'aria-expanded': ariaExpanded,
'aria-multiselectable': ariaMultiselectable, // Windows
'aria-required': ariaRequired, // Windows
+ 'aria-description': ariaDescription, //Windows
'aria-hidden': ariaHidden,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
@@ -227,6 +229,13 @@ const View: React.AbstractComponent<
// Windows]
+ const computedImportantForAccessibility =
+ ariaHidden === true ||
+ importantForAccessibility === 'no-hide-descendants' ||
+ accessibilityElementsHidden === true
+ ? 'no-hide-descendants'
+ : importantForAccessibility;
+
return (
// [Windows
// In core this is a TextAncestor.Provider value={false} See
@@ -248,6 +257,9 @@ const View: React.AbstractComponent<
}
accessibilityLabel={ariaLabel ?? accessibilityLabel}
accessibilityLevel={ariaLevel ?? accessibilityLevel}
+ accessibilityDescription={
+ ariaDescription ?? accessibilityDescription
+ }
accessibilityPosInSet={ariaPosinset ?? accessibilityPosInSet}
accessibilitySetSize={ariaSetsize ?? accessibilitySetSize}
focusable={_focusable}
@@ -258,11 +270,7 @@ const View: React.AbstractComponent<
}
accessibilityLabelledBy={_accessibilityLabelledBy}
accessibilityValue={_accessibilityValue}
- importantForAccessibility={
- ariaHidden === true
- ? 'no-hide-descendants'
- : importantForAccessibility
- }
+ importantForAccessibility={computedImportantForAccessibility}
nativeID={id ?? nativeID}
style={style}
// $FlowFixMe[incompatible-type]
diff --git a/vnext/src-win/Libraries/Components/View/ViewAccessibility.d.ts b/vnext/src-win/Libraries/Components/View/ViewAccessibility.d.ts
index cfc1c115184..0d78395547d 100644
--- a/vnext/src-win/Libraries/Components/View/ViewAccessibility.d.ts
+++ b/vnext/src-win/Libraries/Components/View/ViewAccessibility.d.ts
@@ -14,6 +14,7 @@ import {NativeSyntheticEvent} from '../../Types/CoreEventTypes';
*/
export interface AccessibilityProps
extends AccessibilityPropsAndroid,
+ AccessibilityPropsWindows,
AccessibilityPropsIOS {
/**
* When true, indicates that the view is an accessibility element.
@@ -258,6 +259,72 @@ export type AccessibilityRole =
| 'listitem' // Windows
| 'toolbar';
+// [Windows]
+export type AnnotationType =
+ | 'AdvanceProofingIssue'
+ | 'Author'
+ | 'CircularReferenceError'
+ | 'Comment'
+ | 'ConflictingChange'
+ | 'DataValidationError'
+ | 'DeletionChange'
+ | 'EditingLockedChange'
+ | 'Endnote'
+ | 'ExternalChange'
+ | 'Footer'
+ | 'Footnote'
+ | 'FormatChange'
+ | 'FormulaError'
+ | 'GrammarError'
+ | 'Header'
+ | 'Highlighted'
+ | 'InsertionChange'
+ | 'Mathematics'
+ | 'MoveChange'
+ | 'SpellingError'
+ | 'TrackChanges'
+ | 'Unknown'
+ | 'UnsyncedChange';
+
+// [Windows]
+export type AccessibilityAnnotationInfo = Readonly<{
+ typeID: AnnotationType;
+ typeName?: string;
+ author?: string;
+ dateTime?: string;
+ target?: string;
+}>;
+export interface AccessibilityPropsWindows {
+ /**
+ * Tells a person using a screen reader what kind of annotation they
+ * have selected. If available, it will also tell a person the author of the annotation and
+ * the date and time the annotation was posted.
+ *
+ * Note: If typeID is 'Unknown', a typeName must be provided.
+ */
+ accessibilityAnnotation?: AccessibilityAnnotationInfo; //Windows
+
+ /**
+ * Identifies the ItemType property, which is a text string describing the type of the automation element.
+ * ItemType is used to obtain information about items in a list, tree view, or data grid. For example, an item in a file directory view might be a "Document File" or a "Folder".
+ */
+ accessibilityItemType?: string; //Windows
+
+ /**
+ * An access key to hook up to the UIA_AccessKey_Property.
+ * Access keys are used in keyboard navigation to allow quick navigation to UI in an application.
+ */
+ accessibilityAccessKey?: string; //Windows
+
+ /**
+ * accessibilityDescription provides more detailed information specific to the element (i.e. last edit date, full location for a file)
+ * while accessibilityHint provides information on what will happen when they perform an action.
+ *
+ */
+ accessibilityDescription?: string; // Windows
+ 'aria-description'?: string; // Windows
+}
+
export interface AccessibilityPropsAndroid {
/**
* Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props,
diff --git a/vnext/src-win/Libraries/Components/View/ViewPropTypes.windows.js b/vnext/src-win/Libraries/Components/View/ViewPropTypes.windows.js
index 95c29c44eb1..b41fe7c5490 100644
--- a/vnext/src-win/Libraries/Components/View/ViewPropTypes.windows.js
+++ b/vnext/src-win/Libraries/Components/View/ViewPropTypes.windows.js
@@ -505,6 +505,8 @@ type WindowsViewProps = $ReadOnly<{|
'aria-posinset'?: ?number,
accessibilitySetSize?: ?number,
'aria-setsize'?: ?number,
+ accessibilityDescription?: ?string,
+ 'aria-description'?: ?string,
/**
* Specifies if the control should show System focus visuals
diff --git a/vnext/src-win/Libraries/NativeComponent/BaseViewConfig.windows.js b/vnext/src-win/Libraries/NativeComponent/BaseViewConfig.windows.js
index 0cabff23c53..dee35971a2e 100644
--- a/vnext/src-win/Libraries/NativeComponent/BaseViewConfig.windows.js
+++ b/vnext/src-win/Libraries/NativeComponent/BaseViewConfig.windows.js
@@ -359,6 +359,10 @@ const validAttributesForNonEventProps = {
accessibilityLiveRegion: true, // [Windows]
accessibilityPosInSet: true, // [Windows]
accessibilitySetSize: true, // [Windows]
+ accessibilityAnnotation: true, // [Windows]
+ accessibilityItemType: true, // [Windows]
+ accessibilityAccessKey: true, // [Windows]
+ accessibilityDescription: true, // [Windows]
disabled: true, // [Windows]
focusable: true, // [Windows]
keyDownEvents: true, // [Windows]
diff --git a/yarn.lock b/yarn.lock
index 3ff993f5b14..43f30763344 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6515,11 +6515,6 @@ flow-api-translator@0.19.1:
hermes-parser "0.19.1"
hermes-transform "0.19.1"
-flow-bin@^0.217.2:
- version "0.217.2"
- resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.217.2.tgz#96affa17f3cb303019f740bffeb28cfab7ce1250"
- integrity sha512-fk4NcfybYjzlww1sEsfk71nqXvonAYpMRFEjmZxibDWWBiaw8DGmqXWZ7XzSunVB15VkJfOstn/sYP1EYPPyWg==
-
flow-bin@^0.228.0:
version "0.228.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.228.0.tgz#345dfd090c9edc074a14ad88d1558051ac124529"