Skip to content

Commit 637bed6

Browse files
authored
Merge pull request #23 from Patternslib/scrum-383--suggestion-qa
Scrum 383 suggestion qa
2 parents f973d06 + ca75099 commit 637bed6

File tree

3 files changed

+129
-13
lines changed

3 files changed

+129
-13
lines changed

src/extensions/suggestion.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,16 @@ export const factory = ({ app, name, char, plural }) => {
277277
// Suggestion render
278278
this.options.suggestion.render = () => {
279279
let _debounced_context_menu;
280+
281+
const ctx_close = () => {
282+
context_menu_instance = context_menu_close({
283+
instance: context_menu_instance,
284+
pattern_name: "tiptap-suggestion",
285+
});
286+
this.editor.off("selectionUpdate", _debounced_context_menu);
287+
events.remove_event_listener(document, "tiptap--suggestion_close");
288+
};
289+
280290
return {
281291
onStart: async (props) => {
282292
const _context_menu = async (
@@ -303,13 +313,33 @@ export const factory = ({ app, name, char, plural }) => {
303313
// The query string filter key must be already present on the URL.
304314
url = text ? url + text : url;
305315

306-
return await context_menu({
316+
const ctx_menu = await context_menu({
307317
url: url,
308318
editor: this.editor,
309319
instance: context_menu_instance,
310320
pattern: pattern_suggestion(app, props),
311321
extra_class: `tiptap-${plural || this.name}`, // plural form
312322
});
323+
324+
events.add_event_listener(
325+
document.body,
326+
"mousedown",
327+
"tiptap--suggestion_close",
328+
(e) => {
329+
if (
330+
[
331+
e.target,
332+
...dom.get_parents(e.target),
333+
].includes(context_menu_instance?.tippy.popper)
334+
) {
335+
// Do not close the context menu if we click in it.
336+
return;
337+
}
338+
ctx_close.bind(this)();
339+
}
340+
);
341+
342+
return ctx_menu;
313343
};
314344
_debounced_context_menu = utils.debounce(async (transaction) => {
315345
context_menu_instance = await _context_menu(transaction);
@@ -328,11 +358,7 @@ export const factory = ({ app, name, char, plural }) => {
328358
}
329359

330360
if (props.event.key === "Escape") {
331-
context_menu_instance = context_menu_close({
332-
instance: context_menu_instance,
333-
pattern_name: "tiptap-suggestion",
334-
});
335-
this.editor.off("selectionUpdate", _debounced_context_menu);
361+
ctx_close();
336362
return true;
337363
}
338364
if (
@@ -357,11 +383,7 @@ export const factory = ({ app, name, char, plural }) => {
357383
}
358384
},
359385
onExit: () => {
360-
context_menu_instance = context_menu_close({
361-
instance: context_menu_instance,
362-
pattern_name: "tiptap-suggestion",
363-
});
364-
this.editor.off("selectionUpdate", _debounced_context_menu);
386+
ctx_close();
365387
},
366388
};
367389
};

src/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8">
55
<title>tiptap demo</title>
6-
<script src="/bundle.js"></script>
6+
<script src="/bundle.min.js"></script>
77
<style type="text/css">
88
.tiptap-focus {
99
border: 2px solid red;

src/tiptap.test.js

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Pattern from "./tiptap";
2+
import events from "@patternslib/patternslib/src/core/events";
23
import utils from "@patternslib/patternslib/src/core/utils";
34
import tiptap_utils from "./utils";
45

@@ -1069,7 +1070,6 @@ describe("pat-tiptap", () => {
10691070
await utils.timeout(1); // Wait a tick for the tooltip to open.
10701071
await utils.timeout(1); // Wait a tick for the tooltip to open.
10711072
await utils.timeout(1); // Wait a tick for the tooltip to open.
1072-
console.log(document.body.innerHTML);
10731073

10741074
expect(document.querySelector(".tiptap-items")).toBeFalsy();
10751075
const mention = editable.firstChild.firstChild;
@@ -1097,4 +1097,98 @@ describe("pat-tiptap", () => {
10971097
global.fetch.mockClear();
10981098
delete global.fetch;
10991099
});
1100+
1101+
it("8.8 - Close suggestion dialog when clicking outside", async () => {
1102+
global.fetch = jest.fn().mockImplementation(mockFetch(SUGGESTION_RESPONSE));
1103+
1104+
document.body.innerHTML = `
1105+
<textarea
1106+
class="pat-tiptap"
1107+
data-pat-tiptap="
1108+
tags-menu: https://demo.at/tags.html;
1109+
">
1110+
</textarea>
1111+
`;
1112+
1113+
new Pattern(document.querySelector(".pat-tiptap"));
1114+
await utils.timeout(1);
1115+
1116+
const editable = document.querySelector(".tiptap-container [contenteditable]");
1117+
const range = document.createRange();
1118+
const sel = window.getSelection();
1119+
1120+
// Add the triggering character into the content editable
1121+
editable.innerHTML = "<p>#</p>";
1122+
// Set the cursor right after the #-sign.
1123+
range.setStart(editable.childNodes[0].childNodes[0], 1);
1124+
range.collapse(true);
1125+
sel.removeAllRanges();
1126+
sel.addRange(range);
1127+
1128+
await utils.timeout(1); // Wait a tick for the tooltip to open.
1129+
await utils.timeout(1); // Wait a tick for the suggestion-pattern to be initialized.
1130+
1131+
// Check for class ``tiptap-tags`` set on tooltip container.
1132+
expect(document.querySelector(".tooltip-container.tiptap-tags")).toBeTruthy();
1133+
expect(document.querySelector(".tiptap-items")).toBeTruthy();
1134+
1135+
// No close when clicking within the suggestion menu
1136+
document.querySelector(".tiptap-items").dispatchEvent(events.mousedown_event());
1137+
expect(document.querySelector(".tooltip-container.tiptap-tags")).toBeTruthy();
1138+
1139+
// Close when clicking outside the suggestion menu
1140+
document.body.dispatchEvent(events.mousedown_event());
1141+
expect(document.querySelector(".tooltip-container.tiptap-tags")).toBeFalsy();
1142+
1143+
global.fetch.mockClear();
1144+
delete global.fetch;
1145+
});
1146+
1147+
it("8.9 - Close suggestion with Escape", async () => {
1148+
global.fetch = jest.fn().mockImplementation(mockFetch(SUGGESTION_RESPONSE));
1149+
1150+
document.body.innerHTML = `
1151+
<textarea
1152+
class="pat-tiptap"
1153+
data-pat-tiptap="
1154+
tags-menu: https://demo.at/tags.html;
1155+
">
1156+
</textarea>
1157+
`;
1158+
1159+
new Pattern(document.querySelector(".pat-tiptap"));
1160+
await utils.timeout(1);
1161+
1162+
const editable = document.querySelector(".tiptap-container [contenteditable]");
1163+
const range = document.createRange();
1164+
const sel = window.getSelection();
1165+
1166+
// Add the triggering character into the content editable
1167+
editable.innerHTML = "<p>#</p>";
1168+
// Set the cursor right after the #-sign.
1169+
range.setStart(editable.childNodes[0].childNodes[0], 1);
1170+
range.collapse(true);
1171+
sel.removeAllRanges();
1172+
sel.addRange(range);
1173+
1174+
await utils.timeout(1); // Wait a tick for the tooltip to open.
1175+
await utils.timeout(1); // Wait a tick for the suggestion-pattern to be initialized.
1176+
1177+
// Check for class ``tiptap-tags`` set on tooltip container.
1178+
expect(document.querySelector(".tooltip-container.tiptap-tags")).toBeTruthy();
1179+
expect(document.querySelector(".tiptap-items")).toBeTruthy();
1180+
1181+
// Close when pressing "Escape"
1182+
editable.dispatchEvent(
1183+
new KeyboardEvent("keydown", {
1184+
key: "Escape",
1185+
bubbles: true,
1186+
cancelable: true,
1187+
})
1188+
);
1189+
expect(document.querySelector(".tooltip-container.tiptap-tags")).toBeFalsy();
1190+
1191+
global.fetch.mockClear();
1192+
delete global.fetch;
1193+
});
11001194
});

0 commit comments

Comments
 (0)