UX: re-check triggerRule to avoid autocomplete in code (#30961)

Re-checks triggerRule when navigating around with arrow keys and after
continued typing.

ref /t/-/23884
This commit is contained in:
Renato Atilio
2025-01-27 18:55:24 -03:00
committed by GitHub
parent a5f533667d
commit 7206a7182b
3 changed files with 49 additions and 24 deletions

View File

@ -555,7 +555,7 @@ export default function (options) {
if (options.onKeyUp && key !== options.key) {
let match = options.onKeyUp(options.textHandler.value, cp);
if (match) {
if (match && (await checkTriggerRule())) {
completeStart = cp - match[0].length;
let term = match[0].substring(1, match[0].length);
updateAutoComplete(dataSource(term, options));
@ -567,8 +567,8 @@ export default function (options) {
if (key === options.key) {
let prevChar = options.textHandler.value.charAt(cp - 2);
if (
(await checkTriggerRule()) &&
(!prevChar || ALLOWED_LETTERS_REGEXP.test(prevChar))
(!prevChar || ALLOWED_LETTERS_REGEXP.test(prevChar)) &&
(await checkTriggerRule())
) {
completeStart = cp - 1;
updateAutoComplete(dataSource("", options));

View File

@ -737,10 +737,7 @@ export default class TextareaTextManipulation {
}
async inCodeBlock() {
return inCodeBlock(
this.$textarea.value ?? this.$textarea.val(),
caretPosition(this.$textarea)
);
return await this.autocompleteHandler.inCodeBlock();
}
@bind
@ -869,9 +866,9 @@ export class TextareaAutocompleteHandler {
}
async inCodeBlock() {
return inCodeBlock(
this.$textarea.value ?? this.$textarea.val(),
caretPosition(this.$textarea)
return await inCodeBlock(
this.textarea.value ?? this.$textarea.val(),
caretPosition(this.textarea)
);
}
}

View File

@ -185,10 +185,19 @@ module("Unit | Utility | autocomplete", function (hooks) {
assert.dom(element).hasValue(":smile: ");
await triggerArrowKey(element, "ArrowLeft");
await triggerArrowKey(element, "ArrowLeft");
await triggerArrowKey(element, "ArrowLeft");
await triggerArrowKey(element, "ArrowRight");
async function triggerArrowKey(key) {
await triggerKeyEvent(element, "keydown", key, { code: key });
await triggerKeyEvent(element, "keyup", key, { code: key });
const pos = element.selectionStart;
const direction = key === "ArrowLeft" ? -1 : 1;
element.setSelectionRange(pos + 1 * direction, pos + 1 * direction);
}
await triggerArrowKey("ArrowLeft");
await triggerArrowKey("ArrowLeft");
await triggerArrowKey("ArrowLeft");
await triggerArrowKey("ArrowRight");
assert.strictEqual(element.selectionStart, 6);
@ -196,19 +205,38 @@ module("Unit | Utility | autocomplete", function (hooks) {
// triggerArrowKey isn't triggering the event the autocomplete listens to
assert.dom("#ac-testing").doesNotExist();
await triggerArrowKey(element, "ArrowRight");
await triggerArrowKey("ArrowRight");
await simulateKey(element, "\b");
assert.dom(element).hasValue(":smile ");
assert.dom("#ac-testing").exists();
});
test("Autocomplete respects triggerRule on continued typing", async function (assert) {
const element = textArea();
$(element).autocomplete({
key: ":",
template,
transformComplete: (e) => e.slice(1),
dataSource: () => [":smile:"],
triggerRule: async (_, { inCodeBlock }) => !(await inCodeBlock()),
});
await simulateKeys(element, "```\n:");
assert.dom("#ac-testing").doesNotExist();
await simulateKey(element, "smil");
assert.dom("#ac-testing").doesNotExist();
await simulateKey(element, "\n```\n:");
assert.dom("#ac-testing").exists();
await simulateKey(element, "smil");
assert.dom("#ac-testing").exists();
});
});
async function triggerArrowKey(element, key) {
await triggerKeyEvent(element, "keydown", key, { code: key });
await triggerKeyEvent(element, "keyup", key, { code: key });
const pos = element.selectionStart;
const direction = key === "ArrowLeft" ? -1 : 1;
element.setSelectionRange(pos + 1 * direction, pos + 1 * direction);
}