From 2d6c358a98f9c36eb99090a7012486d5821fdbfa Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:06:27 +0200 Subject: [PATCH] fix update listeners --- .../input-tiptap/input-tiptap.element.ts | 16 ++---- .../input-tiptap/tiptap-fixed-menu.element.ts | 36 +++++++++--- .../input-tiptap/tiptap-hover-menu.element.ts | 55 +++++++++++++++++++ 3 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index 209fb1836d..0b632b56d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -6,6 +6,7 @@ import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import './tiptap-fixed-menu.element.js'; +import './tiptap-hover-menu.element.js'; import { Editor, Link, StarterKit, TextAlign, Underline } from '@umbraco-cms/backoffice/external/tiptap'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @@ -35,23 +36,18 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '' TextAlign.configure({ types: ['heading', 'paragraph', 'blockquote', 'orderedList', 'bulletList', 'codeBlock'], }), - Link, + Link.configure({ openOnClick: false }), Underline, ], content: json, onSelectionUpdate: ({ editor }) => { const { $from } = editor.state.selection; const activeMarks = $from.node(); - - // Log the active marks - console.log('Active Marks:', activeMarks); - this._fixedMenuElement.onUpdate(); // TODO: This is a hack to force the fixed menu to update. We need to find a better way. }, onUpdate: ({ editor }) => { const json = editor.getJSON(); this.value = JSON.stringify(json); this.dispatchEvent(new UmbChangeEvent()); - this._fixedMenuElement.onUpdate(); // TODO: This is a hack to force the fixed menu to update. We need to find a better way. }, }); } @@ -62,10 +58,8 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '' override render() { return html` - + +
`; } @@ -108,7 +102,7 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '' font-size: 0.8rem; padding: 0; } - .ProseMirror { + .tiptap { height: 100%; width: 100%; outline: none; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts index e34eb1445f..a63fb72121 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts @@ -17,6 +17,7 @@ import { strikethrough, underline, } from './icons.js'; +import type { PropertyValues } from '@umbraco-cms/backoffice/external/lit'; import { LitElement, css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; @@ -133,24 +134,41 @@ export class UmbTiptapFixedMenuElement extends LitElement { name: 'link', icon: link, command: () => { + const text = prompt('Enter the text'); const url = prompt('Enter the URL'); - if (url) { - this.editor?.chain().focus().setLink({ href: url, target: '_blank' }).run(); + if (url && text && this.editor) { + const { from } = this.editor.state.selection; + this.editor + .chain() + .focus() + .insertContent(text) + .setTextSelection({ from: from, to: from + text.length }) + .setLink({ href: url, target: '_blank' }) + .run(); } }, }, ]; @property({ attribute: false }) - editor?: Editor; - - public onUpdate() { - //TODO: Find a better way to trigger a re-render of the menu when the editor is updated - // This is used to update the active state of the buttons - this.requestUpdate(); - console.log('onUpdate'); + get editor() { + return this.#editor; } + set editor(value) { + const oldValue = this.#editor; + if (value === oldValue) { + return; + } + this.#editor = value; + this.#editor?.on('selectionUpdate', this.#onUpdate); + this.#editor?.on('update', this.#onUpdate); + } + #editor?: Editor; + + #onUpdate = () => { + this.requestUpdate(); + }; override render() { return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts new file mode 100644 index 0000000000..6dfc91ac56 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-hover-menu.element.ts @@ -0,0 +1,55 @@ +import { LitElement, PropertyValues, css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; +import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; + +@customElement('umb-tiptap-hover-menu') +export class UmbTiptapHoverMenuElement extends LitElement { + @property({ attribute: false }) + get editor() { + return this.#editor; + } + set editor(value) { + const oldValue = this.#editor; + if (value === oldValue) { + return; + } + this.#editor = value; + this.#editor?.on('selectionUpdate', this.#onUpdate); + this.#editor?.on('update', this.#onUpdate); + } + #editor?: Editor; + + override connectedCallback(): void { + super.connectedCallback(); + this.setAttribute('popover', ''); + } + + #onUpdate = () => { + console.log('LINK ACTIVE'); + if (this.editor?.isActive('link')) { + // show the popover + this.showPopover(); + } else { + this.requestUpdate(); + } + }; + + override render() { + console.log('RENDER HOVER MENU'); + return html``; + } + + static override styles = css` + :host { + position: fixed; + background-color: var(--uui-color-surface-alt); + border: 1px solid var(--uui-color-border); + border-radius: var(--uui-size-border-radius); + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-tiptap-hover-menu': UmbTiptapHoverMenuElement; + } +}