This commit is contained in:
2025-11-20 15:23:20 +01:00
parent 980048b6ab
commit 52f7478b5f
4 changed files with 255 additions and 115 deletions

View File

@@ -1,6 +1,5 @@
import { LitElement, html, css } from 'lit';
import { html, css } from 'lit';
import { TpRtbBaseExtension } from './tp-rtb-base-extension.js';
import Mention from '@tiptap/extension-mention';
import { closest } from '@tp/helpers/closest.js';
const emojis = [
@@ -254,18 +253,6 @@ const emojis = [
];
export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
static getEmojis() {
return emojis;
}
static get properties() {
return {
...super.properties,
items: { type: Array },
selectedIndex: { type: Number },
};
}
static get styles() {
return [
super.styles,
@@ -292,12 +279,52 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
];
}
render() {
return html`
${this.items.length > 0
? this.items.map(
(item, index) => html`
<div
class="item ${index === this.selectedIndex ? 'is-selected' : ''}"
@mousedown=${(e) => this._handleItemMouseDown(e, index)}
@click=${(e) => this._selectItem(e, index)}
>
${item.emoji} ${item.name}
</div>
`
)
: html`<div class="item">No result</div>`}
`;
}
static getEmojis() {
return emojis;
}
static get properties() {
return {
...super.properties,
items: { type: Array },
selectedIndex: { type: Number },
};
}
constructor() {
super();
this.items = [];
this.selectedIndex = 0;
this.label = 'Emoji';
}
connectedCallback() {
super.connectedCallback();
this.addEventListener('mousedown', this._handleContainerMouseDown);
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('mousedown', this._handleContainerMouseDown);
}
getSuggestionConfig() {
return {
@@ -308,6 +335,19 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
console.log('Emoji query:', query);
return TpRtbEmojiSuggestion.getEmojis().filter(item => item.name.toLowerCase().startsWith(query.toLowerCase())).slice(0, 10);
},
renderHTML({ options, node, suggestion }) {
return [
'span',
{
class: 'emoji',
'data-type': 'emoji',
'data-id': node.attrs.id,
'data-char': ':',
contenteditable: 'false'
},
node.attrs.label || node.attrs.id
];
},
render: () => {
let component;
let parentEditor;
@@ -315,8 +355,6 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
return {
onStart: props => {
console.log('Emoji suggestion onStart called', props);
console.log('Props clientRect:', props.clientRect);
// Find the parent editor using tp/helpers closest
parentEditor = closest(this, 'tp-rich-text-box', true);
if (!parentEditor) {
@@ -378,7 +416,6 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
return component.onKeyDown(props);
},
onExit: () => {
console.log('Emoji suggestion onExit called');
if (component && selectItemHandler) {
component.removeEventListener('select-item', selectItemHandler);
component.items = [];
@@ -403,23 +440,6 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
// This method can be left empty or used for other purposes
}
render() {
return html`
${this.items.length > 0
? this.items.map(
(item, index) => html`
<div
class="item ${index === this.selectedIndex ? 'is-selected' : ''}"
@click="${() => this._selectItem(index)}"
>
${item.emoji} ${item.name}
</div>
`
)
: html`<div class="item">No result</div>`}
`;
}
updated(changedProperties) {
if (changedProperties.has('selectedIndex')) {
const selectedElement = this.shadowRoot.querySelector('.item.is-selected');
@@ -432,13 +452,27 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
}
}
_selectItem(index) {
_selectItem(e, index) {
e.stopPropagation();
e.preventDefault();
const item = this.items[index];
if (item) {
this.dispatchEvent(new CustomEvent('select-item', { detail: item }));
}
}
_handleItemMouseDown(e, index) {
// Prevent blur event from firing on the editor
e.preventDefault();
}
_handleContainerMouseDown(event) {
// Prevent blur event from firing when clicking anywhere in the suggestion popup
// This includes scrollbars, empty areas, etc.
event.preventDefault();
}
onKeyDown({ event }) {
if (event.key === 'ArrowUp') {
this.selectedIndex = (this.selectedIndex + this.items.length - 1) % this.items.length;
@@ -451,7 +485,9 @@ export class TpRtbEmojiSuggestion extends TpRtbBaseExtension {
}
if (event.key === 'Enter') {
this._selectItem(this.selectedIndex);
event.preventDefault();
event.stopPropagation();
this._selectItem(event, this.selectedIndex);
return true;
}