ngx-sp-infra 6.4.0 → 6.4.2

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.
@@ -18,7 +18,7 @@ import * as i3 from 'ngx-pagination';
18
18
  import { NgxPaginationModule } from 'ngx-pagination';
19
19
  import { Subject, debounceTime, distinctUntilChanged, BehaviorSubject, map, takeUntil, Subscription, take, tap, firstValueFrom, filter } from 'rxjs';
20
20
  import * as i1$2 from '@angular/platform-browser';
21
- import { cloneDeep } from 'lodash';
21
+ import { cloneDeep, escapeRegExp } from 'lodash';
22
22
  import * as i2$1 from 'ngx-drag-drop';
23
23
  import { DndModule } from 'ngx-drag-drop';
24
24
  import * as i1$6 from '@angular/common/http';
@@ -9606,79 +9606,122 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
9606
9606
  }] } });
9607
9607
 
9608
9608
  class SearchInputComponent {
9609
- constructor(http, router) {
9610
- this.http = http;
9611
- this.router = router;
9609
+ // #endregion PUBLIC
9610
+ // #endregion ==========> PROPERTIES <==========
9611
+ constructor(_http, _router) {
9612
+ this._http = _http;
9613
+ this._router = _router;
9614
+ // #region ==========> PROPERTIES <==========
9615
+ // #region PRIVATE
9616
+ this._items = [];
9617
+ this.showIcons = false;
9618
+ this.onClose = new EventEmitter();
9612
9619
  this.isVisible = false;
9613
9620
  this.searchQuery = '';
9614
- this.items = [];
9615
- this.filteredItems = [...this.items];
9621
+ this.filteredItems = [...this._items];
9616
9622
  }
9617
9623
  ngOnInit() {
9618
9624
  this.loadRoutes();
9619
9625
  }
9620
9626
  ngAfterViewInit() {
9621
- if (this.isVisible) {
9627
+ if (this.isVisible)
9622
9628
  this.focusInput();
9623
- }
9624
9629
  }
9630
+ // #region ==========> UTILS <==========
9625
9631
  loadRoutes() {
9626
- this.http.get('assets/jsons/routes.json').subscribe(data => {
9627
- this.items = data;
9628
- }, error => {
9629
- console.error('Error loading routes:', error);
9630
- });
9632
+ if (!this.customItems) {
9633
+ this._http.get('assets\/jsons\/routes.json').subscribe(data => {
9634
+ this._items = data;
9635
+ this.filteredItems = [...this._items];
9636
+ }, error => console.error('Erro ao buscar as rotas.:', error));
9637
+ }
9638
+ else {
9639
+ this._items = this.customItems;
9640
+ }
9631
9641
  }
9632
9642
  onKeydown(event) {
9633
9643
  if (event.ctrlKey && event.key === 'p') {
9634
9644
  event.preventDefault();
9635
9645
  this.isVisible = !this.isVisible;
9636
- if (this.isVisible) {
9646
+ if (this.isVisible)
9637
9647
  setTimeout(() => this.focusInput(), 0);
9638
- }
9639
- else {
9648
+ else
9640
9649
  this.resetSearch();
9641
- }
9642
9650
  }
9643
9651
  else if (this.isVisible && event.key === 'Enter') {
9644
9652
  event.preventDefault();
9645
- if (this.filteredItems.length > 0) {
9653
+ if (this.filteredItems.length > 0)
9646
9654
  this.navigateTo(this.filteredItems[0].route);
9647
- }
9655
+ }
9656
+ else if (event.key === 'Escape') {
9657
+ this.closeSearch();
9648
9658
  }
9649
9659
  }
9660
+ navigateTo(route) {
9661
+ this._router.navigate([route]);
9662
+ this.closeSearch();
9663
+ }
9664
+ highlightList(pesquisa) {
9665
+ let list = document.querySelector('.options-list')?.querySelectorAll('li');
9666
+ // se pesquisa for vazia, remove highlights
9667
+ // if (!pesquisa.trim()) {
9668
+ // list?.forEach(li => {
9669
+ // const span = li.querySelector('span.tela') as HTMLElement | null;
9670
+ // const target = span ?? (li as HTMLElement);
9671
+ // // restaura apenas o texto bruto (remove marcações de highlight)
9672
+ // target.innerHTML = target.textContent ?? '';
9673
+ // });
9674
+ // return;
9675
+ // }
9676
+ const regex = new RegExp(escapeRegExp(pesquisa), 'ig');
9677
+ list?.forEach((li) => {
9678
+ const span = li.querySelector('span.tela');
9679
+ const target = span ?? li;
9680
+ const text = target.textContent ?? '';
9681
+ // substitui as ocorrências por um elemento de destaque (p.ex. <mark>)
9682
+ const highlighted = text.replace(regex, (match) => `<b style="color: #ebae00;">${match}</b>`);
9683
+ target.innerHTML = highlighted;
9684
+ });
9685
+ }
9686
+ // #region PESQUISA
9650
9687
  closeSearch() {
9651
9688
  this.isVisible = false;
9689
+ this.onClose.emit();
9652
9690
  this.resetSearch();
9653
9691
  }
9654
- resetSearch() {
9655
- this.searchQuery = '';
9656
- this.filteredItems = [...this.items];
9657
- }
9658
9692
  onSearch() {
9659
9693
  if (this.searchQuery.trim()) {
9660
- this.filteredItems = this.items.filter(item => item.label.toLowerCase().includes(this.searchQuery.toLowerCase()));
9694
+ this.filteredItems = this._items.filter(item => item.label.toLowerCase().includes(this.searchQuery.toLowerCase()));
9661
9695
  }
9662
9696
  else {
9663
- this.filteredItems = [...this.items];
9697
+ this.filteredItems = [...this._items];
9664
9698
  }
9665
9699
  }
9666
- navigateTo(route) {
9667
- this.router.navigate([route]);
9668
- this.closeSearch();
9700
+ resetSearch() {
9701
+ this.searchQuery = '';
9702
+ this.filteredItems = [...this._items];
9669
9703
  }
9670
9704
  focusInput() {
9671
- if (this.searchInput) {
9705
+ if (this.searchInput)
9672
9706
  this.searchInput.nativeElement.focus();
9673
- }
9674
9707
  }
9675
9708
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SearchInputComponent, deps: [{ token: i1$6.HttpClient }, { token: i1$3.Router }], target: i0.ɵɵFactoryTarget.Component }); }
9676
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: SearchInputComponent, isStandalone: true, selector: "lib-search-input", host: { listeners: { "document:keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "@if (isVisible) {\n<div class=\"search-overlay\">\n <div class=\"search-wrapper\">\n <div class=\"search-container\">\n <input type=\"text\" #searchInput [(ngModel)]=\"searchQuery\" (input)=\"onSearch()\"\n placeholder=\"Pesquise por telas da aplica\u00E7\u00E3o...\" class=\"form-control\" />\n <button (click)=\"closeSearch()\" class=\"btn btn-outline-primary ms-2\">Fechar</button>\n </div>\n\n @if (searchQuery !== '') {\n <div class=\"search-results\">\n <div class=\"scrollable-content\">\n <ul class=\"list-group list-group-flush\">\n @for (item of filteredItems; track $index) {\n <li (click)=\"navigateTo(item.route)\" style=\"cursor: pointer;\" class=\"list-group-item\">{{item.label}}</li>\n } \n @empty {\n <li class=\"list-group-item\">Nenhum registro encontrado</li>\n }\n </ul>\n </div>\n </div>\n \n }\n </div>\n</div>\n}", styles: [".search-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;flex-direction:column;align-items:center;padding-top:10px;z-index:9999}.search-wrapper{display:flex;flex-direction:column;align-items:center;width:100%;max-width:800px}.search-container{background-color:#fff;padding:10px 20px;border-radius:8px;box-shadow:0 4px 8px #0003;display:flex;align-items:center;width:100%}.search-results{background:#fff;padding:10px;border-radius:8px;box-shadow:0 4px 8px #0003;margin-top:10px;max-width:800px;width:100%}.scrollable-content{max-height:500px;overflow-y:auto;border-radius:8px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
9709
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: SearchInputComponent, isStandalone: true, selector: "lib-search-input, lib-pesquisa-global", inputs: { customItems: "customItems", showIcons: "showIcons" }, outputs: { onClose: "onClose" }, host: { listeners: { "document:keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "@if (isVisible) {\n <div class=\"search-overlay position-fixed w-100 h-100 d-flex flex-column align-items-center pt-3\">\n <div class=\"search-wrapper d-flex flex-column align-items-center w-100\" style=\"--max-width: 800px\">\n <div class=\"search-container w-100 bg-light d-flex flex-column align-items-start p-3 rounded\">\n <h6>\n <p class=\"fw-bold mb-0\"> Pesquisa global de telas entre os produtos adquiridos </p>\n <span class=\"text-muted fw-bold fst-italic\" style=\"font-size: 12px;\">(para fechar clique no bot\u00E3o ao lado ou aperte ESC)</span>\n </h6>\n\n <div class=\"input-group\">\n <span class=\"input-group-text\" id=\"addon-wrapping\"> <lib-icon iconName=\"p-lupa\" iconSize=\"medium-small\" /> </span>\n <input #searchInput type=\"text\" class=\"form-control\" [(ngModel)]=\"searchQuery\" placeholder=\"Pesquise pelo nome da tela\"\n (input)=\"onSearch(); highlightList(searchQuery)\" />\n <button (click)=\"resetSearch()\" class=\"btn btn-outline-primary\" tooltip=\"Limpar\" > <lib-icon iconName=\"p-lixeira\" iconSize=\"medium-small\" /> </button>\n <button (click)=\"closeSearch()\" class=\"btn btn-outline-primary\" tooltip=\"Fechar\" > <lib-icon iconName=\"p-fechar\" iconSize=\"medium-small\" /> </button>\n </div>\n </div>\n\n <div class=\"search-results bg-light p-2 rounded mt-3 w-100\">\n <div class=\"scrollable-content overflow-y-auto rounded\" style=\"--max-scrollable-height: 500px\">\n <ul class=\"options-list d-flex flex-column gap-2 p-0 m-0\">\n @for (item of filteredItems; track item.modulo+item.label) {\n <li (click)=\"navigateTo(item.route)\" class=\"glb-cursor-pointer option py-1 px-2 rounded border d-flex align-items-center gap-2\">\n @if (item.icon) { <lib-icon class=\"text-primary\" [iconName]=\"item.icon\" iconSize=\"medium-small\" /> }\n <span class=\"fw-bold text-primary\"> {{ item.modulo ? item.modulo : '' }} </span>\n\n @if (item.menu) {\n <span class=\"fw-bold text-primary menu\">\n / @if (showIcons) { <lib-icon iconName=\"p-menu-hamburguer\" iconSize=\"small\" /> } {{ item.menu }}\n </span>\n }\n\n @if (item.submenu) {\n <span class=\"fw-bold text-primary submenu\">\n / @if (showIcons) { <lib-icon iconName=\"p-link\" iconSize=\"small\" /> } {{ item.submenu }}\n </span>\n }\n\n <span class=\"tela\"> {{ item.label }} </span>\n </li>\n }\n @empty {\n <li class=\"list-group-item\"> Nenhuma tela encontrada com este nome </li>\n }\n </ul>\n </div>\n </div>\n </div>\n </div>\n}\n\n\n", styles: [".search-overlay{top:0;left:0;background-color:#00000080;z-index:9999}.search-overlay .search-wrapper{max-width:var(--max-width)}.search-overlay .search-wrapper .search-container{box-shadow:0 4px 8px #0003}.search-overlay .search-wrapper .search-results{box-shadow:0 4px 8px #0003;max-width:var(--max-width)}.search-overlay .search-wrapper .search-results .scrollable-content{max-height:var(--max-scrollable-height)}.search-overlay .search-wrapper .search-results .scrollable-content::-webkit-scrollbar{width:4px;background:transparent}.search-overlay .search-wrapper .search-results .scrollable-content::-webkit-scrollbar-thumb{background-color:#636363;border-radius:16px}.search-overlay .search-wrapper .search-results .scrollable-content .options-list{list-style-type:none}.search-overlay .search-wrapper .search-results .scrollable-content .options-list .option{transition:all .2s ease}.search-overlay .search-wrapper .search-results .scrollable-content .options-list .option:hover{background-color:#e5e5e5}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: LibIconsComponent, selector: "lib-icon", inputs: ["iconName", "iconColor", "iconSize", "iconFill"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$4.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }] }); }
9677
9710
  }
9678
9711
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SearchInputComponent, decorators: [{
9679
9712
  type: Component,
9680
- args: [{ selector: 'lib-search-input', imports: [FormsModule], template: "@if (isVisible) {\n<div class=\"search-overlay\">\n <div class=\"search-wrapper\">\n <div class=\"search-container\">\n <input type=\"text\" #searchInput [(ngModel)]=\"searchQuery\" (input)=\"onSearch()\"\n placeholder=\"Pesquise por telas da aplica\u00E7\u00E3o...\" class=\"form-control\" />\n <button (click)=\"closeSearch()\" class=\"btn btn-outline-primary ms-2\">Fechar</button>\n </div>\n\n @if (searchQuery !== '') {\n <div class=\"search-results\">\n <div class=\"scrollable-content\">\n <ul class=\"list-group list-group-flush\">\n @for (item of filteredItems; track $index) {\n <li (click)=\"navigateTo(item.route)\" style=\"cursor: pointer;\" class=\"list-group-item\">{{item.label}}</li>\n } \n @empty {\n <li class=\"list-group-item\">Nenhum registro encontrado</li>\n }\n </ul>\n </div>\n </div>\n \n }\n </div>\n</div>\n}", styles: [".search-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;flex-direction:column;align-items:center;padding-top:10px;z-index:9999}.search-wrapper{display:flex;flex-direction:column;align-items:center;width:100%;max-width:800px}.search-container{background-color:#fff;padding:10px 20px;border-radius:8px;box-shadow:0 4px 8px #0003;display:flex;align-items:center;width:100%}.search-results{background:#fff;padding:10px;border-radius:8px;box-shadow:0 4px 8px #0003;margin-top:10px;max-width:800px;width:100%}.scrollable-content{max-height:500px;overflow-y:auto;border-radius:8px}\n"] }]
9681
- }], ctorParameters: () => [{ type: i1$6.HttpClient }, { type: i1$3.Router }], propDecorators: { searchInput: [{
9713
+ args: [{ selector: 'lib-search-input, lib-pesquisa-global', imports: [
9714
+ FormsModule,
9715
+ LibIconsComponent,
9716
+ TooltipModule
9717
+ ], template: "@if (isVisible) {\n <div class=\"search-overlay position-fixed w-100 h-100 d-flex flex-column align-items-center pt-3\">\n <div class=\"search-wrapper d-flex flex-column align-items-center w-100\" style=\"--max-width: 800px\">\n <div class=\"search-container w-100 bg-light d-flex flex-column align-items-start p-3 rounded\">\n <h6>\n <p class=\"fw-bold mb-0\"> Pesquisa global de telas entre os produtos adquiridos </p>\n <span class=\"text-muted fw-bold fst-italic\" style=\"font-size: 12px;\">(para fechar clique no bot\u00E3o ao lado ou aperte ESC)</span>\n </h6>\n\n <div class=\"input-group\">\n <span class=\"input-group-text\" id=\"addon-wrapping\"> <lib-icon iconName=\"p-lupa\" iconSize=\"medium-small\" /> </span>\n <input #searchInput type=\"text\" class=\"form-control\" [(ngModel)]=\"searchQuery\" placeholder=\"Pesquise pelo nome da tela\"\n (input)=\"onSearch(); highlightList(searchQuery)\" />\n <button (click)=\"resetSearch()\" class=\"btn btn-outline-primary\" tooltip=\"Limpar\" > <lib-icon iconName=\"p-lixeira\" iconSize=\"medium-small\" /> </button>\n <button (click)=\"closeSearch()\" class=\"btn btn-outline-primary\" tooltip=\"Fechar\" > <lib-icon iconName=\"p-fechar\" iconSize=\"medium-small\" /> </button>\n </div>\n </div>\n\n <div class=\"search-results bg-light p-2 rounded mt-3 w-100\">\n <div class=\"scrollable-content overflow-y-auto rounded\" style=\"--max-scrollable-height: 500px\">\n <ul class=\"options-list d-flex flex-column gap-2 p-0 m-0\">\n @for (item of filteredItems; track item.modulo+item.label) {\n <li (click)=\"navigateTo(item.route)\" class=\"glb-cursor-pointer option py-1 px-2 rounded border d-flex align-items-center gap-2\">\n @if (item.icon) { <lib-icon class=\"text-primary\" [iconName]=\"item.icon\" iconSize=\"medium-small\" /> }\n <span class=\"fw-bold text-primary\"> {{ item.modulo ? item.modulo : '' }} </span>\n\n @if (item.menu) {\n <span class=\"fw-bold text-primary menu\">\n / @if (showIcons) { <lib-icon iconName=\"p-menu-hamburguer\" iconSize=\"small\" /> } {{ item.menu }}\n </span>\n }\n\n @if (item.submenu) {\n <span class=\"fw-bold text-primary submenu\">\n / @if (showIcons) { <lib-icon iconName=\"p-link\" iconSize=\"small\" /> } {{ item.submenu }}\n </span>\n }\n\n <span class=\"tela\"> {{ item.label }} </span>\n </li>\n }\n @empty {\n <li class=\"list-group-item\"> Nenhuma tela encontrada com este nome </li>\n }\n </ul>\n </div>\n </div>\n </div>\n </div>\n}\n\n\n", styles: [".search-overlay{top:0;left:0;background-color:#00000080;z-index:9999}.search-overlay .search-wrapper{max-width:var(--max-width)}.search-overlay .search-wrapper .search-container{box-shadow:0 4px 8px #0003}.search-overlay .search-wrapper .search-results{box-shadow:0 4px 8px #0003;max-width:var(--max-width)}.search-overlay .search-wrapper .search-results .scrollable-content{max-height:var(--max-scrollable-height)}.search-overlay .search-wrapper .search-results .scrollable-content::-webkit-scrollbar{width:4px;background:transparent}.search-overlay .search-wrapper .search-results .scrollable-content::-webkit-scrollbar-thumb{background-color:#636363;border-radius:16px}.search-overlay .search-wrapper .search-results .scrollable-content .options-list{list-style-type:none}.search-overlay .search-wrapper .search-results .scrollable-content .options-list .option{transition:all .2s ease}.search-overlay .search-wrapper .search-results .scrollable-content .options-list .option:hover{background-color:#e5e5e5}\n"] }]
9718
+ }], ctorParameters: () => [{ type: i1$6.HttpClient }, { type: i1$3.Router }], propDecorators: { customItems: [{
9719
+ type: Input
9720
+ }], showIcons: [{
9721
+ type: Input
9722
+ }], onClose: [{
9723
+ type: Output
9724
+ }], searchInput: [{
9682
9725
  type: ViewChild,
9683
9726
  args: ['searchInput']
9684
9727
  }], onKeydown: [{