Pular para o conteúdo principal

Widget Documentation

Guia completo para integrar o widget de suporte PumaHelp em sua aplicação.

🚀 Início Rápido

Instalação

Adicione o script do widget ao seu HTML:

<script src="https://cdn.pumahelp.com/widget-v2.1.0/widget.js" type="module"></script>

Uso Básico

Opção 1: Web Component (HTML)

<puma-help-widget
app-name="seu-subdominio"
api-key="key-xxxxxxxxxxxxx"
></puma-help-widget>

Opção 2: API JavaScript

const widget = window.PumaHelp.init({
appName: 'seu-subdominio',
apiKey: 'key-xxxxxxxxxxxxx'
});

⚙️ Configuração

Parâmetros Obrigatórios

ParâmetroTipoDescrição
appNamestringSeu subdomínio PumaHelp (ex: minha-empresa)
apiKeystringSua chave de API (começa com rk_live_)
important

Segurança da API Key: Para uso no widget frontend, crie uma chave restrita no dashboard do PumaHelp com apenas a permissão "Criar Convidado (Guest)". Nunca use chaves com permissões administrativas no código client-side, pois elas ficam expostas no navegador.

Parâmetros Opcionais

ParâmetroTipoPadrãoDescrição
theme'light' | 'dark''dark'Esquema de cores do widget
language'pt-BR' | 'en''pt-BR'Idioma da interface
colorstring-Cor primária (formato hex: #FF6B35)
iconTipo do ícone'puma'Ícone do botão do widget
soundEnabledbooleantrueHabilitar sons de notificação
debugbooleanfalseHabilitar logs de debug
translationsstring (JSON)-Textos personalizados

Ícones disponíveis: 'puma', 'emoji', 'question', 'lines', 'bell', 'send'

Personalização de Textos

Você pode personalizar todos os textos estáticos do widget usando o atributo ou propriedade translations (string JSON).

Chaves disponíveis:

ChavePadrão (pt-BR / en)Descrição
mainTitleSuporteO título principal do widget (cabeçalho)
welcomeOlá! 👋 / Hello! 👋Saudação no formulário de novo ticket
descriptionComo podemos...Descrição no formulário de novo ticket
startNewChatNova Conversa / New ConversationTexto do botão para iniciar chat
sendMessageDigite uma mensagem...Placeholder para campos de mensagem
loadingCarregando...Texto de estado de carregamento
endTicketO atendimento foi finalizado.Mensagem quando o ticket é fechado
startedAtIniciado em / Started atTexto do cabeçalho na visualização do chat (seguido da data)

Exemplos

Tema escuro com cor personalizada:

window.PumaHelp.init({
appName: 'acme',
apiKey: 'key-abc123',
theme: 'dark',
color: '#2563eb',
language: 'en',
translations: {
mainTitle: 'Central de Ajuda',
welcome: 'Olá!',
sendMessage: 'Digite aqui...'
}
});
<puma-help-widget
app-name="acme"
api-key="key-abc123"
theme="light"
language="pt-BR"
color="#ff6b35"
icon="question"
translations='{
"mainTitle": "Central de Ajuda",
"welcome": "Olá!",
"sendMessage": "Digite aqui..."
}'
></puma-help-widget>

🛡️ Segurança e Boas Práticas

API Key Restrita

O widget é executado no navegador do usuário (client-side), portanto a apiKey fica visível no código-fonte da página. Para proteger seu sistema:

✅ O que fazer:

  1. Crie uma chave restrita no dashboard do PumaHelp
  2. Configure apenas a permissão: Criar Convidado (Guest)
  3. Use essa chave no widget
<!-- ✅ Correto: Chave restrita para widget -->
<puma-help-widget
app-name="minha-empresa"
api-key="rk_live_abc123xyz" <!-- Apenas permissão Guest -->
></puma-help-widget>

❌ O que NÃO fazer:

  • Nunca use chaves com permissões administrativas no widget
  • Nunca use chaves que podem:
    • Deletar tickets
    • Modificar configurações
    • Acessar dados de outros usuários
    • Executar operações privilegiadas

📘 Tipagem TypeScript

Para projetos TypeScript, crie o arquivo puma-widget.d.ts na raiz do seu projeto (ou em src/types/):

Arquivo de Tipos (puma-widget.d.ts)

import * as React from 'react';

// Atributos do Widget
interface PumaWidgetAttributes {
'app-name'?: string;
'api-key'?: string;
theme?: 'light' | 'dark';
language?: 'pt-BR' | 'en';
color?: string;
icon?: 'puma' | 'emoji' | 'question' | 'lines' | 'bell' | 'send';
'sound-enabled'?: string;
debug?: string;
translations?: string;
class?: string;
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
}

// Configuração do Widget
interface WidgetConfig {
appName: string;
apiKey: string;
theme?: 'light' | 'dark';
language?: 'pt-BR' | 'en';
color?: string;
icon?: 'puma' | 'emoji' | 'question' | 'lines' | 'bell' | 'send';
soundEnabled?: boolean;
debug?: boolean;
translations?: Translations;
}

// Traduções Customizáveis
interface Translations {
mainTitle?: string;
welcome?: string;
description?: string;
startNewChat?: string;
sendMessage?: string;
loading?: string;
endTicket?: string;
startedAt?: string;
[key: string]: string | undefined;
}

// Identidade do Usuário
interface UserIdentity {
accessToken: string;
name?: string;
}

// Instância do Widget
interface WidgetInstance {
id: string;
element: HTMLElement;
isOpen: boolean;
isHidden: boolean;
open(): void;
close(): void;
toggle(): void;
hide(): void;
show(): void;
destroy(): void;
identify(identity: UserIdentity): void;
logout(): void;
on(event: string, callback: (event: CustomEvent) => void): () => void;
}

// API Global
interface PumaHelpAPI {
init(config: WidgetConfig & { container?: HTMLElement }): WidgetInstance;
destroy(instanceId: string): boolean;
getInstances(): WidgetInstance[];
destroyAll(): void;
identify(identity: UserIdentity): void;
logout(): void;
}

// Declaração Global
declare global {
interface Window {
PumaHelp: PumaHelpAPI;
}

// Registro do Custom Element (DOM)
interface HTMLElementTagNameMap {
'puma-help-widget': HTMLElement & {
open(): void;
close(): void;
toggle(): void;
hide(): void;
show(): void;
destroy(): void;
};
}
}

// Declaração JSX para React/Next.js (React 18+)
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'puma-help-widget': PumaWidgetAttributes;
}
}
}

export {};

Uso em TypeScript

// Inicializar widget com tipagem
const widget: WidgetInstance = window.PumaHelp.init({
appName: 'minha-empresa',
apiKey: 'rk_live_xxxxx',
theme: 'dark',
language: 'pt-BR',
});

// Identificar usuário autenticado
window.PumaHelp.identify({
accessToken: user.token,
name: user.name,
});

// Escutar eventos com tipos
widget.on('ticket-created', (event: CustomEvent<{ ticketId: string }>) => {
console.log('Ticket criado:', event.detail.ticketId);
});

// Controlar widget
widget.open();
widget.close();
widget.toggle();

Uso em React

import { useEffect, useRef } from 'react';

// Tipo para a referência do widget
type WidgetRef = WidgetInstance | null;

function App() {
const widgetRef = useRef<WidgetRef>(null);

useEffect(() => {
// Inicializar widget
widgetRef.current = window.PumaHelp.init({
appName: 'minha-empresa',
apiKey: 'rk_live_xxxxx',
});

// Cleanup
return () => {
widgetRef.current?.destroy();
};
}, []);

// Identificar usuário quando logar
const handleLogin = (user: { token: string; name: string }) => {
window.PumaHelp.identify({
accessToken: user.token,
name: user.name,
});
};

return <button onClick={() => widgetRef.current?.open()}>Abrir Suporte</button>;
}

🎨 Customização de CSS com ::part()

O widget utiliza Shadow DOM para isolamento completo de estilos, mas expõe CSS Parts específicos que permitem customização visual controlada usando o pseudo-elemento ::part().

Parts Disponíveis

Part NameElementoDescrição
puma-widget-wrapperContainer PrincipalWrapper externo do widget inteiro
puma-widget-contentContainer do ConteúdoContainer da janela do chat (quando aberto)
puma-widget-triggerBotão de AcionamentoBotão flutuante que abre/fecha o widget
puma-widget-tickets-listLista de TicketsContainer da lista de conversas
puma-widget-first-ticket-formFormulário InicialFormulário de criação de novo ticket
puma-widget-ticket-chatChat de TicketVisualização de conversa ativa
puma-widget-message-itemItem de MensagemContainer de cada mensagem individual (agente ou usuário)
puma-widget-message-item-agentMensagem do AgenteMensagem enviada por um agente de suporte
puma-widget-message-item-userMensagem do UsuárioMensagem enviada pelo usuário final

Como Usar

Use o seletor ::part() no seu CSS para customizar os elementos expostos do widget:

/* Customizar o botão do widget */
puma-help-widget::part(puma-widget-trigger) {
/* Seus estilos customizados */
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}

/* Customizar a janela do chat */
puma-help-widget::part(puma-widget-content) {
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}

/* Customizar o wrapper principal */
puma-help-widget::part(puma-widget-wrapper) {
/* Posicionamento, z-index, etc */
z-index: 99999;
}

Exemplos Práticos

Exemplo 1: Botão com Estilo Personalizado

puma-help-widget::part(puma-widget-trigger) {
/* Adicionar uma borda */
border: 3px solid #fff;

/* Sombra customizada */
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);

/* Aumentar tamanho */
transform: scale(1.1);
}

/* Hover state */
puma-help-widget::part(puma-widget-trigger):hover {
transform: scale(1.2);
}

Exemplo 2: Janela de Chat Customizada

puma-help-widget::part(puma-widget-content) {
/* Bordas arredondadas diferentes */
border-radius: 20px 20px 0 0;

/* Sombra mais pronunciada */
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);

/* Altura customizada */
max-height: 600px;
}

Exemplo 3: Lista de Tickets com Fundo Customizado

puma-help-widget::part(puma-widget-tickets-list) {
/* Padrão de fundo */
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.05) 25%,
transparent 25%
);
}

Exemplo 4: Customizar Mensagens Individuais

/* Estilizar todas as mensagens */
puma-help-widget::part(puma-widget-message-item) {
/* Adicionar animação de entrada */
animation: slideIn 0.3s ease-out;
}

/* Estilizar apenas mensagens do agente */
puma-help-widget::part(puma-widget-message-item-agent) {
/* Espaçamento customizado */
margin-bottom: 12px;

/* Efeito de destaque */
position: relative;
}

/* Estilizar apenas mensagens do usuário */
puma-help-widget::part(puma-widget-message-item-user) {
/* Espaçamento customizado */
margin-bottom: 12px;
}

@keyframes slideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

Customização de Tema via CSS Variables

Você pode customizar todas as cores e variáveis do widget usando ::part() no wrapper principal.

Formato HSL (Compatível com Tailwind)

O widget usa internamente o formato HSL sem vírgulas (H S% L%) para compatibilidade com classes de opacidade do Tailwind:

puma-help-widget::part(puma-widget-wrapper) {
--primary: 220 90% 56%; /* Azul */
--background: 0 0% 100%; /* Branco */
--foreground: 222 47% 11%; /* Texto escuro */
--muted: 210 40% 96%; /* Cinza claro */
--border: 214 32% 91%; /* Bordas */
}

Formato HEX (Mais Simples)

Você também pode usar cores em formato HEX diretamente:

puma-help-widget::part(puma-widget-wrapper) {
--primary: #3b82f6; /* Azul */
--primary-foreground: #ffffff; /* Branco */
--background: #ffffff; /* Fundo branco */
--foreground: #1f2937; /* Texto escuro */
--muted: #f3f4f6; /* Cinza claro */
--muted-foreground: #6b7280; /* Texto secundário */
--secondary: #e5e7eb; /* Bubbles do agente */
--secondary-foreground: #1f2937; /* Texto nas bubbles */
--border: #e5e7eb; /* Bordas */
--input: #e5e7eb; /* Fundo de inputs */
--ring: #3b82f6; /* Cor do foco */
--destructive: #ef4444; /* Erros */
}

CSS Variables Disponíveis

VariávelDescriçãoExemplo HEX
--primaryCor principal (botões, destaques)#3b82f6
--primary-foregroundTexto sobre cor primária#ffffff
--backgroundFundo do widget#ffffff
--foregroundCor do texto principal#1f2937
--mutedFundo de elementos secundários#f3f4f6
--muted-foregroundTexto secundário#6b7280
--secondaryBubbles do agente#e5e7eb
--secondary-foregroundTexto nas bubbles do agente#1f2937
--borderCor das bordas#e5e7eb
--inputFundo de inputs#e5e7eb
--ringCor do foco#3b82f6
--destructiveErros e alertas#ef4444
--radiusRaio de bordas0.5rem

Exemplos de Temas

Tema Azul Corporativo (HEX):

puma-help-widget::part(puma-widget-wrapper) {
--primary: #2563eb;
--primary-foreground: #ffffff;
--background: #ffffff;
--foreground: #1e293b;
--muted: #f1f5f9;
--muted-foreground: #64748b;
--border: #e2e8f0;
}

Tema Roxo Escuro (HEX):

puma-help-widget::part(puma-widget-wrapper) {
--primary: #8b5cf6;
--primary-foreground: #ffffff;
--background: #1e1b2e;
--foreground: #f5f3ff;
--muted: #2e2942;
--muted-foreground: #a5a0c2;
--secondary: #362f50;
--secondary-foreground: #f5f3ff;
--border: #362f50;
}

Tema Verde Natureza (HEX):

puma-help-widget::part(puma-widget-wrapper) {
--primary: #22c55e;
--primary-foreground: #ffffff;
--background: #0f1a14;
--foreground: #ecfdf5;
--muted: #1a2e23;
--muted-foreground: #86efac;
--border: #1a2e23;
}

Estilos Diferentes para Light e Dark Mode

Use seletores de atributo para aplicar estilos diferentes baseado no tema:

/* Estilos para Light Mode */
puma-help-widget[theme="light"]::part(puma-widget-wrapper) {
--primary: #2563eb;
--background: #ffffff;
--foreground: #1f2937;
--muted: #f3f4f6;
--border: #e5e7eb;
}

puma-help-widget[theme="light"]::part(puma-widget-content) {
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
}

/* Estilos para Dark Mode */
puma-help-widget[theme="dark"]::part(puma-widget-wrapper) {
--primary: #3b82f6;
--background: #111827;
--foreground: #f9fafb;
--muted: #1f2937;
--border: #374151;
}

puma-help-widget[theme="dark"]::part(puma-widget-content) {
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.1);
}

puma-help-widget[theme="dark"]::part(puma-widget-trigger) {
border: 2px solid rgba(255, 255, 255, 0.2);
}

Limitações

important

Os ::part() permitem estilizar os elementos expostos e customizar CSS Variables. Porém, não é possível acessar elementos internos não expostos.

O que você PODE fazer:

  • ✅ Modificar layout, posicionamento, dimensões
  • ✅ Adicionar bordas, sombras, fundos
  • ✅ Aplicar transformações
  • ✅ Ajustar opacidade, visibilidade
  • Customizar todas as cores do tema via CSS Variables

O que você NÃO PODE fazer:

  • ❌ Estilizar elementos filhos dentro dos parts
  • ❌ Acessar elementos internos não expostos
  • ❌ Sobrescrever completamente a estrutura do widget

Compatibilidade

O ::part() é suportado em todos os navegadores modernos:

  • ✅ Chrome/Edge 73+
  • ✅ Firefox 72+
  • ✅ Safari 13.1+
  • ✅ Opera 60+

Para navegadores mais antigos, os estilos customizados são simplesmente ignorados (graceful degradation).

Combinando com Props de Configuração

Você pode combinar ::part() com as propriedades de configuração para máxima flexibilidade:

<!-- HTML -->
<puma-help-widget
app-name="acme"
api-key="key-abc123"
theme="dark"
color="#2563eb"
></puma-help-widget>
/* CSS */
puma-help-widget::part(puma-widget-trigger) {
/* Customizações adicionais além da cor primária */
border: 2px solid rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
}

📋 Métodos da API

Todos os métodos disponíveis na instância do widget:

Métodos de Controle

const widget = window.PumaHelp.init({ /* config */ });

// Abrir/fechar widget
widget.open(); // Abre a interface do chat
widget.close(); // Fecha a interface do chat
widget.toggle(); // Alterna entre aberto/fechado

// Mostrar/ocultar botão do widget
widget.hide(); // Oculta o botão do widget
widget.show(); // Mostra o botão do widget

// Verificar estado
console.log(widget.isOpen); // boolean
console.log(widget.isHidden); // boolean

Métodos de Autenticação

// Identificar usuário autenticado
widget.identify({
accessToken: 'seu-jwt-token', // Obrigatório
name: 'João Silva' // Opcional (recomendado)
});

// Logout (retorna ao modo visitante)
widget.logout();

Métodos de Ciclo de Vida

// Destruir instância única
widget.destroy();

// Destruir todos os widgets na página
window.PumaHelp.destroyAll();

Listener de Eventos

// Ouvir eventos
const unsubscribe = widget.on('ticket-created', (event) => {
console.log('ID do Ticket:', event.detail.ticketId);
});

// Parar de ouvir
unsubscribe();

🎧 Referência de Eventos

Inscreva-se em eventos do widget para rastrear interações do usuário:

Eventos de Ciclo de Vida

EventoPayloadDescrição
ready-Widget inicializado e pronto
error{ error, message }Ocorreu um erro
destroy-Widget destruído

Eventos de Estado

EventoPayloadDescrição
open-Widget aberto
close-Widget fechado
hide-Botão do widget oculto
show-Botão do widget mostrado
toggle-Widget aberto/fechado

Eventos de Ação do Usuário

EventoPayloadDescrição
ticket-created{ payload }Novo ticket criado (objeto completo do ticket)
ticket-updated{ payload: { ticketPublicId, comment: { body } } }Ticket atualizado (mensagem enviada)

Exemplos de payload:

widget.on('ticket-created', (event) => {
const { payload } = event.detail;
// Objeto completo do ticket da API
console.log(payload.public_id);
console.log(payload.subject);
console.log(payload.status);
console.log(payload.created_at);
});

widget.on('ticket-updated', (event) => {
const { payload } = event.detail;
console.log(payload.ticketPublicId);
console.log(payload.comment.body);
});

Eventos de Autenticação

EventoPayloadDescrição
auth-error{ code, message, canRetry }Erro de autenticação (ex: token expirado)

Eventos de Interceptação de Payload (Avançado)

EventoPayloadDescrição
before-ticket-create{ payload }Interceptar/modificar dados do ticket antes da criação
before-ticket-update{ payload }Interceptar/modificar dados antes de atualizar ticket

Exemplos de Eventos

const widget = window.PumaHelp.init({ /* config */ });

// Rastrear quando usuários criam tickets
widget.on('ticket-created', (event) => {
const { ticketId, subject } = event.detail;
analytics.track('Ticket de Suporte Criado', { ticketId, subject });
});

// Lidar com expiração de token
widget.on('auth-error', async (event) => {
if (event.detail.canRetry) {
const newToken = await refreshUserToken();
widget.identify({ accessToken: newToken });
}
});

// Rastrear uso do widget
widget.on('open', () => {
analytics.track('Widget Aberto');
});

🎨 Interceptores de Payload (Avançado)

Modifique dados do ticket/mensagem antes de enviar ao servidor:

Antes de Criar Ticket

widget.on('before-ticket-create', (event) => {
// Adicionar tags personalizadas
event.detail.payload.tags = ['vip', user.plan];

// Modificar assunto
const prefix = user.isPremium ? '[VIP]' : '';
event.detail.payload.subject = `${prefix} ${event.detail.payload.subject}`;
});

Estrutura do payload:

{
subject: string;
comment: { body: string };
via: { channel: 'widget' };
tags?: string[];
}

Antes de Atualizar Ticket (Enviar Mensagem)

widget.on('before-ticket-update', (event) => {
// Adicionar informações de rastreamento
const original = event.detail.payload.comment.body;
event.detail.payload.comment.body = `${original}\n\n<!-- session: ${sessionId} -->`;
});

Estrutura do payload:

{
comment: { body: string };
}

Casos de uso:

  • Adicionar tags dinâmicas baseadas no contexto do usuário
  • Incluir metadados para analytics
  • Rastrear contexto da conversa

🔐 Autenticação de Usuário

Padrão Recomendado

Separe configuração da autenticação:

// 1. Inicializar widget no carregamento da página (config estática)
window.PumaHelp.init({
appName: 'acme',
apiKey: 'key-abc123'
});

// 2. Identificar usuário quando fizer login (auth dinâmica)
function onUserLogin(user) {
window.PumaHelp.identify({
accessToken: user.jwtToken,
name: user.fullName // Recomendado para fallback de visitante
});
}

// 3. Logout quando o usuário sair
function onUserLogout() {
window.PumaHelp.logout(); // Widget continua no modo visitante
}

Tratamento de Expiração de Token

Trate erros de autenticação quando o token expirar:

const widget = window.PumaHelp.init({ /* config */ });

widget.on('auth-error', async (event) => {
const { code, message, canRetry } = event.detail;

if (canRetry) {
try {
// Renovar token via seu backend
const newToken = await fetch('/api/auth/refresh').then(r => r.json());

// Atualizar widget com novo token
widget.identify({
accessToken: newToken.accessToken,
name: currentUser.name
});
} catch (error) {
// Não conseguiu renovar - redirecionar para login
window.location.href = '/login?expired=true';
}
}
});

🌐 Integração com Frameworks

React

import { useEffect, useRef } from 'react';

function App() {
const widgetRef = useRef(null);

useEffect(() => {
const widget = widgetRef.current;
if (!widget) return;

// Ouvir eventos
const unsubscribe = widget.addEventListener('ready', () => {
console.log('Widget pronto!');
});

return () => widget.removeEventListener('ready', unsubscribe);
}, []);

return (
<puma-help-widget
ref={widgetRef}
app-name="acme"
api-key="key-abc123"
theme="dark"
/>
);
}

Vue 3

<template>
<puma-help-widget
ref="widget"
app-name="acme"
api-key="key-abc123"
@ready="onReady"
@ticket-created="onTicketCreated"
/>
</template>

<script setup>
import { ref } from 'vue';

const widget = ref(null);

const onReady = () => {
console.log('Widget pronto!');
};

const onTicketCreated = (event) => {
console.log('Ticket:', event.detail.ticketId);
};
</script>

Angular

import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';

@Component({
selector: 'app-root',
template: `
<puma-help-widget
#widget
app-name="acme"
api-key="key-abc123"
></puma-help-widget>
`
})
export class AppComponent implements AfterViewInit {
@ViewChild('widget') widget!: ElementRef;

ngAfterViewInit() {
const el = this.widget.nativeElement;
el.addEventListener('ready', () => {
console.log('Widget pronto!');
});
}
}

🎯 Casos de Uso Comuns

Abrir widget programaticamente

// De um botão
document.getElementById('help-btn').addEventListener('click', () => {
const widget = document.querySelector('puma-help-widget');
widget.open();
});

// Ou com a API JavaScript
const widget = window.PumaHelp.init({ /* config */ });
widget.open();

Rastrear analytics

const widget = window.PumaHelp.init({ /* config */ });

widget.on('ticket-created', (e) => {
gtag('event', 'ticket_suporte_criado', {
ticket_id: e.detail.ticketId
});
});

widget.on('open', () => {
gtag('event', 'widget_aberto');
});

Aplicações multi-página (SPAs)

// Na mudança de rota, destruir e recriar se necessário
function onRouteChange(route) {
if (route === '/contato') {
// Criar widget para a página de contato
window.PumaHelp.init({ /* config */ });
} else {
// Remover de outras páginas
window.PumaHelp.destroyAll();
}
}

🐛 Debug

Habilite o modo debug para ver logs do widget:

window.PumaHelp.init({
appName: 'acme',
apiKey: 'key-abc123',
debug: true // Loga todos os eventos e mudanças de estado
});

Ou use o atributo HTML:

<puma-help-widget
app-name="acme"
api-key="key-abc123"
debug
></puma-help-widget>

🔊 Notificações Sonoras

O widget reproduz notificações de áudio para interações do usuário:

Tipos de Som:

  • Som de Envio: Reproduzido quando você envia uma mensagem ou cria um ticket
  • Som de Recebimento: Reproduzido quando um agente responde ao seu ticket

Configuração:

// Habilitar sons (padrão)
window.PumaHelp.init({
appName: 'acme',
apiKey: 'key-abc123',
soundEnabled: true
});

// Desabilitar sons
window.PumaHelp.init({
appName: 'acme',
apiKey: 'key-abc123',
soundEnabled: false
});

Atributo HTML:

<!-- Habilitar sons -->
<puma-help-widget
app-name="acme"
api-key="key-abc123"
sound-enabled
></puma-help-widget>

<!-- Desabilitar sons -->
<puma-help-widget
app-name="acme"
api-key="key-abc123"
sound-enabled="false"
></puma-help-widget>

Notas:

  • Sons respeitam as políticas de autoplay do navegador
  • Volume é otimizado automaticamente (envio: 50%, recebimento: 30%)
  • Sons são carregados do CDN e funcionam tanto em desenvolvimento quanto em produção

📎 Anexos de Arquivos

O widget suporta anexos de arquivos tanto no formulário "Nova Conversa" quanto na visualização do chat ativo.

Recursos:

  • Botão de Upload: Usuários podem clicar no ícone de clipe de papel para selecionar arquivos de seu dispositivo.
  • Copiar/Colar: Usuários podem colar imagens diretamente da área de transferência (Ctrl+V) na área de entrada de mensagem.
  • Múltiplos Arquivos: Múltiplos arquivos podem ser anexados e enviados em uma única mensagem.
  • Pré-visualização: Arquivos anexados são mostrados em uma lista de pré-visualização onde podem ser removidos antes do envio.

❓ Perguntas Frequentes

P: Posso ter múltiplos widgets em uma página?
R: Sim! Cada chamada de init() ou elemento <puma-help-widget> cria uma instância separada.

P: Como personalizo a aparência do widget?
R: Você tem duas opções:

  1. Configuração básica: Use as props theme, color e icon para customizações rápidas.
  2. Customização avançada: Use CSS Parts com ::part() para estilizar elementos específicos (veja seção "Customização de CSS com ::part()").

P: Posso modificar o CSS do widget?
R: Sim! O widget expõe CSS Parts que podem ser estilizados usando ::part(). Você pode customizar elementos como o botão (puma-widget-trigger), janela do chat (puma-widget-content), lista de tickets, e mais. Veja a documentação completa na seção "Customização de CSS com ::part()".

P: O que acontece quando um usuário faz logout?
R: Chame widget.logout() para limpar a autenticação. O widget continua funcionando no modo visitante.

P: Como lidar com expiração de token?
R: Ouça o evento auth-error e renove o token via widget.identify().

P: Posso modificar dados do ticket antes de enviar?
R: Sim! Use os eventos before-ticket-create ou before-ticket-update.


Versão: 2.1.0
Última Atualização: Dezembro 2025