Fixes
This commit is contained in:
@@ -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 sampleUsers = [
|
||||
@@ -17,18 +16,6 @@ const sampleUsers = [
|
||||
];
|
||||
|
||||
export class TpRtbUserMention extends TpRtbBaseExtension {
|
||||
static getUsers() {
|
||||
return sampleUsers;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
...super.properties,
|
||||
items: { type: Array },
|
||||
selectedIndex: { type: Number },
|
||||
};
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
super.styles,
|
||||
@@ -45,6 +32,7 @@ export class TpRtbUserMention extends TpRtbBaseExtension {
|
||||
z-index: 9999;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
@@ -53,24 +41,30 @@ export class TpRtbUserMention extends TpRtbBaseExtension {
|
||||
gap: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.item.is-selected {
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
@@ -79,11 +73,67 @@ export class TpRtbUserMention extends TpRtbBaseExtension {
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div>
|
||||
${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._handleItemClick(e, index)}
|
||||
>
|
||||
<span class="avatar">${item.avatar}</span>
|
||||
<div class="user-info">
|
||||
<span class="name">${item.name}</span>
|
||||
<span class="username">@${item.username}</span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
: html`<div class="item">No users found</div>`}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
items: { type: Array },
|
||||
selectedIndex: { type: Number },
|
||||
getUsersCallback: { type: Function, state: true },
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.items = [];
|
||||
this.selectedIndex = 0;
|
||||
this.label = 'User Mention';
|
||||
this.getUsersCallback = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.addEventListener('mousedown', this._handleContainerMouseDown);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.removeEventListener('mousedown', this._handleContainerMouseDown);
|
||||
}
|
||||
|
||||
_getFilteredUsers(query) {
|
||||
// Use callback if provided, otherwise fall back to sample users
|
||||
if (this.getUsersCallback && typeof this.getUsersCallback === 'function') {
|
||||
return this.getUsersCallback(query);
|
||||
}
|
||||
|
||||
// Fallback to sample users with default filtering
|
||||
return sampleUsers.filter(user =>
|
||||
user.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
user.username.toLowerCase().includes(query.toLowerCase())
|
||||
).slice(0, 10);
|
||||
}
|
||||
|
||||
getSuggestionConfig() {
|
||||
@@ -92,11 +142,21 @@ export class TpRtbUserMention extends TpRtbBaseExtension {
|
||||
allowSpaces: false,
|
||||
startOfLine: false,
|
||||
items: ({ query }) => {
|
||||
console.log('User mention query:', query);
|
||||
return TpRtbUserMention.getUsers().filter(user =>
|
||||
user.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
user.username.toLowerCase().includes(query.toLowerCase())
|
||||
).slice(0, 10);
|
||||
return this._getFilteredUsers(query);
|
||||
},
|
||||
renderHTML({ options, node, suggestion }) {
|
||||
return [
|
||||
'span',
|
||||
{
|
||||
class: 'user-mention',
|
||||
'data-type': 'mention',
|
||||
'data-id': node.attrs.id,
|
||||
'data-label': node.attrs.label,
|
||||
'data-mention-suggestion-char': '@',
|
||||
contenteditable: 'false'
|
||||
},
|
||||
node.attrs.label || node.attrs.id
|
||||
];
|
||||
},
|
||||
render: () => {
|
||||
let component;
|
||||
@@ -193,27 +253,6 @@ export class TpRtbUserMention 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)}"
|
||||
>
|
||||
<span class="avatar">${item.avatar}</span>
|
||||
<div class="user-info">
|
||||
<span class="name">${item.name}</span>
|
||||
<span class="username">@${item.username}</span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
: html`<div class="item">No users found</div>`}
|
||||
`;
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has('selectedIndex')) {
|
||||
const selectedElement = this.shadowRoot.querySelector('.item.is-selected');
|
||||
@@ -233,18 +272,37 @@ export class TpRtbUserMention extends TpRtbBaseExtension {
|
||||
}
|
||||
}
|
||||
|
||||
_handleItemClick(event, index) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this._selectItem(index);
|
||||
}
|
||||
|
||||
_handleItemMouseDown(event, index) {
|
||||
// Prevent blur event from firing on the editor
|
||||
event.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;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (event.key === 'ArrowDown') {
|
||||
this.selectedIndex = (this.selectedIndex + 1) % this.items.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._selectItem(this.selectedIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user