Skip to content

Commit 80eaa5a

Browse files
arthur-polidorioCSimoesJr
authored andcommitted
feat(news): ajusta popup e listbox para recebimento de template
ajusta popup e listbox para recebimento de template. Fixes: DTHFUI-8799
1 parent f055a01 commit 80eaa5a

12 files changed

+168
-56
lines changed

projects/ui/src/lib/components/po-icon/po-icon-dictionary.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,11 @@ export const AnimaliaIconDictionary: { [key: string]: string } = {
188188
ICON_ALIGN_LEFT: 'an an-text-align-left',
189189
ICON_ALIGN_RIGHT: 'an an-text-align-right',
190190
ICON_ARROW_DOWN: 'an an-caret-down',
191+
ICON_OTHER_ARROW_DOWN: 'an an-arrow-down',
191192
ICON_ARROW_LEFT: 'an an-caret-left',
192193
ICON_ARROW_RIGHT: 'an an-caret-right',
193194
ICON_ARROW_UP: 'an an-caret-up',
195+
ICON_OTHER_ARROW_UP: 'an an-arrow-up',
194196
ICON_CALENDAR: 'an an-calendar-blank',
195197
ICON_CLEAR_CONTENT: 'an an-x-circle',
196198
ICON_CLOCK: 'an an-clock',
@@ -204,6 +206,7 @@ export const AnimaliaIconDictionary: { [key: string]: string } = {
204206
ICON_EYE: 'an an-eye',
205207
ICON_EYE_OFF: 'an an-eye-closed',
206208
ICON_FILTER: 'an an-funnel',
209+
ICON_FUNNEL: 'an an-funnel-simple',
207210
ICON_HELP: 'an an-question',
208211
ICON_INFO: 'an an-info',
209212
ICON_LAST_PAGE: 'an an-caret-double-right',

projects/ui/src/lib/components/po-icon/po-icon.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@if (class) {
2-
<i [class]="class" aria-hidden="true">
2+
<i #iconElement [class]="class" aria-hidden="true">
33
<ng-content></ng-content>
44
</i>
55
} @else {

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import { ChangeDetectionStrategy, Component, Inject, Input, Optional, TemplateRef } from '@angular/core';
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
ElementRef,
5+
Inject,
6+
Input,
7+
Optional,
8+
TemplateRef,
9+
ViewChild
10+
} from '@angular/core';
211
import { ICONS_DICTIONARY, AnimaliaIconDictionary } from './po-icon-dictionary';
312
/**
413
* @docsPrivate
@@ -16,6 +25,7 @@ import { ICONS_DICTIONARY, AnimaliaIconDictionary } from './po-icon-dictionary';
1625
standalone: false
1726
})
1827
export class PoIconComponent {
28+
@ViewChild('iconElement', { static: false }) iconElement: ElementRef;
1929
class: string;
2030
private _icon: string | TemplateRef<void>;
2131
private _iconToken: { [key: string]: string };

projects/ui/src/lib/components/po-listbox/po-item-list/po-item-list-base.component.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ export class PoItemListBaseComponent {
120120
*/
121121
@Input('p-icon') icon: string | TemplateRef<void>;
122122

123+
/**
124+
* @optional
125+
*
126+
* @description
127+
*
128+
* Define se deve ser exibido o ícone indicando subnível.
129+
*/
130+
@Input('p-icon-arrow-right') iconArrowRight: string;
131+
123132
// Define a posição do ícone: 'left' (padrão) ou 'right'.
124133
@Input('p-icon-position') iconPosition: 'left' | 'right' = 'left';
125134

projects/ui/src/lib/components/po-listbox/po-item-list/po-item-list.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
[class.po-item-list__danger]="danger"
1313
class="po-item-list po-item-list__action"
1414
>
15-
@if (icon && iconPosition === 'left') {
15+
@if (icon) {
1616
<po-icon
1717
class="po-popup-icon-item po-field-icon"
1818
[class.po-field-icon-aa]="size === 'small'"
@@ -21,8 +21,8 @@
2121
}
2222
<span class="po-item-list-label">{{ label }}</span>
2323

24-
@if (icon && iconPosition === 'right') {
25-
<po-icon class="po-popup-icon-item-right po-field-icon" [p-icon]="icon"></po-icon>
24+
@if (iconArrowRight) {
25+
<po-icon class="po-popup-icon-item-right po-field-icon" [p-icon]="iconArrowRight"></po-icon>
2626
}
2727
</div>
2828
}

projects/ui/src/lib/components/po-listbox/po-listbox.component.html

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,14 @@
142142
(click)="onSelectItem(item, $event)"
143143
(keydown)="onKeyDown(item, $event)"
144144
>
145-
@if (item.subItems?.length) {
145+
@if (item.subItems?.length || item.$subItemTemplate) {
146146
<po-item-list
147147
[p-label]="item.label"
148148
[p-item]="item"
149149
[p-separator]="item.separator || separator"
150-
[p-icon]="'po-icon-arrow-right'"
151-
[p-icon-position]="'right'"
150+
[p-icon]="item.icon"
151+
[p-icon-arrow-right]="'po-icon-arrow-right'"
152+
[p-selected]="isSelectedItem(item) || item.selected"
152153
>
153154
</po-item-list>
154155
} @else if (!item.subItems?.length && returnBooleanValue(item, 'visible') !== false) {
@@ -176,47 +177,55 @@
176177
[cdkOption]="'back-option'"
177178
[attr.aria-label]="literals?.backToPreviousGroup"
178179
(click)="goBack($event)"
179-
(keydown)="onKeydownGoBack($event)"
180+
(keydown)="onKeydownGoBack($event, currentGroup)"
180181
>
181182
<po-icon class="po-field-icon" [p-icon]="'po-icon-arrow-left'"></po-icon>
182183
<po-tag [p-value]="currentGroup.label"></po-tag>
183184
</li>
184185

185-
@for (subItem of currentItems; track subItem.label) {
186-
@if (subItem.subItems?.length) {
187-
<li
188-
[cdkOption]="subItem[fieldLabel]"
189-
(click)="onSelectItem(subItem, $event)"
190-
(keydown)="onKeyDown(subItem, $event)"
191-
>
192-
<po-item-list
193-
[p-label]="subItem.label"
194-
[p-item]="subItem"
195-
[p-separator]="subItem.separator || separator"
196-
[p-icon]="'po-icon-arrow-right'"
197-
[p-icon-position]="'right'"
186+
@if (currentGroup.$subItemTemplate) {
187+
<div (click)="$event.stopPropagation()" (keydown)="onKeydownTemplate($event)">
188+
<ng-container
189+
*ngTemplateOutlet="currentGroup.$subItemTemplate; context: { $implicit: currentGroup }"
190+
></ng-container>
191+
</div>
192+
} @else {
193+
@for (subItem of currentItems; track subItem.label) {
194+
@if (subItem.subItems?.length) {
195+
<li
196+
[cdkOption]="subItem[fieldLabel]"
197+
(click)="onSelectItem(subItem, $event)"
198+
(keydown)="onKeyDown(subItem, $event)"
198199
>
199-
</po-item-list>
200-
</li>
201-
} @else if (!subItem.subItems?.length && returnBooleanValue(subItem, 'visible') !== false) {
202-
<li
203-
[cdkOption]="subItem[fieldLabel]"
204-
(click)="onSelectItem(subItem, $event)"
205-
(keydown)="onKeyDown(subItem, $event)"
206-
>
207-
<po-item-list
208-
class="po-listbox-item-sub"
209-
[p-disabled]="returnBooleanValue(subItem, 'disabled')"
210-
[p-visible]="returnBooleanValue(subItem, 'visible')"
211-
[p-label]="subItem[fieldLabel]"
212-
[p-item]="subItem"
213-
[p-icon]="subItem.icon"
214-
[p-separator]="subItem.separator || separator"
215-
[p-danger]="subItem.type === 'danger'"
216-
[p-selected]="isSelectedItem(subItem) || subItem.selected"
200+
<po-item-list
201+
[p-label]="subItem.label"
202+
[p-item]="subItem"
203+
[p-separator]="subItem.separator || separator"
204+
[p-icon]="'po-icon-arrow-right'"
205+
[p-icon-position]="'right'"
206+
>
207+
</po-item-list>
208+
</li>
209+
} @else if (!subItem.subItems?.length && returnBooleanValue(subItem, 'visible') !== false) {
210+
<li
211+
[cdkOption]="subItem[fieldLabel]"
212+
(click)="onSelectItem(subItem, $event)"
213+
(keydown)="onKeyDown(subItem, $event)"
217214
>
218-
</po-item-list>
219-
</li>
215+
<po-item-list
216+
class="po-listbox-item-sub"
217+
[p-disabled]="returnBooleanValue(subItem, 'disabled')"
218+
[p-visible]="returnBooleanValue(subItem, 'visible')"
219+
[p-label]="subItem[fieldLabel]"
220+
[p-item]="subItem"
221+
[p-icon]="subItem.icon"
222+
[p-separator]="subItem.separator || separator"
223+
[p-danger]="subItem.type === 'danger'"
224+
[p-selected]="isSelectedItem(subItem) || subItem.selected"
225+
>
226+
</po-item-list>
227+
</li>
228+
}
220229
}
221230
}
222231
}

projects/ui/src/lib/components/po-listbox/po-listbox.component.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,56 @@ describe('PoListBoxComponent', () => {
520520
expect((component as any).navigationStack.length).toBe(2);
521521
});
522522

523+
it('onKeydownTemplate: should emit closeEvent if press Tab out .po-listbox-dropdown', () => {
524+
const emitSpy = spyOn(component.closeEvent, 'emit');
525+
const stopSpy = jasmine.createSpy('stopPropagation');
526+
527+
const event = {
528+
code: 'Tab',
529+
target: document.createElement('div'),
530+
stopPropagation: stopSpy
531+
} as unknown as KeyboardEvent;
532+
533+
component['onKeydownTemplate'](event);
534+
535+
expect(stopSpy).not.toHaveBeenCalled();
536+
expect(emitSpy).toHaveBeenCalled();
537+
});
538+
539+
it('onKeydownTemplate: should call stopPropagation and not emit closeEvent when press Tab in .po-listbox-dropdown', () => {
540+
const emitSpy = spyOn(component.closeEvent, 'emit');
541+
const stopSpy = jasmine.createSpy('stopPropagation');
542+
543+
const dropdown = document.createElement('div');
544+
dropdown.classList.add('po-listbox-dropdown');
545+
546+
const child = document.createElement('div');
547+
dropdown.appendChild(child);
548+
document.body.appendChild(dropdown);
549+
550+
const event = {
551+
code: 'Tab',
552+
target: child,
553+
stopPropagation: stopSpy
554+
} as unknown as KeyboardEvent;
555+
556+
component['onKeydownTemplate'](event);
557+
558+
expect(stopSpy).toHaveBeenCalled();
559+
expect(emitSpy).not.toHaveBeenCalled();
560+
561+
dropdown.remove();
562+
});
563+
564+
it('onKeydownGoBack: should not emit closeEvent if subItemTemplate is true', () => {
565+
const eventTab = new KeyboardEvent('keydown', { code: 'Tab' });
566+
567+
spyOn(component.closeEvent, 'emit');
568+
569+
component.onKeydownGoBack(eventTab, { label: 'item', $subItemTemplate: true as any });
570+
expect(component.closeEvent.emit).not.toHaveBeenCalled();
571+
});
572+
523573
it('onKeydownGoBack should call goBack on Enter, emit closeEvent on Escape or Tab', () => {
524574
const eventEnter = new KeyboardEvent('keydown', { key: 'Enter' });
525575
const eventEscape = new KeyboardEvent('keydown', { code: 'Escape' });

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,25 @@ export class PoListBoxComponent extends PoListBoxBaseComponent implements OnInit
148148
});
149149
}
150150

151-
public onKeydownGoBack(event: KeyboardEvent): void {
151+
public onKeydownGoBack(event: KeyboardEvent, currentGroup?: PoDropdownAction): void {
152152
if (event.key === 'Enter') {
153153
this.goBack(event);
154154
}
155155

156156
if (event?.code === 'Escape' || event.code === 'Tab') {
157+
if (event.code === 'Tab' && !event.shiftKey && currentGroup?.$subItemTemplate) {
158+
return;
159+
}
160+
this.closeEvent.emit();
161+
}
162+
}
163+
164+
protected onKeydownTemplate(event: KeyboardEvent): void {
165+
if (event.code === 'Tab') {
166+
if ((event.target as HTMLElement)?.closest('.po-listbox-dropdown')) {
167+
event.stopPropagation();
168+
return;
169+
}
157170
this.closeEvent.emit();
158171
}
159172
}
@@ -184,7 +197,7 @@ export class PoListBoxComponent extends PoListBoxBaseComponent implements OnInit
184197
return this.openUrl(itemListAction.url);
185198
}
186199

187-
if (itemListAction?.subItems?.length) {
200+
if (itemListAction?.subItems?.length || itemListAction?.$subItemTemplate) {
188201
this.openGroup(itemListAction, event);
189202
} else if (this.listboxSubitems) {
190203
this.closeEvent.emit();

projects/ui/src/lib/components/po-popup/po-popup-action.interface.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,7 @@ export interface PoPopupAction {
139139

140140
// id interno
141141
$id?: string;
142+
143+
// template interno
144+
$subItemTemplate?: TemplateRef<any>;
142145
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ export class PoPopupBaseComponent {
9090
// Indica se há um listbox com subitens
9191
@Input('p-listbox-subitems') listboxSubitems = false;
9292

93+
// template-icon
94+
@Input('p-template-icon') templateIcon = false;
95+
9396
/** Lista de ações que serão exibidas no componente. */
9497
@Input('p-actions') set actions(value: Array<PoPopupAction>) {
9598
this._actions = Array.isArray(value) ? value : [];

0 commit comments

Comments
 (0)