@jvsoft/utils 0.0.13-alpha.6 → 1.0.0-alpha.11
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.
- package/README.md +5 -0
- package/directives/auto-select-first.directive.d.ts +13 -0
- package/directives/autocomplete-match-validator.directive.d.ts +10 -0
- package/directives/autocomplete.directive.d.ts +23 -0
- package/{src/functions → directives}/index.d.ts +1 -1
- package/directives/popover/popover-listener.directive.d.ts +12 -0
- package/directives/popover/popover-panel.component.d.ts +13 -0
- package/directives/popover/popover.directive.d.ts +23 -0
- package/directives/popover/popover.interface.d.ts +8 -0
- package/directives/popover/popover.service.d.ts +17 -0
- package/directives/public-api.d.ts +8 -0
- package/fesm2022/jvsoft-utils-directives.mjs +459 -0
- package/fesm2022/jvsoft-utils-directives.mjs.map +1 -0
- package/fesm2022/{jvsoft-utils-src-functions.mjs → jvsoft-utils-functions.mjs} +485 -191
- package/fesm2022/jvsoft-utils-functions.mjs.map +1 -0
- package/fesm2022/{jvsoft-utils-src-interfaces.mjs → jvsoft-utils-interfaces.mjs} +1 -1
- package/fesm2022/jvsoft-utils-interfaces.mjs.map +1 -0
- package/fesm2022/{jvsoft-utils-src-pipes.mjs → jvsoft-utils-pipes.mjs} +57 -2
- package/fesm2022/jvsoft-utils-pipes.mjs.map +1 -0
- package/fesm2022/jvsoft-utils-services.mjs +105 -0
- package/fesm2022/jvsoft-utils-services.mjs.map +1 -0
- package/fesm2022/jvsoft-utils.mjs +1084 -197
- package/fesm2022/jvsoft-utils.mjs.map +1 -1
- package/functions/base64.d.ts +63 -0
- package/functions/dev-log.d.ts +97 -0
- package/functions/index.d.ts +4 -0
- package/functions/mat-form-controls/autocomplete.d.ts +43 -27
- package/functions/objects-arrays.d.ts +13 -97
- package/functions/public-api.d.ts +1 -0
- package/interfaces/index.d.ts +4 -0
- package/package.json +32 -15
- package/pipes/display-with.pipe.d.ts +14 -0
- package/pipes/index.d.ts +4 -0
- package/pipes/public-api.d.ts +1 -0
- package/public-api.d.ts +6 -4
- package/{src/pipes → services}/index.d.ts +1 -1
- package/services/public-api.d.ts +1 -0
- package/services/reloj.service.d.ts +31 -0
- package/fesm2022/jvsoft-utils-src-functions.mjs.map +0 -1
- package/fesm2022/jvsoft-utils-src-interfaces.mjs.map +0 -1
- package/fesm2022/jvsoft-utils-src-pipes.mjs.map +0 -1
- package/src/functions/base64.d.ts +0 -26
- package/src/functions/browser.d.ts +0 -1
- package/src/functions/crypto-js.d.ts +0 -2
- package/src/functions/date.d.ts +0 -3
- package/src/functions/email.d.ts +0 -2
- package/src/functions/file.d.ts +0 -10
- package/src/functions/forms.d.ts +0 -23
- package/src/functions/http-client.d.ts +0 -2
- package/src/functions/local-storage.d.ts +0 -29
- package/src/functions/mat-form-controls/autocomplete.d.ts +0 -51
- package/src/functions/mat-form-controls/index.d.ts +0 -2
- package/src/functions/number.d.ts +0 -2
- package/src/functions/object-transformation.d.ts +0 -2
- package/src/functions/objects-arrays.d.ts +0 -147
- package/src/functions/public-api.d.ts +0 -16
- package/src/functions/string.d.ts +0 -23
- package/src/functions/sweetalert.d.ts +0 -5
- package/src/functions/utiles.d.ts +0 -1
- package/src/interfaces/datos.d.ts +0 -4
- package/src/interfaces/index.d.ts +0 -5
- package/src/interfaces/public-api.d.ts +0 -1
- package/src/pipes/data-en-lista.pipe.d.ts +0 -8
- package/src/pipes/date-diff-string.pipe.d.ts +0 -17
- package/src/pipes/filtro.pipe.d.ts +0 -18
- package/src/pipes/form-control-is-required.pipe.d.ts +0 -9
- package/src/pipes/json-parse.pipe.d.ts +0 -7
- package/src/pipes/no-sanitize.pipe.d.ts +0 -10
- package/src/pipes/public-api.d.ts +0 -8
- package/src/pipes/tipo-valor-funcion.pipe.d.ts +0 -9
- package/src/pipes/zero-fill.pipe.d.ts +0 -8
- /package/{classes → src/classes}/data-model.d.ts +0 -0
package/README.md
CHANGED
|
@@ -58,6 +58,11 @@ ng e2e
|
|
|
58
58
|
|
|
59
59
|
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
|
60
60
|
|
|
61
|
+
## Documentación
|
|
62
|
+
|
|
63
|
+
- [Directiva JvAutocomplete](./docs/autocomplete.md): Guía detallada de uso, ejemplos y referencia de la API.
|
|
64
|
+
- [Utilidades de Logging](./docs/logging.md): Guía para el uso de logs en desarrollo.
|
|
65
|
+
|
|
61
66
|
## Additional Resources
|
|
62
67
|
|
|
63
68
|
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export declare class AutoSelectFirstDirective {
|
|
3
|
+
private readonly ngControl;
|
|
4
|
+
private readonly fcName;
|
|
5
|
+
private readonly toastr;
|
|
6
|
+
options: import("@angular/core").InputSignal<any[] | null>;
|
|
7
|
+
jvsIdKey: import("@angular/core").InputSignal<string | string[] | null>;
|
|
8
|
+
jvsEmptyMsg: import("@angular/core").InputSignal<string>;
|
|
9
|
+
onAutoSelect: import("@angular/core").OutputEmitterRef<any>;
|
|
10
|
+
constructor();
|
|
11
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AutoSelectFirstDirective, never>;
|
|
12
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AutoSelectFirstDirective, "[jvsAutoSelectFirst]", never, { "options": { "alias": "jvsAutoSelectFirst"; "required": false; "isSignal": true; }; "jvsIdKey": { "alias": "jvsIdKey"; "required": false; "isSignal": true; }; "jvsEmptyMsg": { "alias": "jvsEmptyMsg"; "required": false; "isSignal": true; }; }, { "onAutoSelect": "onAutoSelect"; }, never, never, true, never>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AbstractControl, ValidationErrors, Validator } from '@angular/forms';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class AutocompleteMatchValidatorDirective implements Validator {
|
|
4
|
+
opciones: import("@angular/core").InputSignal<any[]>;
|
|
5
|
+
formControlName: import("@angular/core").InputSignal<any>;
|
|
6
|
+
idLista: import("@angular/core").InputSignal<string | undefined>;
|
|
7
|
+
validate(control: AbstractControl): ValidationErrors | null;
|
|
8
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AutocompleteMatchValidatorDirective, never>;
|
|
9
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AutocompleteMatchValidatorDirective, "[jvsAutocompleteMatch]", never, { "opciones": { "alias": "jvsAutocompleteMatch"; "required": false; "isSignal": true; }; "formControlName": { "alias": "formControlName"; "required": false; "isSignal": true; }; "idLista": { "alias": "idLista"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { OnInit } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class JvsAutocompleteDirective implements OnInit {
|
|
4
|
+
private readonly destroyRef;
|
|
5
|
+
private readonly ngControl;
|
|
6
|
+
private readonly focus$;
|
|
7
|
+
data: import("@angular/core").InputSignal<any[] | null>;
|
|
8
|
+
fields: import("@angular/core").InputSignal<string | string[]>;
|
|
9
|
+
typeReq: import("@angular/core").InputSignal<string>;
|
|
10
|
+
queryService: import("@angular/core").InputSignal<any>;
|
|
11
|
+
minLength: import("@angular/core").InputSignal<number>;
|
|
12
|
+
dataExtra: import("@angular/core").InputSignal<any>;
|
|
13
|
+
anonimo: import("@angular/core").InputSignal<boolean>;
|
|
14
|
+
debounce: import("@angular/core").InputSignal<number>;
|
|
15
|
+
filtered: import("@angular/core").OutputEmitterRef<any[]>;
|
|
16
|
+
loading: import("@angular/core").OutputEmitterRef<boolean>;
|
|
17
|
+
onFocus(): void;
|
|
18
|
+
ngOnInit(): void;
|
|
19
|
+
private filterLocal;
|
|
20
|
+
private fetchApi;
|
|
21
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<JvsAutocompleteDirective, never>;
|
|
22
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<JvsAutocompleteDirective, "[jvsAutocomplete]", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "typeReq": { "alias": "typeReq"; "required": false; "isSignal": true; }; "queryService": { "alias": "queryService"; "required": false; "isSignal": true; }; "minLength": { "alias": "minLength"; "required": false; "isSignal": true; }; "dataExtra": { "alias": "dataExtra"; "required": false; "isSignal": true; }; "anonimo": { "alias": "anonimo"; "required": false; "isSignal": true; }; "debounce": { "alias": "debounce"; "required": false; "isSignal": true; }; }, { "filtered": "filtered"; "loading": "loading"; }, never, never, true, never>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export declare class JvsPopoverListenerDirective {
|
|
3
|
+
private readonly popoverService;
|
|
4
|
+
private readonly elementRef;
|
|
5
|
+
trigger: import("@angular/core").InputSignal<"hover" | "click" | "focus">;
|
|
6
|
+
onMouseOver(event: MouseEvent): void;
|
|
7
|
+
onMouseOut(event: MouseEvent): void;
|
|
8
|
+
onClick(event: MouseEvent): void;
|
|
9
|
+
private findPopoverTarget;
|
|
10
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<JvsPopoverListenerDirective, never>;
|
|
11
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<JvsPopoverListenerDirective, "[jvsPopoverListener]", never, { "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TemplateRef } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class JvsPopoverPanelComponent {
|
|
4
|
+
content: import("@angular/core").InputSignal<string | null>;
|
|
5
|
+
templateContent: import("@angular/core").InputSignal<TemplateRef<any> | null>;
|
|
6
|
+
context: import("@angular/core").InputSignal<any>;
|
|
7
|
+
customClass: import("@angular/core").InputSignal<string>;
|
|
8
|
+
private readonly baseClasses;
|
|
9
|
+
combinedClasses: import("@angular/core").Signal<string>;
|
|
10
|
+
isTemplate(): boolean;
|
|
11
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<JvsPopoverPanelComponent, never>;
|
|
12
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<JvsPopoverPanelComponent, "jvs-popover-panel", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "templateContent": { "alias": "templateContent"; "required": false; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; "customClass": { "alias": "customClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { OnDestroy, TemplateRef } from '@angular/core';
|
|
2
|
+
import { JvsPopoverTrigger } from './popover.interface';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class JvsPopoverDirective implements OnDestroy {
|
|
5
|
+
private readonly popoverService;
|
|
6
|
+
private readonly elementRef;
|
|
7
|
+
private readonly viewContainerRef;
|
|
8
|
+
content: import("@angular/core").InputSignal<string | TemplateRef<any> | null>;
|
|
9
|
+
context: import("@angular/core").InputSignal<any>;
|
|
10
|
+
trigger: import("@angular/core").InputSignal<JvsPopoverTrigger>;
|
|
11
|
+
position: import("@angular/core").InputSignal<"top" | "bottom" | "left" | "right">;
|
|
12
|
+
customClass: import("@angular/core").InputSignal<string>;
|
|
13
|
+
onMouseEnter(): void;
|
|
14
|
+
onMouseLeave(): void;
|
|
15
|
+
onClick(): void;
|
|
16
|
+
onFocus(): void;
|
|
17
|
+
onBlur(): void;
|
|
18
|
+
ngOnDestroy(): void;
|
|
19
|
+
show(): void;
|
|
20
|
+
hide(): void;
|
|
21
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<JvsPopoverDirective, never>;
|
|
22
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<JvsPopoverDirective, "[jvsPopover]", never, { "content": { "alias": "jvsPopover"; "required": false; "isSignal": true; }; "context": { "alias": "context"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "customClass": { "alias": "customClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TemplateRef, ViewContainerRef } from '@angular/core';
|
|
2
|
+
import { OverlayRef } from '@angular/cdk/overlay';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class JvsPopoverService {
|
|
5
|
+
private readonly overlay;
|
|
6
|
+
private readonly overlayPositionBuilder;
|
|
7
|
+
private overlayRef;
|
|
8
|
+
open(element: HTMLElement, content: string | TemplateRef<any>, options?: {
|
|
9
|
+
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
10
|
+
customClass?: string;
|
|
11
|
+
viewContainerRef?: ViewContainerRef;
|
|
12
|
+
context?: any;
|
|
13
|
+
}): OverlayRef;
|
|
14
|
+
close(): void;
|
|
15
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<JvsPopoverService, never>;
|
|
16
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<JvsPopoverService>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './autocomplete-match-validator.directive';
|
|
2
|
+
export * from './popover/popover.directive';
|
|
3
|
+
export * from './popover/popover-listener.directive';
|
|
4
|
+
export * from './popover/popover.interface';
|
|
5
|
+
export * from './popover/popover-panel.component';
|
|
6
|
+
export * from './popover/popover.service';
|
|
7
|
+
export * from './autocomplete.directive';
|
|
8
|
+
export * from './auto-select-first.directive';
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, forwardRef, Directive, computed, Component, inject, TemplateRef, Injectable, ElementRef, ViewContainerRef, HostListener, DestroyRef, output, effect, untracked } from '@angular/core';
|
|
3
|
+
import { NG_VALIDATORS, NgControl, FormControlName } from '@angular/forms';
|
|
4
|
+
import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay';
|
|
5
|
+
import { ComponentPortal } from '@angular/cdk/portal';
|
|
6
|
+
import * as i1 from '@angular/common';
|
|
7
|
+
import { CommonModule } from '@angular/common';
|
|
8
|
+
import { Subject, merge, debounceTime, startWith, distinctUntilChanged, tap, switchMap, of, map, finalize } from 'rxjs';
|
|
9
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
10
|
+
import { ToastrService } from 'ngx-toastr';
|
|
11
|
+
|
|
12
|
+
class AutocompleteMatchValidatorDirective {
|
|
13
|
+
opciones = input([], { alias: 'jvsAutocompleteMatch' });
|
|
14
|
+
formControlName = input();
|
|
15
|
+
idLista = input();
|
|
16
|
+
validate(control) {
|
|
17
|
+
const idLista = this.idLista() ?? this.formControlName();
|
|
18
|
+
const value = control.value;
|
|
19
|
+
const opciones = this.opciones();
|
|
20
|
+
if (!value)
|
|
21
|
+
return null;
|
|
22
|
+
if (!opciones) {
|
|
23
|
+
console.error('Debe definir opciones para el validador jvsAutocompleteMatch');
|
|
24
|
+
return { itemSelected: true };
|
|
25
|
+
}
|
|
26
|
+
const encontrado = opciones.some(item => typeof value === 'object'
|
|
27
|
+
? item[idLista] === value[idLista]
|
|
28
|
+
: item[idLista] === value);
|
|
29
|
+
return encontrado ? null : { itemSelected: true };
|
|
30
|
+
}
|
|
31
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutocompleteMatchValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
32
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: AutocompleteMatchValidatorDirective, isStandalone: true, selector: "[jvsAutocompleteMatch]", inputs: { opciones: { classPropertyName: "opciones", publicName: "jvsAutocompleteMatch", isSignal: true, isRequired: false, transformFunction: null }, formControlName: { classPropertyName: "formControlName", publicName: "formControlName", isSignal: true, isRequired: false, transformFunction: null }, idLista: { classPropertyName: "idLista", publicName: "idLista", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
33
|
+
{
|
|
34
|
+
provide: NG_VALIDATORS,
|
|
35
|
+
useExisting: forwardRef(() => AutocompleteMatchValidatorDirective),
|
|
36
|
+
multi: true,
|
|
37
|
+
},
|
|
38
|
+
], ngImport: i0 });
|
|
39
|
+
}
|
|
40
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutocompleteMatchValidatorDirective, decorators: [{
|
|
41
|
+
type: Directive,
|
|
42
|
+
args: [{
|
|
43
|
+
selector: '[jvsAutocompleteMatch]',
|
|
44
|
+
providers: [
|
|
45
|
+
{
|
|
46
|
+
provide: NG_VALIDATORS,
|
|
47
|
+
useExisting: forwardRef(() => AutocompleteMatchValidatorDirective),
|
|
48
|
+
multi: true,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
standalone: true
|
|
52
|
+
}]
|
|
53
|
+
}] });
|
|
54
|
+
|
|
55
|
+
class JvsPopoverPanelComponent {
|
|
56
|
+
content = input(null);
|
|
57
|
+
templateContent = input(null);
|
|
58
|
+
context = input(null);
|
|
59
|
+
customClass = input('');
|
|
60
|
+
baseClasses = 'bg-white shadow-md rounded border-sm border-gray-700 p-1 mat-elevation-z4';
|
|
61
|
+
combinedClasses = computed(() => {
|
|
62
|
+
return `${this.baseClasses} ${this.customClass()}`.trim();
|
|
63
|
+
});
|
|
64
|
+
isTemplate() {
|
|
65
|
+
return !!this.templateContent();
|
|
66
|
+
}
|
|
67
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
68
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.14", type: JvsPopoverPanelComponent, isStandalone: true, selector: "jvs-popover-panel", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, templateContent: { classPropertyName: "templateContent", publicName: "templateContent", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
69
|
+
<div [class]="combinedClasses()">
|
|
70
|
+
<ng-container *ngIf="isTemplate(); else htmlContent">
|
|
71
|
+
<ng-container *ngTemplateOutlet="templateContent(); context: context()"></ng-container>
|
|
72
|
+
</ng-container>
|
|
73
|
+
<ng-template #htmlContent>
|
|
74
|
+
<div [innerHTML]="content()"></div>
|
|
75
|
+
</ng-template>
|
|
76
|
+
</div>
|
|
77
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
78
|
+
}
|
|
79
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverPanelComponent, decorators: [{
|
|
80
|
+
type: Component,
|
|
81
|
+
args: [{ selector: 'jvs-popover-panel', standalone: true, imports: [CommonModule], template: `
|
|
82
|
+
<div [class]="combinedClasses()">
|
|
83
|
+
<ng-container *ngIf="isTemplate(); else htmlContent">
|
|
84
|
+
<ng-container *ngTemplateOutlet="templateContent(); context: context()"></ng-container>
|
|
85
|
+
</ng-container>
|
|
86
|
+
<ng-template #htmlContent>
|
|
87
|
+
<div [innerHTML]="content()"></div>
|
|
88
|
+
</ng-template>
|
|
89
|
+
</div>
|
|
90
|
+
`, styles: [":host{display:block}\n"] }]
|
|
91
|
+
}] });
|
|
92
|
+
|
|
93
|
+
class JvsPopoverService {
|
|
94
|
+
overlay = inject(Overlay);
|
|
95
|
+
overlayPositionBuilder = inject(OverlayPositionBuilder);
|
|
96
|
+
overlayRef = null;
|
|
97
|
+
open(element, content, options = {}) {
|
|
98
|
+
this.close();
|
|
99
|
+
const positionStrategy = this.overlayPositionBuilder
|
|
100
|
+
.flexibleConnectedTo(element)
|
|
101
|
+
.withPositions([
|
|
102
|
+
{
|
|
103
|
+
originX: 'center',
|
|
104
|
+
originY: options.position === 'top' ? 'top' : 'bottom',
|
|
105
|
+
overlayX: 'center',
|
|
106
|
+
overlayY: options.position === 'top' ? 'bottom' : 'top',
|
|
107
|
+
offsetY: options.position === 'top' ? -8 : 8
|
|
108
|
+
}
|
|
109
|
+
]);
|
|
110
|
+
this.overlayRef = this.overlay.create({
|
|
111
|
+
positionStrategy,
|
|
112
|
+
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
113
|
+
hasBackdrop: false
|
|
114
|
+
});
|
|
115
|
+
const portal = new ComponentPortal(JvsPopoverPanelComponent, options.viewContainerRef);
|
|
116
|
+
const containerRef = this.overlayRef.attach(portal);
|
|
117
|
+
if (content instanceof TemplateRef) {
|
|
118
|
+
containerRef.setInput('templateContent', content);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
containerRef.setInput('content', content);
|
|
122
|
+
}
|
|
123
|
+
if (options.customClass) {
|
|
124
|
+
containerRef.setInput('customClass', options.customClass);
|
|
125
|
+
}
|
|
126
|
+
if (options.context) {
|
|
127
|
+
containerRef.setInput('context', options.context);
|
|
128
|
+
}
|
|
129
|
+
return this.overlayRef;
|
|
130
|
+
}
|
|
131
|
+
close() {
|
|
132
|
+
if (this.overlayRef) {
|
|
133
|
+
this.overlayRef.detach();
|
|
134
|
+
this.overlayRef.dispose();
|
|
135
|
+
this.overlayRef = null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
139
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverService, providedIn: 'root' });
|
|
140
|
+
}
|
|
141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverService, decorators: [{
|
|
142
|
+
type: Injectable,
|
|
143
|
+
args: [{
|
|
144
|
+
providedIn: 'root'
|
|
145
|
+
}]
|
|
146
|
+
}] });
|
|
147
|
+
|
|
148
|
+
class JvsPopoverDirective {
|
|
149
|
+
popoverService = inject(JvsPopoverService);
|
|
150
|
+
elementRef = inject(ElementRef);
|
|
151
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
152
|
+
content = input(null, { alias: 'jvsPopover' });
|
|
153
|
+
context = input(null);
|
|
154
|
+
trigger = input('hover');
|
|
155
|
+
position = input('bottom');
|
|
156
|
+
customClass = input('');
|
|
157
|
+
onMouseEnter() {
|
|
158
|
+
if (this.trigger() === 'hover') {
|
|
159
|
+
this.show();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
onMouseLeave() {
|
|
163
|
+
if (this.trigger() === 'hover') {
|
|
164
|
+
this.hide();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
onClick() {
|
|
168
|
+
if (this.trigger() === 'click') {
|
|
169
|
+
this.show();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
onFocus() {
|
|
173
|
+
if (this.trigger() === 'focus') {
|
|
174
|
+
this.show();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
onBlur() {
|
|
178
|
+
if (this.trigger() === 'focus') {
|
|
179
|
+
this.hide();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
ngOnDestroy() {
|
|
183
|
+
this.hide();
|
|
184
|
+
}
|
|
185
|
+
show() {
|
|
186
|
+
const content = this.content();
|
|
187
|
+
if (!content)
|
|
188
|
+
return;
|
|
189
|
+
this.popoverService.open(this.elementRef.nativeElement, content, {
|
|
190
|
+
position: this.position(),
|
|
191
|
+
customClass: this.customClass(),
|
|
192
|
+
viewContainerRef: this.viewContainerRef,
|
|
193
|
+
context: this.context()
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
hide() {
|
|
197
|
+
this.popoverService.close();
|
|
198
|
+
}
|
|
199
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
200
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: JvsPopoverDirective, isStandalone: true, selector: "[jvsPopover]", inputs: { content: { classPropertyName: "content", publicName: "jvsPopover", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "click": "onClick()", "focusin": "onFocus()", "focusout": "onBlur()" } }, ngImport: i0 });
|
|
201
|
+
}
|
|
202
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverDirective, decorators: [{
|
|
203
|
+
type: Directive,
|
|
204
|
+
args: [{
|
|
205
|
+
selector: '[jvsPopover]',
|
|
206
|
+
standalone: true
|
|
207
|
+
}]
|
|
208
|
+
}], propDecorators: { onMouseEnter: [{
|
|
209
|
+
type: HostListener,
|
|
210
|
+
args: ['mouseenter']
|
|
211
|
+
}], onMouseLeave: [{
|
|
212
|
+
type: HostListener,
|
|
213
|
+
args: ['mouseleave']
|
|
214
|
+
}], onClick: [{
|
|
215
|
+
type: HostListener,
|
|
216
|
+
args: ['click']
|
|
217
|
+
}], onFocus: [{
|
|
218
|
+
type: HostListener,
|
|
219
|
+
args: ['focusin']
|
|
220
|
+
}], onBlur: [{
|
|
221
|
+
type: HostListener,
|
|
222
|
+
args: ['focusout']
|
|
223
|
+
}] } });
|
|
224
|
+
|
|
225
|
+
class JvsPopoverListenerDirective {
|
|
226
|
+
popoverService = inject(JvsPopoverService);
|
|
227
|
+
elementRef = inject(ElementRef);
|
|
228
|
+
trigger = input('hover');
|
|
229
|
+
onMouseOver(event) {
|
|
230
|
+
if (this.trigger() !== 'hover')
|
|
231
|
+
return;
|
|
232
|
+
const target = this.findPopoverTarget(event.target);
|
|
233
|
+
if (target) {
|
|
234
|
+
const content = target.getAttribute('data-jvs-popover');
|
|
235
|
+
if (content) {
|
|
236
|
+
this.popoverService.open(target, content, {
|
|
237
|
+
position: target.getAttribute('data-jvs-position') || 'bottom',
|
|
238
|
+
customClass: target.getAttribute('data-jvs-class') || ''
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
onMouseOut(event) {
|
|
244
|
+
if (this.trigger() !== 'hover')
|
|
245
|
+
return;
|
|
246
|
+
this.popoverService.close();
|
|
247
|
+
}
|
|
248
|
+
onClick(event) {
|
|
249
|
+
if (this.trigger() !== 'click')
|
|
250
|
+
return;
|
|
251
|
+
const target = this.findPopoverTarget(event.target);
|
|
252
|
+
if (target) {
|
|
253
|
+
const content = target.getAttribute('data-jvs-popover');
|
|
254
|
+
if (content) {
|
|
255
|
+
this.popoverService.open(target, content, {
|
|
256
|
+
position: target.getAttribute('data-jvs-position') || 'bottom',
|
|
257
|
+
customClass: target.getAttribute('data-jvs-class') || ''
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
findPopoverTarget(el) {
|
|
263
|
+
while (el && el !== this.elementRef.nativeElement) {
|
|
264
|
+
if (el.hasAttribute('data-jvs-popover')) {
|
|
265
|
+
return el;
|
|
266
|
+
}
|
|
267
|
+
el = el.parentElement;
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverListenerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
272
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: JvsPopoverListenerDirective, isStandalone: true, selector: "[jvsPopoverListener]", inputs: { trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseover": "onMouseOver($event)", "mouseout": "onMouseOut($event)", "click": "onClick($event)" } }, ngImport: i0 });
|
|
273
|
+
}
|
|
274
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsPopoverListenerDirective, decorators: [{
|
|
275
|
+
type: Directive,
|
|
276
|
+
args: [{
|
|
277
|
+
selector: '[jvsPopoverListener]',
|
|
278
|
+
standalone: true
|
|
279
|
+
}]
|
|
280
|
+
}], propDecorators: { onMouseOver: [{
|
|
281
|
+
type: HostListener,
|
|
282
|
+
args: ['mouseover', ['$event']]
|
|
283
|
+
}], onMouseOut: [{
|
|
284
|
+
type: HostListener,
|
|
285
|
+
args: ['mouseout', ['$event']]
|
|
286
|
+
}], onClick: [{
|
|
287
|
+
type: HostListener,
|
|
288
|
+
args: ['click', ['$event']]
|
|
289
|
+
}] } });
|
|
290
|
+
|
|
291
|
+
class JvsAutocompleteDirective {
|
|
292
|
+
destroyRef = inject(DestroyRef);
|
|
293
|
+
ngControl = inject(NgControl, { optional: true });
|
|
294
|
+
focus$ = new Subject();
|
|
295
|
+
// Signal-based Inputs
|
|
296
|
+
data = input(null);
|
|
297
|
+
fields = input('');
|
|
298
|
+
typeReq = input('');
|
|
299
|
+
queryService = input(null);
|
|
300
|
+
minLength = input(3);
|
|
301
|
+
dataExtra = input({});
|
|
302
|
+
anonimo = input(false);
|
|
303
|
+
debounce = input(300);
|
|
304
|
+
// Modern Outputs
|
|
305
|
+
filtered = output();
|
|
306
|
+
loading = output();
|
|
307
|
+
onFocus() {
|
|
308
|
+
this.focus$.next();
|
|
309
|
+
}
|
|
310
|
+
ngOnInit() {
|
|
311
|
+
const control = this.ngControl;
|
|
312
|
+
if (!control || !control.valueChanges) {
|
|
313
|
+
console.warn('JvsAutocompleteDirective: No se encontró ngControl o valueChanges. Asegúrate de que el input tenga un formControl o formControlName.');
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// Si es data local, bajamos el debounce por defecto a 0 si no se ha especificado
|
|
317
|
+
const isLocal = this.data() && !this.typeReq();
|
|
318
|
+
const actualDebounce = (isLocal && this.debounce() === 300) ? 0 : this.debounce();
|
|
319
|
+
merge(control.valueChanges.pipe(debounceTime(actualDebounce)), this.focus$).pipe(takeUntilDestroyed(this.destroyRef), startWith(control.value), distinctUntilChanged(), tap(() => {
|
|
320
|
+
if (this.typeReq())
|
|
321
|
+
this.loading.emit(true);
|
|
322
|
+
}), switchMap(() => {
|
|
323
|
+
const value = control.value;
|
|
324
|
+
// Si el valor es un objeto (proviene de seleccionar una opción), no volvemos a filtrar
|
|
325
|
+
if (typeof value === 'object' && value !== null) {
|
|
326
|
+
if (this.typeReq())
|
|
327
|
+
this.loading.emit(false);
|
|
328
|
+
return of(null);
|
|
329
|
+
}
|
|
330
|
+
if (this.typeReq() && this.queryService()) {
|
|
331
|
+
return this.fetchApi(value?.toString() || '');
|
|
332
|
+
}
|
|
333
|
+
else if (this.data()) {
|
|
334
|
+
const res = this.filterLocal(value?.toString() || '');
|
|
335
|
+
return of(res);
|
|
336
|
+
}
|
|
337
|
+
if (this.typeReq())
|
|
338
|
+
this.loading.emit(false);
|
|
339
|
+
return of([]);
|
|
340
|
+
})).subscribe((result) => {
|
|
341
|
+
if (result !== null) {
|
|
342
|
+
this.filtered.emit(result);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
filterLocal(value) {
|
|
347
|
+
const data = this.data();
|
|
348
|
+
if (!value)
|
|
349
|
+
return data || [];
|
|
350
|
+
const search = value.toLowerCase();
|
|
351
|
+
const rawFields = this.fields();
|
|
352
|
+
const fields = Array.isArray(rawFields) ? rawFields : [rawFields];
|
|
353
|
+
return (data || []).filter(item => {
|
|
354
|
+
return fields.some(field => {
|
|
355
|
+
const val = item[field];
|
|
356
|
+
return val && val.toString().toLowerCase().includes(search);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
fetchApi(value) {
|
|
361
|
+
const typeReq = this.typeReq();
|
|
362
|
+
const queryService = this.queryService();
|
|
363
|
+
if (!value || value.length < this.minLength()) {
|
|
364
|
+
this.loading.emit(false);
|
|
365
|
+
return of([]);
|
|
366
|
+
}
|
|
367
|
+
return queryService.getDataMethod('GET', typeReq, {
|
|
368
|
+
...this.dataExtra(),
|
|
369
|
+
txtBuscar: value
|
|
370
|
+
}, this.anonimo()).pipe(map((res) => res[typeReq] ?? []), finalize(() => this.loading.emit(false)));
|
|
371
|
+
}
|
|
372
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsAutocompleteDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
373
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: JvsAutocompleteDirective, isStandalone: true, selector: "[jvsAutocomplete]", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null }, typeReq: { classPropertyName: "typeReq", publicName: "typeReq", isSignal: true, isRequired: false, transformFunction: null }, queryService: { classPropertyName: "queryService", publicName: "queryService", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, dataExtra: { classPropertyName: "dataExtra", publicName: "dataExtra", isSignal: true, isRequired: false, transformFunction: null }, anonimo: { classPropertyName: "anonimo", publicName: "anonimo", isSignal: true, isRequired: false, transformFunction: null }, debounce: { classPropertyName: "debounce", publicName: "debounce", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filtered: "filtered", loading: "loading" }, host: { listeners: { "focus": "onFocus()" } }, ngImport: i0 });
|
|
374
|
+
}
|
|
375
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsAutocompleteDirective, decorators: [{
|
|
376
|
+
type: Directive,
|
|
377
|
+
args: [{
|
|
378
|
+
selector: '[jvsAutocomplete]',
|
|
379
|
+
standalone: true
|
|
380
|
+
}]
|
|
381
|
+
}], propDecorators: { onFocus: [{
|
|
382
|
+
type: HostListener,
|
|
383
|
+
args: ['focus']
|
|
384
|
+
}] } });
|
|
385
|
+
|
|
386
|
+
class AutoSelectFirstDirective {
|
|
387
|
+
ngControl = inject(NgControl, { optional: true });
|
|
388
|
+
fcName = inject(FormControlName, { optional: true });
|
|
389
|
+
toastr = inject(ToastrService, { optional: true });
|
|
390
|
+
// Inputs using Signals
|
|
391
|
+
options = input(null, { alias: 'jvsAutoSelectFirst' });
|
|
392
|
+
jvsIdKey = input(null);
|
|
393
|
+
jvsEmptyMsg = input('Lista sin elementos');
|
|
394
|
+
onAutoSelect = output();
|
|
395
|
+
constructor() {
|
|
396
|
+
effect(() => {
|
|
397
|
+
const currentOptions = this.options();
|
|
398
|
+
const idKey = this.jvsIdKey();
|
|
399
|
+
const emptyMsg = this.jvsEmptyMsg();
|
|
400
|
+
if (currentOptions === null)
|
|
401
|
+
return;
|
|
402
|
+
const optionsArray = Array.isArray(currentOptions) ? currentOptions : [];
|
|
403
|
+
if (optionsArray.length > 0) {
|
|
404
|
+
untracked(() => {
|
|
405
|
+
const control = this.ngControl?.control;
|
|
406
|
+
const currentValue = control?.value;
|
|
407
|
+
// Only autoselect if empty
|
|
408
|
+
if (control && (currentValue === null || currentValue === undefined || currentValue === '')) {
|
|
409
|
+
const firstItem = optionsArray[0];
|
|
410
|
+
let valueToSet;
|
|
411
|
+
// Resolve key
|
|
412
|
+
let effectiveKey = idKey;
|
|
413
|
+
// Default to formControlName if not provided
|
|
414
|
+
if (!effectiveKey && this.fcName) {
|
|
415
|
+
effectiveKey = this.fcName.name;
|
|
416
|
+
}
|
|
417
|
+
if (effectiveKey) {
|
|
418
|
+
if (Array.isArray(effectiveKey)) {
|
|
419
|
+
// Composite key: build an object with the specified keys
|
|
420
|
+
valueToSet = {};
|
|
421
|
+
effectiveKey.forEach(key => {
|
|
422
|
+
valueToSet[key] = firstItem[key];
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
valueToSet = firstItem[effectiveKey];
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
// Use whole item if no key resolution possible
|
|
431
|
+
valueToSet = firstItem;
|
|
432
|
+
}
|
|
433
|
+
control.setValue(valueToSet);
|
|
434
|
+
this.onAutoSelect.emit(firstItem);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
else if (emptyMsg && this.toastr) {
|
|
439
|
+
this.toastr.warning(emptyMsg, 'Filtrado');
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutoSelectFirstDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
444
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: AutoSelectFirstDirective, isStandalone: true, selector: "[jvsAutoSelectFirst]", inputs: { options: { classPropertyName: "options", publicName: "jvsAutoSelectFirst", isSignal: true, isRequired: false, transformFunction: null }, jvsIdKey: { classPropertyName: "jvsIdKey", publicName: "jvsIdKey", isSignal: true, isRequired: false, transformFunction: null }, jvsEmptyMsg: { classPropertyName: "jvsEmptyMsg", publicName: "jvsEmptyMsg", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAutoSelect: "onAutoSelect" }, ngImport: i0 });
|
|
445
|
+
}
|
|
446
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AutoSelectFirstDirective, decorators: [{
|
|
447
|
+
type: Directive,
|
|
448
|
+
args: [{
|
|
449
|
+
selector: '[jvsAutoSelectFirst]',
|
|
450
|
+
standalone: true
|
|
451
|
+
}]
|
|
452
|
+
}], ctorParameters: () => [] });
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Generated bundle index. Do not edit.
|
|
456
|
+
*/
|
|
457
|
+
|
|
458
|
+
export { AutoSelectFirstDirective, AutocompleteMatchValidatorDirective, JvsAutocompleteDirective, JvsPopoverDirective, JvsPopoverListenerDirective, JvsPopoverPanelComponent, JvsPopoverService };
|
|
459
|
+
//# sourceMappingURL=jvsoft-utils-directives.mjs.map
|