feedback-collector 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,156 +1,151 @@
1
1
  # Feedback Collector
2
2
 
3
- Coletor de feedback visual para desenvolvimento assistido por IA. Você navega pelo seu app em dev, segura ALT, clica nos elementos que quer mudar, escreve uma instrução curta para cada um e, no final, exporta um backlog em markdown com source mapping (`arquivo:linha`) pronto para colar de uma vez no Claude Code ou em outro agente de código.
3
+ Coletor de feedback visual para desenvolvimento assistido por IA. Segure ALT, clique nos elementos que quer mudar, escreva instruções curtas e exporte um backlog markdown com contexto técnico — incluindo `arquivo:linha` quando o projeto injeta source mapping no DOM.
4
4
 
5
- ## O problema
6
-
7
- O fluxo atual de iteração visual com agentes de código é serial: você aponta um elemento, descreve a mudança, espera o agente executar, e só então aponta o próximo. Para quem trabalha com design e front-end, isso é lento por dois motivos: descrever coisas visuais em texto é impreciso, e o ciclo clica-espera-clica desperdiça o tempo em que você já sabe as próximas cinco mudanças que quer fazer.
8
-
9
- A ideia central deste projeto é **desacoplar a coleta da execução**. Você acumula feedbacks anotados enquanto navega (como faria numa ferramenta de revisão tipo Pastel ou BugHerd), e despeja tudo de uma vez para a IA — mas com um payload técnico que ferramentas de anotação para humanos não capturam: elemento DOM, seletor estável, computed styles e, principalmente, o mapeamento para o arquivo e linha no código-fonte.
10
-
11
- ## Posicionamento (o que já existe e qual é o gap)
5
+ O projeto continua deliberadamente pequeno: runtime vanilla, zero dependências de runtime, sem backend, screenshots, imagens ou serviços externos. A v0.2 troca a autoria interna por TypeScript modular, adiciona API de ciclo de vida e builds de biblioteca sem quebrar a instalação v0.1.
12
6
 
13
- | Ferramenta | O que faz | Por que não resolve |
14
- |---|---|---|
15
- | **stagewise** | Toolbar que conecta seleção de elementos a agentes no editor | Fluxo orientado a execução imediata, não a backlog em lote; empresa pivotando para browser/IDE próprios |
16
- | **Pastel / BugHerd** | Anotação visual em site vivo, comentários viram tarefas | Output para humanos ("o botão tá grande"); sem acesso ao código, source mapping é arquitetonicamente impossível |
17
- | **Frontman** | Mapeamento DOM → arquivo/linha, BYOK | Sem modelo de fila + flush em lote |
18
- | **Chrome DevTools MCP** | Dá contexto de browser ao agente | Bare-bones, sem coleta acumulada nem anotação |
19
-
20
- O gap: **fila persistente de feedbacks anotados + payload técnico com source mapping + export em lote otimizado para agentes**. É isso que este projeto entrega.
7
+ ## O problema
21
8
 
22
- ## Estado atual: POC empacotada
9
+ O fluxo de iteração visual com agentes costuma ser serial: apontar um elemento, explicar a mudança, esperar e repetir. O Feedback Collector desacopla coleta e execução. Você acumula feedback enquanto navega e entrega de uma vez um payload com rota, seletor estável, DOM, estilos computados e source mapping.
23
10
 
24
- A POC é um único arquivo (`src/feedback-collector.js`) em JavaScript vanilla, sem dependências, sem backend, sem build — agora publicado como package npm (`feedback-collector`) e instalado em um primeiro projeto de produção real (ver `docs/decisoes.md`). Ela existe para validar a hipótese mais arriscada do projeto:
11
+ ## Instalação
25
12
 
26
- > Um backlog source-mapeado despejado de uma vez faz o Claude Code acertar os arquivos e produzir edits coerentes, de forma mais rápida que o fluxo serial atual.
13
+ ```bash
14
+ npm i -D feedback-collector
15
+ ```
27
16
 
28
- Deliberadamente fora do escopo da POC: extensão de navegador, screenshots, auth, persistência em servidor, MCP, multi-usuário. Nada disso valida a hipótese; tudo isso é v1 em diante.
17
+ O modo compatível continua igual: importar o package auto-inicializa o picker no navegador e é no-op durante SSR.
29
18
 
30
- ### Setup
19
+ ```ts
20
+ if (process.env.NODE_ENV === "development") {
21
+ void import("feedback-collector");
22
+ }
23
+ ```
31
24
 
32
- 1. Instale o package:
25
+ Em React, carregue de um componente client montado no layout. Em produção, renderize esse loader apenas para usuários autorizados; os atributos de source mapping podem expor a estrutura de paths nos chunks públicos.
33
26
 
34
- ```bash
35
- npm i -D feedback-collector
36
- ```
27
+ ### Controle programático
37
28
 
38
- 2. Carregue via import dinâmico (o script é um side effect injeta o picker ao ser importado):
29
+ Use o entry sem side effect quando quiser controlar explicitamente o ciclo de vida:
39
30
 
40
- ```js
41
- // Em um componente raiz (App.tsx, _app.tsx, layout.tsx...)
42
- if (process.env.NODE_ENV === 'development') {
43
- import('feedback-collector');
44
- }
45
- ```
31
+ ```ts
32
+ import { mount, destroy } from "feedback-collector/api";
46
33
 
47
- Em app com auth dá para ir além de dev: renderizar o loader server-side condicionado ao papel do usuário (ex. só owner/admin) e usar o picker **em produção**, contra dados reais — o script só lê o DOM que o próprio usuário já vê. Sites sem build: use o IIFE cru em `feedback-collector/script` via `<script src>`.
34
+ const collector = mount(); // idempotente: devolve a instância ativa
35
+ collector.items;
36
+ collector.exportMarkdown();
48
37
 
49
- 3. Configure o source mapping ele que injeta `arquivo:linha` no DOM):
38
+ destroy(); // remove listeners e todo DOM injetado; a fila persiste
39
+ mount(); // pode montar novamente
40
+ ```
50
41
 
51
- ```bash
52
- npm i -D @react-dev-inspector/babel-plugin
53
- ```
42
+ O entry raiz também exporta `mount()` e `destroy()`, mas mantém o auto-mount por compatibilidade. Para controle total, prefira `feedback-collector/api`.
54
43
 
55
- e plugue no bundler — receitas testadas por stack (Next webpack, Vite, prod vs dev, armadilhas do Babel 8) em [`skills/feedback-collector-setup/SKILL.md`](skills/feedback-collector-setup/SKILL.md), que também serve de skill para agentes de código instalarem/removerem isso sozinhos.
44
+ ### Script clássico / site sem bundler
56
45
 
57
- > ⚠️ **React 19:** o fallback via fiber (`_debugSource`) foi removido do React 19 sem o plugin de build **não há** arquivo:linha (o resto do payload continua funcionando).
46
+ `feedback-collector/script` aponta para o IIFE compilado em `dist/feedback-collector.js`. Copie esse arquivo para os assets do site ou sirva-o diretamente:
58
47
 
59
- ### Uso
48
+ ```html
49
+ <script src="/vendor/feedback-collector.js"></script>
50
+ <script>
51
+ // O IIFE auto-monta e expõe a API global.
52
+ FeedbackCollector.destroy();
53
+ FeedbackCollector.mount();
54
+ </script>
55
+ ```
60
56
 
61
- Segure **ALT** para entrar em modo picker — os elementos ganham highlight com o nome do arquivo no tooltip. **ALT + clique** captura o elemento e abre um campo para sua instrução ("diminuir o padding", "esse botão deveria ser secundário"). O painel no canto inferior direito acumula os itens; eles persistem em `localStorage`, então sobrevivem a reload e navegação. Quando terminar a sessão, **"Copiar backlog"** gera o markdown numerado no clipboard — cole no Claude Code e peça para executar.
57
+ Durante a transição da v0.1, `src/feedback-collector.js` continua publicado e contém o mesmo IIFE. Esse caminho é compatibilidade temporária; novos consumidores devem usar o export `feedback-collector/script` ou `dist/feedback-collector.js`.
62
58
 
63
- O contador **"N com source"** no header do painel é o termômetro da POC: se a maioria dos itens está sendo capturada sem source mapping, o problema está no setup do plugin, e vale resolver antes de testar o flush.
59
+ ## Source mapping
64
60
 
65
- ## Como o script funciona por dentro
61
+ O runtime os atributos suportados pela v0.1 no elemento ou em seus ancestrais:
66
62
 
67
- O script é auto-executável (IIFE) e se protege contra dupla injeção via flag em `window`. Ele opera em quatro camadas:
63
+ - `data-inspector-relative-path`
64
+ - `data-inspector-line`
65
+ - `data-inspector-column`
66
+ - `data-source="arquivo:linha:coluna"` como convenção alternativa
68
67
 
69
- ### 1. Picker (interação)
68
+ Para React, a receita validada usa `@react-dev-inspector/babel-plugin`. Instruções de Next webpack, Vite, uso em produção e remoção estão em [`skills/feedback-collector-setup/SKILL.md`](skills/feedback-collector-setup/SKILL.md).
70
69
 
71
- Listeners globais de teclado e mouse em fase de captura (`capture: true`, para interceptar antes do app). Segurar ALT ativa o modo picker; um `div` overlay com `pointer-events: none` segue o cursor usando `document.elementFromPoint` + `getBoundingClientRect`, desenhando o highlight. No clique, `preventDefault` + `stopPropagation` impedem que a ação real do elemento dispare (um botão não é clicado de verdade), e o elemento é capturado.
70
+ > React 19 removeu `_debugSource` do fiber. Sem plugin de build, a captura continua funcionando, mas o item não terá `arquivo:linha`.
72
71
 
73
- ### 2. Extração do payload (a inteligência)
72
+ ## Uso
74
73
 
75
- Para cada elemento capturado, o script monta um objeto com:
74
+ 1. Segure ALT para ativar o picker.
75
+ 2. Passe o mouse para ver highlight e source no tooltip.
76
+ 3. Use ALT + clique para capturar sem disparar a ação real do elemento.
77
+ 4. Escreva a instrução no painel.
78
+ 5. Clique em “Copiar backlog” e cole o markdown no agente de código.
76
79
 
77
- - **Source mapping**, em ordem de tentativa: (a) atributos `data-inspector-relative-path/-line/-column` injetados pelo react-dev-inspector no elemento ou em ancestrais; (b) fallback lendo o fiber interno do React (`_debugSource`, disponível em dev builds do React < 19), subindo a árvore de owners; (c) se nada disso existir, o item fica sem source, mas ainda carrega o resto do payload.
78
- - **Cadeia de componentes**: nomes dos ~3 componentes React mais próximos, extraídos do fiber, úteis quando não há arquivo:linha.
79
- - **Seletor CSS estável**: prioriza `id`, depois atributos estáveis (`data-testid`, `aria-label`, `name`), depois classes — filtrando classes que parecem geradas por hash/CSS Modules — e por fim `nth-of-type`. Para de subir na árvore assim que o seletor parcial já é único no documento.
80
- - **Computed styles curados**: um subconjunto de ~20 propriedades relevantes a layout e aparência, descartando valores default barulhentos (`none`, `auto`, `0px`...). Isso mantém o payload pequeno sem perder o que importa para ajustes visuais.
81
- - **Contexto**: rota atual, tag, texto visível (truncado), `outerHTML` truncado em 600 chars, bounding box e viewport.
80
+ Enquanto ALT está pressionado, o painel fica invisível e deixa o mouse atravessá-lo, permitindo capturar elementos que estavam por baixo. Arraste o cabeçalho para mover o painel; ao soltar, ele se encaixa no canto mais próximo.
82
81
 
83
- ### 3. Fila (estado)
82
+ A fila e o canto escolhido sobrevivem a reloads e navegação SPA. `localStorage` é por origem, portanto portas diferentes têm filas e preferências independentes.
84
83
 
85
- Array em memória espelhado em `localStorage` a cada mutação. Observação: `localStorage` é por origem, então `localhost:3000` e `localhost:5173` têm filas independentes. Não há servidor nem escrita em disco — tudo vive no navegador.
84
+ ## Persistência e migração segura
86
85
 
87
- ### 4. Painel e export (saída)
86
+ A v0.2 usa a chave `__fbc_state_v2` com envelope versionado:
88
87
 
89
- O painel é DOM puro injetado pelo próprio script (re-render por innerHTML a cada mudança — suficiente para a POC). O export concatena os itens em markdown numerado: título com a instrução, rota, `arquivo:linha`, seletor, styles atuais e o HTML do elemento em bloco de código. O cabeçalho do markdown já instrui o agente a agrupar edits do mesmo arquivo — mitigação barata para o risco de dispersão em backlogs grandes.
88
+ ```json
89
+ {
90
+ "version": 2,
91
+ "items": []
92
+ }
93
+ ```
90
94
 
91
- ### Decisão de design: sem screenshot (por enquanto)
95
+ Na primeira montagem, se ainda não houver estado v2 válido, o runtime lê o array legado `__fbc_items_v1`, preserva os objetos completos e grava o envelope v2. A chave v1 não é apagada, permitindo rollback sem perder a fila existente. Depois da migração, novas mutações são gravadas apenas em v2.
92
96
 
93
- Cada screenshot custa ~1 a 1,8k tokens; um backlog de 15 itens com prints estoura contexto rápido. A aposta da POC é que, para ajustes de layout e estilo, source mapping + DOM + styles + instrução textual bastam. Captura visual só entra se o teste mostrar que não basta — e aí no formato econômico: um screenshot de página com pins numerados + crops apertados por elemento.
97
+ Falhas de parse, indisponibilidade ou quota do storage não derrubam a página; o collector segue com estado em memória quando possível.
94
98
 
95
- ## Compatibilidade
99
+ ## Arquitetura v0.2
96
100
 
97
- | Camada | React (Next, Vite, CRA) | Vue / Svelte | Site sem build (HTML, CMS) |
98
- |---|---|---|---|
99
- | Picker, painel, fila, export | ✅ | ✅ | ✅ |
100
- | Seletor, styles, HTML | | ✅ | ✅ |
101
- | Source mapping (arquivo:linha) | via babel-plugin (obrigatório em React 19 — fiber fallback morreu) | 🔧 pequeno ajuste (vue-inspector / Svelte inspector injetam atributos análogos) | ❌ (menos grave: o agente acha via grep no HTML) |
101
+ ```text
102
+ src/
103
+ ├── api.ts # entry controlado, sem auto-mount
104
+ ├── index.ts # entry ESM compatível, com auto-mount
105
+ ├── script.ts # entry IIFE + API global
106
+ ├── lifecycle.ts # singleton mount()/destroy()
107
+ ├── collector.ts # interação e painel DOM vanilla
108
+ ├── extract.ts # source, seletor, styles e payload
109
+ ├── storage.ts # schema v2 e migração v1
110
+ ├── markdown.ts # export puro
111
+ └── types.ts # contrato público
112
+ ```
102
113
 
103
- A captura em si é framework-agnostic; só o source mapping é acoplado. Suportar Vue/Svelte é acrescentar os atributos deles na função `getSourceInfo` (~10 linhas).
114
+ O build gera:
104
115
 
105
- ## Critérios de sucesso da POC
116
+ - `dist/index.js` + `dist/index.d.ts`: ESM com auto-inicialização;
117
+ - `dist/api.js` + `dist/api.d.ts`: ESM programático sem side effect;
118
+ - `dist/feedback-collector.js`: IIFE/script com global `FeedbackCollector`;
119
+ - `src/feedback-collector.js`: cópia IIFE temporária para consumidores do path v0.1.
106
120
 
107
- Medir em uma sessão real de trabalho, cronometrada contra o fluxo atual:
121
+ Não dependências em `dependencies`; TypeScript, tsup, Vitest e Playwright são somente ferramentas de desenvolvimento.
108
122
 
109
- 1. **Precisão**: o agente vai direto no arquivo certo, sem caçar?
110
- 2. **Coerência em lote**: um backlog de ~10 itens produz edits coerentes, ou o agente dispersa e mistura contexto? Se degradar, as respostas prováveis são agrupar o export por arquivo/proximidade ou capar em N itens por flush.
111
- 3. **Velocidade**: foi mais rápido que o clica-espera-clica atual?
123
+ ## Desenvolvimento e validação
112
124
 
113
- Se os três derem verde, há produto. Se o item 2 falhar, o valor está no source mapping por clique (não no lote), o que muda o desenho da v1.
125
+ ```bash
126
+ npm install
127
+ npx playwright install chromium # necessário uma vez em máquinas sem browser do Playwright
128
+ npm run build
129
+ npm test
130
+ npm run test:browser
131
+ npm run size
132
+ npm run check
133
+ ```
114
134
 
115
- ## Próximos passos
135
+ Os testes puros cobrem migração/persistência, export markdown e helpers. O teste Playwright usa Chromium real para verificar auto-mount, ALT+clique, leitura de `data-inspector-*`, edição, persistência, clipboard, destroy e remontagem.
116
136
 
117
- **Curto prazo (validação)**
118
- - [ ] Rodar a POC em 1–2 projetos reais e medir os três critérios acima
119
- - [ ] Testar o limite do lote: em que N de itens o agente começa a dispersar?
120
- - [ ] Adicionar suporte a atributos do vue-inspector / Svelte inspector no `getSourceInfo`
137
+ O orçamento automatizado limita cada runtime a 30 KB raw e 8 KiB gzip. A v0.2 fica em cerca de 5,2 KB gzip; o arquivo v0.1 de referência tinha aproximadamente 6,3 KB gzip.
121
138
 
122
- **v1 (se a POC validar)**
123
- - [x] Empacotar como dev-dependency npm (`npm i -D feedback-collector`), modelo ESLint/Storybook: instalação por projeto
124
- - [x] Skill para agentes de código instalarem/removerem sozinhos (`skills/feedback-collector-setup/`)
125
- - [ ] Embutir o plugin de source mapping no pacote (Vite/Babel/SWC), eliminando o react-dev-inspector como passo separado
126
- - [ ] Export agrupado por arquivo/proximidade, se o teste de lote indicar necessidade
127
- - [ ] Nível 1 de integração: endpoint dev local que grava `.feedback/backlog.md` no repo — o agente lê o arquivo em vez de receber colagem
128
- - [ ] Melhorias de UX no painel: reordenar itens, marcar como resolvido, pausar coleta por iteração (padrão Pastel)
139
+ ## Integração futura com compiler/bundler
129
140
 
130
- **v2 (exploração)**
131
- - [ ] Captura visual econômica: screenshot de página com pins numerados + crops por elemento, opt-in
132
- - [ ] Integração via MCP para flush direto no agente, sem clipboard
133
- - [ ] Sessões nomeadas / múltiplos backlogs por projeto
141
+ A base desta versão mantém source mapping separado do runtime. Uma integração própria para Next/Vite só deve avançar depois de validar a coleta e o export em projetos reais. O desenho de extensão, critérios e sequência de protótipo estão em [`docs/integracao-compiler-futura.md`](docs/integracao-compiler-futura.md). Nenhum plugin próprio foi implementado nesta versão.
134
142
 
135
- **Explicitamente fora de escopo por ora**: extensão de navegador (perderia o acesso ao build e, com ele, o source mapping — que é o diferencial), auth, backend, multi-usuário.
143
+ ## Escopo
136
144
 
137
- ## Estrutura do repo
145
+ Incluído agora: runtime vanilla, fila local, source mapping por atributos/fiber legado, API de ciclo de vida, builds ESM/IIFE/tipos, migração segura, testes e orçamento de bundle.
138
146
 
139
- ```
140
- feedback-collector/
141
- ├── README.md # este documento
142
- ├── package.json # publicado no npm como `feedback-collector`
143
- ├── src/
144
- │ ├── feedback-collector.js # o script (IIFE, side effect)
145
- │ ├── index.js # entry ESM (import 'feedback-collector')
146
- │ └── index.d.ts # tipos (package sem API — só side effect)
147
- ├── skills/
148
- │ └── feedback-collector-setup/
149
- │ └── SKILL.md # skill p/ agentes: instalar/remover por stack
150
- └── docs/
151
- └── decisoes.md # registro de decisões conforme a POC evolui
152
- ```
147
+ Fora de escopo por enquanto: backend, screenshots, dashboard, auth própria, múltiplos adapters, extensão de navegador, MCP e ecossistema de packages.
153
148
 
154
149
  ## Licença
155
150
 
156
- MIT (observar que stagewise é AGPL, o que restringe reuso direto de código deles).
151
+ MIT.
package/dist/api.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ interface SourceInfo {
2
+ file: string;
3
+ line: string | number;
4
+ column: string | number;
5
+ via: "data-attr" | "fiber";
6
+ ownerHops?: number;
7
+ componentName?: string;
8
+ }
9
+ interface FeedbackItem {
10
+ id: string;
11
+ url: string;
12
+ tag: string;
13
+ selector: string;
14
+ source: SourceInfo | null;
15
+ components: string[];
16
+ text: string;
17
+ html: string;
18
+ styles: Record<string, string>;
19
+ rect: {
20
+ x: number;
21
+ y: number;
22
+ w: number;
23
+ h: number;
24
+ };
25
+ viewport: string;
26
+ instruction: string;
27
+ ts: string;
28
+ [key: string]: unknown;
29
+ }
30
+ interface FeedbackCollectorController {
31
+ readonly mounted: boolean;
32
+ readonly items: readonly FeedbackItem[];
33
+ exportMarkdown(): string;
34
+ destroy(): void;
35
+ }
36
+ interface MountOptions {
37
+ /** Storage alternativo para testes ou isolamento. O padrão é localStorage. */
38
+ storage?: Pick<Storage, "getItem" | "setItem">;
39
+ }
40
+
41
+ declare global {
42
+ interface Window {
43
+ __FEEDBACK_COLLECTOR__?: boolean | FeedbackCollectorController;
44
+ }
45
+ }
46
+ declare function mount(options?: MountOptions): FeedbackCollectorController;
47
+ declare function destroy(): void;
48
+
49
+ export { type FeedbackCollectorController, type FeedbackItem, type MountOptions, type SourceInfo, destroy, mount };
package/dist/api.js ADDED
@@ -0,0 +1,24 @@
1
+ var ce=["display","position","width","height","margin","padding","color","background-color","font-size","font-weight","line-height","border","border-radius","gap","flex-direction","justify-content","align-items","grid-template-columns","overflow","z-index","opacity","box-shadow","text-align"],de=new Set(["none","normal","auto","rgba(0, 0, 0, 0)","0px","visible","static","start"]);function W(t){let n=t;for(let e in n)if(e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"))return n[e];return null}function ue(t){let n=t;for(;n;){let e=n.type;if(typeof n.type=="function")return e?.displayName||e?.name||"";if(e&&typeof e=="object"&&e.displayName)return e.displayName;n=n._debugOwner||n.return;}return ""}function pe(t){return t.match(/(?:^|\/)((?:src|app|pages|components|lib|features)\/.*)$/)?.[1]||t}function fe(t){let n=t.match(/^(.*):(\d+):(\d+)$/);if(n)return {file:n[1]||t,line:n[2]||"",column:n[3]||""};let e=t.match(/^(.*):(\d+)$/);return {file:e?.[1]||t,line:e?.[2]||"",column:""}}function T(t){let n=t,e=0;for(;n&&n!==document.body;){let a=n.getAttribute("data-inspector-relative-path"),s=n.getAttribute("data-source");if(a||s){let l=s?fe(s):null;return {file:a||l?.file||"",line:n.getAttribute("data-inspector-line")||l?.line||"",column:n.getAttribute("data-inspector-column")||l?.column||"",via:"data-attr",ownerHops:e}}n=n.parentElement,e+=1;}let r=W(t),u=0;for(;r&&u<20;){let a=r._debugSource;if(a?.fileName)return {file:pe(a.fileName),line:a.lineNumber||"",column:a.columnNumber||"",via:"fiber",componentName:ue(r)};r=r._debugOwner||r.return||null,u+=1;}return null}function me(t){let n=W(t),e=[],r=0;for(;n&&e.length<3&&r<30;){let u=n.type,a=typeof n.type=="function"?u?.displayName||u?.name:u?.displayName;a&&!e.includes(a)&&e.push(a),n=n._debugOwner||n.return||null,r+=1;}return e}function X(t){return typeof CSS<"u"&&CSS.escape?CSS.escape(t):t.replace(/[^a-zA-Z0-9_-]/g,"\\$&")}function ge(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function be(t){if(t.id)return `#${X(t.id)}`;let n=[],e=t;for(;e&&e!==document.body&&n.length<5;){let r=e.tagName.toLowerCase(),u=false;for(let a of ["data-testid","data-test","aria-label","name"]){let s=e.getAttribute(a);if(s){r+=`[${a}="${ge(s)}"]`,u=true;break}}if(!u&&e.classList.length){let a=Array.from(e.classList).filter(s=>!/^[a-z]*[_-][a-zA-Z0-9]{5,}$/.test(s)&&!/^\d/.test(s)&&s.length<30).slice(0,2);a.length&&(r+=`.${a.map(X).join(".")}`,u=true);}if(!u){let a=1,s=e.previousElementSibling;for(;s;)s.tagName===e.tagName&&(a+=1),s=s.previousElementSibling;a>1&&(r+=`:nth-of-type(${a})`);}n.unshift(r);try{if(document.querySelectorAll(n.join(" > ")).length===1)break}catch{}e=e.parentElement;}return n.join(" > ")}function ye(t){let n=getComputedStyle(t),e={};for(let r of ce){let u=n.getPropertyValue(r);u&&!de.has(u)&&(e[r]=u);}return e}function he(t,n){let e=t.outerHTML||"";return e.length<=n?e:`${e.slice(0,n)}\u2026 [truncado]`}function V(t){let n=t.getBoundingClientRect();return {id:`${Date.now()}_${Math.random().toString(36).slice(2,7)}`,url:location.pathname+location.search+location.hash,tag:t.tagName.toLowerCase(),selector:be(t),source:T(t),components:me(t),text:(t.textContent||"").trim().slice(0,120),html:he(t,600),styles:ye(t),rect:{x:Math.round(n.x),y:Math.round(n.y),w:Math.round(n.width),h:Math.round(n.height)},viewport:`${window.innerWidth}x${window.innerHeight}`,instruction:"",ts:new Date().toISOString()}}function g(t){return String(t).replace(/`/g,"\\`")}function I(t,n=new Date){let e=["# Backlog de feedback visual","",`Gerado em ${n.toLocaleString()} \u2014 ${t.length} itens.`,"Cada item indica o arquivo:linha quando dispon\xEDvel. Execute na ordem, agrupando edits do mesmo arquivo.",""];return t.forEach((r,u)=>{if(e.push(`## ${u+1}. ${r.instruction?r.instruction.split(`
2
+ `)[0]:"(sem instru\xE7\xE3o)"}`),e.push(""),r.instruction.includes(`
3
+ `)&&e.push(r.instruction,""),e.push(`- **Rota:** \`${g(r.url)}\``),r.source){let s=`${r.source.file}${r.source.line?`:${r.source.line}`:""}`,l=r.source.componentName?` (componente \`${g(r.source.componentName)}\`)`:"";e.push(`- **Source:** \`${g(s)}\`${l}`);}else r.components.length&&e.push(`- **Componentes (do mais interno):** ${r.components.map(s=>`\`${g(s)}\``).join(" \u2192 ")}`);e.push(`- **Elemento:** \`<${g(r.tag)}>\` \u2014 seletor: \`${g(r.selector)}\``),r.text&&e.push(`- **Texto vis\xEDvel:** "${r.text}"`),e.push(`- **Posi\xE7\xE3o:** ${r.rect.w}x${r.rect.h} @ (${r.rect.x},${r.rect.y}), viewport ${r.viewport}`);let a=Object.entries(r.styles);a.length&&e.push(`- **Styles atuais:** ${a.map(([s,l])=>`\`${g(s)}: ${g(l)}\``).join(", ")}`),e.push("","```html",r.html,"```","");}),e.join(`
4
+ `)}var U="__fbc_state_v2",xe="__fbc_items_v1";var Z=()=>({version:2,items:[]});function J(t){if(!t)return null;try{return JSON.parse(t)}catch{return null}}function ve(t){return !!t&&typeof t=="object"&&Array.isArray(t.items)}function we(t,n){let e=J(t);if(ve(e)&&e.version===2)return {state:{version:2,items:e.items},migrated:false};let r=J(n);return Array.isArray(r)?{state:{version:2,items:r},migrated:true}:{state:Z(),migrated:false}}function A(t,n){try{return t.setItem(U,JSON.stringify(n)),!0}catch{return false}}function Q(t){let n=null,e=null;try{n=t.getItem(U),e=t.getItem(xe);}catch{return Z()}let r=we(n,e);return r.migrated&&A(t,r.state),r.state}var Ee="position:fixed;pointer-events:none;z-index:2147483645;border:2px solid #2563eb;background:rgba(37,99,235,.08);border-radius:2px;display:none;transition:all .05s linear;",Se="position:absolute;top:-22px;left:0;background:#2563eb;color:#fff;font:11px/1.4 ui-monospace,monospace;padding:1px 6px;border-radius:2px;white-space:nowrap;",ke="position:fixed;bottom:16px;right:16px;width:340px;max-width:calc(100vw - 32px);max-height:70vh;z-index:2147483646;background:#1c1c1e;color:#e5e5e7;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.4);font:13px/1.45 system-ui,sans-serif;display:flex;flex-direction:column;overflow:hidden;transition:opacity .08s ease;",$e="position:fixed;bottom:16px;left:50%;transform:translateX(-50%);z-index:2147483647;background:#15803d;color:#fff;padding:8px 16px;border-radius:8px;font:13px system-ui,sans-serif;display:none;box-shadow:0 4px 14px rgba(0,0,0,.3);",ee="__fbc_panel_corner_v1",m=16,Ce=4;function Le(t){return t==="top-left"||t==="top-right"||t==="bottom-left"||t==="bottom-right"}function w(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/"/g,"&quot;")}function _e(t,n){let e=t.source?`${t.source.file.split("/").slice(-2).join("/")}${t.source.line?`:${t.source.line}`:""}`:t.components[0]?`<${t.components[0]}>`:t.selector.slice(0,40);return `<div style="background:#2c2c2e;border-radius:8px;padding:8px;">
5
+ <div style="display:flex;align-items:baseline;gap:6px;margin-bottom:6px;">
6
+ <span style="color:#a8a8ae;font-size:11px;">#${n+1}</span>
7
+ <span style="font-family:ui-monospace,monospace;font-size:11px;color:#64d2ff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;" title="${w(t.selector)}">${w(e)}</span>
8
+ <span data-fbc-del="${w(t.id)}" style="cursor:pointer;color:#a8a8ae;padding:0 4px;" title="Remover">\u2715</span>
9
+ </div>
10
+ <textarea data-fbc-ta="${w(t.id)}" placeholder="O que mudar aqui?" style="width:100%;box-sizing:border-box;background:#1c1c1e;color:#e5e5e7;border:1px solid #3a3a3c;border-radius:6px;padding:6px;font:13px system-ui;resize:vertical;min-height:40px;">${w(t.instruction)}</textarea>
11
+ </div>`}function te(t={}){if(!document.body)throw new Error("feedback-collector: mount() requer document.body dispon\xEDvel.");let n=t.storage||window.localStorage,e=Q(n),r=false,u=null,a=false,s="bottom-right",l=null,E=false,L=true,x,h,S=new Set,ne=document.body.style.cursor,p=document.createElement("div");p.dataset.fbcRoot="highlight",p.style.cssText=Ee;let _=document.createElement("div");_.style.cssText=Se,p.append(_);let c=document.createElement("div");c.dataset.fbcRoot="panel",c.style.cssText=ke;let y=document.createElement("div");y.dataset.fbcRoot="toast",y.style.cssText=$e;try{let o=n.getItem(ee);Le(o)&&(s=o);}catch{}function R(o,i){let d=Math.max(m,window.innerWidth-c.offsetWidth-m),f=Math.max(m,window.innerHeight-c.offsetHeight-m);c.style.left=`${Math.min(Math.max(m,o),d)}px`,c.style.top=`${Math.min(Math.max(m,i),f)}px`,c.style.right="auto",c.style.bottom="auto";}function k(){let o=s.endsWith("right")?window.innerWidth-c.offsetWidth-m:m,i=s.startsWith("bottom")?window.innerHeight-c.offsetHeight-m:m;R(o,i);}function oe(){try{n.setItem(ee,s);}catch{}}function P(o){c.style.opacity=o?"0":"1",c.style.pointerEvents=o?"none":"auto";}function $(){A(n,e);}function re(o){y.textContent=o,y.style.display="block",x&&clearTimeout(x),x=setTimeout(()=>{y.style.display="none";},2500);}function v(){let o=e.items.filter(i=>i.source).length;c.innerHTML=`<div data-fbc="header" title="Arraste para mover \xB7 clique para recolher" style="display:flex;align-items:center;gap:8px;padding:10px 12px;background:#2c2c2e;cursor:grab;user-select:none;touch-action:none;">
12
+ <span style="font-weight:600;">Feedback</span>
13
+ <span style="background:#2563eb;border-radius:10px;padding:0 8px;font-size:11px;">${e.items.length}</span>
14
+ ${e.items.length?`<span style="font-size:11px;color:#a8a8ae;">${o} com source</span>`:""}
15
+ <span style="margin-left:auto;color:#a8a8ae;font-size:11px;">segure ALT + clique</span>
16
+ <span data-fbc="toggle" style="color:#a8a8ae;">${a?"\u25B8":"\u25BE"}</span>
17
+ </div>${a?"":`<div style="overflow-y:auto;flex:1;padding:8px 12px;display:flex;flex-direction:column;gap:8px;">
18
+ ${e.items.length?e.items.map(_e).join(""):'<div style="color:#a8a8ae;padding:12px 0;text-align:center;">Nenhum item. Segure ALT e clique num elemento da p\xE1gina.</div>'}
19
+ </div>
20
+ <div style="display:flex;gap:8px;padding:10px 12px;background:#2c2c2e;">
21
+ <button data-fbc="copy" ${e.items.length?"":"disabled"} style="flex:1;background:${e.items.length?"#2563eb":"#3a3a3c"};color:${e.items.length?"#fff":"#a8a8ae"};border:0;border-radius:6px;padding:8px;font:600 13px system-ui;cursor:${e.items.length?"pointer":"default"};">Copiar backlog</button>
22
+ <button data-fbc="clear" style="background:#3a3a3c;color:#e5e5e7;border:0;border-radius:6px;padding:8px 12px;font:13px system-ui;cursor:pointer;">Limpar</button>
23
+ </div>`}`,l||k();}function C(){r=false,u=null,p.style.display="none",P(false),document.body.style.cursor=ne;}function ie(o){let i=o.style.outline;o.style.outline="3px solid #16a34a";let d=setTimeout(()=>{o.style.outline=i,S.delete(d);},400);S.add(d);}function ae(o){let i=V(o);e.items.push(i),$(),v(),setTimeout(()=>c.querySelector(`[data-fbc-ta="${CSS.escape(i.id)}"]`)?.focus(),50),o instanceof HTMLElement&&ie(o);}async function se(){let o=I(e.items);try{await navigator.clipboard.writeText(o),re(`Backlog copiado (${e.items.length} itens). Cola no seu agente de c\xF3digo.`);}catch{window.prompt("Copie manualmente:",o);}}function M(o){o.key==="Alt"&&!r&&(r=true,P(true),document.body.style.cursor="crosshair");}function N(o){o.key==="Alt"&&C();}function F(o){if(!r)return;let i=document.elementFromPoint(o.clientX,o.clientY);if(!i||c.contains(i)||p.contains(i)||i===p){p.style.display="none",u=null;return}u=i;let d=i.getBoundingClientRect();p.style.display="block",p.style.left=`${d.left}px`,p.style.top=`${d.top}px`,p.style.width=`${d.width}px`,p.style.height=`${d.height}px`;let f=T(i);_.textContent=`<${i.tagName.toLowerCase()}>${f?` ${f.file.split("/").pop()}${f.line?`:${f.line}`:""}`:""}`;}function D(o){!r||!u||!(o.target instanceof Node)||c.contains(o.target)||(o.preventDefault(),o.stopPropagation(),ae(u));}function H(o){if(!(o.target instanceof Element))return;let i=o.target,d=i.getAttribute("data-fbc");if(d==="copy"){se();return}if(d==="clear"){e.items.length&&window.confirm(`Limpar todos os ${e.items.length} itens?`)&&(e.items=[],$(),v());return}let f=i.getAttribute("data-fbc-del");if(f){e.items=e.items.filter(K=>K.id!==f),$(),v();return}if(i.closest('[data-fbc="header"]')){if(E){E=false;return}a=!a,v();}}function Y(o){if(o.button!==0||!(o.target instanceof Element))return;let i=o.target.closest('[data-fbc="header"]');if(!i)return;let d=c.getBoundingClientRect();l={pointerId:o.pointerId,startX:o.clientX,startY:o.clientY,panelX:d.left,panelY:d.top,moved:false,header:i},i.style.cursor="grabbing";}function z(o){if(!l||o.pointerId!==l.pointerId)return;let i=o.clientX-l.startX,d=o.clientY-l.startY;!l.moved&&Math.hypot(i,d)<Ce||(l.moved=true,o.preventDefault(),R(l.panelX+i,l.panelY+d));}function j(o){if(!l||o.pointerId!==l.pointerId)return;let i=l;if(l=null,i.header.style.cursor="grab",!i.moved)return;let d=c.getBoundingClientRect(),f=d.left+d.width/2<window.innerWidth/2?"left":"right";s=`${d.top+d.height/2<window.innerHeight/2?"top":"bottom"}-${f}`,E=true,h&&clearTimeout(h),h=setTimeout(()=>{E=false,h=void 0;},0),k(),oe();}function B(o){!l||o.pointerId!==l.pointerId||(l.header.style.cursor="grab",l=null,k());}function G(){l||k();}function q(o){if(!(o.target instanceof HTMLTextAreaElement))return;let i=o.target.getAttribute("data-fbc-ta"),d=e.items.find(f=>f.id===i);d&&(d.instruction=o.target.value,$());}document.addEventListener("keydown",M,true),document.addEventListener("keyup",N,true),window.addEventListener("blur",C),document.addEventListener("mousemove",F,true),document.addEventListener("click",D,true),c.addEventListener("click",H),c.addEventListener("input",q),c.addEventListener("pointerdown",Y),window.addEventListener("pointermove",z,{passive:false}),window.addEventListener("pointerup",j),window.addEventListener("pointercancel",B),window.addEventListener("resize",G),document.body.append(p,c,y),v();let le={get mounted(){return L},get items(){return e.items},exportMarkdown(){return I(e.items)},destroy(){if(L){L=false,C(),document.removeEventListener("keydown",M,true),document.removeEventListener("keyup",N,true),window.removeEventListener("blur",C),document.removeEventListener("mousemove",F,true),document.removeEventListener("click",D,true),c.removeEventListener("click",H),c.removeEventListener("input",q),c.removeEventListener("pointerdown",Y),window.removeEventListener("pointermove",z),window.removeEventListener("pointerup",j),window.removeEventListener("pointercancel",B),window.removeEventListener("resize",G),x&&clearTimeout(x),h&&clearTimeout(h);for(let o of S)clearTimeout(o);S.clear(),p.remove(),c.remove(),y.remove();}}};return console.log(`[feedback-collector] ativo. Segure ALT + clique pra capturar. ${e.items.length} item(ns) restaurado(s) do localStorage.`),le}var b=null;function Te(t={}){if(typeof window>"u"||typeof document>"u")throw new Error("feedback-collector: mount() s\xF3 pode ser chamado no navegador.");if(b?.mounted)return b;let n=window.__FEEDBACK_COLLECTOR__;if(n&&typeof n=="object"&&n.mounted)return b=n,n;if(n===true)throw new Error("feedback-collector: uma vers\xE3o anterior j\xE1 est\xE1 montada nesta p\xE1gina.");return b=te(t),window.__FEEDBACK_COLLECTOR__=b,b}function Ie(){b?.destroy(),b=null,typeof window<"u"&&delete window.__FEEDBACK_COLLECTOR__;}export{Ie as destroy,Te as mount};//# sourceMappingURL=api.js.map
24
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/extract.ts","../src/markdown.ts","../src/storage.ts","../src/collector.ts","../src/lifecycle.ts"],"names":["STYLE_PROPERTIES","NOISY_STYLE_VALUES","getFiber","element","record","key","fiberName","fiber","current","type","relativize","fileName","parseDataSource","value","withColumn","withLine","getSourceInfo","node","ownerHops","inspectorPath","dataSource","alternative","hops","source","componentChain","names","name","escapeIdentifier","escapeAttribute","cssSelector","parts","part","gotStablePart","attribute","classes","index","sibling","curatedStyles","computed","styles","property","truncatedHtml","max","html","captureElement","rect","inline","toMarkdown","items","generatedAt","lines","item","location","component","STORAGE_KEY","LEGACY_STORAGE_KEY","emptyState","parseJson","raw","hasItems","decodeStoredState","currentRaw","legacyRaw","legacy","persistState","storage","state","loadState","decoded","HIGHLIGHT_STYLE","LABEL_STYLE","PANEL_STYLE","TOAST_STYLE","PANEL_CORNER_KEY","PANEL_MARGIN","DRAG_THRESHOLD","isPanelCorner","escapeHtml","renderItem","createCollector","options","pickerActive","hoverElement","collapsed","panelCorner","panelDrag","suppressHeaderClick","mounted","toastTimer","dragClickTimer","flashTimers","previousCursor","highlight","highlightLabel","panel","toastElement","storedCorner","setPanelPosition","x","y","maxX","maxY","applyPanelCorner","persistPanelCorner","setPanelHiddenForPicker","hidden","save","toast","message","renderPanel","sourceCount","deactivatePicker","flashElement","previousOutline","timer","capture","copyBacklog","markdown","onKeyDown","event","onKeyUp","onMouseMove","onClick","onPanelClick","target","action","deleteId","onPanelPointerDown","header","onPanelPointerMove","deltaX","deltaY","finishPanelDrag","drag","horizontal","cancelPanelDrag","onViewportResize","onPanelInput","id","candidate","controller","activeController","mount","existing","destroy"],"mappings":"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","file":"api.js","sourcesContent":["import type { FeedbackItem, SourceInfo } from \"./types\";\n\ntype Fiber = {\n type?: unknown;\n return?: Fiber | null;\n _debugOwner?: Fiber | null;\n _debugSource?: { fileName?: string; lineNumber?: number; columnNumber?: number };\n};\n\nconst STYLE_PROPERTIES = [\n \"display\", \"position\", \"width\", \"height\", \"margin\", \"padding\", \"color\",\n \"background-color\", \"font-size\", \"font-weight\", \"line-height\", \"border\",\n \"border-radius\", \"gap\", \"flex-direction\", \"justify-content\", \"align-items\",\n \"grid-template-columns\", \"overflow\", \"z-index\", \"opacity\", \"box-shadow\", \"text-align\",\n];\n\nconst NOISY_STYLE_VALUES = new Set([\n \"none\", \"normal\", \"auto\", \"rgba(0, 0, 0, 0)\", \"0px\", \"visible\", \"static\", \"start\",\n]);\n\nfunction getFiber(element: Element): Fiber | null {\n const record = element as unknown as Record<string, unknown>;\n for (const key in record) {\n if (key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\")) {\n return record[key] as Fiber;\n }\n }\n return null;\n}\n\nfunction fiberName(fiber: Fiber): string {\n let current: Fiber | null | undefined = fiber;\n while (current) {\n const type = current.type as { displayName?: string; name?: string } | undefined;\n if (typeof current.type === \"function\") return type?.displayName || type?.name || \"\";\n if (type && typeof type === \"object\" && type.displayName) return type.displayName;\n current = current._debugOwner || current.return;\n }\n return \"\";\n}\n\nexport function relativize(fileName: string): string {\n const match = fileName.match(/(?:^|\\/)((?:src|app|pages|components|lib|features)\\/.*)$/);\n return match?.[1] || fileName;\n}\n\nfunction parseDataSource(value: string): { file: string; line: string; column: string } {\n const withColumn = value.match(/^(.*):(\\d+):(\\d+)$/);\n if (withColumn) {\n return { file: withColumn[1] || value, line: withColumn[2] || \"\", column: withColumn[3] || \"\" };\n }\n const withLine = value.match(/^(.*):(\\d+)$/);\n return {\n file: withLine?.[1] || value,\n line: withLine?.[2] || \"\",\n column: \"\",\n };\n}\n\nexport function getSourceInfo(element: Element): SourceInfo | null {\n let node: Element | null = element;\n let ownerHops = 0;\n while (node && node !== document.body) {\n const inspectorPath = node.getAttribute(\"data-inspector-relative-path\");\n const dataSource = node.getAttribute(\"data-source\");\n if (inspectorPath || dataSource) {\n const alternative = dataSource ? parseDataSource(dataSource) : null;\n return {\n file: inspectorPath || alternative?.file || \"\",\n line: node.getAttribute(\"data-inspector-line\") || alternative?.line || \"\",\n column: node.getAttribute(\"data-inspector-column\") || alternative?.column || \"\",\n via: \"data-attr\",\n ownerHops,\n };\n }\n node = node.parentElement;\n ownerHops += 1;\n }\n\n let fiber = getFiber(element);\n let hops = 0;\n while (fiber && hops < 20) {\n const source = fiber._debugSource;\n if (source?.fileName) {\n return {\n file: relativize(source.fileName),\n line: source.lineNumber || \"\",\n column: source.columnNumber || \"\",\n via: \"fiber\",\n componentName: fiberName(fiber),\n };\n }\n fiber = fiber._debugOwner || fiber.return || null;\n hops += 1;\n }\n return null;\n}\n\nexport function componentChain(element: Element): string[] {\n let fiber = getFiber(element);\n const names: string[] = [];\n let hops = 0;\n while (fiber && names.length < 3 && hops < 30) {\n const type = fiber.type as { displayName?: string; name?: string } | undefined;\n const name = typeof fiber.type === \"function\" ? type?.displayName || type?.name : type?.displayName;\n if (name && !names.includes(name)) names.push(name);\n fiber = fiber._debugOwner || fiber.return || null;\n hops += 1;\n }\n return names;\n}\n\nfunction escapeIdentifier(value: string): string {\n return typeof CSS !== \"undefined\" && CSS.escape ? CSS.escape(value) : value.replace(/[^a-zA-Z0-9_-]/g, \"\\\\$&\");\n}\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nexport function cssSelector(element: Element): string {\n if (element.id) return `#${escapeIdentifier(element.id)}`;\n const parts: string[] = [];\n let node: Element | null = element;\n while (node && node !== document.body && parts.length < 5) {\n let part = node.tagName.toLowerCase();\n let gotStablePart = false;\n for (const attribute of [\"data-testid\", \"data-test\", \"aria-label\", \"name\"]) {\n const value = node.getAttribute(attribute);\n if (value) {\n part += `[${attribute}=\"${escapeAttribute(value)}\"]`;\n gotStablePart = true;\n break;\n }\n }\n\n if (!gotStablePart && node.classList.length) {\n const classes = Array.from(node.classList)\n .filter((value) => !/^[a-z]*[_-][a-zA-Z0-9]{5,}$/.test(value) && !/^\\d/.test(value) && value.length < 30)\n .slice(0, 2);\n if (classes.length) {\n part += `.${classes.map(escapeIdentifier).join(\".\")}`;\n gotStablePart = true;\n }\n }\n\n if (!gotStablePart) {\n let index = 1;\n let sibling = node.previousElementSibling;\n while (sibling) {\n if (sibling.tagName === node.tagName) index += 1;\n sibling = sibling.previousElementSibling;\n }\n if (index > 1) part += `:nth-of-type(${index})`;\n }\n\n parts.unshift(part);\n try {\n if (document.querySelectorAll(parts.join(\" > \")).length === 1) break;\n } catch {\n // Continue até montar um seletor válido/mais específico.\n }\n node = node.parentElement;\n }\n return parts.join(\" > \");\n}\n\nfunction curatedStyles(element: Element): Record<string, string> {\n const computed = getComputedStyle(element);\n const styles: Record<string, string> = {};\n for (const property of STYLE_PROPERTIES) {\n const value = computed.getPropertyValue(property);\n if (value && !NOISY_STYLE_VALUES.has(value)) styles[property] = value;\n }\n return styles;\n}\n\nfunction truncatedHtml(element: Element, max: number): string {\n const html = element.outerHTML || \"\";\n return html.length <= max ? html : `${html.slice(0, max)}… [truncado]`;\n}\n\nexport function captureElement(element: Element): FeedbackItem {\n const rect = element.getBoundingClientRect();\n return {\n id: `${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n url: location.pathname + location.search + location.hash,\n tag: element.tagName.toLowerCase(),\n selector: cssSelector(element),\n source: getSourceInfo(element),\n components: componentChain(element),\n text: (element.textContent || \"\").trim().slice(0, 120),\n html: truncatedHtml(element, 600),\n styles: curatedStyles(element),\n rect: {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n w: Math.round(rect.width),\n h: Math.round(rect.height),\n },\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n instruction: \"\",\n ts: new Date().toISOString(),\n };\n}\n","import type { FeedbackItem } from \"./types\";\n\nfunction inline(value: unknown): string {\n return String(value).replace(/`/g, \"\\\\`\");\n}\n\nexport function toMarkdown(items: readonly FeedbackItem[], generatedAt = new Date()): string {\n const lines = [\n \"# Backlog de feedback visual\",\n \"\",\n `Gerado em ${generatedAt.toLocaleString()} — ${items.length} itens.`,\n \"Cada item indica o arquivo:linha quando disponível. Execute na ordem, agrupando edits do mesmo arquivo.\",\n \"\",\n ];\n\n items.forEach((item, index) => {\n lines.push(`## ${index + 1}. ${item.instruction ? item.instruction.split(\"\\n\")[0] : \"(sem instrução)\"}`);\n lines.push(\"\");\n if (item.instruction.includes(\"\\n\")) lines.push(item.instruction, \"\");\n lines.push(`- **Rota:** \\`${inline(item.url)}\\``);\n if (item.source) {\n const location = `${item.source.file}${item.source.line ? `:${item.source.line}` : \"\"}`;\n const component = item.source.componentName ? ` (componente \\`${inline(item.source.componentName)}\\`)` : \"\";\n lines.push(`- **Source:** \\`${inline(location)}\\`${component}`);\n } else if (item.components.length) {\n lines.push(`- **Componentes (do mais interno):** ${item.components.map((name) => `\\`${inline(name)}\\``).join(\" → \")}`);\n }\n lines.push(`- **Elemento:** \\`<${inline(item.tag)}>\\` — seletor: \\`${inline(item.selector)}\\``);\n if (item.text) lines.push(`- **Texto visível:** \"${item.text}\"`);\n lines.push(`- **Posição:** ${item.rect.w}x${item.rect.h} @ (${item.rect.x},${item.rect.y}), viewport ${item.viewport}`);\n\n const styles = Object.entries(item.styles);\n if (styles.length) {\n lines.push(`- **Styles atuais:** ${styles.map(([key, value]) => `\\`${inline(key)}: ${inline(value)}\\``).join(\", \")}`);\n }\n lines.push(\"\", \"```html\", item.html, \"```\", \"\");\n });\n\n return lines.join(\"\\n\");\n}\n","import type { FeedbackItem } from \"./types\";\n\nexport const STORAGE_KEY = \"__fbc_state_v2\";\nexport const LEGACY_STORAGE_KEY = \"__fbc_items_v1\";\nexport const STORAGE_VERSION = 2 as const;\n\nexport interface StoredState {\n version: typeof STORAGE_VERSION;\n items: FeedbackItem[];\n}\n\nexport interface DecodedState {\n state: StoredState;\n migrated: boolean;\n}\n\nconst emptyState = (): StoredState => ({ version: STORAGE_VERSION, items: [] });\n\nfunction parseJson(raw: string | null): unknown {\n if (!raw) return null;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return null;\n }\n}\n\nfunction hasItems(value: unknown): value is { items: FeedbackItem[] } {\n return Boolean(value) && typeof value === \"object\" && Array.isArray((value as { items?: unknown }).items);\n}\n\n/** Pure migration used by the runtime and unit tests. */\nexport function decodeStoredState(currentRaw: string | null, legacyRaw: string | null): DecodedState {\n const current = parseJson(currentRaw);\n if (hasItems(current) && (current as { version?: unknown }).version === STORAGE_VERSION) {\n return {\n state: { version: STORAGE_VERSION, items: current.items },\n migrated: false,\n };\n }\n\n const legacy = parseJson(legacyRaw);\n if (Array.isArray(legacy)) {\n return {\n state: { version: STORAGE_VERSION, items: legacy as FeedbackItem[] },\n migrated: true,\n };\n }\n\n return { state: emptyState(), migrated: false };\n}\n\nexport function persistState(storage: Pick<Storage, \"setItem\">, state: StoredState): boolean {\n try {\n storage.setItem(STORAGE_KEY, JSON.stringify(state));\n return true;\n } catch {\n return false;\n }\n}\n\nexport function loadState(storage: Pick<Storage, \"getItem\" | \"setItem\">): StoredState {\n let currentRaw: string | null = null;\n let legacyRaw: string | null = null;\n try {\n currentRaw = storage.getItem(STORAGE_KEY);\n legacyRaw = storage.getItem(LEGACY_STORAGE_KEY);\n } catch {\n return emptyState();\n }\n\n const decoded = decodeStoredState(currentRaw, legacyRaw);\n if (decoded.migrated) {\n // A chave v1 fica intacta para permitir rollback sem perda de dados.\n persistState(storage, decoded.state);\n }\n return decoded.state;\n}\n","import { captureElement, getSourceInfo } from \"./extract\";\nimport { toMarkdown } from \"./markdown\";\nimport { loadState, persistState, type StoredState } from \"./storage\";\nimport type { FeedbackCollectorController, FeedbackItem, MountOptions } from \"./types\";\n\nconst HIGHLIGHT_STYLE = \"position:fixed;pointer-events:none;z-index:2147483645;border:2px solid #2563eb;background:rgba(37,99,235,.08);border-radius:2px;display:none;transition:all .05s linear;\";\nconst LABEL_STYLE = \"position:absolute;top:-22px;left:0;background:#2563eb;color:#fff;font:11px/1.4 ui-monospace,monospace;padding:1px 6px;border-radius:2px;white-space:nowrap;\";\nconst PANEL_STYLE = \"position:fixed;bottom:16px;right:16px;width:340px;max-width:calc(100vw - 32px);max-height:70vh;z-index:2147483646;background:#1c1c1e;color:#e5e5e7;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.4);font:13px/1.45 system-ui,sans-serif;display:flex;flex-direction:column;overflow:hidden;transition:opacity .08s ease;\";\nconst TOAST_STYLE = \"position:fixed;bottom:16px;left:50%;transform:translateX(-50%);z-index:2147483647;background:#15803d;color:#fff;padding:8px 16px;border-radius:8px;font:13px system-ui,sans-serif;display:none;box-shadow:0 4px 14px rgba(0,0,0,.3);\";\nconst PANEL_CORNER_KEY = \"__fbc_panel_corner_v1\";\nconst PANEL_MARGIN = 16;\nconst DRAG_THRESHOLD = 4;\n\ntype PanelCorner = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\n\ninterface PanelDrag {\n pointerId: number;\n startX: number;\n startY: number;\n panelX: number;\n panelY: number;\n moved: boolean;\n header: HTMLElement;\n}\n\nfunction isPanelCorner(value: unknown): value is PanelCorner {\n return value === \"top-left\" || value === \"top-right\" || value === \"bottom-left\" || value === \"bottom-right\";\n}\n\nfunction escapeHtml(value: unknown): string {\n return String(value).replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/\"/g, \"&quot;\");\n}\n\nfunction renderItem(item: FeedbackItem, index: number): string {\n const location = item.source\n ? `${item.source.file.split(\"/\").slice(-2).join(\"/\")}${item.source.line ? `:${item.source.line}` : \"\"}`\n : item.components[0]\n ? `<${item.components[0]}>`\n : item.selector.slice(0, 40);\n\n return `<div style=\"background:#2c2c2e;border-radius:8px;padding:8px;\">\n <div style=\"display:flex;align-items:baseline;gap:6px;margin-bottom:6px;\">\n <span style=\"color:#a8a8ae;font-size:11px;\">#${index + 1}</span>\n <span style=\"font-family:ui-monospace,monospace;font-size:11px;color:#64d2ff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;\" title=\"${escapeHtml(item.selector)}\">${escapeHtml(location)}</span>\n <span data-fbc-del=\"${escapeHtml(item.id)}\" style=\"cursor:pointer;color:#a8a8ae;padding:0 4px;\" title=\"Remover\">✕</span>\n </div>\n <textarea data-fbc-ta=\"${escapeHtml(item.id)}\" placeholder=\"O que mudar aqui?\" style=\"width:100%;box-sizing:border-box;background:#1c1c1e;color:#e5e5e7;border:1px solid #3a3a3c;border-radius:6px;padding:6px;font:13px system-ui;resize:vertical;min-height:40px;\">${escapeHtml(item.instruction)}</textarea>\n </div>`;\n}\n\nexport function createCollector(options: MountOptions = {}): FeedbackCollectorController {\n if (!document.body) throw new Error(\"feedback-collector: mount() requer document.body disponível.\");\n\n const storage = options.storage || window.localStorage;\n let state: StoredState = loadState(storage);\n let pickerActive = false;\n let hoverElement: Element | null = null;\n let collapsed = false;\n let panelCorner: PanelCorner = \"bottom-right\";\n let panelDrag: PanelDrag | null = null;\n let suppressHeaderClick = false;\n let mounted = true;\n let toastTimer: ReturnType<typeof setTimeout> | undefined;\n let dragClickTimer: ReturnType<typeof setTimeout> | undefined;\n const flashTimers = new Set<ReturnType<typeof setTimeout>>();\n const previousCursor = document.body.style.cursor;\n\n const highlight = document.createElement(\"div\");\n highlight.dataset.fbcRoot = \"highlight\";\n highlight.style.cssText = HIGHLIGHT_STYLE;\n const highlightLabel = document.createElement(\"div\");\n highlightLabel.style.cssText = LABEL_STYLE;\n highlight.append(highlightLabel);\n\n const panel = document.createElement(\"div\");\n panel.dataset.fbcRoot = \"panel\";\n panel.style.cssText = PANEL_STYLE;\n\n const toastElement = document.createElement(\"div\");\n toastElement.dataset.fbcRoot = \"toast\";\n toastElement.style.cssText = TOAST_STYLE;\n\n try {\n const storedCorner = storage.getItem(PANEL_CORNER_KEY);\n if (isPanelCorner(storedCorner)) panelCorner = storedCorner;\n } catch {\n // O painel continua no canto padrão quando o storage não está disponível.\n }\n\n function setPanelPosition(x: number, y: number): void {\n const maxX = Math.max(PANEL_MARGIN, window.innerWidth - panel.offsetWidth - PANEL_MARGIN);\n const maxY = Math.max(PANEL_MARGIN, window.innerHeight - panel.offsetHeight - PANEL_MARGIN);\n panel.style.left = `${Math.min(Math.max(PANEL_MARGIN, x), maxX)}px`;\n panel.style.top = `${Math.min(Math.max(PANEL_MARGIN, y), maxY)}px`;\n panel.style.right = \"auto\";\n panel.style.bottom = \"auto\";\n }\n\n function applyPanelCorner(): void {\n const x = panelCorner.endsWith(\"right\")\n ? window.innerWidth - panel.offsetWidth - PANEL_MARGIN\n : PANEL_MARGIN;\n const y = panelCorner.startsWith(\"bottom\")\n ? window.innerHeight - panel.offsetHeight - PANEL_MARGIN\n : PANEL_MARGIN;\n setPanelPosition(x, y);\n }\n\n function persistPanelCorner(): void {\n try {\n storage.setItem(PANEL_CORNER_KEY, panelCorner);\n } catch {\n // A posição ainda funciona durante a sessão quando o storage falha.\n }\n }\n\n function setPanelHiddenForPicker(hidden: boolean): void {\n panel.style.opacity = hidden ? \"0\" : \"1\";\n panel.style.pointerEvents = hidden ? \"none\" : \"auto\";\n }\n\n function save(): void {\n persistState(storage, state);\n }\n\n function toast(message: string): void {\n toastElement.textContent = message;\n toastElement.style.display = \"block\";\n if (toastTimer) clearTimeout(toastTimer);\n toastTimer = setTimeout(() => {\n toastElement.style.display = \"none\";\n }, 2500);\n }\n\n function renderPanel(): void {\n const sourceCount = state.items.filter((item) => item.source).length;\n panel.innerHTML = `<div data-fbc=\"header\" title=\"Arraste para mover · clique para recolher\" style=\"display:flex;align-items:center;gap:8px;padding:10px 12px;background:#2c2c2e;cursor:grab;user-select:none;touch-action:none;\">\n <span style=\"font-weight:600;\">Feedback</span>\n <span style=\"background:#2563eb;border-radius:10px;padding:0 8px;font-size:11px;\">${state.items.length}</span>\n ${state.items.length ? `<span style=\"font-size:11px;color:#a8a8ae;\">${sourceCount} com source</span>` : \"\"}\n <span style=\"margin-left:auto;color:#a8a8ae;font-size:11px;\">segure ALT + clique</span>\n <span data-fbc=\"toggle\" style=\"color:#a8a8ae;\">${collapsed ? \"▸\" : \"▾\"}</span>\n </div>${collapsed ? \"\" : `<div style=\"overflow-y:auto;flex:1;padding:8px 12px;display:flex;flex-direction:column;gap:8px;\">\n ${state.items.length ? state.items.map(renderItem).join(\"\") : '<div style=\"color:#a8a8ae;padding:12px 0;text-align:center;\">Nenhum item. Segure ALT e clique num elemento da página.</div>'}\n </div>\n <div style=\"display:flex;gap:8px;padding:10px 12px;background:#2c2c2e;\">\n <button data-fbc=\"copy\" ${state.items.length ? \"\" : \"disabled\"} style=\"flex:1;background:${state.items.length ? \"#2563eb\" : \"#3a3a3c\"};color:${state.items.length ? \"#fff\" : \"#a8a8ae\"};border:0;border-radius:6px;padding:8px;font:600 13px system-ui;cursor:${state.items.length ? \"pointer\" : \"default\"};\">Copiar backlog</button>\n <button data-fbc=\"clear\" style=\"background:#3a3a3c;color:#e5e5e7;border:0;border-radius:6px;padding:8px 12px;font:13px system-ui;cursor:pointer;\">Limpar</button>\n </div>`}`;\n if (!panelDrag) applyPanelCorner();\n }\n\n function deactivatePicker(): void {\n pickerActive = false;\n hoverElement = null;\n highlight.style.display = \"none\";\n setPanelHiddenForPicker(false);\n document.body.style.cursor = previousCursor;\n }\n\n function flashElement(element: HTMLElement): void {\n const previousOutline = element.style.outline;\n element.style.outline = \"3px solid #16a34a\";\n const timer = setTimeout(() => {\n element.style.outline = previousOutline;\n flashTimers.delete(timer);\n }, 400);\n flashTimers.add(timer);\n }\n\n function capture(element: Element): void {\n const item = captureElement(element);\n state.items.push(item);\n save();\n renderPanel();\n setTimeout(() => panel.querySelector<HTMLTextAreaElement>(`[data-fbc-ta=\"${CSS.escape(item.id)}\"]`)?.focus(), 50);\n if (element instanceof HTMLElement) flashElement(element);\n }\n\n async function copyBacklog(): Promise<void> {\n const markdown = toMarkdown(state.items);\n try {\n await navigator.clipboard.writeText(markdown);\n toast(`Backlog copiado (${state.items.length} itens). Cola no seu agente de código.`);\n } catch {\n window.prompt(\"Copie manualmente:\", markdown);\n }\n }\n\n function onKeyDown(event: KeyboardEvent): void {\n if (event.key === \"Alt\" && !pickerActive) {\n pickerActive = true;\n setPanelHiddenForPicker(true);\n document.body.style.cursor = \"crosshair\";\n }\n }\n\n function onKeyUp(event: KeyboardEvent): void {\n if (event.key === \"Alt\") deactivatePicker();\n }\n\n function onMouseMove(event: MouseEvent): void {\n if (!pickerActive) return;\n const element = document.elementFromPoint(event.clientX, event.clientY);\n if (!element || panel.contains(element) || highlight.contains(element) || element === highlight) {\n highlight.style.display = \"none\";\n hoverElement = null;\n return;\n }\n hoverElement = element;\n const rect = element.getBoundingClientRect();\n highlight.style.display = \"block\";\n highlight.style.left = `${rect.left}px`;\n highlight.style.top = `${rect.top}px`;\n highlight.style.width = `${rect.width}px`;\n highlight.style.height = `${rect.height}px`;\n const source = getSourceInfo(element);\n highlightLabel.textContent = `<${element.tagName.toLowerCase()}>${source ? ` ${source.file.split(\"/\").pop()}${source.line ? `:${source.line}` : \"\"}` : \"\"}`;\n }\n\n function onClick(event: MouseEvent): void {\n if (!pickerActive || !hoverElement || !(event.target instanceof Node) || panel.contains(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n capture(hoverElement);\n }\n\n function onPanelClick(event: MouseEvent): void {\n if (!(event.target instanceof Element)) return;\n const target = event.target;\n const action = target.getAttribute(\"data-fbc\");\n if (action === \"copy\") {\n void copyBacklog();\n return;\n }\n if (action === \"clear\") {\n if (state.items.length && window.confirm(`Limpar todos os ${state.items.length} itens?`)) {\n state.items = [];\n save();\n renderPanel();\n }\n return;\n }\n const deleteId = target.getAttribute(\"data-fbc-del\");\n if (deleteId) {\n state.items = state.items.filter((item) => item.id !== deleteId);\n save();\n renderPanel();\n return;\n }\n if (target.closest('[data-fbc=\"header\"]')) {\n if (suppressHeaderClick) {\n suppressHeaderClick = false;\n return;\n }\n collapsed = !collapsed;\n renderPanel();\n }\n }\n\n function onPanelPointerDown(event: PointerEvent): void {\n if (event.button !== 0 || !(event.target instanceof Element)) return;\n const header = event.target.closest<HTMLElement>('[data-fbc=\"header\"]');\n if (!header) return;\n const rect = panel.getBoundingClientRect();\n panelDrag = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n panelX: rect.left,\n panelY: rect.top,\n moved: false,\n header,\n };\n header.style.cursor = \"grabbing\";\n }\n\n function onPanelPointerMove(event: PointerEvent): void {\n if (!panelDrag || event.pointerId !== panelDrag.pointerId) return;\n const deltaX = event.clientX - panelDrag.startX;\n const deltaY = event.clientY - panelDrag.startY;\n if (!panelDrag.moved && Math.hypot(deltaX, deltaY) < DRAG_THRESHOLD) return;\n panelDrag.moved = true;\n event.preventDefault();\n setPanelPosition(panelDrag.panelX + deltaX, panelDrag.panelY + deltaY);\n }\n\n function finishPanelDrag(event: PointerEvent): void {\n if (!panelDrag || event.pointerId !== panelDrag.pointerId) return;\n const drag = panelDrag;\n panelDrag = null;\n drag.header.style.cursor = \"grab\";\n if (!drag.moved) return;\n\n const rect = panel.getBoundingClientRect();\n const horizontal = rect.left + rect.width / 2 < window.innerWidth / 2 ? \"left\" : \"right\";\n const vertical = rect.top + rect.height / 2 < window.innerHeight / 2 ? \"top\" : \"bottom\";\n panelCorner = `${vertical}-${horizontal}` as PanelCorner;\n suppressHeaderClick = true;\n if (dragClickTimer) clearTimeout(dragClickTimer);\n dragClickTimer = setTimeout(() => {\n suppressHeaderClick = false;\n dragClickTimer = undefined;\n }, 0);\n applyPanelCorner();\n persistPanelCorner();\n }\n\n function cancelPanelDrag(event: PointerEvent): void {\n if (!panelDrag || event.pointerId !== panelDrag.pointerId) return;\n panelDrag.header.style.cursor = \"grab\";\n panelDrag = null;\n applyPanelCorner();\n }\n\n function onViewportResize(): void {\n if (!panelDrag) applyPanelCorner();\n }\n\n function onPanelInput(event: Event): void {\n if (!(event.target instanceof HTMLTextAreaElement)) return;\n const id = event.target.getAttribute(\"data-fbc-ta\");\n const item = state.items.find((candidate) => candidate.id === id);\n if (item) {\n item.instruction = event.target.value;\n save();\n }\n }\n\n document.addEventListener(\"keydown\", onKeyDown, true);\n document.addEventListener(\"keyup\", onKeyUp, true);\n window.addEventListener(\"blur\", deactivatePicker);\n document.addEventListener(\"mousemove\", onMouseMove, true);\n document.addEventListener(\"click\", onClick, true);\n panel.addEventListener(\"click\", onPanelClick);\n panel.addEventListener(\"input\", onPanelInput);\n panel.addEventListener(\"pointerdown\", onPanelPointerDown);\n window.addEventListener(\"pointermove\", onPanelPointerMove, { passive: false });\n window.addEventListener(\"pointerup\", finishPanelDrag);\n window.addEventListener(\"pointercancel\", cancelPanelDrag);\n window.addEventListener(\"resize\", onViewportResize);\n document.body.append(highlight, panel, toastElement);\n renderPanel();\n\n const controller: FeedbackCollectorController = {\n get mounted() {\n return mounted;\n },\n get items() {\n return state.items;\n },\n exportMarkdown() {\n return toMarkdown(state.items);\n },\n destroy() {\n if (!mounted) return;\n mounted = false;\n deactivatePicker();\n document.removeEventListener(\"keydown\", onKeyDown, true);\n document.removeEventListener(\"keyup\", onKeyUp, true);\n window.removeEventListener(\"blur\", deactivatePicker);\n document.removeEventListener(\"mousemove\", onMouseMove, true);\n document.removeEventListener(\"click\", onClick, true);\n panel.removeEventListener(\"click\", onPanelClick);\n panel.removeEventListener(\"input\", onPanelInput);\n panel.removeEventListener(\"pointerdown\", onPanelPointerDown);\n window.removeEventListener(\"pointermove\", onPanelPointerMove);\n window.removeEventListener(\"pointerup\", finishPanelDrag);\n window.removeEventListener(\"pointercancel\", cancelPanelDrag);\n window.removeEventListener(\"resize\", onViewportResize);\n if (toastTimer) clearTimeout(toastTimer);\n if (dragClickTimer) clearTimeout(dragClickTimer);\n for (const timer of flashTimers) clearTimeout(timer);\n flashTimers.clear();\n highlight.remove();\n panel.remove();\n toastElement.remove();\n },\n };\n\n console.log(`[feedback-collector] ativo. Segure ALT + clique pra capturar. ${state.items.length} item(ns) restaurado(s) do localStorage.`);\n return controller;\n}\n","import { createCollector } from \"./collector\";\nimport type { FeedbackCollectorController, MountOptions } from \"./types\";\n\ndeclare global {\n interface Window {\n __FEEDBACK_COLLECTOR__?: boolean | FeedbackCollectorController;\n }\n}\n\nlet activeController: FeedbackCollectorController | null = null;\nlet pendingAutoMount: (() => void) | null = null;\n\nexport function mount(options: MountOptions = {}): FeedbackCollectorController {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n throw new Error(\"feedback-collector: mount() só pode ser chamado no navegador.\");\n }\n if (activeController?.mounted) return activeController;\n\n const existing = window.__FEEDBACK_COLLECTOR__;\n if (existing && typeof existing === \"object\" && existing.mounted) {\n activeController = existing;\n return existing;\n }\n if (existing === true) {\n throw new Error(\"feedback-collector: uma versão anterior já está montada nesta página.\");\n }\n\n activeController = createCollector(options);\n window.__FEEDBACK_COLLECTOR__ = activeController;\n return activeController;\n}\n\nexport function destroy(): void {\n if (pendingAutoMount) {\n document.removeEventListener(\"DOMContentLoaded\", pendingAutoMount);\n pendingAutoMount = null;\n }\n activeController?.destroy();\n activeController = null;\n if (typeof window !== \"undefined\") delete window.__FEEDBACK_COLLECTOR__;\n}\n\nexport function autoMount(): void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n // Uma v0.1 já injetada usa o booleano; auto-init duplicado continua sendo no-op.\n if (window.__FEEDBACK_COLLECTOR__ === true) return;\n if (document.readyState === \"loading\") {\n pendingAutoMount = () => {\n pendingAutoMount = null;\n mount();\n };\n document.addEventListener(\"DOMContentLoaded\", pendingAutoMount, { once: true });\n return;\n }\n mount();\n}\n"]}
@@ -0,0 +1,24 @@
1
+ var FeedbackCollector=(function(exports){'use strict';var ue=["display","position","width","height","margin","padding","color","background-color","font-size","font-weight","line-height","border","border-radius","gap","flex-direction","justify-content","align-items","grid-template-columns","overflow","z-index","opacity","box-shadow","text-align"],pe=new Set(["none","normal","auto","rgba(0, 0, 0, 0)","0px","visible","static","start"]);function V(t){let n=t;for(let e in n)if(e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"))return n[e];return null}function fe(t){let n=t;for(;n;){let e=n.type;if(typeof n.type=="function")return e?.displayName||e?.name||"";if(e&&typeof e=="object"&&e.displayName)return e.displayName;n=n._debugOwner||n.return;}return ""}function me(t){return t.match(/(?:^|\/)((?:src|app|pages|components|lib|features)\/.*)$/)?.[1]||t}function ge(t){let n=t.match(/^(.*):(\d+):(\d+)$/);if(n)return {file:n[1]||t,line:n[2]||"",column:n[3]||""};let e=t.match(/^(.*):(\d+)$/);return {file:e?.[1]||t,line:e?.[2]||"",column:""}}function I(t){let n=t,e=0;for(;n&&n!==document.body;){let a=n.getAttribute("data-inspector-relative-path"),s=n.getAttribute("data-source");if(a||s){let l=s?ge(s):null;return {file:a||l?.file||"",line:n.getAttribute("data-inspector-line")||l?.line||"",column:n.getAttribute("data-inspector-column")||l?.column||"",via:"data-attr",ownerHops:e}}n=n.parentElement,e+=1;}let r=V(t),u=0;for(;r&&u<20;){let a=r._debugSource;if(a?.fileName)return {file:me(a.fileName),line:a.lineNumber||"",column:a.columnNumber||"",via:"fiber",componentName:fe(r)};r=r._debugOwner||r.return||null,u+=1;}return null}function be(t){let n=V(t),e=[],r=0;for(;n&&e.length<3&&r<30;){let u=n.type,a=typeof n.type=="function"?u?.displayName||u?.name:u?.displayName;a&&!e.includes(a)&&e.push(a),n=n._debugOwner||n.return||null,r+=1;}return e}function W(t){return typeof CSS<"u"&&CSS.escape?CSS.escape(t):t.replace(/[^a-zA-Z0-9_-]/g,"\\$&")}function he(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ye(t){if(t.id)return `#${W(t.id)}`;let n=[],e=t;for(;e&&e!==document.body&&n.length<5;){let r=e.tagName.toLowerCase(),u=false;for(let a of ["data-testid","data-test","aria-label","name"]){let s=e.getAttribute(a);if(s){r+=`[${a}="${he(s)}"]`,u=true;break}}if(!u&&e.classList.length){let a=Array.from(e.classList).filter(s=>!/^[a-z]*[_-][a-zA-Z0-9]{5,}$/.test(s)&&!/^\d/.test(s)&&s.length<30).slice(0,2);a.length&&(r+=`.${a.map(W).join(".")}`,u=true);}if(!u){let a=1,s=e.previousElementSibling;for(;s;)s.tagName===e.tagName&&(a+=1),s=s.previousElementSibling;a>1&&(r+=`:nth-of-type(${a})`);}n.unshift(r);try{if(document.querySelectorAll(n.join(" > ")).length===1)break}catch{}e=e.parentElement;}return n.join(" > ")}function xe(t){let n=getComputedStyle(t),e={};for(let r of ue){let u=n.getPropertyValue(r);u&&!pe.has(u)&&(e[r]=u);}return e}function ve(t,n){let e=t.outerHTML||"";return e.length<=n?e:`${e.slice(0,n)}\u2026 [truncado]`}function J(t){let n=t.getBoundingClientRect();return {id:`${Date.now()}_${Math.random().toString(36).slice(2,7)}`,url:location.pathname+location.search+location.hash,tag:t.tagName.toLowerCase(),selector:ye(t),source:I(t),components:be(t),text:(t.textContent||"").trim().slice(0,120),html:ve(t,600),styles:xe(t),rect:{x:Math.round(n.x),y:Math.round(n.y),w:Math.round(n.width),h:Math.round(n.height)},viewport:`${window.innerWidth}x${window.innerHeight}`,instruction:"",ts:new Date().toISOString()}}function g(t){return String(t).replace(/`/g,"\\`")}function A(t,n=new Date){let e=["# Backlog de feedback visual","",`Gerado em ${n.toLocaleString()} \u2014 ${t.length} itens.`,"Cada item indica o arquivo:linha quando dispon\xEDvel. Execute na ordem, agrupando edits do mesmo arquivo.",""];return t.forEach((r,u)=>{if(e.push(`## ${u+1}. ${r.instruction?r.instruction.split(`
2
+ `)[0]:"(sem instru\xE7\xE3o)"}`),e.push(""),r.instruction.includes(`
3
+ `)&&e.push(r.instruction,""),e.push(`- **Rota:** \`${g(r.url)}\``),r.source){let s=`${r.source.file}${r.source.line?`:${r.source.line}`:""}`,l=r.source.componentName?` (componente \`${g(r.source.componentName)}\`)`:"";e.push(`- **Source:** \`${g(s)}\`${l}`);}else r.components.length&&e.push(`- **Componentes (do mais interno):** ${r.components.map(s=>`\`${g(s)}\``).join(" \u2192 ")}`);e.push(`- **Elemento:** \`<${g(r.tag)}>\` \u2014 seletor: \`${g(r.selector)}\``),r.text&&e.push(`- **Texto vis\xEDvel:** "${r.text}"`),e.push(`- **Posi\xE7\xE3o:** ${r.rect.w}x${r.rect.h} @ (${r.rect.x},${r.rect.y}), viewport ${r.viewport}`);let a=Object.entries(r.styles);a.length&&e.push(`- **Styles atuais:** ${a.map(([s,l])=>`\`${g(s)}: ${g(l)}\``).join(", ")}`),e.push("","```html",r.html,"```","");}),e.join(`
4
+ `)}var Z="__fbc_state_v2",we="__fbc_items_v1";var Q=()=>({version:2,items:[]});function U(t){if(!t)return null;try{return JSON.parse(t)}catch{return null}}function Ee(t){return !!t&&typeof t=="object"&&Array.isArray(t.items)}function Se(t,n){let e=U(t);if(Ee(e)&&e.version===2)return {state:{version:2,items:e.items},migrated:false};let r=U(n);return Array.isArray(r)?{state:{version:2,items:r},migrated:true}:{state:Q(),migrated:false}}function O(t,n){try{return t.setItem(Z,JSON.stringify(n)),!0}catch{return false}}function ee(t){let n=null,e=null;try{n=t.getItem(Z),e=t.getItem(we);}catch{return Q()}let r=Se(n,e);return r.migrated&&O(t,r.state),r.state}var ke="position:fixed;pointer-events:none;z-index:2147483645;border:2px solid #2563eb;background:rgba(37,99,235,.08);border-radius:2px;display:none;transition:all .05s linear;",$e="position:absolute;top:-22px;left:0;background:#2563eb;color:#fff;font:11px/1.4 ui-monospace,monospace;padding:1px 6px;border-radius:2px;white-space:nowrap;",Le="position:fixed;bottom:16px;right:16px;width:340px;max-width:calc(100vw - 32px);max-height:70vh;z-index:2147483646;background:#1c1c1e;color:#e5e5e7;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.4);font:13px/1.45 system-ui,sans-serif;display:flex;flex-direction:column;overflow:hidden;transition:opacity .08s ease;",Ce="position:fixed;bottom:16px;left:50%;transform:translateX(-50%);z-index:2147483647;background:#15803d;color:#fff;padding:8px 16px;border-radius:8px;font:13px system-ui,sans-serif;display:none;box-shadow:0 4px 14px rgba(0,0,0,.3);",te="__fbc_panel_corner_v1",m=16,_e=4;function Te(t){return t==="top-left"||t==="top-right"||t==="bottom-left"||t==="bottom-right"}function E(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/"/g,"&quot;")}function Ie(t,n){let e=t.source?`${t.source.file.split("/").slice(-2).join("/")}${t.source.line?`:${t.source.line}`:""}`:t.components[0]?`<${t.components[0]}>`:t.selector.slice(0,40);return `<div style="background:#2c2c2e;border-radius:8px;padding:8px;">
5
+ <div style="display:flex;align-items:baseline;gap:6px;margin-bottom:6px;">
6
+ <span style="color:#a8a8ae;font-size:11px;">#${n+1}</span>
7
+ <span style="font-family:ui-monospace,monospace;font-size:11px;color:#64d2ff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;" title="${E(t.selector)}">${E(e)}</span>
8
+ <span data-fbc-del="${E(t.id)}" style="cursor:pointer;color:#a8a8ae;padding:0 4px;" title="Remover">\u2715</span>
9
+ </div>
10
+ <textarea data-fbc-ta="${E(t.id)}" placeholder="O que mudar aqui?" style="width:100%;box-sizing:border-box;background:#1c1c1e;color:#e5e5e7;border:1px solid #3a3a3c;border-radius:6px;padding:6px;font:13px system-ui;resize:vertical;min-height:40px;">${E(t.instruction)}</textarea>
11
+ </div>`}function ne(t={}){if(!document.body)throw new Error("feedback-collector: mount() requer document.body dispon\xEDvel.");let n=t.storage||window.localStorage,e=ee(n),r=false,u=null,a=false,s="bottom-right",l=null,S=false,_=true,v,y,k=new Set,re=document.body.style.cursor,p=document.createElement("div");p.dataset.fbcRoot="highlight",p.style.cssText=ke;let T=document.createElement("div");T.style.cssText=$e,p.append(T);let c=document.createElement("div");c.dataset.fbcRoot="panel",c.style.cssText=Le;let h=document.createElement("div");h.dataset.fbcRoot="toast",h.style.cssText=Ce;try{let o=n.getItem(te);Te(o)&&(s=o);}catch{}function P(o,i){let d=Math.max(m,window.innerWidth-c.offsetWidth-m),f=Math.max(m,window.innerHeight-c.offsetHeight-m);c.style.left=`${Math.min(Math.max(m,o),d)}px`,c.style.top=`${Math.min(Math.max(m,i),f)}px`,c.style.right="auto",c.style.bottom="auto";}function $(){let o=s.endsWith("right")?window.innerWidth-c.offsetWidth-m:m,i=s.startsWith("bottom")?window.innerHeight-c.offsetHeight-m:m;P(o,i);}function ie(){try{n.setItem(te,s);}catch{}}function M(o){c.style.opacity=o?"0":"1",c.style.pointerEvents=o?"none":"auto";}function L(){O(n,e);}function ae(o){h.textContent=o,h.style.display="block",v&&clearTimeout(v),v=setTimeout(()=>{h.style.display="none";},2500);}function w(){let o=e.items.filter(i=>i.source).length;c.innerHTML=`<div data-fbc="header" title="Arraste para mover \xB7 clique para recolher" style="display:flex;align-items:center;gap:8px;padding:10px 12px;background:#2c2c2e;cursor:grab;user-select:none;touch-action:none;">
12
+ <span style="font-weight:600;">Feedback</span>
13
+ <span style="background:#2563eb;border-radius:10px;padding:0 8px;font-size:11px;">${e.items.length}</span>
14
+ ${e.items.length?`<span style="font-size:11px;color:#a8a8ae;">${o} com source</span>`:""}
15
+ <span style="margin-left:auto;color:#a8a8ae;font-size:11px;">segure ALT + clique</span>
16
+ <span data-fbc="toggle" style="color:#a8a8ae;">${a?"\u25B8":"\u25BE"}</span>
17
+ </div>${a?"":`<div style="overflow-y:auto;flex:1;padding:8px 12px;display:flex;flex-direction:column;gap:8px;">
18
+ ${e.items.length?e.items.map(Ie).join(""):'<div style="color:#a8a8ae;padding:12px 0;text-align:center;">Nenhum item. Segure ALT e clique num elemento da p\xE1gina.</div>'}
19
+ </div>
20
+ <div style="display:flex;gap:8px;padding:10px 12px;background:#2c2c2e;">
21
+ <button data-fbc="copy" ${e.items.length?"":"disabled"} style="flex:1;background:${e.items.length?"#2563eb":"#3a3a3c"};color:${e.items.length?"#fff":"#a8a8ae"};border:0;border-radius:6px;padding:8px;font:600 13px system-ui;cursor:${e.items.length?"pointer":"default"};">Copiar backlog</button>
22
+ <button data-fbc="clear" style="background:#3a3a3c;color:#e5e5e7;border:0;border-radius:6px;padding:8px 12px;font:13px system-ui;cursor:pointer;">Limpar</button>
23
+ </div>`}`,l||$();}function C(){r=false,u=null,p.style.display="none",M(false),document.body.style.cursor=re;}function se(o){let i=o.style.outline;o.style.outline="3px solid #16a34a";let d=setTimeout(()=>{o.style.outline=i,k.delete(d);},400);k.add(d);}function le(o){let i=J(o);e.items.push(i),L(),w(),setTimeout(()=>c.querySelector(`[data-fbc-ta="${CSS.escape(i.id)}"]`)?.focus(),50),o instanceof HTMLElement&&se(o);}async function ce(){let o=A(e.items);try{await navigator.clipboard.writeText(o),ae(`Backlog copiado (${e.items.length} itens). Cola no seu agente de c\xF3digo.`);}catch{window.prompt("Copie manualmente:",o);}}function N(o){o.key==="Alt"&&!r&&(r=true,M(true),document.body.style.cursor="crosshair");}function F(o){o.key==="Alt"&&C();}function D(o){if(!r)return;let i=document.elementFromPoint(o.clientX,o.clientY);if(!i||c.contains(i)||p.contains(i)||i===p){p.style.display="none",u=null;return}u=i;let d=i.getBoundingClientRect();p.style.display="block",p.style.left=`${d.left}px`,p.style.top=`${d.top}px`,p.style.width=`${d.width}px`,p.style.height=`${d.height}px`;let f=I(i);T.textContent=`<${i.tagName.toLowerCase()}>${f?` ${f.file.split("/").pop()}${f.line?`:${f.line}`:""}`:""}`;}function H(o){!r||!u||!(o.target instanceof Node)||c.contains(o.target)||(o.preventDefault(),o.stopPropagation(),le(u));}function Y(o){if(!(o.target instanceof Element))return;let i=o.target,d=i.getAttribute("data-fbc");if(d==="copy"){ce();return}if(d==="clear"){e.items.length&&window.confirm(`Limpar todos os ${e.items.length} itens?`)&&(e.items=[],L(),w());return}let f=i.getAttribute("data-fbc-del");if(f){e.items=e.items.filter(X=>X.id!==f),L(),w();return}if(i.closest('[data-fbc="header"]')){if(S){S=false;return}a=!a,w();}}function z(o){if(o.button!==0||!(o.target instanceof Element))return;let i=o.target.closest('[data-fbc="header"]');if(!i)return;let d=c.getBoundingClientRect();l={pointerId:o.pointerId,startX:o.clientX,startY:o.clientY,panelX:d.left,panelY:d.top,moved:false,header:i},i.style.cursor="grabbing";}function j(o){if(!l||o.pointerId!==l.pointerId)return;let i=o.clientX-l.startX,d=o.clientY-l.startY;!l.moved&&Math.hypot(i,d)<_e||(l.moved=true,o.preventDefault(),P(l.panelX+i,l.panelY+d));}function B(o){if(!l||o.pointerId!==l.pointerId)return;let i=l;if(l=null,i.header.style.cursor="grab",!i.moved)return;let d=c.getBoundingClientRect(),f=d.left+d.width/2<window.innerWidth/2?"left":"right";s=`${d.top+d.height/2<window.innerHeight/2?"top":"bottom"}-${f}`,S=true,y&&clearTimeout(y),y=setTimeout(()=>{S=false,y=void 0;},0),$(),ie();}function G(o){!l||o.pointerId!==l.pointerId||(l.header.style.cursor="grab",l=null,$());}function q(){l||$();}function K(o){if(!(o.target instanceof HTMLTextAreaElement))return;let i=o.target.getAttribute("data-fbc-ta"),d=e.items.find(f=>f.id===i);d&&(d.instruction=o.target.value,L());}document.addEventListener("keydown",N,true),document.addEventListener("keyup",F,true),window.addEventListener("blur",C),document.addEventListener("mousemove",D,true),document.addEventListener("click",H,true),c.addEventListener("click",Y),c.addEventListener("input",K),c.addEventListener("pointerdown",z),window.addEventListener("pointermove",j,{passive:false}),window.addEventListener("pointerup",B),window.addEventListener("pointercancel",G),window.addEventListener("resize",q),document.body.append(p,c,h),w();let de={get mounted(){return _},get items(){return e.items},exportMarkdown(){return A(e.items)},destroy(){if(_){_=false,C(),document.removeEventListener("keydown",N,true),document.removeEventListener("keyup",F,true),window.removeEventListener("blur",C),document.removeEventListener("mousemove",D,true),document.removeEventListener("click",H,true),c.removeEventListener("click",Y),c.removeEventListener("input",K),c.removeEventListener("pointerdown",z),window.removeEventListener("pointermove",j),window.removeEventListener("pointerup",B),window.removeEventListener("pointercancel",G),window.removeEventListener("resize",q),v&&clearTimeout(v),y&&clearTimeout(y);for(let o of k)clearTimeout(o);k.clear(),p.remove(),c.remove(),h.remove();}}};return console.log(`[feedback-collector] ativo. Segure ALT + clique pra capturar. ${e.items.length} item(ns) restaurado(s) do localStorage.`),de}var b=null,x=null;function R(t={}){if(typeof window>"u"||typeof document>"u")throw new Error("feedback-collector: mount() s\xF3 pode ser chamado no navegador.");if(b?.mounted)return b;let n=window.__FEEDBACK_COLLECTOR__;if(n&&typeof n=="object"&&n.mounted)return b=n,n;if(n===true)throw new Error("feedback-collector: uma vers\xE3o anterior j\xE1 est\xE1 montada nesta p\xE1gina.");return b=ne(t),window.__FEEDBACK_COLLECTOR__=b,b}function Ae(){x&&(document.removeEventListener("DOMContentLoaded",x),x=null),b?.destroy(),b=null,typeof window<"u"&&delete window.__FEEDBACK_COLLECTOR__;}function oe(){if(!(typeof window>"u"||typeof document>"u")&&window.__FEEDBACK_COLLECTOR__!==true){if(document.readyState==="loading"){x=()=>{x=null,R();},document.addEventListener("DOMContentLoaded",x,{once:true});return}R();}}oe();exports.destroy=Ae;exports.mount=R;return exports;})({});//# sourceMappingURL=feedback-collector.js.map
24
+ //# sourceMappingURL=feedback-collector.js.map