@seniorsistemas/angular-components 19.5.4 → 19.5.5-feature-sds-547-89307cfb

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 (113) hide show
  1. package/accordion/lib/accordion/components/accordion-panel/accordion-panel.component.d.ts +2 -0
  2. package/accordion/lib/accordion/models/accordion-button-settings.d.ts +5 -0
  3. package/button/lib/button/button.component.d.ts +5 -1
  4. package/calendar-mask/lib/calendar-mask/calendar-mask.directive.d.ts +4 -0
  5. package/datepicker/README.md +175 -0
  6. package/datepicker/index.d.ts +5 -0
  7. package/datepicker/lib/datepicker/date.utils.d.ts +21 -0
  8. package/datepicker/lib/datepicker/datepicker.component.d.ts +254 -0
  9. package/datepicker/lib/datepicker/models/index.d.ts +16 -0
  10. package/datepicker/public-api.d.ts +2 -0
  11. package/dynamic-form/dynamic-form/form-field/configurations/fields/calendar-field.d.ts +119 -24
  12. package/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.d.ts +6 -23
  13. package/esm2022/accordion/lib/accordion/components/accordion-panel/accordion-panel.component.mjs +11 -3
  14. package/esm2022/accordion/lib/accordion/models/accordion-button-settings.mjs +1 -1
  15. package/esm2022/button/lib/button/button.component.mjs +9 -3
  16. package/esm2022/calendar-mask/lib/calendar-mask/calendar-mask.directive.mjs +5 -1
  17. package/esm2022/confirm-dialog/lib/popup-confirm-dialog/popup-confirm-dialog.component.mjs +1 -1
  18. package/esm2022/content-generator/lib/content-generator/content-generator.component.mjs +1 -1
  19. package/esm2022/datepicker/lib/datepicker/date.utils.mjs +182 -0
  20. package/esm2022/datepicker/lib/datepicker/datepicker.component.mjs +1062 -0
  21. package/esm2022/datepicker/lib/datepicker/models/index.mjs +2 -0
  22. package/esm2022/datepicker/public-api.mjs +2 -0
  23. package/esm2022/datepicker/seniorsistemas-angular-components-datepicker.mjs +5 -0
  24. package/esm2022/dynamic-form/dynamic-form/components/grid/row/row.component.mjs +2 -2
  25. package/esm2022/dynamic-form/dynamic-form/components/lookup/lookup.component.mjs +2 -2
  26. package/esm2022/dynamic-form/dynamic-form/form-field/configurations/fields/calendar-field.mjs +1 -1
  27. package/esm2022/dynamic-form/dynamic-form/form-field/fields/bignumber/bignumber-field.component.mjs +2 -2
  28. package/esm2022/dynamic-form/dynamic-form/form-field/fields/boolean/boolean-radio-field/boolean-field.component.mjs +1 -1
  29. package/esm2022/dynamic-form/dynamic-form/form-field/fields/button-field/button-field.component.mjs +1 -1
  30. package/esm2022/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.mjs +23 -116
  31. package/esm2022/dynamic-form/dynamic-form/form-field/fields/number/number-field.component.mjs +2 -2
  32. package/esm2022/dynamic-form/dynamic-form/form-field/fields/password/password-field.component.mjs +2 -2
  33. package/esm2022/dynamic-form/dynamic-form/form-field/fields/radio-button/radio-button-field.component.mjs +2 -2
  34. package/esm2022/dynamic-form/dynamic-form/form-field/fields/text/text-field.component.mjs +2 -2
  35. package/esm2022/empty-state/lib/empty-state/empty-state.component.mjs +1 -1
  36. package/esm2022/file-picker/lib/file-picker/file-picker.component.mjs +1 -1
  37. package/esm2022/global-search/lib/global-search/components/dropdown/global-search-dropdown-item.component.mjs +1 -1
  38. package/esm2022/global-search/lib/global-search/global-search.component.mjs +2 -2
  39. package/esm2022/help-popover/lib/help-popover/help-popover/help-popover.component.mjs +1 -1
  40. package/esm2022/image-cropper/lib/image-cropper/image-cropper.component.mjs +1 -1
  41. package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.mjs +22 -12
  42. package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-number/inline-edit-number.component.mjs +1 -1
  43. package/esm2022/inline-edit/lib/inline-edit/components/inline-edit-item/inline-edit-item.component.mjs +1 -1
  44. package/esm2022/inline-edit/lib/inline-edit/inline-edit.module.mjs +5 -5
  45. package/esm2022/kanban/lib/kanban/components/kanban-column/kanban-column.component.mjs +1 -1
  46. package/esm2022/lib/locale/fallback.mjs +52 -3
  47. package/esm2022/object-card/lib/object-card/elements/field/object-card-field.component.mjs +1 -1
  48. package/esm2022/object-card/lib/object-card/elements/main/object-card-main.component.mjs +1 -1
  49. package/esm2022/picklist/lib/picklist/picklist.component.mjs +2 -2
  50. package/esm2022/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.component.mjs +1 -1
  51. package/esm2022/select/lib/select/select.component.mjs +89 -11
  52. package/esm2022/shared/lib/accessibility/datepicker-no-period-tab.directive.mjs +545 -0
  53. package/esm2022/shared/public-api.mjs +2 -1
  54. package/esm2022/spotlight/lib/spotlight/spotlight.component.mjs +2 -2
  55. package/esm2022/table/lib/table/table-paging/table-paging.component.mjs +1 -1
  56. package/fesm2022/seniorsistemas-angular-components-accordion.mjs +10 -2
  57. package/fesm2022/seniorsistemas-angular-components-accordion.mjs.map +1 -1
  58. package/fesm2022/seniorsistemas-angular-components-button.mjs +8 -2
  59. package/fesm2022/seniorsistemas-angular-components-button.mjs.map +1 -1
  60. package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs +4 -0
  61. package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs.map +1 -1
  62. package/fesm2022/seniorsistemas-angular-components-confirm-dialog.mjs +1 -1
  63. package/fesm2022/seniorsistemas-angular-components-confirm-dialog.mjs.map +1 -1
  64. package/fesm2022/seniorsistemas-angular-components-content-generator.mjs +1 -1
  65. package/fesm2022/seniorsistemas-angular-components-content-generator.mjs.map +1 -1
  66. package/fesm2022/seniorsistemas-angular-components-datepicker.mjs +1250 -0
  67. package/fesm2022/seniorsistemas-angular-components-datepicker.mjs.map +1 -0
  68. package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +41 -133
  69. package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
  70. package/fesm2022/seniorsistemas-angular-components-empty-state.mjs +1 -1
  71. package/fesm2022/seniorsistemas-angular-components-empty-state.mjs.map +1 -1
  72. package/fesm2022/seniorsistemas-angular-components-file-picker.mjs +1 -1
  73. package/fesm2022/seniorsistemas-angular-components-file-picker.mjs.map +1 -1
  74. package/fesm2022/seniorsistemas-angular-components-global-search.mjs +2 -2
  75. package/fesm2022/seniorsistemas-angular-components-global-search.mjs.map +1 -1
  76. package/fesm2022/seniorsistemas-angular-components-help-popover.mjs +1 -1
  77. package/fesm2022/seniorsistemas-angular-components-help-popover.mjs.map +1 -1
  78. package/fesm2022/seniorsistemas-angular-components-image-cropper.mjs +1 -1
  79. package/fesm2022/seniorsistemas-angular-components-image-cropper.mjs.map +1 -1
  80. package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +26 -17
  81. package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
  82. package/fesm2022/seniorsistemas-angular-components-kanban.mjs +1 -1
  83. package/fesm2022/seniorsistemas-angular-components-kanban.mjs.map +1 -1
  84. package/fesm2022/seniorsistemas-angular-components-object-card.mjs +2 -2
  85. package/fesm2022/seniorsistemas-angular-components-object-card.mjs.map +1 -1
  86. package/fesm2022/seniorsistemas-angular-components-picklist.mjs +1 -1
  87. package/fesm2022/seniorsistemas-angular-components-picklist.mjs.map +1 -1
  88. package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs +1 -1
  89. package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs.map +1 -1
  90. package/fesm2022/seniorsistemas-angular-components-select.mjs +88 -10
  91. package/fesm2022/seniorsistemas-angular-components-select.mjs.map +1 -1
  92. package/fesm2022/seniorsistemas-angular-components-shared.mjs +545 -3
  93. package/fesm2022/seniorsistemas-angular-components-shared.mjs.map +1 -1
  94. package/fesm2022/seniorsistemas-angular-components-spotlight.mjs +1 -1
  95. package/fesm2022/seniorsistemas-angular-components-spotlight.mjs.map +1 -1
  96. package/fesm2022/seniorsistemas-angular-components-table.mjs +1 -1
  97. package/fesm2022/seniorsistemas-angular-components-table.mjs.map +1 -1
  98. package/fesm2022/seniorsistemas-angular-components.mjs +51 -2
  99. package/fesm2022/seniorsistemas-angular-components.mjs.map +1 -1
  100. package/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.d.ts +6 -4
  101. package/inline-edit/lib/inline-edit/inline-edit.module.d.ts +2 -2
  102. package/package.json +17 -7
  103. package/schematics/collection.json +4 -0
  104. package/schematics/migrations/migrate-p-datepicker/index.d.ts +2 -0
  105. package/schematics/migrations/migrate-p-datepicker/index.js +194 -0
  106. package/schematics/migrations/migrate-p-datepicker/index.js.map +1 -0
  107. package/schematics/migrations/migrate-p-datepicker/index.test.d.ts +1 -0
  108. package/schematics/migrations/migrate-p-datepicker/index.test.js +295 -0
  109. package/schematics/migrations/migrate-p-datepicker/index.test.js.map +1 -0
  110. package/schematics/migrations.json +10 -0
  111. package/select/lib/select/select.component.d.ts +40 -2
  112. package/shared/lib/accessibility/datepicker-no-period-tab.directive.d.ts +181 -0
  113. package/shared/public-api.d.ts +1 -0
@@ -84,6 +84,7 @@ export declare class AccordionPanelComponent implements OnChanges, AfterViewInit
84
84
  panelClosed: EventEmitter<void>;
85
85
  isAnimating: boolean;
86
86
  isContentAnimationDisabled: boolean;
87
+ readonly panelId: number;
87
88
  private _isOpen;
88
89
  get isOpen(): boolean;
89
90
  set isOpen(isOpen: boolean);
@@ -91,6 +92,7 @@ export declare class AccordionPanelComponent implements OnChanges, AfterViewInit
91
92
  ngAfterViewInit(): void;
92
93
  onIconButtonsClick(event: Event, callback: VoidFunction): void;
93
94
  onTabClick(): void;
95
+ onHeaderKeydown(event: KeyboardEvent): void;
94
96
  onContentAnimationStart(): void;
95
97
  onContentAnimationDone(): void;
96
98
  private _emitPanelEvent;
@@ -1,5 +1,10 @@
1
1
  export interface AccordionButtonSettings {
2
2
  icon: string;
3
3
  onClick: VoidFunction;
4
+ /**
5
+ * @description Rótulo acessível do botão, usado como `aria-label`.
6
+ * Recomendado para conformidade WCAG 2.1 AA (4.1.2 Name, Role, Value).
7
+ */
8
+ label?: string;
4
9
  }
5
10
  export type ValidationMessageIconColor = "Red" | "Orange" | "Yellow" | "Green" | "Blue";
@@ -128,6 +128,10 @@ export declare class ButtonComponent implements OnChanges {
128
128
  * @description Texto alternativo para o menu associado ao botão, utilizado para acessibilidade.
129
129
  */
130
130
  menuAriaLabel?: string;
131
+ /**
132
+ * @description Texto alternativo para quando o botão não tiver um texto explicito, utilizado para acessibilidade.
133
+ */
134
+ ariaLabel?: string;
131
135
  /**
132
136
  * @description Emitido ao clicar no botão, desde que não esteja desabilitado.
133
137
  */
@@ -139,5 +143,5 @@ export declare class ButtonComponent implements OnChanges {
139
143
  onTieredMenuOpened(): void;
140
144
  onTieredMenuClosed(): void;
141
145
  static ɵfac: i0.ɵɵFactoryDeclaration<ButtonComponent, never>;
142
- static ɵcmp: i0.ɵɵComponentDeclaration<ButtonComponent, "s-button", never, { "id": { "alias": "id"; "required": false; }; "label": { "alias": "label"; "required": false; }; "tooltip": { "alias": "tooltip"; "required": false; }; "tooltipPosition": { "alias": "tooltipPosition"; "required": false; }; "iconClass": { "alias": "iconClass"; "required": false; }; "rightIconClass": { "alias": "rightIconClass"; "required": false; }; "caret": { "alias": "caret"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "baseZIndex": { "alias": "baseZIndex"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "auxiliary": { "alias": "auxiliary"; "required": false; }; "type": { "alias": "type"; "required": false; }; "priority": { "alias": "priority"; "required": false; }; "menuOptions": { "alias": "menuOptions"; "required": false; }; "size": { "alias": "size"; "required": false; }; "slide": { "alias": "slide"; "required": false; }; "animation": { "alias": "animation"; "required": false; }; "badge": { "alias": "badge"; "required": false; }; "iconColor": { "alias": "iconColor"; "required": false; }; "menuAriaLabel": { "alias": "menuAriaLabel"; "required": false; }; }, { "clicked": "clicked"; }, never, ["*"], true, never>;
146
+ static ɵcmp: i0.ɵɵComponentDeclaration<ButtonComponent, "s-button", never, { "id": { "alias": "id"; "required": false; }; "label": { "alias": "label"; "required": false; }; "tooltip": { "alias": "tooltip"; "required": false; }; "tooltipPosition": { "alias": "tooltipPosition"; "required": false; }; "iconClass": { "alias": "iconClass"; "required": false; }; "rightIconClass": { "alias": "rightIconClass"; "required": false; }; "caret": { "alias": "caret"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "baseZIndex": { "alias": "baseZIndex"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "auxiliary": { "alias": "auxiliary"; "required": false; }; "type": { "alias": "type"; "required": false; }; "priority": { "alias": "priority"; "required": false; }; "menuOptions": { "alias": "menuOptions"; "required": false; }; "size": { "alias": "size"; "required": false; }; "slide": { "alias": "slide"; "required": false; }; "animation": { "alias": "animation"; "required": false; }; "badge": { "alias": "badge"; "required": false; }; "iconColor": { "alias": "iconColor"; "required": false; }; "menuAriaLabel": { "alias": "menuAriaLabel"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; }, { "clicked": "clicked"; }, never, ["*"], true, never>;
143
147
  }
@@ -2,6 +2,10 @@ import { AfterViewChecked, OnDestroy, OnInit, Renderer2 } from '@angular/core';
2
2
  import { Calendar } from 'primeng/calendar';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
5
+ * @deprecated
6
+ * @since 19.6.0
7
+ * Favor utilizar o componente: s-datepicker, que é o calendário oficial do Design System da Senior.
8
+ *
5
9
  * @description Diretiva que aplica máscara de entrada a um componente `p-calendar` do PrimeNG,
6
10
  * formatando automaticamente a data conforme o formato configurado no calendário.
7
11
  * Intercepta os eventos de teclado e input do campo interno do calendar para garantir
@@ -0,0 +1,175 @@
1
+ # Datepicker
2
+
3
+ ![Status](https://img.shields.io/badge/status-beta-yellow)
4
+
5
+ Componente completo de seleção de datas com campo de input e painel flutuante. Substituto direto do `p-datepicker` do PrimeNG, com API moderna baseada em Angular Signals e posicionamento nativo via CDK Overlay.
6
+
7
+ ## Quando usar
8
+
9
+ - Formulários que exigem seleção de data, hora ou intervalo de datas
10
+ - Filtros de período com seleção de data de início e fim (`mode="range"`)
11
+ - Campos de hora isolados sem calendário (`mode="time"`)
12
+ - Seleção de competência (mês/ano) sem necessidade de escolher o dia (`mode="month"`)
13
+
14
+ ## Quando não usar
15
+
16
+ - Para exibir datas sem interação — use `DatePipe` do Angular diretamente
17
+ - Para seleção de múltiplas datas avulsas — este componente não suporta `selectionMode="multiple"`
18
+ - Quando o campo está dentro de um modal e o painel precisa escapar do `overflow: hidden` — o CDK Overlay já trata isso nativamente; não é necessário configuração extra
19
+
20
+ ## Instalação
21
+
22
+ ```typescript
23
+ import { DatepickerComponent } from '@seniorsistemas/angular-components/datepicker';
24
+
25
+ @Component({
26
+ standalone: true,
27
+ imports: [DatepickerComponent],
28
+ })
29
+ export class MeuComponent {}
30
+ ```
31
+
32
+ ## Uso básico
33
+
34
+ ```html
35
+ <s-datepicker [formControl]="dataCtrl" mode="date" />
36
+ ```
37
+
38
+ ## API
39
+
40
+ ### Inputs
41
+
42
+ | Propriedade | Tipo | Padrão | Obrigatório | Descrição |
43
+ |---|---|---|:-----------:|---|
44
+ | `inputId` | `string` | auto-gerado | Não | HTML `id` aplicado ao elemento `<input>`. |
45
+ | `name` | `string` | `undefined` | Não | Atributo `name` do `<input>` nativo. |
46
+ | `placeholder` | `string` | `undefined` | Não | Texto exibido quando nenhum valor está selecionado. |
47
+ | `mode` | `DatePickerMode` | `'date'` | Não | Modo de seleção do componente. Ver tabela de modos abaixo. |
48
+ | `showIcon` | `boolean` | `true` | Não | Exibe o botão de ícone ao lado do campo. |
49
+ | `icon` | `string` | `'fas fa-calendar'` | Não | Classe CSS do ícone. No modo `time`, usa `'fas fa-clock'` automaticamente. |
50
+ | `showOnFocus` | `boolean` | `false` | Não | Abre o painel ao focar o campo. |
51
+ | `min` | `Date \| null` | `null` | Não | Data mínima selecionável. Dias anteriores ficam desabilitados. |
52
+ | `max` | `Date \| null` | `null` | Não | Data máxima selecionável. Dias posteriores ficam desabilitados. |
53
+ | `defaultDate` | `Date \| null` | `null` | Não | Data exibida ao abrir o painel quando nenhuma data está selecionada. |
54
+ | `dateFormat` | `string` | `'dd/MM/yyyy'` | Não | Formato de exibição da data no campo. |
55
+ | `hourFormat` | `'12' \| '24'` | `'24'` | Não | Formato de exibição das horas. |
56
+ | `minuteStep` | `number` | `5` | Não | Incremento em minutos ao usar as setas do time picker. |
57
+ | `showSeconds` | `boolean` | `false` | Não | Exibe o campo de segundos no time picker. |
58
+ | `rangeSeparator` | `string` | `' — '` | Não | Separador exibido entre as datas no modo `range`. |
59
+ | `disabled` | `boolean` | `false` | Não | Desabilita o componente (model two-way). |
60
+
61
+ ### Outputs
62
+
63
+ | Evento | Tipo emitido | Descrição |
64
+ |---|---|---|
65
+ | `blur` | `Event` | Emitido quando o campo perde o foco. |
66
+ | `focus` | `Event` | Emitido quando o campo recebe o foco. |
67
+ | `select` | `Date \| DateRange \| null` | Emitido ao selecionar uma data, mês, horário ou intervalo. |
68
+ | `close` | `void` | Emitido quando o painel do calendário fecha. |
69
+ | `todayClick` | `Date` | Emitido ao clicar no botão "Hoje". |
70
+ | `clearClick` | `void` | Emitido ao clicar no botão "Limpar". |
71
+ | `monthChange` | `{ month: number; year: number }` | Emitido quando o mês visualizado muda. |
72
+ | `yearChange` | `{ month: number; year: number }` | Emitido quando o ano visualizado muda. |
73
+
74
+ ### Tipos
75
+
76
+ ```typescript
77
+ type DatePickerMode = 'date' | 'month' | 'datetime' | 'time' | 'range';
78
+
79
+ interface DateRange {
80
+ start: Date | null;
81
+ end: Date | null;
82
+ }
83
+ ```
84
+
85
+ ### Modos (`DatePickerMode`)
86
+
87
+ | Modo | Valor emitido | Descrição |
88
+ |---|---|---|
89
+ | `date` | `Date` | Calendário com seleção de dia (padrão). |
90
+ | `month` | `Date` | Seleção de mês e ano — o `Date` emitido aponta para o primeiro dia do mês. |
91
+ | `datetime` | `Date` | Calendário + time picker. O painel só fecha ao clicar em "Confirmar". |
92
+ | `time` | `Date` | Apenas seletor de hora, sem calendário. |
93
+ | `range` | `DateRange` | Seleção de intervalo com data de início e fim. |
94
+
95
+ ## Exemplos
96
+
97
+ ### Com `formControl`
98
+
99
+ ```html
100
+ <s-datepicker [formControl]="dataCtrl" mode="date" />
101
+ ```
102
+
103
+ ```typescript
104
+ dataCtrl = new FormControl<Date | null>(null, Validators.required);
105
+ ```
106
+
107
+ ### Com `ngModel`
108
+
109
+ ```html
110
+ <s-datepicker [(ngModel)]="dataSelecionada" mode="datetime" />
111
+ ```
112
+
113
+ ### Data e hora
114
+
115
+ ```html
116
+ <s-datepicker [formControl]="ctrl" mode="datetime" [minuteStep]="15" [showSeconds]="true" />
117
+ ```
118
+
119
+ ### Intervalo de datas
120
+
121
+ ```html
122
+ <s-datepicker [formControl]="periodoCtrl" mode="range" rangeSeparator=" até " />
123
+ ```
124
+
125
+ ```typescript
126
+ periodoCtrl = new FormControl<DateRange | null>(null);
127
+ ```
128
+
129
+ ### Com limites de data
130
+
131
+ ```html
132
+ <s-datepicker [formControl]="ctrl" mode="date" [min]="dataMinima" [max]="dataMaxima" />
133
+ ```
134
+
135
+ ### Seleção de mês
136
+
137
+ ```html
138
+ <s-datepicker [formControl]="competenciaCtrl" mode="month" placeholder="Selecione a competência" />
139
+ ```
140
+
141
+ ### Apenas hora
142
+
143
+ ```html
144
+ <s-datepicker [formControl]="horaCtrl" mode="time" [minuteStep]="1" [showSeconds]="true" />
145
+ ```
146
+
147
+ ### Com Dynamic Form
148
+
149
+ ```typescript
150
+ const config: CalendarFieldConfig = {
151
+ type: 'date',
152
+ name: 'dataNascimento',
153
+ label: 'Data de nascimento',
154
+ };
155
+ ```
156
+
157
+ ```html
158
+ <s-dynamic-form [config]="config" />
159
+ ```
160
+
161
+ ## Acessibilidade
162
+
163
+ - O trigger usa `role="combobox"` com `aria-haspopup="grid"`, `aria-expanded` e `aria-controls` apontando para o painel
164
+ - O painel usa `role="dialog"` com `aria-label` traduzido e `cdkTrapFocus` para prender o foco dentro do popup
165
+ - Ao abrir o painel, o foco é movido automaticamente para o primeiro botão do calendário ou para o botão de incremento de horas no modo `time`
166
+ - Ao fechar o painel, o foco retorna ao botão de ícone do input trigger
167
+ - Tecla `Escape` fecha o painel e devolve o foco ao trigger
168
+ - Dias do calendário usam `role="gridcell"` com `aria-label` contendo a data por extenso, `aria-selected` e `aria-disabled`
169
+ - Cabeçalhos dos dias da semana usam `role="columnheader"` com `aria-label`
170
+ - Setas do time picker têm `aria-label` descritivos; as horas/minutos têm `aria-live="polite"`
171
+ - Todos os ícones decorativos têm `aria-hidden="true"`
172
+
173
+ ## Componentes relacionados
174
+
175
+ - [`DynamicFormComponent`](../../src/lib/dynamic-form/README.md) — usa `s-datepicker` internamente para campos do tipo `date`, `time`, `dateTime` e `localDateTime`
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="@seniorsistemas/angular-components/datepicker" />
5
+ export * from './public-api';
@@ -0,0 +1,21 @@
1
+ import type { DateRange } from './models';
2
+ export type { DateRange };
3
+ export declare function formatNativeDate(date: Date): string;
4
+ /**
5
+ * Formata uma data segundo um padrão simples contendo os tokens `dd`, `MM` e `yyyy`.
6
+ * Usado apenas para exibição em campos `type="text"` (modo `range`), onde o browser
7
+ * não controla o formato. Para `type="date"` nativo o formato é definido pelo browser.
8
+ */
9
+ export declare function formatWithPattern(date: Date, pattern: string): string;
10
+ export declare function formatTime(h: number, m: number, s?: number): string;
11
+ /** Parses yyyy-MM-dd. Returns null when invalid. */
12
+ export declare function parseDate(raw: string): Date | null;
13
+ export declare function isSameDay(a: Date, b: Date): boolean;
14
+ export declare function stripTime(date: Date): number;
15
+ export declare function parseRangeInput(raw: string, separator?: string): DateRange | null;
16
+ export declare function parseTimeInput(raw: string, base: Date | null, maxHours: number, maxMinutes: number): Date | null;
17
+ export declare function parseYearInput(raw: string): Date | null;
18
+ export declare function parseMonthInput(raw: string): Date | null;
19
+ export declare function parseDateTimeInput(raw: string): Date | null;
20
+ export declare function parseInput(mode: string, raw: string, base: Date | null, maxHours: number, maxMinutes: number, rangeSeparator?: string): Date | DateRange | null;
21
+ export declare function formatValueForInput(mode: string, value: Date | DateRange | Date[] | null, rangeSeparator?: string, dateFormat?: string, multipleSeparator?: string): string;
@@ -0,0 +1,254 @@
1
+ import { ConnectedPosition } from '@angular/cdk/overlay';
2
+ import { OnInit } from '@angular/core';
3
+ import { AbstractControl, ControlValueAccessor, NgControl, ValidationErrors, Validator } from '@angular/forms';
4
+ import type { CalendarDay, DatePickerMode, DateRange } from './models';
5
+ import * as i0 from "@angular/core";
6
+ type DatepickerValue = Date | DateRange | Date[] | null;
7
+ type PickerView = 'calendar' | 'months' | 'years';
8
+ export declare class DatepickerComponent implements ControlValueAccessor, Validator, OnInit {
9
+ private static idCounter;
10
+ private static readonly DAYS_IN_WEEK;
11
+ private static readonly MONTHS_IN_YEAR;
12
+ private static readonly MONTHS_PER_ROW;
13
+ private static readonly YEARS_PER_GRID;
14
+ private static readonly YEARS_PER_ROW;
15
+ private static readonly DEFAULT_MINUTE_STEP;
16
+ private static readonly MAX_HOURS;
17
+ private static readonly MAX_MINUTES;
18
+ private static readonly HOURS_PER_MERIDIEM;
19
+ private static nextId;
20
+ /** HTML `id` aplicado ao elemento `<input>`. Auto-gerado quando omitido. */
21
+ readonly inputId: import("@angular/core").InputSignal<string>;
22
+ /** Atributo `name` do `<input>` nativo. */
23
+ readonly name: import("@angular/core").InputSignal<string | undefined>;
24
+ /** Texto exibido quando nenhum valor está selecionado. */
25
+ readonly placeholder: import("@angular/core").InputSignal<string | undefined>;
26
+ /**
27
+ * Modo de seleção do componente.
28
+ * - `'date'` — seleção de data única (padrão)
29
+ * - `'month'` — seleção de mês/ano
30
+ * - `'datetime'` — data com hora (requer confirmação)
31
+ * - `'time'` — apenas seleção de hora
32
+ * - `'range'` — intervalo entre duas datas
33
+ */
34
+ readonly mode: import("@angular/core").InputSignal<DatePickerMode>;
35
+ /**
36
+ * Modo de seleção quando `mode` é `'date'`.
37
+ * - `'single'` — seleção de uma única data (padrão)
38
+ * - `'multiple'` — seleção de múltiplas datas avulsas
39
+ */
40
+ readonly selectionMode: import("@angular/core").InputSignal<"single" | "multiple">;
41
+ /** Separador exibido entre as datas no modo `selectionMode = 'multiple'`. */
42
+ readonly multipleSeparator: import("@angular/core").InputSignal<string>;
43
+ /** Quando `true`, exibe o botão de ícone ao lado do campo. */
44
+ readonly showIcon: import("@angular/core").InputSignal<boolean>;
45
+ /**
46
+ * Classe do ícone exibido no botão do campo.
47
+ * Quando `mode` é `'time'`, o padrão muda automaticamente para `'fas fa-clock'`.
48
+ */
49
+ readonly icon: import("@angular/core").InputSignal<string>;
50
+ /** Data mínima selecionável. Dias/meses anteriores ficam desabilitados. */
51
+ readonly min: import("@angular/core").InputSignal<Date | null>;
52
+ /** Data máxima selecionável. Dias/meses posteriores ficam desabilitados. */
53
+ readonly max: import("@angular/core").InputSignal<Date | null>;
54
+ /** Data exibida ao abrir o calendário quando nenhuma data está selecionada. */
55
+ readonly defaultDate: import("@angular/core").InputSignal<Date | null>;
56
+ /** Formato de exibição da data no campo (usado apenas para display). */
57
+ readonly dateFormat: import("@angular/core").InputSignal<string>;
58
+ /** Formato de exibição das horas: `'12'` ou `'24'`. */
59
+ readonly hourFormat: import("@angular/core").InputSignal<"12" | "24">;
60
+ /** Incremento em minutos ao usar as setas do time picker. */
61
+ readonly minuteStep: import("@angular/core").InputSignal<number>;
62
+ /** Quando `true`, exibe o campo de segundos no time picker. */
63
+ readonly showSeconds: import("@angular/core").InputSignal<boolean>;
64
+ /** Separador exibido entre as datas no modo `'range'`. */
65
+ readonly rangeSeparator: import("@angular/core").InputSignal<string>;
66
+ /** Abre o painel ao focar o input; foco permanece no input, não pula para o dropdown. */
67
+ readonly showOnFocus: import("@angular/core").InputSignal<boolean>;
68
+ /** Impede digitação manual; valor só pode ser selecionado pelo calendário. */
69
+ readonly readonlyInput: import("@angular/core").InputSignal<boolean>;
70
+ /** Primeiro dia da semana (0 = domingo, 1 = segunda-feira, ..., 6 = sábado). */
71
+ readonly firstDayOfWeek: import("@angular/core").InputSignal<number>;
72
+ /** Exibe/oculta a barra de botões Hoje e Limpar no rodapé. */
73
+ readonly showButtonBar: import("@angular/core").InputSignal<boolean>;
74
+ /** Exibe ícone de limpar inline no campo de input. */
75
+ readonly showClear: import("@angular/core").InputSignal<boolean>;
76
+ /** Exibe dias de meses adjacentes na grade do calendário. */
77
+ readonly showOtherMonths: import("@angular/core").InputSignal<boolean>;
78
+ /** Permite selecionar dias de meses adjacentes na grade do calendário. */
79
+ readonly selectOtherMonths: import("@angular/core").InputSignal<boolean>;
80
+ /** Fecha o painel após selecionar uma data no modo `datetime`. */
81
+ readonly hideOnDateTimeSelect: import("@angular/core").InputSignal<boolean>;
82
+ /** Incremento de horas no time picker. */
83
+ readonly stepHour: import("@angular/core").InputSignal<number>;
84
+ /** Incremento de segundos no time picker. */
85
+ readonly stepSecond: import("@angular/core").InputSignal<number>;
86
+ /** Índice de tab do campo de input. */
87
+ readonly tabindex: import("@angular/core").InputSignal<number | undefined>;
88
+ /** Foca automaticamente o campo ao carregar o componente. */
89
+ readonly autofocus: import("@angular/core").InputSignal<boolean>;
90
+ /** Datas específicas desabilitadas no calendário. */
91
+ readonly disabledDates: import("@angular/core").InputSignal<Date[]>;
92
+ /** Dias da semana desabilitados (0 = domingo, ..., 6 = sábado). */
93
+ readonly disabledDays: import("@angular/core").InputSignal<number[]>;
94
+ /** Estado desabilitado do componente. */
95
+ readonly disabled: import("@angular/core").ModelSignal<boolean>;
96
+ /** Emitido quando o campo perde o foco. */
97
+ readonly blurred: import("@angular/core").OutputEmitterRef<Event>;
98
+ /** Emitido quando o campo recebe o foco. */
99
+ readonly focused: import("@angular/core").OutputEmitterRef<Event>;
100
+ /** Emitido ao selecionar uma data, mês, horário ou intervalo. */
101
+ readonly selected: import("@angular/core").OutputEmitterRef<DatepickerValue>;
102
+ /** Emitido quando o painel do calendário fecha. Emite o elemento do painel. */
103
+ readonly closed: import("@angular/core").OutputEmitterRef<HTMLElement>;
104
+ /** Emitido ao clicar no botão "Hoje". */
105
+ readonly todayClick: import("@angular/core").OutputEmitterRef<Date>;
106
+ /** Emitido ao clicar no botão "Limpar" ou no ícone de limpar inline. */
107
+ readonly clearClick: import("@angular/core").OutputEmitterRef<MouseEvent>;
108
+ /** Emitido quando o mês visualizado muda. */
109
+ readonly monthChange: import("@angular/core").OutputEmitterRef<{
110
+ month: number;
111
+ year: number;
112
+ }>;
113
+ /** Emitido quando o ano visualizado muda. */
114
+ readonly yearChange: import("@angular/core").OutputEmitterRef<{
115
+ month: number;
116
+ year: number;
117
+ }>;
118
+ /** Emitido quando o painel do calendário abre. */
119
+ readonly show: import("@angular/core").OutputEmitterRef<void>;
120
+ /** Emitido quando o usuário digita manualmente no campo. */
121
+ readonly valueInput: import("@angular/core").OutputEmitterRef<Event>;
122
+ protected readonly maxHours = 24;
123
+ protected readonly maxMinutes = 60;
124
+ protected readonly timeInputMaxLength = 2;
125
+ protected inputDate: string;
126
+ protected ngControl: NgControl | null;
127
+ protected readonly value: import("@angular/core").WritableSignal<Date | null>;
128
+ protected readonly isOpen: import("@angular/core").WritableSignal<boolean>;
129
+ protected readonly viewDate: import("@angular/core").WritableSignal<Date>;
130
+ protected readonly pickerView: import("@angular/core").WritableSignal<PickerView>;
131
+ protected readonly hours: import("@angular/core").WritableSignal<number>;
132
+ protected readonly minutes: import("@angular/core").WritableSignal<number>;
133
+ protected readonly seconds: import("@angular/core").WritableSignal<number>;
134
+ protected readonly rangeValue: import("@angular/core").WritableSignal<DateRange | null>;
135
+ protected readonly multipleValues: import("@angular/core").WritableSignal<Date[]>;
136
+ protected readonly pendingRangeStart: import("@angular/core").WritableSignal<Date | null>;
137
+ protected readonly hoverDate: import("@angular/core").WritableSignal<Date | null>;
138
+ private _hasFormatError;
139
+ private _isBadInput;
140
+ private onValidatorChange;
141
+ private _onChange;
142
+ private _onTouched;
143
+ private readonly popupPanel;
144
+ private readonly increaseHourButton;
145
+ private readonly iconButton;
146
+ private readonly injector;
147
+ private readonly hostElement;
148
+ protected readonly resolvedIcon: import("@angular/core").Signal<string>;
149
+ /** Indica se o time picker deve usar o formato de 12 horas com seletor AM/PM. */
150
+ protected readonly is12HourFormat: import("@angular/core").Signal<boolean>;
151
+ /** Hora exibida no time picker: 1–12 no formato 12h, 0–23 no formato 24h. */
152
+ protected readonly displayHours: import("@angular/core").Signal<number>;
153
+ /** Meridiano atual derivado da hora interna (0–23). */
154
+ protected readonly amPm: import("@angular/core").Signal<"AM" | "PM">;
155
+ protected readonly positions: ConnectedPosition[];
156
+ protected readonly popupId: import("@angular/core").Signal<string>;
157
+ protected readonly currentMonthIndex: import("@angular/core").Signal<number>;
158
+ protected readonly currentYear: import("@angular/core").Signal<number>;
159
+ protected readonly currentMonthKey: import("@angular/core").Signal<string>;
160
+ protected readonly showCalendar: import("@angular/core").Signal<boolean>;
161
+ protected readonly showTimePicker: import("@angular/core").Signal<boolean>;
162
+ /** Seleção múltipla ativa: apenas no modo `date` com `selectionMode = 'multiple'`. */
163
+ protected readonly isMultipleMode: import("@angular/core").Signal<boolean>;
164
+ protected readonly orderedWeekDayKeys: import("@angular/core").Signal<string[]>;
165
+ protected readonly inputType: import("@angular/core").Signal<"date" | "month" | "time" | "text" | "datetime-local">;
166
+ protected readonly dialogAriaLabelKey: import("@angular/core").Signal<"platform.angular_components.datepicker_select_range" | "platform.angular_components.datepicker_select_date">;
167
+ protected readonly placeholderKey: import("@angular/core").Signal<string>;
168
+ protected readonly effectiveRange: import("@angular/core").Signal<{
169
+ start: Date | null;
170
+ end: Date | null;
171
+ }>;
172
+ protected readonly calendarWeeks: import("@angular/core").Signal<CalendarDay[][]>;
173
+ protected readonly monthsGrid: import("@angular/core").Signal<{
174
+ key: string;
175
+ index: number;
176
+ }[][]>;
177
+ protected readonly currentDecadeStart: import("@angular/core").Signal<number>;
178
+ protected readonly yearsGrid: import("@angular/core").Signal<number[][]>;
179
+ protected readonly prevDisabled: import("@angular/core").Signal<boolean>;
180
+ protected readonly nextDisabled: import("@angular/core").Signal<boolean>;
181
+ protected readonly weekDayKeys: string[];
182
+ protected readonly monthKeys: string[];
183
+ ngOnInit(): void;
184
+ writeValue(value: DatepickerValue): void;
185
+ registerOnChange(fn: (value: DatepickerValue) => void): void;
186
+ registerOnTouched(fn: () => void): void;
187
+ setDisabledState(isDisabled: boolean): void;
188
+ validate(control: AbstractControl): ValidationErrors | null;
189
+ registerOnValidatorChange(fn: () => void): void;
190
+ protected open(): void;
191
+ /** Abre o painel sem transferir o foco para o dropdown (usado pelo showOnFocus). */
192
+ private openOnFocus;
193
+ /**
194
+ * Define a view inicial do painel e posiciona o calendário no `defaultDate`
195
+ * quando nenhum valor está selecionado.
196
+ */
197
+ private prepareOpenView;
198
+ private focusBestCalendarTarget;
199
+ protected closePanel(): void;
200
+ protected toggle(): void;
201
+ protected handleOverlayKeydown(event: KeyboardEvent): void;
202
+ protected handleInputClick(): void;
203
+ protected handleInputFocus(event: Event): void;
204
+ protected handleNativeInput(event: Event): void;
205
+ protected handleInputBlur(event: Event): void;
206
+ protected handleInputChange(raw: string): void;
207
+ protected handleTriggerKeydown(event: KeyboardEvent): void;
208
+ protected navigatePrev(): void;
209
+ protected navigateNext(): void;
210
+ protected handleCalendarGridKeydown(event: KeyboardEvent): void;
211
+ private static findEnabled;
212
+ protected switchToMonths(): void;
213
+ protected backToCalendar(): void;
214
+ protected selectDate(day: CalendarDay): void;
215
+ /** Adiciona/remove uma data da seleção múltipla. O painel permanece aberto. */
216
+ private toggleMultipleDate;
217
+ protected selectYear(year: number): void;
218
+ protected selectMonth(monthIndex: number): void;
219
+ protected selectToday(): void;
220
+ protected clearValue(event: MouseEvent): void;
221
+ protected confirm(): void;
222
+ protected incrementHours(): void;
223
+ protected decrementHours(): void;
224
+ protected incrementMinutes(): void;
225
+ protected decrementMinutes(): void;
226
+ protected incrementSeconds(): void;
227
+ protected decrementSeconds(): void;
228
+ protected handleHoursKeydown(event: KeyboardEvent): void;
229
+ protected handleMinutesKeydown(event: KeyboardEvent): void;
230
+ protected handleSecondsKeydown(event: KeyboardEvent): void;
231
+ protected handleHoursInput(event: Event): void;
232
+ /** Alterna entre AM e PM somando/subtraindo 12 horas da hora interna. */
233
+ protected toggleAmPm(): void;
234
+ protected handleMinutesInput(event: Event): void;
235
+ protected handleSecondsInput(event: Event): void;
236
+ protected onDayHover(date: Date | null): void;
237
+ protected isDateDisabled(date: Date): boolean;
238
+ protected isYearSelected(year: number): boolean;
239
+ protected isYearDisabled(year: number): boolean;
240
+ protected isCurrentYear(year: number): boolean;
241
+ protected isMonthSelected(monthIndex: number): boolean;
242
+ protected isMonthDisabled(monthIndex: number): boolean;
243
+ protected padTime(value: number): string;
244
+ protected formatDayAriaLabel(date: Date): string;
245
+ /** Formata o valor para exibição no input, aplicando rangeSeparator, dateFormat e multipleSeparator. */
246
+ private formatForDisplay;
247
+ private syncTimeToValue;
248
+ private buildCalendarDay;
249
+ private computeValidationErrors;
250
+ private isDateRange;
251
+ static ɵfac: i0.ɵɵFactoryDeclaration<DatepickerComponent, never>;
252
+ static ɵcmp: i0.ɵɵComponentDeclaration<DatepickerComponent, "s-datepicker", never, { "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "multipleSeparator": { "alias": "multipleSeparator"; "required": false; "isSignal": true; }; "showIcon": { "alias": "showIcon"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "defaultDate": { "alias": "defaultDate"; "required": false; "isSignal": true; }; "dateFormat": { "alias": "dateFormat"; "required": false; "isSignal": true; }; "hourFormat": { "alias": "hourFormat"; "required": false; "isSignal": true; }; "minuteStep": { "alias": "minuteStep"; "required": false; "isSignal": true; }; "showSeconds": { "alias": "showSeconds"; "required": false; "isSignal": true; }; "rangeSeparator": { "alias": "rangeSeparator"; "required": false; "isSignal": true; }; "showOnFocus": { "alias": "showOnFocus"; "required": false; "isSignal": true; }; "readonlyInput": { "alias": "readonlyInput"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "showButtonBar": { "alias": "showButtonBar"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "showOtherMonths": { "alias": "showOtherMonths"; "required": false; "isSignal": true; }; "selectOtherMonths": { "alias": "selectOtherMonths"; "required": false; "isSignal": true; }; "hideOnDateTimeSelect": { "alias": "hideOnDateTimeSelect"; "required": false; "isSignal": true; }; "stepHour": { "alias": "stepHour"; "required": false; "isSignal": true; }; "stepSecond": { "alias": "stepSecond"; "required": false; "isSignal": true; }; "tabindex": { "alias": "tabindex"; "required": false; "isSignal": true; }; "autofocus": { "alias": "autofocus"; "required": false; "isSignal": true; }; "disabledDates": { "alias": "disabledDates"; "required": false; "isSignal": true; }; "disabledDays": { "alias": "disabledDays"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; "blurred": "blurred"; "focused": "focused"; "selected": "selected"; "closed": "closed"; "todayClick": "todayClick"; "clearClick": "clearClick"; "monthChange": "monthChange"; "yearChange": "yearChange"; "show": "show"; "valueInput": "valueInput"; }, never, never, true, never>;
253
+ }
254
+ export {};
@@ -0,0 +1,16 @@
1
+ export type DatePickerMode = 'date' | 'month' | 'year' | 'datetime' | 'time' | 'range';
2
+ export interface DateRange {
3
+ start: Date | null;
4
+ end: Date | null;
5
+ }
6
+ export interface CalendarDay {
7
+ date: Date;
8
+ dayOfMonth: number;
9
+ isCurrentMonth: boolean;
10
+ isToday: boolean;
11
+ isSelected: boolean;
12
+ isDisabled: boolean;
13
+ isRangeStart: boolean;
14
+ isRangeEnd: boolean;
15
+ isInRange: boolean;
16
+ }
@@ -0,0 +1,2 @@
1
+ export { DatepickerComponent } from './lib/datepicker/datepicker.component';
2
+ export type { DatePickerMode, DateRange, CalendarDay } from './lib/datepicker/models';