MentionPicker
App@-trigger autocomplete picker. Headless: takes users + query + position, fires onSelect. Keyboard nav (ArrowUp/Down, Enter/Tab, Escape).
"al"
<%- include('modules/app/MentionPicker', {
users: candidates,
query: 'al',
anchorInputId: 'comment-input'
}) %>
"zzz"
No matching users
<%- include('modules/app/MentionPicker', {
users: candidates,
query: 'zzz'
}) %>
<%
var _id = locals.id || ('mention-' + Math.random().toString(36).substr(2,6));
var _users = locals.users || [];
var _query = locals.query || '';
var _open = (locals.open === undefined) ? true : !!locals.open;
var _position = locals.position || null;
var _maxItems = (typeof locals.maxItems === 'number') ? locals.maxItems : 6;
var _emptyMessage = locals.emptyMessage || 'No matching users';
var _className = locals.className ? ' ' + locals.className : '';
var _anchorInputId = locals.anchorInputId || '';
function _initials(name) {
if (!name) return '?';
var parts = String(name).trim().split(/\s+/);
return (parts.slice(0,2).map(function(p){ return p[0]; }).join('') || '?').toUpperCase();
}
function _filter(u, q) {
if (!q) return true;
var lq = String(q).toLowerCase();
return (u.name && u.name.toLowerCase().includes(lq)) ||
(u.handle && u.handle.toLowerCase().includes(lq));
}
var _filtered = _users.filter(function(u){ return _filter(u, _query); }).slice(0, _maxItems);
var _style = '';
if (_position) {
_style = 'position: absolute; top: ' + (_position.top || 0) + 'px; left: ' + (_position.left || 0) + 'px;';
}
%>