From 4b324692e76864dcb001129d00de1c19b56fbfb9 Mon Sep 17 00:00:00 2001 From: i518532 Date: Wed, 13 Aug 2025 12:10:16 +0300 Subject: [PATCH 1/5] fix(ui5-textarea): escape interaction can now be prevented --- packages/main/cypress/specs/TextArea.cy.tsx | 38 +++++++++++++++++++++ packages/main/src/TextArea.ts | 18 +++++++--- packages/main/test/pages/TextArea.html | 11 ++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/packages/main/cypress/specs/TextArea.cy.tsx b/packages/main/cypress/specs/TextArea.cy.tsx index ecb931be9ddb..1f2b380987e0 100644 --- a/packages/main/cypress/specs/TextArea.cy.tsx +++ b/packages/main/cypress/specs/TextArea.cy.tsx @@ -533,6 +533,44 @@ describe("TextArea general interaction", () => { .should("have.value", ""); }); + it("Should allow preventing escape behavior by preventing the input event", () => { + cy.mount(); + + cy.get("[ui5-textarea]") + .as("textarea"); + + cy.get("@textarea") + .then(textarea => { + textarea.get(0).addEventListener("ui5-input", (event: CustomEvent) => { + if (event.detail && event.detail.inputType === "escapePressed") { + event.preventDefault(); + } + }); + }); + + cy.get("@textarea") + .realClick(); + + cy.get("@textarea") + .should("be.focused"); + + cy.get("@textarea") + .realType(" modified"); + + cy.get("@textarea") + .shadow() + .find("textarea") + .should("have.value", "initial value modified"); + + cy.get("@textarea") + .realPress("Escape"); + + cy.get("@textarea") + .shadow() + .find("textarea") + .should("have.value", "initial value modified"); + }); + it("Value state type should be added to the screen readers default value states announcement", () => { // Negative cy.mount(); diff --git a/packages/main/src/TextArea.ts b/packages/main/src/TextArea.ts index 614ff77f2eef..42c20511d276 100644 --- a/packages/main/src/TextArea.ts +++ b/packages/main/src/TextArea.ts @@ -48,6 +48,10 @@ type ExceededText = { calcedMaxLength?: number; }; +type TextAreaInputEventDetail = { + inputType?: string; +}; + /** * @class * @@ -101,6 +105,7 @@ type ExceededText = { */ @event("input", { bubbles: true, + cancelable: true, }) /** @@ -126,7 +131,7 @@ type ExceededText = { class TextArea extends UI5Element implements IFormInputElement { eventDetails!: { "change": void; - "input": void; + "input": TextAreaInputEventDetail; "select": void; "scroll": void; "value-changed": void; @@ -393,9 +398,14 @@ class TextArea extends UI5Element implements IFormInputElement { if (isEscape(e)) { const nativeTextArea = this.getInputDomRef(); - this.value = this.previousValue; - nativeTextArea.value = this.value; - this.fireDecoratorEvent("input"); + const prevented = !this.fireDecoratorEvent("input", { + inputType: "escapePressed", + }); + + if (!prevented) { + this.value = this.previousValue; + nativeTextArea.value = this.value; + } } } diff --git a/packages/main/test/pages/TextArea.html b/packages/main/test/pages/TextArea.html index d5bee0c0ec28..f7aaf7cf68a8 100644 --- a/packages/main/test/pages/TextArea.html +++ b/packages/main/test/pages/TextArea.html @@ -210,6 +210,11 @@ +
+ Text Area: Escape Prevention + +
+ From 5f521546c3f28b3bddbbe2d2345e0dc85d768814 Mon Sep 17 00:00:00 2001 From: i518532 Date: Wed, 13 Aug 2025 12:10:16 +0300 Subject: [PATCH 2/5] fix(ui5-textarea): escape interaction can now be prevented --- packages/main/cypress/specs/TextArea.cy.tsx | 38 +++++++++++++++++++++ packages/main/src/TextArea.ts | 18 +++++++--- packages/main/test/pages/TextArea.html | 11 ++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/packages/main/cypress/specs/TextArea.cy.tsx b/packages/main/cypress/specs/TextArea.cy.tsx index ecb931be9ddb..7a3f1c3e9880 100644 --- a/packages/main/cypress/specs/TextArea.cy.tsx +++ b/packages/main/cypress/specs/TextArea.cy.tsx @@ -533,6 +533,44 @@ describe("TextArea general interaction", () => { .should("have.value", ""); }); + it("Should allow preventing escape behavior by preventing the input event", () => { + cy.mount(); + + cy.get("[ui5-textarea]") + .as("textarea"); + + cy.get("@textarea") + .then(textarea => { + textarea.get(0).addEventListener("ui5-input", (event: CustomEvent) => { + if (event.detail && event.detail.escapePressed) { + event.preventDefault(); + } + }); + }); + + cy.get("@textarea") + .realClick(); + + cy.get("@textarea") + .should("be.focused"); + + cy.get("@textarea") + .realType(" modified"); + + cy.get("@textarea") + .shadow() + .find("textarea") + .should("have.value", "initial value modified"); + + cy.get("@textarea") + .realPress("Escape"); + + cy.get("@textarea") + .shadow() + .find("textarea") + .should("have.value", "initial value modified"); + }); + it("Value state type should be added to the screen readers default value states announcement", () => { // Negative cy.mount(); diff --git a/packages/main/src/TextArea.ts b/packages/main/src/TextArea.ts index 614ff77f2eef..5078c49ddec3 100644 --- a/packages/main/src/TextArea.ts +++ b/packages/main/src/TextArea.ts @@ -48,6 +48,10 @@ type ExceededText = { calcedMaxLength?: number; }; +type TextAreaInputEventDetail = { + escapePressed?: boolean; +}; + /** * @class * @@ -101,6 +105,7 @@ type ExceededText = { */ @event("input", { bubbles: true, + cancelable: true, }) /** @@ -126,7 +131,7 @@ type ExceededText = { class TextArea extends UI5Element implements IFormInputElement { eventDetails!: { "change": void; - "input": void; + "input": TextAreaInputEventDetail; "select": void; "scroll": void; "value-changed": void; @@ -393,9 +398,14 @@ class TextArea extends UI5Element implements IFormInputElement { if (isEscape(e)) { const nativeTextArea = this.getInputDomRef(); - this.value = this.previousValue; - nativeTextArea.value = this.value; - this.fireDecoratorEvent("input"); + const prevented = !this.fireDecoratorEvent("input", { + escapePressed: true, + }); + + if (!prevented) { + this.value = this.previousValue; + nativeTextArea.value = this.value; + } } } diff --git a/packages/main/test/pages/TextArea.html b/packages/main/test/pages/TextArea.html index d5bee0c0ec28..ca7b9c0f5f72 100644 --- a/packages/main/test/pages/TextArea.html +++ b/packages/main/test/pages/TextArea.html @@ -210,6 +210,11 @@ +
+ Text Area: Escape Prevention + +
+ From 26d0a535b29d7b8748454db462231e25e0bd775f Mon Sep 17 00:00:00 2001 From: i518532 Date: Wed, 13 Aug 2025 12:16:16 +0300 Subject: [PATCH 3/5] fix(ui5-textarea): escape interaction can now be prevented --- packages/main/cypress/specs/TextArea.cy.tsx | 4 ---- packages/main/src/TextArea.ts | 8 -------- packages/main/test/pages/TextArea.html | 4 ---- 3 files changed, 16 deletions(-) diff --git a/packages/main/cypress/specs/TextArea.cy.tsx b/packages/main/cypress/specs/TextArea.cy.tsx index 7e8d9df87a01..7a3f1c3e9880 100644 --- a/packages/main/cypress/specs/TextArea.cy.tsx +++ b/packages/main/cypress/specs/TextArea.cy.tsx @@ -542,11 +542,7 @@ describe("TextArea general interaction", () => { cy.get("@textarea") .then(textarea => { textarea.get(0).addEventListener("ui5-input", (event: CustomEvent) => { -<<<<<<< HEAD if (event.detail && event.detail.escapePressed) { -======= - if (event.detail && event.detail.inputType === "escapePressed") { ->>>>>>> 4b324692e76864dcb001129d00de1c19b56fbfb9 event.preventDefault(); } }); diff --git a/packages/main/src/TextArea.ts b/packages/main/src/TextArea.ts index 1290dd35e117..5078c49ddec3 100644 --- a/packages/main/src/TextArea.ts +++ b/packages/main/src/TextArea.ts @@ -49,11 +49,7 @@ type ExceededText = { }; type TextAreaInputEventDetail = { -<<<<<<< HEAD escapePressed?: boolean; -======= - inputType?: string; ->>>>>>> 4b324692e76864dcb001129d00de1c19b56fbfb9 }; /** @@ -403,11 +399,7 @@ class TextArea extends UI5Element implements IFormInputElement { const nativeTextArea = this.getInputDomRef(); const prevented = !this.fireDecoratorEvent("input", { -<<<<<<< HEAD escapePressed: true, -======= - inputType: "escapePressed", ->>>>>>> 4b324692e76864dcb001129d00de1c19b56fbfb9 }); if (!prevented) { diff --git a/packages/main/test/pages/TextArea.html b/packages/main/test/pages/TextArea.html index bbe35f334790..ca7b9c0f5f72 100644 --- a/packages/main/test/pages/TextArea.html +++ b/packages/main/test/pages/TextArea.html @@ -230,11 +230,7 @@ }); document.getElementById('textarea-prevent-escape').addEventListener("ui5-input", function (event) { -<<<<<<< HEAD if (event.detail.escapePressed) { -======= - if (event.detail.inputType === "escapePressed") { ->>>>>>> 4b324692e76864dcb001129d00de1c19b56fbfb9 event.preventDefault(); } }); From 243b4c18f495587e3a66683c17f177389793a5f8 Mon Sep 17 00:00:00 2001 From: i518532 Date: Wed, 13 Aug 2025 14:40:08 +0300 Subject: [PATCH 4/5] fix(ui5-textarea): add docs --- packages/main/src/TextArea.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/main/src/TextArea.ts b/packages/main/src/TextArea.ts index 5078c49ddec3..33af70ad2027 100644 --- a/packages/main/src/TextArea.ts +++ b/packages/main/src/TextArea.ts @@ -101,6 +101,7 @@ type TextAreaInputEventDetail = { * Fired when the value of the component changes at each keystroke or when * something is pasted. * @since 1.0.0-rc.5 + * @param {boolean} escapePressed Indicates whether the Escape key was pressed, which triggers a revert to the previous value * @public */ @event("input", { From 99c43e075a5d22bdff400ec2b16bbc23fb9a5e86 Mon Sep 17 00:00:00 2001 From: i518532 Date: Wed, 13 Aug 2025 15:52:48 +0300 Subject: [PATCH 5/5] fix(ui5-textarea): fix build --- packages/main/src/TextArea.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/main/src/TextArea.ts b/packages/main/src/TextArea.ts index 33af70ad2027..33cab1c7587d 100644 --- a/packages/main/src/TextArea.ts +++ b/packages/main/src/TextArea.ts @@ -652,3 +652,4 @@ class TextArea extends UI5Element implements IFormInputElement { TextArea.define(); export default TextArea; +export type { TextAreaInputEventDetail };