@seniorsistemas/angular-components 19.3.3 → 19.3.4

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.
Files changed (76) hide show
  1. package/accordion/README.md +166 -0
  2. package/alert/README.md +92 -0
  3. package/autocomplete/README.md +162 -0
  4. package/badge/README.md +126 -0
  5. package/bignumber-input/README.md +122 -0
  6. package/breadcrumb/README.md +144 -0
  7. package/button/README.md +159 -0
  8. package/calendar-mask/README.md +89 -0
  9. package/card/README.md +133 -0
  10. package/chat/README.md +130 -0
  11. package/checkbox/README.md +108 -0
  12. package/checkbox-list/README.md +149 -0
  13. package/chips/README.md +152 -0
  14. package/code-editor/README.md +149 -0
  15. package/collapse-link/README.md +128 -0
  16. package/confirm-dialog/README.md +105 -0
  17. package/content-generator/README.md +111 -0
  18. package/control-errors/README.md +92 -0
  19. package/country-phone-picker/README.md +121 -0
  20. package/currency/README.md +90 -0
  21. package/custom-fields/README.md +142 -0
  22. package/dialog/README.md +152 -0
  23. package/dynamic-form/README.md +176 -0
  24. package/editable-overlay/README.md +98 -0
  25. package/empty-state/README.md +134 -0
  26. package/esm2022/loading-state/lib/loading-state/loading-state.component.mjs +4 -4
  27. package/fesm2022/seniorsistemas-angular-components-loading-state.mjs +3 -3
  28. package/fesm2022/seniorsistemas-angular-components-loading-state.mjs.map +1 -1
  29. package/fieldset/README.md +135 -0
  30. package/file-picker/README.md +162 -0
  31. package/file-upload/README.md +23 -7
  32. package/gantt/README.md +173 -0
  33. package/global-search/README.md +151 -0
  34. package/grid-menu/README.md +123 -0
  35. package/help-popover/README.md +134 -0
  36. package/ia-insight/README.md +24 -6
  37. package/image-cropper/README.md +140 -0
  38. package/infinite-scroll/README.md +130 -0
  39. package/info-sign/README.md +111 -0
  40. package/inline-edit/README.md +139 -0
  41. package/insights/README.md +159 -0
  42. package/interactive-content/README.md +120 -0
  43. package/kanban/README.md +184 -0
  44. package/label-value/README.md +154 -0
  45. package/loading-state/README.md +141 -0
  46. package/localized-number-input/README.md +128 -0
  47. package/mouse-events/README.md +157 -0
  48. package/navigation-button/README.md +160 -0
  49. package/numeric/README.md +147 -0
  50. package/numeric-mask/README.md +170 -0
  51. package/object-card/README.md +158 -0
  52. package/package.json +1 -1
  53. package/paginator/README.md +121 -0
  54. package/panel/README.md +147 -0
  55. package/password-strength/README.md +144 -0
  56. package/picklist/README.md +170 -0
  57. package/pin-code-field/README.md +137 -0
  58. package/product-header/README.md +33 -6
  59. package/profile-picture-picker/README.md +159 -0
  60. package/progressbar/README.md +136 -0
  61. package/radio-button/README.md +117 -0
  62. package/rating-scale/README.md +154 -0
  63. package/select/README.md +147 -0
  64. package/select-button/README.md +137 -0
  65. package/sidebar/README.md +117 -0
  66. package/slide-in-bar/README.md +122 -0
  67. package/slider/README.md +127 -0
  68. package/speech-recognition/README.md +104 -0
  69. package/split-button/README.md +126 -0
  70. package/spotlight/README.md +200 -0
  71. package/star-rating/README.md +127 -0
  72. package/stats-card/README.md +135 -0
  73. package/stepper/README.md +164 -0
  74. package/switch/README.md +125 -0
  75. package/table/README.md +185 -0
  76. package/text-area-ia/README.md +17 -6
@@ -0,0 +1,122 @@
1
+ # SlideInBar
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Componente de painel deslizante lateral que expande e colapsa ao clicar em um botão de toggle. Em telas pequenas (largura <= 420px), entra automaticamente em modo overlay, sobrepondo o conteúdo.
6
+
7
+ > **Nota:** O seletor `s-slide-panel` e o pacote `slide-panel` estão descontinuados. Use `s-slide-in-bar` e o pacote `slide-in-bar` em novos projetos. O seletor antigo será removido na versão 20.0.0.
8
+
9
+ ## Quando usar
10
+
11
+ - Filtros laterais em listas e tabelas que podem ser ocultados para dar mais espaço ao conteúdo
12
+ - Painéis de detalhes ou configurações que coexistem com o conteúdo principal
13
+ - Propriedades ou atributos de um elemento selecionado na área principal
14
+ - Quando o painel deve empurrar o layout adjacente (`noOverlap`) ou flutuar sobre ele
15
+
16
+ ## Quando não usar
17
+
18
+ - Painéis que precisam de overlay com backdrop — prefira `Sidebar`
19
+ - Conteúdo que deve aparecer temporariamente em resposta a uma ação — prefira `Dialog` ou `Sidebar`
20
+
21
+ ## Instalação
22
+
23
+ ```typescript
24
+ import { SlideInBarModule, SlideInBarService } from '@seniorsistemas/angular-components/slide-in-bar';
25
+
26
+ @NgModule({
27
+ imports: [SlideInBarModule],
28
+ providers: [SlideInBarService],
29
+ })
30
+ export class MeuModule {}
31
+ ```
32
+
33
+ ## Uso básico
34
+
35
+ ```html
36
+ <s-slide-in-bar (panelOpened)="onAbrir()" (panelClosed)="onFechar()">
37
+ <div slide-content>
38
+ <!-- conteúdo do painel deslizante -->
39
+ </div>
40
+ <div side-content>
41
+ <!-- conteúdo principal ao lado do painel -->
42
+ </div>
43
+ </s-slide-in-bar>
44
+ ```
45
+
46
+ ## API
47
+
48
+ ### Inputs
49
+
50
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
51
+ |-------------|------|--------|:-----------:|-----------|
52
+ | `id` | `string` | `slide-panel-{n}` | Não | Identificador único do painel. Usado pelo `SlideInBarService` para fechar programaticamente |
53
+ | `openIcon` | `string` | `'fas fa-chevron-right'` | Não | Classe Font Awesome do ícone no botão de abertura |
54
+ | `closeIcon` | `string` | `'fas fa-chevron-left'` | Não | Classe Font Awesome do ícone no botão de fechamento |
55
+ | `cache` | `boolean` | `false` | Não | Mantém o conteúdo no DOM quando fechado, preservando estado interno |
56
+ | `createOpen` | `boolean` | `false` | Não | Inicia o painel já aberto |
57
+ | `noOverlap` | `boolean` | `false` | Não | O painel empurra o layout adjacente em vez de sobrepor o conteúdo |
58
+
59
+ ### Outputs
60
+
61
+ | Evento | Tipo | Descrição |
62
+ |--------|------|-----------|
63
+ | `panelOpened` | `EventEmitter<void>` | Emitido quando o painel é aberto pelo usuário |
64
+ | `panelClosed` | `EventEmitter<void>` | Emitido quando o painel é fechado pelo usuário |
65
+
66
+ ## Exemplos
67
+
68
+ ### Painel de filtros
69
+
70
+ ```html
71
+ <div style="display: flex; height: 400px;">
72
+ <s-slide-in-bar [cache]="true" (panelOpened)="onAbrir()">
73
+ <div slide-content style="padding: 16px; min-width: 200px;">
74
+ <h4>Filtros</h4>
75
+ <!-- inputs de filtro -->
76
+ </div>
77
+ <div side-content style="padding: 16px; flex: 1;">
78
+ <!-- conteúdo principal (tabela, lista) -->
79
+ </div>
80
+ </s-slide-in-bar>
81
+ </div>
82
+ ```
83
+
84
+ ### Iniciando aberto com ícones customizados
85
+
86
+ ```html
87
+ <s-slide-in-bar
88
+ [createOpen]="true"
89
+ openIcon="fas fa-plus"
90
+ closeIcon="fas fa-minus"
91
+ >
92
+ <div slide-content>Conteúdo do painel</div>
93
+ <div side-content>Conteúdo principal</div>
94
+ </s-slide-in-bar>
95
+ ```
96
+
97
+ ### Fechando programaticamente via serviço
98
+
99
+ ```typescript
100
+ constructor(private slideInBarService: SlideInBarService) {}
101
+
102
+ fecharPainel(): void {
103
+ this.slideInBarService.closeModal('meu-painel-id');
104
+ }
105
+ ```
106
+
107
+ ```html
108
+ <s-slide-in-bar id="meu-painel-id">
109
+ <div slide-content>Painel</div>
110
+ <div side-content>Conteúdo</div>
111
+ </s-slide-in-bar>
112
+ ```
113
+
114
+ ## Acessibilidade
115
+
116
+ - O botão de toggle é focável via teclado e pode ser acionado com `Enter` ou `Espaço`
117
+ - Em telas com largura <= 420px, o painel entra automaticamente em modo overlay
118
+ - A animação de abertura/fechamento tem duração de 200ms para não prejudicar a experiência de usuários sensíveis a movimento
119
+
120
+ ## Componentes relacionados
121
+
122
+ - [`Sidebar`](../sidebar/README.md) — painel lateral com backdrop e suporte a templates customizados
@@ -0,0 +1,127 @@
1
+ # Slider
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Componente de controle deslizante para seleção de valores numéricos dentro de um intervalo definido. Suporta modo simples (um valor) e modo de intervalo (dois valores: início e fim). Implementa `ControlValueAccessor` para integração com Angular Forms.
6
+
7
+ ## Quando usar
8
+
9
+ - Seleção de um valor dentro de um intervalo contínuo (volume, brilho, porcentagem)
10
+ - Filtros de faixa de valores (faixa de preço, temperatura, população)
11
+ - Controles onde a posição relativa é mais relevante que o valor exato
12
+
13
+ ## Quando não usar
14
+
15
+ - Entrada de valores numéricos precisos — prefira `NumberInput` com campo de texto
16
+ - Intervalos com muitos passos discretos onde a precisão é crítica — prefira um campo com máscara numérica
17
+ - Valores que não se encaixam em uma progressão linear
18
+
19
+ ## Instalação
20
+
21
+ ```typescript
22
+ import { SliderModule } from '@seniorsistemas/angular-components/slider';
23
+
24
+ @NgModule({ imports: [SliderModule] })
25
+ export class MeuModule {}
26
+ ```
27
+
28
+ ## Uso básico
29
+
30
+ ```html
31
+ <!-- Slider simples -->
32
+ <s-slider formControlName="volume" [min]="0" [max]="100" [step]="5" />
33
+
34
+ <!-- Slider de intervalo -->
35
+ <s-slider formControlName="faixa" [multiple]="true" [min]="0" [max]="1000" />
36
+ ```
37
+
38
+ ## API
39
+
40
+ ### Inputs
41
+
42
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
43
+ |-------------|------|--------|:-----------:|-----------|
44
+ | `value` | `number \| [number, number]` | `0` | Não | Valor atual. No modo range é `[inicio, fim]` |
45
+ | `multiple` | `boolean` | `false` | Não | Habilita modo de intervalo (dois thumbs) |
46
+ | `min` | `number` | `0` | Não | Valor mínimo do intervalo |
47
+ | `max` | `number` | `100` | Não | Valor máximo do intervalo |
48
+ | `step` | `number` | `1` | Não | Incremento aplicado a cada movimento do thumb |
49
+ | `minValueLabel` | `string` | `undefined` | Não | Label exibido abaixo do valor mínimo |
50
+ | `maxValueLabel` | `string` | `undefined` | Não | Label exibido abaixo do valor máximo |
51
+ | `disabled` | `boolean` | `false` | Não | Desabilita a interação do usuário |
52
+ | `hiddenThumb` | `boolean` | `false` | Não | Oculta visualmente o thumb (exibe apenas a barra de progresso) |
53
+ | `tabindex` | `number` | `0` | Não | Ordem de tabulação do elemento |
54
+
55
+ ### Outputs
56
+
57
+ | Evento | Tipo | Descrição |
58
+ |--------|------|-----------|
59
+ | `valueChange` | `EventEmitter<number \| [number, number]>` | Emitido quando o valor é alterado pelo usuário |
60
+
61
+ ## Exemplos
62
+
63
+ ### Slider simples com labels
64
+
65
+ ```html
66
+ <s-slider
67
+ [(ngModel)]="populacao"
68
+ [min]="0"
69
+ [max]="220"
70
+ [step]="5"
71
+ minValueLabel="0M"
72
+ maxValueLabel="220M"
73
+ (valueChange)="onMudanca($event)"
74
+ ></s-slider>
75
+ ```
76
+
77
+ ### Slider de intervalo
78
+
79
+ ```html
80
+ <s-slider
81
+ [(ngModel)]="faixaTemperatura"
82
+ [multiple]="true"
83
+ [min]="-20"
84
+ [max]="50"
85
+ [step]="1"
86
+ minValueLabel="-20°C"
87
+ maxValueLabel="50°C"
88
+ ></s-slider>
89
+ ```
90
+
91
+ ### Integração com Reactive Forms
92
+
93
+ ```html
94
+ <form [formGroup]="form">
95
+ <s-slider
96
+ formControlName="desconto"
97
+ [min]="0"
98
+ [max]="100"
99
+ [step]="5"
100
+ minValueLabel="0%"
101
+ maxValueLabel="100%"
102
+ ></s-slider>
103
+ </form>
104
+ ```
105
+
106
+ ### Slider desabilitado (somente leitura)
107
+
108
+ ```html
109
+ <s-slider [value]="45" [min]="0" [max]="100" [disabled]="true"></s-slider>
110
+ ```
111
+
112
+ ### Apenas barra de progresso (sem thumb)
113
+
114
+ ```html
115
+ <s-slider [value]="65" [min]="0" [max]="100" [hiddenThumb]="true"></s-slider>
116
+ ```
117
+
118
+ ## Acessibilidade
119
+
120
+ - Navegação por teclado: `ArrowLeft`/`ArrowRight` para decrementar/incrementar o valor em `step` unidades
121
+ - No modo de intervalo (`multiple`), as setas movem o intervalo inteiro mantendo a largura
122
+ - O atributo `tabindex` controla a ordem de tabulação
123
+ - Tooltips sobre os thumbs exibem os valores atuais visualmente
124
+
125
+ ## Componentes relacionados
126
+
127
+ - [`NumberInput`](../number-input/README.md) — entrada numérica precisa com campo de texto
@@ -0,0 +1,104 @@
1
+ # SpeechRecognition
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Componente de reconhecimento de voz que integra a Web Speech API para transcrever a fala do usuário em texto, inserida diretamente em um `<textarea>` fornecido. Suporta também text-to-speech para leitura em voz alta do conteúdo do campo.
6
+
7
+ > **Nota:** Este componente é utilizado internamente pelo `TextAreaComponent` quando `speechRecognition: true`. Para uso em campos de texto simples, prefira o `TextAreaComponent`.
8
+
9
+ ## Quando usar
10
+
11
+ - Campos de texto onde o usuário pode preferir ditar em vez de digitar
12
+ - Acessibilidade para usuários com dificuldade de digitação
13
+ - Formulários de observações ou descrições longas
14
+ - Ditado de textos longos em múltiplas sessões (`keepContext: true`)
15
+
16
+ ## Quando não usar
17
+
18
+ - Ambientes sem suporte à Web Speech API (Firefox, Safari) — o componente não renderiza nesses browsers
19
+ - Campos de texto curtos onde a digitação é mais eficiente
20
+ - Contextos sem acesso ao microfone do dispositivo
21
+
22
+ ## Instalação
23
+
24
+ ```typescript
25
+ import { SpeechRecognitionModule } from '@seniorsistemas/angular-components/speech-recognition';
26
+
27
+ @NgModule({ imports: [SpeechRecognitionModule] })
28
+ export class MeuModule {}
29
+ ```
30
+
31
+ ## Uso básico
32
+
33
+ ```html
34
+ <textarea #meuTextArea rows="5" placeholder="Digite ou use o microfone..."></textarea>
35
+ <s-speech-recognition
36
+ [textAreaElement]="meuTextArea"
37
+ (recognizedText)="onTextoReconhecido($event)"
38
+ ></s-speech-recognition>
39
+ ```
40
+
41
+ ## API
42
+
43
+ ### Inputs
44
+
45
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
46
+ |-------------|------|--------|:-----------:|-----------|
47
+ | `textAreaElement` | `HTMLTextAreaElement` | — | Sim | Referência ao elemento `<textarea>` nativo que receberá o texto transcrito |
48
+ | `keepContext` | `boolean` | `false` | Não | Quando `true`, o texto reconhecido é adicionado ao texto existente em vez de substituí-lo |
49
+ | `speechRecognitionPlaceholder` | `string` | `''` | Não | Placeholder exibido no textarea durante o reconhecimento de voz |
50
+
51
+ ### Outputs
52
+
53
+ | Evento | Tipo | Descrição |
54
+ |--------|------|-----------|
55
+ | `recognizedText` | `EventEmitter<string>` | Emitido quando o reconhecimento é concluído e aprovado pelo usuário. Emite o texto transcrito |
56
+
57
+ ## Exemplos
58
+
59
+ ### Uso padrão com textarea
60
+
61
+ ```html
62
+ <div style="display: flex; align-items: flex-start; gap: 8px;">
63
+ <textarea
64
+ #textAreaRef
65
+ rows="5"
66
+ placeholder="Digite ou use o microfone..."
67
+ style="flex: 1;"
68
+ ></textarea>
69
+ <s-speech-recognition
70
+ [textAreaElement]="textAreaRef"
71
+ [keepContext]="false"
72
+ speechRecognitionPlaceholder="Ouvindo..."
73
+ (recognizedText)="onReconhecido($event)"
74
+ ></s-speech-recognition>
75
+ </div>
76
+ ```
77
+
78
+ ### Ditado acumulativo (keepContext)
79
+
80
+ ```html
81
+ <div style="display: flex; align-items: flex-start; gap: 8px;">
82
+ <textarea
83
+ #textAreaRef
84
+ rows="5"
85
+ placeholder="Cada reconhecimento adiciona ao texto existente..."
86
+ style="flex: 1;"
87
+ ></textarea>
88
+ <s-speech-recognition
89
+ [textAreaElement]="textAreaRef"
90
+ [keepContext]="true"
91
+ ></s-speech-recognition>
92
+ </div>
93
+ ```
94
+
95
+ ## Acessibilidade
96
+
97
+ - Requer suporte do browser à Web Speech API (compatível com Chrome e Edge)
98
+ - Ao iniciar o reconhecimento, o textarea é bloqueado para edição até o usuário aprovar ou descartar o texto reconhecido
99
+ - Após o reconhecimento, botões de **Aprovar** e **Descartar** são exibidos, permitindo confirmação antes de aplicar o texto
100
+ - O botão de text-to-speech lê o conteúdo atual do textarea em voz alta, com controles de velocidade (0.5x, 1x, 1.5x, 2x)
101
+
102
+ ## Componentes relacionados
103
+
104
+ - [`TextArea`](../text-area/README.md) — área de texto com Speech Recognition integrado via prop `speechRecognition`
@@ -0,0 +1,126 @@
1
+ # SplitButton
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Botão composto com ação principal e dropdown de opções adicionais. Ao clicar no botão principal emite `buttonClicked`; ao clicar no ícone de seta abre ou fecha o dropdown com a lista de `options`.
6
+
7
+ ## Quando usar
8
+
9
+ - Ação dominante (ex.: Adicionar) com variantes relacionadas (Atualizar, Alterar, Remover)
10
+ - Toolbars com uma ação principal e ações secundárias no mesmo botão
11
+ - Exportação de dados em múltiplos formatos (PDF, Excel, CSV)
12
+
13
+ ## Quando não usar
14
+
15
+ - Todas as ações têm igual relevância — prefira múltiplos botões separados
16
+ - Há uma única ação — prefira um `Button` simples
17
+ - As ações secundárias são navigacionais — prefira `TieredMenu` separado
18
+
19
+ ## Instalação
20
+
21
+ ```typescript
22
+ import { SplitButtonModule } from '@seniorsistemas/angular-components/split-button';
23
+
24
+ @NgModule({ imports: [SplitButtonModule] })
25
+ export class MeuModule {}
26
+ ```
27
+
28
+ ## Uso básico
29
+
30
+ ```html
31
+ <s-split-button
32
+ label="Adicionar"
33
+ iconClass="far fa-plus"
34
+ [options]="opcoes"
35
+ (buttonClicked)="onAdicionar()"
36
+ />
37
+ ```
38
+
39
+ ## API
40
+
41
+ ### Inputs
42
+
43
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
44
+ |-------------|------|--------|:-----------:|-----------|
45
+ | `label` | `string` | — | Sim | Rótulo do botão principal |
46
+ | `iconClass` | `string` | — | Sim | Classe Font Awesome do ícone exibido no botão principal |
47
+ | `options` | `SplitButtonOption[]` | — | Sim | Lista de opções exibidas no dropdown |
48
+ | `type` | `SplitButtonType` | `'primary'` | Não | Estilo visual do botão: `'primary'`, `'secondary'` ou `'default'` |
49
+ | `disabled` | `boolean` | `false` | Não | Desabilita o botão principal e o dropdown |
50
+
51
+ ### Outputs
52
+
53
+ | Evento | Tipo | Descrição |
54
+ |--------|------|-----------|
55
+ | `buttonClicked` | `EventEmitter<void>` | Emitido quando o usuário clica no botão principal (não no dropdown) |
56
+
57
+ ### Tipos
58
+
59
+ ```typescript
60
+ interface SplitButtonOption {
61
+ title: string; // Texto exibido no dropdown
62
+ action: () => void; // Função executada ao clicar na opção
63
+ }
64
+
65
+ type SplitButtonType = 'primary' | 'secondary' | 'default';
66
+ ```
67
+
68
+ ## Exemplos
69
+
70
+ ### Botão primário com operações CRUD
71
+
72
+ ```html
73
+ <s-split-button
74
+ label="Adicionar"
75
+ iconClass="far fa-plus"
76
+ type="primary"
77
+ [options]="opcoesCrud"
78
+ (buttonClicked)="onAdicionar()"
79
+ ></s-split-button>
80
+ ```
81
+
82
+ ```typescript
83
+ opcoesCrud: SplitButtonOption[] = [
84
+ { title: 'Atualizar', action: () => this.atualizar() },
85
+ { title: 'Alterar', action: () => this.alterar() },
86
+ { title: 'Remover', action: () => this.remover() },
87
+ ];
88
+ ```
89
+
90
+ ### Exportação em múltiplos formatos
91
+
92
+ ```html
93
+ <s-split-button
94
+ label="Exportar"
95
+ iconClass="fa fa-download"
96
+ type="primary"
97
+ [options]="opcoesExportar"
98
+ ></s-split-button>
99
+ ```
100
+
101
+ ```typescript
102
+ opcoesExportar: SplitButtonOption[] = [
103
+ { title: 'Exportar PDF', action: () => this.exportarPDF() },
104
+ { title: 'Exportar Excel', action: () => this.exportarExcel() },
105
+ { title: 'Exportar CSV', action: () => this.exportarCSV() },
106
+ ];
107
+ ```
108
+
109
+ ### Visão geral dos tipos
110
+
111
+ ```html
112
+ <s-split-button label="Adicionar" iconClass="far fa-plus" type="primary" [options]="opcoes"></s-split-button>
113
+ <s-split-button label="Alterar" iconClass="far fa-pencil" type="secondary" [options]="opcoes"></s-split-button>
114
+ <s-split-button label="Remover" iconClass="far fa-trash" type="default" [options]="opcoes"></s-split-button>
115
+ ```
116
+
117
+ ## Acessibilidade
118
+
119
+ - O botão principal é focável via teclado e pode ser acionado com `Enter` ou `Espaço`
120
+ - Clicar fora do componente fecha o dropdown automaticamente via `HostListener`
121
+ - O estado desabilitado impede interação tanto no botão principal quanto no dropdown e nas opções
122
+
123
+ ## Componentes relacionados
124
+
125
+ - [`Button`](../button/README.md) — botão de ação individual com suporte a menu via `menuOptions`
126
+ - [`TieredMenu`](../tiered-menu/README.md) — menu dropdown com submenus aninhados
@@ -0,0 +1,200 @@
1
+ # Spotlight
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Sistema de destaque guiado que combina máscara de fundo semitransparente com um popover informativo posicionado ao lado de um elemento alvo. Suporta destaque simples (passo único) e tours guiados com múltiplos passos e navegação sequencial.
6
+
7
+ ## Quando usar
8
+
9
+ - Onboarding de novos usuários apresentando funcionalidades pela primeira vez
10
+ - Destacar um campo ou ação importante em resposta a uma regra de negócio
11
+ - Tours guiados para apresentar uma tela complexa em sequência lógica
12
+ - Dicas contextuais disparadas por clique ou por lógica da aplicação
13
+
14
+ ## Quando não usar
15
+
16
+ - Ajuda contextual estática sempre visível — prefira `HelpPopover`
17
+ - Dicas simples ao passar o mouse — prefira `Tooltip`
18
+ - Mensagens de alerta críticas que exigem uma ação imediata — prefira `Dialog`
19
+
20
+ ## Instalação
21
+
22
+ ```typescript
23
+ import {
24
+ SpotlightTourService,
25
+ SpotlightStepDirective,
26
+ } from '@seniorsistemas/angular-components/spotlight';
27
+
28
+ @Component({
29
+ standalone: true,
30
+ imports: [SpotlightStepDirective],
31
+ providers: [SpotlightTourService],
32
+ })
33
+ export class MeuComponent {
34
+ private readonly tourService = inject(SpotlightTourService);
35
+ }
36
+ ```
37
+
38
+ ## Uso básico
39
+
40
+ ```html
41
+ <!-- Marque os elementos alvo com a diretiva -->
42
+ <button [sSpotlightStep]="'meu-botao'">Clique aqui</button>
43
+ ```
44
+
45
+ ```typescript
46
+ // Destaque simples em um elemento
47
+ this.tourService.spotlight('meu-botao', {
48
+ title: 'Novo recurso',
49
+ message: 'Este botão agora tem uma função adicional.',
50
+ position: 'bottom-center',
51
+ });
52
+
53
+ // Tour guiado com múltiplos passos
54
+ this.tourService.start([
55
+ { stepId: 'passo-1', title: 'Início', message: 'Descrição do passo 1' },
56
+ { stepId: 'passo-2', title: 'Configuração', message: 'Descrição do passo 2' },
57
+ ]);
58
+ ```
59
+
60
+ ## API
61
+
62
+ ### Diretiva `[sSpotlightStep]`
63
+
64
+ | Propriedade | Tipo | Obrigatório | Descrição |
65
+ |-------------|------|:-----------:|-----------|
66
+ | `sSpotlightStep` | `string` | Sim | ID único do passo do tour ao qual este elemento está associado |
67
+
68
+ ### SpotlightComponent (popover isolado)
69
+
70
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
71
+ |-------------|------|--------|:-----------:|-----------|
72
+ | `title` | `string \| TemplateRef<any>` | `''` | Não | Título exibido no cabeçalho do popover |
73
+ | `message` | `string \| TemplateRef<any>` | `undefined` | Não | Mensagem principal do popover |
74
+ | `content` | `TemplateRef<any> \| null` | `null` | Não | Template para área de mídia/conteúdo customizado |
75
+ | `position` | `SpotlightPosition` | `'bottom-center'` | Não | Posição do popover em relação ao elemento alvo |
76
+ | `currentStep` | `number` | `1` | Não | Número do passo atual (1-based) |
77
+ | `totalSteps` | `number` | `1` | Não | Total de passos do tour |
78
+ | `showDoNotShowAgain` | `boolean` | `true` | Não | Exibe o checkbox "Não mostrar novamente" (apenas em modo simples) |
79
+ | `actions` | `SpotlightStepAction[]` | `[]` | Não | Botões adicionais no rodapé do popover |
80
+ | `arrowOffsetPx` | `number \| null` | `null` | Não | Deslocamento em pixels para posicionar a seta manualmente |
81
+
82
+ ### Outputs do SpotlightComponent
83
+
84
+ | Evento | Tipo | Descrição |
85
+ |--------|------|-----------|
86
+ | `closed` | `OutputEmitterRef<void>` | Emitido ao clicar no botão de fechar (X) |
87
+ | `next` | `OutputEmitterRef<void>` | Emitido ao clicar em "Próximo" |
88
+ | `previous` | `OutputEmitterRef<void>` | Emitido ao clicar em "Voltar" |
89
+ | `understand` | `OutputEmitterRef<void>` | Emitido ao clicar em "Entendido" (modo simples) |
90
+
91
+ ### Tipos
92
+
93
+ ```typescript
94
+ type SpotlightPosition =
95
+ | 'top-start' | 'top-center' | 'top-end'
96
+ | 'right-start' | 'right-center' | 'right-end'
97
+ | 'bottom-start' | 'bottom-center' | 'bottom-end'
98
+ | 'left-start' | 'left-center' | 'left-end';
99
+
100
+ interface SpotlightStep {
101
+ stepId: string;
102
+ title?: string | TemplateRef<any>;
103
+ message?: string | TemplateRef<any>;
104
+ position?: SpotlightPosition;
105
+ showDoNotShowAgain?: boolean;
106
+ dismissible?: boolean;
107
+ actions?: SpotlightStepAction[];
108
+ }
109
+
110
+ interface SpotlightStepAction {
111
+ label: string;
112
+ handler: () => void;
113
+ }
114
+ ```
115
+
116
+ ### SpotlightTourService — API pública
117
+
118
+ | Método/Propriedade | Descrição |
119
+ |---|---|
120
+ | `spotlight(stepId, config)` | Exibe destaque simples em um elemento |
121
+ | `start(steps)` | Inicia tour guiado com múltiplos passos |
122
+ | `next()` | Avança para o próximo passo |
123
+ | `previous()` | Retorna ao passo anterior |
124
+ | `stop(event?)` | Encerra o tour |
125
+ | `isActive` | Signal: indica se o tour está ativo |
126
+ | `currentIndex` | Signal: índice (0-based) do passo atual |
127
+ | `totalSteps` | Signal computado: total de passos |
128
+ | `stopped$` | Observable emitido ao encerrar o tour |
129
+ | `stepChanged$` | Observable emitido ao mudar de passo |
130
+
131
+ ## Exemplos
132
+
133
+ ### Destaque simples
134
+
135
+ ```typescript
136
+ this.tourService.spotlight('campo-obrigatorio', {
137
+ title: 'Campo obrigatório',
138
+ message: 'Este campo deve ser preenchido antes de continuar.',
139
+ position: 'bottom-center',
140
+ showDoNotShowAgain: true,
141
+ dismissible: true,
142
+ });
143
+ ```
144
+
145
+ ### Tour guiado com 3 passos
146
+
147
+ ```typescript
148
+ this.tourService.start([
149
+ {
150
+ stepId: 'btn-novo',
151
+ title: 'Passo 1 — Criar',
152
+ message: 'Use este botão para criar um novo registro.',
153
+ position: 'bottom-center',
154
+ },
155
+ {
156
+ stepId: 'filtro-data',
157
+ title: 'Passo 2 — Filtrar',
158
+ message: 'Filtre por período usando este campo de data.',
159
+ position: 'bottom-start',
160
+ },
161
+ {
162
+ stepId: 'btn-exportar',
163
+ title: 'Passo 3 — Exportar',
164
+ message: 'Exporte os dados filtrados em diferentes formatos.',
165
+ position: 'top-center',
166
+ },
167
+ ]);
168
+
169
+ // Reagir ao encerramento
170
+ this.tourService.stopped$.subscribe(event => {
171
+ if (event.doNotShowAgain) {
172
+ // salvar preferência do usuário
173
+ }
174
+ });
175
+ ```
176
+
177
+ ### Spotlight bloqueado (não pode ser fechado pelo backdrop)
178
+
179
+ ```typescript
180
+ this.tourService.spotlight('elemento-alvo', {
181
+ title: 'Ação obrigatória',
182
+ message: 'Você deve completar esta ação antes de continuar.',
183
+ position: 'bottom-center',
184
+ dismissible: false,
185
+ showDoNotShowAgain: false,
186
+ });
187
+ ```
188
+
189
+ ## Acessibilidade
190
+
191
+ - O popover utiliza `role="dialog"` com `aria-labelledby` e `aria-describedby` referenciando título e mensagem
192
+ - O foco é gerenciado via CDK FocusTrap: ao abrir, o foco vai para o primeiro elemento interativo do popover
193
+ - Pressionar `Escape` fecha o spotlight quando `dismissible !== false`
194
+ - A posição do popover se ajusta automaticamente quando há pouco espaço na viewport
195
+ - Suporte completo à navegação por teclado (Tab, Shift+Tab, Enter, Escape)
196
+
197
+ ## Componentes relacionados
198
+
199
+ - [`HelpPopover`](../help-popover/README.md) — popover de ajuda contextual fixo em elementos de formulário
200
+ - [`Tooltip`](../tooltip/README.md) — dica de conteúdo simples ao passar o mouse