tui.editor
tui.editor copied to clipboard
Menus don't work inside Shadow DOM
Describe the bug
The menus, such as when selecting a heading, disappear when clicked. Likely caused by using the editor inside a shadow root?
To Reproduce
Steps to reproduce the behavior:
- Wrap the editor inside a
LitElement
(gist) - Use it on a page as
<tui-editor></tui-editor>
- Click the header menu icon
- Select a heading size
- Nothing happens
Expected behavior
Heading should be applied to the editor text
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: macOS
- Browser: Chrome (Brave)
-
Version 1.38.109 Chromium: 101.0.4951.41 (Official Build) (x86_64)
Additional context
I debugged the moment as menu disappears to this switch in code
function createDefaultToolbarItemInfo(type) {
var info;
switch (type) {
case 'heading':
}
}
Apparently, any time any menu icon or any popup is clicked, the value of type
equals more
and what would be expected...
Unfortunately, we also ran into this problem. Within the Shadow DOM, several features do not work correctly, e.g. it is not possible to insert a URL via the link menu dialog. Open dialogues are closed immediately when clicking, in this case in the URL input field.
Hello, I have also experienced this problem. As soon as I use the editor in a custom element with its own Shadow DOM, the pop-up menus do not work. As soon as I click on them, they close immediately. An input in input fields in the menus is not possible.
I also ran into this. It is a showstopper for our potential use case. The cause is a mousedown
handler on the document, installed by the base Popup
class. It looks for the popup element as an ancestor of the event target, but when the event crosses the shadow DOM boundary, the target is changed to the host element. I wonder if we could solve this by putting an additional mousedown
handler on the Popup element itself which stops propagation on the event:
private handleMousedownDocument = (ev: MouseEvent) => {
this.props.hidePopup();
};
private handleMousedownPopup = (ev: MouseEvent) => {
if (
closest(ev.target as HTMLElement, `.${cls('popup')}`) ||
closest(ev.target as HTMLElement, this.props.info.fromEl)
) {
ev.stopPropagation();
}
};
mounted() {
document.addEventListener('mousedown', this.handleMousedownDocument );
this.addEventListener('mousedown', this.handleMousedownPopup );
this.props.eventEmitter.listen('closePopup', this.props.hidePopup);
}
For anyone else getting tired of waiting for a fix for this - a workaround along these lines appear to work:
export class MarkdownEditorCustomElement
{
// ...
// The element, inside a Shadow DOM, for which the editor is initialized.
private editorElement: HTMLElement;
public attached(): void
{
// ...
this.editorElement.addEventListener("mousedown", this.handleMousedown);
}
public deatached(): void
{
// ...
this.editorElement.removeEventListener("mousedown", this.handleMousedown);
}
private handleMousedown = (event: MouseEvent) =>
{
if ((event.target as HTMLElement).closest(".toastui-editor-popup") != null)
{
event.stopPropagation();
}
};
}