Skip to content

Commit

Permalink
feat(multiselect): ajustes de merge do Carlos
Browse files Browse the repository at this point in the history
  • Loading branch information
CSimoesJr committed Oct 26, 2023
1 parent 1494d91 commit 776d39d
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[class.po-multiselect-show]="dropdownOpen"
>
<div
role="radiogroup"
#inputElement
[tabindex]="disabled ? -1 : 0"
[attr.disabled]="disabled"
Expand All @@ -31,13 +32,14 @@
</span>

<po-tag
*ngFor="let disclaimer of visibleDisclaimers"
*ngFor="let disclaimer of visibleDisclaimers; index as i"
[p-value]="disclaimer[fieldLabel]"
[p-literals]="i + 1 === visibleDisclaimers.length && hasMoreTag ? literalsTag : undefined"
[p-removable]="true"
[class.po-clickable]="disclaimer[fieldValue] === '' && !disabled"
[p-disabled]="disabled"
(p-close)="closeDisclaimer(disclaimer[fieldValue])"
(p-click)="closeDisclaimer(disclaimer[fieldValue])"
(p-close)="closeTag(disclaimer[fieldValue])"
(p-click)="closeTag(disclaimer[fieldValue], $event)"
></po-tag>

<div class="po-field-icon-container-right">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,52 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ContentChild,
DoCheck,
ElementRef,
forwardRef,
OnChanges,
OnDestroy,
Renderer2,
SimpleChanges,
ViewChild,
ContentChild
forwardRef
} from '@angular/core';
import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';

import { Observable, of } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { Observable, Subscription, fromEvent, of } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';

import { isMobile } from './../../../utils/util';
import { PoControlPositionService } from './../../../services/po-control-position/po-control-position.service';
import { PoKeyCodeEnum } from './../../../enums/po-key-code.enum';
import { PoLanguageService } from '../../../services/po-language/po-language.service';
import { PoKeyCodeEnum } from './../../../enums/po-key-code.enum';
import { PoControlPositionService } from './../../../services/po-control-position/po-control-position.service';
import { isMobile } from './../../../utils/util';

import { poLocaleDefault } from '../../../../public-api';
import { PoMultiselectBaseComponent } from './po-multiselect-base.component';
import { PoMultiselectOption } from './po-multiselect-option.interface';
import { PoMultiselectFilterService } from './po-multiselect-filter.service';
import { PoMultiselectOptionTemplateDirective } from './po-multiselect-option-template/po-multiselect-option-template.directive';
import { PoMultiselectOption } from './po-multiselect-option.interface';

const poMultiselectContainerOffset = 8;
const poMultiselectContainerPositionDefault = 'bottom';
const poMultiselectInputPaddingRight = 52;
const poMultiselectSpaceBetweenDisclaimers = 8;

const literalsTagRemoveOthers = {
pt: {
remove: 'Limpar todos os itens selecionados'
},
ru: {
remove: 'Очистить все выбранные элементы'
},
es: {
remove: 'Borrar todos los itens seleccionados'
},
en: {
remove: 'Clear all selected itens'
}
};

/* istanbul ignore next */
const providers = [
PoMultiselectFilterService,
Expand Down Expand Up @@ -110,14 +126,18 @@ export class PoMultiselectComponent
@ViewChild('iconElement', { read: ElementRef, static: true }) iconElement: ElementRef;
@ViewChild('inputElement', { read: ElementRef, static: true }) inputElement: ElementRef;

literalsTag;
disclaimerOffset = 0;
dropdownIcon: string = 'po-icon-arrow-down';
dropdownOpen: boolean = false;
initialized = false;
hasMoreTag: boolean;
positionDisclaimerExtra;
timeoutResize;
visibleElement = false;
initializedOnKeyDown: boolean = false;
private subscription: Subscription = new Subscription();
private enterCloseTag = false;
private initCalculateItems = true;
private isCalculateVisibleItems: boolean = true;
private cacheOptions: Array<PoMultiselectOption | any>;

Expand All @@ -130,23 +150,21 @@ export class PoMultiselectComponent
languageService: PoLanguageService
) {
super(languageService);
const language = languageService.getShortLanguage();
this.literalsTag = {
...literalsTagRemoveOthers[poLocaleDefault],
...literalsTagRemoveOthers[language]
};
}

ngAfterViewInit() {
// this.literalsTag;
if (this.autoFocus) {
this.focus();
}
this.initialized = true;
}

onKeyDownDropdown(event: KeyboardEvent, index: number) {
if (event.key === 'Escape') {
event.preventDefault();
this.controlDropdownVisibility(false);
this.inputElement.nativeElement.focus();
}
}

ngOnChanges(changes: SimpleChanges) {
if (this.filterService && (changes.filterService || changes.fieldValue || changes.fieldLabel)) {
this.setService(this.filterService);
Expand All @@ -167,6 +185,7 @@ export class PoMultiselectComponent
this.removeListeners();
this.getObjectsByValuesSubscription?.unsubscribe();
this.filterSubject?.unsubscribe();
this.subscription.unsubscribe();
}

/**
Expand Down Expand Up @@ -202,9 +221,10 @@ export class PoMultiselectComponent
}

calculateVisibleItems() {
this.hasMoreTag = false;
const disclaimersWidth = this.getDisclaimersWidth();
const inputWidth = this.getInputWidth();
const extraDisclaimerSize = 44;
const extraDisclaimerSize = 63;
const disclaimersVisible = disclaimersWidth[0];

this.visibleDisclaimers = [];
Expand All @@ -229,6 +249,7 @@ export class PoMultiselectComponent
return;
}

this.hasMoreTag = true;
if (sum + extraDisclaimerSize > inputWidth) {
this.visibleDisclaimers.splice(-2, 2);
const label = '+' + (this.selectedOptions.length + 1 - i).toString();
Expand All @@ -239,6 +260,13 @@ export class PoMultiselectComponent
this.visibleDisclaimers.push({ [this.fieldValue]: '', [this.fieldLabel]: label });
}
}
if (this.initCalculateItems) {
setTimeout(() => {
this.handleKeyboardNavigationTag();
}, 300);
}
this.initCalculateItems = false;
console.log('Mudei aqui: ', this.literalsTag);
}
this.changeDetector.markForCheck();
}
Expand All @@ -251,6 +279,9 @@ export class PoMultiselectComponent
this.changeDetector.detectChanges();
this.adjustContainerPosition();
}
setTimeout(() => {
this.handleKeyboardNavigationTag();
}, 300);
}

updateVisibleItems() {
Expand Down Expand Up @@ -294,29 +325,30 @@ export class PoMultiselectComponent
return;
}

if (event.keyCode === PoKeyCodeEnum.arrowDown) {
if (event.keyCode === PoKeyCodeEnum.arrowDown && this.visibleDisclaimers.length > 0) {
event.preventDefault();
this.controlDropdownVisibility(true);
this.dropdown?.listbox?.setFocus();
return;
}

if (event.keyCode === PoKeyCodeEnum.enter) {
if (event.keyCode === PoKeyCodeEnum.enter && !this.enterCloseTag) {
if (this.visibleDisclaimers.length === 0) {
this.controlDropdownVisibility(true);
this.toggleDropdownVisibility();
this.focus();
return;
} else {
event.preventDefault();
this.controlDropdownVisibility(true);
this.toggleDropdownVisibility();
return;
}
}

if (event.keyCode === PoKeyCodeEnum.space) {
event.preventDefault();
this.controlDropdownVisibility(true);
this.toggleDropdownVisibility();
}
this.enterCloseTag = false;
}

toggleDropdownVisibility() {
Expand All @@ -331,6 +363,14 @@ export class PoMultiselectComponent
this.controlDropdownVisibility(!this.dropdownOpen);
}

onKeyDownDropdown(event: KeyboardEvent, index: number) {
if (event.key === 'Escape') {
event.preventDefault();
this.controlDropdownVisibility(false);
this.inputElement.nativeElement.focus();
}
}

openDropdown(toOpen) {
if (toOpen && !this.disabled) {
this.controlDropdownVisibility(true);
Expand Down Expand Up @@ -370,22 +410,31 @@ export class PoMultiselectComponent
setTimeout(() => this.adjustContainerPosition());
}

closeDisclaimer(value) {
// criar funcao que se value estiver vazio remover de visubleOptionsDropdown todos os que nao estao em visibleDisclaimers
if (!value) {
for (let option of this.visibleDisclaimers) {
closeTag(value, event) {
let index;
this.enterCloseTag = true;
if (!value || (typeof value === 'string' && value.includes('+'))) {
index = null;
const itemsNotInVisibleDisclaimers = this.selectedOptions.filter(
option => !this.visibleDisclaimers.includes(option)
);
for (const option of this.visibleDisclaimers) {
if (!this.selectedOptions.includes(option)) {
this.selectedOptions.splice(this.selectedOptions.indexOf(option), 1);
this.selectedOptions.splice(this.visibleDisclaimers.length - 1, itemsNotInVisibleDisclaimers.length);
this.updateVisibleItems();
this.callOnChange(this.selectedOptions);
}
}
} else {
const index = this.selectedOptions.findIndex(option => option[this.fieldValue] === value);
index = this.selectedOptions.findIndex(option => option[this.fieldValue] === value);
this.selectedOptions.splice(index, 1);
this.updateVisibleItems();
this.callOnChange(this.selectedOptions);
}

setTimeout(() => {
this.focusOnNextTag(index, event);
}, 300);
}

wasClickedOnToggle(event: MouseEvent): void {
Expand Down Expand Up @@ -463,6 +512,53 @@ export class PoMultiselectComponent
this.removeListeners();
}

private focusOnNextTag(indexClosed: number, clickOrEnter: string) {
if (clickOrEnter === 'enter') {
const tagRemoveElements = this.el.nativeElement.querySelectorAll('.po-tag-remove');
indexClosed = indexClosed || indexClosed === 0 ? indexClosed : tagRemoveElements.length;
if (tagRemoveElements.length === indexClosed) {
tagRemoveElements[indexClosed - 1]?.focus();
} else {
tagRemoveElements[indexClosed]?.focus();
}
} else {
indexClosed = 0;
}
this.handleKeyboardNavigationTag(indexClosed);
}

private handleKeyboardNavigationTag(initialIndex = 0) {
this.subscription.unsubscribe();
this.subscription = new Subscription();
const tagRemoveElements = this.el.nativeElement.querySelectorAll('.po-tag-remove');
tagRemoveElements.forEach((tagRemoveElement, index) => {
if (index === initialIndex) {
tagRemoveElements[initialIndex].setAttribute('tabindex', 0);
} else if (tagRemoveElements.length === initialIndex) {
tagRemoveElements[initialIndex - 1].setAttribute('tabindex', 0);
} else {
tagRemoveElements[index].setAttribute('tabindex', -1);
}
this.subscription.add(
fromEvent(tagRemoveElement, 'keydown').subscribe((event: KeyboardEvent) => {
if (event.code === 'Space') {
event.preventDefault();
event.stopPropagation();
}
if (event.key === 'ArrowLeft' && index > 0) {
tagRemoveElements[index].setAttribute('tabindex', -1);
tagRemoveElements[index - 1].focus();
tagRemoveElements[index - 1].setAttribute('tabindex', 0);
} else if (event.key === 'ArrowRight' && index < tagRemoveElements.length - 1) {
tagRemoveElements[index].setAttribute('tabindex', -1);
tagRemoveElements[index + 1].focus();
tagRemoveElements[index + 1].setAttribute('tabindex', 0);
}
})
);
});
}

private initializeListeners(): void {
this.clickOutListener = this.renderer.listen('document', 'click', (event: MouseEvent) => {
this.wasClickedOnToggle(event);
Expand Down
1 change: 1 addition & 0 deletions projects/ui/src/lib/components/po-tag/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './enums/po-tag-orientation.enum';
export * from './enums/po-tag-type.enum';
export * from './interfaces/po-tag-literals.interface';
export * from './po-tag.component';

export * from './po-tag.module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @usedBy PoTagComponent
*
* @description
*
* Interface para definição das literais usadas no `po-tag`.
*/
export interface PoTagLiterals {
/** Texto exibido no tooltip indicando remoção da tag. */
remove?: string;
}
Loading

0 comments on commit 776d39d

Please sign in to comment.