ng-hub-ui-table
Version:
Highly customizable Angular table and list components with pagination, sorting and filtering support.
862 lines (847 loc) • 202 kB
JavaScript
import * as i0 from '@angular/core';
import { signal, effect, InjectionToken, Injectable, Optional, Inject, inject, NgModule, Component, ChangeDetectionStrategy, Input, Directive, Pipe, model, input, TemplateRef, ContentChild, ChangeDetectorRef, ElementRef, ViewContainerRef, ViewChild, HostListener, forwardRef, HostBinding, EventEmitter, Output, computed, contentChild, contentChildren, viewChildren } from '@angular/core';
import { Subject, Observable, isObservable, BehaviorSubject, debounceTime, distinctUntilChanged, of, fromEvent } from 'rxjs';
import * as i1 from '@angular/common';
import { NgClass, CommonModule, NgStyle, KeyValuePipe, UpperCasePipe, NgTemplateOutlet, AsyncPipe, DOCUMENT } from '@angular/common';
import * as i1$1 from '@angular/forms';
import { FormBuilder, NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule, UntypedFormBuilder, FormGroup } from '@angular/forms';
import { trigger, transition, style, animate } from '@angular/animations';
import { toSignal } from '@angular/core/rxjs-interop';
import { tap, switchMap, map, distinctUntilChanged as distinctUntilChanged$1, takeUntil } from 'rxjs/operators';
const locale$1 = {
lang: 'en',
data: {
LOADING: 'loading',
SEARCH: 'search',
ROWS_PER_PAGE: 'rows per page',
SHOWING_X_OF_Y_ROWS: 'Showing {{ amount }} of {{ total }} rows',
NO_RESULTS_FOUND: 'No results found',
BATCH_ACTIONS: 'Batch actions',
APPLY: 'Apply',
ERROR_OCURRED: 'Error ocurred getting data.',
FROM: 'from',
TO: 'to',
SAVE: 'save',
NEW_VIEW: 'new view',
ADD_VIEW: 'add view',
EDIT_VIEW: 'edit view',
DELETE_VIEW: 'delete view',
SAVE_FILTERS: 'save filters',
CANCEL: 'cancel',
NO_VIEWS_CREATED: 'No views have been created',
SELECT_VIEW: 'Select a view',
CLEAN_FILTERS: 'Clean filters',
NAME: 'name',
A_VIEW_WILL_BE_CREATED: 'A view will be created with the following configuration',
MUST_PROVIDE_A_VIEW_NAME: 'Must provide a view name.',
MUST_PROVIDE_VIEW_CONDITIONS: 'Must provide the conditions of the view.',
TODAY: 'today',
YESTERDAY: 'yesterday',
CURRENT_WEEK: 'current_week',
LAST_WEEK: 'last_week',
CURRENT_MONTH: 'current_month',
LAST_MONTH: 'last_month',
CURRENT_YEAR: 'current_year',
LAST_YEAR: 'last_year',
NO_ELEMENTS_FOUND: 'No elements found',
STAR_TYPING: 'Start typing to begin your search',
OPERATIONS: {
EQUAL_TO: 'Equal to',
VARIABLE: 'Variable'
},
CLEAR: 'clean',
ADD_RULE: 'add condition',
REMOVE_RULE: 'remove condition',
MATCH_ALL: 'match all',
MATCH_ANY: 'match any',
MATCH_MODES: {
GREATERTHAN: 'Greater than',
GREATERTHANOREQUAL: 'Greater than or equal to',
LESSTHAN: 'Less than',
LESSTHANOREQUAL: 'Less than or equal to',
EQUALS: 's',
NOTEQUALS: 'Not equal to',
EQUAL: 'Equal to',
NOTEQUAL: 'Not equal to',
BEFORE: 'Before',
BEFOREOREQUAL: 'Before or equal to',
AFTER: 'After',
AFTEROREQUAL: 'After or equal to',
STARTSWITH: 'Starts with',
CONTAINS: 'Contains',
NOTCONTAINS: 'Does not contain',
ENDSWITH: 'Ends with'
}
},
TRUE: 'true',
FALSE: 'false'
};
const locale = {
lang: 'es',
data: {
LOADING: 'cargando',
SEARCH: 'buscar',
ROWS_PER_PAGE: 'Filas por página',
SHOWING_X_OF_Y_ROWS: 'Mostrando {{ amount }} de {{ total }} resultados',
NO_RESULTS_FOUND: 'No se han encontrado resultados',
BATCH_ACTIONS: 'Acciones en lote',
APPLY: 'Aplicar',
ERROR_OCURRED: 'Ha ocurrido un error obteniendo los datos.',
FROM: 'desde',
TO: 'hasta',
SAVE: 'guardar',
NEW_VIEW: 'nueva vista',
ADD_VIEW: 'añadir vista',
EDIT_VIEW: 'editar vista',
DELETE_VIEW: 'eliminar vista',
SAVE_FILTERS: 'guardar filtros',
CANCEL: 'cancelar',
NO_VIEWS_CREATED: 'No hay vistas creadas',
SELECT_VIEW: 'Selecciona una vista',
CLEAN_FILTERS: 'Limpiar filtros',
NAME: 'Nombre',
A_VIEW_WILL_BE_CREATED: 'La vista se creará con las siguientes condiciones',
MUST_PROVIDE_A_VIEW_NAME: 'El nombre de la vista es requerido.',
MUST_PROVIDE_VIEW_CONDITIONS: 'Debe añadir condiciones a la vista.',
TODAY: 'hoy',
YESTERDAY: 'ayer',
CURRENT_WEEK: 'semana actual',
LAST_WEEK: 'semana pasada',
CURRENT_MONTH: 'mes actual',
LAST_MONTH: 'mes pasado',
CURRENT_YEAR: 'año actual',
LAST_YEAR: 'año pasado',
NO_ELEMENTS_FOUND: 'No se han encontrado elementos',
STAR_TYPING: 'Comienza a escribir para iniciar la búsqueda',
OPERATIONS: {
EQUAL_TO: 'Igual a',
VARIABLE: 'Variable'
},
CLEAR: 'Limpiar',
ADD_RULE: 'Añadir condición',
REMOVE_RULE: 'eliminar condición',
MATCH_ALL: 'Coincidir todo',
MATCH_ANY: 'Coincidir algo',
MATCH_MODES: {
GREATERTHAN: 'Mayor que',
GREATERTHANOREQUAL: 'Mayor o igual que',
LESSTHAN: 'Menor que',
LESSTHANOREQUAL: 'Menor o igual que',
EQUALS: 'Igual a',
NOTEQUALS: 'No igual a',
EQUAL: 'Igual a',
NOTEQUAL: 'No igual a',
BEFORE: 'Antes de',
BEFOREOREQUAL: 'Antes o igual a',
AFTER: 'Después de',
AFTEROREQUAL: 'Después o igual a',
STARTSWITH: 'Comienza con',
CONTAINS: 'Contiene',
NOTCONTAINS: 'No contiene',
ENDSWITH: 'Termina con'
}
},
TRUE: 'verdadero',
FALSE: 'falso'
};
const DEFAULT_LANGUAGE = navigator.language.split('-').at(0) ?? 'en';
const DEFAULT_PAGINABLE_CONFIG = {
theme: null,
mapping: {
currentPage: 'currentPage',
lastPage: 'lastPage',
data: 'data',
total: 'total'
},
views: {
key: 'paginable-table_view_'
},
language: DEFAULT_LANGUAGE
};
/**
* Creates a debounced version of a given signal. The returned signal updates its value
* only after the specified debounce time has elapsed since the last change in the source signal.
*
* @template T - The type of the signal's value.
* @param sourceSignal - The source signal to debounce.
* @param debounceDelay - Either a number (ms) or a signal<number> indicating debounce delay.
* @returns A new signal that emits debounced values from the source signal.
*/
function debouncedSignal(sourceSignal, debounceDelay = 0) {
const debounced = signal(sourceSignal());
effect((onCleanup) => {
const delay = typeof debounceDelay === 'number' ? debounceDelay : debounceDelay();
const value = sourceSignal();
const timeout = setTimeout(() => {
debounced.set(value);
}, delay);
onCleanup(() => clearTimeout(timeout));
});
return debounced;
}
/**
* Determines if two objects or two values are equivalent.
*
* Two objects or values are considered equivalent if at least one of the following is true:
*
* * Both objects or values pass `===` comparison.
* * Both objects or values are of the same type and all of their properties are equal by
* comparing them with `equals`.
*
* @param o1 Object or value to compare.
* @param o2 Object or value to compare.
* @returns true if arguments are equal.
*/
function equals(o1, o2) {
if (o1 === o2) {
return true;
}
if (o1 === null || o2 === null) {
return false;
}
if (o1 !== o1 && o2 !== o2) {
return true;
} // NaN === NaN
let t1 = typeof o1, t2 = typeof o2, length, key, keySet;
if (t1 == t2 && t1 == 'object') {
if (Array.isArray(o1)) {
if (!Array.isArray(o2)) {
return false;
}
if ((length = o1.length) == o2.length) {
for (key = 0; key < length; key++) {
if (!equals(o1[key], o2[key])) {
return false;
}
}
return true;
}
}
else {
if (Array.isArray(o2)) {
return false;
}
keySet = Object.create(null);
for (key in o1) {
if (!equals(o1[key], o2[key])) {
return false;
}
keySet[key] = true;
}
for (key in o2) {
if (!(key in keySet) && typeof o2[key] !== 'undefined') {
return false;
}
}
return true;
}
}
return false;
}
/**
* Checks if a value is defined and not null.
*
* @param {any} value - is of type `any`, which means it can accept any data type.
*
* @returns a boolean value.
*/
function isDefined(value) {
return typeof value !== 'undefined' && value !== null;
}
/**
* Checks if the given item is an object and not an array.
*
* @param {any} item - is of type "any", which means it can be any data type.
*
* @returns a boolean value.
*/
function isObject(item) {
return item && typeof item === 'object' && !Array.isArray(item);
}
/**
* Recursively merges two objects, combining their properties into a new object.
*
* @param {any} target - is the object that you want to merge the `source` object into.
* @param {any} source - is an object that contains the properties and values that you want to merge into the `target` object.
*
* @returns the merged object, which is the result of merging the `target` and `source` objects.
*/
function mergeDeep(target, source) {
let output = Object.assign({}, target);
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach((key) => {
if (isObject(source[key])) {
if (!(key in target)) {
Object.assign(output, { [key]: source[key] });
}
else {
output[key] = mergeDeep(target[key], source[key]);
}
}
else {
Object.assign(output, { [key]: source[key] });
}
});
}
return output;
}
/**
* Generates a unique ID of a specified length by randomly selecting characters from a predefined set of characters.
*
* @param {number} length - is the desired length of the generated unique ID.
*
* @returns a unique id string.
*/
function generateUniqueId(length) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let result = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charactersLength);
result += characters.charAt(randomIndex);
}
return result;
}
/**
* Replaces placeholders in a string with corresponding values from a given object.
*
* @param {string} expr - a string that represents the expression to be interpolated. It may contain
* placeholders that will be replaced with values from the `params` object.
* @param {any} [params] - an optional object that contains the values to be interpolated into the `expr`
* string. It is used to replace placeholders in the `expr` string with actual values.
*
* @returns returns the interpolated string. If `params` is not provided, it returns the original
* `expr` string. If `params` is provided, it replaces placeholders in the `expr` string with corresponding values from `params`
* and returns the interpolated string.
*/
function interpolateString(expr = '', params = {}, templateMatcher = /{{\s?([^{}\s]*)\s?}}/g) {
if (!params) {
return expr;
}
return expr.replace(templateMatcher, (substring, b) => {
let r = getValue(params, b);
return isDefined(r) ? r : substring;
});
}
/**
* Retrieves the value of a nested property from an object using dot notation.
*
* @param {any} target - the object from which you want to retrieve a value.
* @param {string} key - a string that represents the property or nested properties of the `target` object that you want to
* retrieve the value from. The `key` can be a single property name or a dot-separated string representing a nested property path.
*
* @returns the value of the specified key in the target object.
*/
function getValue(target, key) {
let keys = typeof key === 'string' ? key.split('.') : [key];
key = '';
do {
key += keys.shift();
if (isDefined(target) &&
isDefined(target[key]) &&
(typeof target[key] === 'object' || !keys.length)) {
target = target[key];
key = '';
}
else if (!keys.length) {
target = undefined;
}
else {
key += '.';
}
} while (keys.length);
return target;
}
/**
* This is not a real service, but it looks like it from the outside.
* It's just an InjectionTToken used to import the config object, provided from the outside
*/
// tslint:disable-next-line: variable-name
const PaginableConfigService = new InjectionToken('PaginableConfig');
class PaginableService {
get mapping() {
return this.config.mapping;
}
constructor(_config = DEFAULT_PAGINABLE_CONFIG) {
this._config = _config;
this.initialize();
}
initialize() {
this.config = mergeDeep(DEFAULT_PAGINABLE_CONFIG, this._config);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableService, deps: [{ token: PaginableConfigService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [PaginableConfigService]
}] }] });
class PaginableTranslationService {
#paginableSvc;
constructor() {
this.#paginableSvc = inject(PaginableService);
this.defaultTranslations = [locale$1, locale].reduce((acc, c) => {
acc[c.lang] = c.data;
return acc;
}, {});
this.translationSource = new Subject();
this.translationObserver = this.translationSource.asObservable();
this.initialize();
}
initialize() {
this.setTranslations(this.defaultTranslations[this.#paginableSvc.config.language] ??
this.defaultTranslations['en']);
}
/**
* Retrieves a value from a translations object based on a given key.
*
* @param {string} key - The `key` parameter in the `getTranslation` function is a string that represents the unique identifier or
* key for the translation you want to retrieve from the translations object. This key is used to look up the corresponding
* translation value in the translations object.
*
* @returns The value associated with the provided `key` from the `translations` object.
*/
getTranslation(key) {
return getValue(this.translations, key);
}
/**
* Merges the default English translations with the provided translations and updates the translation source.
*
* @param {Record<string, string> | any} translations - The `translations` parameter in the `setTranslation` method is a parameter that accepts
* either an object of type `Record<string, string>` or any other type. If no value is provided, it defaults to an empty object
* `{}`.
*/
setTranslations(translations = {}) {
this.translations = { ...locale$1, ...translations };
this.translationSource.next(this.translations);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableTranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableTranslationService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableTranslationService, decorators: [{
type: Injectable
}], ctorParameters: () => [] });
// import { PaginableTableComponent } from './components/paginable-table/paginable-table.component';
// import { PaginableTableHeaderDirective } from './directives/paginable-table-header.directive';
// import { PaginableTableRowDirective } from './directives/paginable-table-row.directive';
// import { PaginableTableCellDirective } from './directives/paginable-table-cell.directive';
// import { PaginableTableLoadingDirective } from './directives/paginable-table-loading.directive';
// import { PaginableTableErrorDirective } from './directives/paginable-table-error.directive';
// import { PaginableTableExpandingRowDirective } from './directives/paginable-table-expanding-row.directive';
// import { PaginableTableFilterDirective } from './directives/paginable-table-filter.directive';
class TableModule {
static forRoot(config) {
return {
ngModule: TableModule,
providers: [
{
provide: PaginableConfigService,
useValue: config
},
PaginableService,
PaginableTranslationService
]
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: TableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.8", ngImport: i0, type: TableModule }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: TableModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: TableModule, decorators: [{
type: NgModule,
args: [{
imports: [
// PaginableTableComponent,
// PaginableTableHeaderDirective,
// PaginableTableRowDirective,
// PaginableTableCellDirective,
// PaginableTableLoadingDirective,
// PaginableTableErrorDirective,
// PaginableTableExpandingRowDirective,
// PaginableTableFilterDirective
],
exports: [
// PaginableTableComponent,
// PaginableTableHeaderDirective,
// PaginableTableRowDirective,
// PaginableTableCellDirective,
// PaginableTableLoadingDirective,
// PaginableTableErrorDirective,
// PaginableTableExpandingRowDirective,
// PaginableTableFilterDirective
],
providers: []
}]
}] });
/**
* Checks if any Font Awesome base class is present in the input string.
*
* @param {string} input - The `containsFontAwesomeClass` function takes a string input and checks if it contains any of the Font
* Awesome base classes such as 'fa-solid', 'fa-regular', 'fa-light', 'fa-duotone', 'fa-thin', or 'fa-brands'.
*
* @returns A boolean value - `true` if any of the Font Awesome base classes are
* present in the input string, and `false` otherwise.
*/
function containsFontAwesomeClass(input) {
// Define an array of Font Awesome base classes to check for
const faClasses = [
'fa-solid',
'fa-regular',
'fa-light',
'fa-duotone',
'fa-thin',
'fa-brands'
];
// Use a regular expression to check if any of the Font Awesome classes are present in the input string
const faClassRegex = new RegExp(`\\b(${faClasses.join('|')})\\b`, 'i');
// Return true if any class matches, false otherwise
return faClassRegex.test(input);
}
/**
* Checks if a string contains the 'bi' class using a regular expression in TypeScript.
*
* @param {string} input - The `input` parameter in the `containsBootstrapIconsClass` function is a string that represents a CSS
* class or a list of CSS classes. The function checks if the input string contains the Bootstrap Icons class 'bi'.
*
* @returns returns a boolean value - `true` if the input string contains the 'bi'
* class, and `false` otherwise.
*/
function containsBootstrapIconsClass(input) {
// Define a regular expression pattern to match 'bi' class
const biClassRegex = /\bbi\b/;
// Return true if the class matches, false otherwise
return biClassRegex.test(input);
}
/**
* @file icon.component.ts
* @description Angular component for rendering icons with support for different icon libraries.
*/
/**
* @component HubIconComponent
* @selector hub-icon
* @description A versatile icon component that supports multiple icon libraries.
*
* @example
* <hub-icon [config]="iconConfig"></hub-icon>
*/
class HubIconComponent {
/**
* @input config
* @description Sets the icon configuration. Can be a string or an Icon object.
* @type {string | Icon}
*/
set config(value) {
if (!value) {
value = '';
}
if (typeof value === 'string') {
this.value = value;
}
else {
this.type = value.type ?? null;
this.variant = value.variant ?? '';
this.value = value.value ?? null;
}
}
/**
* @getter classlist
* @description Computes the CSS classes for the icon based on its type and value.
* @returns {string | null} The computed CSS class string or null if no value is set.
*/
get classlist() {
if (!this.value) {
return null;
}
if (!this.type) {
return this.value;
}
const classlist = [];
if (['font-awesome', 'bootstrap'].includes(this.type)) {
if (Array.isArray(this.value)) {
classlist.push(...this.value);
}
else {
classlist.push(...this.value.split(' '));
}
}
switch (this.type) {
case 'font-awesome':
if (!containsFontAwesomeClass(classlist.join(' '))) {
classlist.push('fa');
}
break;
case 'bootstrap':
if (!containsFontAwesomeClass(classlist.join(' '))) {
classlist.push('bs');
}
break;
case 'material':
classlist.push('material-symbols-outlined');
break;
}
return classlist.join(' ');
}
/**
* @getter content
* @description Gets the content for material icons.
* @returns {string | null} The icon content for material icons, or null for other types.
*/
get content() {
return ['material'].includes(this.type) ? this.value : null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: HubIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.8", type: HubIconComponent, isStandalone: true, selector: "hub-icon, ng-hub-ui-icon", inputs: { config: "config" }, ngImport: i0, template: "@if (value) {\n <i [ngClass]=\"classlist\">\n {{ content }}\n </i>\n}\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: HubIconComponent, decorators: [{
type: Component,
args: [{ selector: 'hub-icon, ng-hub-ui-icon', standalone: true, imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (value) {\n <i [ngClass]=\"classlist\">\n {{ content }}\n </i>\n}\n" }]
}], propDecorators: { config: [{
type: Input,
args: [{ required: true }]
}] } });
class PaginableListItemDirective {
constructor(template) {
this.template = template;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableListItemDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: PaginableListItemDirective, isStandalone: true, selector: "[listItemTpt]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableListItemDirective, decorators: [{
type: Directive,
args: [{
selector: '[listItemTpt]'
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
class PaginableTableNotFoundDirective {
constructor(template) {
this.template = template;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableTableNotFoundDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: PaginableTableNotFoundDirective, isStandalone: true, selector: "[noDataTpt], [paginableTableNotFound]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableTableNotFoundDirective, decorators: [{
type: Directive,
args: [{
selector: '[noDataTpt], [paginableTableNotFound]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
class UcfirstPipe {
transform(value = '') {
return value.charAt(0).toUpperCase() + value.slice(1);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: UcfirstPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.8", ngImport: i0, type: UcfirstPipe, isStandalone: true, name: "ucfirst" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: UcfirstPipe, decorators: [{
type: Pipe,
args: [{
name: 'ucfirst',
standalone: true
}]
}] });
class PaginatorComponent {
constructor() {
this.page = model(1);
this.numberOfPages = input();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.8", type: PaginatorComponent, isStandalone: true, selector: "hub-paginator, paginable-table-paginator", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, numberOfPages: { classPropertyName: "numberOfPages", publicName: "numberOfPages", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange" }, ngImport: i0, template: "<nav class=\"pager\" aria-label=\"Page navigation\">\n\t<ul class=\"pager pagination pager__list\">\n\t\t<li\n\t\t\tclass=\"page-item pager__item\"\n\t\t\t[class.pager__item--disabled]=\"page() === 1\"\n\t\t\t[class.disabled]=\"page() === 1\"\n\t\t>\n\t\t\t<a\n\t\t\t\trole=\"button\"\n\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t(click)=\"page.set(1)\"\n\t\t\t>\n\t\t\t\t<i class=\"pager__icon fa fa-angle-double-left\"></i>\n\t\t\t</a>\n\t\t</li>\n\t\t<li\n\t\t\tclass=\"page-item pager__item\"\n\t\t\t[class.pager__item--disabled]=\"page() <= 1\"\n\t\t\t[class.disabled]=\"page() <= 1\"\n\t\t>\n\t\t\t<a\n\t\t\t\trole=\"button\"\n\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\thref=\"javascript:{}\"\n\t\t\t\taria-label=\"Previous\"\n\t\t\t\t(click)=\"page.set(page() - 1)\"\n\t\t\t>\n\t\t\t\t<span class=\"pager__icon-wrapper\" aria-hidden=\"true\">\n\t\t\t\t\t<i class=\"pager__icon fa fa-angle-left\"></i>\n\t\t\t\t</span>\n\t\t\t</a>\n\t\t</li>\n\t\t@if (page() - 1 > 1) {\n\t\t\t<li class=\"page-item pager__item pager__item--disabled disabled\">\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t>...</a\n\t\t\t\t>\n\t\t\t</li>\n\t\t}\n\t\t<li class=\"page-item pager__item\">\n\t\t\t@if (page() - 1 >= 1) {\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t(click)=\"page.set(page() - 1)\"\n\t\t\t\t\t>{{ page() - 1 }}</a\n\t\t\t\t>\n\t\t\t}\n\t\t</li>\n\t\t<li class=\"page-item pager__item pager__item--active active\">\n\t\t\t<a\n\t\t\t\trole=\"button\"\n\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t>{{ page() }}</a\n\t\t\t>\n\t\t</li>\n\t\t@if (numberOfPages()) {\n\t\t\t<li class=\"page-item pager__item\">\n\t\t\t\t@if (page() + 1 <= numberOfPages()!) {\n\t\t\t\t\t<a\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t\t(click)=\"page.set(page() + 1)\"\n\t\t\t\t\t\t>{{ page() + 1 }}</a\n\t\t\t\t\t>\n\t\t\t\t}\n\t\t\t</li>\n\t\t\t@if (page() + 1 < numberOfPages()!) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"page-item pager__item pager__item--disabled disabled\"\n\t\t\t\t>\n\t\t\t\t\t<a\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t\t>...</a\n\t\t\t\t\t>\n\t\t\t\t</li>\n\t\t\t}\n\t\t\t<li\n\t\t\t\tclass=\"page-item pager__item\"\n\t\t\t\t[class.pager__item--disabled]=\"page() >= numberOfPages()!\"\n\t\t\t\t[class.disabled]=\"page() >= numberOfPages()!\"\n\t\t\t>\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\taria-label=\"Next\"\n\t\t\t\t\t(click)=\"page.set(page() + 1)\"\n\t\t\t\t>\n\t\t\t\t\t<span class=\"pager__icon-wrapper\" aria-hidden=\"true\">\n\t\t\t\t\t\t<i class=\"pager__icon fa fa-angle-right\"></i>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t<li\n\t\t\t\tclass=\"page-item pager__item\"\n\t\t\t\t[class.pager__item--disabled]=\"page() === numberOfPages()\"\n\t\t\t\t[class.disabled]=\"page() === numberOfPages()\"\n\t\t\t>\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t(click)=\"page.set(numberOfPages() ?? 1)\"\n\t\t\t\t>\n\t\t\t\t\t<i class=\"pager__icon fa fa-angle-double-right\"></i>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t} @else {\n\t\t\t<li class=\"page-item pager__item\">\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\taria-label=\"Next\"\n\t\t\t\t\t(click)=\"page.set(page() + 1)\"\n\t\t\t\t>\n\t\t\t\t\t<span class=\"pager__icon-wrapper\" aria-hidden=\"true\">\n\t\t\t\t\t\t<i class=\"pager__icon fa fa-angle-right\"></i>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t}\n\t</ul>\n</nav>\n", styles: [".pager .pager__list{margin-bottom:0}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginatorComponent, decorators: [{
type: Component,
args: [{ selector: 'hub-paginator, paginable-table-paginator', standalone: true, template: "<nav class=\"pager\" aria-label=\"Page navigation\">\n\t<ul class=\"pager pagination pager__list\">\n\t\t<li\n\t\t\tclass=\"page-item pager__item\"\n\t\t\t[class.pager__item--disabled]=\"page() === 1\"\n\t\t\t[class.disabled]=\"page() === 1\"\n\t\t>\n\t\t\t<a\n\t\t\t\trole=\"button\"\n\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t(click)=\"page.set(1)\"\n\t\t\t>\n\t\t\t\t<i class=\"pager__icon fa fa-angle-double-left\"></i>\n\t\t\t</a>\n\t\t</li>\n\t\t<li\n\t\t\tclass=\"page-item pager__item\"\n\t\t\t[class.pager__item--disabled]=\"page() <= 1\"\n\t\t\t[class.disabled]=\"page() <= 1\"\n\t\t>\n\t\t\t<a\n\t\t\t\trole=\"button\"\n\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\thref=\"javascript:{}\"\n\t\t\t\taria-label=\"Previous\"\n\t\t\t\t(click)=\"page.set(page() - 1)\"\n\t\t\t>\n\t\t\t\t<span class=\"pager__icon-wrapper\" aria-hidden=\"true\">\n\t\t\t\t\t<i class=\"pager__icon fa fa-angle-left\"></i>\n\t\t\t\t</span>\n\t\t\t</a>\n\t\t</li>\n\t\t@if (page() - 1 > 1) {\n\t\t\t<li class=\"page-item pager__item pager__item--disabled disabled\">\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t>...</a\n\t\t\t\t>\n\t\t\t</li>\n\t\t}\n\t\t<li class=\"page-item pager__item\">\n\t\t\t@if (page() - 1 >= 1) {\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t(click)=\"page.set(page() - 1)\"\n\t\t\t\t\t>{{ page() - 1 }}</a\n\t\t\t\t>\n\t\t\t}\n\t\t</li>\n\t\t<li class=\"page-item pager__item pager__item--active active\">\n\t\t\t<a\n\t\t\t\trole=\"button\"\n\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t>{{ page() }}</a\n\t\t\t>\n\t\t</li>\n\t\t@if (numberOfPages()) {\n\t\t\t<li class=\"page-item pager__item\">\n\t\t\t\t@if (page() + 1 <= numberOfPages()!) {\n\t\t\t\t\t<a\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t\t(click)=\"page.set(page() + 1)\"\n\t\t\t\t\t\t>{{ page() + 1 }}</a\n\t\t\t\t\t>\n\t\t\t\t}\n\t\t\t</li>\n\t\t\t@if (page() + 1 < numberOfPages()!) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"page-item pager__item pager__item--disabled disabled\"\n\t\t\t\t>\n\t\t\t\t\t<a\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t\t>...</a\n\t\t\t\t\t>\n\t\t\t\t</li>\n\t\t\t}\n\t\t\t<li\n\t\t\t\tclass=\"page-item pager__item\"\n\t\t\t\t[class.pager__item--disabled]=\"page() >= numberOfPages()!\"\n\t\t\t\t[class.disabled]=\"page() >= numberOfPages()!\"\n\t\t\t>\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\taria-label=\"Next\"\n\t\t\t\t\t(click)=\"page.set(page() + 1)\"\n\t\t\t\t>\n\t\t\t\t\t<span class=\"pager__icon-wrapper\" aria-hidden=\"true\">\n\t\t\t\t\t\t<i class=\"pager__icon fa fa-angle-right\"></i>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t<li\n\t\t\t\tclass=\"page-item pager__item\"\n\t\t\t\t[class.pager__item--disabled]=\"page() === numberOfPages()\"\n\t\t\t\t[class.disabled]=\"page() === numberOfPages()\"\n\t\t\t>\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\t(click)=\"page.set(numberOfPages() ?? 1)\"\n\t\t\t\t>\n\t\t\t\t\t<i class=\"pager__icon fa fa-angle-double-right\"></i>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t} @else {\n\t\t\t<li class=\"page-item pager__item\">\n\t\t\t\t<a\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\tclass=\"page-link pager__link\"\n\t\t\t\t\thref=\"javascript:{}\"\n\t\t\t\t\taria-label=\"Next\"\n\t\t\t\t\t(click)=\"page.set(page() + 1)\"\n\t\t\t\t>\n\t\t\t\t\t<span class=\"pager__icon-wrapper\" aria-hidden=\"true\">\n\t\t\t\t\t\t<i class=\"pager__icon fa fa-angle-right\"></i>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t}\n\t</ul>\n</nav>\n", styles: [".pager .pager__list{margin-bottom:0}\n"] }]
}] });
class PaginableListComponent {
constructor() {
this.#fb = inject(FormBuilder);
this.bindLabel = 'label';
this.bindChildren = 'children';
this._options = {
cursor: 'default',
hoverableRows: false,
striped: null,
variant: null,
searchable: false,
collapsed: true
};
this.form = this.#fb.array([]);
this.value = [];
// NOTE: Otros
this.isDisabled = false;
this.onChange = () => { };
this.onTouch = () => { };
// NOTE: Filters
this.searchFG = this.#fb.control({});
// NOTE: Batch actions
/**
* Collection of actions for items
*
* @type {PaginableTableRowAction[]}
* @memberof PaginableTableComponent
*/
this._batchActions = [];
}
#fb;
get options() {
return this._options;
}
set options(v) {
this._options = v;
this.buildForm(this.form, this._items);
}
get items() {
return this._items;
}
set items(v) {
this._items = v ?? [];
this.form.clear();
this.buildForm(this.form, this._items);
}
get batchActions() {
return this._batchActions;
}
set batchActions(v) {
this._batchActions = v.map((b) => {
if (b.buttons) {
b = { fill: null, position: 'start', color: 'light', ...b };
}
return b;
});
}
// NOTE: Control access value
writeValue(value = []) {
// this.value = this.buildValue(value);
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouch = fn;
}
setDisabledState(isDisabled) {
this.isDisabled = isDisabled;
}
/**
* Handles the action to be executed in a batch
*
* @param {Event} event
* @memberof PaginableTableComponent
*/
handleBatchAction(event) {
event.handler(this.value);
}
buildForm(form, items) {
form.clear();
for (const index in items) {
if (Object.prototype.hasOwnProperty.call(items, index)) {
const item = items[index];
const group = this.#fb.group({
selected: [true],
collapsed: [this.options.collapsed],
data: [item],
children: this.#fb.array([])
});
group.patchValue(item);
if (item[this.bindChildren]?.length) {
this.buildForm(group.get('children'), item[this.bindChildren]);
// newItem['children'] = this.buildValue(children);
}
form.push(group);
}
}
}
buildValue(items) {
const value = [];
for (const item of items) {
const { children, ...newItem } = item;
if (children?.length) {
newItem['children'] = this.buildValue(children);
}
value.push({
...newItem,
collapsed: true
});
}
return value;
}
toggleCollapsed(control) {
control.patchValue(!control.value);
}
/**
* Emits a structured click event for the clicked list item, including metadata and state.
*
* This method is typically called when an item in the list is clicked. It extracts contextual
* information such as depth, index, selection state, and expansion state, then passes it to
* the user-defined `clickFn` callback.
*
* If a `bindLabel` is configured, the emitted `value` will be derived from that property;
* otherwise, the full item will be passed as `value`.
*
* @param item - The list item object, including `selected` and `collapsed` state.
* @param depth - The nesting depth of the item within a tree structure (0 = root level).
* @param index - The position of the item in the current visible list or page.
* @param event - The native `MouseEvent` that triggered the click.
*
* @remarks
* If the `clickFn` callback is not defined, the method exits early and no event is emitted.
*/
onItemClick({ collapsed, selected, ...item }, depth, index, event) {
if (!this.clickFn) {
return;
}
this.clickFn({
depth,
index,
selected,
collapsed,
value: this.bindLabel ? getValue(item, this.bindLabel) : item,
item: item,
mouseEvent: event
});
}
onPageClicked(page) {
// if (!this.data) {
// return;
// }
// this.data.currentPage = page;
// this.triggerTheParamChanges();
}
filter() {
// if (!this.data) {
// return;
// }
// this.data.currentPage = 1;
// this.filterChange.emit({
// searchText: this.searchFG?.value ?? null,
// specificSearch: this.specificSearchFG?.value ?? null
// });
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.8", type: PaginableListComponent, isStandalone: true, selector: "hub-list, hub-ui-list, hub-paginable-list", inputs: { bindValue: "bindValue", bindLabel: "bindLabel", bindChildren: "bindChildren", selectable: "selectable", options: "options", items: "items", clickFn: "clickFn", batchActions: "batchActions" }, host: { classAttribute: "d-flex flex-column gap-4" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: PaginableListComponent,
multi: true
}
], queries: [{ propertyName: "itemTpt", first: true, predicate: PaginableListItemDirective, descendants: true, read: TemplateRef }, { propertyName: "noDataTpt", first: true, predicate: PaginableTableNotFoundDirective, descendants: true, read: TemplateRef }], ngImport: i0, template: "@if (batchActions.length || options.searchable) {\n\t<div class=\"d-flex justify-content-between gap-3\">\n\t\t<div class=\"ms-auto\">\n\t\t\t<div class=\"d-flex justify-content-end gap-2\">\n\t\t\t\t@if (options.searchable) {\n\t\t\t\t\t<div class=\"input-group search_input-group\">\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tclass=\"form-control border border-light search_input\"\n\t\t\t\t\t\t\t[formControl]=\"searchFG\"\n\t\t\t\t\t\t\t[placeholder]=\"'SEARCH' | ucfirst\"\n\t\t\t\t\t\t\t(keyup.enter)=\"filter()\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div class=\"input-group-append\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tclass=\"btn btn-light search_button\"\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t(click)=\"filter()\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<i class=\"fa fa-search\" aria-hidden=\"true\"></i>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n}\n\n<ng-container\n\t[ngTemplateOutlet]=\"containerTpt\"\n\t[ngTemplateOutletContext]=\"{\n\t\tformArray: form,\n\t\tisRoot: true,\n\t\titems: items,\n\t\tdepth: 0\n\t}\"\n></ng-container>\n\n<ng-template\n\t#containerTpt\n\tlet-formArray=\"formArray\"\n\tlet-isRoot=\"isRoot\"\n\tlet-items=\"items\"\n\tlet-depth=\"depth\"\n>\n\t<ul class=\"list-group list-group-flush tree-list\" [class.root]=\"isRoot\">\n\t\t@for (\n\t\t\tformGroup of formArray.controls;\n\t\t\ttrack formGroup;\n\t\t\tlet index = $index\n\t\t) {\n\t\t\t<li\n\t\t\t\tclass=\"list-group-item tree-list__node\"\n\t\t\t\t[class.clickable-item]=\"clickFn\"\n\t\t\t\t[formGroup]=\"formGroup\"\n\t\t\t\t(click)=\"\n\t\t\t\t\tonItemClick(formGroup.value, depth, index, $event);\n\t\t\t\t\t$event.preventDefault();\n\t\t\t\t\t$event.stopPropagation()\n\t\t\t\t\"\n\t\t\t>\n\t\t\t\t@if (formGroup.value; as item) {\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"d-flex justify-content-between align-items-center gap-2\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@if (selectable === 'multiple') {\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tclass=\"form-check-input tree-list__node-checkbox\"\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tformControlName=\"selected\"\n\t\t\t\t\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t<div class=\"tree-list__node-label\">\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"itemTpt || defaultItemtTpt\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\tdata: items[index],\n\t\t\t\t\t\t\t\t\tdepth,\n\t\t\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\t\t\tcollapsed:\n\t\t\t\t\t\t\t\t\t\t!!formGroup.get('collapsed').value,\n\t\t\t\t\t\t\t\t\tselected: formGroup.get('selected').value\n\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"tree-list__node-buttons d-flex align-items-center gap-2\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@if (item[bindChildren]?.length) {\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tclass=\"btn\"\n\t\t\t\t\t\t\t\t\t(click)=\"\n\t\t\t\t\t\t\t\t\t\ttoggleCollapsed(\n\t\t\t\t\t\t\t\t\t\t\tformGroup.get('collapsed')\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t$event.preventDefault();\n\t\t\t\t\t\t\t\t\t\t$event.stopPropagation()\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<i\n\t\t\t\t\t\t\t\t\t\tclass=\"fas\"\n\t\t\t\t\t\t\t\t\t\t[ngClass]=\"\n\t\t\t\t\t\t\t\t\t\t\titem.collapsed\n\t\t\t\t\t\t\t\t\t\t\t\t? 'fa-chevron-down'\n\t\t\t\t\t\t\t\t\t\t\t\t: 'fa-chevron-up'\n\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t></i>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t@if (item[bindChildren]?.length && !item.collapsed) {\n\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t[ngTemplateOutlet]=\"containerTpt\"\n\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\tformArray: formGroup.get('children'),\n\t\t\t\t\t\t\t\titems: items[index][bindChildren],\n\t\t\t\t\t\t\t\tdepth: depth + 1\n\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t></ng-container>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</li>\n\t\t}\n\t</ul>\n</ng-template>\n\n<ng-template #noDataRowTpt>\n\t<li class=\"list-group-item\">\n\t\t<ng-container [ngTemplateOutlet]=\"noDataTpt || defaultNoDataTpt\">\n\t\t</ng-container>\n\t</li>\n</ng-template>\n\n<ng-template #defaultNoDataTpt>\n\t<div class=\"alert alert-info d-flex align-items-center m-4\" role=\"alert\">\n\t\t<i class=\"fa fa-info fa-2x me-4 mr-4\" aria-hidden=\"true\"></i>\n\t\t{{ 'NO_RESULTS_FOUND' | ucfirst }}\n\t</div>\n</ng-template>\n\n<ng-template #defaultItemtTpt let-data=\"data\">\n\t{{ data[bindLabel] }}\n</ng-template>\n", styles: [":host{display:block;overflow:auto}.tree-list:not(.root)>.tree-list__node{padding-right:0}.tree-list__node-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-grow:1}.clickable-item{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: UcfirstPipe, name: "ucfirst" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: PaginableListComponent, decorators: [{
type: Component,
args: [{ selector: 'hub-list, hub-ui-list, hub-paginable-list', host: {
class: 'd-flex flex-column gap-4'
}, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: PaginableListComponent,
multi: true
}
], imports: [
CommonModule,
ReactiveFormsModule,
PaginatorComponent,
PaginableTableNotF