react-native-windows 0.77.2 → 0.77.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/Button.windows.js +3 -0
- package/Libraries/Components/Pressable/Pressable.windows.js +3 -0
- package/Libraries/Components/TextInput/TextInput.windows.js +3 -0
- package/Libraries/Components/Touchable/TouchableBounce.windows.js +2 -0
- package/Libraries/Components/Touchable/TouchableNativeFeedback.windows.js +2 -0
- package/Libraries/Components/Touchable/TouchableOpacity.windows.js +2 -0
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +2 -0
- package/Libraries/Components/View/View.windows.js +3 -0
- package/Libraries/Components/View/ViewAccessibility.d.ts +7 -2
- package/Libraries/Components/View/ViewAccessibility.windows.js +1 -0
- package/Libraries/Components/View/ViewPropTypes.windows.js +1 -0
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Core/setUpDeveloperTools.js +2 -3
- package/Libraries/Image/Image.windows.js +2 -0
- package/Libraries/Text/Text.windows.js +4 -0
- package/Libraries/Text/TextProps.windows.js +1 -0
- package/Libraries/Utilities/HMRClient.js +0 -28
- package/Libraries/Utilities/HMRClientProdShim.js +0 -1
- package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +215 -21
- package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +10 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +115 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +41 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +298 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +59 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +1 -2
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +14 -10
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +3 -2
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +1 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/accessibilityPropsConversions.h +4 -0
- package/Shared/Networking/WinRTWebSocketResource.cpp +369 -7
- package/Shared/Networking/WinRTWebSocketResource.h +118 -0
- package/Shared/Shared.vcxitems +6 -0
- package/Shared/Shared.vcxitems.filters +8 -0
- package/package.json +12 -12
|
@@ -164,6 +164,7 @@ type ButtonProps = $ReadOnly<{|
|
|
|
164
164
|
'aria-disabled'?: ?boolean,
|
|
165
165
|
'aria-expanded'?: ?boolean,
|
|
166
166
|
'aria-selected'?: ?boolean,
|
|
167
|
+
'aria-readonly'?: ?boolean, // Windows
|
|
167
168
|
'aria-multiselectable'?: ?boolean, // Windows
|
|
168
169
|
'aria-required'?: ?boolean, // Windows
|
|
169
170
|
|
|
@@ -312,6 +313,7 @@ const Button: component(
|
|
|
312
313
|
'aria-expanded': ariaExpanded,
|
|
313
314
|
'aria-label': ariaLabel,
|
|
314
315
|
'aria-selected': ariaSelected,
|
|
316
|
+
'aria-readonly': ariaReadOnly, // Windows
|
|
315
317
|
'aria-multiselectable': ariaMultiselectable, // Windows
|
|
316
318
|
'aria-required': ariaRequired, // Windows
|
|
317
319
|
importantForAccessibility,
|
|
@@ -349,6 +351,7 @@ const Button: component(
|
|
|
349
351
|
disabled: ariaDisabled ?? accessibilityState?.disabled,
|
|
350
352
|
expanded: ariaExpanded ?? accessibilityState?.expanded,
|
|
351
353
|
selected: ariaSelected ?? accessibilityState?.selected,
|
|
354
|
+
readOnly: ariaReadOnly ?? accessibilityState?.readOnly, // Windows
|
|
352
355
|
multiselectable: ariaMultiselectable ?? accessibilityState?.multiselectable, // Windows
|
|
353
356
|
required: ariaRequired ?? accessibilityState?.required, // Windows
|
|
354
357
|
};
|
|
@@ -75,6 +75,7 @@ type Props = $ReadOnly<{|
|
|
|
75
75
|
'aria-disabled'?: ?boolean,
|
|
76
76
|
'aria-expanded'?: ?boolean,
|
|
77
77
|
'aria-selected'?: ?boolean,
|
|
78
|
+
'aria-readonly'?: ?boolean, // Windows
|
|
78
79
|
'aria-multiselectable'?: ?boolean, // Windows
|
|
79
80
|
'aria-required'?: ?boolean, // Windows
|
|
80
81
|
/**
|
|
@@ -264,6 +265,7 @@ function Pressable(
|
|
|
264
265
|
'aria-expanded': ariaExpanded,
|
|
265
266
|
'aria-label': ariaLabel,
|
|
266
267
|
'aria-selected': ariaSelected,
|
|
268
|
+
'aria-readonly': ariaReadOnly,
|
|
267
269
|
'aria-multiselectable': ariaMultiselectable, // Windows
|
|
268
270
|
'aria-required': ariaRequired, // Windows
|
|
269
271
|
cancelable,
|
|
@@ -309,6 +311,7 @@ function Pressable(
|
|
|
309
311
|
disabled: ariaDisabled ?? accessibilityState?.disabled,
|
|
310
312
|
expanded: ariaExpanded ?? accessibilityState?.expanded,
|
|
311
313
|
selected: ariaSelected ?? accessibilityState?.selected,
|
|
314
|
+
readOnly: ariaReadOnly ?? accessibilityState?.readOnly,
|
|
312
315
|
multiselectable: ariaMultiselectable ?? accessibilityState?.multiselectable, // Windows
|
|
313
316
|
required: ariaRequired ?? accessibilityState?.required, // Windows
|
|
314
317
|
};
|
|
@@ -1360,6 +1360,7 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1360
1360
|
'aria-disabled': ariaDisabled,
|
|
1361
1361
|
'aria-expanded': ariaExpanded,
|
|
1362
1362
|
'aria-selected': ariaSelected,
|
|
1363
|
+
'aria-readonly': ariaReadOnly, // Windows
|
|
1363
1364
|
'aria-multiselectable': ariaMultiselectable, // Windows
|
|
1364
1365
|
'aria-required': ariaRequired, // Windows
|
|
1365
1366
|
accessibilityState,
|
|
@@ -1691,6 +1692,7 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1691
1692
|
ariaDisabled != null ||
|
|
1692
1693
|
ariaExpanded != null ||
|
|
1693
1694
|
ariaSelected != null ||
|
|
1695
|
+
ariaReadOnly != null || // Windows
|
|
1694
1696
|
ariaMultiselectable != null || // Windows
|
|
1695
1697
|
ariaRequired != null // Windows
|
|
1696
1698
|
) {
|
|
@@ -1700,6 +1702,7 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1700
1702
|
disabled: ariaDisabled ?? accessibilityState?.disabled,
|
|
1701
1703
|
expanded: ariaExpanded ?? accessibilityState?.expanded,
|
|
1702
1704
|
selected: ariaSelected ?? accessibilityState?.selected,
|
|
1705
|
+
readOnly: ariaReadOnly ?? accessibilityState?.readOnly, // Windows
|
|
1703
1706
|
multiselectable:
|
|
1704
1707
|
ariaMultiselectable ?? accessibilityState?.multiselectable, // Windows
|
|
1705
1708
|
required: ariaRequired ?? accessibilityState?.required, // Windows
|
|
@@ -146,6 +146,8 @@ class TouchableBounce extends React.Component<Props, State> {
|
|
|
146
146
|
this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded,
|
|
147
147
|
selected:
|
|
148
148
|
this.props['aria-selected'] ?? this.props.accessibilityState?.selected,
|
|
149
|
+
readOnly:
|
|
150
|
+
this.props['aria-readonly'] ?? this.props.accessibilityState?.readOnly, // Windows
|
|
149
151
|
multiselectable:
|
|
150
152
|
this.props['aria-multiselectable'] ??
|
|
151
153
|
this.props.accessibilityState?.multiselectable, // Windows
|
|
@@ -265,6 +265,8 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
|
|
|
265
265
|
this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded,
|
|
266
266
|
selected:
|
|
267
267
|
this.props['aria-selected'] ?? this.props.accessibilityState?.selected,
|
|
268
|
+
readOnly:
|
|
269
|
+
this.props['aria-readonly'] ?? this.props.accessibilityState?.readOnly,
|
|
268
270
|
multiselectable:
|
|
269
271
|
this.props['aria-multiselectable'] ??
|
|
270
272
|
this.props.accessibilityState?.multiselectable, // Windows
|
|
@@ -235,6 +235,8 @@ class TouchableOpacity extends React.Component<Props, State> {
|
|
|
235
235
|
this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded,
|
|
236
236
|
selected:
|
|
237
237
|
this.props['aria-selected'] ?? this.props.accessibilityState?.selected,
|
|
238
|
+
readOnly:
|
|
239
|
+
this.props['aria-readonly'] ?? this.props.accessibilityState?.readOnly, // Windows
|
|
238
240
|
multiselectable:
|
|
239
241
|
this.props['aria-multiselectable'] ??
|
|
240
242
|
this.props.accessibilityState?.multiselectable, // Windows
|
|
@@ -59,6 +59,7 @@ type Props = $ReadOnly<{|
|
|
|
59
59
|
'aria-disabled'?: ?boolean,
|
|
60
60
|
'aria-expanded'?: ?boolean,
|
|
61
61
|
'aria-selected'?: ?boolean,
|
|
62
|
+
'aria-readonly'?: ?boolean, // Windows
|
|
62
63
|
'aria-multiselectable'?: ?boolean, // Windows
|
|
63
64
|
'aria-required'?: ?boolean, // Windows
|
|
64
65
|
'aria-hidden'?: ?boolean,
|
|
@@ -224,6 +225,7 @@ const TouchableWithoutFeedback: React.AbstractComponent<
|
|
|
224
225
|
disabled: props['aria-disabled'] ?? props.accessibilityState?.disabled,
|
|
225
226
|
expanded: props['aria-expanded'] ?? props.accessibilityState?.expanded,
|
|
226
227
|
selected: props['aria-selected'] ?? props.accessibilityState?.selected,
|
|
228
|
+
readonly: props['aria-readonly'] ?? props.accessibilityState?.readOnly, // Windows
|
|
227
229
|
multiselectable:
|
|
228
230
|
props['aria-multiselectable'] ??
|
|
229
231
|
props.accessibilityState?.multiselectable, // Windows
|
|
@@ -84,6 +84,7 @@ const View: component(
|
|
|
84
84
|
'aria-level': ariaLevel,
|
|
85
85
|
'aria-live': ariaLive,
|
|
86
86
|
'aria-posinset': ariaPosinset, // Windows
|
|
87
|
+
'aria-readonly': ariaReadOnly, // Windows
|
|
87
88
|
'aria-selected': ariaSelected,
|
|
88
89
|
'aria-setsize': ariaSetsize, // Windows
|
|
89
90
|
'aria-valuemax': ariaValueMax,
|
|
@@ -111,6 +112,7 @@ const View: component(
|
|
|
111
112
|
ariaDisabled != null ||
|
|
112
113
|
ariaExpanded != null ||
|
|
113
114
|
ariaSelected != null ||
|
|
115
|
+
ariaReadOnly != null || // Windows
|
|
114
116
|
ariaMultiselectable != null || // Windows
|
|
115
117
|
ariaRequired != null // Windows
|
|
116
118
|
) {
|
|
@@ -120,6 +122,7 @@ const View: component(
|
|
|
120
122
|
disabled: ariaDisabled ?? accessibilityState?.disabled,
|
|
121
123
|
expanded: ariaExpanded ?? accessibilityState?.expanded,
|
|
122
124
|
selected: ariaSelected ?? accessibilityState?.selected,
|
|
125
|
+
readOnly: ariaReadOnly ?? accessibilityState?.readOnly, // Windows
|
|
123
126
|
multiselectable:
|
|
124
127
|
ariaMultiselectable ?? accessibilityState?.multiselectable, // Windows
|
|
125
128
|
required: ariaRequired ?? accessibilityState?.required, // Windows
|
|
@@ -183,14 +183,19 @@ export interface AccessibilityState {
|
|
|
183
183
|
* When present, informs accessible tools the element is expanded or collapsed
|
|
184
184
|
*/
|
|
185
185
|
expanded?: boolean | undefined;
|
|
186
|
+
/**
|
|
187
|
+
* When present, informs accessible tools the element is read only
|
|
188
|
+
* @platform windows
|
|
189
|
+
*/
|
|
190
|
+
readOnly?: boolean | undefined;
|
|
186
191
|
/**
|
|
187
192
|
* When present, informs accessible tools the element can have multiple items selected
|
|
188
|
-
*
|
|
193
|
+
* @platform windows
|
|
189
194
|
*/
|
|
190
195
|
multiselectable?: boolean | undefined;
|
|
191
196
|
/**
|
|
192
197
|
* When present, informs accessible tools the element requires selection
|
|
193
|
-
*
|
|
198
|
+
* @platform windows
|
|
194
199
|
*/
|
|
195
200
|
required?: boolean | undefined;
|
|
196
201
|
}
|
|
@@ -620,6 +620,7 @@ export type ViewProps = $ReadOnly<{|
|
|
|
620
620
|
'aria-disabled'?: ?boolean,
|
|
621
621
|
'aria-expanded'?: ?boolean,
|
|
622
622
|
'aria-selected'?: ?boolean,
|
|
623
|
+
'aria-readonly'?: ?boolean, // Windows
|
|
623
624
|
/** A value indicating whether the accessibility elements contained within
|
|
624
625
|
* this accessibility element are hidden.
|
|
625
626
|
*
|
|
@@ -42,9 +42,8 @@ if (__DEV__) {
|
|
|
42
42
|
if (!Platform.isTesting) {
|
|
43
43
|
const HMRClient = require('../Utilities/HMRClient');
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} else if (console._isPolyfilled) {
|
|
45
|
+
// TODO(T214991636): Remove legacy Metro log forwarding
|
|
46
|
+
if (console._isPolyfilled) {
|
|
48
47
|
// We assume full control over the console and send JavaScript logs to Metro.
|
|
49
48
|
[
|
|
50
49
|
'trace',
|
|
@@ -147,6 +147,7 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => {
|
|
|
147
147
|
'aria-disabled': ariaDisabled,
|
|
148
148
|
'aria-expanded': ariaExpanded,
|
|
149
149
|
'aria-selected': ariaSelected,
|
|
150
|
+
'aria-readonly': ariaReadOnly, // Windows
|
|
150
151
|
'aria-multiselectable': ariaMultiselectable, // Windows
|
|
151
152
|
'aria-required': ariaRequired, // Windows
|
|
152
153
|
height,
|
|
@@ -160,6 +161,7 @@ let BaseImage: AbstractImageIOS = React.forwardRef((props, forwardedRef) => {
|
|
|
160
161
|
disabled: ariaDisabled ?? props.accessibilityState?.disabled,
|
|
161
162
|
expanded: ariaExpanded ?? props.accessibilityState?.expanded,
|
|
162
163
|
selected: ariaSelected ?? props.accessibilityState?.selected,
|
|
164
|
+
readOnly: ariaReadOnly ?? props.accessibilityState?.readOnly, // Windows
|
|
163
165
|
multiselectable:
|
|
164
166
|
ariaMultiselectable ?? props.accessibilityState?.multiselectable, // Windows
|
|
165
167
|
required: ariaRequired ?? props.accessibilityState?.required, // Windows
|
|
@@ -60,6 +60,7 @@ const Text: component(
|
|
|
60
60
|
'aria-posinset': ariaPosinset, // Windows
|
|
61
61
|
'aria-setsize': ariaSetsize, // Windows
|
|
62
62
|
'aria-selected': ariaSelected,
|
|
63
|
+
'aria-readonly': ariaReadOnly, //Windows
|
|
63
64
|
children,
|
|
64
65
|
ellipsizeMode,
|
|
65
66
|
disabled,
|
|
@@ -98,6 +99,7 @@ const Text: component(
|
|
|
98
99
|
ariaDisabled != null ||
|
|
99
100
|
ariaExpanded != null ||
|
|
100
101
|
ariaSelected != null ||
|
|
102
|
+
ariaReadOnly != null || // Windows
|
|
101
103
|
ariaMultiselectable != null || // Windows
|
|
102
104
|
ariaRequired != null // Windows
|
|
103
105
|
) {
|
|
@@ -108,6 +110,7 @@ const Text: component(
|
|
|
108
110
|
disabled: ariaDisabled ?? _accessibilityState.disabled,
|
|
109
111
|
expanded: ariaExpanded ?? _accessibilityState.expanded,
|
|
110
112
|
selected: ariaSelected ?? _accessibilityState.selected,
|
|
113
|
+
readOnly: ariaReadOnly ?? _accessibilityState.readOnly, // Windows
|
|
111
114
|
multiselectable:
|
|
112
115
|
ariaMultiselectable ?? _accessibilityState.multiselectable, // Windows
|
|
113
116
|
required: ariaRequired ?? _accessibilityState.required, // Windows
|
|
@@ -119,6 +122,7 @@ const Text: component(
|
|
|
119
122
|
disabled: ariaDisabled,
|
|
120
123
|
expanded: ariaExpanded,
|
|
121
124
|
selected: ariaSelected,
|
|
125
|
+
readOnly: ariaReadOnly, // Windows
|
|
122
126
|
multiselectable: ariaMultiselectable, // Windows
|
|
123
127
|
required: ariaRequired, // Windows
|
|
124
128
|
};
|
|
@@ -97,6 +97,7 @@ export type TextProps = $ReadOnly<{
|
|
|
97
97
|
'aria-posinset'?: ?number, // Windows
|
|
98
98
|
'aria-setsize'?: ?number, // Windows
|
|
99
99
|
'aria-level'?: ?number, // Windows
|
|
100
|
+
'aria-readonly'?: ?boolean, // Windows
|
|
100
101
|
'aria-multiselectable'?: ?boolean, // Windows
|
|
101
102
|
'aria-required'?: ?boolean, // Windows
|
|
102
103
|
|
|
@@ -26,7 +26,6 @@ let hmrUnavailableReason: string | null = null;
|
|
|
26
26
|
let currentCompileErrorMessage: string | null = null;
|
|
27
27
|
let didConnect: boolean = false;
|
|
28
28
|
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
|
29
|
-
let pendingFuseboxConsoleNotification = false;
|
|
30
29
|
|
|
31
30
|
type LogLevel =
|
|
32
31
|
| 'trace'
|
|
@@ -52,7 +51,6 @@ export type HMRClientNativeInterface = {|
|
|
|
52
51
|
isEnabled: boolean,
|
|
53
52
|
scheme?: string,
|
|
54
53
|
): void,
|
|
55
|
-
unstable_notifyFuseboxConsoleEnabled(): void,
|
|
56
54
|
|};
|
|
57
55
|
|
|
58
56
|
/**
|
|
@@ -142,29 +140,6 @@ const HMRClient: HMRClientNativeInterface = {
|
|
|
142
140
|
}
|
|
143
141
|
},
|
|
144
142
|
|
|
145
|
-
unstable_notifyFuseboxConsoleEnabled() {
|
|
146
|
-
if (!hmrClient) {
|
|
147
|
-
pendingFuseboxConsoleNotification = true;
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
hmrClient.send(
|
|
151
|
-
JSON.stringify({
|
|
152
|
-
type: 'log',
|
|
153
|
-
level: 'info',
|
|
154
|
-
data: [
|
|
155
|
-
'\n' +
|
|
156
|
-
'\u001B[7m' +
|
|
157
|
-
' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
|
|
158
|
-
'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
|
|
159
|
-
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
|
|
160
|
-
'\u001B[27m' +
|
|
161
|
-
'\n',
|
|
162
|
-
],
|
|
163
|
-
}),
|
|
164
|
-
);
|
|
165
|
-
pendingFuseboxConsoleNotification = false;
|
|
166
|
-
},
|
|
167
|
-
|
|
168
143
|
// Called once by the bridge on startup, even if Fast Refresh is off.
|
|
169
144
|
// It creates the HMR client but doesn't actually set up the socket yet.
|
|
170
145
|
setup(
|
|
@@ -341,9 +316,6 @@ function flushEarlyLogs(client: MetroHMRClient) {
|
|
|
341
316
|
pendingLogs.forEach(([level, data]) => {
|
|
342
317
|
HMRClient.log(level, data);
|
|
343
318
|
});
|
|
344
|
-
if (pendingFuseboxConsoleNotification) {
|
|
345
|
-
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
|
346
|
-
}
|
|
347
319
|
} finally {
|
|
348
320
|
pendingLogs.length = 0;
|
|
349
321
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#include "pch.h"
|
|
2
2
|
#include "CompositionDynamicAutomationProvider.h"
|
|
3
3
|
#include <Fabric/ComponentView.h>
|
|
4
|
+
#include <Fabric/Composition/CompositionTextRangeProvider.h>
|
|
5
|
+
#include <Fabric/Composition/ParagraphComponentView.h>
|
|
4
6
|
#include <Fabric/Composition/SwitchComponentView.h>
|
|
5
7
|
#include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
|
|
6
8
|
#include <Unicode.h>
|
|
@@ -25,6 +27,13 @@ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
|
|
|
25
27
|
if (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value()) {
|
|
26
28
|
AddSelectionItemsToContainer(this);
|
|
27
29
|
}
|
|
30
|
+
|
|
31
|
+
if (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
|
|
32
|
+
strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>()) {
|
|
33
|
+
m_textProvider = winrt::make<CompositionTextProvider>(
|
|
34
|
+
strongView.as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), this)
|
|
35
|
+
.try_as<ITextProvider2>();
|
|
36
|
+
}
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
|
|
@@ -141,8 +150,12 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_ProviderOptions(Prov
|
|
|
141
150
|
return S_OK;
|
|
142
151
|
}
|
|
143
152
|
|
|
144
|
-
bool
|
|
145
|
-
return
|
|
153
|
+
bool accessibilityValueHasTextValue(const facebook::react::AccessibilityValue &value) {
|
|
154
|
+
return value.text.has_value();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
bool accessibilityValueHasNumericValue(const facebook::react::AccessibilityValue &value) {
|
|
158
|
+
return (value.min.has_value() && value.max.has_value() && value.now.has_value());
|
|
146
159
|
}
|
|
147
160
|
|
|
148
161
|
bool expandableControl(const facebook::react::SharedViewProps props) {
|
|
@@ -203,8 +216,15 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
|
|
|
203
216
|
}
|
|
204
217
|
|
|
205
218
|
if (patternId == UIA_ValuePatternId &&
|
|
206
|
-
(strongView
|
|
207
|
-
|
|
219
|
+
((strongView
|
|
220
|
+
.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() &&
|
|
221
|
+
!accessibilityValueHasNumericValue(props->accessibilityValue)) ||
|
|
222
|
+
accessibilityValueHasTextValue(props->accessibilityValue))) {
|
|
223
|
+
*pRetVal = static_cast<IValueProvider *>(this);
|
|
224
|
+
AddRef();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (patternId == UIA_RangeValuePatternId && accessibilityValueHasNumericValue(props->accessibilityValue)) {
|
|
208
228
|
*pRetVal = static_cast<IValueProvider *>(this);
|
|
209
229
|
AddRef();
|
|
210
230
|
}
|
|
@@ -233,10 +253,21 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
|
|
|
233
253
|
AddRef();
|
|
234
254
|
}
|
|
235
255
|
|
|
256
|
+
if (patternId == UIA_TextPatternId &&
|
|
257
|
+
(strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
|
|
258
|
+
strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>())) {
|
|
259
|
+
m_textProvider.as<IUnknown>().copy_to(pRetVal);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (patternId == UIA_TextPattern2Id &&
|
|
263
|
+
strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>()) {
|
|
264
|
+
m_textProvider.as<IUnknown>().copy_to(pRetVal);
|
|
265
|
+
}
|
|
266
|
+
|
|
236
267
|
return S_OK;
|
|
237
268
|
}
|
|
238
269
|
|
|
239
|
-
long
|
|
270
|
+
long GetControlTypeFromString(const std::string &role) noexcept {
|
|
240
271
|
if (role == "adjustable") {
|
|
241
272
|
return UIA_SliderControlTypeId;
|
|
242
273
|
} else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
|
|
@@ -299,6 +330,96 @@ long GetControlType(const std::string &role) noexcept {
|
|
|
299
330
|
return UIA_GroupControlTypeId;
|
|
300
331
|
}
|
|
301
332
|
|
|
333
|
+
long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
|
|
334
|
+
switch (role) {
|
|
335
|
+
case facebook::react::Role::Alert:
|
|
336
|
+
return UIA_TextControlTypeId;
|
|
337
|
+
case facebook::react::Role::Application:
|
|
338
|
+
return UIA_WindowControlTypeId;
|
|
339
|
+
case facebook::react::Role::Button:
|
|
340
|
+
return UIA_ButtonControlTypeId;
|
|
341
|
+
case facebook::react::Role::Checkbox:
|
|
342
|
+
return UIA_CheckBoxControlTypeId;
|
|
343
|
+
case facebook::react::Role::Columnheader:
|
|
344
|
+
return UIA_HeaderControlTypeId;
|
|
345
|
+
case facebook::react::Role::Combobox:
|
|
346
|
+
return UIA_ComboBoxControlTypeId;
|
|
347
|
+
case facebook::react::Role::Document:
|
|
348
|
+
return UIA_DocumentControlTypeId;
|
|
349
|
+
case facebook::react::Role::Grid:
|
|
350
|
+
return UIA_GroupControlTypeId;
|
|
351
|
+
case facebook::react::Role::Group:
|
|
352
|
+
return UIA_GroupControlTypeId;
|
|
353
|
+
case facebook::react::Role::Heading:
|
|
354
|
+
return UIA_TextControlTypeId;
|
|
355
|
+
case facebook::react::Role::Img:
|
|
356
|
+
return UIA_ImageControlTypeId;
|
|
357
|
+
case facebook::react::Role::Link:
|
|
358
|
+
return UIA_HyperlinkControlTypeId;
|
|
359
|
+
case facebook::react::Role::List:
|
|
360
|
+
return UIA_ListControlTypeId;
|
|
361
|
+
case facebook::react::Role::Listitem:
|
|
362
|
+
return UIA_ListItemControlTypeId;
|
|
363
|
+
case facebook::react::Role::Menu:
|
|
364
|
+
return UIA_MenuControlTypeId;
|
|
365
|
+
case facebook::react::Role::Menubar:
|
|
366
|
+
return UIA_MenuBarControlTypeId;
|
|
367
|
+
case facebook::react::Role::Menuitem:
|
|
368
|
+
return UIA_MenuItemControlTypeId;
|
|
369
|
+
case facebook::react::Role::None:
|
|
370
|
+
return UIA_GroupControlTypeId;
|
|
371
|
+
case facebook::react::Role::Presentation:
|
|
372
|
+
return UIA_GroupControlTypeId;
|
|
373
|
+
case facebook::react::Role::Progressbar:
|
|
374
|
+
return UIA_ProgressBarControlTypeId;
|
|
375
|
+
case facebook::react::Role::Radio:
|
|
376
|
+
return UIA_RadioButtonControlTypeId;
|
|
377
|
+
case facebook::react::Role::Radiogroup:
|
|
378
|
+
return UIA_GroupControlTypeId;
|
|
379
|
+
case facebook::react::Role::Rowgroup:
|
|
380
|
+
return UIA_GroupControlTypeId;
|
|
381
|
+
case facebook::react::Role::Rowheader:
|
|
382
|
+
return UIA_HeaderControlTypeId;
|
|
383
|
+
case facebook::react::Role::Scrollbar:
|
|
384
|
+
return UIA_ScrollBarControlTypeId;
|
|
385
|
+
case facebook::react::Role::Searchbox:
|
|
386
|
+
return UIA_EditControlTypeId;
|
|
387
|
+
case facebook::react::Role::Separator:
|
|
388
|
+
return UIA_SeparatorControlTypeId;
|
|
389
|
+
case facebook::react::Role::Slider:
|
|
390
|
+
return UIA_SliderControlTypeId;
|
|
391
|
+
case facebook::react::Role::Spinbutton:
|
|
392
|
+
return UIA_SpinnerControlTypeId;
|
|
393
|
+
case facebook::react::Role::Status:
|
|
394
|
+
return UIA_StatusBarControlTypeId;
|
|
395
|
+
case facebook::react::Role::Summary:
|
|
396
|
+
return UIA_GroupControlTypeId;
|
|
397
|
+
case facebook::react::Role::Switch:
|
|
398
|
+
return UIA_ButtonControlTypeId;
|
|
399
|
+
case facebook::react::Role::Tab:
|
|
400
|
+
return UIA_TabItemControlTypeId;
|
|
401
|
+
case facebook::react::Role::Table:
|
|
402
|
+
return UIA_TableControlTypeId;
|
|
403
|
+
case facebook::react::Role::Tablist:
|
|
404
|
+
return UIA_TabControlTypeId;
|
|
405
|
+
case facebook::react::Role::Tabpanel:
|
|
406
|
+
return UIA_TabControlTypeId;
|
|
407
|
+
case facebook::react::Role::Timer:
|
|
408
|
+
return UIA_ButtonControlTypeId;
|
|
409
|
+
case facebook::react::Role::Toolbar:
|
|
410
|
+
return UIA_ToolBarControlTypeId;
|
|
411
|
+
case facebook::react::Role::Tooltip:
|
|
412
|
+
return UIA_ToolTipControlTypeId;
|
|
413
|
+
case facebook::react::Role::Tree:
|
|
414
|
+
return UIA_TreeControlTypeId;
|
|
415
|
+
case facebook::react::Role::Treegrid:
|
|
416
|
+
return UIA_TreeControlTypeId;
|
|
417
|
+
case facebook::react::Role::Treeitem:
|
|
418
|
+
return UIA_TreeItemControlTypeId;
|
|
419
|
+
}
|
|
420
|
+
return UIA_GroupControlTypeId;
|
|
421
|
+
}
|
|
422
|
+
|
|
302
423
|
HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
|
|
303
424
|
if (pRetVal == nullptr)
|
|
304
425
|
return E_POINTER;
|
|
@@ -324,8 +445,10 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
|
|
|
324
445
|
switch (propertyId) {
|
|
325
446
|
case UIA_ControlTypePropertyId: {
|
|
326
447
|
pRetVal->vt = VT_I4;
|
|
327
|
-
|
|
328
|
-
|
|
448
|
+
pRetVal->lVal = props->role == facebook::react::Role::None ? props->accessibilityRole.empty()
|
|
449
|
+
? GetControlTypeFromString(compositionView->DefaultControlType())
|
|
450
|
+
: GetControlTypeFromString(props->accessibilityRole)
|
|
451
|
+
: GetControlTypeFromRole(props->role);
|
|
329
452
|
break;
|
|
330
453
|
}
|
|
331
454
|
case UIA_AutomationIdPropertyId: {
|
|
@@ -365,12 +488,18 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
|
|
|
365
488
|
}
|
|
366
489
|
case UIA_IsContentElementPropertyId: {
|
|
367
490
|
pRetVal->vt = VT_BOOL;
|
|
368
|
-
pRetVal->boolVal =
|
|
491
|
+
pRetVal->boolVal =
|
|
492
|
+
(props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
|
|
493
|
+
? VARIANT_TRUE
|
|
494
|
+
: VARIANT_FALSE;
|
|
369
495
|
break;
|
|
370
496
|
}
|
|
371
497
|
case UIA_IsControlElementPropertyId: {
|
|
372
498
|
pRetVal->vt = VT_BOOL;
|
|
373
|
-
pRetVal->boolVal =
|
|
499
|
+
pRetVal->boolVal =
|
|
500
|
+
(props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
|
|
501
|
+
? VARIANT_TRUE
|
|
502
|
+
: VARIANT_FALSE;
|
|
374
503
|
break;
|
|
375
504
|
}
|
|
376
505
|
case UIA_IsOffscreenPropertyId: {
|
|
@@ -485,6 +614,8 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(LPCWSTR val) {
|
|
|
485
614
|
|
|
486
615
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
|
|
487
616
|
->setAcccessiblityValue(winrt::to_string(val));
|
|
617
|
+
// TODO: Edit once/if onAccessibilityAction props supports returning UIA event data. See
|
|
618
|
+
// https://github.com/react-native-community/discussions-and-proposals/issues/843.
|
|
488
619
|
DispatchAccessibilityAction(m_view, "setValue");
|
|
489
620
|
return S_OK;
|
|
490
621
|
}
|
|
@@ -515,23 +646,86 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe
|
|
|
515
646
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
|
|
516
647
|
if (props == nullptr)
|
|
517
648
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
// Control is using default control type. Use default IsReadOnly value.
|
|
521
|
-
*pRetVal = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
|
|
522
|
-
->getAcccessiblityIsReadOnly();
|
|
523
|
-
} else if (
|
|
524
|
-
accessibilityRole == "textinput" || accessibilityRole == "searchbox" || accessibilityRole == "adjustable" ||
|
|
525
|
-
accessibilityRole == "spinbutton" || accessibilityRole == "combobox") {
|
|
526
|
-
// Control is using customized control type which should not be IsReadOnly for value pattern.
|
|
527
|
-
*pRetVal = false;
|
|
649
|
+
if (props->accessibilityState.has_value() && props->accessibilityState->readOnly.has_value()) {
|
|
650
|
+
*pRetVal = props->accessibilityState->readOnly.value();
|
|
528
651
|
} else {
|
|
529
|
-
//
|
|
530
|
-
*pRetVal =
|
|
652
|
+
// Use default IsReadOnly value.
|
|
653
|
+
*pRetVal = false;
|
|
531
654
|
}
|
|
532
655
|
return S_OK;
|
|
533
656
|
}
|
|
534
657
|
|
|
658
|
+
HRESULT __stdcall CompositionDynamicAutomationProvider::get_LargeChange(double *pRetVal) {
|
|
659
|
+
// no-op
|
|
660
|
+
return S_OK;
|
|
661
|
+
}
|
|
662
|
+
HRESULT __stdcall CompositionDynamicAutomationProvider::get_Maximum(double *pRetVal) {
|
|
663
|
+
if (pRetVal == nullptr)
|
|
664
|
+
return E_POINTER;
|
|
665
|
+
auto strongView = m_view.view();
|
|
666
|
+
|
|
667
|
+
if (!strongView)
|
|
668
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
669
|
+
|
|
670
|
+
auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
|
|
671
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
|
|
672
|
+
|
|
673
|
+
if (props == nullptr)
|
|
674
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
675
|
+
|
|
676
|
+
*pRetVal = props->accessibilityValue.max.value();
|
|
677
|
+
return S_OK;
|
|
678
|
+
}
|
|
679
|
+
HRESULT __stdcall CompositionDynamicAutomationProvider::get_Minimum(double *pRetVal) {
|
|
680
|
+
if (pRetVal == nullptr)
|
|
681
|
+
return E_POINTER;
|
|
682
|
+
auto strongView = m_view.view();
|
|
683
|
+
|
|
684
|
+
if (!strongView)
|
|
685
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
686
|
+
|
|
687
|
+
auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
|
|
688
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
|
|
689
|
+
|
|
690
|
+
if (props == nullptr)
|
|
691
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
692
|
+
|
|
693
|
+
*pRetVal = props->accessibilityValue.min.value();
|
|
694
|
+
return S_OK;
|
|
695
|
+
}
|
|
696
|
+
HRESULT __stdcall CompositionDynamicAutomationProvider::get_SmallChange(double *pRetVal) {
|
|
697
|
+
// no-op
|
|
698
|
+
return S_OK;
|
|
699
|
+
}
|
|
700
|
+
HRESULT __stdcall CompositionDynamicAutomationProvider::get_Value(double *pRetVal) {
|
|
701
|
+
if (pRetVal == nullptr)
|
|
702
|
+
return E_POINTER;
|
|
703
|
+
auto strongView = m_view.view();
|
|
704
|
+
|
|
705
|
+
if (!strongView)
|
|
706
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
707
|
+
|
|
708
|
+
auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
|
|
709
|
+
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
|
|
710
|
+
|
|
711
|
+
if (props == nullptr)
|
|
712
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
713
|
+
|
|
714
|
+
*pRetVal = props->accessibilityValue.now.value();
|
|
715
|
+
return S_OK;
|
|
716
|
+
}
|
|
717
|
+
HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(double val) {
|
|
718
|
+
auto strongView = m_view.view();
|
|
719
|
+
|
|
720
|
+
if (!strongView)
|
|
721
|
+
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
722
|
+
|
|
723
|
+
// TODO: Edit once/if onAccessibilityAction props supports returning UIA event data. See
|
|
724
|
+
// https://github.com/react-native-community/discussions-and-proposals/issues/843.
|
|
725
|
+
DispatchAccessibilityAction(m_view, "setValue");
|
|
726
|
+
return S_OK;
|
|
727
|
+
}
|
|
728
|
+
|
|
535
729
|
HRESULT __stdcall CompositionDynamicAutomationProvider::get_ToggleState(ToggleState *pRetVal) {
|
|
536
730
|
if (pRetVal == nullptr)
|
|
537
731
|
return E_POINTER;
|