npm package: @feedget/widget
Description: Widget de feedback integrado à API Feedget para coleta de feedback de usuários em aplicações web
Author: Feedget
Latest version: 1.3.0

# @feedget/widget

<div align="center">

![Feedget Logo](https://feedget.io/logo.svg)

**Widget de feedback inteligente e multi-plataforma para aplicações web**

[![npm version](https://img.shields.io/npm/v/@feedget/widget.svg)](https://www.npmjs.com/package/@feedget/widget)
[![npm downloads](https://img.shields.io/npm/dm/@feedget/widget.svg)](https://www.npmjs.com/package/@feedget/widget)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)

[Demo](https://feedget.io) · [Documentação](https://feedget.io/docs) · [Reportar Bug](hello@feedget.io) · [Solicitar Feature](hello@feedget.io)

</div>

---

## Sobre o Feedget Widget

O **Feedget Widget** é uma biblioteca JavaScript/TypeScript moderna e leve que permite coletar feedbacks de usuários diretamente em sua aplicação web. Com suporte nativo para **React**, **Angular** e **Vanilla JavaScript**, o widget oferece uma experiência de usuário fluida e profissional.

### Por que escolher o Feedget Widget?

- **Multi-plataforma**: Funciona com React, Angular e Vanilla JS
- **TypeScript First**: Tipagem completa incluída
- **Captura de Screenshots**: Integração automática com html2canvas
- **Análise Inteligente**: Feedback enviado para análise de sentimento via API
- **Zero Configuração**: Funciona out-of-the-box com configurações sensatas
- **Leve e Rápido**: Bundle otimizado < 50KB gzipped
- **Totalmente Customizável**: Posicionamento, tema e metadata personalizáveis
- **Acessível**: Componentes acessíveis e responsivos

---

## Demonstração

<div align="center">
  <img src="https://feedget.io/demo.gif" alt="Feedget Widget Demo" width="600">
</div>

> **Nota:** Adicione um GIF ou screenshot do widget em ação para melhor visualização.

---

## Instalação

### Via NPM

```bash
npm install @feedget/widget
```

### Via Yarn

```bash
yarn add @feedget/widget
```

### Via pnpm

```bash
pnpm add @feedget/widget
```

---

## Início Rápido

### React

```tsx
import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

function App() {
  return (
    <div>
      <h1>Minha Aplicação</h1>

      <FeedgetWidget
        apiKey="feedget_pk_live_abc123..."
        apiUrl="https://api.feedget.io"
      />
    </div>
  );
}

export default App;
```

### Angular

```typescript
// app.component.ts
import { Component, OnInit, OnDestroy } from "@angular/core";
import {
  createFeedgetWidget,
  FeedgetWidgetAngular,
} from "@feedget/widget/angular";
import "@feedget/widget/styles.css";

@Component({
  selector: "app-root",
  template: '<div id="app">Minha Aplicação</div>',
})
export class AppComponent implements OnInit, OnDestroy {
  private widget: FeedgetWidgetAngular | null = null;

  ngOnInit() {
    this.widget = createFeedgetWidget({
      apiKey: "feedget_pk_live_abc123...",
      apiUrl: "https://api.feedget.io",
    });

    this.widget.mount();
  }

  ngOnDestroy() {
    this.widget?.unmount();
  }
}
```

### Vanilla JavaScript

```javascript
import { Feedget } from "@feedget/widget/vanilla";
import "@feedget/widget/styles.css";

Feedget.init({
  apiKey: "feedget_pk_live_abc123...",
  apiUrl: "https://api.feedget.io",
});
```

---

## Funcionalidades

### Core Features

- **Tipos de Feedback**: Suporte para BUG, IDEA e OTHER
- **Captura de Screenshots**: Captura automática da tela com html2canvas
- **Validação de Entrada**: Comentários entre 10-1000 caracteres
- **Metadata Automática**: Coleta automática de URL, User Agent e Viewport
- **Rate Limiting**: Proteção contra spam (100 req/min por API key)
- **Tratamento de Erros**: Mensagens de erro específicas e amigáveis
- **Loading States**: Indicadores de carregamento durante envio

### Segurança

- **API Key Authentication**: Autenticação segura via API keys
- **HTTPS Only**: Comunicação criptografada obrigatória
- **Input Sanitization**: Proteção contra XSS e injeção
- **CORS Support**: Configuração adequada de CORS

### UI/UX

- **Interface Responsiva**: Funciona perfeitamente em desktop e mobile
- **Posicionamento Fixo**: Widget sempre visível no canto da tela
- **Animações Suaves**: Transições e animações fluidas
- **Dark Mode Ready**: Suporte a temas claro e escuro (em breve)
- **Acessibilidade**: Seguindo padrões WCAG 2.1

---

## Configuração Detalhada

### Propriedades do Widget

| Propriedade | Tipo     | Obrigatório | Descrição                                      |
| ----------- | -------- | ----------- | ---------------------------------------------- |
| `apiKey`    | `string` | Sim         | API Key obtida no dashboard Feedget            |
| `apiUrl`    | `string` | Não         | URL da API (default: `https://api.feedget.io`) |
| `metadata`  | `object` | Não         | Metadata customizada para enviar com feedbacks |

### Exemplo com Todas as Opções

```tsx
<FeedgetWidget
  apiKey="feedget_pk_live_abc123..."
  apiUrl="https://api.feedget.io"
  metadata={{
    // Identificação do usuário
    userId: "user-123",
    userEmail: "user@example.com",

    // Informações da aplicação
    version: "1.0.0",
    environment: "production",

    // Dados customizados
    custom: {
      plan: "premium",
      feature: "checkout",
      sessionId: "sess_xyz789",
    },
  }}
/>
```

---

## Guia de Integração por Framework

### React (Create React App / Vite / Next.js)

#### Create React App

```tsx
// src/App.tsx
import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

function App() {
  return (
    <>
      {/* Seu conteúdo */}
      <FeedgetWidget
        apiKey={process.env.REACT_APP_FEEDGET_API_KEY!}
        apiUrl={process.env.REACT_APP_FEEDGET_API_URL}
      />
    </>
  );
}
```

#### Next.js (App Router)

```tsx
// app/layout.tsx
"use client";

import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="pt-BR">
      <body>
        {children}
        <FeedgetWidget
          apiKey={process.env.NEXT_PUBLIC_FEEDGET_API_KEY!}
          apiUrl={process.env.NEXT_PUBLIC_FEEDGET_API_URL}
        />
      </body>
    </html>
  );
}
```

#### Next.js (Pages Router)

```tsx
// pages/_app.tsx
import type { AppProps } from "next/app";
import { FeedgetWidget } from "@feedget/widget/react";
import "@feedget/widget/styles.css";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <FeedgetWidget
        apiKey={process.env.NEXT_PUBLIC_FEEDGET_API_KEY!}
        apiUrl={process.env.NEXT_PUBLIC_FEEDGET_API_URL}
      />
    </>
  );
}
```

#### Vite

```tsx
// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "@feedget/widget/styles.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```

```tsx
// src/App.tsx
import { FeedgetWidget } from "@feedget/widget/react";

function App() {
  return (
    <>
      {/* Seu conteúdo */}
      <FeedgetWidget
        apiKey={import.meta.env.VITE_FEEDGET_API_KEY}
        apiUrl={import.meta.env.VITE_FEEDGET_API_URL}
      />
    </>
  );
}
```

### Angular

#### Módulo Principal

```typescript
// app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

#### Componente

```typescript
// app.component.ts
import { Component, OnInit, OnDestroy } from "@angular/core";
import {
  createFeedgetWidget,
  FeedgetWidgetAngular,
  FeedgetConfig,
} from "@feedget/widget/angular";

@Component({
  selector: "app-root",
  template: `
    <div id="app">
      <h1>Minha Aplicação Angular</h1>
    </div>
  `,
  styleUrls: ["./app.component.scss"],
})
export class AppComponent implements OnInit, OnDestroy {
  private widget: FeedgetWidgetAngular | null = null;

  ngOnInit() {
    const config: FeedgetConfig = {
      apiKey: "feedget_pk_live_abc123...",
      apiUrl: "https://api.feedget.io",
      metadata: {
        userId: "user-123",
        version: "1.0.0",
      },
    };

    this.widget = createFeedgetWidget(config);
    this.widget.mount();
  }

  ngOnDestroy() {
    if (this.widget) {
      this.widget.unmount();
    }
  }
}
```

#### Estilos Globais

```scss
// styles.scss
@import "@feedget/widget/styles.css";
```

### Vanilla JavaScript

#### Com Módulos ES6

```javascript
// main.js
import { Feedget } from "@feedget/widget/vanilla";
import "@feedget/widget/styles.css";

// Inicializar quando o DOM estiver pronto
document.addEventListener("DOMContentLoaded", () => {
  Feedget.init({
    apiKey: "feedget_pk_live_abc123...",
    apiUrl: "https://api.feedget.io",
    metadata: {
      userId: getUserId(), // Função customizada
      version: "1.0.0",
    },
  });
});

// Para destruir o widget (cleanup)
window.addEventListener("beforeunload", () => {
  Feedget.destroy();
});
```

#### Via CDN (Experimental)

```html
<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Meu Site</title>

    <!-- Estilos do Widget -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/@feedget/widget@latest/dist/style.css"
    />
  </head>
  <body>
    <h1>Meu Site</h1>

    <!-- Widget Script -->
    <script type="module">
      import { Feedget } from "https://unpkg.com/@feedget/widget@latest/dist/vanilla.js";

      Feedget.init({
        apiKey: "feedget_pk_live_abc123...",
        apiUrl: "https://api.feedget.io",
      });
    </script>
  </body>
</html>
```

---

## API Reference

### React Component Props

```typescript
interface FeedgetWidgetProps {
  apiKey: string;
  apiUrl?: string;
  metadata?: {
    userId?: string;
    userEmail?: string;
    version?: string;
    environment?: string;
    custom?: Record<string, any>;
  };
}
```

### Angular Config

```typescript
interface FeedgetConfig {
  apiKey: string;
  apiUrl?: string;
  metadata?: FeedgetMetadata;
}

interface FeedgetWidgetAngular {
  mount(container?: HTMLElement): void;
  unmount(): void;
  updateConfig(config: Partial<FeedgetConfig>): void;
}
```

### Vanilla JS API

```typescript
interface FeedgetVanilla {
  init(config: FeedgetConfig): void;
  destroy(): void;
  updateConfig(config: Partial<FeedgetConfig>): void;
}
```

---

## Integração com a API Feedget

### Endpoint do Widget

O widget envia feedbacks para:

```
POST https://api.feedget.io/public/feedbacks
```

**Headers:**

```
X-API-Key: feedget_pk_live_abc123...
Content-Type: application/json
```

**Payload:**

```json
{
  "type": "BUG" | "IDEA" | "OTHER",
  "comment": "Descrição do feedback...",
  "screenshot": "data:image/png;base64,iVBOR...",
  "metadata": {
    "url": "https://meusite.com/page",
    "userAgent": "Mozilla/5.0...",
    "viewport": {
      "width": 1920,
      "height": 1080
    },
    "custom": {
      "userId": "user-123",
      "version": "1.0.0"
    }
  }
}
```

### Códigos de Status HTTP

| Código | Descrição                                      |
| ------ | ---------------------------------------------- |
| `200`  | Feedback enviado com sucesso                   |
| `400`  | Dados inválidos (comentário muito curto/longo) |
| `401`  | API key inválida ou expirada                   |
| `403`  | Assinatura necessária ou inativa               |
| `429`  | Rate limit excedido (100 req/min)              |
| `500`  | Erro interno do servidor                       |

---

## Customização Avançada

### Posicionamento do Widget

Por padrão, o widget fica fixo no **canto inferior esquerdo** da tela.

**CSS Customizado:**

```css
/* Ajustar posicionamento */
.feedget-widget-container {
  bottom: 32px;
  left: 32px;
  /* ou right: 32px para canto direito */
}

/* Mobile */
@media (max-width: 768px) {
  .feedget-widget-container {
    bottom: 16px;
    left: 16px;
  }
}
```

### Temas

```css
/* Customizar cores do widget */
:root {
  --feedget-primary: #8257e6;
  --feedget-secondary: #996dff;
  --feedget-text: #27272a;
  --feedget-bg: #ffffff;
  --feedget-border: #e4e4e7;
}

/* Dark mode */
[data-theme="dark"] {
  --feedget-text: #fafafa;
  --feedget-bg: #18181b;
  --feedget-border: #3f3f46;
}
```

---

## Troubleshooting

### Widget não aparece na tela

**Problema:** Widget não é renderizado

**Soluções:**

1. Certifique-se de importar o CSS:

   ```tsx
   import "@feedget/widget/styles.css";
   ```

2. Verifique se a API Key está configurada:

   ```tsx
   apiKey = "feedget_pk_live_..."; // não vazio
   ```

3. Verifique o console do navegador para erros

4. Confirme que a assinatura está ativa

### Erro 401: Unauthorized

**Problema:** API key inválida ou expirada

**Soluções:**

1. Gere uma nova API key no dashboard Feedget
2. Verifique se a key começa com `feedget_pk_`
3. Confirme se a key não está expirada
4. Verifique se a assinatura está ativa

### Erro 403: Forbidden

**Problema:** Assinatura inativa ou limite excedido

**Soluções:**

1. Verifique status da assinatura no dashboard
2. Confirme método de pagamento
3. Verifique se o limite mensal foi atingido
4. Entre em contato com o suporte

### Erro 429: Too Many Requests

**Problema:** Rate limit excedido (100 req/min)

**Soluções:**

1. Aguarde 1 minuto antes de tentar novamente
2. Implemente debounce no lado do cliente
3. Para produção, considere upgrade do plano
4. Entre em contato para ajuste de limites

### Screenshots não são capturados

**Problema:** html2canvas não funciona

**Soluções:**

1. Verifique CORS das imagens externas
2. Confirme que html2canvas foi instalado:
   ```bash
   npm list html2canvas
   ```
3. Algumas imagens podem não ser capturadas por política CORS
4. Teste em diferentes navegadores

### Problemas de TypeScript

**Problema:** Erros de tipagem

**Soluções:**

```json
// tsconfig.json
{
  "compilerOptions": {
    "moduleResolution": "bundler", // ou "node"
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
```

### Widget conflita com outros componentes

**Problema:** z-index ou posicionamento

**Soluções:**

```css
/* Ajuste o z-index do widget */
.feedget-widget-container {
  z-index: 9999 !important;
}

/* Ou dos elementos conflitantes */
.seu-modal {
  z-index: 10000;
}
```

---

## FAQ

### Quanto custa usar o Feedget?

O Feedget oferece planos gratuitos e pagos. Visite [feedget.io/pricing](https://feedget.io/pricing) para mais detalhes.

### O widget funciona em todos os navegadores?

Sim, o widget é compatível com:

- Chrome/Edge (últimas 2 versões)
- Firefox (últimas 2 versões)
- Safari 13+
- Opera (última versão)

### Posso usar em aplicações mobile?

Sim, o widget é totalmente responsivo. Para apps mobile nativos, aguarde nosso SDK React Native.

### Os dados dos feedbacks ficam onde?

Os feedbacks são armazenados de forma segura nos servidores da Feedget, com criptografia em repouso e em trânsito. Conformidade com GDPR e LGPD.

### Posso self-host a API?

Atualmente não oferecemos versão self-hosted. Entre em contato para planos enterprise.

### O widget afeta a performance do site?

Não. O widget é carregado de forma assíncrona e tem um bundle otimizado < 50KB gzipped. Impacto mínimo na performance.

### Posso customizar o visual do widget?

Sim, você pode customizar cores, posicionamento e tema via CSS. Suporte a temas customizados completos em breve.

---

## Segurança

### Relatando Vulnerabilidades

Se você encontrar uma vulnerabilidade de segurança, por favor **NÃO** abra uma issue pública.

Envie um email para: **hello@feedget.io**

### Práticas de Segurança

- ✅ Use HTTPS em produção
- ✅ Armazene API keys em variáveis de ambiente
- ✅ Nunca commite API keys no código
- ✅ Rotacione API keys periodicamente
- ✅ Use diferentes keys para dev/staging/prod
- ✅ Configure CSP headers adequadamente

**Content Security Policy:**

```
Content-Security-Policy:
  connect-src 'self' https://api.feedget.io;
  img-src 'self' data: https://api.feedget.io;
```

---

## Contribuindo

Contribuições são bem-vindas! Por favor, leia nosso [Guia de Contribuição](CONTRIBUTING.md) antes de submeter PRs.

### Como Contribuir

1. **Fork** o repositório
2. **Clone** seu fork:
   ```bash
   git clone https://github.com/seu-usuario/widget.git
   ```
3. **Crie uma branch** para sua feature:
   ```bash
   git checkout -b feature/minha-feature
   ```
4. **Commit** suas mudanças:
   ```bash
   git commit -m 'feat: adiciona minha feature'
   ```
5. **Push** para a branch:
   ```bash
   git push origin feature/minha-feature
   ```
6. **Abra um Pull Request**

### Padrão de Commits

Usamos [Conventional Commits](https://www.conventionalcommits.org/):

- `feat:` Nova funcionalidade
- `fix:` Correção de bug
- `docs:` Mudanças na documentação
- `style:` Formatação, ponto-e-vírgula, etc
- `refactor:` Refatoração de código
- `test:` Adição de testes
- `chore:` Manutenção

---

## Roadmap

- [x] Suporte React
- [x] Suporte Angular
- [x] Suporte Vanilla JS
- [x] Captura de screenshots
- [x] TypeScript completo
- [ ] Dark mode nativo
- [ ] Temas customizáveis
- [ ] Suporte Vue.js
- [ ] Suporte Svelte
- [ ] React Native SDK
- [ ] Flutter SDK
- [ ] Internacionalização (i18n)
- [ ] Acessibilidade WCAG 2.1 AA
- [ ] Webhooks customizáveis

---

## Licença

Este projeto está licenciado sob a [Licença MIT](LICENSE).

---

## Suporte

### Documentação

- **Documentação Completa:** [docs.feedget.io](https://docs.feedget.io)
- **Guia de API:** [docs.feedget.io/api](https://docs.feedget.io/api)
- **Exemplos:** [github.com/feedget/examples](https://github.com/feedget/examples)

### Comunidade

- **Discord:** [discord.gg/feedget](https://discord.gg/feedget)
- **Twitter:** [@feedget](https://twitter.com/feedget)
- **GitHub Issues:** [github.com/feedget/widget/issues](https://github.com/feedget/widget/issues)

### Contato Direto

- **Email:** hello@feedget.io
- **Chat:** [feedget.io/support](https://feedget.io/support)

---

## Créditos

Desenvolvido e mantido por [Feedget Team](https://feedget.io/team)

### Tecnologias Utilizadas

- [React](https://react.dev/)
- [TypeScript](https://www.typescriptlang.org/)
- [Vite](https://vitejs.dev/)
- [Tailwind CSS](https://tailwindcss.com/)
- [html2canvas](https://html2canvas.hertzen.com/)
- [Axios](https://axios-http.com/)

---

<div align="center">

**Feito com ❤️ pela equipe Feedget**

[Website](https://feedget.io) · [Blog](https://feedget.io/blog) · [Status](https://status.feedget.io)

</div>