ngx-sp-infra 6.4.0 → 6.4.1

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,118 @@ 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;
9612
9618
  this.isVisible = false;
9613
9619
  this.searchQuery = '';
9614
- this.items = [];
9615
- this.filteredItems = [...this.items];
9620
+ this.filteredItems = [...this._items];
9616
9621
  }
9617
9622
  ngOnInit() {
9618
9623
  this.loadRoutes();
9619
9624
  }
9620
9625
  ngAfterViewInit() {
9621
- if (this.isVisible) {
9626
+ if (this.isVisible)
9622
9627
  this.focusInput();
9623
- }
9624
9628
  }
9629
+ // #region ==========> UTILS <==========
9625
9630
  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
- });
9631
+ if (!this.customItems) {
9632
+ this._http.get('assets\/jsons\/routes.json').subscribe(data => this._items = data, error => console.error('Erro ao buscar as rotas.:', error));
9633
+ }
9634
+ else {
9635
+ this._items = this.customItems;
9636
+ }
9631
9637
  }
9632
9638
  onKeydown(event) {
9633
9639
  if (event.ctrlKey && event.key === 'p') {
9634
9640
  event.preventDefault();
9635
9641
  this.isVisible = !this.isVisible;
9636
- if (this.isVisible) {
9642
+ if (this.isVisible)
9637
9643
  setTimeout(() => this.focusInput(), 0);
9638
- }
9639
- else {
9644
+ else
9640
9645
  this.resetSearch();
9641
- }
9642
9646
  }
9643
9647
  else if (this.isVisible && event.key === 'Enter') {
9644
9648
  event.preventDefault();
9645
- if (this.filteredItems.length > 0) {
9649
+ if (this.filteredItems.length > 0)
9646
9650
  this.navigateTo(this.filteredItems[0].route);
9647
- }
9651
+ }
9652
+ else if (event.key === 'Escape') {
9653
+ this.closeSearch();
9648
9654
  }
9649
9655
  }
9656
+ navigateTo(route) {
9657
+ this._router.navigate([route]);
9658
+ this.closeSearch();
9659
+ }
9660
+ highlightList(pesquisa) {
9661
+ let list = document.querySelector('.options-list')?.querySelectorAll('li');
9662
+ // se pesquisa for vazia, remove highlights
9663
+ // if (!pesquisa.trim()) {
9664
+ // list?.forEach(li => {
9665
+ // const span = li.querySelector('span.tela') as HTMLElement | null;
9666
+ // const target = span ?? (li as HTMLElement);
9667
+ // // restaura apenas o texto bruto (remove marcações de highlight)
9668
+ // target.innerHTML = target.textContent ?? '';
9669
+ // });
9670
+ // return;
9671
+ // }
9672
+ const regex = new RegExp(escapeRegExp(pesquisa), 'ig');
9673
+ list?.forEach((li) => {
9674
+ const span = li.querySelector('span.tela');
9675
+ const target = span ?? li;
9676
+ const text = target.textContent ?? '';
9677
+ // substitui as ocorrências por um elemento de destaque (p.ex. <mark>)
9678
+ const highlighted = text.replace(regex, (match) => `<b style="color: #ebae00;">${match}</b>`);
9679
+ target.innerHTML = highlighted;
9680
+ });
9681
+ }
9682
+ // #region PESQUISA
9650
9683
  closeSearch() {
9651
9684
  this.isVisible = false;
9652
9685
  this.resetSearch();
9653
9686
  }
9654
- resetSearch() {
9655
- this.searchQuery = '';
9656
- this.filteredItems = [...this.items];
9657
- }
9658
9687
  onSearch() {
9659
9688
  if (this.searchQuery.trim()) {
9660
- this.filteredItems = this.items.filter(item => item.label.toLowerCase().includes(this.searchQuery.toLowerCase()));
9689
+ this.filteredItems = this._items.filter(item => item.label.toLowerCase().includes(this.searchQuery.toLowerCase()));
9690
+ console.log(this.searchQuery);
9691
+ console.log(this._items);
9692
+ console.log(this.filteredItems);
9661
9693
  }
9662
9694
  else {
9663
- this.filteredItems = [...this.items];
9695
+ this.filteredItems = [...this._items];
9664
9696
  }
9665
9697
  }
9666
- navigateTo(route) {
9667
- this.router.navigate([route]);
9668
- this.closeSearch();
9698
+ resetSearch() {
9699
+ this.searchQuery = '';
9700
+ this.filteredItems = [...this._items];
9669
9701
  }
9670
9702
  focusInput() {
9671
- if (this.searchInput) {
9703
+ if (this.searchInput)
9672
9704
  this.searchInput.nativeElement.focus();
9673
- }
9674
9705
  }
9675
9706
  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"] }] }); }
9707
+ 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" }, 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>Pesquisa global de telas entre os produtos adquiridos</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 @if (searchQuery !== '') {\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 }\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
9708
  }
9678
9709
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: SearchInputComponent, decorators: [{
9679
9710
  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: [{
9711
+ args: [{ selector: 'lib-search-input, lib-pesquisa-global', imports: [
9712
+ FormsModule,
9713
+ LibIconsComponent,
9714
+ TooltipModule
9715
+ ], 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>Pesquisa global de telas entre os produtos adquiridos</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 @if (searchQuery !== '') {\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 }\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"] }]
9716
+ }], ctorParameters: () => [{ type: i1$6.HttpClient }, { type: i1$3.Router }], propDecorators: { customItems: [{
9717
+ type: Input
9718
+ }], showIcons: [{
9719
+ type: Input
9720
+ }], searchInput: [{
9682
9721
  type: ViewChild,
9683
9722
  args: ['searchInput']
9684
9723
  }], onKeydown: [{