Skip to content

Commit cd76202

Browse files
committed
fix(ui5-tokenizer): allow copy/cut of focused token when not selected
When a token is focused but not selected, Ctrl+C now copies its value to the clipboard. In readonly mode, Ctrl+X copies without deleting. Also removed redundant selected filter in _fillClipboard since callers already pass the correct token list. Fixes #13446
1 parent 4727fb5 commit cd76202

2 files changed

Lines changed: 54 additions & 4 deletions

File tree

packages/main/cypress/specs/Tokenizer.cy.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,52 @@ describe("Clipboard Operations", () => {
18241824
// Only the selected token should be copied
18251825
cy.get("@clipboardWrite").should("have.been.calledOnceWith", "Selected");
18261826
});
1827+
1828+
it("should copy focused token text when no tokens are selected", () => {
1829+
cy.mount(
1830+
<Tokenizer>
1831+
<Token text="Focused"></Token>
1832+
<Token text="Other"></Token>
1833+
</Tokenizer>
1834+
);
1835+
1836+
// Tab into the tokenizer to focus the first token without selecting it
1837+
cy.realPress("Tab");
1838+
cy.get("[ui5-token]").eq(0).should("have.prop", "focused", true);
1839+
cy.get("[ui5-token]").eq(0).should("have.prop", "selected", false);
1840+
1841+
cy.window().then((win) => {
1842+
cy.stub(win.navigator.clipboard, "writeText").as("clipboardWrite");
1843+
Object.defineProperty(win, "isSecureContext", { value: true, writable: true });
1844+
});
1845+
1846+
cy.realPress(["Control", "c"]);
1847+
1848+
cy.get("@clipboardWrite").should("have.been.calledOnceWith", "Focused");
1849+
});
1850+
1851+
it("should not cut token in readonly mode", () => {
1852+
cy.mount(
1853+
<Tokenizer readonly={true}>
1854+
<Token text="ReadonlyToken"></Token>
1855+
<Token text="Other"></Token>
1856+
</Tokenizer>
1857+
);
1858+
1859+
cy.realPress("Tab");
1860+
cy.get("[ui5-token]").eq(0).should("have.prop", "focused", true);
1861+
1862+
cy.window().then((win) => {
1863+
cy.stub(win.navigator.clipboard, "writeText").as("clipboardWrite");
1864+
Object.defineProperty(win, "isSecureContext", { value: true, writable: true });
1865+
});
1866+
1867+
cy.realPress(["Control", "x"]);
1868+
1869+
// Should copy but not delete in readonly mode
1870+
cy.get("@clipboardWrite").should("have.been.calledOnceWith", "ReadonlyToken");
1871+
cy.get("[ui5-token]").should("have.length", 2);
1872+
});
18271873
});
18281874

18291875
describe("Tokenizer - getFocusDomRef Method", () => {

packages/main/src/Tokenizer.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -720,10 +720,14 @@ class Tokenizer extends UI5Element implements IFormInputElement {
720720
e.preventDefault();
721721

722722
const isCut = e.key.toLowerCase() === "x" || isDeleteShift(e);
723-
const selectedTokens = this._tokens.filter(token => token.selected);
724-
const focusedToken = selectedTokens.find(token => token.focused);
723+
let selectedTokens = this._tokens.filter(token => token.selected);
724+
const focusedToken = this._tokens.find(token => token.focused);
725725

726-
if (isCut) {
726+
if (!selectedTokens.length && focusedToken) {
727+
selectedTokens = [focusedToken];
728+
}
729+
730+
if (isCut && !this.readonly) {
727731
const cutResult = this._fillClipboard(ClipboardDataOperation.cut, selectedTokens);
728732

729733
focusedToken && this.deleteToken(focusedToken);
@@ -1079,7 +1083,7 @@ class Tokenizer extends UI5Element implements IFormInputElement {
10791083
}
10801084

10811085
_fillClipboard(shortcutName: ClipboardDataOperation, tokens: Array<IToken>) {
1082-
const tokensTexts = tokens.filter(token => token.selected).map(token => token.text).join("\r\n");
1086+
const tokensTexts = tokens.map(token => token.text).join("\r\n");
10831087

10841088
// Async clipboard API (works in secure contexts - HTTPS/localhost)
10851089
if (navigator.clipboard?.writeText && window.isSecureContext) {

0 commit comments

Comments
 (0)