@jvsoft/mat-form-controls 1.0.0-alpha.13
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 +184 -0
- package/base/index.d.ts +5 -0
- package/base/jvs-mat-form-control-base.d.ts +51 -0
- package/base/public-api.d.ts +1 -0
- package/fesm2022/jvsoft-mat-form-controls-base.mjs +145 -0
- package/fesm2022/jvsoft-mat-form-controls-base.mjs.map +1 -0
- package/fesm2022/jvsoft-mat-form-controls-jvs-autocomplete.mjs +101 -0
- package/fesm2022/jvsoft-mat-form-controls-jvs-autocomplete.mjs.map +1 -0
- package/fesm2022/jvsoft-mat-form-controls-jvs-file-upload.mjs +624 -0
- package/fesm2022/jvsoft-mat-form-controls-jvs-file-upload.mjs.map +1 -0
- package/fesm2022/jvsoft-mat-form-controls.mjs +145 -0
- package/fesm2022/jvsoft-mat-form-controls.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/jvs-autocomplete/index.d.ts +5 -0
- package/jvs-autocomplete/jvs-autocomplete.component.d.ts +26 -0
- package/jvs-autocomplete/jvs-autocomplete.component.scss +58 -0
- package/jvs-autocomplete/public-api.d.ts +1 -0
- package/jvs-file-upload/README.md +613 -0
- package/jvs-file-upload/index.d.ts +5 -0
- package/jvs-file-upload/jvs-file-upload-item/jvs-file-upload-item.component.d.ts +29 -0
- package/jvs-file-upload/jvs-file-upload-item/jvs-file-upload-item.component.scss +118 -0
- package/jvs-file-upload/jvs-file-upload.component.d.ts +140 -0
- package/jvs-file-upload/jvs-file-upload.component.scss +163 -0
- package/jvs-file-upload/jvs-file-upload.directive.d.ts +42 -0
- package/jvs-file-upload/jvs-file-upload.interfaces.d.ts +77 -0
- package/jvs-file-upload/public-api.d.ts +4 -0
- package/package.json +39 -0
- package/public-api.d.ts +1 -0
- package/src/lib/mat-form-controls/mat-form-controls.component.css +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jvsoft-mat-form-controls-jvs-file-upload.mjs","sources":["../../../projects/mat-form-controls/jvs-file-upload/jvs-file-upload.directive.ts","../../../projects/mat-form-controls/jvs-file-upload/jvs-file-upload-item/jvs-file-upload-item.component.ts","../../../projects/mat-form-controls/jvs-file-upload/jvs-file-upload-item/jvs-file-upload-item.component.html","../../../projects/mat-form-controls/jvs-file-upload/jvs-file-upload.component.ts","../../../projects/mat-form-controls/jvs-file-upload/jvs-file-upload.component.html","../../../projects/mat-form-controls/jvs-file-upload/jvsoft-mat-form-controls-jvs-file-upload.ts"],"sourcesContent":["import {\n Directive,\n EventEmitter,\n HostBinding,\n HostListener,\n input,\n Output,\n} from '@angular/core';\nimport { mensajeToast } from '@jvsoft/utils';\nimport { JvsFileFilterParams } from './jvs-file-upload.interfaces';\n\n/**\n * Directiva que convierte cualquier elemento en una zona de drag-and-drop\n * para subida de archivos.\n *\n * @example\n * <div jvsFileUpload [controlFile]=\"inputRef\" (filesChange)=\"onFiles($event)\">\n */\n@Directive({\n standalone: true,\n selector: '[jvsFileUpload]',\n})\nexport class JvsFileUploadDirective {\n\n // ── Inputs ──────────────────────────────────────────────────────────────\n fondoInicial = input('');\n fondoDragOver = input('#e5e7eb');\n controlFile = input.required<HTMLInputElement>();\n\n extensionesPermitidas = input<string[]>([]);\n parteDeNombre = input<string[]>([]);\n parteDeNombreExclusivo = input<string[]>([]);\n tamanoMaximoMB = input<number | null>(null);\n isDisabled = input<boolean>(false);\n\n // ── Outputs ─────────────────────────────────────────────────────────────\n @Output() filesChange = new EventEmitter<File[]>();\n @Output() filesInvalidChange = new EventEmitter<File[]>();\n\n // ── Host bindings ────────────────────────────────────────────────────────\n @HostBinding('style.background') background = '';\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n @HostListener('dragover', ['$event'])\n onDragOver(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n if (!this.isDisabled()) {\n this.background = this.fondoDragOver();\n }\n }\n\n @HostListener('dragleave', ['$event'])\n onDragLeave(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n if (!this.isDisabled()) {\n this.background = this.fondoInicial();\n }\n }\n\n @HostListener('drop', ['$event'])\n onDrop(evt: DragEvent): void {\n evt.preventDefault();\n evt.stopPropagation();\n if (this.isDisabled()) return;\n\n this.background = this.fondoInicial();\n const files = Array.from(evt.dataTransfer?.files ?? []);\n const result = JvsFileUploadDirective.filtrarArchivos(files, {\n extensionesPermitidas: this.extensionesPermitidas(),\n parteDeNombre: this.parteDeNombre(),\n parteDeNombreExclusivo: this.parteDeNombreExclusivo(),\n tamanoMaximoMB: this.tamanoMaximoMB(),\n }, this.controlFile().multiple);\n\n this.filesChange.emit(result.valid);\n this.filesInvalidChange.emit(result.invalid);\n }\n\n // ── Static helpers ───────────────────────────────────────────────────────\n\n /**\n * Filtra un array de archivos según extensión, partes de nombre y tamaño máximo.\n *\n * Lógica:\n * 1. Si el archivo excede `tamanoMaximoMB` → inválido.\n * 2. Si el nombre contiene algún valor de `parteDeNombreExclusivo` → válido sin checar extensión.\n * 3. Si la extensión está en `extensionesPermitidas` Y el nombre contiene TODOS los valores\n * de `parteDeNombre` → válido.\n * 4. En cualquier otro caso → inválido.\n */\n static filtrarArchivos(\n files: File[],\n params: JvsFileFilterParams,\n multiple = true,\n ): { valid: File[]; invalid: File[] } {\n const validFiles: File[] = [];\n const invalidFiles: File[] = [];\n\n const getExt = (nombre: string): string => {\n const idx = nombre.lastIndexOf('.');\n return idx !== -1 ? nombre.slice(idx + 1).toLowerCase() : '';\n };\n\n for (const file of files) {\n const ext = getExt(file.name);\n const tamanoMB = file.size / (1024 * 1024);\n\n // 1. Validar tamaño\n if (params.tamanoMaximoMB && tamanoMB > params.tamanoMaximoMB) {\n mensajeToast('error', 'Archivo no válido',\n `El archivo <strong>${file.name}</strong> supera el tamaño máximo permitido (${params.tamanoMaximoMB} MB).`);\n invalidFiles.push(file);\n continue;\n }\n\n // 2. Nombre exclusivo (bypass de extensión)\n if (params.parteDeNombreExclusivo.length > 0 &&\n params.parteDeNombreExclusivo.some(p => file.name.includes(p))) {\n validFiles.push(file);\n if (!multiple) break;\n continue;\n }\n\n // 3. Extensión permitida + partes de nombre requeridas\n const extensionOk = params.extensionesPermitidas.length === 0 ||\n params.extensionesPermitidas.includes(ext);\n const nombreOk = params.parteDeNombre.every(p => file.name.includes(p));\n\n if (extensionOk && nombreOk) {\n validFiles.push(file);\n if (!multiple) break;\n } else {\n mensajeToast('error', 'Archivo no válido',\n `El archivo <strong>${file.name}</strong> no es válido.`);\n invalidFiles.push(file);\n }\n }\n\n return { valid: validFiles, invalid: invalidFiles };\n }\n}\n","import {\n Component,\n computed,\n input,\n output,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatRippleModule } from '@angular/material/core';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { convertirBytes } from '@jvsoft/utils';\nimport { JvsFileEntry, JvsArchivoServidor } from '../jvs-file-upload.interfaces';\n\n/**\n * Componente de ítem individual de la lista de archivos en modo `temporal`.\n * Muestra nombre, tamaño, barra de progreso y acciones (descargar, firmar, eliminar).\n */\n@Component({\n selector: 'jvs-file-upload-item',\n standalone: true,\n imports: [\n NgClass,\n MatIconModule,\n MatProgressBarModule,\n MatRippleModule,\n MatTooltipModule,\n ],\n templateUrl: './jvs-file-upload-item.component.html',\n styleUrl: './jvs-file-upload-item.component.scss',\n})\nexport class JvsFileUploadItemComponent {\n\n // ── Inputs ───────────────────────────────────────────────────────────────\n file = input.required<JvsFileEntry>();\n permitirEliminar = input<boolean>(true);\n isDisabled = input<boolean>(false);\n\n // ── Outputs ──────────────────────────────────────────────────────────────\n eliminar = output<JvsFileEntry>();\n descargar = output<JvsFileEntry>();\n firmar = output<JvsArchivoServidor>();\n\n // ── Computed ──────────────────────────────────────────────────────────────\n\n readonly extension = computed(() => {\n const f = this.file();\n return f.servFile?.extension ?? f.file?.name?.split('.').pop()?.toLowerCase() ?? '';\n });\n\n readonly nombreMostrado = computed(() => {\n const f = this.file();\n return f.servFile?.nombre ?? f.file?.name ?? '';\n });\n\n readonly estadoProgreso = computed<'cargando' | 'incompleto' | 'completado' | ''>(() => {\n const f = this.file();\n if (f.progress === 100 && f.servFile) return 'completado';\n if (f.progress === 100 && !f.servFile) return 'incompleto';\n if (f.progress > 0 && f.progress < 100) return 'cargando';\n return '';\n });\n\n readonly modoProgreso = computed<'indeterminate' | 'determinate'>(() => {\n const f = this.file();\n return (f.progress === 100 && !f.servFile) ? 'indeterminate' : 'determinate';\n });\n\n readonly mostrarBotonDescargar = computed(() => {\n const sf = this.file().servFile;\n // key → DB-stored file; path → freshly uploaded (backend returns plain path string); cArchivoData → PDF generation metadata\n return !!sf?.key || !!sf?.path || !!sf?.cArchivoData;\n });\n\n readonly mostrarBotonFirmar = computed(() =>\n !!this.file().servFile && !this.isDisabled()\n );\n\n readonly mostrarBotonEliminar = computed(() =>\n this.permitirEliminar() && !this.isDisabled()\n );\n\n readonly tamanioArchivo = computed(() => {\n const f = this.file();\n const file = f.file;\n if (!file) return 0;\n return (file as File).size ?? 0;\n });\n\n // ── Utilidades ────────────────────────────────────────────────────────────\n\n readonly convertirBytes = convertirBytes;\n\n onEliminar(): void {\n this.eliminar.emit(this.file());\n }\n\n onDescargar(): void {\n this.descargar.emit(this.file());\n }\n\n onFirmar(): void {\n if (this.file().servFile) {\n this.firmar.emit(this.file().servFile!);\n }\n }\n}\n","<div class=\"jvs-file-item\">\n\n <!-- Ícono por tipo de archivo -->\n <div class=\"jvs-file-item__icon\">\n @switch (extension()) {\n @case ('pdf') {\n <mat-icon class=\"icon-pdf\" svgIcon=\"fa5FilePdf\" />\n }\n @case ('xls') {\n <mat-icon class=\"icon-excel\" svgIcon=\"fa5FileExcel\" />\n }\n @case ('xlsx') {\n <mat-icon class=\"icon-excel\" svgIcon=\"fa5FileExcel\" />\n }\n @case ('doc') {\n <mat-icon class=\"icon-word\" svgIcon=\"fa5FileWord\" />\n }\n @case ('docx') {\n <mat-icon class=\"icon-word\" svgIcon=\"fa5FileWord\" />\n }\n @case ('jpg') {\n <mat-icon class=\"icon-image\" svgIcon=\"roundImage\" />\n }\n @case ('jpeg') {\n <mat-icon class=\"icon-image\" svgIcon=\"roundImage\" />\n }\n @case ('png') {\n <mat-icon class=\"icon-image\" svgIcon=\"roundImage\" />\n }\n @default {\n <mat-icon svgIcon=\"fa5File\" />\n }\n }\n </div>\n\n <!-- Información del archivo -->\n <div class=\"jvs-file-item__info\">\n <p class=\"jvs-file-item__name\" [title]=\"nombreMostrado()\">\n {{ nombreMostrado() }}\n </p>\n\n @if (file().servFile) {\n <p class=\"jvs-file-item__status jvs-file-item__status--server\">En servidor</p>\n } @else {\n <p class=\"jvs-file-item__status\">\n {{ convertirBytes(tamanioArchivo()) }}\n </p>\n }\n\n @if (file().errorSubida) {\n <p class=\"jvs-file-item__status jvs-file-item__status--error\">Error al subir</p>\n }\n\n <mat-progress-bar\n [value]=\"file().progress\"\n [mode]=\"modoProgreso()\"\n [class]=\"estadoProgreso()\"\n />\n </div>\n\n <!-- Acciones -->\n <div class=\"jvs-file-item__actions\">\n\n @if (mostrarBotonDescargar()) {\n <button\n type=\"button\"\n class=\"jvs-file-item__btn jvs-file-item__btn--download\"\n matRipple\n (click)=\"onDescargar()\"\n matTooltip=\"Descargar\"\n >\n <mat-icon svgIcon=\"roundDownload\" />\n </button>\n }\n\n @if (mostrarBotonFirmar()) {\n <button\n type=\"button\"\n class=\"jvs-file-item__btn jvs-file-item__btn--sign\"\n matRipple\n (click)=\"onFirmar()\"\n matTooltip=\"Firmar\"\n >\n <mat-icon svgIcon=\"roundDraw\" />\n </button>\n }\n\n @if (mostrarBotonEliminar()) {\n <button\n type=\"button\"\n class=\"jvs-file-item__btn jvs-file-item__btn--delete\"\n matRipple\n (click)=\"onEliminar()\"\n matTooltip=\"Eliminar\"\n >\n <mat-icon svgIcon=\"roundDelete\" />\n </button>\n }\n\n </div>\n</div>\n","import {\n Component,\n computed,\n forwardRef,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { NgClass, NgTemplateOutlet } from '@angular/common';\nimport {\n ControlValueAccessor,\n FormControl,\n NG_VALIDATORS,\n NG_VALUE_ACCESSOR,\n ReactiveFormsModule,\n ValidationErrors,\n Validator,\n} from '@angular/forms';\nimport { formatDate } from '@angular/common';\nimport { HttpEventType } from '@angular/common/http';\nimport { MatDividerModule } from '@angular/material/divider';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatListModule } from '@angular/material/list';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { lastValueFrom } from 'rxjs';\nimport { catchError, map, of } from 'rxjs';\nimport { mensajeConfirmacion, mensajeToast } from '@jvsoft/utils';\n\nimport {\n JvsArchivoServidor,\n JvsFileEntry,\n JvsRemoveFn,\n JvsUploadFn,\n} from './jvs-file-upload.interfaces';\nimport { JvsFileUploadDirective } from './jvs-file-upload.directive';\nimport { JvsFileUploadItemComponent } from './jvs-file-upload-item/jvs-file-upload-item.component';\n\n/**\n * Componente de subida de archivos reutilizable.\n *\n * Implementa `ControlValueAccessor` para integrarse con formularios reactivos y\n * template-driven. El valor del control es `JvsArchivoServidor[]`.\n *\n * ## Modos de operación\n *\n * - **`temporal = false`** (defecto): los archivos se seleccionan localmente y se\n * envían todos juntos llamando a `uploadFilesPreForm()` antes de guardar el form.\n *\n * - **`temporal = true`**: cada archivo se sube de forma inmediata al seleccionarse,\n * mostrando barra de progreso individual. El valor del control se actualiza en\n * tiempo real con los archivos ya subidos.\n *\n * ## Ejemplo de uso\n *\n * ```html\n * <jvs-file-upload\n * [temporal]=\"true\"\n * [extensionesPermitidas]=\"['pdf','docx']\"\n * [tamanoMaximoMB]=\"10\"\n * [uploadFn]=\"filesService.upload.bind(filesService)\"\n * [removeFn]=\"filesService.remove.bind(filesService)\"\n * (archivoDescarga)=\"onDescargar($event)\"\n * (firmarArchivo)=\"onFirmar($event)\"\n * formControlName=\"archivos\"\n * />\n * ```\n */\n@Component({\n selector: 'jvs-file-upload',\n standalone: true,\n imports: [\n NgClass,\n NgTemplateOutlet,\n ReactiveFormsModule,\n MatDividerModule,\n MatIconModule,\n MatListModule,\n MatTooltipModule,\n JvsFileUploadDirective,\n JvsFileUploadItemComponent,\n ],\n templateUrl: './jvs-file-upload.component.html',\n styleUrl: './jvs-file-upload.component.scss',\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => JvsFileUploadComponent),\n multi: true,\n },\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => JvsFileUploadComponent),\n multi: true,\n },\n ],\n})\nexport class JvsFileUploadComponent implements ControlValueAccessor, Validator {\n\n // ── Inputs ───────────────────────────────────────────────────────────────\n\n /** Activa subida inmediata de cada archivo al seleccionarlo. */\n temporal = input<boolean>(false);\n\n /** Habilita la opción de eliminar archivos. */\n permitirEliminar = input<boolean>(true);\n\n /** Solo muestra la lista; oculta la zona de drop. */\n readonly = input<boolean>(false);\n\n /** Permite seleccionar múltiples archivos. */\n multiple = input<boolean>(true);\n\n /** Extensiones de archivo permitidas (sin punto, en minúsculas). */\n extensionesPermitidas = input<string[]>([]);\n\n /**\n * El nombre del archivo debe contener TODOS estos fragmentos.\n * Solo aplica cuando `parteDeNombreExclusivo` está vacío.\n */\n parteDeNombre = input<string[]>([]);\n\n /**\n * Si el nombre del archivo contiene ALGUNO de estos fragmentos,\n * se acepta sin verificar extensión.\n */\n parteDeNombreExclusivo = input<string[]>([]);\n\n /** Tamaño máximo en MB. `null` = sin límite. */\n tamanoMaximoMB = input<number | null>(null);\n\n /** Nombre fijo que se envía al servidor al subir. */\n nombreArchivoFijo = input<string | null>(null);\n\n /**\n * Carpeta destino en el servidor.\n * Defecto: `temp/YYYY-MM-DD_HH`\n */\n carpetaSubida = input<string | null>(null);\n\n /** Disk de Laravel para el almacenamiento. `null` = usar default del servidor. */\n diskSubida = input<string | null>(null);\n\n /**\n * Función que recibe un `FormData` y devuelve un `Observable<HttpEvent<any>>`.\n * Obligatoria en modo `temporal = true` o al llamar `uploadFilesPreForm()`.\n *\n * @example\n * [uploadFn]=\"filesService.upload.bind(filesService)\"\n */\n uploadFn = input<JvsUploadFn | null>(null);\n\n /**\n * Función que elimina un archivo del servidor.\n * Recibe el path o parámetros necesarios y devuelve una Promise.\n *\n * @example\n * [removeFn]=\"filesService.remove.bind(filesService)\"\n */\n removeFn = input<JvsRemoveFn | null>(null);\n\n /** Clase CSS extra para el contenedor de la lista (modo temporal). */\n cssContenedorAgregados = input<string>('');\n\n /** Clase CSS extra para el contenedor de lista de archivos válidos/inválidos. */\n cssContenedorAgregadosLista = input<string>('');\n\n // ── Outputs ──────────────────────────────────────────────────────────────\n\n /** Emite la lista de archivos restante tras eliminar un elemento. */\n resultadoEliminado = output<JvsArchivoServidor[]>();\n\n /**\n * Emite el archivo del servidor cuando el usuario hace click en \"Descargar\".\n * El componente padre es responsable de ejecutar la descarga real.\n */\n archivoDescarga = output<JvsFileEntry>();\n\n /**\n * Emite el archivo del servidor cuando el usuario hace click en \"Firmar\".\n * El componente padre es responsable de abrir el diálogo de firma.\n */\n firmarArchivo = output<JvsArchivoServidor>();\n\n // ── Estado interno (signals) ──────────────────────────────────────────────\n\n readonly fileList = signal<JvsFileEntry[]>([]);\n readonly invalidFiles = signal<File[]>([]);\n readonly isDisabled = signal<boolean>(false);\n\n // ── Computed ──────────────────────────────────────────────────────────────\n\n /** Verdadero si no hay archivos en la lista. */\n readonly isEmpty = computed(() => this.fileList().length === 0);\n\n /** Extensiones normalizadas a minúsculas. */\n readonly extensionesNormalizadas = computed(() =>\n this.extensionesPermitidas().map(e => e.toLowerCase())\n );\n\n /** Texto informativo de extensiones permitidas. */\n readonly textoExtensiones = computed(() => {\n const exc = this.parteDeNombreExclusivo();\n const ext = this.extensionesNormalizadas();\n if (exc.length > 0) return `El nombre debe contener: ${exc.join(', ').toUpperCase()}`;\n if (ext.length > 0) return `Permitidos: ${ext.join(', ').toUpperCase()}`;\n return 'Todos los archivos';\n });\n\n // ── CVA callbacks ─────────────────────────────────────────────────────────\n private onChange: (value: any) => void = () => {};\n private onTouched: () => void = () => {};\n private _onValidatorChange: () => void = () => {};\n\n // ── ControlValueAccessor ──────────────────────────────────────────────────\n\n writeValue(value: JvsArchivoServidor[] | null): void {\n this.fileList.set([]);\n if (!value || !Array.isArray(value)) return;\n\n const entries: JvsFileEntry[] = value.map(f => ({\n file: { name: f.nombre ?? '' },\n desdeServidor: true,\n inProgress: false,\n progress: 100,\n servFile: f,\n }));\n this.fileList.set(entries);\n }\n\n registerOnChange(fn: (v: any) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this.isDisabled.set(isDisabled); }\n registerOnValidatorChange(fn: () => void): void { this._onValidatorChange = fn; }\n\n // ── Validator ─────────────────────────────────────────────────────────────\n\n // @ts-ignore\n validate(_: FormControl): ValidationErrors | null {\n if (this.fileList().some(f => f.inProgress)) return { uploadEnProgreso: true };\n if (this.fileList().some(f => f.errorSubida)) return { errorSubida: true };\n return null;\n }\n\n // ── Manejo de selección de archivos ───────────────────────────────────────\n\n /** Llamado desde el template al cambiar el input[type=file]. */\n onUploadChange(files: FileList | null): void {\n if (!files) return;\n const fileArray = Array.from(files);\n const filtered = JvsFileUploadDirective.filtrarArchivos(fileArray, {\n extensionesPermitidas: this.extensionesNormalizadas(),\n parteDeNombre: this.parteDeNombre(),\n parteDeNombreExclusivo: this.parteDeNombreExclusivo(),\n tamanoMaximoMB: this.tamanoMaximoMB(),\n }, this.multiple());\n\n this.onFilesChange(filtered.valid);\n this.invalidFiles.set(filtered.invalid);\n }\n\n /** Llamado desde la directiva drag-and-drop al soltar archivos válidos. */\n onFilesChange(newFiles: File[]): void {\n if (!this.multiple() && (newFiles.length + this.fileList().length) > 1) {\n mensajeToast('error', 'Error', 'Solo se permite un archivo.');\n return;\n }\n\n if (this.temporal()) {\n const nuevos: JvsFileEntry[] = newFiles\n .filter(f => !this.fileList().some(e => e.file?.name === f.name))\n .map(f => ({\n file: f,\n desdeServidor: false,\n inProgress: false,\n progress: 0,\n servFile: undefined,\n }));\n\n this.fileList.update(list => [...list, ...nuevos]);\n // Subida inmediata en modo temporal\n nuevos.forEach(entry => this.uploadFileTemporal(entry));\n } else {\n const entries: JvsFileEntry[] = newFiles.map(f => ({\n file: f,\n desdeServidor: false,\n inProgress: false,\n progress: 0,\n }));\n // Keep server-loaded entries, replace only locally selected ones\n this.fileList.update(list => [\n ...list.filter(f => f.desdeServidor),\n ...entries,\n ]);\n }\n\n this._notifyChange();\n }\n\n // ── Subida de archivos ────────────────────────────────────────────────────\n\n /**\n * Sube todos los archivos pendientes (sin `servFile`) al servidor.\n * Para usar antes del envío del formulario en modo `temporal = false`.\n *\n * @param carpeta Carpeta destino en el servidor (opcional, sobreescribe el input).\n * @param anonimo `true` para subir sin autenticación.\n * @param disk Disk de almacenamiento (opcional, sobreescribe el input).\n * @returns Promise con la lista de `JvsArchivoServidor[]` subidos correctamente.\n */\n async uploadFilesPreForm(\n carpeta?: string,\n anonimo = false,\n disk?: string,\n ): Promise<JvsArchivoServidor[]> {\n const uploadFn = this.uploadFn();\n if (!uploadFn) {\n console.warn('[JvsFileUpload] uploadFn no proporcionado. No se subirán archivos.');\n return this.fileList()\n .filter(f => f.servFile)\n .map(f => f.servFile!);\n }\n\n const carpetaFinal = carpeta ?? this.carpetaSubida() ??\n 'temp/' + formatDate(new Date(), 'yyyy-MM-dd_HH', 'en');\n const diskFinal = disk ?? this.diskSubida();\n\n const pendientes = this.fileList().filter(f => !f.servFile);\n\n const promises = pendientes.map(entry =>\n this._subirEntrada(entry, uploadFn, carpetaFinal, anonimo, diskFinal)\n );\n\n await Promise.allSettled(promises);\n\n const todosBien = pendientes.every(p => !p.errorSubida);\n if (!todosBien) {\n const hayMas = this.fileList().length > 1;\n if (hayMas) {\n const result = await mensajeConfirmacion(\n 'warning',\n 'Archivos no cargados',\n 'Algunos archivos no se cargaron. ¿Desea continuar de todos modos?',\n );\n if (!result.isConfirmed) return [];\n } else {\n return [];\n }\n }\n\n return this.fileList()\n .filter(f => f.servFile)\n .map(f => f.servFile!);\n }\n\n /** Subida automática individual (modo temporal). */\n private uploadFileTemporal(entry: JvsFileEntry): void {\n const uploadFn = this.uploadFn();\n if (!uploadFn) {\n console.warn('[JvsFileUpload] uploadFn no proporcionado. No se puede subir en modo temporal.');\n return;\n }\n\n const carpeta = this.carpetaSubida() ??\n 'temp/' + formatDate(new Date(), 'yyyy-MM-dd_HH', 'en');\n const disk = this.diskSubida();\n\n this._subirEntrada(entry, uploadFn, carpeta, false, disk).catch(() => {});\n }\n\n /** Lógica central de subida de una entrada. */\n private _subirEntrada(\n entry: JvsFileEntry,\n uploadFn: JvsUploadFn,\n carpeta: string,\n anonimo: boolean,\n disk: string | null,\n ): Promise<void> {\n const formData = new FormData();\n if (this.nombreArchivoFijo()) {\n formData.append('nombreArchivo', this.nombreArchivoFijo()!);\n }\n formData.append('archivo', entry.file as File);\n formData.append('carpeta', carpeta);\n if (disk) formData.append('disk', disk);\n\n this.fileList.update(list =>\n list.map(f => f === entry ? { ...f, inProgress: true } : f)\n );\n this._onValidatorChange();\n\n return lastValueFrom(\n uploadFn(formData, anonimo).pipe(\n map(event => {\n switch (event.type) {\n case HttpEventType.UploadProgress: {\n const loaded = (event as any).loaded ?? 0;\n const total = (event as any).total ?? 1;\n const progress = Math.round(loaded * 100 / total);\n this.fileList.update(list =>\n list.map(f => f === entry ? { ...f, progress } : f)\n );\n break;\n }\n case HttpEventType.Response: {\n const res = event as any;\n if (res.status === 200) {\n // Backend returns a plain path string (e.g. \"temp/2024-01-15_14/file.pdf\").\n // Normalize to JvsArchivoServidor so downstream logic (download, remove) works uniformly.\n const servFile: JvsArchivoServidor = typeof res.body === 'string'\n ? { path: res.body }\n : res.body;\n this.fileList.update(list =>\n list.map(f => f === entry\n ? { ...f, servFile, progress: 100, inProgress: false }\n : f)\n );\n this._notifyChange();\n }\n break;\n }\n }\n }),\n catchError(err => {\n const mensaje = err?.error?.message ?? err?.message ?? 'Error al subir';\n mensajeToast('error', 'Error', `No se pudo subir <strong>${entry.file?.name}</strong>: ${mensaje}`);\n this.fileList.update(list =>\n list.map(f => f === entry\n ? { ...f, inProgress: false, progress: 0, errorSubida: true }\n : f)\n );\n this._onValidatorChange();\n return of(null);\n }),\n )\n ).then(() => {});\n }\n\n // ── Eliminación ───────────────────────────────────────────────────────────\n\n async onEliminar(entry: JvsFileEntry): Promise<void> {\n if (!this.permitirEliminar()) return;\n\n if (!this.fileList().includes(entry)) return;\n\n const remover = () => {\n this.fileList.update(list => list.filter(f => f !== entry));\n this._notifyChange();\n this.resultadoEliminado.emit(\n this.fileList().filter(f => f.servFile).map(f => f.servFile!)\n );\n };\n\n if (entry.servFile) {\n const removeFn = this.removeFn();\n\n if (removeFn) {\n // Archivo confirmado en servidor → confirmar y eliminar via API\n const result = await mensajeConfirmacion(\n 'warning',\n 'Eliminar archivo',\n 'Se eliminará definitivamente este archivo. Esta acción no se puede deshacer.',\n );\n if (!result.isConfirmed) return;\n\n try {\n await removeFn({ servFile: entry.servFile });\n remover();\n } catch {\n mensajeToast('error', 'Error', 'No se pudo eliminar el archivo del servidor.');\n }\n } else {\n // No hay removeFn: solo elimina de la lista local\n remover();\n }\n } else {\n // Archivo local aún no subido → eliminar sin confirmación\n remover();\n }\n }\n\n // ── Métodos públicos ──────────────────────────────────────────────────────\n\n /** Limpia toda la lista de archivos. */\n reset(): void {\n this.fileList.set([]);\n this.invalidFiles.set([]);\n this._notifyChange();\n }\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n\n private _notifyChange(): void {\n this.onTouched();\n if (this.temporal()) {\n this.onChange(this.fileList().map(f => f.servFile).filter(Boolean));\n } else {\n // Server-loaded entries (desdeServidor=true) have a mock {name} object, not a real File.\n // The parent only needs the real local File objects to upload later via uploadFilesPreForm().\n this.onChange(this.fileList().filter(f => !f.desdeServidor).map(f => f.file));\n }\n }\n\n}\n","<!-- Solo lista: modo readonly -->\n@if (readonly()) {\n <ng-container [ngTemplateOutlet]=\"listaTemporal\" />\n}\n\n<!-- Input oculto de selección de archivo -->\n<input\n #controlFile\n #fileInput\n hidden\n type=\"file\"\n [multiple]=\"multiple()\"\n [disabled]=\"isDisabled()\"\n (change)=\"onUploadChange(fileInput.files)\"\n/>\n\n<!-- Zona de drop (visible cuando NO es readonly) -->\n@if (!readonly()) {\n <div\n class=\"jvs-dropzone\"\n jvsFileUpload\n [controlFile]=\"controlFile\"\n [extensionesPermitidas]=\"extensionesNormalizadas()\"\n [parteDeNombre]=\"parteDeNombre()\"\n [tamanoMaximoMB]=\"tamanoMaximoMB()\"\n [parteDeNombreExclusivo]=\"parteDeNombreExclusivo()\"\n [isDisabled]=\"isDisabled()\"\n (filesChange)=\"onFilesChange($event)\"\n (filesInvalidChange)=\"invalidFiles.set($event)\"\n [class.jvs-dropzone--disabled]=\"isDisabled()\"\n >\n\n <!-- Instrucciones de selección -->\n @if (!isDisabled()) {\n <div class=\"jvs-dropzone__prompt\" (click)=\"fileInput.click()\">\n <mat-icon svgIcon=\"roundCloudUpload\" class=\"jvs-dropzone__icon\" />\n <span class=\"jvs-dropzone__label\">\n Haz click o arrastra {{ multiple() ? 'archivos' : 'un archivo' }} aquí\n </span>\n\n @if (tamanoMaximoMB()) {\n <small class=\"jvs-dropzone__hint\">Tamaño máximo: {{ tamanoMaximoMB() }} MB</small>\n }\n\n <small class=\"jvs-dropzone__hint\">{{ textoExtensiones() }}</small>\n\n <!-- Slot para mensajes de validación del form -->\n <small class=\"jvs-dropzone__error\">\n <ng-content select=\"[validator]\" />\n </small>\n <ng-content select=\"[mensajeExtra]\" />\n </div>\n }\n\n <!-- Lista de archivos temporales (con progreso) -->\n <ng-container [ngTemplateOutlet]=\"listaTemporal\" />\n\n <!-- Lista simple: archivos válidos/inválidos (modo no-temporal) -->\n @if (!temporal()) {\n <div class=\"jvs-dropzone__simple-list\" [ngClass]=\"cssContenedorAgregadosLista()\">\n @if (fileList().length > 0) {\n <mat-list dense>\n <h4 class=\"jvs-list-title jvs-list-title--valid\">Archivos válidos</h4>\n @for (file of fileList(); track file.file?.name) {\n <mat-list-item>\n <mat-icon matListItemIcon svgIcon=\"roundDone\" class=\"icon-valid\" />\n <span matListItemTitle [title]=\"file.file?.name ?? ''\">\n {{ file.file?.name }}\n </span>\n </mat-list-item>\n }\n </mat-list>\n }\n\n @if (invalidFiles().length > 0) {\n <mat-divider />\n <mat-list dense>\n <h4 class=\"jvs-list-title jvs-list-title--invalid\">Archivos inválidos</h4>\n @for (file of invalidFiles(); track file.name) {\n <mat-list-item>\n <mat-icon matListItemIcon svgIcon=\"roundCancel\" class=\"icon-invalid\" />\n <span matListItemTitle [title]=\"file.name\">{{ file.name }}</span>\n </mat-list-item>\n }\n </mat-list>\n\n <p class=\"jvs-dropzone__warning\">\n <mat-icon svgIcon=\"roundWarning\" class=\"icon-warning\" />\n Solo se enviarán los archivos\n <mat-icon svgIcon=\"roundDone\" class=\"icon-valid-inline\" />\n válidos.\n </p>\n }\n </div>\n }\n\n </div>\n}\n\n<!-- ── Template: lista temporal con progreso ─────────────────────────── -->\n<ng-template #listaTemporal>\n @if (temporal() && fileList().length > 0) {\n <ul class=\"jvs-file-list\" [ngClass]=\"cssContenedorAgregados()\">\n @for (entry of fileList(); track entry.file?.name ?? entry.servFile?.id) {\n <li class=\"jvs-file-list__item\">\n <jvs-file-upload-item\n [file]=\"entry\"\n [permitirEliminar]=\"permitirEliminar()\"\n [isDisabled]=\"isDisabled()\"\n (eliminar)=\"onEliminar($event)\"\n (descargar)=\"archivoDescarga.emit($event)\"\n (firmar)=\"firmarArchivo.emit($event)\"\n />\n </li>\n }\n </ul>\n }\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1","i3"],"mappings":";;;;;;;;;;;;;;;;;;;;AAWA;;;;;;AAMG;MAKU,sBAAsB,CAAA;;AAG/B,IAAA,YAAY,GAAI,KAAK,CAAC,EAAE,CAAC;AACzB,IAAA,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;AAChC,IAAA,WAAW,GAAK,KAAK,CAAC,QAAQ,EAAoB;AAElD,IAAA,qBAAqB,GAAM,KAAK,CAAW,EAAE,CAAC;AAC9C,IAAA,aAAa,GAAc,KAAK,CAAW,EAAE,CAAC;AAC9C,IAAA,sBAAsB,GAAK,KAAK,CAAW,EAAE,CAAC;AAC9C,IAAA,cAAc,GAAa,KAAK,CAAgB,IAAI,CAAC;AACrD,IAAA,UAAU,GAAiB,KAAK,CAAU,KAAK,CAAC;;AAGtC,IAAA,WAAW,GAAU,IAAI,YAAY,EAAU;AAC/C,IAAA,kBAAkB,GAAG,IAAI,YAAY,EAAU;;IAGxB,UAAU,GAAG,EAAE;;AAKhD,IAAA,UAAU,CAAC,GAAc,EAAA;QACrB,GAAG,CAAC,cAAc,EAAE;QACpB,GAAG,CAAC,eAAe,EAAE;AACrB,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE;;;AAK9C,IAAA,WAAW,CAAC,GAAc,EAAA;QACtB,GAAG,CAAC,cAAc,EAAE;QACpB,GAAG,CAAC,eAAe,EAAE;AACrB,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE;;;AAK7C,IAAA,MAAM,CAAC,GAAc,EAAA;QACjB,GAAG,CAAC,cAAc,EAAE;QACpB,GAAG,CAAC,eAAe,EAAE;QACrB,IAAI,IAAI,CAAC,UAAU,EAAE;YAAE;AAEvB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE;AACrC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC;AACvD,QAAA,MAAM,MAAM,GAAG,sBAAsB,CAAC,eAAe,CAAC,KAAK,EAAE;AACzD,YAAA,qBAAqB,EAAG,IAAI,CAAC,qBAAqB,EAAE;AACpD,YAAA,aAAa,EAAW,IAAI,CAAC,aAAa,EAAE;AAC5C,YAAA,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EAAE;AACrD,YAAA,cAAc,EAAU,IAAI,CAAC,cAAc,EAAE;AAChD,SAAA,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC;QAE/B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QACnC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;;;AAKhD;;;;;;;;;AASG;IACH,OAAO,eAAe,CAClB,KAAa,EACb,MAA2B,EAC3B,QAAQ,GAAG,IAAI,EAAA;QAEf,MAAM,UAAU,GAAa,EAAE;QAC/B,MAAM,YAAY,GAAW,EAAE;AAE/B,QAAA,MAAM,MAAM,GAAG,CAAC,MAAc,KAAY;YACtC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;YACnC,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE;AAChE,SAAC;AAED,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACtB,MAAM,GAAG,GAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;;YAG1C,IAAI,MAAM,CAAC,cAAc,IAAI,QAAQ,GAAG,MAAM,CAAC,cAAc,EAAE;AAC3D,gBAAA,YAAY,CAAC,OAAO,EAAE,mBAAmB,EACrC,CAAsB,mBAAA,EAAA,IAAI,CAAC,IAAI,gDAAgD,MAAM,CAAC,cAAc,CAAA,KAAA,CAAO,CAAC;AAChH,gBAAA,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;gBACvB;;;AAIJ,YAAA,IAAI,MAAM,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC;AACxC,gBAAA,MAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AAChE,gBAAA,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;AACrB,gBAAA,IAAI,CAAC,QAAQ;oBAAE;gBACf;;;YAIJ,MAAM,WAAW,GAAG,MAAM,CAAC,qBAAqB,CAAC,MAAM,KAAK,CAAC;AACxC,gBAAA,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC/D,MAAM,QAAQ,GAAM,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAE1E,YAAA,IAAI,WAAW,IAAI,QAAQ,EAAE;AACzB,gBAAA,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;AACrB,gBAAA,IAAI,CAAC,QAAQ;oBAAE;;iBACZ;gBACH,YAAY,CAAC,OAAO,EAAE,mBAAmB,EACrC,CAAsB,mBAAA,EAAA,IAAI,CAAC,IAAI,CAAyB,uBAAA,CAAA,CAAC;AAC7D,gBAAA,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;;QAI/B,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE;;wGAvH9C,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAtB,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,qBAAA,EAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,UAAA,EAAA,uBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,sBAAA,EAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,WAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,gBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,kBAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAAtB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAJlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACP,oBAAA,UAAU,EAAE,IAAI;AAChB,oBAAA,QAAQ,EAAE,iBAAiB;AAC9B,iBAAA;8BAea,WAAW,EAAA,CAAA;sBAApB;gBACS,kBAAkB,EAAA,CAAA;sBAA3B;gBAGgC,UAAU,EAAA,CAAA;sBAA1C,WAAW;uBAAC,kBAAkB;gBAK/B,UAAU,EAAA,CAAA;sBADT,YAAY;uBAAC,UAAU,EAAE,CAAC,QAAQ,CAAC;gBAUpC,WAAW,EAAA,CAAA;sBADV,YAAY;uBAAC,WAAW,EAAE,CAAC,QAAQ,CAAC;gBAUrC,MAAM,EAAA,CAAA;sBADL,YAAY;uBAAC,MAAM,EAAE,CAAC,QAAQ,CAAC;;;AChDpC;;;AAGG;MAcU,0BAA0B,CAAA;;AAGnC,IAAA,IAAI,GAAc,KAAK,CAAC,QAAQ,EAAgB;AAChD,IAAA,gBAAgB,GAAG,KAAK,CAAU,IAAI,CAAC;AACvC,IAAA,UAAU,GAAQ,KAAK,CAAU,KAAK,CAAC;;IAGvC,QAAQ,GAAI,MAAM,EAAgB;IAClC,SAAS,GAAG,MAAM,EAAgB;IAClC,MAAM,GAAM,MAAM,EAAsB;;AAI/B,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;AAC/B,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,OAAO,CAAC,CAAC,QAAQ,EAAE,SAAS,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;AACvF,KAAC,CAAC;AAEO,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AACpC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;AACrB,QAAA,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE;AACnD,KAAC,CAAC;AAEO,IAAA,cAAc,GAAG,QAAQ,CAAgD,MAAK;AACnF,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ;AAAE,YAAA,OAAO,YAAY;QACzD,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ;AAAE,YAAA,OAAO,YAAY;QAC1D,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,GAAG;AAAE,YAAA,OAAO,UAAU;AACzD,QAAA,OAAO,EAAE;AACb,KAAC,CAAC;AAEO,IAAA,YAAY,GAAG,QAAQ,CAAkC,MAAK;AACnE,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,OAAO,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,eAAe,GAAG,aAAa;AAChF,KAAC,CAAC;AAEO,IAAA,qBAAqB,GAAG,QAAQ,CAAC,MAAK;QAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ;;AAE/B,QAAA,OAAO,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,YAAY;AACxD,KAAC,CAAC;IAEO,kBAAkB,GAAG,QAAQ,CAAC,MACnC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAC/C;AAEQ,IAAA,oBAAoB,GAAG,QAAQ,CAAC,MACrC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAChD;AAEQ,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AACpC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;AACrB,QAAA,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI;AACnB,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,CAAC;AACnB,QAAA,OAAQ,IAAa,CAAC,IAAI,IAAI,CAAC;AACnC,KAAC,CAAC;;IAIO,cAAc,GAAG,cAAc;IAExC,UAAU,GAAA;QACN,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;;IAGnC,WAAW,GAAA;QACP,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;;IAGpC,QAAQ,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;AACtB,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAS,CAAC;;;wGAxEtC,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA1B,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC/BvC,mrFAqGA,ED9EQ,MAAA,EAAA,CAAA,62DAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,aAAa,mLACb,oBAAoB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,cAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,aAAA,EAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,CAAA,EAAA,QAAA,EAAA,CAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACpB,eAAe,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,CAAA,gBAAA,EAAA,oBAAA,EAAA,mBAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,mBAAA,EAAA,kBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,WAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACf,gBAAgB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,UAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,oBAAA,EAAA,4BAAA,EAAA,oBAAA,EAAA,qBAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,YAAA,EAAA,iBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAKX,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAbtC,SAAS;+BACI,sBAAsB,EAAA,UAAA,EACpB,IAAI,EACP,OAAA,EAAA;wBACL,OAAO;wBACP,aAAa;wBACb,oBAAoB;wBACpB,eAAe;wBACf,gBAAgB;AACnB,qBAAA,EAAA,QAAA,EAAA,mrFAAA,EAAA,MAAA,EAAA,CAAA,62DAAA,CAAA,EAAA;;;AEUL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;MA8BU,sBAAsB,CAAA;;;AAK/B,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,CAAC;;AAGhC,IAAA,gBAAgB,GAAG,KAAK,CAAU,IAAI,CAAC;;AAGvC,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,CAAC;;AAGhC,IAAA,QAAQ,GAAG,KAAK,CAAU,IAAI,CAAC;;AAG/B,IAAA,qBAAqB,GAAG,KAAK,CAAW,EAAE,CAAC;AAE3C;;;AAGG;AACH,IAAA,aAAa,GAAG,KAAK,CAAW,EAAE,CAAC;AAEnC;;;AAGG;AACH,IAAA,sBAAsB,GAAG,KAAK,CAAW,EAAE,CAAC;;AAG5C,IAAA,cAAc,GAAG,KAAK,CAAgB,IAAI,CAAC;;AAG3C,IAAA,iBAAiB,GAAG,KAAK,CAAgB,IAAI,CAAC;AAE9C;;;AAGG;AACH,IAAA,aAAa,GAAG,KAAK,CAAgB,IAAI,CAAC;;AAG1C,IAAA,UAAU,GAAG,KAAK,CAAgB,IAAI,CAAC;AAEvC;;;;;;AAMG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAqB,IAAI,CAAC;AAE1C;;;;;;AAMG;AACH,IAAA,QAAQ,GAAG,KAAK,CAAqB,IAAI,CAAC;;AAG1C,IAAA,sBAAsB,GAAG,KAAK,CAAS,EAAE,CAAC;;AAG1C,IAAA,2BAA2B,GAAG,KAAK,CAAS,EAAE,CAAC;;;IAK/C,kBAAkB,GAAG,MAAM,EAAwB;AAEnD;;;AAGG;IACH,eAAe,GAAG,MAAM,EAAgB;AAExC;;;AAGG;IACH,aAAa,GAAG,MAAM,EAAsB;;AAInC,IAAA,QAAQ,GAAM,MAAM,CAAiB,EAAE,CAAC;AACxC,IAAA,YAAY,GAAG,MAAM,CAAS,EAAE,CAAC;AACjC,IAAA,UAAU,GAAI,MAAM,CAAU,KAAK,CAAC;;;AAKpC,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC;;IAGtD,uBAAuB,GAAG,QAAQ,CAAC,MACxC,IAAI,CAAC,qBAAqB,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CACzD;;AAGQ,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAK;AACtC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,sBAAsB,EAAE;AACzC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,uBAAuB,EAAE;AAC1C,QAAA,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAA,yBAAA,EAA4B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA,CAAE;AACrF,QAAA,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAA,YAAA,EAAe,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA,CAAE;AACxE,QAAA,OAAO,oBAAoB;AAC/B,KAAC,CAAC;;AAGM,IAAA,QAAQ,GAAyB,MAAK,GAAG;AACzC,IAAA,SAAS,GAAe,MAAK,GAAG;AAChC,IAAA,kBAAkB,GAAe,MAAK,GAAG;;AAIjD,IAAA,UAAU,CAAC,KAAkC,EAAA;AACzC,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE;QAErC,MAAM,OAAO,GAAmB,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK;YAC5C,IAAI,EAAW,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE;AACvC,YAAA,aAAa,EAAE,IAAI;AACnB,YAAA,UAAU,EAAK,KAAK;AACpB,YAAA,QAAQ,EAAO,GAAG;AAClB,YAAA,QAAQ,EAAO,CAAC;AACnB,SAAA,CAAC,CAAC;AACH,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;;IAG9B,gBAAgB,CAAC,EAAoB,EAAA,EAAsB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IAC9E,iBAAiB,CAAC,EAAc,EAAA,EAA2B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;AAC/E,IAAA,gBAAgB,CAAC,UAAmB,EAAuB,EAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3F,yBAAyB,CAAC,EAAc,EAAA,EAAmB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;;;AAKxF,IAAA,QAAQ,CAAC,CAAc,EAAA;AACnB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC;AAAG,YAAA,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE;AAC/E,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC;AAAE,YAAA,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE;AAC1E,QAAA,OAAO,IAAI;;;;AAMf,IAAA,cAAc,CAAC,KAAsB,EAAA;AACjC,QAAA,IAAI,CAAC,KAAK;YAAE;QACZ,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AACnC,QAAA,MAAM,QAAQ,GAAI,sBAAsB,CAAC,eAAe,CAAC,SAAS,EAAE;AAChE,YAAA,qBAAqB,EAAG,IAAI,CAAC,uBAAuB,EAAE;AACtD,YAAA,aAAa,EAAW,IAAI,CAAC,aAAa,EAAE;AAC5C,YAAA,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EAAE;AACrD,YAAA,cAAc,EAAU,IAAI,CAAC,cAAc,EAAE;AAChD,SAAA,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;AAEnB,QAAA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC;QAClC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;;;AAI3C,IAAA,aAAa,CAAC,QAAgB,EAAA;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE;AACpE,YAAA,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,6BAA6B,CAAC;YAC7D;;AAGJ,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACjB,MAAM,MAAM,GAAmB;iBAC1B,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC;AAC/D,iBAAA,GAAG,CAAC,CAAC,KAAK;AACP,gBAAA,IAAI,EAAW,CAAC;AAChB,gBAAA,aAAa,EAAE,KAAK;AACpB,gBAAA,UAAU,EAAK,KAAK;AACpB,gBAAA,QAAQ,EAAO,CAAC;AAChB,gBAAA,QAAQ,EAAO,SAAS;AAC3B,aAAA,CAAC,CAAC;AAEP,YAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC;;AAElD,YAAA,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;;aACpD;YACH,MAAM,OAAO,GAAmB,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK;AAC/C,gBAAA,IAAI,EAAW,CAAC;AAChB,gBAAA,aAAa,EAAE,KAAK;AACpB,gBAAA,UAAU,EAAK,KAAK;AACpB,gBAAA,QAAQ,EAAO,CAAC;AACnB,aAAA,CAAC,CAAC;;YAEH,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI;gBACzB,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC;AACpC,gBAAA,GAAG,OAAO;AACb,aAAA,CAAC;;QAGN,IAAI,CAAC,aAAa,EAAE;;;AAKxB;;;;;;;;AAQG;IACH,MAAM,kBAAkB,CACpB,OAAgB,EAChB,OAAO,GAAG,KAAK,EACf,IAAa,EAAA;AAEb,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;QAChC,IAAI,CAAC,QAAQ,EAAE;AACX,YAAA,OAAO,CAAC,IAAI,CAAC,oEAAoE,CAAC;YAClF,OAAO,IAAI,CAAC,QAAQ;iBACf,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ;iBACtB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAS,CAAC;;AAG9B,QAAA,MAAM,YAAY,GAAG,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE;YAChD,OAAO,GAAG,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AAE3C,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;QAE3D,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,IACjC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,CAAC,CACxE;AAED,QAAA,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;AAElC,QAAA,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;QACvD,IAAI,CAAC,SAAS,EAAE;YACZ,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,GAAG,CAAC;YACzC,IAAI,MAAM,EAAE;gBACR,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACpC,SAAS,EACT,sBAAsB,EACtB,mEAAmE,CACtE;gBACD,IAAI,CAAC,MAAM,CAAC,WAAW;AAAE,oBAAA,OAAO,EAAE;;iBAC/B;AACH,gBAAA,OAAO,EAAE;;;QAIjB,OAAO,IAAI,CAAC,QAAQ;aACf,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ;aACtB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAS,CAAC;;;AAItB,IAAA,kBAAkB,CAAC,KAAmB,EAAA;AAC1C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;QAChC,IAAI,CAAC,QAAQ,EAAE;AACX,YAAA,OAAO,CAAC,IAAI,CAAC,gFAAgF,CAAC;YAC9F;;AAGJ,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE;YAChC,OAAO,GAAG,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC;AAC3D,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE;QAE9B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAK,GAAG,CAAC;;;IAIrE,aAAa,CACjB,KAAmB,EACnB,QAAqB,EACrB,OAAe,EACf,OAAgB,EAChB,IAAmB,EAAA;AAEnB,QAAA,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE;AAC/B,QAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE;YAC1B,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,iBAAiB,EAAG,CAAC;;QAE/D,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAY,CAAC;AAC9C,QAAA,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC;AACnC,QAAA,IAAI,IAAI;AAAE,YAAA,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;AAEvC,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,GAAG,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAC9D;QACD,IAAI,CAAC,kBAAkB,EAAE;AAEzB,QAAA,OAAO,aAAa,CAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAC5B,GAAG,CAAC,KAAK,IAAG;AACR,YAAA,QAAQ,KAAK,CAAC,IAAI;AACd,gBAAA,KAAK,aAAa,CAAC,cAAc,EAAE;AAC/B,oBAAA,MAAM,MAAM,GAAI,KAAa,CAAC,MAAM,IAAI,CAAC;AACzC,oBAAA,MAAM,KAAK,GAAK,KAAa,CAAC,KAAK,IAAK,CAAC;AACzC,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC;AACjD,oBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CACtD;oBACD;;AAEJ,gBAAA,KAAK,aAAa,CAAC,QAAQ,EAAE;oBACzB,MAAM,GAAG,GAAG,KAAY;AACxB,oBAAA,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE;;;AAGpB,wBAAA,MAAM,QAAQ,GAAuB,OAAO,GAAG,CAAC,IAAI,KAAK;AACrD,8BAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI;AAClB,8BAAE,GAAG,CAAC,IAAI;AACd,wBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK;AAChB,8BAAE,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK;AACpD,8BAAE,CAAC,CAAC,CACX;wBACD,IAAI,CAAC,aAAa,EAAE;;oBAExB;;;AAGZ,SAAC,CAAC,EACF,UAAU,CAAC,GAAG,IAAG;AACb,YAAA,MAAM,OAAO,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,OAAO,IAAI,gBAAgB;AACvE,YAAA,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,CAA4B,yBAAA,EAAA,KAAK,CAAC,IAAI,EAAE,IAAI,CAAA,WAAA,EAAc,OAAO,CAAA,CAAE,CAAC;AACnG,YAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK;AAChB,kBAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI;AAC3D,kBAAE,CAAC,CAAC,CACX;YACD,IAAI,CAAC,kBAAkB,EAAE;AACzB,YAAA,OAAO,EAAE,CAAC,IAAI,CAAC;SAClB,CAAC,CACL,CACJ,CAAC,IAAI,CAAC,MAAK,GAAG,CAAC;;;IAKpB,MAAM,UAAU,CAAC,KAAmB,EAAA;AAChC,QAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAAE;QAE9B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE;QAEtC,MAAM,OAAO,GAAG,MAAK;YACjB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;YAC3D,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CACxB,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAS,CAAC,CAChE;AACL,SAAC;AAED,QAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;AAChB,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;YAEhC,IAAI,QAAQ,EAAE;;gBAEV,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACpC,SAAS,EACT,kBAAkB,EAClB,8EAA8E,CACjF;gBACD,IAAI,CAAC,MAAM,CAAC,WAAW;oBAAE;AAEzB,gBAAA,IAAI;oBACA,MAAM,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC5C,oBAAA,OAAO,EAAE;;AACX,gBAAA,MAAM;AACJ,oBAAA,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,8CAA8C,CAAC;;;iBAE/E;;AAEH,gBAAA,OAAO,EAAE;;;aAEV;;AAEH,YAAA,OAAO,EAAE;;;;;IAOjB,KAAK,GAAA;AACD,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;AACrB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE;;;IAKhB,aAAa,GAAA;QACjB,IAAI,CAAC,SAAS,EAAE;AAChB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;;aAChE;;;AAGH,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;;;wGAlZ5E,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAbpB,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,qBAAA,EAAA,EAAA,iBAAA,EAAA,uBAAA,EAAA,UAAA,EAAA,uBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,sBAAA,EAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,sBAAA,EAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,UAAA,EAAA,wBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,2BAAA,EAAA,EAAA,iBAAA,EAAA,6BAAA,EAAA,UAAA,EAAA,6BAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,SAAA,EAAA;AACP,YAAA;AACI,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,sBAAsB,CAAC;AACrD,gBAAA,KAAK,EAAE,IAAI;AACd,aAAA;AACD,YAAA;AACI,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,sBAAsB,CAAC;AACrD,gBAAA,KAAK,EAAE,IAAI;AACd,aAAA;AACJ,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC9FL,20IAsHA,ED/CQ,MAAA,EAAA,CAAA,+lEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,OAAO,oFACP,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAChB,mBAAmB,EACnB,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,gBAAgB,EAChB,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,UAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,aAAa,mLACb,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,WAAA,EAAA,QAAA,EAAA,wDAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACb,gBAAgB,EAChB,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,sBAAsB,0QACtB,0BAA0B,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,kBAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,WAAA,EAAA,QAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAiBrB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBA7BlC,SAAS;+BACI,iBAAiB,EAAA,UAAA,EACf,IAAI,EACP,OAAA,EAAA;wBACL,OAAO;wBACP,gBAAgB;wBAChB,mBAAmB;wBACnB,gBAAgB;wBAChB,aAAa;wBACb,aAAa;wBACb,gBAAgB;wBAChB,sBAAsB;wBACtB,0BAA0B;qBAC7B,EAGU,SAAA,EAAA;AACP,wBAAA;AACI,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,CAAC,4BAA4B,CAAC;AACrD,4BAAA,KAAK,EAAE,IAAI;AACd,yBAAA;AACD,wBAAA;AACI,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,4BAA4B,CAAC;AACrD,4BAAA,KAAK,EAAE,IAAI;AACd,yBAAA;AACJ,qBAAA,EAAA,QAAA,EAAA,20IAAA,EAAA,MAAA,EAAA,CAAA,+lEAAA,CAAA,EAAA;;;AE9FL;;AAEG;;;;"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { FocusMonitor } from '@angular/cdk/a11y';
|
|
2
|
+
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { inject, ElementRef, Injector, signal, Input, ViewChild, Component } from '@angular/core';
|
|
5
|
+
import { NgControl } from '@angular/forms';
|
|
6
|
+
import { MAT_FORM_FIELD } from '@angular/material/form-field';
|
|
7
|
+
import { Subject } from 'rxjs';
|
|
8
|
+
|
|
9
|
+
class JvsMatFormControlBase {
|
|
10
|
+
static nextId = 0;
|
|
11
|
+
inputElement;
|
|
12
|
+
_focusMonitor = inject(FocusMonitor);
|
|
13
|
+
_elementRef = inject(ElementRef);
|
|
14
|
+
_formField = null;
|
|
15
|
+
ngControl = inject(NgControl, { optional: true, self: true });
|
|
16
|
+
injector = inject(Injector);
|
|
17
|
+
stateChanges = new Subject();
|
|
18
|
+
controlType = 'jvs-mat-form-control';
|
|
19
|
+
id = `jvs-mat-form-control-${JvsMatFormControlBase.nextId++}`;
|
|
20
|
+
_focused = signal(false);
|
|
21
|
+
get focused() {
|
|
22
|
+
return this._focused();
|
|
23
|
+
}
|
|
24
|
+
_touched = signal(false);
|
|
25
|
+
get touched() {
|
|
26
|
+
return this._touched();
|
|
27
|
+
}
|
|
28
|
+
get placeholder() {
|
|
29
|
+
return this._placeholder();
|
|
30
|
+
}
|
|
31
|
+
set placeholder(value) {
|
|
32
|
+
this._placeholder.set(value);
|
|
33
|
+
this.stateChanges.next();
|
|
34
|
+
}
|
|
35
|
+
_placeholder = signal('');
|
|
36
|
+
get required() {
|
|
37
|
+
return this._required();
|
|
38
|
+
}
|
|
39
|
+
set required(value) {
|
|
40
|
+
this._required.set(coerceBooleanProperty(value));
|
|
41
|
+
this.stateChanges.next();
|
|
42
|
+
}
|
|
43
|
+
_required = signal(false);
|
|
44
|
+
get disabled() {
|
|
45
|
+
return this._disabled();
|
|
46
|
+
}
|
|
47
|
+
set disabled(value) {
|
|
48
|
+
this._disabled.set(coerceBooleanProperty(value));
|
|
49
|
+
this.stateChanges.next();
|
|
50
|
+
}
|
|
51
|
+
_disabled = signal(false);
|
|
52
|
+
get value() {
|
|
53
|
+
return this._value();
|
|
54
|
+
}
|
|
55
|
+
set value(value) {
|
|
56
|
+
this._value.set(value);
|
|
57
|
+
this.onChange(value);
|
|
58
|
+
this.stateChanges.next();
|
|
59
|
+
}
|
|
60
|
+
_value = signal(null);
|
|
61
|
+
get empty() {
|
|
62
|
+
const value = this._value();
|
|
63
|
+
return (value === null ||
|
|
64
|
+
value === undefined ||
|
|
65
|
+
(typeof value === 'string' && value.length === 0));
|
|
66
|
+
}
|
|
67
|
+
get shouldLabelFloat() {
|
|
68
|
+
return this.focused || !this.empty;
|
|
69
|
+
}
|
|
70
|
+
get errorState() {
|
|
71
|
+
return !!(this.ngControl?.invalid && this.touched);
|
|
72
|
+
}
|
|
73
|
+
onContainerClick(event) {
|
|
74
|
+
if (event.target.tagName.toLowerCase() !== 'input') {
|
|
75
|
+
this.inputElement?.nativeElement.focus();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
setDescribedByIds(ids) {
|
|
79
|
+
// Implementación opcional si se necesita aria-describedby
|
|
80
|
+
}
|
|
81
|
+
// ControlValueAccessor implementation
|
|
82
|
+
onChange = (_) => { };
|
|
83
|
+
onTouched = () => { };
|
|
84
|
+
writeValue(value) {
|
|
85
|
+
this._value.set(value);
|
|
86
|
+
this.stateChanges.next();
|
|
87
|
+
}
|
|
88
|
+
registerOnChange(fn) {
|
|
89
|
+
this.onChange = fn;
|
|
90
|
+
}
|
|
91
|
+
registerOnTouched(fn) {
|
|
92
|
+
this.onTouched = fn;
|
|
93
|
+
}
|
|
94
|
+
setDisabledState(isDisabled) {
|
|
95
|
+
this._disabled.set(isDisabled);
|
|
96
|
+
this.stateChanges.next();
|
|
97
|
+
}
|
|
98
|
+
constructor() {
|
|
99
|
+
if (this.ngControl != null) {
|
|
100
|
+
this.ngControl.valueAccessor = this;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
ngOnInit() {
|
|
104
|
+
this._formField = this.injector.get(MAT_FORM_FIELD, null, { optional: true });
|
|
105
|
+
this._focusMonitor.monitor(this._elementRef, true).subscribe((origin) => {
|
|
106
|
+
this._focused.set(!!origin);
|
|
107
|
+
if (!origin) {
|
|
108
|
+
this._touched.set(true);
|
|
109
|
+
this.onTouched();
|
|
110
|
+
}
|
|
111
|
+
this.stateChanges.next();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
ngOnDestroy() {
|
|
115
|
+
this.stateChanges.complete();
|
|
116
|
+
this._focusMonitor.stopMonitoring(this._elementRef);
|
|
117
|
+
}
|
|
118
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsMatFormControlBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
119
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: JvsMatFormControlBase, isStandalone: true, selector: "ng-component", inputs: { placeholder: "placeholder", required: "required", disabled: "disabled", value: "value" }, viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: '', isInline: true });
|
|
120
|
+
}
|
|
121
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: JvsMatFormControlBase, decorators: [{
|
|
122
|
+
type: Component,
|
|
123
|
+
args: [{
|
|
124
|
+
template: '',
|
|
125
|
+
standalone: true,
|
|
126
|
+
}]
|
|
127
|
+
}], ctorParameters: () => [], propDecorators: { inputElement: [{
|
|
128
|
+
type: ViewChild,
|
|
129
|
+
args: ['input']
|
|
130
|
+
}], placeholder: [{
|
|
131
|
+
type: Input
|
|
132
|
+
}], required: [{
|
|
133
|
+
type: Input
|
|
134
|
+
}], disabled: [{
|
|
135
|
+
type: Input
|
|
136
|
+
}], value: [{
|
|
137
|
+
type: Input
|
|
138
|
+
}] } });
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Generated bundle index. Do not edit.
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
export { JvsMatFormControlBase };
|
|
145
|
+
//# sourceMappingURL=jvsoft-mat-form-controls.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jvsoft-mat-form-controls.mjs","sources":["../../../projects/mat-form-controls/base/jvs-mat-form-control-base.ts","../../../projects/mat-form-controls/jvsoft-mat-form-controls.ts"],"sourcesContent":["import {FocusMonitor} from '@angular/cdk/a11y';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {Component, ElementRef, inject, Injector, Input, OnDestroy, OnInit, signal, ViewChild} from '@angular/core';\nimport {ControlValueAccessor, NgControl} from '@angular/forms';\nimport {MAT_FORM_FIELD, MatFormField, MatFormFieldControl} from '@angular/material/form-field';\nimport {Subject} from 'rxjs';\n\n@Component({\n template: '',\n standalone: true,\n})\nexport abstract class JvsMatFormControlBase<T>\n implements MatFormFieldControl<T>, ControlValueAccessor, OnInit, OnDestroy\n{\n static nextId = 0;\n\n @ViewChild('input') inputElement!: ElementRef<HTMLInputElement>;\n\n protected _focusMonitor = inject(FocusMonitor);\n protected _elementRef = inject(ElementRef);\n public _formField: MatFormField | null = null;\n public ngControl = inject(NgControl, { optional: true, self: true });\n private injector = inject(Injector);\n\n readonly stateChanges = new Subject<void>();\n readonly controlType = 'jvs-mat-form-control';\n readonly id = `jvs-mat-form-control-${JvsMatFormControlBase.nextId++}`;\n\n protected readonly _focused = signal(false);\n get focused(): boolean {\n return this._focused();\n }\n\n protected readonly _touched = signal(false);\n get touched(): boolean {\n return this._touched();\n }\n @Input()\n get placeholder(): string {\n return this._placeholder();\n }\n set placeholder(value: string) {\n this._placeholder.set(value);\n this.stateChanges.next();\n }\n private readonly _placeholder = signal('');\n\n @Input()\n get required(): boolean {\n return this._required();\n }\n set required(value: BooleanInput) {\n this._required.set(coerceBooleanProperty(value));\n this.stateChanges.next();\n }\n private readonly _required = signal(false);\n\n @Input()\n get disabled(): boolean {\n return this._disabled();\n }\n set disabled(value: BooleanInput) {\n this._disabled.set(coerceBooleanProperty(value));\n this.stateChanges.next();\n }\n private readonly _disabled = signal(false);\n\n @Input()\n get value(): T | null {\n return this._value();\n }\n set value(value: T | null) {\n this._value.set(value);\n this.onChange(value);\n this.stateChanges.next();\n }\n protected readonly _value = signal<T | null>(null);\n\n get empty(): boolean {\n const value = this._value();\n return (\n value === null ||\n value === undefined ||\n (typeof value === 'string' && value.length === 0)\n );\n }\n\n get shouldLabelFloat(): boolean {\n return this.focused || !this.empty;\n }\n\n get errorState(): boolean {\n return !!(this.ngControl?.invalid && this.touched);\n }\n\n onContainerClick(event: MouseEvent): void {\n if ((event.target as Element).tagName.toLowerCase() !== 'input') {\n this.inputElement?.nativeElement.focus();\n }\n }\n\n setDescribedByIds(ids: string[]): void {\n // Implementación opcional si se necesita aria-describedby\n }\n\n // ControlValueAccessor implementation\n onChange = (_: any) => {};\n onTouched = () => {};\n\n writeValue(value: T | null): void {\n this._value.set(value);\n this.stateChanges.next();\n }\n\n registerOnChange(fn: any): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._disabled.set(isDisabled);\n this.stateChanges.next();\n }\n\n constructor() {\n if (this.ngControl != null) {\n this.ngControl.valueAccessor = this;\n }\n }\n\n ngOnInit(): void {\n this._formField = this.injector.get(MAT_FORM_FIELD, null, { optional: true });\n\n this._focusMonitor.monitor(this._elementRef, true).subscribe((origin) => {\n this._focused.set(!!origin);\n if (!origin) {\n this._touched.set(true);\n this.onTouched();\n }\n this.stateChanges.next();\n });\n }\n\n ngOnDestroy(): void {\n this.stateChanges.complete();\n this._focusMonitor.stopMonitoring(this._elementRef);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { OnInit } from '@angular/core';
|
|
2
|
+
import { FormControl } from '@angular/forms';
|
|
3
|
+
import { JvsMatFormControlBase } from '@jvsoft/mat-form-controls/base';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class JvsAutocompleteComponent extends JvsMatFormControlBase<any> implements OnInit {
|
|
6
|
+
private readonly destroyRef;
|
|
7
|
+
data: import("@angular/core").InputSignal<any[] | null>;
|
|
8
|
+
fields: import("@angular/core").InputSignal<string | string[]>;
|
|
9
|
+
idField: import("@angular/core").InputSignal<string>;
|
|
10
|
+
displayField: import("@angular/core").InputSignal<string>;
|
|
11
|
+
queryService: import("@angular/core").InputSignal<any>;
|
|
12
|
+
showSearchButton: import("@angular/core").InputSignal<boolean>;
|
|
13
|
+
internalControl: FormControl<any>;
|
|
14
|
+
filteredOptions: import("@angular/core").WritableSignal<any[]>;
|
|
15
|
+
isLoading: import("@angular/core").WritableSignal<boolean>;
|
|
16
|
+
ngOnInit(): void;
|
|
17
|
+
writeValue(value: any): void;
|
|
18
|
+
onFiltered(data: any[]): void;
|
|
19
|
+
onLoading(loading: boolean): void;
|
|
20
|
+
onSearchClick(): void;
|
|
21
|
+
limpiar(): void;
|
|
22
|
+
_onInputFocus(): void;
|
|
23
|
+
_onInputBlur(): void;
|
|
24
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<JvsAutocompleteComponent, never>;
|
|
25
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<JvsAutocompleteComponent, "jvs-autocomplete", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "idField": { "alias": "idField"; "required": false; "isSignal": true; }; "displayField": { "alias": "displayField"; "required": false; "isSignal": true; }; "queryService": { "alias": "queryService"; "required": false; "isSignal": true; }; "showSearchButton": { "alias": "showSearchButton"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.jvs-autocomplete-container {
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
position: relative;
|
|
10
|
+
width: 100%;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.jvs-autocomplete-input {
|
|
15
|
+
flex: 1;
|
|
16
|
+
width: 100%;
|
|
17
|
+
border: none;
|
|
18
|
+
background: transparent;
|
|
19
|
+
outline: none;
|
|
20
|
+
font: inherit;
|
|
21
|
+
color: inherit;
|
|
22
|
+
padding: 0;
|
|
23
|
+
margin: 0;
|
|
24
|
+
min-width: 0; /* Evita que el input crezca más que el contenedor */
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Standalone styling (Plano) */
|
|
28
|
+
.jvs-autocomplete-standalone {
|
|
29
|
+
border: 1px solid #d1d5db; /* Gris más suave (gray-300) */
|
|
30
|
+
border-radius: 0.375rem; /* rounded-md */
|
|
31
|
+
padding: 0.5rem 0.75rem; /* p-2 px-3 */
|
|
32
|
+
background-color: white;
|
|
33
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
34
|
+
|
|
35
|
+
&.jvs-autocomplete-focused {
|
|
36
|
+
border-color: #3b82f6; /* blue-500 */
|
|
37
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.jvs-autocomplete-suffix {
|
|
42
|
+
margin-left: 0.5rem;
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Ajustes cuando está dentro de un mat-form-field */
|
|
47
|
+
:host-context(mat-form-field) {
|
|
48
|
+
.jvs-autocomplete-container {
|
|
49
|
+
padding: 0;
|
|
50
|
+
border: none;
|
|
51
|
+
box-shadow: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* El input debe tener un poco de altura mínima para que Material lo vea bien */
|
|
55
|
+
.jvs-autocomplete-input {
|
|
56
|
+
height: 1.5rem;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './jvs-autocomplete.component';
|