Fix outside click in story replies
This commit is contained in:
parent
b449450098
commit
f64426fbe0
3 changed files with 56 additions and 40 deletions
|
@ -42,7 +42,7 @@ export class EmojiCompletion {
|
|||
|
||||
quill: Quill;
|
||||
|
||||
outsideClickDestructor: () => void;
|
||||
outsideClickDestructor?: () => void;
|
||||
|
||||
constructor(quill: Quill, options: EmojiPickerOptions) {
|
||||
this.results = [];
|
||||
|
@ -51,18 +51,6 @@ export class EmojiCompletion {
|
|||
this.root = document.body.appendChild(document.createElement('div'));
|
||||
this.quill = quill;
|
||||
|
||||
// Just to make sure that we don't propagate outside clicks until this
|
||||
// is closed.
|
||||
this.outsideClickDestructor = handleOutsideClick(
|
||||
() => {
|
||||
return true;
|
||||
},
|
||||
{
|
||||
name: 'quill.emoji.completion',
|
||||
containerElements: [this.root],
|
||||
}
|
||||
);
|
||||
|
||||
const clearResults = () => {
|
||||
if (this.results.length) {
|
||||
this.reset();
|
||||
|
@ -108,7 +96,8 @@ export class EmojiCompletion {
|
|||
}
|
||||
|
||||
destroy(): void {
|
||||
this.outsideClickDestructor();
|
||||
this.outsideClickDestructor?.();
|
||||
this.outsideClickDestructor = undefined;
|
||||
this.root.remove();
|
||||
}
|
||||
|
||||
|
@ -277,14 +266,16 @@ export class EmojiCompletion {
|
|||
}
|
||||
|
||||
onUnmount(): void {
|
||||
document.body.removeChild(this.root);
|
||||
this.outsideClickDestructor?.();
|
||||
this.outsideClickDestructor = undefined;
|
||||
this.options.setEmojiPickerElement(null);
|
||||
}
|
||||
|
||||
render(): void {
|
||||
const { results: emojiResults, index: emojiResultsIndex } = this;
|
||||
|
||||
if (emojiResults.length === 0) {
|
||||
this.options.setEmojiPickerElement(null);
|
||||
this.onUnmount();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -374,7 +365,21 @@ export class EmojiCompletion {
|
|||
</div>
|
||||
)}
|
||||
</Popper>,
|
||||
document.body
|
||||
this.root
|
||||
);
|
||||
|
||||
// Just to make sure that we don't propagate outside clicks until this
|
||||
// is closed.
|
||||
this.outsideClickDestructor?.();
|
||||
this.outsideClickDestructor = handleOutsideClick(
|
||||
() => {
|
||||
this.onUnmount();
|
||||
return true;
|
||||
},
|
||||
{
|
||||
name: 'quill.emoji.completion',
|
||||
containerElements: [this.root],
|
||||
}
|
||||
);
|
||||
|
||||
this.options.setEmojiPickerElement(element);
|
||||
|
|
|
@ -43,7 +43,7 @@ export class MentionCompletion {
|
|||
|
||||
suggestionListRef: RefObject<HTMLDivElement>;
|
||||
|
||||
outsideClickDestructor: () => void;
|
||||
outsideClickDestructor?: () => void;
|
||||
|
||||
constructor(quill: Quill, options: MentionCompletionOptions) {
|
||||
this.results = [];
|
||||
|
@ -53,18 +53,6 @@ export class MentionCompletion {
|
|||
this.quill = quill;
|
||||
this.suggestionListRef = React.createRef<HTMLDivElement>();
|
||||
|
||||
// Just to make sure that we don't propagate outside clicks until this
|
||||
// is closed.
|
||||
this.outsideClickDestructor = handleOutsideClick(
|
||||
() => {
|
||||
return true;
|
||||
},
|
||||
{
|
||||
name: 'quill.emoji.completion',
|
||||
containerElements: [this.root],
|
||||
}
|
||||
);
|
||||
|
||||
const clearResults = () => {
|
||||
if (this.results.length) {
|
||||
this.clearResults();
|
||||
|
@ -92,7 +80,9 @@ export class MentionCompletion {
|
|||
}
|
||||
|
||||
destroy(): void {
|
||||
this.outsideClickDestructor();
|
||||
this.outsideClickDestructor?.();
|
||||
this.outsideClickDestructor = undefined;
|
||||
|
||||
this.root.remove();
|
||||
}
|
||||
|
||||
|
@ -220,7 +210,9 @@ export class MentionCompletion {
|
|||
}
|
||||
|
||||
onUnmount(): void {
|
||||
document.body.removeChild(this.root);
|
||||
this.outsideClickDestructor?.();
|
||||
this.outsideClickDestructor = undefined;
|
||||
this.options.setMentionPickerElement(null);
|
||||
}
|
||||
|
||||
render(): void {
|
||||
|
@ -228,7 +220,7 @@ export class MentionCompletion {
|
|||
const { getPreferredBadge, theme } = this.options;
|
||||
|
||||
if (memberResults.length === 0) {
|
||||
this.options.setMentionPickerElement(null);
|
||||
this.onUnmount();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -293,6 +285,20 @@ export class MentionCompletion {
|
|||
this.root
|
||||
);
|
||||
|
||||
// Just to make sure that we don't propagate outside clicks until this
|
||||
// is closed.
|
||||
this.outsideClickDestructor?.();
|
||||
this.outsideClickDestructor = handleOutsideClick(
|
||||
() => {
|
||||
this.onUnmount();
|
||||
return true;
|
||||
},
|
||||
{
|
||||
name: 'quill.mentions.completion',
|
||||
containerElements: [this.root],
|
||||
}
|
||||
);
|
||||
|
||||
this.options.setMentionPickerElement(element);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,15 @@ export type ContainerElementType = Node | RefObject<Node> | null | undefined;
|
|||
|
||||
// TODO(indutny): DESKTOP-4177
|
||||
// A stack of handlers. Handlers are executed from the top to the bottom
|
||||
const fakeClickHandlers = new Array<(event: MouseEvent) => boolean>();
|
||||
const fakeClickHandlers = new Array<{
|
||||
name: string;
|
||||
handleEvent: (event: MouseEvent) => boolean;
|
||||
}>();
|
||||
|
||||
function runFakeClickHandlers(event: MouseEvent): void {
|
||||
for (const handler of fakeClickHandlers.slice().reverse()) {
|
||||
if (handler(event)) {
|
||||
for (const entry of fakeClickHandlers.slice().reverse()) {
|
||||
const { handleEvent } = entry;
|
||||
if (handleEvent(event)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +29,7 @@ export type HandleOutsideClickOptionsType = Readonly<{
|
|||
|
||||
export const handleOutsideClick = (
|
||||
handler: ClickHandlerType,
|
||||
{ containerElements }: HandleOutsideClickOptionsType
|
||||
{ name, containerElements }: HandleOutsideClickOptionsType
|
||||
): (() => void) => {
|
||||
const handleEvent = (event: MouseEvent) => {
|
||||
const target = event.target as Node;
|
||||
|
@ -49,19 +53,20 @@ export const handleOutsideClick = (
|
|||
return handler(target);
|
||||
};
|
||||
|
||||
fakeClickHandlers.push(handleEvent);
|
||||
const fakeHandler = { name, handleEvent };
|
||||
fakeClickHandlers.push(fakeHandler);
|
||||
if (fakeClickHandlers.length === 1) {
|
||||
const useCapture = true;
|
||||
document.addEventListener('click', runFakeClickHandlers, useCapture);
|
||||
}
|
||||
|
||||
return () => {
|
||||
const index = fakeClickHandlers.indexOf(handleEvent);
|
||||
const index = fakeClickHandlers.indexOf(fakeHandler);
|
||||
fakeClickHandlers.splice(index, 1);
|
||||
|
||||
if (fakeClickHandlers.length === 0) {
|
||||
const useCapture = true;
|
||||
document.removeEventListener('click', handleEvent, useCapture);
|
||||
document.removeEventListener('click', runFakeClickHandlers, useCapture);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue