Skip to content

Commit 7b7c004

Browse files
HariniMalothu17Harini Malothu
andauthored
[Fabric] Implement the onPressOut property for the fabric implementation of TextInput (#14784)
* Introduced OnPressOut in EventEmitter files * Change files * Fixed tester files * Updated OnPressIn and OnPressOut test files * Lint fix * Fixed lint issues and updates snapshots --------- Co-authored-by: Harini Malothu <[email protected]>
1 parent 34c7dc8 commit 7b7c004

File tree

11 files changed

+258
-34
lines changed

11 files changed

+258
-34
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Implement the onPressOut property for the fabric implementation of TextInput",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,36 @@ class PressInOutEvents extends React.Component<
7878
> {
7979
constructor(props) {
8080
super(props);
81-
this.state = {text: 'PressIn/PressOut message'};
81+
this.state = {
82+
OnpressInText: 'OnPressIn message',
83+
OnpressOutText: 'OnPressOut message',
84+
};
8285
}
8386

8487
render() {
8588
return (
8689
<View>
87-
<Text testID="textinput-state-display">{this.state.text}</Text>
90+
<Text testID="textinput-state-display-in">
91+
{this.state.OnpressInText}
92+
</Text>
93+
<Text testID="textinput-state-display-out">
94+
{this.state.OnpressOutText}
95+
</Text>
8896
<ExampleTextInput
89-
placeholder="Click inside the box to observe events being fired."
97+
placeholder="OnPressIn test."
9098
style={[styles.singleLineWithHeightTextInput]}
9199
onPressIn={() => {
92-
this.setState({text: 'Holding down the click/touch'});
100+
this.setState({OnpressInText: 'Holding down the click/touch'});
101+
}}
102+
testID="textinput-pressin"
103+
/>
104+
<ExampleTextInput
105+
placeholder="OnPressOut test."
106+
style={[styles.singleLineWithHeightTextInput]}
107+
onPressOut={() => {
108+
this.setState({OnpressOutText: 'Released click/touch'});
93109
}}
94-
onPressOut={() => this.setState({text: 'Released click/touch'})}
95-
testID="textinput-press"
110+
testID="textinput-pressout"
96111
/>
97112
</View>
98113
);

packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,16 @@ describe('TextInput Tests', () => {
197197
test('TextInput triggers onPressIn and updates state text', async () => {
198198
// Scroll the example into view
199199
await searchBox('onPressIn');
200-
const component = await app.findElementByTestID('textinput-press');
200+
const component = await app.findElementByTestID('textinput-pressin');
201201
await component.waitForDisplayed({timeout: 5000});
202-
const dump = await dumpVisualTree('textinput-press');
202+
const dump = await dumpVisualTree('textinput-pressin');
203203
expect(dump).toMatchSnapshot();
204204

205205
// Trigger onPressIn (click only)
206206
await component.click();
207-
const stateText = await app.findElementByTestID('textinput-state-display');
207+
const stateText = await app.findElementByTestID(
208+
'textinput-state-display-in',
209+
);
208210

209211
await app.waitUntil(
210212
async () => {
@@ -222,6 +224,39 @@ describe('TextInput Tests', () => {
222224
const search = await app.findElementByTestID('example_search');
223225
await search.setValue('');
224226
});
227+
test('TextInput triggers onPressOut and updates state text', async () => {
228+
// Scroll the example into view
229+
await searchBox('onPressOut');
230+
const component = await app.findElementByTestID('textinput-pressout');
231+
await component.waitForDisplayed({timeout: 5000});
232+
const dump = await dumpVisualTree('textinput-pressout');
233+
expect(dump).toMatchSnapshot();
234+
235+
// Trigger onPressOut followed by onPressOut (using touchAction for press and release)
236+
await component.click();
237+
const stateText = await app.findElementByTestID(
238+
'textinput-state-display-out',
239+
);
240+
241+
// Wait for onPressOut to update the state text
242+
await app.waitUntil(
243+
async () => {
244+
const currentText = await stateText.getText();
245+
return currentText === 'Released click/touch';
246+
},
247+
{
248+
timeout: 5000,
249+
timeoutMsg: 'State text not updated after onPressOut.',
250+
},
251+
);
252+
253+
// Assertion
254+
expect(await stateText.getText()).toBe('Released click/touch');
255+
256+
// Clean up by unfocusing the input
257+
const search = await app.findElementByTestID('example_search');
258+
await search.setValue('');
259+
});
225260
test('TextInputs can have attributed text', async () => {
226261
const component = await app.findElementByTestID('text-input');
227262
await component.waitForDisplayed({timeout: 5000});
@@ -890,9 +925,9 @@ describe('TextInput Tests', () => {
890925
expect(dump).toMatchSnapshot();
891926
});
892927
test('TextInputs can register press events', async () => {
893-
const component = await app.findElementByTestID('textinput-press');
928+
const component = await app.findElementByTestID('textinput-pressin');
894929
await component.waitForDisplayed({timeout: 5000});
895-
const dump = await dumpVisualTree('textinput-press');
930+
const dump = await dumpVisualTree('textinput-pressin');
896931
expect(dump).toMatchSnapshot();
897932
});
898933
test('TextInputs can autogrow', async () => {

packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -394,22 +394,100 @@ exports[`TextInput Tests Text have cursorColor 1`] = `
394394
exports[`TextInput Tests TextInput triggers onPressIn and updates state text 1`] = `
395395
{
396396
"Automation Tree": {
397-
"AutomationId": "textinput-press",
397+
"AutomationId": "textinput-pressin",
398398
"ControlType": 50004,
399-
"HelpText": "Click inside the box to observe events being fired.",
399+
"HelpText": "OnPressIn test.",
400400
"IsKeyboardFocusable": true,
401401
"LocalizedControlType": "edit",
402-
"Name": "Click inside the box to observe events being fired.",
403-
"TextRangePattern.GetText": "Click inside the box to observe events being fired.",
402+
"Name": "OnPressIn test.",
403+
"TextRangePattern.GetText": "OnPressIn test.",
404404
},
405405
"Component Tree": {
406406
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
407407
"_Props": {
408-
"TestId": "textinput-press",
408+
"TestId": "textinput-pressin",
409409
},
410410
},
411411
"Visual Tree": {
412-
"Comment": "textinput-press",
412+
"Comment": "textinput-pressin",
413+
"Offset": "0, 0, 0",
414+
"Size": "916, 30",
415+
"Visual Type": "SpriteVisual",
416+
"__Children": [
417+
{
418+
"Offset": "0, 0, 0",
419+
"Size": "1, 1",
420+
"Visual Type": "SpriteVisual",
421+
},
422+
{
423+
"Offset": "1, 0, 0",
424+
"Size": "-2, 1",
425+
"Visual Type": "SpriteVisual",
426+
},
427+
{
428+
"Offset": "-1, 0, 0",
429+
"Size": "1, 1",
430+
"Visual Type": "SpriteVisual",
431+
},
432+
{
433+
"Offset": "-1, 1, 0",
434+
"Size": "1, -2",
435+
"Visual Type": "SpriteVisual",
436+
},
437+
{
438+
"Offset": "-1, -1, 0",
439+
"Size": "1, 1",
440+
"Visual Type": "SpriteVisual",
441+
},
442+
{
443+
"Offset": "1, -1, 0",
444+
"Size": "-2, 1",
445+
"Visual Type": "SpriteVisual",
446+
},
447+
{
448+
"Offset": "0, -1, 0",
449+
"Size": "1, 1",
450+
"Visual Type": "SpriteVisual",
451+
},
452+
{
453+
"Offset": "0, 1, 0",
454+
"Size": "1, -2",
455+
"Visual Type": "SpriteVisual",
456+
},
457+
{
458+
"Brush": {
459+
"Brush Type": "ColorBrush",
460+
"Color": "rgba(0, 0, 0, 255)",
461+
},
462+
"Offset": "0, 0, 0",
463+
"Opacity": 0,
464+
"Size": "0, 0",
465+
"Visual Type": "SpriteVisual",
466+
},
467+
],
468+
},
469+
}
470+
`;
471+
472+
exports[`TextInput Tests TextInput triggers onPressOut and updates state text 1`] = `
473+
{
474+
"Automation Tree": {
475+
"AutomationId": "textinput-pressout",
476+
"ControlType": 50004,
477+
"HelpText": "OnPressOut test.",
478+
"IsKeyboardFocusable": true,
479+
"LocalizedControlType": "edit",
480+
"Name": "OnPressOut test.",
481+
"TextRangePattern.GetText": "OnPressOut test.",
482+
},
483+
"Component Tree": {
484+
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
485+
"_Props": {
486+
"TestId": "textinput-pressout",
487+
},
488+
},
489+
"Visual Tree": {
490+
"Comment": "textinput-pressout",
413491
"Offset": "0, 0, 0",
414492
"Size": "916, 30",
415493
"Visual Type": "SpriteVisual",
@@ -1080,12 +1158,12 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP
10801158
"__Children": [
10811159
{
10821160
"Offset": "0, 0, 0",
1083-
"Size": "916, 32",
1161+
"Size": "916, 33",
10841162
"Visual Type": "SpriteVisual",
10851163
"__Children": [
10861164
{
10871165
"Offset": "0, 0, 0",
1088-
"Size": "916, 32",
1166+
"Size": "916, 33",
10891167
"Visual Type": "SpriteVisual",
10901168
"__Children": [
10911169
{
@@ -1758,7 +1836,7 @@ exports[`TextInput Tests TextInputs can clear on submit 1`] = `
17581836
"Visual Tree": {
17591837
"Comment": "textinput-clear-on-submit",
17601838
"Offset": "0, 0, 0",
1761-
"Size": "916, 32",
1839+
"Size": "916, 33",
17621840
"Visual Type": "SpriteVisual",
17631841
"__Children": [
17641842
{
@@ -2679,7 +2757,7 @@ exports[`TextInput Tests TextInputs can have caretHidden 1`] = `
26792757
"Visual Tree": {
26802758
"Comment": "textinput-carethidden",
26812759
"Offset": "0, 0, 0",
2682-
"Size": "916, 32",
2760+
"Size": "916, 33",
26832761
"Visual Type": "SpriteVisual",
26842762
"__Children": [
26852763
{
@@ -4255,7 +4333,7 @@ exports[`TextInput Tests TextInputs can have shadows 1`] = `
42554333
"Visual Tree": {
42564334
"Comment": "textinput-shadow",
42574335
"Offset": "0, 0, 0",
4258-
"Size": "916, 33",
4336+
"Size": "916, 32",
42594337
"Visual Type": "SpriteVisual",
42604338
"__Children": [
42614339
{
@@ -4548,22 +4626,22 @@ exports[`TextInput Tests TextInputs can propagate events 1`] = `
45484626
exports[`TextInput Tests TextInputs can register press events 1`] = `
45494627
{
45504628
"Automation Tree": {
4551-
"AutomationId": "textinput-press",
4629+
"AutomationId": "textinput-pressin",
45524630
"ControlType": 50004,
4553-
"HelpText": "Click inside the box to observe events being fired.",
4631+
"HelpText": "OnPressIn test.",
45544632
"IsKeyboardFocusable": true,
45554633
"LocalizedControlType": "edit",
4556-
"Name": "Click inside the box to observe events being fired.",
4557-
"TextRangePattern.GetText": "Click inside the box to observe events being fired.",
4634+
"Name": "OnPressIn test.",
4635+
"TextRangePattern.GetText": "OnPressIn test.",
45584636
},
45594637
"Component Tree": {
45604638
"Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView",
45614639
"_Props": {
4562-
"TestId": "textinput-press",
4640+
"TestId": "textinput-pressin",
45634641
},
45644642
},
45654643
"Visual Tree": {
4566-
"Comment": "textinput-press",
4644+
"Comment": "textinput-pressin",
45674645
"Offset": "0, 0, 0",
45684646
"Size": "916, 30",
45694647
"Visual Type": "SpriteVisual",
@@ -5968,12 +6046,12 @@ exports[`TextInput Tests TextInputs which have a searchbox role should also supp
59686046
"__Children": [
59696047
{
59706048
"Offset": "0, 0, 0",
5971-
"Size": "916, 33",
6049+
"Size": "916, 32",
59726050
"Visual Type": "SpriteVisual",
59736051
"__Children": [
59746052
{
59756053
"Offset": "0, 0, 0",
5976-
"Size": "916, 33",
6054+
"Size": "916, 32",
59776055
"Visual Type": "SpriteVisual",
59786056
"__Children": [
59796057
{

packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80996,14 +80996,44 @@ exports[`snapshotAllPages TextInput 40`] = `
8099680996
exports[`snapshotAllPages TextInput 41`] = `
8099780997
<View>
8099880998
<Text
80999-
testID="textinput-state-display"
80999+
testID="textinput-state-display-in"
8100081000
>
81001-
PressIn/PressOut message
81001+
OnPressIn message
81002+
</Text>
81003+
<Text
81004+
testID="textinput-state-display-out"
81005+
>
81006+
OnPressOut message
8100281007
</Text>
8100381008
<TextInput
8100481009
onPressIn={[Function]}
81010+
placeholder="OnPressIn test."
81011+
style={
81012+
[
81013+
{
81014+
"backgroundColor": "#ffffffff",
81015+
"borderColor": "#3c3c432d",
81016+
"color": "#000000ff",
81017+
},
81018+
{
81019+
"borderWidth": 1,
81020+
"flexGrow": 1,
81021+
"flexShrink": 1,
81022+
"fontSize": 13,
81023+
"padding": 4,
81024+
},
81025+
[
81026+
{
81027+
"height": 30,
81028+
},
81029+
],
81030+
]
81031+
}
81032+
testID="textinput-pressin"
81033+
/>
81034+
<TextInput
8100581035
onPressOut={[Function]}
81006-
placeholder="Click inside the box to observe events being fired."
81036+
placeholder="OnPressOut test."
8100781037
style={
8100881038
[
8100981039
{
@@ -81025,7 +81055,7 @@ exports[`snapshotAllPages TextInput 41`] = `
8102581055
],
8102681056
]
8102781057
}
81028-
testID="textinput-press"
81058+
testID="textinput-pressout"
8102981059
/>
8103081060
</View>
8103181061
`;

packages/playground/Samples/textinput.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,13 @@ export default class Bootstrap extends React.Component<{}, any> {
258258
Alert.alert('Pressed!');
259259
}}
260260
/>
261+
<TextInput
262+
style={styles.input}
263+
placeholder="OnPressOut..."
264+
onPressOut={event => {
265+
Alert.alert('Released!');
266+
}}
267+
/>
261268
<TextInput
262269
placeholder="Single line with selection color"
263270
cursorColor="#00FF00"

0 commit comments

Comments
 (0)