@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,152 @@
1
+ # Dialog
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Componente de diálogo modal que exibe conteúdo em uma janela sobreposta. Pode ser utilizado de forma declarativa (via `[(visible)]` no template) ou programática (via `DialogService.open()`).
6
+
7
+ ## Quando usar
8
+
9
+ - Exibir formulários ou conteúdo que requer atenção exclusiva do usuário
10
+ - Fluxos de confirmação, edição ou criação em sobreposição à tela atual
11
+ - Quando precisa capturar o resultado do diálogo (botão confirmar/cancelar)
12
+
13
+ ## Quando não usar
14
+
15
+ - Confirmações simples sem formulário — use [`ConfirmDialog`](../confirm-dialog/README.md)
16
+ - Mensagens de feedback — use [`Alert`](../alert/README.md) ou notificações inline
17
+ - Tooltips ou popovers de ajuda — use [`HelpPopover`](../help-popover/README.md)
18
+
19
+ ## Instalação
20
+
21
+ ```typescript
22
+ import { DialogComponent, DialogService } from '@seniorsistemas/angular-components/dialog';
23
+
24
+ @Component({
25
+ standalone: true,
26
+ imports: [DialogComponent],
27
+ providers: [DialogService],
28
+ })
29
+ export class MeuComponent {}
30
+ ```
31
+
32
+ ## Uso básico
33
+
34
+ ```html
35
+ <!-- Modo declarativo -->
36
+ <s-button label="Abrir" (clicked)="visible = true"></s-button>
37
+
38
+ <s-dialog header="Título" [(visible)]="visible">
39
+ <p>Conteúdo do diálogo</p>
40
+ <ng-template sTemplate="footer" let-activeDialog="activeDialog">
41
+ <s-button label="Cancelar" priority="secondary" (clicked)="activeDialog.dismiss()"></s-button>
42
+ <s-button label="Confirmar" priority="primary" (clicked)="activeDialog.close('ok')"></s-button>
43
+ </ng-template>
44
+ </s-dialog>
45
+ ```
46
+
47
+ ## API
48
+
49
+ ### Inputs
50
+
51
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
52
+ |-------------|------|--------|:-----------:|-----------|
53
+ | `header` | `string` | — | — | Texto do cabeçalho. Pode ser substituído por `sTemplate="header"` |
54
+ | `visible` | `boolean` | `undefined` | — | Controla a visibilidade. Suporta two-way binding via `[(visible)]`. Não usar com `DialogService` |
55
+ | `size` | `DialogSize` | `'md'` | — | Tamanho do diálogo |
56
+ | `escapeOnEsc` | `boolean` | `true` | — | Fecha o diálogo ao pressionar Escape |
57
+ | `destroyClickOutside` | `boolean` | `true` | — | Fecha o diálogo ao clicar no backdrop |
58
+ | `contentClassName` | `string` | `''` | — | Classes CSS adicionais no container de conteúdo |
59
+ | `closeAriaLabel` | `string` | `'Fechar'` | — | Aria-label do botão de fechar |
60
+
61
+ ### Tipos
62
+
63
+ ```typescript
64
+ type DialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'fullscreen';
65
+ // sm = 300px | md = 500px | lg = 800px | xl = 1140px | fullscreen
66
+
67
+ type DialogOptions = {
68
+ destroyClickOutside?: boolean;
69
+ escapeOnEsc?: boolean;
70
+ size?: DialogSize;
71
+ };
72
+
73
+ type DialogRef<T> = {
74
+ componentInstance: T;
75
+ closed: Observable<any>; // Emite ao chamar activeDialog.close(result)
76
+ dismissed: Observable<any>; // Emite ao chamar activeDialog.dismiss() ou fechar pelo X/Esc
77
+ };
78
+ ```
79
+
80
+ ## Exemplos
81
+
82
+ ### Modo declarativo
83
+
84
+ ```html
85
+ <s-button label="Abrir Dialog" priority="primary" (clicked)="dialogVisible = true"></s-button>
86
+
87
+ <s-dialog
88
+ header="Editar registro"
89
+ [(visible)]="dialogVisible"
90
+ size="lg"
91
+ [escapeOnEsc]="true"
92
+ [destroyClickOutside]="false"
93
+ >
94
+ <ng-template sTemplate="body">
95
+ <p>Conteúdo do formulário aqui.</p>
96
+ </ng-template>
97
+ <ng-template sTemplate="footer" let-activeDialog="activeDialog">
98
+ <div style="display: flex; justify-content: flex-end; gap: 8px; width: 100%;">
99
+ <s-button label="Cancelar" priority="secondary" (clicked)="activeDialog.dismiss()"></s-button>
100
+ <s-button label="Salvar" priority="primary" (clicked)="activeDialog.close('salvo')"></s-button>
101
+ </div>
102
+ </ng-template>
103
+ </s-dialog>
104
+ ```
105
+
106
+ ### Modo programático via DialogService
107
+
108
+ ```typescript
109
+ // Componente de conteúdo do diálogo
110
+ @Component({
111
+ standalone: true,
112
+ imports: [TemplateModule, ButtonModule],
113
+ template: `
114
+ <ng-template sTemplate="footer" let-activeDialog="activeDialog">
115
+ <s-button label="Cancelar" (clicked)="activeDialog.dismiss()"></s-button>
116
+ <s-button label="Confirmar" priority="primary" (clicked)="activeDialog.close('confirmado')"></s-button>
117
+ </ng-template>
118
+ <p>Conteúdo do diálogo.</p>
119
+ `,
120
+ })
121
+ class MeuDialogComponent {}
122
+
123
+ // No componente pai
124
+ const ref = this.dialogService.open(MeuDialogComponent, { size: 'lg' });
125
+ ref.closed.subscribe(result => console.log('Fechado:', result));
126
+ ref.dismissed.subscribe(() => console.log('Dispensado'));
127
+ ```
128
+
129
+ ### Cabeçalho customizado
130
+
131
+ ```html
132
+ <s-dialog [(visible)]="visible">
133
+ <ng-template sTemplate="header">
134
+ <div style="display: flex; align-items: center; gap: 8px;">
135
+ <i class="fas fa-exclamation-triangle" style="color: #f59e0b;"></i>
136
+ <span>Atenção</span>
137
+ </div>
138
+ </ng-template>
139
+ <p>Esta ação requer sua atenção.</p>
140
+ </s-dialog>
141
+ ```
142
+
143
+ ## Acessibilidade
144
+
145
+ - O diálogo é renderizado como uma janela modal com `role="dialog"` e captura o foco enquanto está aberto
146
+ - Pressionar `Escape` fecha o diálogo quando `escapeOnEsc` é `true`
147
+ - O botão de fechar possui `aria-label` configurável via `closeAriaLabel`
148
+ - O backdrop bloqueia interação com o conteúdo de fundo
149
+
150
+ ## Componentes relacionados
151
+
152
+ - [`ConfirmDialog`](../confirm-dialog/README.md) — diálogo de confirmação rápido via serviço, sem template customizado
@@ -0,0 +1,176 @@
1
+ # DynamicForm
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Componente de formulário dinâmico que renderiza campos configuráveis a partir de uma estrutura de dados (`DynamicStructure[]`). Integra-se a um `FormGroup` Angular existente e suporta uma grande variedade de tipos de campo, layout em grid e organização em seções e fieldsets.
6
+
7
+ ## Quando usar
8
+
9
+ - Formulários gerados a partir de metadados ou configuração da API
10
+ - Campos que precisam de layout em grid responsivo configurável
11
+ - Formulários com estrutura variável em runtime
12
+
13
+ ## Quando não usar
14
+
15
+ - Formulários simples com poucos campos fixos — crie o template diretamente
16
+ - Quando a flexibilidade de layout do DynamicForm é desnecessária e adiciona complexidade sem ganho
17
+
18
+ ## Instalação
19
+
20
+ ```typescript
21
+ import { DynamicFormModule } from '@seniorsistemas/angular-components/dynamic-form';
22
+ // ou standalone:
23
+ import { DynamicFormComponent } from '@seniorsistemas/angular-components/dynamic-form';
24
+
25
+ @Component({ standalone: true, imports: [DynamicFormComponent] })
26
+ export class MeuComponent {}
27
+ ```
28
+
29
+ ## Uso básico
30
+
31
+ ```html
32
+ <s-dynamic-form [form]="meuFormGroup" [configs]="estrutura" />
33
+ ```
34
+
35
+ ```typescript
36
+ this.form = new FormGroup({
37
+ nome: new FormControl(''),
38
+ email: new FormControl(''),
39
+ });
40
+
41
+ this.configs: DynamicStructure[] = [{
42
+ type: 'row',
43
+ fields: [
44
+ { name: 'nome', type: 'string', label: 'Nome', size: { md: 6 } },
45
+ { name: 'email', type: 'string', label: 'E-mail', size: { md: 6 } },
46
+ ]
47
+ }];
48
+ ```
49
+
50
+ ## API
51
+
52
+ ### Inputs
53
+
54
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
55
+ |-------------|------|--------|:-----------:|-----------|
56
+ | `form` | `FormGroup` | — | Sim | `FormGroup` Angular ao qual os campos serão vinculados |
57
+ | `configs` | `DynamicStructure[]` | `[]` | — | Lista de estruturas de campos dinâmicos a renderizar |
58
+ | `fields` | `DynamicType[]` | — | — | **Depreciado.** Use `configs` no lugar |
59
+ | `id` | `string` | — | — | Identificador único do formulário no DOM |
60
+ | `errorMessages` | `any` | `{}` | — | Mapa de mensagens de erro globais por nome de validador |
61
+
62
+ ### Tipos de campo disponíveis
63
+
64
+ | Tipo | Descrição |
65
+ |------|-----------|
66
+ | `string` | Campo de texto simples |
67
+ | `password` | Campo de senha com toggle de visibilidade |
68
+ | `textArea` | Área de texto multilinha |
69
+ | `number` | Campo numérico com máscara |
70
+ | `integer` | Campo de número inteiro |
71
+ | `money` | Campo monetário |
72
+ | `slider` | Controle deslizante |
73
+ | `date` | Seletor de data |
74
+ | `dateTime` | Seletor de data e hora |
75
+ | `time` | Seletor de hora |
76
+ | `boolean` | Radio button sim/não/vazio |
77
+ | `booleanSwitch` | Toggle switch |
78
+ | `enum` | Dropdown de opções |
79
+ | `radioButton` | Grupo de radio buttons |
80
+ | `autocomplete` | Campo com sugestões |
81
+ | `chips` | Campo de tags |
82
+ | `checkbox` | Checkbox hierárquico |
83
+ | `lookup` | Campo de busca avançada (modal) |
84
+ | `starRating` | Avaliação por estrelas |
85
+ | `contentGenerator` | Gerador de conteúdo com IA |
86
+ | `profilePicture` | Upload de foto de perfil |
87
+ | `countryPhonePicker` | Seletor de telefone por país |
88
+ | `blob` | Upload de arquivo |
89
+
90
+ ### Estruturas de layout
91
+
92
+ ```typescript
93
+ type DynamicStructure =
94
+ | { type: 'row'; fields: DynamicType[] }
95
+ | { type: 'section'; title?: string; configs: DynamicStructure[] }
96
+ | { type: 'fieldset'; legend?: string; configs: DynamicStructure[] };
97
+ ```
98
+
99
+ ## Exemplos
100
+
101
+ ### Formulário básico com grid
102
+
103
+ ```html
104
+ <form [formGroup]="form" style="max-width: 800px;">
105
+ <s-dynamic-form [form]="form" [configs]="configs" />
106
+ </form>
107
+ ```
108
+
109
+ ```typescript
110
+ this.form = new FormGroup({
111
+ nome: new FormControl(''),
112
+ email: new FormControl(''),
113
+ tipo: new FormControl(null),
114
+ ativo: new FormControl(false),
115
+ });
116
+
117
+ this.configs = [{
118
+ type: 'row',
119
+ fields: [
120
+ { name: 'nome', type: 'string', label: 'Nome', size: { md: 6 } },
121
+ { name: 'email', type: 'string', label: 'E-mail', size: { md: 6 } },
122
+ {
123
+ name: 'tipo',
124
+ type: 'enum',
125
+ label: 'Tipo',
126
+ size: { md: 6 },
127
+ options: [
128
+ { label: 'Pessoa Física', value: 'pf' },
129
+ { label: 'Pessoa Jurídica', value: 'pj' },
130
+ ],
131
+ },
132
+ { name: 'ativo', type: 'booleanSwitch', label: 'Ativo', size: { md: 6 },
133
+ optionsLabel: { true: 'Sim', false: 'Não' } },
134
+ ],
135
+ }];
136
+ ```
137
+
138
+ ### Formulário com data e número
139
+
140
+ ```typescript
141
+ this.configs = [{
142
+ type: 'row',
143
+ fields: [
144
+ { name: 'valor', type: 'number', label: 'Valor', size: { md: 4 }, allowNegative: false },
145
+ { name: 'data', type: 'date', label: 'Data', size: { md: 4 }, appendTo: 'body' },
146
+ { name: 'descricao', type: 'string', label: 'Descrição', size: { md: 4 } },
147
+ ],
148
+ }];
149
+ ```
150
+
151
+ ### Formulário com seções
152
+
153
+ ```typescript
154
+ this.configs = [{
155
+ type: 'section',
156
+ title: 'Dados Pessoais',
157
+ configs: [{
158
+ type: 'row',
159
+ fields: [
160
+ { name: 'nome', type: 'string', label: 'Nome', size: { md: 6 } },
161
+ { name: 'cpf', type: 'string', label: 'CPF', size: { md: 6 } },
162
+ ]
163
+ }]
164
+ }];
165
+ ```
166
+
167
+ ## Acessibilidade
168
+
169
+ - Os campos internos utilizam `label` vinculado via `for`/`id`
170
+ - Campos obrigatórios são marcados com `aria-required`
171
+ - Mensagens de erro são associadas aos campos correspondentes
172
+
173
+ ## Componentes relacionados
174
+
175
+ - [`CustomFields`](../custom-fields/README.md) — campos customizados via API da plataforma Senior, baseado no DynamicForm
176
+ - [`Fieldset`](../fieldset/README.md) — agrupador de campos com suporte a toggle
@@ -0,0 +1,98 @@
1
+ # EditableOverlay
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Diretiva aplicada a um `p-table` do PrimeNG para corrigir o comportamento de clique fora da célula editável. Evita que cliques em overlays internos (dropdowns, modais, lookups) fechem indevidamente o modo de edição da célula da tabela.
6
+
7
+ ## Quando usar
8
+
9
+ - Tabelas PrimeNG (`p-table`) com células editáveis que contêm dropdowns, selects ou modais
10
+ - Quando o modo de edição da célula fecha ao interagir com overlays internos, impedindo a seleção de valores
11
+
12
+ ## Quando não usar
13
+
14
+ - Tabelas sem modo de edição inline — a diretiva não tem efeito nesse cenário
15
+ - Tabelas que não são do PrimeNG — a diretiva sobrescreve métodos internos do `p-table`
16
+
17
+ ## Instalação
18
+
19
+ ```typescript
20
+ import { EditableOverlayModule } from '@seniorsistemas/angular-components/editable-overlay';
21
+
22
+ @Component({ standalone: true, imports: [EditableOverlayModule] })
23
+ export class MeuComponent {}
24
+ ```
25
+
26
+ ## Uso básico
27
+
28
+ Aplique `sEditableOverlay` no elemento `p-table` e passe a referência da tabela via `[table]`:
29
+
30
+ ```html
31
+ <p-table sEditableOverlay [table]="dt" #dt>
32
+ <ng-template pTemplate="body" let-row>
33
+ <tr>
34
+ <td pEditableColumn>
35
+ <p-cellEditor>
36
+ <ng-template pTemplate="input">
37
+ <p-dropdown [options]="opcoes" [(ngModel)]="row.tipo"></p-dropdown>
38
+ </ng-template>
39
+ <ng-template pTemplate="output">
40
+ {{ row.tipo }}
41
+ </ng-template>
42
+ </p-cellEditor>
43
+ </td>
44
+ </tr>
45
+ </ng-template>
46
+ </p-table>
47
+ ```
48
+
49
+ ## API
50
+
51
+ ### Inputs (na diretiva `sEditableOverlay`)
52
+
53
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
54
+ |-------------|------|--------|:-----------:|-----------|
55
+ | `table` | `any` | — | Sim | Referência direta à instância do `p-table` (mesmo que a template reference variable `#dt`) |
56
+
57
+ ## Exemplos
58
+
59
+ ### Tabela com dropdown em célula editável
60
+
61
+ ```html
62
+ <p-table [value]="dados" sEditableOverlay [table]="dt" #dt>
63
+ <ng-template pTemplate="header">
64
+ <tr>
65
+ <th>Nome</th>
66
+ <th>Categoria</th>
67
+ </tr>
68
+ </ng-template>
69
+ <ng-template pTemplate="body" let-item>
70
+ <tr>
71
+ <td>{{ item.nome }}</td>
72
+ <td pEditableColumn>
73
+ <p-cellEditor>
74
+ <ng-template pTemplate="input">
75
+ <p-dropdown
76
+ [options]="categorias"
77
+ [(ngModel)]="item.categoria"
78
+ appendTo="body"
79
+ ></p-dropdown>
80
+ </ng-template>
81
+ <ng-template pTemplate="output">
82
+ {{ item.categoria }}
83
+ </ng-template>
84
+ </p-cellEditor>
85
+ </td>
86
+ </tr>
87
+ </ng-template>
88
+ </p-table>
89
+ ```
90
+
91
+ ## Acessibilidade
92
+
93
+ - A diretiva não altera atributos ARIA — a acessibilidade da tabela editável depende da configuração do `p-table` do PrimeNG
94
+ - O comportamento de foco e teclado permanece o mesmo do `p-table`
95
+
96
+ ## Componentes relacionados
97
+
98
+ - [`Select`](../select/README.md) — dropdown de seleção usado em células editáveis
@@ -0,0 +1,134 @@
1
+ # EmptyState
2
+
3
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen)
4
+
5
+ Componente de estado vazio para exibição padronizada de mensagens quando não há conteúdo a ser exibido. Apresenta ícone, título, descrição opcional e até dois botões de ação (primário e secundário), com suporte a menu de múltiplas opções no botão primário.
6
+
7
+ ## Quando usar
8
+
9
+ - Listagens sem registros onde o usuário deve ser orientado sobre a próxima ação
10
+ - Telas de busca sem resultados
11
+ - Páginas de erro ou acesso negado onde o usuário deve ser redirecionado
12
+
13
+ ## Quando não usar
14
+
15
+ - Estados de carregamento — use um skeleton ou spinner
16
+ - Mensagens de feedback sobre ações recém executadas — use [`Alert`](../alert/README.md)
17
+ - Erros de formulário — use [`ControlErrors`](../control-errors/README.md)
18
+
19
+ ## Instalação
20
+
21
+ ```typescript
22
+ import { EmptyStateModule } from '@seniorsistemas/angular-components/empty-state';
23
+
24
+ @Component({ standalone: true, imports: [EmptyStateModule] })
25
+ export class MeuComponent {}
26
+ ```
27
+
28
+ ## Uso básico
29
+
30
+ ```html
31
+ <s-empty-state
32
+ title="Nenhum registro encontrado"
33
+ (primaryAction)="onCreate()"
34
+ />
35
+ ```
36
+
37
+ ## API
38
+
39
+ ### Inputs
40
+
41
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
42
+ |-------------|------|--------|:-----------:|-----------|
43
+ | `title` | `string` | — | Sim | Título principal exibido no estado vazio |
44
+ | `iconClass` | `string` | `'fa fa-inbox'` | — | Classe CSS do ícone (ex: `'fa fa-search'`) |
45
+ | `description` | `string` | — | — | Texto descritivo exibido abaixo do título |
46
+ | `showPrimaryAction` | `boolean` | `true` | — | Controla a visibilidade do botão de ação primária |
47
+ | `showSecondaryAction` | `boolean` | `true` | — | Controla a visibilidade do botão de ação secundária |
48
+ | `primaryActionLabel` | `string` | — | — | Texto do botão de ação primária |
49
+ | `secondaryActionLabel` | `string` | — | — | Texto do botão de ação secundária |
50
+ | `primaryModel` | `TieredMenuItemData[]` | `[]` | — | Itens do menu do botão primário. Quando fornecido, transforma o botão em split-button |
51
+ | `id` | `string` | `s-empty-state-{n}` | — | Identificador único do componente |
52
+
53
+ ### Outputs
54
+
55
+ | Evento | Tipo | Descrição |
56
+ |--------|------|-----------|
57
+ | `primaryAction` | `EventEmitter<void>` | Emitido ao clicar no botão primário (quando `primaryModel` está vazio) |
58
+ | `secondaryAction` | `EventEmitter<void>` | Emitido ao clicar no botão secundário |
59
+
60
+ ## Exemplos
61
+
62
+ ### Estado vazio simples
63
+
64
+ ```html
65
+ <s-empty-state
66
+ title="Nenhum registro encontrado"
67
+ [showPrimaryAction]="false"
68
+ [showSecondaryAction]="false"
69
+ ></s-empty-state>
70
+ ```
71
+
72
+ ### Com descrição e ação primária
73
+
74
+ ```html
75
+ <s-empty-state
76
+ title="Nenhum registro encontrado"
77
+ description="Clique no botão abaixo para adicionar um novo registro."
78
+ iconClass="fa fa-inbox"
79
+ [showPrimaryAction]="true"
80
+ primaryActionLabel="Adicionar"
81
+ [showSecondaryAction]="false"
82
+ (primaryAction)="onCreate()"
83
+ ></s-empty-state>
84
+ ```
85
+
86
+ ### Com ambas as ações
87
+
88
+ ```html
89
+ <s-empty-state
90
+ title="Nenhum registro encontrado"
91
+ description="Adicione um novo registro ou cancele para voltar."
92
+ [showPrimaryAction]="true"
93
+ primaryActionLabel="Adicionar"
94
+ [showSecondaryAction]="true"
95
+ secondaryActionLabel="Cancelar"
96
+ (primaryAction)="onCreate()"
97
+ (secondaryAction)="onCancel()"
98
+ ></s-empty-state>
99
+ ```
100
+
101
+ ### Com menu de opções no botão primário
102
+
103
+ ```html
104
+ <s-empty-state
105
+ title="Nenhum registro encontrado"
106
+ [showPrimaryAction]="true"
107
+ primaryActionLabel="Adicionar"
108
+ [primaryModel]="[
109
+ { label: 'Adicionar manualmente', iconClass: 'fa fa-plus' },
110
+ { label: 'Importar arquivo', iconClass: 'fa fa-upload' }
111
+ ]"
112
+ ></s-empty-state>
113
+ ```
114
+
115
+ ### Componente auxiliar para redirecionamento ao portal
116
+
117
+ ```html
118
+ <s-empty-state-go-back
119
+ title="Acesso não autorizado"
120
+ description="Você não tem permissão para acessar esta página."
121
+ iconClass="fa fa-exclamation-triangle"
122
+ primaryActionLabel="Voltar ao portal"
123
+ ></s-empty-state-go-back>
124
+ ```
125
+
126
+ ## Acessibilidade
127
+
128
+ - O ícone é puramente decorativo e não possui texto alternativo obrigatório
129
+ - Os botões de ação são elementos `<button>` com labels visíveis
130
+ - O título deve descrever claramente o estado vazio para leitores de tela
131
+
132
+ ## Componentes relacionados
133
+
134
+ - [`Button`](../button/README.md) — botões de ação primária e secundária usados internamente
@@ -1,4 +1,4 @@
1
- import { Component, Input } from '@angular/core';
1
+ import { Component, Input, ViewEncapsulation } from '@angular/core';
2
2
  import { LoadingStateIndicators } from './components/loading-state-indicators';
3
3
  import * as i0 from "@angular/core";
4
4
  import * as i1 from "@angular/common";
@@ -92,11 +92,11 @@ export class LoadingStateComponent {
92
92
  }
93
93
  }
94
94
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoadingStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
95
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LoadingStateComponent, selector: "s-loading-state", inputs: { indicator: "indicator", id: "id", blockWindow: "blockWindow", loading: "loading" }, ngImport: i0, template: "<div\n [id]=\"id\"\n class=\"s-loading-state\"\n [ngClass]=\"{\n 's-loading-state--loading': loading,\n 's-loading-state--blocking': blocking,\n 's-loading-state--fullscreen': blockWindow\n }\"\n>\n <div\n [id]=\"id + '-loader'\"\n class=\"loader\"\n >\n <div\n [id]=\"id + '-spinner'\"\n class=\"spinner\"\n >\n @switch (indicator) {\n @case ('logo') {\n <s-logo-indicator></s-logo-indicator>\n }\n @case ('dots') {\n <s-dots-indicator></s-dots-indicator>\n }\n }\n </div>\n <div\n [id]=\"id + '-overlay'\"\n class=\"overlay\"\n ></div>\n </div>\n <div\n [id]=\"id + '-contents'\"\n class=\"state-contents\"\n >\n <ng-container *ngTemplateOutlet=\"contents || originalContent\"></ng-container>\n <ng-template #originalContent>\n <ng-content></ng-content>\n </ng-template>\n </div>\n</div>\n", styles: [".s-loading-state{position:relative}.s-loading-state .loader{opacity:0;position:absolute;transition:opacity .2s ease-out,display .2s ease-out;visibility:hidden;inset:1px;display:flex;justify-content:center;align-items:center}.s-loading-state .loader .overlay{background-color:#fff;height:100%;opacity:.8;transition:opacity .2s ease-out,display .2s ease-out;width:100%}.s-loading-state .loader .spinner{display:flex;position:absolute;z-index:2}.s-loading-state.s-loading-state--loading>.loader,.s-loading-state.s-loading-state--blocking>.loader{visibility:visible}.s-loading-state.s-loading-state--loading>.loader,.s-loading-state.s-loading-state--loading>.loader>.overlay,.s-loading-state.s-loading-state--blocking>.loader,.s-loading-state.s-loading-state--blocking>.loader>.overlay{cursor:wait;z-index:1}.s-loading-state.s-loading-state--loading>.state-contents,.s-loading-state.s-loading-state--blocking>.state-contents{z-index:0!important}.s-loading-state.s-loading-state--blocking.s-loading-state--loading>.loader{opacity:1}.s-loading-state.s-loading-state--fullscreen>.loader{left:0;position:fixed;top:0;z-index:1005}::ng-deep .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.loader{opacity:0;visibility:hidden}::ng-deep .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.state-contents{z-index:0!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.DotsIndicatorComponent, selector: "s-dots-indicator" }, { kind: "component", type: i3.LoadingIndicatorComponent, selector: "s-logo-indicator" }] });
95
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LoadingStateComponent, selector: "s-loading-state", inputs: { indicator: "indicator", id: "id", blockWindow: "blockWindow", loading: "loading" }, ngImport: i0, template: "<div\n [id]=\"id\"\n class=\"s-loading-state\"\n [ngClass]=\"{\n 's-loading-state--loading': loading,\n 's-loading-state--blocking': blocking,\n 's-loading-state--fullscreen': blockWindow\n }\"\n>\n <div\n [id]=\"id + '-loader'\"\n class=\"loader\"\n >\n <div\n [id]=\"id + '-spinner'\"\n class=\"spinner\"\n >\n @switch (indicator) {\n @case ('logo') {\n <s-logo-indicator></s-logo-indicator>\n }\n @case ('dots') {\n <s-dots-indicator></s-dots-indicator>\n }\n }\n </div>\n <div\n [id]=\"id + '-overlay'\"\n class=\"overlay\"\n ></div>\n </div>\n <div\n [id]=\"id + '-contents'\"\n class=\"state-contents\"\n >\n <ng-container *ngTemplateOutlet=\"contents || originalContent\"></ng-container>\n <ng-template #originalContent>\n <ng-content></ng-content>\n </ng-template>\n </div>\n</div>\n", styles: ["s-loading-state .s-loading-state{position:relative}s-loading-state .s-loading-state .loader{opacity:0;position:absolute;transition:opacity .2s ease-out,display .2s ease-out;visibility:hidden;inset:1px;display:flex;justify-content:center;align-items:center}s-loading-state .s-loading-state .loader .overlay{height:100%;opacity:.8;transition:opacity .2s ease-out,display .2s ease-out;width:100%}s-loading-state .s-loading-state .loader .spinner{display:flex;position:absolute;z-index:2}s-loading-state .s-loading-state.s-loading-state--loading>.loader,s-loading-state .s-loading-state.s-loading-state--blocking>.loader{cursor:wait;visibility:visible;z-index:2}s-loading-state .s-loading-state.s-loading-state--loading>.loader>.overlay,s-loading-state .s-loading-state.s-loading-state--blocking>.loader>.overlay{cursor:wait;z-index:1}s-loading-state .s-loading-state.s-loading-state--loading>.state-contents,s-loading-state .s-loading-state.s-loading-state--blocking>.state-contents{position:relative;z-index:0!important;opacity:.5}s-loading-state .s-loading-state.s-loading-state--fullscreen>.loader{left:0;position:fixed;top:0;z-index:1005}s-loading-state .s-loading-state.s-loading-state--blocking.s-loading-state--loading>.loader{opacity:1}s-loading-state .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.loader{opacity:0;visibility:hidden}s-loading-state .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.state-contents{z-index:0!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.DotsIndicatorComponent, selector: "s-dots-indicator" }, { kind: "component", type: i3.LoadingIndicatorComponent, selector: "s-logo-indicator" }], encapsulation: i0.ViewEncapsulation.None });
96
96
  }
97
97
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoadingStateComponent, decorators: [{
98
98
  type: Component,
99
- args: [{ selector: 's-loading-state', template: "<div\n [id]=\"id\"\n class=\"s-loading-state\"\n [ngClass]=\"{\n 's-loading-state--loading': loading,\n 's-loading-state--blocking': blocking,\n 's-loading-state--fullscreen': blockWindow\n }\"\n>\n <div\n [id]=\"id + '-loader'\"\n class=\"loader\"\n >\n <div\n [id]=\"id + '-spinner'\"\n class=\"spinner\"\n >\n @switch (indicator) {\n @case ('logo') {\n <s-logo-indicator></s-logo-indicator>\n }\n @case ('dots') {\n <s-dots-indicator></s-dots-indicator>\n }\n }\n </div>\n <div\n [id]=\"id + '-overlay'\"\n class=\"overlay\"\n ></div>\n </div>\n <div\n [id]=\"id + '-contents'\"\n class=\"state-contents\"\n >\n <ng-container *ngTemplateOutlet=\"contents || originalContent\"></ng-container>\n <ng-template #originalContent>\n <ng-content></ng-content>\n </ng-template>\n </div>\n</div>\n", styles: [".s-loading-state{position:relative}.s-loading-state .loader{opacity:0;position:absolute;transition:opacity .2s ease-out,display .2s ease-out;visibility:hidden;inset:1px;display:flex;justify-content:center;align-items:center}.s-loading-state .loader .overlay{background-color:#fff;height:100%;opacity:.8;transition:opacity .2s ease-out,display .2s ease-out;width:100%}.s-loading-state .loader .spinner{display:flex;position:absolute;z-index:2}.s-loading-state.s-loading-state--loading>.loader,.s-loading-state.s-loading-state--blocking>.loader{visibility:visible}.s-loading-state.s-loading-state--loading>.loader,.s-loading-state.s-loading-state--loading>.loader>.overlay,.s-loading-state.s-loading-state--blocking>.loader,.s-loading-state.s-loading-state--blocking>.loader>.overlay{cursor:wait;z-index:1}.s-loading-state.s-loading-state--loading>.state-contents,.s-loading-state.s-loading-state--blocking>.state-contents{z-index:0!important}.s-loading-state.s-loading-state--blocking.s-loading-state--loading>.loader{opacity:1}.s-loading-state.s-loading-state--fullscreen>.loader{left:0;position:fixed;top:0;z-index:1005}::ng-deep .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.loader{opacity:0;visibility:hidden}::ng-deep .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.state-contents{z-index:0!important}\n"] }]
99
+ args: [{ selector: 's-loading-state', encapsulation: ViewEncapsulation.None, template: "<div\n [id]=\"id\"\n class=\"s-loading-state\"\n [ngClass]=\"{\n 's-loading-state--loading': loading,\n 's-loading-state--blocking': blocking,\n 's-loading-state--fullscreen': blockWindow\n }\"\n>\n <div\n [id]=\"id + '-loader'\"\n class=\"loader\"\n >\n <div\n [id]=\"id + '-spinner'\"\n class=\"spinner\"\n >\n @switch (indicator) {\n @case ('logo') {\n <s-logo-indicator></s-logo-indicator>\n }\n @case ('dots') {\n <s-dots-indicator></s-dots-indicator>\n }\n }\n </div>\n <div\n [id]=\"id + '-overlay'\"\n class=\"overlay\"\n ></div>\n </div>\n <div\n [id]=\"id + '-contents'\"\n class=\"state-contents\"\n >\n <ng-container *ngTemplateOutlet=\"contents || originalContent\"></ng-container>\n <ng-template #originalContent>\n <ng-content></ng-content>\n </ng-template>\n </div>\n</div>\n", styles: ["s-loading-state .s-loading-state{position:relative}s-loading-state .s-loading-state .loader{opacity:0;position:absolute;transition:opacity .2s ease-out,display .2s ease-out;visibility:hidden;inset:1px;display:flex;justify-content:center;align-items:center}s-loading-state .s-loading-state .loader .overlay{height:100%;opacity:.8;transition:opacity .2s ease-out,display .2s ease-out;width:100%}s-loading-state .s-loading-state .loader .spinner{display:flex;position:absolute;z-index:2}s-loading-state .s-loading-state.s-loading-state--loading>.loader,s-loading-state .s-loading-state.s-loading-state--blocking>.loader{cursor:wait;visibility:visible;z-index:2}s-loading-state .s-loading-state.s-loading-state--loading>.loader>.overlay,s-loading-state .s-loading-state.s-loading-state--blocking>.loader>.overlay{cursor:wait;z-index:1}s-loading-state .s-loading-state.s-loading-state--loading>.state-contents,s-loading-state .s-loading-state.s-loading-state--blocking>.state-contents{position:relative;z-index:0!important;opacity:.5}s-loading-state .s-loading-state.s-loading-state--fullscreen>.loader{left:0;position:fixed;top:0;z-index:1005}s-loading-state .s-loading-state.s-loading-state--blocking.s-loading-state--loading>.loader{opacity:1}s-loading-state .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.loader{opacity:0;visibility:hidden}s-loading-state .s-loading-state-container.s-loading-state--loading.s-loading-state--blocking s-loading-state .s-loading-state-container>.state-contents{z-index:0!important}\n"] }]
100
100
  }], propDecorators: { indicator: [{
101
101
  type: Input
102
102
  }], id: [{
@@ -107,4 +107,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
107
107
  type: Input,
108
108
  args: [{ required: true }]
109
109
  }] } });
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZGluZy1zdGF0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNvbXBvbmVudHMvbG9hZGluZy1zdGF0ZS9zcmMvbGliL2xvYWRpbmctc3RhdGUvbG9hZGluZy1zdGF0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNvbXBvbmVudHMvbG9hZGluZy1zdGF0ZS9zcmMvbGliL2xvYWRpbmctc3RhdGUvbG9hZGluZy1zdGF0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBMEIsTUFBTSxlQUFlLENBQUM7QUFFekUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7Ozs7O0FBRS9FOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBTUgsTUFBTSxPQUFPLHFCQUFxQjtJQUN2QixNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUV6Qjs7Ozs7O09BTUc7SUFFSSxTQUFTLEdBQTJCLHNCQUFzQixDQUFDLElBQUksQ0FBQztJQUV2RTs7T0FFRztJQUVJLEVBQUUsR0FBRyxtQkFBbUIscUJBQXFCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUVoRTs7Ozs7T0FLRztJQUVJLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFFM0I7Ozs7T0FJRztJQUNILElBQ1csT0FBTyxDQUFDLE9BQWdCO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDNUMsQ0FBQztJQUVELElBQVcsT0FBTztRQUNkLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDO0lBRU0sUUFBUSxHQUE0QixJQUFJLENBQUM7SUFDekMsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUVoQixRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztJQUMxQixxQkFBcUIsR0FBRyxHQUFHLENBQUM7SUFDNUIsY0FBYyxDQUFNO0lBQ3BCLGdCQUFnQixDQUFNO0lBRXZCLFdBQVc7UUFDZCxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUs7UUFDUixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1lBQ3BDLENBQUMsRUFBRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLE9BQU87UUFDVixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1FBQ3BDLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ3BDLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUN0QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDO1lBQ3RDLENBQUMsRUFBRSxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0wsQ0FBQzt3R0F4RlEscUJBQXFCOzRGQUFyQixxQkFBcUIscUpDeEJsQywra0NBeUNBOzs0RkRqQmEscUJBQXFCO2tCQUxqQyxTQUFTOytCQUNJLGlCQUFpQjs4QkFlcEIsU0FBUztzQkFEZixLQUFLO2dCQU9DLEVBQUU7c0JBRFIsS0FBSztnQkFVQyxXQUFXO3NCQURqQixLQUFLO2dCQVNLLE9BQU87c0JBRGpCLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT25EZXN0cm95LCBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBMb2FkaW5nU3RhdGVJbmRpY2F0b3JzIH0gZnJvbSAnLi9jb21wb25lbnRzL2xvYWRpbmctc3RhdGUtaW5kaWNhdG9ycyc7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbXBvbmVudGUgZGUgZXN0YWRvIGRlIGNhcnJlZ2FtZW50byBxdWUgZXhpYmUgdW0gaW5kaWNhZG9yIGFuaW1hZG8gZW5xdWFudG9cbiAqIHVtIHByb2Nlc3NvIGFzc8OtbmNyb25vIGVzdMOhIGVtIGFuZGFtZW50by4gU3Vwb3J0YSBibG9xdWVpbyBkYSBqYW5lbGEgaW50ZWlyYVxuICogZSBkaWZlcmVudGVzIHRpcG9zIGRlIGluZGljYWRvcmVzIHZpc3VhaXMuXG4gKiBUYW1iw6ltIHBvZGUgc2VyIHVzYWRvIGNvbW8gZGlyZXRpdmEgZXN0cnV0dXJhbCBgW3NMb2FkaW5nU3RhdGVdYC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgaHRtbFxuICogPHMtbG9hZGluZy1zdGF0ZSBbbG9hZGluZ109XCJpc0xvYWRpbmdcIiBbYmxvY2tXaW5kb3ddPVwidHJ1ZVwiPlxuICogICA8cD5Db250ZcO6ZG8gY2FycmVnYWRvITwvcD5cbiAqIDwvcy1sb2FkaW5nLXN0YXRlPlxuICogYGBgXG4gKlxuICogQGNhdGVnb3J5IEZlZWRiYWNrXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAncy1sb2FkaW5nLXN0YXRlJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vbG9hZGluZy1zdGF0ZS5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vbG9hZGluZy1zdGF0ZS5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBMb2FkaW5nU3RhdGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAgIHB1YmxpYyBzdGF0aWMgbmV4dElkID0gMDtcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBUaXBvIGRlIGluZGljYWRvciB2aXN1YWwgZXhpYmlkbyBkdXJhbnRlIG8gY2FycmVnYW1lbnRvLlxuICAgICAqIC0gYExvYWRpbmdTdGF0ZUluZGljYXRvcnMuRG90c2A6IGluZGljYWRvciBkZSBwb250b3MgYW5pbWFkb3MgKHBhZHLDo28pLlxuICAgICAqIC0gYExvYWRpbmdTdGF0ZUluZGljYXRvcnMuTG9nb2A6IGluZGljYWRvciBjb20gbG9nb3RpcG8gYW5pbWFkby5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IExvYWRpbmdTdGF0ZUluZGljYXRvcnMuRG90c1xuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGluZGljYXRvcjogTG9hZGluZ1N0YXRlSW5kaWNhdG9ycyA9IExvYWRpbmdTdGF0ZUluZGljYXRvcnMuRG90cztcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBJZGVudGlmaWNhZG9yIMO6bmljbyBkbyBjb21wb25lbnRlLiBHZXJhZG8gYXV0b21hdGljYW1lbnRlIHNlIG7Do28gaW5mb3JtYWRvLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGlkID0gYHMtbG9hZGluZy1zdGF0ZS0ke0xvYWRpbmdTdGF0ZUNvbXBvbmVudC5uZXh0SWQrK31gO1xuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFF1YW5kbyBgdHJ1ZWAsIGJsb3F1ZWlhIGEgamFuZWxhIGludGVpcmEgZHVyYW50ZSBvIGNhcnJlZ2FtZW50byxcbiAgICAgKiBzb2JyZXBvbmRvIHRvZG8gbyBjb250ZcO6ZG8gZGEgcMOhZ2luYSBjb20gbyBpbmRpY2Fkb3IuXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGJsb2NrV2luZG93ID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQ29udHJvbGEgbyBlc3RhZG8gZGUgY2FycmVnYW1lbnRvIGRvIGNvbXBvbmVudGUuIENhbXBvIG9icmlnYXTDs3Jpby5cbiAgICAgKiBRdWFuZG8gYHRydWVgLCBleGliZSBvIGluZGljYWRvciBkZSBjYXJyZWdhbWVudG8gYXDDs3MgdW0gYnJldmUgZGVsYXkuXG4gICAgICogUXVhbmRvIGBmYWxzZWAsIHJlbW92ZSBvIGluZGljYWRvciBhcMOzcyB1bSBicmV2ZSBkZWxheSAoZXZpdGEgZmxhc2gpLlxuICAgICAqL1xuICAgIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pXG4gICAgcHVibGljIHNldCBsb2FkaW5nKGxvYWRpbmc6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fbG9hZGluZyA9IGxvYWRpbmc7XG4gICAgICAgIGxvYWRpbmcgPyB0aGlzLmJsb2NrKCkgOiB0aGlzLnVuYmxvY2soKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGxvYWRpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkaW5nO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb250ZW50czogVGVtcGxhdGVSZWY8YW55PiB8IG51bGwgPSBudWxsO1xuICAgIHB1YmxpYyBibG9ja2luZyA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBfbG9hZGluZyA9IGZhbHNlO1xuICAgIHByaXZhdGUgQkxPQ0tfVElNRU9VVF9WQUxVRSA9IDMwMDtcbiAgICBwcml2YXRlIFVOQkxPQ0tfVElNRU9VVF9WQUxVRSA9IDIwMDtcbiAgICBwcml2YXRlIGJsb2NrVGltZW91dElkOiBhbnk7XG4gICAgcHJpdmF0ZSB1bmJsb2NrVGltZW91dElkOiBhbnk7XG5cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmJsb2NrVGltZW91dElkKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5ibG9ja1RpbWVvdXRJZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy51bmJsb2NrVGltZW91dElkKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy51bmJsb2NrVGltZW91dElkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBibG9jaygpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudW5ibG9ja1RpbWVvdXRJZCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMudW5ibG9ja1RpbWVvdXRJZCk7XG4gICAgICAgICAgICB0aGlzLnVuYmxvY2tUaW1lb3V0SWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuYmxvY2tUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIHRoaXMuYmxvY2tUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmJsb2NraW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmJsb2NrVGltZW91dElkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSwgdGhpcy5CTE9DS19USU1FT1VUX1ZBTFVFKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyB1bmJsb2NrKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5ibG9ja1RpbWVvdXRJZCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuYmxvY2tUaW1lb3V0SWQpO1xuICAgICAgICAgICAgdGhpcy5ibG9ja1RpbWVvdXRJZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy51bmJsb2NrVGltZW91dElkKSB7XG4gICAgICAgICAgICB0aGlzLnVuYmxvY2tUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmJsb2NraW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy51bmJsb2NrVGltZW91dElkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSwgdGhpcy5VTkJMT0NLX1RJTUVPVVRfVkFMVUUpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4iLCI8ZGl2XG4gICAgW2lkXT1cImlkXCJcbiAgICBjbGFzcz1cInMtbG9hZGluZy1zdGF0ZVwiXG4gICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAncy1sb2FkaW5nLXN0YXRlLS1sb2FkaW5nJzogbG9hZGluZyxcbiAgICAgICAgJ3MtbG9hZGluZy1zdGF0ZS0tYmxvY2tpbmcnOiBibG9ja2luZyxcbiAgICAgICAgJ3MtbG9hZGluZy1zdGF0ZS0tZnVsbHNjcmVlbic6IGJsb2NrV2luZG93XG4gICAgfVwiXG4+XG4gICAgPGRpdlxuICAgICAgICBbaWRdPVwiaWQgKyAnLWxvYWRlcidcIlxuICAgICAgICBjbGFzcz1cImxvYWRlclwiXG4gICAgPlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgICBbaWRdPVwiaWQgKyAnLXNwaW5uZXInXCJcbiAgICAgICAgICAgIGNsYXNzPVwic3Bpbm5lclwiXG4gICAgICAgID5cbiAgICAgICAgICAgIEBzd2l0Y2ggKGluZGljYXRvcikge1xuICAgICAgICAgICAgICAgIEBjYXNlICgnbG9nbycpIHtcbiAgICAgICAgICAgICAgICAgICAgPHMtbG9nby1pbmRpY2F0b3I+PC9zLWxvZ28taW5kaWNhdG9yPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBAY2FzZSAoJ2RvdHMnKSB7XG4gICAgICAgICAgICAgICAgICAgIDxzLWRvdHMtaW5kaWNhdG9yPjwvcy1kb3RzLWluZGljYXRvcj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgICBbaWRdPVwiaWQgKyAnLW92ZXJsYXknXCJcbiAgICAgICAgICAgIGNsYXNzPVwib3ZlcmxheVwiXG4gICAgICAgID48L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2XG4gICAgICAgIFtpZF09XCJpZCArICctY29udGVudHMnXCJcbiAgICAgICAgY2xhc3M9XCJzdGF0ZS1jb250ZW50c1wiXG4gICAgPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY29udGVudHMgfHwgb3JpZ2luYWxDb250ZW50XCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjb3JpZ2luYWxDb250ZW50PlxuICAgICAgICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZGluZy1zdGF0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNvbXBvbmVudHMvbG9hZGluZy1zdGF0ZS9zcmMvbGliL2xvYWRpbmctc3RhdGUvbG9hZGluZy1zdGF0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWNvbXBvbmVudHMvbG9hZGluZy1zdGF0ZS9zcmMvbGliL2xvYWRpbmctc3RhdGUvbG9hZGluZy1zdGF0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBMEIsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFNUYsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7Ozs7O0FBRS9FOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBT0gsTUFBTSxPQUFPLHFCQUFxQjtJQUN2QixNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUV6Qjs7Ozs7O09BTUc7SUFFSSxTQUFTLEdBQTJCLHNCQUFzQixDQUFDLElBQUksQ0FBQztJQUV2RTs7T0FFRztJQUVJLEVBQUUsR0FBRyxtQkFBbUIscUJBQXFCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUVoRTs7Ozs7T0FLRztJQUVJLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFFM0I7Ozs7T0FJRztJQUNILElBQ1csT0FBTyxDQUFDLE9BQWdCO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDNUMsQ0FBQztJQUVELElBQVcsT0FBTztRQUNkLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDO0lBRU0sUUFBUSxHQUE0QixJQUFJLENBQUM7SUFDekMsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUVoQixRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLG1CQUFtQixHQUFHLEdBQUcsQ0FBQztJQUMxQixxQkFBcUIsR0FBRyxHQUFHLENBQUM7SUFDNUIsY0FBYyxDQUFNO0lBQ3BCLGdCQUFnQixDQUFNO0lBRXZCLFdBQVc7UUFDZCxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUs7UUFDUixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1lBQ3BDLENBQUMsRUFBRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNqQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLE9BQU87UUFDVixJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1FBQ3BDLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ3BDLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUN0QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsU0FBUyxDQUFDO1lBQ3RDLENBQUMsRUFBRSxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0wsQ0FBQzt3R0F4RlEscUJBQXFCOzRGQUFyQixxQkFBcUIscUpDekJsQywra0NBeUNBOzs0RkRoQmEscUJBQXFCO2tCQU5qQyxTQUFTOytCQUNJLGlCQUFpQixpQkFHWixpQkFBaUIsQ0FBQyxJQUFJOzhCQWE5QixTQUFTO3NCQURmLEtBQUs7Z0JBT0MsRUFBRTtzQkFEUixLQUFLO2dCQVVDLFdBQVc7c0JBRGpCLEtBQUs7Z0JBU0ssT0FBTztzQkFEakIsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkRlc3Ryb3ksIFRlbXBsYXRlUmVmLCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBMb2FkaW5nU3RhdGVJbmRpY2F0b3JzIH0gZnJvbSAnLi9jb21wb25lbnRzL2xvYWRpbmctc3RhdGUtaW5kaWNhdG9ycyc7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbXBvbmVudGUgZGUgZXN0YWRvIGRlIGNhcnJlZ2FtZW50byBxdWUgZXhpYmUgdW0gaW5kaWNhZG9yIGFuaW1hZG8gZW5xdWFudG9cbiAqIHVtIHByb2Nlc3NvIGFzc8OtbmNyb25vIGVzdMOhIGVtIGFuZGFtZW50by4gU3Vwb3J0YSBibG9xdWVpbyBkYSBqYW5lbGEgaW50ZWlyYVxuICogZSBkaWZlcmVudGVzIHRpcG9zIGRlIGluZGljYWRvcmVzIHZpc3VhaXMuXG4gKiBUYW1iw6ltIHBvZGUgc2VyIHVzYWRvIGNvbW8gZGlyZXRpdmEgZXN0cnV0dXJhbCBgW3NMb2FkaW5nU3RhdGVdYC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgaHRtbFxuICogPHMtbG9hZGluZy1zdGF0ZSBbbG9hZGluZ109XCJpc0xvYWRpbmdcIiBbYmxvY2tXaW5kb3ddPVwidHJ1ZVwiPlxuICogICA8cD5Db250ZcO6ZG8gY2FycmVnYWRvITwvcD5cbiAqIDwvcy1sb2FkaW5nLXN0YXRlPlxuICogYGBgXG4gKlxuICogQGNhdGVnb3J5IEZlZWRiYWNrXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAncy1sb2FkaW5nLXN0YXRlJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vbG9hZGluZy1zdGF0ZS5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vbG9hZGluZy1zdGF0ZS5jb21wb25lbnQuc2NzcyddLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG59KVxuZXhwb3J0IGNsYXNzIExvYWRpbmdTdGF0ZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gICAgcHVibGljIHN0YXRpYyBuZXh0SWQgPSAwO1xuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFRpcG8gZGUgaW5kaWNhZG9yIHZpc3VhbCBleGliaWRvIGR1cmFudGUgbyBjYXJyZWdhbWVudG8uXG4gICAgICogLSBgTG9hZGluZ1N0YXRlSW5kaWNhdG9ycy5Eb3RzYDogaW5kaWNhZG9yIGRlIHBvbnRvcyBhbmltYWRvcyAocGFkcsOjbykuXG4gICAgICogLSBgTG9hZGluZ1N0YXRlSW5kaWNhdG9ycy5Mb2dvYDogaW5kaWNhZG9yIGNvbSBsb2dvdGlwbyBhbmltYWRvLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgTG9hZGluZ1N0YXRlSW5kaWNhdG9ycy5Eb3RzXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaW5kaWNhdG9yOiBMb2FkaW5nU3RhdGVJbmRpY2F0b3JzID0gTG9hZGluZ1N0YXRlSW5kaWNhdG9ycy5Eb3RzO1xuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIElkZW50aWZpY2Fkb3Igw7puaWNvIGRvIGNvbXBvbmVudGUuIEdlcmFkbyBhdXRvbWF0aWNhbWVudGUgc2UgbsOjbyBpbmZvcm1hZG8uXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaWQgPSBgcy1sb2FkaW5nLXN0YXRlLSR7TG9hZGluZ1N0YXRlQ29tcG9uZW50Lm5leHRJZCsrfWA7XG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gUXVhbmRvIGB0cnVlYCwgYmxvcXVlaWEgYSBqYW5lbGEgaW50ZWlyYSBkdXJhbnRlIG8gY2FycmVnYW1lbnRvLFxuICAgICAqIHNvYnJlcG9uZG8gdG9kbyBvIGNvbnRlw7pkbyBkYSBww6FnaW5hIGNvbSBvIGluZGljYWRvci5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0IGZhbHNlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgYmxvY2tXaW5kb3cgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBDb250cm9sYSBvIGVzdGFkbyBkZSBjYXJyZWdhbWVudG8gZG8gY29tcG9uZW50ZS4gQ2FtcG8gb2JyaWdhdMOzcmlvLlxuICAgICAqIFF1YW5kbyBgdHJ1ZWAsIGV4aWJlIG8gaW5kaWNhZG9yIGRlIGNhcnJlZ2FtZW50byBhcMOzcyB1bSBicmV2ZSBkZWxheS5cbiAgICAgKiBRdWFuZG8gYGZhbHNlYCwgcmVtb3ZlIG8gaW5kaWNhZG9yIGFww7NzIHVtIGJyZXZlIGRlbGF5IChldml0YSBmbGFzaCkuXG4gICAgICovXG4gICAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcbiAgICBwdWJsaWMgc2V0IGxvYWRpbmcobG9hZGluZzogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9sb2FkaW5nID0gbG9hZGluZztcbiAgICAgICAgbG9hZGluZyA/IHRoaXMuYmxvY2soKSA6IHRoaXMudW5ibG9jaygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgbG9hZGluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRpbmc7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbnRlbnRzOiBUZW1wbGF0ZVJlZjxhbnk+IHwgbnVsbCA9IG51bGw7XG4gICAgcHVibGljIGJsb2NraW5nID0gZmFsc2U7XG5cbiAgICBwcml2YXRlIF9sb2FkaW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBCTE9DS19USU1FT1VUX1ZBTFVFID0gMzAwO1xuICAgIHByaXZhdGUgVU5CTE9DS19USU1FT1VUX1ZBTFVFID0gMjAwO1xuICAgIHByaXZhdGUgYmxvY2tUaW1lb3V0SWQ6IGFueTtcbiAgICBwcml2YXRlIHVuYmxvY2tUaW1lb3V0SWQ6IGFueTtcblxuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuYmxvY2tUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmJsb2NrVGltZW91dElkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVuYmxvY2tUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnVuYmxvY2tUaW1lb3V0SWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGJsb2NrKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy51bmJsb2NrVGltZW91dElkKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy51bmJsb2NrVGltZW91dElkKTtcbiAgICAgICAgICAgIHRoaXMudW5ibG9ja1RpbWVvdXRJZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5ibG9ja1RpbWVvdXRJZCkge1xuICAgICAgICAgICAgdGhpcy5ibG9ja1RpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYmxvY2tpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYmxvY2tUaW1lb3V0SWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9LCB0aGlzLkJMT0NLX1RJTUVPVVRfVkFMVUUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHVuYmxvY2soKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmJsb2NrVGltZW91dElkKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5ibG9ja1RpbWVvdXRJZCk7XG4gICAgICAgICAgICB0aGlzLmJsb2NrVGltZW91dElkID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLnVuYmxvY2tUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIHRoaXMudW5ibG9ja1RpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYmxvY2tpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLnVuYmxvY2tUaW1lb3V0SWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9LCB0aGlzLlVOQkxPQ0tfVElNRU9VVF9WQUxVRSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbiIsIjxkaXZcbiAgICBbaWRdPVwiaWRcIlxuICAgIGNsYXNzPVwicy1sb2FkaW5nLXN0YXRlXCJcbiAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICdzLWxvYWRpbmctc3RhdGUtLWxvYWRpbmcnOiBsb2FkaW5nLFxuICAgICAgICAncy1sb2FkaW5nLXN0YXRlLS1ibG9ja2luZyc6IGJsb2NraW5nLFxuICAgICAgICAncy1sb2FkaW5nLXN0YXRlLS1mdWxsc2NyZWVuJzogYmxvY2tXaW5kb3dcbiAgICB9XCJcbj5cbiAgICA8ZGl2XG4gICAgICAgIFtpZF09XCJpZCArICctbG9hZGVyJ1wiXG4gICAgICAgIGNsYXNzPVwibG9hZGVyXCJcbiAgICA+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICAgIFtpZF09XCJpZCArICctc3Bpbm5lcidcIlxuICAgICAgICAgICAgY2xhc3M9XCJzcGlubmVyXCJcbiAgICAgICAgPlxuICAgICAgICAgICAgQHN3aXRjaCAoaW5kaWNhdG9yKSB7XG4gICAgICAgICAgICAgICAgQGNhc2UgKCdsb2dvJykge1xuICAgICAgICAgICAgICAgICAgICA8cy1sb2dvLWluZGljYXRvcj48L3MtbG9nby1pbmRpY2F0b3I+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIEBjYXNlICgnZG90cycpIHtcbiAgICAgICAgICAgICAgICAgICAgPHMtZG90cy1pbmRpY2F0b3I+PC9zLWRvdHMtaW5kaWNhdG9yPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICAgIFtpZF09XCJpZCArICctb3ZlcmxheSdcIlxuICAgICAgICAgICAgY2xhc3M9XCJvdmVybGF5XCJcbiAgICAgICAgPjwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXZcbiAgICAgICAgW2lkXT1cImlkICsgJy1jb250ZW50cydcIlxuICAgICAgICBjbGFzcz1cInN0YXRlLWNvbnRlbnRzXCJcbiAgICA+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjb250ZW50cyB8fCBvcmlnaW5hbENvbnRlbnRcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNvcmlnaW5hbENvbnRlbnQ+XG4gICAgICAgICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==