Skip to content

Commit faab158

Browse files
luiz-s-vasconcellosanabye
authored andcommitted
refactor(timepicker): otimiza interações via teclado
Fixes DTHFUI-12748
1 parent c59c5f4 commit faab158

13 files changed

Lines changed: 1605 additions & 378 deletions

projects/ui/src/lib/components/po-button/po-button.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ import { PoButtonBaseComponent } from './po-button-base.component';
3131
export class PoButtonComponent extends PoButtonBaseComponent {
3232
@ViewChild('button', { static: true }) buttonElement: ElementRef;
3333

34+
constructor(public elementRef: ElementRef) {
35+
super();
36+
}
37+
3438
onBlur(): void {
3539
this.blur.emit();
3640
}

projects/ui/src/lib/components/po-dynamic/po-dynamic-form/interfaces/po-dynamic-form-field.interface.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ export interface PoDynamicFormField extends PoDynamicField {
7979
*/
8080
keydown?: Function;
8181

82-
/** Define a obrigatoriedade do campo. */
82+
/**
83+
* Define a obrigatoriedade do campo.
84+
*
85+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-timepicker`, `po-input`, `po-number`,
86+
* `po-decimal`, `po-select`, `po-radio-group`, `po-combo`, `po-lookup`, `po-checkbox-group`, `po-multiselect`,
87+
* `po-textarea`, `po-password``, `po-upload`.
88+
*/
8389
required?: boolean;
8490

8591
/**
@@ -88,7 +94,7 @@ export interface PoDynamicFormField extends PoDynamicField {
8894
*
8995
* > Necessário que a propriedade `required` esteja habilitada.
9096
*
91-
* **Componentes compatíveis:** `po-datepicker`, `po-input`, `po-number`, `po-decimal`, `po-password`.
97+
* **Componentes compatíveis:** `po-datepicker`, `po-timepicker`, `po-input`, `po-number`, `po-decimal`, `po-password`.
9298
*/
9399
requiredFieldErrorMessage?: boolean;
94100

@@ -98,6 +104,10 @@ export interface PoDynamicFormField extends PoDynamicField {
98104
* > A indicação não será exibida, se:
99105
* - O campo for `required`, ou;
100106
* - Não possuir `help` e `label`.
107+
*
108+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-timepicker`, `po-input`, `po-number`,
109+
* `po-decimal`, `po-select`, `po-radio-group`, `po-combo`, `po-lookup`, `po-checkbox-group`, `po-multiselect`,
110+
* `po-textarea`, `po-password`.
101111
*/
102112
optional?: boolean;
103113

@@ -360,14 +370,15 @@ export interface PoDynamicFormField extends PoDynamicField {
360370
* - required;
361371
*
362372
* > Esta mensagem pode ser exibida quando o campo estiver vazio, caso seja requerido. Em casos de componentes como
363-
* `po-datepicker`, `po-input`, `po-number`, `po-decimal`, `po-password`, é necessário que a propriedade
373+
* `po-datepicker`, `po-input`, `po-number`, `po-decimal`, `po-password`, `po-timepicker`, é necessário que a propriedade
364374
* `requiredFieldErrorMessage` esteja como `true` para que a mensagem seja exibida com o campo vazio. Componentes
365375
* como `po-datepicker-range`, `po-select`, `po-checkbox-group`, `po-radio-group`, `po-multiselect`, `po-combo`,
366376
* `po-lookup` e `po-textarea` não é necessário passar a propriedade `requiredFieldErrorMessage`.
367377
*
368378
*
369379
* **Componentes compatíveis:** `po-checkbox-group`, `po-combo`, `po-datepicker`, `po-datepicker-range`,
370-
* `po-decimal`, `po-input`, `po-lookup`, `po-multiselect`, `po-number`, `po-password`, `po-radio-group`, `po-select`, `po-switch`, `po-textarea`.
380+
* `po-decimal`, `po-input`, `po-lookup`, `po-multiselect`, `po-number`, `po-password`, `po-radio-group`, `po-select`,
381+
* `po-switch`, `po-textarea`, `po-timepicker`.
371382
*/
372383
errorMessage?: string;
373384

@@ -382,7 +393,8 @@ export interface PoDynamicFormField extends PoDynamicField {
382393
* e um tooltip será exibido ao passar o mouse sobre a mensagem para mostrar o conteúdo completo.
383394
*
384395
* **Componentes compatíveis:** `po-checkbox-group`, `po-combo`, `po-datepicker`, `po-datepicker-range`,
385-
* `po-decimal`, `po-input`, `po-lookup`, `po-multiselect`, `po-number`, `po-password`, `po-radio-group`, `po-select`, `po-switch`, `po-textarea`.
396+
* `po-decimal`, `po-input`, `po-lookup`, `po-multiselect`, `po-number`, `po-password`, `po-radio-group`, `po-select`,
397+
* `po-switch`, `po-textarea`, `po-timepicker`.
386398
*
387399
* @default `false`
388400
*/
@@ -426,6 +438,8 @@ export interface PoDynamicFormField extends PoDynamicField {
426438
*
427439
* Também pode-se utilizar em conjunto com `searchService`, informando uma lista de propriedades que será utilizado
428440
* para formatação da exibição no campo, por exemplo: ["id", "name"].
441+
*
442+
* **Componentes compatíveis:** `po-datepicker`, `po-timepicker`, `po-lookup`.
429443
*/
430444
format?: string | Array<string>;
431445

@@ -479,7 +493,12 @@ export interface PoDynamicFormField extends PoDynamicField {
479493
*/
480494
order?: number;
481495

482-
/** Mensagem que será exibida enquanto o campo não estiver preenchido. */
496+
/**
497+
* Mensagem que será exibida enquanto o campo não estiver preenchido.
498+
*
499+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-timepicker`, `po-input`, `po-number`,
500+
* `po-decimal`, `po-select`, `po-combo`, `po-lookup`, `po-multiselect`, `po-textarea`, `po-password`.
501+
*/
483502
placeholder?: string;
484503

485504
/**
@@ -495,7 +514,8 @@ export interface PoDynamicFormField extends PoDynamicField {
495514
* ```
496515
*
497516
* > Para ver quais linguagens suportadas acesse [`I18n`](documentation/po-i18n)
498-
* > A propriedade será repassada para os componentes que suportam a mesma.
517+
*
518+
* **Componentes compatíveis:** `po-datepicker`, `po-decimal`, `po-timepicker`.
499519
*/
500520
locale?: string;
501521

@@ -508,7 +528,8 @@ export interface PoDynamicFormField extends PoDynamicField {
508528

509529
/** Indica que o campo será somente leitura.
510530
*
511-
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-input`, `po-number`, `po-decimal`, `po-select`, `po-textarea`, `po-password`
531+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-timepicker`, `po-input`, `po-number`,
532+
* `po-decimal`, `po-select`, `po-textarea`, `po-password`.
512533
*/
513534
readonly?: boolean;
514535

@@ -521,14 +542,16 @@ export interface PoDynamicFormField extends PoDynamicField {
521542

522543
/** Se verdadeiro, o campo receberá um botão para ser limpo.
523544
*
524-
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-input`, `po-number`, `po-decimal`, `po-combo`, `po-lookup`, `po-password`
545+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-input`, `po-number`, `po-decimal`,
546+
* `po-combo`, `po-lookup`, `po-password`, `po-timepicker`.
525547
*/
526548
clean?: boolean;
527549

528550
/**
529551
* Define a propriedade nativa `autocomplete` do campo como off.
530552
*
531-
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-input`, `po-number`, `po-decimal`, `po-lookup`, `po-password`
553+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-input`, `po-number`, `po-decimal`,
554+
* `po-lookup`, `po-password`, `po-timepicker`.
532555
*/
533556
noAutocomplete?: boolean;
534557

@@ -838,6 +861,10 @@ export interface PoDynamicFormField extends PoDynamicField {
838861
*
839862
* > Não será exibida a indicação se:
840863
* - Não possuir `p-help` e/ou `p-label`.
864+
*
865+
* **Componentes compatíveis:** `po-datepicker`, `po-datepicker-range`, `po-timepicker`, `po-input`, `po-number`,
866+
* `po-decimal`, `po-select`, `po-radio-group`, `po-combo`, `po-lookup`, `po-checkbox-group`, `po-multiselect`,
867+
* `po-textarea`, `po-password`, `po-upload`.
841868
*/
842869
showRequired?: boolean;
843870

projects/ui/src/lib/components/po-field/po-timepicker/enums/po-timepicker-iso-format.enum.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @usedBy PoTimepickerComponent
2+
* @usedBy PoTimepickerComponent, PoDynamicFormComponent
33
*
44
* @description
55
*

projects/ui/src/lib/components/po-field/po-timepicker/po-timepicker-base.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,10 @@ export abstract class PoTimepickerBaseComponent implements ControlValueAccessor,
697697
}
698698

699699
validate(c: AbstractControl): { [key: string]: any } {
700-
this.errorPattern = this.isGeneratedErrorPattern(this.errorPattern) ? '' : this.errorPattern;
700+
// Limpar errorPattern se valor atual é válido (não tem erro parcial ou erro anterior)
701+
if (!this.hasValidationValue() && this.isValidTimeString(this.getValidationValue(c.value))) {
702+
this.errorPattern = this.isGeneratedErrorPattern(this.errorPattern) ? '' : this.errorPattern;
703+
}
701704

702705
if (!this.hasValidatorRequired && this.showErrorMessageRequired && c.hasValidator(Validators.required)) {
703706
this.hasValidatorRequired = true;

projects/ui/src/lib/components/po-field/po-timepicker/po-timepicker.component.html

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
[class.po-timepicker-field-disabled]="isDisabled"
2424
[class.po-timepicker-field-readonly]="readonly"
2525
[class.po-timepicker-field-focused]="isSegmentFocused"
26-
[attr.data-focused-element]="!isDisabled"
26+
[class.po-timepicker-field-placeholder]="isPlaceholder"
2727
[attr.data-inactive-component]="isDisabled || readonly"
2828
[attr.p-size]="size"
2929
[attr.data-append-in-body]="appendBox"
@@ -45,6 +45,7 @@
4545
[attr.aria-valuemin]="is12HourFormat ? 1 : 0"
4646
[attr.aria-valuemax]="is12HourFormat ? 12 : 23"
4747
[attr.aria-valuetext]="hourDisplay || null"
48+
[attr.data-focused-element]="!isDisabled"
4849
[attr.name]="name"
4950
[autocomplete]="autocomplete"
5051
[disabled]="isDisabled"
@@ -126,9 +127,8 @@
126127
type="text"
127128
[value]="periodDisplay || 'AM'"
128129
[disabled]="isDisabled"
129-
[readonly]="true"
130130
[attr.tabindex]="isDisabled || readonly ? -1 : 0"
131-
role="button"
131+
role="spinbutton"
132132
[attr.aria-label]="periodDisplay || 'AM'"
133133
(keydown)="onPeriodSegmentKeydown($event)"
134134
(click)="onPeriodSegmentClick($event)"
@@ -166,10 +166,11 @@
166166
[class.po-button-tertiary-danger]="getErrorPattern()"
167167
p-icon="ICON_CLOCK"
168168
p-kind="tertiary"
169+
[p-aria-label]="literals.open"
169170
[p-disabled]="isDisabled || readonly"
170171
[p-size]="size"
171172
(keydown)="onKeyPress($event)"
172-
(keydown.tab)="handleCleanKeyboardTab($event)"
173+
(keydown.tab)="handleTimepickerButtonKeyboardTab($event)"
173174
(p-click)="togglePicker(false)"
174175
>
175176
</po-button>
@@ -204,28 +205,30 @@
204205
}
205206

206207
<ng-template #sharedTimerContent>
207-
<div #dialogPicker [class.po-timepicker-popup-timer]="!verifyMobile()" tabindex="-1" [hidden]="!visible">
208-
@if (verifyMobile()) {
209-
<div class="po-timepicker-timer-overlay"></div>
210-
}
211-
<po-timer
212-
#timer
213-
[class.po-timepicker-timer-mobile]="verifyMobile()"
214-
[p-format]="format"
215-
[p-locale]="locale"
216-
[p-show-seconds]="showSeconds"
217-
[p-minute-interval]="minuteInterval"
218-
[p-second-interval]="secondInterval"
219-
[p-min-time]="minTime"
220-
[p-max-time]="maxTime"
221-
[p-size]="size"
222-
[p-value]="timeValue"
223-
(p-change)="timerSelected($event)"
224-
(p-boundary-tab)="onTimerBoundaryTab($event)"
225-
(keydown)="onTimerKeyDown($event)"
226-
(focusout)="onTimerFocusOut($event)"
227-
></po-timer>
228-
</div>
208+
@if (visible) {
209+
<div #dialogPicker [class.po-timepicker-popup-timer]="!verifyMobile()" tabindex="-1">
210+
@if (verifyMobile()) {
211+
<div class="po-timepicker-timer-overlay"></div>
212+
}
213+
<po-timer
214+
#timer
215+
[class.po-timepicker-timer-mobile]="verifyMobile()"
216+
[p-format]="format"
217+
[p-locale]="locale"
218+
[p-show-seconds]="showSeconds"
219+
[p-minute-interval]="minuteInterval"
220+
[p-second-interval]="secondInterval"
221+
[p-min-time]="minTime"
222+
[p-max-time]="maxTime"
223+
[p-size]="size"
224+
[p-value]="timeValue"
225+
(p-change)="timerSelected($event)"
226+
(p-boundary-tab)="onTimerBoundaryTab($event)"
227+
(keydown)="onTimerKeyDown($event)"
228+
(focusout)="onTimerFocusOut($event)"
229+
></po-timer>
230+
</div>
231+
}
229232
</ng-template>
230233

231234
<span class="po-sr-only" aria-live="polite" aria-atomic="true">{{ ariaLiveMessage }}</span>

0 commit comments

Comments
 (0)