# @seniorsistemas/angular-components

Biblioteca de componentes Angular reutilizáveis da Senior Sistemas, construída com Angular 18 e Tailwind CSS.

Inclui mais de 70 componentes, diretivas e pipes para construção de interfaces — desde inputs e formulários dinâmicos até tabelas, kanban, chat e muito mais.

## Documentação

A documentação oficial é feita via **Storybook**. Cada componente tem stories com exemplos interativos, descrição de inputs/outputs e variantes visuais.

### Rodar o Storybook localmente

```bash
npm run storybook
```

Acesse em `http://localhost:6006`.

### Build do Storybook

```bash
npm run build-storybook
```

O output é gerado em `storybook-static/`.

## Showcase

Além do Storybook, há um projeto de showcase com exemplos reais de uso:

```bash
npm run start
```

Acesse em `http://localhost:4200`.

## Estrutura do monorepo

```
projects/
  angular-components/     # Biblioteca de componentes
    <nome-componente>/    # Cada componente é um sub-pacote independente
      src/lib/
      ng-package.json
  showcase/               # Aplicação de demonstração
```

## Instalação

```bash
npm install @seniorsistemas/angular-components
```

Cada componente é importado individualmente pelo seu sub-pacote:

```typescript
import { ButtonComponent } from '@seniorsistemas/angular-components/button';
import { DynamicFormComponent } from '@seniorsistemas/angular-components/dynamic-form';

@Component({
  standalone: true,
  imports: [ButtonComponent, DynamicFormComponent],
})
export class MeuComponent {}
```

Os componentes são standalone. Os `*Module` (ex.: `ButtonModule`) estão depreciados e serão removidos na v20; para migrar o seu código automaticamente, use `ng generate @seniorsistemas/angular-components:migrate-modules-to-standalone`.

Para a configuração global da aplicação (`app.config.ts`), use as funções `provide*` no lugar dos `forRoot()` dos módulos:

```typescript
import { provideAngularComponents } from '@seniorsistemas/angular-components/common';
import { provideLocale } from '@seniorsistemas/angular-components/locale';

export const appConfig: ApplicationConfig = {
  providers: [provideAngularComponents({ domain: 'meu_dominio', service: 'meu_servico' }), provideLocale()],
};
```

## Schematics de migração

A biblioteca oferece schematics de migração via `ng update`, então é boa prática sempre atualizar a versão instalada com esse comando em vez de só trocar o número no `package.json` — além de atualizar a dependência, ele aplica automaticamente as migrations necessárias no seu projeto e mostra o que há de novo relevante para o seu código:

```bash
ng update @seniorsistemas/angular-components
```

Migrations disponíveis (por versão em que passam a ser aplicadas):

| Versão   | Migration                                  | O que faz                                                                                                                                                                                                                                   |
| -------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `19.0.0` | `migration-v19-0-0-dynamic-form`           | Migra o `DynamicForm` de v18 para v19: construtores → plain objects, enums → string literals, `[fields]` → `[configs]`, `Editor` → `provideEditorField()`, estilos → `angular.json`                                                         |
| `19.0.0` | `migration-v19-0-0-steps-to-stepper`       | Migra `Steps` para `Stepper`: `<s-steps>` → `<s-stepper>`, import de `.../steps` → `.../stepper`, `StepsComponent` → `StepperComponent`, e remove o `StepsModule` (componente agora standalone) substituindo por `StepperComponent`         |
| `19.6.0` | `migration-v19-6-0-p-datepicker`           | Migra `p-datepicker` (PrimeNG) para `s-datepicker` (`@seniorsistemas/angular-components`)                                                                                                                                                   |
| `19.6.0` | `migration-v19-6-0-p-editor`               | Migra `p-editor` (PrimeNG/Quill) para `s-editor`: renomeia tag e eventos, remove atributos sem equivalente, limpa configs legadas do `DynamicForm` e atualiza dependências do `package.json`                                                |
| `19.6.2` | `migration-v19-6-2-s-chips-outputs`        | Renomeia outputs legados do `s-chips`: `onAdd`→`added`, `onRemove`→`removed`, `onChipClick`→`chipClicked`, `onFocus`→`focused`, `onBlur`→`focusLost`                                                                                        |
| `19.9.3` | `migration-v19-9-3-fieldset-body-template` | Envolve o conteúdo projetado do `s-fieldset` em `<ng-template sTemplate="body">`, mantendo templates de slot como `sTemplate="header"` fora do body, e garante o `TemplateDirective` no escopo do componente (standalone ou via `NgModule`) |
| `20.0.0` | `migration-v20-0-0-migrate-v20` | Prepara o projeto para a v20, executando automaticamente seletores, pacotes alias, APIs depreciadas, `dynamic-form`, datepicker e módulos → standalone (ver [Preparar para a v20](#preparar-para-a-v20)) |

A lista completa, com a `version` que dispara cada migration e a `factory` correspondente, fica em [`projects/angular-components/schematics/migrations.json`](projects/angular-components/schematics/migrations.json).

### Preparar para a v20

A v20 remove os seletores, pacotes alias, APIs e `*Module` depreciados na v19. Você pode migrar o seu código **agora, ainda na v19**, com o schematic `migrate-v20`. Ao atualizar para a `20.0.0`, o `ng update` executa **todos os itens automaticamente, sem perguntar**, porque tudo isso deixa de existir na v20:

```bash
ng generate @seniorsistemas/angular-components:migrate-v20
```

Rodando pelo `ng generate`, ele pergunta o que migrar, com um checkbox por item e a opção **Marcar todos** (liga e desliga todos os itens):

```
? O que deseja migrar?
 ◉ Marcar todos
 ◉ Seletores depreciados (s-sidebar → s-drawer, s-steps → s-stepper, ...)
 ◉ Pacotes e símbolos alias (sidebar → drawer, steps → stepper, ...)
 ◉ Inputs, outputs e APIs depreciadas (onCodeChange, scale, pipes localized*, ...)
 ◉ Dynamic-form (fields → configs, integer → number, textAreaIA, ...)
 ◉ Datepicker (remove sCalendarMask e sDatepickerNoPeriodTab)
 ◉ Módulos → standalone (ButtonModule, LocaleModule.forRoot(), ...)
```

No final ele mostra um resumo por item e a lista de **pendências manuais** (com arquivo e linha) que a migração automática não conseguiu resolver. Recomendamos commitar antes de rodar, para revisar o diff. Use `--dry-run` para ver o que seria alterado sem gravar.

**Atualize a lib antes de rodar pelo `ng generate`.** O código migrado usa APIs novas, como `provideLocale()` e `provideAngularComponents()`. Se o projeto ainda estiver numa versão anterior da lib, ele não compila depois da migração. Pelo `ng update` isso não acontece, porque a lib é atualizada antes das migrações.

O item de módulos lê o template de cada componente declarado no `NgModule` para importar só os standalones usados. Ele segue imports relativos e os aliases de `paths` do `tsconfig.json` (ex.: `~features/*`). Quando não consegue ler um template, importa todos os standalones do módulo e avisa nas pendências manuais.

Para usar sem terminal interativo (CI) ou migrar só uma parte:

| Opção               | O que faz                                                                                                                              |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `--all`             | Executa todos os itens, sem perguntar                                                                                                  |
| `--items=a,b`       | Executa só os itens informados: `selectors`, `imports`, `apis`, `dynamic-form`, `datepicker`, `modules`, `app-standalone`             |
| `--skip=a,b`        | Pula os itens informados                                                                                                               |
| `--path=src/app`    | Limita a migração a uma pasta                                                                                                          |
| `--project=meu-app` | Limita a migração ao projeto do `angular.json`                                                                                         |

Sem terminal interativo e sem `--items`/`--all`, todos os itens são executados (a conversão do app para standalone só roda com `--items=app-standalone`).

Cada item também roda isolado, sem perguntas:

```bash
ng generate @seniorsistemas/angular-components:migrate-deprecated-selectors
ng generate @seniorsistemas/angular-components:migrate-deprecated-imports
ng generate @seniorsistemas/angular-components:migrate-deprecated-apis
ng generate @seniorsistemas/angular-components:migrate-deprecated-dynamic-form
ng generate @seniorsistemas/angular-components:migrate-deprecated-datepicker
ng generate @seniorsistemas/angular-components:migrate-modules-to-standalone
```

**Migrações nativas do Angular (standalone).** O `migrate-v20` **não pergunta** sobre a conversão do seu app para standalone. Ao terminar, ele avisa que existe um schematic para isso e lista o que ele faz. Essas migrações são feitas **pelo Angular**: o `migrate-app-to-standalone` é só um wrapper que chama o schematic oficial [`@angular/core:standalone`](https://angular.dev/reference/migrations/standalone). Por isso o resultado e eventuais problemas dessa etapa vêm do schematic do Angular, e não do angular-components. O Angular a executa em 3 modos, nesta ordem:

1. `convert-to-standalone`: converte componentes, diretivas e pipes para standalone (remove `standalone: false` e adiciona as dependências ao `imports` de cada um) e atualiza os NgModules que os declaravam, que passam a importá-los em vez de declará-los.
2. `prune-ng-modules`: remove os NgModules que ficaram sem função depois da conversão (sem `declarations`, `providers` nem `bootstrap`, e que não são usados em testes) e as referências a eles nos `imports`/`exports` de outros módulos.
3. `standalone-bootstrap`: troca `platformBrowserDynamic().bootstrapModule(AppModule)` por `bootstrapApplication(AppComponent, ...)`, move os providers e imports do módulo raiz para a configuração do bootstrap (por exemplo, `app.config.ts`, usando funções como `provideRouter` e `provideHttpClient` quando há equivalente) e remove o módulo raiz.

O Angular recomenda rodar um modo por vez, conferir o build e revisar o diff entre eles. Para executar, use `--mode` e `--path` para limitar:

```bash
ng generate @seniorsistemas/angular-components:migrate-app-to-standalone
```

### Executando uma migration individualmente

Se você já está na versão instalada (não chegou até ela via `ng update`) e só precisa aplicar uma migration específica no seu projeto, sem atualizar nada, há duas formas:

**Via `ng generate`** (mais simples) — cada migration também está disponível com um nome curto, sem o prefixo de versão (`migrate-<nome>` em vez de `migration-v<versão>-<nome>`):

```bash
ng generate @seniorsistemas/angular-components:migrate-fieldset-body-template
```

**Via `ng update --name`** (mais completo) — usa o nome versionado, o mesmo que aparece na tabela acima:

```bash
ng update @seniorsistemas/angular-components --name migration-v19-9-3-fieldset-body-template
```

Os dois rodam exatamente a mesma migration e nenhum dos dois altera a versão instalada ou reinstala dependências.

## Build da biblioteca

```bash
npm run build
```

## Testes

```bash
npm run test
```

