npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@billbarsch/mentionjs

v1.2.9

Published

Uma biblioteca JavaScript para adicionar funcionalidade de menções em campos de texto editáveis

Downloads

16

Readme

MentionJS

Uma biblioteca JavaScript leve e flexível para adicionar funcionalidade de menções (@mention) em campos de texto editáveis.

Características

  • 🚀 Suporte para múltiplos tipos de menções (Usuário: , Produto: , Venda: )
  • 🎨 Estilos personalizáveis por tipo de menção
  • 🔄 Suporte para dados estáticos e dinâmicos (via API)
  • 🎯 Display personalizado para cada tipo de menção
  • 📝 Compatível com campos contentEditable
  • ⚛️ Exemplo de integração com React
  • 🌐 Exemplo de uso com HTML puro
  • 🏷️ Prefixos personalizáveis por tipo de menção

Instalação

npm install @billbarsch/mentionjs

Uso Básico

import MentionJS from '@billbarsch/mentionjs';

const editor = document.getElementById('editor');
const mention = new MentionJS({
    inputElement: editor,
    data: {
        // Exemplo com API
        usuarios: {
            label: 'Usuários',
            data: 'https://jsonplaceholder.typicode.com/users?username_like=',
            prefix: 'Usuario: ',
            // Obrigatório: função para exibição do item
            display: item => `${item.username} (${item.email})`,
            // Obrigatório: função para processar resposta da API
            parseResponse: (data) => data.map(user => ({
                tipo: 'usuario',
                id: user.id,
                username: user.username,
                email: user.email
            })),
            // Opcional: estilos personalizados
            styles: {
                background: '#e3f2fd',
                color: '#1565c0',
                border: '#90caf9'
            }
        },
        // Exemplo com dados estáticos
        vendas: {
            label: 'Vendas',
            prefix: 'Venda: ',
            // Obrigatório: função para exibição do item
            display: item => `${item.label} - R$ ${item.valor}`,
            data: [
                { id: 1, label: 'Venda 1', valor: 1000 },
                { id: 2, label: 'Venda 2', valor: 2000 }
            ],
            // Obrigatório: função para processar os dados
            parseResponse: (data) => data.map(venda => ({
                ...venda,
                tipo: 'venda'
            })),
            // Opcional: estilos personalizados
            styles: {
                background: '#e8f5e9',
                color: '#2e7d32',
                border: '#a5d6a7'
            }
        }
    }
});

🎯 Exemplos

O projeto inclui exemplos em HTML e React:

HTML

Exemplo completo com dados estáticos e dinâmicos:

# Abra diretamente no navegador
open examples/html/url.html

React

import React, { useEffect, useRef } from 'react';
import MentionJS from '@billbarsch/mentionjs';

function App() {
    const editorRef = useRef(null);
    const outputHtmlRef = useRef(null);
    const outputJsonRef = useRef(null);
    const outputTextRef = useRef(null);
    const outputDisplayRef = useRef(null);
    const mentionRef = useRef(null);

    useEffect(() => {
        if (editorRef.current) {
            mentionRef.current = new MentionJS({
                inputElement: editorRef.current,
                data: {
                    usuarios: {
                        label: 'Usuários',
                        data: 'https://jsonplaceholder.typicode.com/users?username_like=',
                        prefix: 'Usuário: ',
                        display: item => `${item.username} (${item.email})`,
                        parseResponse: (data) => data.map(user => ({
                            tipo: 'usuario',
                            id: user.id,
                            username: user.username,
                            email: user.email
                        })),
                        styles: {
                            background: '#e3f2fd',
                            color: '#1565c0',
                            border: '#90caf9'
                        }
                    },
                    produtos: {
                        label: 'Produtos',
                        data: 'https://dummyjson.com/products/search?q=',
                        prefix: 'Produto: ',
                        display: item => `${item.title} - ${item.description}`,
                        parseResponse: (data) => {
                            if (!data || !data.products) return [];
                            return data.products.map(product => ({
                                tipo: 'produto',
                                id: product.id,
                                title: product.title,
                                description: product.description
                            }));
                        },
                        styles: {
                            background: '#fff9c4',
                            color: '#f57f17',
                            border: '#ffd54f'
                        }
                    },
                    vendas: {
                        label: 'Vendas',
                        prefix: 'Venda: ',
                        display: item => `${item.label} - R$ ${item.valor} (${item.data})`,
                        data: [
                            {
                                tipo: 'venda',
                                id: 1,
                                label: 'Venda 1',
                                valor: 1000,
                                data: '2024-03-20'
                            },
                            {
                                tipo: 'venda',
                                id: 2,
                                label: 'Venda 2',
                                valor: 2000,
                                data: '2024-03-21'
                            }
                        ],
                        styles: {
                            background: '#fff9c4',
                            color: '#f57f17',
                            border: '#ffd54f'
                        }
                    }
                },
                styles: {
                    usuarios: {
                        background: '#e3f2fd',
                        color: '#1565c0',
                        border: '#90caf9'
                    },
                    produtos: {
                        background: '#fff9c4',
                        color: '#f57f17',
                        border: '#ffd54f'
                    },
                    vendas: {
                        background: '#fff9c4',
                        color: '#f57f17',
                        border: '#ffd54f'
                    }
                }
            });

            const updateOutputs = () => {
                if (outputHtmlRef.current) {
                    outputHtmlRef.current.textContent = mentionRef.current.getHtml();
                }
                if (outputJsonRef.current) {
                    outputJsonRef.current.textContent = JSON.stringify(mentionRef.current.getJson(), null, 2);
                }
                if (outputTextRef.current) {
                    outputTextRef.current.textContent = mentionRef.current.getText();
                }
                if (outputDisplayRef.current) {
                    outputDisplayRef.current.textContent = mentionRef.current.getDisplayText();
                }
            };

            editorRef.current.addEventListener('input', updateOutputs);
            return () => {
                if (editorRef.current) {
                    editorRef.current.removeEventListener('input', updateOutputs);
                }
                if (mentionRef.current) {
                    mentionRef.current.destroy();
                }
            };
        }
    }, []);

    return (
        <div className="App">
            <h1>MentionJS - Exemplo React</h1>
            <p>Digite @ e escolha o tipo de menção (usuários, produtos ou vendas)</p>

            <div ref={editorRef} className="editor" contentEditable></div>

            <div className="output">
                <h3>Conteúdo HTML:</h3>
                <pre ref={outputHtmlRef}></pre>

                <h3>Conteúdo JSON:</h3>
                <pre ref={outputJsonRef}></pre>

                <h3>Conteúdo Texto:</h3>
                <pre ref={outputTextRef}></pre>

                <h3>Conteúdo Display:</h3>
                <pre ref={outputDisplayRef}></pre>
            </div>
        </div>
    );
}

export default App;

Para usar o exemplo React:

# Entre na pasta do exemplo React
cd examples/react

# Instale as dependências
npm install

# Inicie o servidor de desenvolvimento
npm start

API

Opções

  • inputElement: Elemento HTML onde as menções serão habilitadas
  • data: Objeto com configuração dos tipos de menção. Cada tipo deve ser um objeto com:
    • label: Nome amigável do tipo que será exibido no menu de seleção (opcional, usa o tipo se não fornecido)
    • data: URL para busca ou array de dados estáticos
    • display: (Obrigatório) Função que define como o item será exibido no menu de seleção
    • prefix: Prefixo opcional que será adicionado antes do texto do display (ex: "Usuario: ", "Produto: ", "Venda: ")
    • parseResponse: (Obrigatório) Função de transformação dos dados
    • styles: (Opcional) Objeto com estilos personalizados para o tipo:
      • background: Cor de fundo
      • color: Cor do texto
      • border: Cor da borda

Configuração de Dados

Cada tipo de menção deve ser configurado como um objeto com as seguintes propriedades:

  1. Configuração com dados estáticos:
vendas: {
    label: 'Vendas', // opcional
    prefix: 'Venda: ', // opcional
    display: item => `${item.label} - R$ ${item.valor}`, // obrigatório
    data: [
        { id: 1, label: 'Venda 1', valor: 1000 },
        { id: 2, label: 'Venda 2', valor: 2000 }
    ],
    parseResponse: (data) => data.map(venda => ({ // obrigatório
        ...venda,
        tipo: 'venda'
    })),
    styles: { // opcional
        background: '#e8f5e9',
        color: '#2e7d32',
        border: '#a5d6a7'
    }
}
  1. Configuração com API:
usuarios: {
    label: 'Usuários', // opcional
    prefix: 'Usuario: ', // opcional
    data: 'https://api.exemplo.com/usuarios?q=',
    display: item => `${item.nome} (${item.email})`, // obrigatório
    parseResponse: (data) => data.map(user => ({ // obrigatório
        tipo: 'usuario',
        id: user.id,
        nome: user.nome,
        email: user.email
    })),
    styles: { // opcional
        background: '#e3f2fd',
        color: '#1565c0',
        border: '#90caf9'
    }
}

A função parseResponse pode retornar objetos com qualquer estrutura, desde que:

  • Tenha um id único
  • Contenha todos os campos necessários para a função display

A função display define como o item será exibido no menu de seleção e pode usar qualquer campo retornado pelo parseResponse.

Métodos

  • getText(): Retorna o texto puro com as menções em formato JSON
  • getHtml(): Retorna o HTML do conteúdo com as menções formatadas
  • getJson(): Retorna um array com todas as menções e seus dados
  • getDisplayText(): Retorna o texto puro com as menções formatadas usando a função display original

Por exemplo:

// Se o texto no editor for: "Olá Usuário: Bret ([email protected]), como vai?"

mention.getText()
// Retorna: 'Olá {"tipo":"usuario","id":"1","username":"Bret","email":"[email protected]"}, como vai?'

mention.getDisplayText()
// Retorna: 'Olá Bret ([email protected]), como vai?'

Desenvolvimento

  1. Clone o repositório
git clone https://github.com/billbarsch/mentionjs.git
  1. Instale as dependências
npm install
  1. Execute o exemplo React
cd examples/react
npm install
npm start

🤝 Contribuindo

  1. Faça um fork do projeto
  2. Crie sua feature branch (git checkout -b feature/AmazingFeature)
  3. Commit suas mudanças (git commit -m 'Add some AmazingFeature')
  4. Push para a branch (git push origin feature/AmazingFeature)
  5. Abra um Pull Request

📧 Suporte

🛣️ Roadmap

  • [ ] Suporte a TypeScript
  • [ ] Temas personalizáveis
  • [ ] Mais eventos e callbacks
  • [ ] Suporte a Vue.js
  • [ ] Suporte a Angular
  • [ ] Testes automatizados
  • [ ] CI/CD
  • [ ] Documentação interativa

⭐ Autor

Bill Barsch ([email protected])

Licença

MIT