tecnualng 0.0.1 → 21.0.12

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.
@@ -1,8 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, model, forwardRef, signal, computed, HostListener, effect, Injectable } from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, model, forwardRef, signal, computed, HostListener, viewChild, TemplateRef, contentChildren, effect, Injectable, createComponent, Input, Directive, output, ContentChildren } from '@angular/core';
3
3
  import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule } from '@angular/common';
6
+ import { trigger, transition, style, animate } from '@angular/animations';
7
+ import * as i1$1 from '@angular/router';
8
+ import { RouterModule } from '@angular/router';
6
9
 
7
10
  class TngButton {
8
11
  variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : []));
@@ -30,7 +33,7 @@ class TngButton {
30
33
  button.appendChild(circle);
31
34
  }
32
35
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
33
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngButton, isStandalone: true, selector: "button[tngButton], a[tngButton]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, soft: { classPropertyName: "soft", publicName: "soft", isSignal: true, isRequired: false, transformFunction: null }, ripple: { classPropertyName: "ripple", publicName: "ripple", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "createRipple($event)" }, properties: { "class.tng-button--primary": "variant() === \"primary\"", "class.tng-button--secondary": "variant() === \"secondary\"", "class.tng-button--success": "variant() === \"success\"", "class.tng-button--warning": "variant() === \"warning\"", "class.tng-button--error": "variant() === \"error\"", "class.tng-button--rounded": "rounded()", "class.tng-button--soft": "soft()" }, classAttribute: "tng-button" }, exportAs: ["tngButton"], ngImport: i0, template: "<span class=\"tng-button__label\">\n @if (icon() && iconPosition() === 'left') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--left\"></i>\n }\n <ng-content></ng-content>\n @if (icon() && iconPosition() === 'right') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--right\"></i>\n }\n</span>\n\n", styles: [".tng-button{position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;height:32px;border:none;outline:none;line-height:inherit;-webkit-appearance:none;overflow:hidden;vertical-align:middle;background:transparent;padding:0 16px;font-family:inherit;font-size:.875rem;font-weight:500;letter-spacing:.02857em;border-radius:4px;transition:background-color .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-radius .25s cubic-bezier(.4,0,.2,1),transform .1s ease-in-out}.tng-button::-moz-focus-inner{padding:0;border:0}.tng-button:active{outline:none;transform:scale(.98)}.tng-button:hover{cursor:pointer}.tng-button:disabled{cursor:default;pointer-events:none;opacity:.5}.tng-button[hidden]{display:none}.tng-button .mdc-button__label{position:relative;z-index:1;display:inline-flex;align-items:center;gap:8px}.tng-button .tng-button__icon--left{margin-right:4px}.tng-button .tng-button__icon--right{margin-left:4px}.tng-button--rounded{border-radius:24px}.tng-button--soft{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-button--soft:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-1px)}.tng-button--primary{background-color:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-button--primary:hover{background-color:color-mix(in srgb,var(--tng-primary),white 10%)}.tng-button--secondary{background-color:var(--tng-secondary);color:var(--tng-secondary-contrast)}.tng-button--secondary:hover{background-color:color-mix(in srgb,var(--tng-secondary),white 10%)}.tng-button--success{background-color:var(--tng-success);color:#fff}.tng-button--success:hover{background-color:color-mix(in srgb,var(--tng-success),white 10%)}.tng-button--warning{background-color:var(--tng-warning);color:#fff}.tng-button--warning:hover{background-color:color-mix(in srgb,var(--tng-warning),white 10%)}.tng-button--error{background-color:var(--tng-error);color:#fff}.tng-button--error:hover{background-color:color-mix(in srgb,var(--tng-error),white 10%)}span.tng-ripple{position:absolute;border-radius:50%;transform:scale(0);animation:ripple .6s linear;background-color:#ffffff4d;pointer-events:none}@keyframes ripple{to{transform:scale(4);opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
36
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngButton, isStandalone: true, selector: "button[tngButton], a[tngButton]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, soft: { classPropertyName: "soft", publicName: "soft", isSignal: true, isRequired: false, transformFunction: null }, ripple: { classPropertyName: "ripple", publicName: "ripple", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "createRipple($event)" }, properties: { "class.tng-button--primary": "variant() === \"primary\"", "class.tng-button--secondary": "variant() === \"secondary\"", "class.tng-button--success": "variant() === \"success\"", "class.tng-button--warning": "variant() === \"warning\"", "class.tng-button--error": "variant() === \"error\"", "class.tng-button--rounded": "rounded()", "class.tng-button--soft": "soft()" }, classAttribute: "tng-button" }, exportAs: ["tngButton"], ngImport: i0, template: "<span class=\"tng-button__label\">\n @if (icon() && iconPosition() === 'left') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--left\"></i>\n }\n <ng-content></ng-content>\n @if (icon() && iconPosition() === 'right') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--right\"></i>\n }\n</span>\n\n", styles: [".tng-button{position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;height:32px;border:none;outline:none;line-height:inherit;appearance:none;-webkit-appearance:none;overflow:hidden;vertical-align:middle;background:transparent;color:var(--tng-text);padding:0 16px;font-family:inherit;font-size:.875rem;font-weight:500;letter-spacing:.02857em;border-radius:4px;transition:background-color .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-radius .25s cubic-bezier(.4,0,.2,1),transform .1s ease-in-out}.tng-button::-moz-focus-inner{padding:0;border:0}.tng-button:active{outline:none;transform:scale(.98)}.tng-button:hover{cursor:pointer}.tng-button:disabled{cursor:default;pointer-events:none;opacity:.5}.tng-button[hidden]{display:none}.tng-button .mdc-button__label{position:relative;z-index:1;display:inline-flex;align-items:center;gap:8px}.tng-button .tng-button__icon--left{margin-right:4px}.tng-button .tng-button__icon--right{margin-left:4px}.tng-button--rounded{border-radius:24px}.tng-button--soft{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-button--soft:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-1px)}.tng-button--primary{background:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-button--primary:hover{background:color-mix(in srgb,var(--tng-primary),white 10%)}.tng-button--secondary{background:var(--tng-secondary);color:var(--tng-secondary-contrast)}.tng-button--secondary:hover{background:color-mix(in srgb,var(--tng-secondary),white 10%)}.tng-button--success{background:var(--tng-success);color:#fff}.tng-button--success:hover{background:color-mix(in srgb,var(--tng-success),white 10%)}.tng-button--warning{background:var(--tng-warning);color:#fff}.tng-button--warning:hover{background:color-mix(in srgb,var(--tng-warning),white 10%)}.tng-button--error{background:var(--tng-error);color:#fff}.tng-button--error:hover{background:color-mix(in srgb,var(--tng-error),white 10%)}span.tng-ripple{position:absolute;border-radius:50%;transform:scale(0);animation:ripple .6s linear;background-color:#ffffff4d;pointer-events:none}@keyframes ripple{to{transform:scale(4);opacity:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
34
37
  }
35
38
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngButton, decorators: [{
36
39
  type: Component,
@@ -44,7 +47,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
44
47
  '[class.tng-button--rounded]': 'rounded()',
45
48
  '[class.tng-button--soft]': 'soft()',
46
49
  '(click)': 'createRipple($event)',
47
- }, exportAs: 'tngButton', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"tng-button__label\">\n @if (icon() && iconPosition() === 'left') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--left\"></i>\n }\n <ng-content></ng-content>\n @if (icon() && iconPosition() === 'right') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--right\"></i>\n }\n</span>\n\n", styles: [".tng-button{position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;height:32px;border:none;outline:none;line-height:inherit;-webkit-appearance:none;overflow:hidden;vertical-align:middle;background:transparent;padding:0 16px;font-family:inherit;font-size:.875rem;font-weight:500;letter-spacing:.02857em;border-radius:4px;transition:background-color .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-radius .25s cubic-bezier(.4,0,.2,1),transform .1s ease-in-out}.tng-button::-moz-focus-inner{padding:0;border:0}.tng-button:active{outline:none;transform:scale(.98)}.tng-button:hover{cursor:pointer}.tng-button:disabled{cursor:default;pointer-events:none;opacity:.5}.tng-button[hidden]{display:none}.tng-button .mdc-button__label{position:relative;z-index:1;display:inline-flex;align-items:center;gap:8px}.tng-button .tng-button__icon--left{margin-right:4px}.tng-button .tng-button__icon--right{margin-left:4px}.tng-button--rounded{border-radius:24px}.tng-button--soft{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-button--soft:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-1px)}.tng-button--primary{background-color:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-button--primary:hover{background-color:color-mix(in srgb,var(--tng-primary),white 10%)}.tng-button--secondary{background-color:var(--tng-secondary);color:var(--tng-secondary-contrast)}.tng-button--secondary:hover{background-color:color-mix(in srgb,var(--tng-secondary),white 10%)}.tng-button--success{background-color:var(--tng-success);color:#fff}.tng-button--success:hover{background-color:color-mix(in srgb,var(--tng-success),white 10%)}.tng-button--warning{background-color:var(--tng-warning);color:#fff}.tng-button--warning:hover{background-color:color-mix(in srgb,var(--tng-warning),white 10%)}.tng-button--error{background-color:var(--tng-error);color:#fff}.tng-button--error:hover{background-color:color-mix(in srgb,var(--tng-error),white 10%)}span.tng-ripple{position:absolute;border-radius:50%;transform:scale(0);animation:ripple .6s linear;background-color:#ffffff4d;pointer-events:none}@keyframes ripple{to{transform:scale(4);opacity:0}}\n"] }]
50
+ }, exportAs: 'tngButton', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"tng-button__label\">\n @if (icon() && iconPosition() === 'left') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--left\"></i>\n }\n <ng-content></ng-content>\n @if (icon() && iconPosition() === 'right') {\n <i [class]=\"icon()\" class=\"tng-button__icon tng-button__icon--right\"></i>\n }\n</span>\n\n", styles: [".tng-button{position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;height:32px;border:none;outline:none;line-height:inherit;appearance:none;-webkit-appearance:none;overflow:hidden;vertical-align:middle;background:transparent;color:var(--tng-text);padding:0 16px;font-family:inherit;font-size:.875rem;font-weight:500;letter-spacing:.02857em;border-radius:4px;transition:background-color .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),border-radius .25s cubic-bezier(.4,0,.2,1),transform .1s ease-in-out}.tng-button::-moz-focus-inner{padding:0;border:0}.tng-button:active{outline:none;transform:scale(.98)}.tng-button:hover{cursor:pointer}.tng-button:disabled{cursor:default;pointer-events:none;opacity:.5}.tng-button[hidden]{display:none}.tng-button .mdc-button__label{position:relative;z-index:1;display:inline-flex;align-items:center;gap:8px}.tng-button .tng-button__icon--left{margin-right:4px}.tng-button .tng-button__icon--right{margin-left:4px}.tng-button--rounded{border-radius:24px}.tng-button--soft{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-button--soft:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-1px)}.tng-button--primary{background:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-button--primary:hover{background:color-mix(in srgb,var(--tng-primary),white 10%)}.tng-button--secondary{background:var(--tng-secondary);color:var(--tng-secondary-contrast)}.tng-button--secondary:hover{background:color-mix(in srgb,var(--tng-secondary),white 10%)}.tng-button--success{background:var(--tng-success);color:#fff}.tng-button--success:hover{background:color-mix(in srgb,var(--tng-success),white 10%)}.tng-button--warning{background:var(--tng-warning);color:#fff}.tng-button--warning:hover{background:color-mix(in srgb,var(--tng-warning),white 10%)}.tng-button--error{background:var(--tng-error);color:#fff}.tng-button--error:hover{background:color-mix(in srgb,var(--tng-error),white 10%)}span.tng-ripple{position:absolute;border-radius:50%;transform:scale(0);animation:ripple .6s linear;background-color:#ffffff4d;pointer-events:none}@keyframes ripple{to{transform:scale(4);opacity:0}}\n"] }]
48
51
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], soft: [{ type: i0.Input, args: [{ isSignal: true, alias: "soft", required: false }] }], ripple: [{ type: i0.Input, args: [{ isSignal: true, alias: "ripple", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }] } });
49
52
 
50
53
  class TngCardComponent {
@@ -56,7 +59,7 @@ class TngCardComponent {
56
59
  image = input(null, ...(ngDevMode ? [{ debugName: "image" }] : []));
57
60
  imageAlt = input('Card image', ...(ngDevMode ? [{ debugName: "imageAlt" }] : []));
58
61
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
59
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngCardComponent, isStandalone: true, selector: "tng-card", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, elevated: { classPropertyName: "elevated", publicName: "elevated", isSignal: true, isRequired: false, transformFunction: null }, outlined: { classPropertyName: "outlined", publicName: "outlined", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.tng-card--primary": "variant() === \"primary\"", "class.tng-card--secondary": "variant() === \"secondary\"", "class.tng-card--success": "variant() === \"success\"", "class.tng-card--warning": "variant() === \"warning\"", "class.tng-card--error": "variant() === \"error\"", "class.tng-card--elevated": "elevated()", "class.tng-card--outlined": "outlined()" }, classAttribute: "tng-card" }, ngImport: i0, template: "<div class=\"tng-card__container\">\n @if (image()) {\n <div class=\"tng-card__image\">\n <img [src]=\"image()\" [alt]=\"imageAlt()\" />\n </div>\n }\n\n @if (title() || subtitle()) {\n <div class=\"tng-card__header\">\n <ng-content select=\"[card-header]\"></ng-content>\n \n @if (!title() && !subtitle()) {\n <!-- Header projection only -->\n } @else {\n <div class=\"tng-card__header-text\">\n @if (title()) {\n <h3 class=\"tng-card__title\">{{ title() }}</h3>\n }\n @if (subtitle()) {\n <p class=\"tng-card__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"tng-card__content\">\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-card__footer\">\n <ng-content select=\"[card-footer]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-card{display:block;position:relative;background-color:#fff;border-radius:8px;overflow:hidden;transition:box-shadow .3s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tng-card__container{display:flex;flex-direction:column;height:100%}.tng-card__image{width:100%;overflow:hidden}.tng-card__image img{width:100%;height:auto;display:block;object-fit:cover}.tng-card__header{padding:16px 20px;border-bottom:1px solid rgba(0,0,0,.08)}.tng-card__header-text{display:flex;flex-direction:column;gap:4px}.tng-card__title{margin:0;font-size:1.25rem;font-weight:500;color:var(--tng-text, #333);line-height:1.4}.tng-card__subtitle{margin:0;font-size:.875rem;color:var(--tng-text-secondary, #666);line-height:1.5}.tng-card__content{padding:20px;flex:1;color:var(--tng-text, #333)}.tng-card__footer{padding:12px 20px;border-top:1px solid rgba(0,0,0,.08)}.tng-card__footer:empty{display:none}.tng-card--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-card--elevated:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-2px)}.tng-card--outlined{border:1px solid rgba(0,0,0,.12);box-shadow:none}.tng-card--outlined:hover{border-color:#0000003d}.tng-card--primary .tng-card__header{background-color:var(--tng-primary);color:var(--tng-primary-contrast);border-bottom-color:#ffffff1f}.tng-card--primary .tng-card__title,.tng-card--primary .tng-card__subtitle{color:inherit}.tng-card--secondary .tng-card__header{background-color:var(--tng-secondary);color:var(--tng-secondary-contrast);border-bottom-color:#ffffff1f}.tng-card--secondary .tng-card__title,.tng-card--secondary .tng-card__subtitle{color:inherit}.tng-card--success .tng-card__header{background-color:var(--tng-success);color:#fff;border-bottom-color:#ffffff1f}.tng-card--success .tng-card__title,.tng-card--success .tng-card__subtitle{color:inherit}.tng-card--warning .tng-card__header{background-color:var(--tng-warning);color:#fff;border-bottom-color:#ffffff1f}.tng-card--warning .tng-card__title,.tng-card--warning .tng-card__subtitle{color:inherit}.tng-card--error .tng-card__header{background-color:var(--tng-error);color:#fff;border-bottom-color:#ffffff1f}.tng-card--error .tng-card__title,.tng-card--error .tng-card__subtitle{color:inherit}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
62
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngCardComponent, isStandalone: true, selector: "tng-card", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, elevated: { classPropertyName: "elevated", publicName: "elevated", isSignal: true, isRequired: false, transformFunction: null }, outlined: { classPropertyName: "outlined", publicName: "outlined", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.tng-card--primary": "variant() === \"primary\"", "class.tng-card--secondary": "variant() === \"secondary\"", "class.tng-card--success": "variant() === \"success\"", "class.tng-card--warning": "variant() === \"warning\"", "class.tng-card--error": "variant() === \"error\"", "class.tng-card--elevated": "elevated()", "class.tng-card--outlined": "outlined()" }, classAttribute: "tng-card" }, ngImport: i0, template: "<div class=\"tng-card__container\">\n @if (image()) {\n <div class=\"tng-card__image\">\n <img [src]=\"image()\" [alt]=\"imageAlt()\" />\n </div>\n }\n\n @if (title() || subtitle()) {\n <div class=\"tng-card__header\">\n <ng-content select=\"[card-header]\"></ng-content>\n \n @if (!title() && !subtitle()) {\n <!-- Header projection only -->\n } @else {\n <div class=\"tng-card__header-text\">\n @if (title()) {\n <h3 class=\"tng-card__title\">{{ title() }}</h3>\n }\n @if (subtitle()) {\n <p class=\"tng-card__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"tng-card__content\">\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-card__footer\">\n <ng-content select=\"[card-footer]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-card{display:block;position:relative;background-color:#fff;border-radius:8px;overflow:hidden;transition:box-shadow .3s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tng-card__container{display:flex;flex-direction:column;height:100%}.tng-card__image{width:100%;overflow:hidden}.tng-card__image img{width:100%;height:auto;display:block;object-fit:cover}.tng-card__header{padding:16px 20px;border-bottom:1px solid rgba(0,0,0,.08)}.tng-card__header-text{display:flex;flex-direction:column;gap:4px}.tng-card__title{margin:0;font-size:1.25rem;font-weight:500;color:var(--tng-text, #333);line-height:1.4}.tng-card__subtitle{margin:0;font-size:.875rem;color:var(--tng-text-secondary, #666);line-height:1.5}.tng-card__content{padding:20px;flex:1;color:var(--tng-text, #333)}.tng-card__footer{padding:12px 20px;border-top:1px solid rgba(0,0,0,.08)}.tng-card__footer:empty{display:none}.tng-card--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-card--elevated:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-2px)}.tng-card--outlined{border:1px solid rgba(0,0,0,.12);box-shadow:none}.tng-card--outlined:hover{border-color:#0000003d}.tng-card--primary .tng-card__header{background:var(--tng-primary);color:var(--tng-primary-contrast);border-bottom-color:#ffffff1f}.tng-card--primary .tng-card__title,.tng-card--primary .tng-card__subtitle{color:inherit}.tng-card--secondary .tng-card__header{background:var(--tng-secondary);color:var(--tng-secondary-contrast);border-bottom-color:#ffffff1f}.tng-card--secondary .tng-card__title,.tng-card--secondary .tng-card__subtitle{color:inherit}.tng-card--success .tng-card__header{background:var(--tng-success);color:#fff;border-bottom-color:#ffffff1f}.tng-card--success .tng-card__title,.tng-card--success .tng-card__subtitle{color:inherit}.tng-card--warning .tng-card__header{background:var(--tng-warning);color:#fff;border-bottom-color:#ffffff1f}.tng-card--warning .tng-card__title,.tng-card--warning .tng-card__subtitle{color:inherit}.tng-card--error .tng-card__header{background:var(--tng-error);color:#fff;border-bottom-color:#ffffff1f}.tng-card--error .tng-card__title,.tng-card--error .tng-card__subtitle{color:inherit}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
60
63
  }
61
64
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngCardComponent, decorators: [{
62
65
  type: Component,
@@ -69,7 +72,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
69
72
  '[class.tng-card--error]': 'variant() === "error"',
70
73
  '[class.tng-card--elevated]': 'elevated()',
71
74
  '[class.tng-card--outlined]': 'outlined()',
72
- }, template: "<div class=\"tng-card__container\">\n @if (image()) {\n <div class=\"tng-card__image\">\n <img [src]=\"image()\" [alt]=\"imageAlt()\" />\n </div>\n }\n\n @if (title() || subtitle()) {\n <div class=\"tng-card__header\">\n <ng-content select=\"[card-header]\"></ng-content>\n \n @if (!title() && !subtitle()) {\n <!-- Header projection only -->\n } @else {\n <div class=\"tng-card__header-text\">\n @if (title()) {\n <h3 class=\"tng-card__title\">{{ title() }}</h3>\n }\n @if (subtitle()) {\n <p class=\"tng-card__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"tng-card__content\">\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-card__footer\">\n <ng-content select=\"[card-footer]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-card{display:block;position:relative;background-color:#fff;border-radius:8px;overflow:hidden;transition:box-shadow .3s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tng-card__container{display:flex;flex-direction:column;height:100%}.tng-card__image{width:100%;overflow:hidden}.tng-card__image img{width:100%;height:auto;display:block;object-fit:cover}.tng-card__header{padding:16px 20px;border-bottom:1px solid rgba(0,0,0,.08)}.tng-card__header-text{display:flex;flex-direction:column;gap:4px}.tng-card__title{margin:0;font-size:1.25rem;font-weight:500;color:var(--tng-text, #333);line-height:1.4}.tng-card__subtitle{margin:0;font-size:.875rem;color:var(--tng-text-secondary, #666);line-height:1.5}.tng-card__content{padding:20px;flex:1;color:var(--tng-text, #333)}.tng-card__footer{padding:12px 20px;border-top:1px solid rgba(0,0,0,.08)}.tng-card__footer:empty{display:none}.tng-card--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-card--elevated:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-2px)}.tng-card--outlined{border:1px solid rgba(0,0,0,.12);box-shadow:none}.tng-card--outlined:hover{border-color:#0000003d}.tng-card--primary .tng-card__header{background-color:var(--tng-primary);color:var(--tng-primary-contrast);border-bottom-color:#ffffff1f}.tng-card--primary .tng-card__title,.tng-card--primary .tng-card__subtitle{color:inherit}.tng-card--secondary .tng-card__header{background-color:var(--tng-secondary);color:var(--tng-secondary-contrast);border-bottom-color:#ffffff1f}.tng-card--secondary .tng-card__title,.tng-card--secondary .tng-card__subtitle{color:inherit}.tng-card--success .tng-card__header{background-color:var(--tng-success);color:#fff;border-bottom-color:#ffffff1f}.tng-card--success .tng-card__title,.tng-card--success .tng-card__subtitle{color:inherit}.tng-card--warning .tng-card__header{background-color:var(--tng-warning);color:#fff;border-bottom-color:#ffffff1f}.tng-card--warning .tng-card__title,.tng-card--warning .tng-card__subtitle{color:inherit}.tng-card--error .tng-card__header{background-color:var(--tng-error);color:#fff;border-bottom-color:#ffffff1f}.tng-card--error .tng-card__title,.tng-card--error .tng-card__subtitle{color:inherit}\n"] }]
75
+ }, template: "<div class=\"tng-card__container\">\n @if (image()) {\n <div class=\"tng-card__image\">\n <img [src]=\"image()\" [alt]=\"imageAlt()\" />\n </div>\n }\n\n @if (title() || subtitle()) {\n <div class=\"tng-card__header\">\n <ng-content select=\"[card-header]\"></ng-content>\n \n @if (!title() && !subtitle()) {\n <!-- Header projection only -->\n } @else {\n <div class=\"tng-card__header-text\">\n @if (title()) {\n <h3 class=\"tng-card__title\">{{ title() }}</h3>\n }\n @if (subtitle()) {\n <p class=\"tng-card__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"tng-card__content\">\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-card__footer\">\n <ng-content select=\"[card-footer]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-card{display:block;position:relative;background-color:#fff;border-radius:8px;overflow:hidden;transition:box-shadow .3s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.tng-card__container{display:flex;flex-direction:column;height:100%}.tng-card__image{width:100%;overflow:hidden}.tng-card__image img{width:100%;height:auto;display:block;object-fit:cover}.tng-card__header{padding:16px 20px;border-bottom:1px solid rgba(0,0,0,.08)}.tng-card__header-text{display:flex;flex-direction:column;gap:4px}.tng-card__title{margin:0;font-size:1.25rem;font-weight:500;color:var(--tng-text, #333);line-height:1.4}.tng-card__subtitle{margin:0;font-size:.875rem;color:var(--tng-text-secondary, #666);line-height:1.5}.tng-card__content{padding:20px;flex:1;color:var(--tng-text, #333)}.tng-card__footer{padding:12px 20px;border-top:1px solid rgba(0,0,0,.08)}.tng-card__footer:empty{display:none}.tng-card--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-card--elevated:hover{box-shadow:0 5px 5px -3px #0000001a,0 8px 10px 1px #00000012,0 3px 14px 2px #0000000f;transform:translateY(-2px)}.tng-card--outlined{border:1px solid rgba(0,0,0,.12);box-shadow:none}.tng-card--outlined:hover{border-color:#0000003d}.tng-card--primary .tng-card__header{background:var(--tng-primary);color:var(--tng-primary-contrast);border-bottom-color:#ffffff1f}.tng-card--primary .tng-card__title,.tng-card--primary .tng-card__subtitle{color:inherit}.tng-card--secondary .tng-card__header{background:var(--tng-secondary);color:var(--tng-secondary-contrast);border-bottom-color:#ffffff1f}.tng-card--secondary .tng-card__title,.tng-card--secondary .tng-card__subtitle{color:inherit}.tng-card--success .tng-card__header{background:var(--tng-success);color:#fff;border-bottom-color:#ffffff1f}.tng-card--success .tng-card__title,.tng-card--success .tng-card__subtitle{color:inherit}.tng-card--warning .tng-card__header{background:var(--tng-warning);color:#fff;border-bottom-color:#ffffff1f}.tng-card--warning .tng-card__title,.tng-card--warning .tng-card__subtitle{color:inherit}.tng-card--error .tng-card__header{background:var(--tng-error);color:#fff;border-bottom-color:#ffffff1f}.tng-card--error .tng-card__title,.tng-card--error .tng-card__subtitle{color:inherit}\n"] }]
73
76
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], elevated: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevated", required: false }] }], outlined: [{ type: i0.Input, args: [{ isSignal: true, alias: "outlined", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }] } });
74
77
 
75
78
  class TecnualInputComponent {
@@ -311,13 +314,13 @@ class TecnualDatepickerComponent {
311
314
  }
312
315
  }
313
316
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TecnualDatepickerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
314
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: TecnualDatepickerComponent, isStandalone: true, selector: "tng-datepicker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
317
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TecnualDatepickerComponent, isStandalone: true, selector: "tng-datepicker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
315
318
  {
316
319
  provide: NG_VALUE_ACCESSOR,
317
320
  useExisting: forwardRef(() => TecnualDatepickerComponent),
318
321
  multi: true
319
322
  }
320
- ], ngImport: i0, template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar()\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <div class=\"tng-input-display\">\n {{ formattedValue || (isOpen() ? placeholder() : '') }}\n </div>\n <span class=\"material-icons tng-icon\">calendar_today</span>\n </div>\n\n <!-- Calendar Popup -->\n <div class=\"tng-calendar-popup\" *ngIf=\"isOpen()\">\n <div class=\"tng-calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth($event)\">\n <span class=\"material-icons\">chevron_left</span>\n </button>\n <span class=\"current-month\">{{ currentMonthYear }}</span>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth($event)\">\n <span class=\"material-icons\">chevron_right</span>\n </button>\n </div>\n\n <div class=\"tng-calendar-grid\">\n <div class=\"day-name\" *ngFor=\"let day of daysOfWeek\">{{ day }}</div>\n <div\n class=\"day-cell\"\n *ngFor=\"let date of calendarDays()\"\n [class.not-current-month]=\"!isCurrentMonth(date)\"\n [class.today]=\"isToday(date)\"\n [class.selected]=\"isSelected(date)\"\n [class.in-range]=\"isInRange(date)\"\n [class.range-start]=\"mode() === 'range' && isSameDay(date, rangeValue.start)\"\n [class.range-end]=\"mode() === 'range' && isSameDay(date, rangeValue.end)\"\n [class.disabled]=\"isDisabled(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif);position:relative}.tng-datepicker-container{position:relative}.tng-datepicker-container.disabled{opacity:.6;pointer-events:none}.tng-datepicker-container.disabled .tng-fieldset{border-color:var(--tng-border, #ccc);background-color:var(--tng-background, #f9f9f9)}.tng-input-trigger{position:relative;border-radius:var(--tng-border-radius, 4px);padding:0 16px;height:48px;display:flex;align-items:center;cursor:pointer}.tng-input-trigger:hover .tng-fieldset{border-color:color-mix(in srgb,var(--tng-border, #999),black 20%)}.tng-fieldset{position:absolute;inset:0 0 5px;margin:0;padding:0 12px;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);pointer-events:none;transition:border-color .2s ease}.tng-legend{width:auto;max-width:0;height:11px;font-size:.75em;visibility:hidden;white-space:nowrap;padding-inline:0px}.tng-legend span{padding:0 2px;visibility:visible;opacity:0}.tng-label{position:absolute;top:50%;left:16px;transform:translateY(-50%);color:var(--tng-text-secondary, #666);font-size:16px;font-weight:400;pointer-events:none;transform-origin:left top;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease}.tng-input-display{flex:1;font-size:16px;color:var(--tng-text, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.tng-icon{color:var(--tng-text-secondary, #666);font-size:20px;margin-left:8px}.tng-datepicker-container.focused .tng-fieldset,.tng-datepicker-container.has-value .tng-fieldset{border-color:var(--tng-primary, #6200ee);border-width:2px}.tng-datepicker-container.focused .tng-label,.tng-datepicker-container.has-value .tng-label{color:var(--tng-primary, #6200ee);transform:translateY(-24px) scale(.75)}.tng-datepicker-container.focused .tng-legend,.tng-datepicker-container.has-value .tng-legend{max-width:100%}.tng-datepicker-container.focused .tng-label{color:var(--tng-primary, #6200ee)}.tng-calendar-popup{position:absolute;top:100%;left:0;z-index:1000;margin-top:4px;background:var(--tng-surface, #fff);border-radius:8px;box-shadow:var(--tng-shadow-md, 0 4px 20px rgba(0, 0, 0, .15));padding:16px;width:300px;animation:fadeIn .2s ease;border:1px solid var(--tng-border, #eee)}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.tng-calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.tng-calendar-header .current-month{font-weight:600;font-size:16px;color:var(--tng-text, #333)}.tng-calendar-header .nav-btn{background:none;border:none;cursor:pointer;padding:4px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--tng-text-secondary, #666)}.tng-calendar-header .nav-btn:hover{background-color:var(--tng-background, #f5f5f5)}.tng-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}.day-name{font-size:12px;color:var(--tng-text-secondary, #666);font-weight:500;margin-bottom:8px}.day-cell{height:36px;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:50%;transition:all .2s ease;position:relative;color:var(--tng-text, #333)}.day-cell:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end){background-color:var(--tng-background, #f5f5f5)}.day-cell.not-current-month{color:#ccc}.day-cell.today{font-weight:600;color:var(--tng-primary, #6200ee);border:1px solid var(--tng-primary, #6200ee)}.day-cell.selected,.day-cell.range-start,.day-cell.range-end{background-color:var(--tng-primary, #6200ee);color:var(--tng-primary-contrast, #fff)}.day-cell.selected.today,.day-cell.range-start.today,.day-cell.range-end.today{border-color:transparent}.day-cell.in-range{background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);border-radius:0;color:var(--tng-primary, #6200ee)}.day-cell.in-range.range-start{border-top-right-radius:0;border-bottom-right-radius:0}.day-cell.in-range.range-end{border-top-left-radius:0;border-bottom-left-radius:0}.day-cell.range-start{border-radius:50% 0 0 50%;position:relative}.day-cell.range-start:after{content:\"\";position:absolute;inset:0 0 0 50%;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.range-end{border-radius:0 50% 50% 0;position:relative}.day-cell.range-end:after{content:\"\";position:absolute;inset:0 50% 0 0;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.selected{border-radius:50%}.day-cell.disabled{opacity:.3;pointer-events:none;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }] });
323
+ ], ngImport: i0, template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar()\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <div class=\"tng-input-display\">\n {{ formattedValue || (isOpen() ? placeholder() : '') }}\n </div>\n <span class=\"material-icons tng-icon\">calendar_today</span>\n </div>\n\n <!-- Calendar Popup -->\n @if (isOpen()) {\n <div class=\"tng-calendar-popup\">\n <div class=\"tng-calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth($event)\">\n <span class=\"material-icons\">chevron_left</span>\n </button>\n <span class=\"current-month\">{{ currentMonthYear }}</span>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth($event)\">\n <span class=\"material-icons\">chevron_right</span>\n </button>\n </div>\n\n <div class=\"tng-calendar-grid\">\n @for (day of daysOfWeek; track day) {\n <div class=\"day-name\">{{ day }}</div>\n }\n @for (date of calendarDays(); track date.getTime()) {\n <div\n class=\"day-cell\"\n [class.not-current-month]=\"!isCurrentMonth(date)\"\n [class.today]=\"isToday(date)\"\n [class.selected]=\"isSelected(date)\"\n [class.in-range]=\"isInRange(date)\"\n [class.range-start]=\"mode() === 'range' && isSameDay(date, rangeValue.start)\"\n [class.range-end]=\"mode() === 'range' && isSameDay(date, rangeValue.end)\"\n [class.disabled]=\"isDisabled(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif);position:relative}.tng-datepicker-container{position:relative}.tng-datepicker-container.disabled{opacity:.6;pointer-events:none}.tng-datepicker-container.disabled .tng-fieldset{border-color:var(--tng-border, #ccc);background-color:var(--tng-background, #f9f9f9)}.tng-input-trigger{position:relative;border-radius:var(--tng-border-radius, 4px);padding:0 16px;height:48px;display:flex;align-items:center;cursor:pointer}.tng-input-trigger:hover .tng-fieldset{border-color:color-mix(in srgb,var(--tng-border, #999),black 20%)}.tng-fieldset{position:absolute;inset:0 0 5px;margin:0;padding:0 12px;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);pointer-events:none;transition:border-color .2s ease}.tng-legend{width:auto;max-width:0;height:11px;font-size:.75em;visibility:hidden;white-space:nowrap;padding-inline:0px}.tng-legend span{padding:0 2px;visibility:visible;opacity:0}.tng-label{position:absolute;top:50%;left:16px;transform:translateY(-50%);color:var(--tng-text-secondary, #666);font-size:16px;font-weight:400;pointer-events:none;transform-origin:left top;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease}.tng-input-display{flex:1;font-size:16px;color:var(--tng-text, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.tng-icon{color:var(--tng-text-secondary, #666);font-size:20px;margin-left:8px}.tng-datepicker-container.focused .tng-fieldset,.tng-datepicker-container.has-value .tng-fieldset{border-color:var(--tng-primary, #6200ee);border-width:2px}.tng-datepicker-container.focused .tng-label,.tng-datepicker-container.has-value .tng-label{color:var(--tng-primary, #6200ee);transform:translateY(-24px) scale(.75)}.tng-datepicker-container.focused .tng-legend,.tng-datepicker-container.has-value .tng-legend{max-width:100%}.tng-datepicker-container.focused .tng-label{color:var(--tng-primary, #6200ee)}.tng-calendar-popup{position:absolute;top:100%;left:0;z-index:1000;margin-top:4px;background:var(--tng-surface, #fff);border-radius:8px;box-shadow:var(--tng-shadow-md, 0 4px 20px rgba(0, 0, 0, .15));padding:16px;width:300px;animation:fadeIn .2s ease;border:1px solid var(--tng-border, #eee)}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.tng-calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.tng-calendar-header .current-month{font-weight:600;font-size:16px;color:var(--tng-text, #333)}.tng-calendar-header .nav-btn{background:none;border:none;cursor:pointer;padding:4px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--tng-text-secondary, #666)}.tng-calendar-header .nav-btn:hover{background-color:var(--tng-background, #f5f5f5)}.tng-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}.day-name{font-size:12px;color:var(--tng-text-secondary, #666);font-weight:500;margin-bottom:8px}.day-cell{height:36px;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:50%;transition:all .2s ease;position:relative;color:var(--tng-text, #333)}.day-cell:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end){background-color:var(--tng-background, #f5f5f5)}.day-cell.not-current-month{color:#ccc}.day-cell.today{font-weight:600;color:var(--tng-primary, #6200ee);border:1px solid var(--tng-primary, #6200ee)}.day-cell.selected,.day-cell.range-start,.day-cell.range-end{background-color:var(--tng-primary, #6200ee);color:var(--tng-primary-contrast, #fff)}.day-cell.selected.today,.day-cell.range-start.today,.day-cell.range-end.today{border-color:transparent}.day-cell.in-range{background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);border-radius:0;color:var(--tng-primary, #6200ee)}.day-cell.in-range.range-start{border-top-right-radius:0;border-bottom-right-radius:0}.day-cell.in-range.range-end{border-top-left-radius:0;border-bottom-left-radius:0}.day-cell.range-start{border-radius:50% 0 0 50%;position:relative}.day-cell.range-start:after{content:\"\";position:absolute;inset:0 0 0 50%;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.range-end{border-radius:0 50% 50% 0;position:relative}.day-cell.range-end:after{content:\"\";position:absolute;inset:0 50% 0 0;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.selected{border-radius:50%}.day-cell.disabled{opacity:.3;pointer-events:none;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }] });
321
324
  }
322
325
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TecnualDatepickerComponent, decorators: [{
323
326
  type: Component,
@@ -327,7 +330,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
327
330
  useExisting: forwardRef(() => TecnualDatepickerComponent),
328
331
  multi: true
329
332
  }
330
- ], template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar()\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <div class=\"tng-input-display\">\n {{ formattedValue || (isOpen() ? placeholder() : '') }}\n </div>\n <span class=\"material-icons tng-icon\">calendar_today</span>\n </div>\n\n <!-- Calendar Popup -->\n <div class=\"tng-calendar-popup\" *ngIf=\"isOpen()\">\n <div class=\"tng-calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth($event)\">\n <span class=\"material-icons\">chevron_left</span>\n </button>\n <span class=\"current-month\">{{ currentMonthYear }}</span>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth($event)\">\n <span class=\"material-icons\">chevron_right</span>\n </button>\n </div>\n\n <div class=\"tng-calendar-grid\">\n <div class=\"day-name\" *ngFor=\"let day of daysOfWeek\">{{ day }}</div>\n <div\n class=\"day-cell\"\n *ngFor=\"let date of calendarDays()\"\n [class.not-current-month]=\"!isCurrentMonth(date)\"\n [class.today]=\"isToday(date)\"\n [class.selected]=\"isSelected(date)\"\n [class.in-range]=\"isInRange(date)\"\n [class.range-start]=\"mode() === 'range' && isSameDay(date, rangeValue.start)\"\n [class.range-end]=\"mode() === 'range' && isSameDay(date, rangeValue.end)\"\n [class.disabled]=\"isDisabled(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif);position:relative}.tng-datepicker-container{position:relative}.tng-datepicker-container.disabled{opacity:.6;pointer-events:none}.tng-datepicker-container.disabled .tng-fieldset{border-color:var(--tng-border, #ccc);background-color:var(--tng-background, #f9f9f9)}.tng-input-trigger{position:relative;border-radius:var(--tng-border-radius, 4px);padding:0 16px;height:48px;display:flex;align-items:center;cursor:pointer}.tng-input-trigger:hover .tng-fieldset{border-color:color-mix(in srgb,var(--tng-border, #999),black 20%)}.tng-fieldset{position:absolute;inset:0 0 5px;margin:0;padding:0 12px;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);pointer-events:none;transition:border-color .2s ease}.tng-legend{width:auto;max-width:0;height:11px;font-size:.75em;visibility:hidden;white-space:nowrap;padding-inline:0px}.tng-legend span{padding:0 2px;visibility:visible;opacity:0}.tng-label{position:absolute;top:50%;left:16px;transform:translateY(-50%);color:var(--tng-text-secondary, #666);font-size:16px;font-weight:400;pointer-events:none;transform-origin:left top;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease}.tng-input-display{flex:1;font-size:16px;color:var(--tng-text, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.tng-icon{color:var(--tng-text-secondary, #666);font-size:20px;margin-left:8px}.tng-datepicker-container.focused .tng-fieldset,.tng-datepicker-container.has-value .tng-fieldset{border-color:var(--tng-primary, #6200ee);border-width:2px}.tng-datepicker-container.focused .tng-label,.tng-datepicker-container.has-value .tng-label{color:var(--tng-primary, #6200ee);transform:translateY(-24px) scale(.75)}.tng-datepicker-container.focused .tng-legend,.tng-datepicker-container.has-value .tng-legend{max-width:100%}.tng-datepicker-container.focused .tng-label{color:var(--tng-primary, #6200ee)}.tng-calendar-popup{position:absolute;top:100%;left:0;z-index:1000;margin-top:4px;background:var(--tng-surface, #fff);border-radius:8px;box-shadow:var(--tng-shadow-md, 0 4px 20px rgba(0, 0, 0, .15));padding:16px;width:300px;animation:fadeIn .2s ease;border:1px solid var(--tng-border, #eee)}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.tng-calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.tng-calendar-header .current-month{font-weight:600;font-size:16px;color:var(--tng-text, #333)}.tng-calendar-header .nav-btn{background:none;border:none;cursor:pointer;padding:4px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--tng-text-secondary, #666)}.tng-calendar-header .nav-btn:hover{background-color:var(--tng-background, #f5f5f5)}.tng-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}.day-name{font-size:12px;color:var(--tng-text-secondary, #666);font-weight:500;margin-bottom:8px}.day-cell{height:36px;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:50%;transition:all .2s ease;position:relative;color:var(--tng-text, #333)}.day-cell:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end){background-color:var(--tng-background, #f5f5f5)}.day-cell.not-current-month{color:#ccc}.day-cell.today{font-weight:600;color:var(--tng-primary, #6200ee);border:1px solid var(--tng-primary, #6200ee)}.day-cell.selected,.day-cell.range-start,.day-cell.range-end{background-color:var(--tng-primary, #6200ee);color:var(--tng-primary-contrast, #fff)}.day-cell.selected.today,.day-cell.range-start.today,.day-cell.range-end.today{border-color:transparent}.day-cell.in-range{background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);border-radius:0;color:var(--tng-primary, #6200ee)}.day-cell.in-range.range-start{border-top-right-radius:0;border-bottom-right-radius:0}.day-cell.in-range.range-end{border-top-left-radius:0;border-bottom-left-radius:0}.day-cell.range-start{border-radius:50% 0 0 50%;position:relative}.day-cell.range-start:after{content:\"\";position:absolute;inset:0 0 0 50%;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.range-end{border-radius:0 50% 50% 0;position:relative}.day-cell.range-end:after{content:\"\";position:absolute;inset:0 50% 0 0;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.selected{border-radius:50%}.day-cell.disabled{opacity:.3;pointer-events:none;cursor:not-allowed}\n"] }]
333
+ ], template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar()\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <div class=\"tng-input-display\">\n {{ formattedValue || (isOpen() ? placeholder() : '') }}\n </div>\n <span class=\"material-icons tng-icon\">calendar_today</span>\n </div>\n\n <!-- Calendar Popup -->\n @if (isOpen()) {\n <div class=\"tng-calendar-popup\">\n <div class=\"tng-calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth($event)\">\n <span class=\"material-icons\">chevron_left</span>\n </button>\n <span class=\"current-month\">{{ currentMonthYear }}</span>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth($event)\">\n <span class=\"material-icons\">chevron_right</span>\n </button>\n </div>\n\n <div class=\"tng-calendar-grid\">\n @for (day of daysOfWeek; track day) {\n <div class=\"day-name\">{{ day }}</div>\n }\n @for (date of calendarDays(); track date.getTime()) {\n <div\n class=\"day-cell\"\n [class.not-current-month]=\"!isCurrentMonth(date)\"\n [class.today]=\"isToday(date)\"\n [class.selected]=\"isSelected(date)\"\n [class.in-range]=\"isInRange(date)\"\n [class.range-start]=\"mode() === 'range' && isSameDay(date, rangeValue.start)\"\n [class.range-end]=\"mode() === 'range' && isSameDay(date, rangeValue.end)\"\n [class.disabled]=\"isDisabled(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif);position:relative}.tng-datepicker-container{position:relative}.tng-datepicker-container.disabled{opacity:.6;pointer-events:none}.tng-datepicker-container.disabled .tng-fieldset{border-color:var(--tng-border, #ccc);background-color:var(--tng-background, #f9f9f9)}.tng-input-trigger{position:relative;border-radius:var(--tng-border-radius, 4px);padding:0 16px;height:48px;display:flex;align-items:center;cursor:pointer}.tng-input-trigger:hover .tng-fieldset{border-color:color-mix(in srgb,var(--tng-border, #999),black 20%)}.tng-fieldset{position:absolute;inset:0 0 5px;margin:0;padding:0 12px;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);pointer-events:none;transition:border-color .2s ease}.tng-legend{width:auto;max-width:0;height:11px;font-size:.75em;visibility:hidden;white-space:nowrap;padding-inline:0px}.tng-legend span{padding:0 2px;visibility:visible;opacity:0}.tng-label{position:absolute;top:50%;left:16px;transform:translateY(-50%);color:var(--tng-text-secondary, #666);font-size:16px;font-weight:400;pointer-events:none;transform-origin:left top;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease}.tng-input-display{flex:1;font-size:16px;color:var(--tng-text, #333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:100%;display:flex;align-items:center}.tng-icon{color:var(--tng-text-secondary, #666);font-size:20px;margin-left:8px}.tng-datepicker-container.focused .tng-fieldset,.tng-datepicker-container.has-value .tng-fieldset{border-color:var(--tng-primary, #6200ee);border-width:2px}.tng-datepicker-container.focused .tng-label,.tng-datepicker-container.has-value .tng-label{color:var(--tng-primary, #6200ee);transform:translateY(-24px) scale(.75)}.tng-datepicker-container.focused .tng-legend,.tng-datepicker-container.has-value .tng-legend{max-width:100%}.tng-datepicker-container.focused .tng-label{color:var(--tng-primary, #6200ee)}.tng-calendar-popup{position:absolute;top:100%;left:0;z-index:1000;margin-top:4px;background:var(--tng-surface, #fff);border-radius:8px;box-shadow:var(--tng-shadow-md, 0 4px 20px rgba(0, 0, 0, .15));padding:16px;width:300px;animation:fadeIn .2s ease;border:1px solid var(--tng-border, #eee)}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.tng-calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.tng-calendar-header .current-month{font-weight:600;font-size:16px;color:var(--tng-text, #333)}.tng-calendar-header .nav-btn{background:none;border:none;cursor:pointer;padding:4px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--tng-text-secondary, #666)}.tng-calendar-header .nav-btn:hover{background-color:var(--tng-background, #f5f5f5)}.tng-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}.day-name{font-size:12px;color:var(--tng-text-secondary, #666);font-weight:500;margin-bottom:8px}.day-cell{height:36px;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:50%;transition:all .2s ease;position:relative;color:var(--tng-text, #333)}.day-cell:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end){background-color:var(--tng-background, #f5f5f5)}.day-cell.not-current-month{color:#ccc}.day-cell.today{font-weight:600;color:var(--tng-primary, #6200ee);border:1px solid var(--tng-primary, #6200ee)}.day-cell.selected,.day-cell.range-start,.day-cell.range-end{background-color:var(--tng-primary, #6200ee);color:var(--tng-primary-contrast, #fff)}.day-cell.selected.today,.day-cell.range-start.today,.day-cell.range-end.today{border-color:transparent}.day-cell.in-range{background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);border-radius:0;color:var(--tng-primary, #6200ee)}.day-cell.in-range.range-start{border-top-right-radius:0;border-bottom-right-radius:0}.day-cell.in-range.range-end{border-top-left-radius:0;border-bottom-left-radius:0}.day-cell.range-start{border-radius:50% 0 0 50%;position:relative}.day-cell.range-start:after{content:\"\";position:absolute;inset:0 0 0 50%;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.range-end{border-radius:0 50% 50% 0;position:relative}.day-cell.range-end:after{content:\"\";position:absolute;inset:0 50% 0 0;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),white 80%);z-index:-1}.day-cell.selected{border-radius:50%}.day-cell.disabled{opacity:.3;pointer-events:none;cursor:not-allowed}\n"] }]
331
334
  }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], onClickOutside: [{
332
335
  type: HostListener,
333
336
  args: ['document:click', ['$event']]
@@ -407,20 +410,20 @@ class TecnualTableComponent {
407
410
  this.onSearch(input.value);
408
411
  }
409
412
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TecnualTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
410
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: TecnualTableComponent, isStandalone: true, selector: "tng-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"tng-table-container\">\n <!-- Toolbar -->\n <div class=\"tng-table-toolbar\" *ngIf=\"filterable()\">\n <div class=\"tng-table-search\">\n <tng-input\n [placeholder]=\"'Search...'\"\n (input)=\"onSearchInput($event)\"\n ></tng-input>\n </div>\n </div>\n\n <!-- Table -->\n <div class=\"tng-table-wrapper\">\n <table class=\"tng-table\">\n <thead>\n <tr>\n <th \n *ngFor=\"let col of columns()\"\n [style.width]=\"col.width\"\n [class.sortable]=\"col.sortable\"\n (click)=\"onSort(col)\"\n >\n <div class=\"th-content\">\n {{ col.label }}\n <span class=\"sort-indicator\" *ngIf=\"sortColumn() === col.key\">\n {{ sortDirection() === 'asc' ? '\u2191' : '\u2193' }}\n </span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of paginatedData()\">\n <td *ngFor=\"let col of columns()\">\n <ng-container *ngIf=\"col.template; else defaultCell\">\n <ng-container *ngTemplateOutlet=\"col.template; context: { $implicit: row[col.key], row: row }\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n {{ row[col.key] }}\n </ng-template>\n </td>\n </tr>\n <tr *ngIf=\"paginatedData().length === 0\" class=\"no-data-row\">\n <td [attr.colspan]=\"columns().length\">\n No data found\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"tng-table-pagination\" *ngIf=\"totalPages() > 1\">\n <div class=\"pagination-info\">\n Page {{ currentPage() }} of {{ totalPages() }}\n </div>\n <div class=\"pagination-controls\">\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === 1\"\n (click)=\"setPage(currentPage() - 1)\"\n >\n \u2039\n </button>\n \n <ng-container *ngFor=\"let page of [].constructor(totalPages()); let i = index\">\n <!-- Show limited pages logic could go here, for now simple list -->\n <button \n *ngIf=\"i + 1 === currentPage() || i + 1 === 1 || i + 1 === totalPages() || (i + 1 >= currentPage() - 1 && i + 1 <= currentPage() + 1)\"\n class=\"tng-btn-page\"\n [class.active]=\"currentPage() === i + 1\"\n (click)=\"setPage(i + 1)\"\n >\n {{ i + 1 }}\n </button>\n <span *ngIf=\"(i + 1 === 2 && currentPage() > 4) || (i + 1 === totalPages() - 1 && currentPage() < totalPages() - 3)\" class=\"pagination-dots\">...</span>\n </ng-container>\n\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === totalPages()\"\n (click)=\"setPage(currentPage() + 1)\"\n >\n \u203A\n </button>\n </div>\n </div>\n</div>\n", styles: [".tng-table-container{display:flex;flex-direction:column;gap:var(--tng-spacing-unit, 16px);width:100%;background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 8px);box-shadow:var(--tng-shadow-sm, 0 1px 3px rgba(0, 0, 0, .1));padding:var(--tng-spacing-unit, 16px);box-sizing:border-box}.tng-table-toolbar{display:flex;justify-content:flex-end;margin-bottom:var(--tng-spacing-unit, 8px)}.tng-table-search{width:100%;max-width:300px}.tng-table-wrapper{overflow-x:auto;width:100%;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px)}.tng-table{width:100%;border-collapse:collapse;font-family:var(--tng-font-family, sans-serif);font-size:var(--tng-font-size-base, 14px)}.tng-table th,.tng-table td{padding:12px 16px;text-align:left;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-table th{background-color:var(--tng-background, #fafafa);font-weight:var(--tng-font-weight-medium, 500);color:var(--tng-text-secondary, #666);white-space:nowrap;-webkit-user-select:none;user-select:none}.tng-table th.sortable{cursor:pointer;transition:background-color .2s}.tng-table th.sortable:hover{background-color:#ededed}.tng-table tr:last-child td{border-bottom:none}.tng-table tr:hover td{background-color:#00000005}.th-content{display:flex;align-items:center;gap:4px}.sort-indicator{font-size:12px}.no-data-row{text-align:center;color:var(--tng-text-secondary, #666);padding:24px}.tng-table-pagination{display:flex;justify-content:space-between;align-items:center;padding-top:var(--tng-spacing-unit, 8px);flex-wrap:wrap;gap:16px}.pagination-info{color:var(--tng-text-secondary, #666);font-size:.9em}.pagination-controls{display:flex;gap:4px;align-items:center}.tng-btn-icon,.tng-btn-page{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 6px;border:1px solid var(--tng-border, #e0e0e0);background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 4px);cursor:pointer;color:var(--tng-text, #333);transition:all .2s}.tng-btn-icon:hover:not(:disabled),.tng-btn-page:hover:not(:disabled){background-color:var(--tng-background, #f5f5f5);border-color:var(--tng-primary, #3f51b5);color:var(--tng-primary, #3f51b5)}.tng-btn-icon:disabled,.tng-btn-page:disabled{opacity:.5;cursor:not-allowed}.tng-btn-icon.active,.tng-btn-page.active{background-color:var(--tng-primary, #3f51b5);color:var(--tng-primary-contrast, #fff);border-color:var(--tng-primary, #3f51b5)}.pagination-dots{display:inline-flex;align-items:center;justify-content:center;width:32px;color:var(--tng-text-secondary, #666)}@media(max-width:600px){.tng-table-pagination{justify-content:center;flex-direction:column}.tng-table-toolbar{justify-content:stretch}.tng-table-search{max-width:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: TecnualInputComponent, selector: "tng-input", inputs: ["label", "type", "placeholder", "required", "disabled", "id"], outputs: ["disabledChange"] }] });
413
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TecnualTableComponent, isStandalone: true, selector: "tng-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"tng-table-container\">\n <!-- Toolbar -->\n @if (filterable()) {\n <div class=\"tng-table-toolbar\">\n <div class=\"tng-table-search\">\n <tng-input\n [placeholder]=\"'Search...'\"\n (input)=\"onSearchInput($event)\"\n ></tng-input>\n </div>\n </div>\n }\n\n <!-- Table -->\n <div class=\"tng-table-wrapper\">\n <table class=\"tng-table\">\n <thead>\n <tr>\n @for (col of columns(); track col.key) {\n <th \n [style.width]=\"col.width\"\n [class.sortable]=\"col.sortable\"\n (click)=\"onSort(col)\"\n >\n <div class=\"th-content\">\n {{ col.label }}\n @if (sortColumn() === col.key) {\n <span class=\"sort-indicator\">\n {{ sortDirection() === 'asc' ? '\u2191' : '\u2193' }}\n </span>\n }\n </div>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of paginatedData(); track row) {\n <tr>\n @for (col of columns(); track col.key) {\n <td>\n @if (col.template) {\n <ng-container *ngTemplateOutlet=\"col.template; context: { $implicit: row[col.key], row: row }\"></ng-container>\n } @else {\n {{ row[col.key] }}\n }\n </td>\n }\n </tr>\n }\n @if (paginatedData().length === 0) {\n <tr class=\"no-data-row\">\n <td [attr.colspan]=\"columns().length\">\n No data found\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n @if (totalPages() > 1) {\n <div class=\"tng-table-pagination\">\n <div class=\"pagination-info\">\n Page {{ currentPage() }} of {{ totalPages() }}\n </div>\n <div class=\"pagination-controls\">\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === 1\"\n (click)=\"setPage(currentPage() - 1)\"\n >\n \u2039\n </button>\n \n @for (page of [].constructor(totalPages()); track $index; let i = $index) {\n @if (i + 1 === currentPage() || i + 1 === 1 || i + 1 === totalPages() || (i + 1 >= currentPage() - 1 && i + 1 <= currentPage() + 1)) {\n <button \n class=\"tng-btn-page\"\n [class.active]=\"currentPage() === i + 1\"\n (click)=\"setPage(i + 1)\"\n >\n {{ i + 1 }}\n </button>\n }\n @if ((i + 1 === 2 && currentPage() > 4) || (i + 1 === totalPages() - 1 && currentPage() < totalPages() - 3)) {\n <span class=\"pagination-dots\">...</span>\n }\n }\n\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === totalPages()\"\n (click)=\"setPage(currentPage() + 1)\"\n >\n \u203A\n </button>\n </div>\n </div>\n }\n</div>\n", styles: [".tng-table-container{display:flex;flex-direction:column;gap:var(--tng-spacing-unit, 16px);width:100%;background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 8px);box-shadow:var(--tng-shadow-sm, 0 1px 3px rgba(0, 0, 0, .1));padding:var(--tng-spacing-unit, 16px);box-sizing:border-box}.tng-table-toolbar{display:flex;justify-content:flex-end;margin-bottom:var(--tng-spacing-unit, 8px)}.tng-table-search{width:100%;max-width:300px}.tng-table-wrapper{overflow-x:auto;width:100%;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px)}.tng-table{width:100%;border-collapse:collapse;font-family:var(--tng-font-family, sans-serif);font-size:var(--tng-font-size-base, 14px)}.tng-table th,.tng-table td{padding:12px 16px;text-align:left;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-table th{background-color:var(--tng-background, #fafafa);font-weight:var(--tng-font-weight-medium, 500);color:var(--tng-text-secondary, #666);white-space:nowrap;-webkit-user-select:none;user-select:none}.tng-table th.sortable{cursor:pointer;transition:background-color .2s}.tng-table th.sortable:hover{background-color:#ededed}.tng-table tr:last-child td{border-bottom:none}.tng-table tr:hover td{background-color:#00000005}.th-content{display:flex;align-items:center;gap:4px}.sort-indicator{font-size:12px}.no-data-row{text-align:center;color:var(--tng-text-secondary, #666);padding:24px}.tng-table-pagination{display:flex;justify-content:space-between;align-items:center;padding-top:var(--tng-spacing-unit, 8px);flex-wrap:wrap;gap:16px}.pagination-info{color:var(--tng-text-secondary, #666);font-size:.9em}.pagination-controls{display:flex;gap:4px;align-items:center}.tng-btn-icon,.tng-btn-page{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 6px;border:1px solid var(--tng-border, #e0e0e0);background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 4px);cursor:pointer;color:var(--tng-text, #333);transition:all .2s}.tng-btn-icon:hover:not(:disabled),.tng-btn-page:hover:not(:disabled){background-color:var(--tng-background, #f5f5f5);border-color:var(--tng-primary, #3f51b5);color:var(--tng-primary, #3f51b5)}.tng-btn-icon:disabled,.tng-btn-page:disabled{opacity:.5;cursor:not-allowed}.tng-btn-icon.active,.tng-btn-page.active{background-color:var(--tng-primary, #3f51b5);color:var(--tng-primary-contrast, #fff);border-color:var(--tng-primary, #3f51b5)}.pagination-dots{display:inline-flex;align-items:center;justify-content:center;width:32px;color:var(--tng-text-secondary, #666)}@media(max-width:600px){.tng-table-pagination{justify-content:center;flex-direction:column}.tng-table-toolbar{justify-content:stretch}.tng-table-search{max-width:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: TecnualInputComponent, selector: "tng-input", inputs: ["label", "type", "placeholder", "required", "disabled", "id"], outputs: ["disabledChange"] }] });
411
414
  }
412
415
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TecnualTableComponent, decorators: [{
413
416
  type: Component,
414
- args: [{ selector: 'tng-table', standalone: true, imports: [CommonModule, FormsModule, TecnualInputComponent], template: "<div class=\"tng-table-container\">\n <!-- Toolbar -->\n <div class=\"tng-table-toolbar\" *ngIf=\"filterable()\">\n <div class=\"tng-table-search\">\n <tng-input\n [placeholder]=\"'Search...'\"\n (input)=\"onSearchInput($event)\"\n ></tng-input>\n </div>\n </div>\n\n <!-- Table -->\n <div class=\"tng-table-wrapper\">\n <table class=\"tng-table\">\n <thead>\n <tr>\n <th \n *ngFor=\"let col of columns()\"\n [style.width]=\"col.width\"\n [class.sortable]=\"col.sortable\"\n (click)=\"onSort(col)\"\n >\n <div class=\"th-content\">\n {{ col.label }}\n <span class=\"sort-indicator\" *ngIf=\"sortColumn() === col.key\">\n {{ sortDirection() === 'asc' ? '\u2191' : '\u2193' }}\n </span>\n </div>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of paginatedData()\">\n <td *ngFor=\"let col of columns()\">\n <ng-container *ngIf=\"col.template; else defaultCell\">\n <ng-container *ngTemplateOutlet=\"col.template; context: { $implicit: row[col.key], row: row }\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n {{ row[col.key] }}\n </ng-template>\n </td>\n </tr>\n <tr *ngIf=\"paginatedData().length === 0\" class=\"no-data-row\">\n <td [attr.colspan]=\"columns().length\">\n No data found\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"tng-table-pagination\" *ngIf=\"totalPages() > 1\">\n <div class=\"pagination-info\">\n Page {{ currentPage() }} of {{ totalPages() }}\n </div>\n <div class=\"pagination-controls\">\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === 1\"\n (click)=\"setPage(currentPage() - 1)\"\n >\n \u2039\n </button>\n \n <ng-container *ngFor=\"let page of [].constructor(totalPages()); let i = index\">\n <!-- Show limited pages logic could go here, for now simple list -->\n <button \n *ngIf=\"i + 1 === currentPage() || i + 1 === 1 || i + 1 === totalPages() || (i + 1 >= currentPage() - 1 && i + 1 <= currentPage() + 1)\"\n class=\"tng-btn-page\"\n [class.active]=\"currentPage() === i + 1\"\n (click)=\"setPage(i + 1)\"\n >\n {{ i + 1 }}\n </button>\n <span *ngIf=\"(i + 1 === 2 && currentPage() > 4) || (i + 1 === totalPages() - 1 && currentPage() < totalPages() - 3)\" class=\"pagination-dots\">...</span>\n </ng-container>\n\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === totalPages()\"\n (click)=\"setPage(currentPage() + 1)\"\n >\n \u203A\n </button>\n </div>\n </div>\n</div>\n", styles: [".tng-table-container{display:flex;flex-direction:column;gap:var(--tng-spacing-unit, 16px);width:100%;background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 8px);box-shadow:var(--tng-shadow-sm, 0 1px 3px rgba(0, 0, 0, .1));padding:var(--tng-spacing-unit, 16px);box-sizing:border-box}.tng-table-toolbar{display:flex;justify-content:flex-end;margin-bottom:var(--tng-spacing-unit, 8px)}.tng-table-search{width:100%;max-width:300px}.tng-table-wrapper{overflow-x:auto;width:100%;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px)}.tng-table{width:100%;border-collapse:collapse;font-family:var(--tng-font-family, sans-serif);font-size:var(--tng-font-size-base, 14px)}.tng-table th,.tng-table td{padding:12px 16px;text-align:left;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-table th{background-color:var(--tng-background, #fafafa);font-weight:var(--tng-font-weight-medium, 500);color:var(--tng-text-secondary, #666);white-space:nowrap;-webkit-user-select:none;user-select:none}.tng-table th.sortable{cursor:pointer;transition:background-color .2s}.tng-table th.sortable:hover{background-color:#ededed}.tng-table tr:last-child td{border-bottom:none}.tng-table tr:hover td{background-color:#00000005}.th-content{display:flex;align-items:center;gap:4px}.sort-indicator{font-size:12px}.no-data-row{text-align:center;color:var(--tng-text-secondary, #666);padding:24px}.tng-table-pagination{display:flex;justify-content:space-between;align-items:center;padding-top:var(--tng-spacing-unit, 8px);flex-wrap:wrap;gap:16px}.pagination-info{color:var(--tng-text-secondary, #666);font-size:.9em}.pagination-controls{display:flex;gap:4px;align-items:center}.tng-btn-icon,.tng-btn-page{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 6px;border:1px solid var(--tng-border, #e0e0e0);background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 4px);cursor:pointer;color:var(--tng-text, #333);transition:all .2s}.tng-btn-icon:hover:not(:disabled),.tng-btn-page:hover:not(:disabled){background-color:var(--tng-background, #f5f5f5);border-color:var(--tng-primary, #3f51b5);color:var(--tng-primary, #3f51b5)}.tng-btn-icon:disabled,.tng-btn-page:disabled{opacity:.5;cursor:not-allowed}.tng-btn-icon.active,.tng-btn-page.active{background-color:var(--tng-primary, #3f51b5);color:var(--tng-primary-contrast, #fff);border-color:var(--tng-primary, #3f51b5)}.pagination-dots{display:inline-flex;align-items:center;justify-content:center;width:32px;color:var(--tng-text-secondary, #666)}@media(max-width:600px){.tng-table-pagination{justify-content:center;flex-direction:column}.tng-table-toolbar{justify-content:stretch}.tng-table-search{max-width:none}}\n"] }]
417
+ args: [{ selector: 'tng-table', standalone: true, imports: [CommonModule, FormsModule, TecnualInputComponent], template: "<div class=\"tng-table-container\">\n <!-- Toolbar -->\n @if (filterable()) {\n <div class=\"tng-table-toolbar\">\n <div class=\"tng-table-search\">\n <tng-input\n [placeholder]=\"'Search...'\"\n (input)=\"onSearchInput($event)\"\n ></tng-input>\n </div>\n </div>\n }\n\n <!-- Table -->\n <div class=\"tng-table-wrapper\">\n <table class=\"tng-table\">\n <thead>\n <tr>\n @for (col of columns(); track col.key) {\n <th \n [style.width]=\"col.width\"\n [class.sortable]=\"col.sortable\"\n (click)=\"onSort(col)\"\n >\n <div class=\"th-content\">\n {{ col.label }}\n @if (sortColumn() === col.key) {\n <span class=\"sort-indicator\">\n {{ sortDirection() === 'asc' ? '\u2191' : '\u2193' }}\n </span>\n }\n </div>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of paginatedData(); track row) {\n <tr>\n @for (col of columns(); track col.key) {\n <td>\n @if (col.template) {\n <ng-container *ngTemplateOutlet=\"col.template; context: { $implicit: row[col.key], row: row }\"></ng-container>\n } @else {\n {{ row[col.key] }}\n }\n </td>\n }\n </tr>\n }\n @if (paginatedData().length === 0) {\n <tr class=\"no-data-row\">\n <td [attr.colspan]=\"columns().length\">\n No data found\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n @if (totalPages() > 1) {\n <div class=\"tng-table-pagination\">\n <div class=\"pagination-info\">\n Page {{ currentPage() }} of {{ totalPages() }}\n </div>\n <div class=\"pagination-controls\">\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === 1\"\n (click)=\"setPage(currentPage() - 1)\"\n >\n \u2039\n </button>\n \n @for (page of [].constructor(totalPages()); track $index; let i = $index) {\n @if (i + 1 === currentPage() || i + 1 === 1 || i + 1 === totalPages() || (i + 1 >= currentPage() - 1 && i + 1 <= currentPage() + 1)) {\n <button \n class=\"tng-btn-page\"\n [class.active]=\"currentPage() === i + 1\"\n (click)=\"setPage(i + 1)\"\n >\n {{ i + 1 }}\n </button>\n }\n @if ((i + 1 === 2 && currentPage() > 4) || (i + 1 === totalPages() - 1 && currentPage() < totalPages() - 3)) {\n <span class=\"pagination-dots\">...</span>\n }\n }\n\n <button \n class=\"tng-btn-icon\" \n [disabled]=\"currentPage() === totalPages()\"\n (click)=\"setPage(currentPage() + 1)\"\n >\n \u203A\n </button>\n </div>\n </div>\n }\n</div>\n", styles: [".tng-table-container{display:flex;flex-direction:column;gap:var(--tng-spacing-unit, 16px);width:100%;background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 8px);box-shadow:var(--tng-shadow-sm, 0 1px 3px rgba(0, 0, 0, .1));padding:var(--tng-spacing-unit, 16px);box-sizing:border-box}.tng-table-toolbar{display:flex;justify-content:flex-end;margin-bottom:var(--tng-spacing-unit, 8px)}.tng-table-search{width:100%;max-width:300px}.tng-table-wrapper{overflow-x:auto;width:100%;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px)}.tng-table{width:100%;border-collapse:collapse;font-family:var(--tng-font-family, sans-serif);font-size:var(--tng-font-size-base, 14px)}.tng-table th,.tng-table td{padding:12px 16px;text-align:left;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-table th{background-color:var(--tng-background, #fafafa);font-weight:var(--tng-font-weight-medium, 500);color:var(--tng-text-secondary, #666);white-space:nowrap;-webkit-user-select:none;user-select:none}.tng-table th.sortable{cursor:pointer;transition:background-color .2s}.tng-table th.sortable:hover{background-color:#ededed}.tng-table tr:last-child td{border-bottom:none}.tng-table tr:hover td{background-color:#00000005}.th-content{display:flex;align-items:center;gap:4px}.sort-indicator{font-size:12px}.no-data-row{text-align:center;color:var(--tng-text-secondary, #666);padding:24px}.tng-table-pagination{display:flex;justify-content:space-between;align-items:center;padding-top:var(--tng-spacing-unit, 8px);flex-wrap:wrap;gap:16px}.pagination-info{color:var(--tng-text-secondary, #666);font-size:.9em}.pagination-controls{display:flex;gap:4px;align-items:center}.tng-btn-icon,.tng-btn-page{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 6px;border:1px solid var(--tng-border, #e0e0e0);background:var(--tng-surface, #fff);border-radius:var(--tng-border-radius, 4px);cursor:pointer;color:var(--tng-text, #333);transition:all .2s}.tng-btn-icon:hover:not(:disabled),.tng-btn-page:hover:not(:disabled){background-color:var(--tng-background, #f5f5f5);border-color:var(--tng-primary, #3f51b5);color:var(--tng-primary, #3f51b5)}.tng-btn-icon:disabled,.tng-btn-page:disabled{opacity:.5;cursor:not-allowed}.tng-btn-icon.active,.tng-btn-page.active{background-color:var(--tng-primary, #3f51b5);color:var(--tng-primary-contrast, #fff);border-color:var(--tng-primary, #3f51b5)}.pagination-dots{display:inline-flex;align-items:center;justify-content:center;width:32px;color:var(--tng-text-secondary, #666)}@media(max-width:600px){.tng-table-pagination{justify-content:center;flex-direction:column}.tng-table-toolbar{justify-content:stretch}.tng-table-search{max-width:none}}\n"] }]
415
418
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }] } });
416
419
 
417
420
  class TngToolbarComponent {
418
421
  position = input('static', ...(ngDevMode ? [{ debugName: "position" }] : []));
419
- positionType = input('fixed', ...(ngDevMode ? [{ debugName: "positionType" }] : []));
422
+ positionType = input('relative', ...(ngDevMode ? [{ debugName: "positionType" }] : []));
420
423
  color = input('default', ...(ngDevMode ? [{ debugName: "color" }] : []));
421
424
  elevation = input(true, ...(ngDevMode ? [{ debugName: "elevation" }] : []));
422
425
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
423
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: TngToolbarComponent, isStandalone: true, selector: "tng-toolbar", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, positionType: { classPropertyName: "positionType", publicName: "positionType", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, elevation: { classPropertyName: "elevation", publicName: "elevation", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.tng-toolbar--top": "position() === \"top\"", "class.tng-toolbar--bottom": "position() === \"bottom\"", "class.tng-toolbar--fixed": "positionType() === \"fixed\"", "class.tng-toolbar--absolute": "positionType() === \"absolute\"", "class.tng-toolbar--relative": "positionType() === \"relative\"", "class.tng-toolbar--static": "positionType() === \"static\"", "class.tng-toolbar--primary": "color() === \"primary\"", "class.tng-toolbar--secondary": "color() === \"secondary\"", "class.tng-toolbar--elevated": "elevation()" }, classAttribute: "tng-toolbar" }, ngImport: i0, template: "<div class=\"tng-toolbar__container\">\n <div class=\"tng-toolbar__section tng-toolbar__section--left\">\n <ng-content select=\"[toolbar-left]\"></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--center\">\n <ng-content select=\"[toolbar-center]\"></ng-content>\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--right\">\n <ng-content select=\"[toolbar-right]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-toolbar{display:block;width:100%;background-color:#fff;transition:box-shadow .3s cubic-bezier(.4,0,.2,1)}.tng-toolbar__container{display:flex;align-items:center;justify-content:space-between;padding:0 16px;min-height:64px;max-width:100%;gap:16px}@media(max-width:768px){.tng-toolbar__container{min-height:56px;padding:0 12px;gap:12px}}.tng-toolbar__section{display:flex;align-items:center;gap:12px;flex-shrink:0}.tng-toolbar__section--left{justify-content:flex-start}.tng-toolbar__section--center{justify-content:center;flex:1;overflow:hidden}.tng-toolbar__section--right{justify-content:flex-end}.tng-toolbar--fixed{position:fixed;z-index:1000}.tng-toolbar--absolute{position:absolute;z-index:1000}.tng-toolbar--relative{position:relative}.tng-toolbar--static{position:static}.tng-toolbar--top.tng-toolbar--fixed,.tng-toolbar--top.tng-toolbar--absolute{top:0;left:0;right:0}.tng-toolbar--bottom.tng-toolbar--fixed,.tng-toolbar--bottom.tng-toolbar--absolute{bottom:0;left:0;right:0}.tng-toolbar--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-toolbar--primary{background-color:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-toolbar--secondary{background-color:var(--tng-secondary);color:var(--tng-secondary-contrast)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
426
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: TngToolbarComponent, isStandalone: true, selector: "tng-toolbar", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, positionType: { classPropertyName: "positionType", publicName: "positionType", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, elevation: { classPropertyName: "elevation", publicName: "elevation", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.tng-toolbar--top": "position() === \"top\"", "class.tng-toolbar--bottom": "position() === \"bottom\"", "class.tng-toolbar--fixed": "positionType() === \"fixed\"", "class.tng-toolbar--absolute": "positionType() === \"absolute\"", "class.tng-toolbar--relative": "positionType() === \"relative\"", "class.tng-toolbar--static": "positionType() === \"static\"", "class.tng-toolbar--sticky": "positionType() === \"sticky\"", "class.tng-toolbar--primary": "color() === \"primary\"", "class.tng-toolbar--secondary": "color() === \"secondary\"", "class.tng-toolbar--elevated": "elevation()" }, classAttribute: "tng-toolbar" }, ngImport: i0, template: "<div class=\"tng-toolbar__container\">\n <div class=\"tng-toolbar__section tng-toolbar__section--left\">\n <ng-content select=\"[toolbar-left]\"></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--center\">\n <ng-content select=\"[toolbar-center]\"></ng-content>\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--right\">\n <ng-content select=\"[toolbar-right]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-toolbar{display:block;width:100%;background-color:#fff;transition:box-shadow .3s cubic-bezier(.4,0,.2,1)}.tng-toolbar__container{display:flex;align-items:center;justify-content:space-between;padding:0 16px;min-height:64px;max-width:100%;gap:16px}@media(max-width:768px){.tng-toolbar__container{min-height:56px;padding:0 12px;gap:12px}}.tng-toolbar__section{display:flex;align-items:center;gap:12px;flex-shrink:0}.tng-toolbar__section--left{justify-content:flex-start}.tng-toolbar__section--center{justify-content:center;flex:1;overflow:hidden}.tng-toolbar__section--right{justify-content:flex-end}.tng-toolbar--fixed{position:fixed;z-index:1000}.tng-toolbar--absolute{position:absolute;z-index:1000}.tng-toolbar--relative{position:relative}.tng-toolbar--static{position:static}.tng-toolbar--sticky{position:sticky;top:0;z-index:1000}.tng-toolbar--top.tng-toolbar--fixed,.tng-toolbar--top.tng-toolbar--absolute{top:0;left:0;right:0}.tng-toolbar--bottom.tng-toolbar--fixed,.tng-toolbar--bottom.tng-toolbar--absolute{bottom:0;left:0;right:0}.tng-toolbar--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-toolbar--primary{background:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-toolbar--secondary{background:var(--tng-secondary);color:var(--tng-secondary-contrast)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
424
427
  }
425
428
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngToolbarComponent, decorators: [{
426
429
  type: Component,
@@ -432,12 +435,273 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
432
435
  '[class.tng-toolbar--absolute]': 'positionType() === "absolute"',
433
436
  '[class.tng-toolbar--relative]': 'positionType() === "relative"',
434
437
  '[class.tng-toolbar--static]': 'positionType() === "static"',
438
+ '[class.tng-toolbar--sticky]': 'positionType() === "sticky"',
435
439
  '[class.tng-toolbar--primary]': 'color() === "primary"',
436
440
  '[class.tng-toolbar--secondary]': 'color() === "secondary"',
437
441
  '[class.tng-toolbar--elevated]': 'elevation()',
438
- }, template: "<div class=\"tng-toolbar__container\">\n <div class=\"tng-toolbar__section tng-toolbar__section--left\">\n <ng-content select=\"[toolbar-left]\"></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--center\">\n <ng-content select=\"[toolbar-center]\"></ng-content>\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--right\">\n <ng-content select=\"[toolbar-right]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-toolbar{display:block;width:100%;background-color:#fff;transition:box-shadow .3s cubic-bezier(.4,0,.2,1)}.tng-toolbar__container{display:flex;align-items:center;justify-content:space-between;padding:0 16px;min-height:64px;max-width:100%;gap:16px}@media(max-width:768px){.tng-toolbar__container{min-height:56px;padding:0 12px;gap:12px}}.tng-toolbar__section{display:flex;align-items:center;gap:12px;flex-shrink:0}.tng-toolbar__section--left{justify-content:flex-start}.tng-toolbar__section--center{justify-content:center;flex:1;overflow:hidden}.tng-toolbar__section--right{justify-content:flex-end}.tng-toolbar--fixed{position:fixed;z-index:1000}.tng-toolbar--absolute{position:absolute;z-index:1000}.tng-toolbar--relative{position:relative}.tng-toolbar--static{position:static}.tng-toolbar--top.tng-toolbar--fixed,.tng-toolbar--top.tng-toolbar--absolute{top:0;left:0;right:0}.tng-toolbar--bottom.tng-toolbar--fixed,.tng-toolbar--bottom.tng-toolbar--absolute{bottom:0;left:0;right:0}.tng-toolbar--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-toolbar--primary{background-color:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-toolbar--secondary{background-color:var(--tng-secondary);color:var(--tng-secondary-contrast)}\n"] }]
442
+ }, template: "<div class=\"tng-toolbar__container\">\n <div class=\"tng-toolbar__section tng-toolbar__section--left\">\n <ng-content select=\"[toolbar-left]\"></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--center\">\n <ng-content select=\"[toolbar-center]\"></ng-content>\n <ng-content></ng-content>\n </div>\n\n <div class=\"tng-toolbar__section tng-toolbar__section--right\">\n <ng-content select=\"[toolbar-right]\"></ng-content>\n </div>\n</div>\n", styles: [".tng-toolbar{display:block;width:100%;background-color:#fff;transition:box-shadow .3s cubic-bezier(.4,0,.2,1)}.tng-toolbar__container{display:flex;align-items:center;justify-content:space-between;padding:0 16px;min-height:64px;max-width:100%;gap:16px}@media(max-width:768px){.tng-toolbar__container{min-height:56px;padding:0 12px;gap:12px}}.tng-toolbar__section{display:flex;align-items:center;gap:12px;flex-shrink:0}.tng-toolbar__section--left{justify-content:flex-start}.tng-toolbar__section--center{justify-content:center;flex:1;overflow:hidden}.tng-toolbar__section--right{justify-content:flex-end}.tng-toolbar--fixed{position:fixed;z-index:1000}.tng-toolbar--absolute{position:absolute;z-index:1000}.tng-toolbar--relative{position:relative}.tng-toolbar--static{position:static}.tng-toolbar--sticky{position:sticky;top:0;z-index:1000}.tng-toolbar--top.tng-toolbar--fixed,.tng-toolbar--top.tng-toolbar--absolute{top:0;left:0;right:0}.tng-toolbar--bottom.tng-toolbar--fixed,.tng-toolbar--bottom.tng-toolbar--absolute{bottom:0;left:0;right:0}.tng-toolbar--elevated{box-shadow:0 2px 4px -1px #0000001a,0 4px 5px #00000012,0 1px 10px #0000000f}.tng-toolbar--primary{background:var(--tng-primary);color:var(--tng-primary-contrast)}.tng-toolbar--secondary{background:var(--tng-secondary);color:var(--tng-secondary-contrast)}\n"] }]
439
443
  }], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], positionType: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionType", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], elevation: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevation", required: false }] }] } });
440
444
 
445
+ class TngTabComponent {
446
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
447
+ // We use a template to lazy load the content or just to hold the reference
448
+ content = viewChild.required(TemplateRef);
449
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
450
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.0", type: TngTabComponent, isStandalone: true, selector: "tng-tab", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "content", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: `
451
+ <ng-template>
452
+ <ng-content></ng-content>
453
+ </ng-template>
454
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
455
+ }
456
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTabComponent, decorators: [{
457
+ type: Component,
458
+ args: [{
459
+ selector: 'tng-tab',
460
+ standalone: true,
461
+ imports: [],
462
+ template: `
463
+ <ng-template>
464
+ <ng-content></ng-content>
465
+ </ng-template>
466
+ `,
467
+ changeDetection: ChangeDetectionStrategy.OnPush,
468
+ }]
469
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], content: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
470
+
471
+ class TngTabsComponent {
472
+ ngZone;
473
+ tabs = contentChildren(TngTabComponent, ...(ngDevMode ? [{ debugName: "tabs" }] : []));
474
+ activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
475
+ inkBarLeft = signal(0, ...(ngDevMode ? [{ debugName: "inkBarLeft" }] : []));
476
+ inkBarWidth = signal(0, ...(ngDevMode ? [{ debugName: "inkBarWidth" }] : []));
477
+ // Pagination state
478
+ scrollLeft = signal(0, ...(ngDevMode ? [{ debugName: "scrollLeft" }] : []));
479
+ showPagination = signal(false, ...(ngDevMode ? [{ debugName: "showPagination" }] : []));
480
+ isScrolledToEnd = signal(false, ...(ngDevMode ? [{ debugName: "isScrolledToEnd" }] : []));
481
+ // Element refs
482
+ listContainer = viewChild('listContainer', ...(ngDevMode ? [{ debugName: "listContainer" }] : []));
483
+ tabList = viewChild('tabList', ...(ngDevMode ? [{ debugName: "tabList" }] : []));
484
+ tabLabels = viewChild.required('tabLabel'); // Using any cast as viewChildren is not available in this version or syntax might differ, actually let's use DOM query for labels or just rely on index
485
+ resizeObserver = null;
486
+ constructor(ngZone) {
487
+ this.ngZone = ngZone;
488
+ effect(() => {
489
+ // Recalculate ink bar when active index changes
490
+ this.updateInkBar();
491
+ });
492
+ effect(() => {
493
+ // Recalculate pagination when tabs change
494
+ this.tabs();
495
+ this.checkPagination();
496
+ });
497
+ }
498
+ ngAfterViewInit() {
499
+ this.updateInkBar();
500
+ this.checkPagination();
501
+ // Setup resize observer
502
+ if (typeof ResizeObserver !== 'undefined') {
503
+ this.resizeObserver = new ResizeObserver(() => {
504
+ this.ngZone.run(() => {
505
+ this.checkPagination();
506
+ this.updateInkBar();
507
+ });
508
+ });
509
+ const container = this.listContainer()?.nativeElement;
510
+ if (container) {
511
+ this.resizeObserver.observe(container);
512
+ }
513
+ }
514
+ }
515
+ ngOnDestroy() {
516
+ if (this.resizeObserver) {
517
+ this.resizeObserver.disconnect();
518
+ }
519
+ }
520
+ selectTab(index) {
521
+ this.activeIndex.set(index);
522
+ }
523
+ updateInkBar() {
524
+ // We need to find the label element for the active index
525
+ // Since we don't have viewChildren easily accessible in this context without more setup,
526
+ // we can query the DOM within the list
527
+ const list = this.tabList()?.nativeElement;
528
+ if (!list)
529
+ return;
530
+ const labels = list.querySelectorAll('.tng-tabs__label');
531
+ const activeLabel = labels[this.activeIndex()];
532
+ if (activeLabel) {
533
+ this.inkBarLeft.set(activeLabel.offsetLeft);
534
+ this.inkBarWidth.set(activeLabel.offsetWidth);
535
+ // Auto scroll to active tab if needed
536
+ this.scrollToTab(activeLabel);
537
+ }
538
+ }
539
+ checkPagination() {
540
+ const container = this.listContainer()?.nativeElement;
541
+ const list = this.tabList()?.nativeElement;
542
+ if (container && list) {
543
+ const containerWidth = container.offsetWidth;
544
+ const listWidth = list.scrollWidth;
545
+ this.showPagination.set(listWidth > containerWidth);
546
+ // Re-check scroll end
547
+ this.updateScrollState();
548
+ }
549
+ }
550
+ scrollHeader(direction) {
551
+ const container = this.listContainer()?.nativeElement;
552
+ if (!container)
553
+ return;
554
+ const scrollAmount = container.offsetWidth * 0.8;
555
+ const currentScroll = this.scrollLeft();
556
+ const maxScroll = this.getMaxScroll();
557
+ let newScroll = currentScroll + (direction * scrollAmount);
558
+ newScroll = Math.max(0, Math.min(newScroll, maxScroll));
559
+ this.scrollLeft.set(newScroll);
560
+ this.updateScrollState();
561
+ }
562
+ getMaxScroll() {
563
+ const container = this.listContainer()?.nativeElement;
564
+ const list = this.tabList()?.nativeElement;
565
+ if (!container || !list)
566
+ return 0;
567
+ return Math.max(0, list.scrollWidth - container.offsetWidth);
568
+ }
569
+ updateScrollState() {
570
+ const maxScroll = this.getMaxScroll();
571
+ this.isScrolledToEnd.set(Math.abs(this.scrollLeft() - maxScroll) < 1);
572
+ }
573
+ scrollToTab(tabLabel) {
574
+ if (!this.showPagination())
575
+ return;
576
+ const container = this.listContainer()?.nativeElement;
577
+ if (!container)
578
+ return;
579
+ const labelLeft = tabLabel.offsetLeft;
580
+ const labelWidth = tabLabel.offsetWidth;
581
+ const containerWidth = container.offsetWidth;
582
+ const currentScroll = this.scrollLeft();
583
+ // If tab is to the left of view
584
+ if (labelLeft < currentScroll) {
585
+ this.scrollLeft.set(labelLeft);
586
+ }
587
+ // If tab is to the right of view
588
+ else if (labelLeft + labelWidth > currentScroll + containerWidth) {
589
+ this.scrollLeft.set(labelLeft + labelWidth - containerWidth);
590
+ }
591
+ this.updateScrollState();
592
+ }
593
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTabsComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
594
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngTabsComponent, isStandalone: true, selector: "tng-tabs", queries: [{ propertyName: "tabs", predicate: TngTabComponent, isSignal: true }], viewQueries: [{ propertyName: "listContainer", first: true, predicate: ["listContainer"], descendants: true, isSignal: true }, { propertyName: "tabList", first: true, predicate: ["tabList"], descendants: true, isSignal: true }, { propertyName: "tabLabels", first: true, predicate: 'tabLabel', descendants: true, isSignal: true }], ngImport: i0, template: `
595
+ <div class="tng-tabs">
596
+ <div class="tng-tabs__header">
597
+ @if (showPagination()) {
598
+ <div
599
+ class="tng-tabs__pagination tng-tabs__pagination--prev"
600
+ [class.tng-tabs__pagination--disabled]="scrollLeft() <= 0"
601
+ (click)="scrollHeader(-1)">
602
+ <i class="fa fa-chevron-left"></i>
603
+ </div>
604
+ }
605
+
606
+ <div class="tng-tabs__list-container" #listContainer>
607
+ <div
608
+ class="tng-tabs__list"
609
+ #tabList
610
+ [style.transform]="'translateX(' + (-scrollLeft()) + 'px)'">
611
+ @for (tab of tabs(); track tab; let i = $index) {
612
+ <div
613
+ class="tng-tabs__label"
614
+ [class.tng-tabs__label--active]="activeIndex() === i"
615
+ (click)="selectTab(i)"
616
+ #tabLabel>
617
+ {{ tab.label() }}
618
+ </div>
619
+ }
620
+ <div
621
+ class="tng-tabs__ink-bar"
622
+ [style.left.px]="inkBarLeft()"
623
+ [style.width.px]="inkBarWidth()">
624
+ </div>
625
+ </div>
626
+ </div>
627
+
628
+ @if (showPagination()) {
629
+ <div
630
+ class="tng-tabs__pagination tng-tabs__pagination--next"
631
+ [class.tng-tabs__pagination--disabled]="isScrolledToEnd()"
632
+ (click)="scrollHeader(1)">
633
+ <i class="fa fa-chevron-right"></i>
634
+ </div>
635
+ }
636
+ </div>
637
+
638
+ <div class="tng-tabs__content">
639
+ @for (tab of tabs(); track tab; let i = $index) {
640
+ @if (activeIndex() === i) {
641
+ <ng-container *ngTemplateOutlet="tab.content()"></ng-container>
642
+ }
643
+ }
644
+ </div>
645
+ </div>
646
+ `, isInline: true, styles: [".tng-tabs{display:flex;flex-direction:column;width:100%;overflow:hidden}.tng-tabs__header{display:flex;align-items:center;position:relative;border-bottom:1px solid var(--tng-border, #e0e0e0);background:var(--tng-surface, #fff)}.tng-tabs__list-container{flex:1;overflow:hidden;position:relative;display:flex}.tng-tabs__list{display:flex;flex-direction:row;position:relative;transition:transform .3s cubic-bezier(.35,0,.25,1);list-style:none;margin:0;padding:0;white-space:nowrap}.tng-tabs__label{padding:0 24px;height:48px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-family:var(--tng-font-family, sans-serif);font-size:14px;font-weight:500;color:var(--tng-text-secondary, #666);text-transform:uppercase;transition:color .2s;-webkit-user-select:none;user-select:none;min-width:90px;box-sizing:border-box}.tng-tabs__label:hover{background-color:#0000000a}.tng-tabs__label--active{color:var(--tng-primary, #3f51b5)}.tng-tabs__ink-bar{position:absolute;bottom:0;height:2px;background-color:var(--tng-primary, #3f51b5);transition:left .3s cubic-bezier(.35,0,.25,1),width .3s cubic-bezier(.35,0,.25,1);pointer-events:none}.tng-tabs__pagination{display:flex;align-items:center;justify-content:center;width:32px;height:48px;cursor:pointer;color:var(--tng-text-secondary, #666);z-index:2;background:var(--tng-surface, #fff)}.tng-tabs__pagination:hover{background-color:#0000000a;color:var(--tng-text, #333)}.tng-tabs__pagination--disabled{opacity:.3;pointer-events:none}.tng-tabs__pagination--prev{box-shadow:4px 0 4px -4px #0000001a}.tng-tabs__pagination--next{box-shadow:-4px 0 4px -4px #0000001a}.tng-tabs__content{padding:24px;background:var(--tng-background, #fafafa)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
647
+ }
648
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTabsComponent, decorators: [{
649
+ type: Component,
650
+ args: [{ selector: 'tng-tabs', standalone: true, imports: [CommonModule], template: `
651
+ <div class="tng-tabs">
652
+ <div class="tng-tabs__header">
653
+ @if (showPagination()) {
654
+ <div
655
+ class="tng-tabs__pagination tng-tabs__pagination--prev"
656
+ [class.tng-tabs__pagination--disabled]="scrollLeft() <= 0"
657
+ (click)="scrollHeader(-1)">
658
+ <i class="fa fa-chevron-left"></i>
659
+ </div>
660
+ }
661
+
662
+ <div class="tng-tabs__list-container" #listContainer>
663
+ <div
664
+ class="tng-tabs__list"
665
+ #tabList
666
+ [style.transform]="'translateX(' + (-scrollLeft()) + 'px)'">
667
+ @for (tab of tabs(); track tab; let i = $index) {
668
+ <div
669
+ class="tng-tabs__label"
670
+ [class.tng-tabs__label--active]="activeIndex() === i"
671
+ (click)="selectTab(i)"
672
+ #tabLabel>
673
+ {{ tab.label() }}
674
+ </div>
675
+ }
676
+ <div
677
+ class="tng-tabs__ink-bar"
678
+ [style.left.px]="inkBarLeft()"
679
+ [style.width.px]="inkBarWidth()">
680
+ </div>
681
+ </div>
682
+ </div>
683
+
684
+ @if (showPagination()) {
685
+ <div
686
+ class="tng-tabs__pagination tng-tabs__pagination--next"
687
+ [class.tng-tabs__pagination--disabled]="isScrolledToEnd()"
688
+ (click)="scrollHeader(1)">
689
+ <i class="fa fa-chevron-right"></i>
690
+ </div>
691
+ }
692
+ </div>
693
+
694
+ <div class="tng-tabs__content">
695
+ @for (tab of tabs(); track tab; let i = $index) {
696
+ @if (activeIndex() === i) {
697
+ <ng-container *ngTemplateOutlet="tab.content()"></ng-container>
698
+ }
699
+ }
700
+ </div>
701
+ </div>
702
+ `, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".tng-tabs{display:flex;flex-direction:column;width:100%;overflow:hidden}.tng-tabs__header{display:flex;align-items:center;position:relative;border-bottom:1px solid var(--tng-border, #e0e0e0);background:var(--tng-surface, #fff)}.tng-tabs__list-container{flex:1;overflow:hidden;position:relative;display:flex}.tng-tabs__list{display:flex;flex-direction:row;position:relative;transition:transform .3s cubic-bezier(.35,0,.25,1);list-style:none;margin:0;padding:0;white-space:nowrap}.tng-tabs__label{padding:0 24px;height:48px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-family:var(--tng-font-family, sans-serif);font-size:14px;font-weight:500;color:var(--tng-text-secondary, #666);text-transform:uppercase;transition:color .2s;-webkit-user-select:none;user-select:none;min-width:90px;box-sizing:border-box}.tng-tabs__label:hover{background-color:#0000000a}.tng-tabs__label--active{color:var(--tng-primary, #3f51b5)}.tng-tabs__ink-bar{position:absolute;bottom:0;height:2px;background-color:var(--tng-primary, #3f51b5);transition:left .3s cubic-bezier(.35,0,.25,1),width .3s cubic-bezier(.35,0,.25,1);pointer-events:none}.tng-tabs__pagination{display:flex;align-items:center;justify-content:center;width:32px;height:48px;cursor:pointer;color:var(--tng-text-secondary, #666);z-index:2;background:var(--tng-surface, #fff)}.tng-tabs__pagination:hover{background-color:#0000000a;color:var(--tng-text, #333)}.tng-tabs__pagination--disabled{opacity:.3;pointer-events:none}.tng-tabs__pagination--prev{box-shadow:4px 0 4px -4px #0000001a}.tng-tabs__pagination--next{box-shadow:-4px 0 4px -4px #0000001a}.tng-tabs__content{padding:24px;background:var(--tng-background, #fafafa)}\n"] }]
703
+ }], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TngTabComponent), { isSignal: true }] }], listContainer: [{ type: i0.ViewChild, args: ['listContainer', { isSignal: true }] }], tabList: [{ type: i0.ViewChild, args: ['tabList', { isSignal: true }] }], tabLabels: [{ type: i0.ViewChild, args: [i0.forwardRef(() => 'tabLabel'), { isSignal: true }] }] } });
704
+
441
705
  class ThemeService {
442
706
  STORAGE_KEY = 'tng-theme';
443
707
  currentTheme = signal(this.loadTheme(), ...(ngDevMode ? [{ debugName: "currentTheme" }] : []));
@@ -490,6 +754,20 @@ class ThemeService {
490
754
  description: 'Elegant grayscale',
491
755
  primaryColor: '#616161',
492
756
  isDark: false
757
+ },
758
+ {
759
+ name: 'aurora',
760
+ displayName: 'Aurora',
761
+ description: 'Elegant gradients',
762
+ primaryColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
763
+ isDark: false
764
+ },
765
+ {
766
+ name: 'aurora-dark',
767
+ displayName: 'Aurora Dark',
768
+ description: 'Dark mode gradients',
769
+ primaryColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
770
+ isDark: true
493
771
  }
494
772
  ];
495
773
  constructor() {
@@ -509,17 +787,33 @@ class ThemeService {
509
787
  }
510
788
  applyTheme(theme) {
511
789
  console.log('Applying theme:', theme);
512
- // Remove all theme classes
790
+ // Remove all theme classes (optional if we rely solely on CSS files, but good for safety)
513
791
  this.themes.forEach(t => {
514
792
  document.body.classList.remove(`${t.name}-theme`);
515
793
  });
516
- // Add new theme class
794
+ // Add new theme class (still useful for component-level hooks)
517
795
  document.body.classList.add(`${theme}-theme`);
518
796
  // Set data attribute for CSS
519
797
  document.body.setAttribute('data-theme', theme);
798
+ // Load the theme CSS file
799
+ this.loadThemeCss(theme);
520
800
  console.log('Body classes:', document.body.className);
521
801
  console.log('Data theme:', document.body.getAttribute('data-theme'));
522
802
  }
803
+ loadThemeCss(theme) {
804
+ const head = document.head;
805
+ const existingLink = document.getElementById('theme-css');
806
+ const link = document.createElement('link');
807
+ link.id = 'theme-css';
808
+ link.rel = 'stylesheet';
809
+ link.href = `theme-${theme}.css`;
810
+ if (existingLink) {
811
+ head.replaceChild(link, existingLink);
812
+ }
813
+ else {
814
+ head.appendChild(link);
815
+ }
816
+ }
523
817
  loadTheme() {
524
818
  const saved = localStorage.getItem(this.STORAGE_KEY);
525
819
  return saved || 'light';
@@ -540,6 +834,446 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
540
834
  }]
541
835
  }], ctorParameters: () => [] });
542
836
 
837
+ class TngTooltipComponent {
838
+ content = input('', ...(ngDevMode ? [{ debugName: "content" }] : []));
839
+ isTemplate(value) {
840
+ return value instanceof TemplateRef;
841
+ }
842
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
843
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngTooltipComponent, isStandalone: true, selector: "tng-tooltip", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
844
+ <div class="tng-tooltip-container" [@tooltipAnimation]>
845
+ @if (isTemplate(content())) {
846
+ <ng-container *ngTemplateOutlet="$any(content())"></ng-container>
847
+ } @else {
848
+ {{ content() }}
849
+ }
850
+ </div>
851
+ `, isInline: true, styles: [":host{display:block;pointer-events:none;z-index:10000;position:fixed}.tng-tooltip-container{background:#14141ee6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff;padding:8px 12px;border-radius:8px;font-size:14px;font-family:Inter,sans-serif;box-shadow:0 4px 15px #0003;border:1px solid rgba(255,255,255,.1);max-width:250px;word-wrap:break-word;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], animations: [
852
+ trigger('tooltipAnimation', [
853
+ transition(':enter', [
854
+ style({ opacity: 0, transform: 'scale(0.9)' }),
855
+ animate('150ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ opacity: 1, transform: 'scale(1)' }))
856
+ ]),
857
+ transition(':leave', [
858
+ animate('100ms ease-out', style({ opacity: 0, transform: 'scale(0.9)' }))
859
+ ])
860
+ ])
861
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
862
+ }
863
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTooltipComponent, decorators: [{
864
+ type: Component,
865
+ args: [{ selector: 'tng-tooltip', standalone: true, imports: [CommonModule], template: `
866
+ <div class="tng-tooltip-container" [@tooltipAnimation]>
867
+ @if (isTemplate(content())) {
868
+ <ng-container *ngTemplateOutlet="$any(content())"></ng-container>
869
+ } @else {
870
+ {{ content() }}
871
+ }
872
+ </div>
873
+ `, animations: [
874
+ trigger('tooltipAnimation', [
875
+ transition(':enter', [
876
+ style({ opacity: 0, transform: 'scale(0.9)' }),
877
+ animate('150ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ opacity: 1, transform: 'scale(1)' }))
878
+ ]),
879
+ transition(':leave', [
880
+ animate('100ms ease-out', style({ opacity: 0, transform: 'scale(0.9)' }))
881
+ ])
882
+ ])
883
+ ], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;pointer-events:none;z-index:10000;position:fixed}.tng-tooltip-container{background:#14141ee6;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff;padding:8px 12px;border-radius:8px;font-size:14px;font-family:Inter,sans-serif;box-shadow:0 4px 15px #0003;border:1px solid rgba(255,255,255,.1);max-width:250px;word-wrap:break-word;line-height:1.4}\n"] }]
884
+ }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }] } });
885
+
886
+ class TngTooltipDirective {
887
+ elementRef;
888
+ appRef;
889
+ injector;
890
+ content = '';
891
+ tngTooltipPosition = 'top';
892
+ tngTooltipDelay = 200;
893
+ componentRef = null;
894
+ timeoutId;
895
+ constructor(elementRef, appRef, injector) {
896
+ this.elementRef = elementRef;
897
+ this.appRef = appRef;
898
+ this.injector = injector;
899
+ }
900
+ onMouseEnter() {
901
+ this.timeoutId = setTimeout(() => {
902
+ this.show();
903
+ }, this.tngTooltipDelay);
904
+ }
905
+ onMouseLeave() {
906
+ if (this.timeoutId) {
907
+ clearTimeout(this.timeoutId);
908
+ }
909
+ this.hide();
910
+ }
911
+ onFocus() {
912
+ this.show();
913
+ }
914
+ onBlur() {
915
+ this.hide();
916
+ }
917
+ show() {
918
+ if (this.componentRef)
919
+ return;
920
+ // Create component
921
+ this.componentRef = createComponent(TngTooltipComponent, {
922
+ environmentInjector: this.injector
923
+ });
924
+ // Set input using setInput for signal-based inputs
925
+ this.componentRef.setInput('content', this.content);
926
+ // Trigger change detection to render content
927
+ this.componentRef.changeDetectorRef.detectChanges();
928
+ // Attach to the view so change detection works
929
+ this.appRef.attachView(this.componentRef.hostView);
930
+ // Get DOM element
931
+ const domElem = this.componentRef.hostView.rootNodes[0];
932
+ document.body.appendChild(domElem);
933
+ // Position it
934
+ this.updatePosition(domElem);
935
+ }
936
+ hide() {
937
+ if (!this.componentRef)
938
+ return;
939
+ this.appRef.detachView(this.componentRef.hostView);
940
+ this.componentRef.destroy();
941
+ this.componentRef = null;
942
+ }
943
+ updatePosition(tooltipElem) {
944
+ const hostRect = this.elementRef.nativeElement.getBoundingClientRect();
945
+ const tooltipRect = tooltipElem.getBoundingClientRect();
946
+ let top = 0;
947
+ let left = 0;
948
+ const gap = 8;
949
+ switch (this.tngTooltipPosition) {
950
+ case 'top':
951
+ top = hostRect.top - tooltipRect.height - gap;
952
+ left = hostRect.left + (hostRect.width - tooltipRect.width) / 2;
953
+ break;
954
+ case 'bottom':
955
+ top = hostRect.bottom + gap;
956
+ left = hostRect.left + (hostRect.width - tooltipRect.width) / 2;
957
+ break;
958
+ case 'left':
959
+ top = hostRect.top + (hostRect.height - tooltipRect.height) / 2;
960
+ left = hostRect.left - tooltipRect.width - gap;
961
+ break;
962
+ case 'right':
963
+ top = hostRect.top + (hostRect.height - tooltipRect.height) / 2;
964
+ left = hostRect.right + gap;
965
+ break;
966
+ }
967
+ // Prevent overflow (basic)
968
+ if (top < 0)
969
+ top = hostRect.bottom + gap; // Flip to bottom if top overflows
970
+ if (left < 0)
971
+ left = 0;
972
+ tooltipElem.style.top = `${top}px`;
973
+ tooltipElem.style.left = `${left}px`;
974
+ }
975
+ ngOnDestroy() {
976
+ this.hide();
977
+ }
978
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
979
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: TngTooltipDirective, isStandalone: true, selector: "[tngTooltip]", inputs: { content: ["tngTooltip", "content"], tngTooltipPosition: "tngTooltipPosition", tngTooltipDelay: "tngTooltipDelay" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0 });
980
+ }
981
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngTooltipDirective, decorators: [{
982
+ type: Directive,
983
+ args: [{
984
+ selector: '[tngTooltip]',
985
+ standalone: true
986
+ }]
987
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }], propDecorators: { content: [{
988
+ type: Input,
989
+ args: ['tngTooltip']
990
+ }], tngTooltipPosition: [{
991
+ type: Input
992
+ }], tngTooltipDelay: [{
993
+ type: Input
994
+ }], onMouseEnter: [{
995
+ type: HostListener,
996
+ args: ['mouseenter']
997
+ }], onMouseLeave: [{
998
+ type: HostListener,
999
+ args: ['mouseleave']
1000
+ }], onFocus: [{
1001
+ type: HostListener,
1002
+ args: ['focus']
1003
+ }], onBlur: [{
1004
+ type: HostListener,
1005
+ args: ['blur']
1006
+ }] } });
1007
+
1008
+ class TngExpansionPanelComponent {
1009
+ // Signal inputs
1010
+ title = input('Panel Title', ...(ngDevMode ? [{ debugName: "title" }] : []));
1011
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1012
+ expanded = input(false, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
1013
+ // Signal output
1014
+ toggled = output();
1015
+ // Internal state
1016
+ isExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : []));
1017
+ constructor() {
1018
+ // Sync the expanded input with internal state
1019
+ effect(() => {
1020
+ this.isExpanded.set(this.expanded());
1021
+ });
1022
+ }
1023
+ toggle() {
1024
+ if (this.disabled())
1025
+ return;
1026
+ const newState = !this.isExpanded();
1027
+ this.isExpanded.set(newState);
1028
+ this.toggled.emit(newState);
1029
+ }
1030
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngExpansionPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1031
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngExpansionPanelComponent, isStandalone: true, selector: "tng-expansion-panel", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggled: "toggled" }, host: { properties: { "class.tng-expansion-panel--expanded": "isExpanded()", "class.tng-expansion-panel--disabled": "disabled()" }, classAttribute: "tng-expansion-panel" }, ngImport: i0, template: "<div class=\"tng-expansion-panel__container\">\n <div \n class=\"tng-expansion-panel__header\" \n (click)=\"toggle()\"\n [class.tng-expansion-panel__header--disabled]=\"disabled()\"\n >\n <h3 class=\"tng-expansion-panel__title\">{{ title() }}</h3>\n <span class=\"tng-expansion-panel__icon material-icons\">\n expand_more\n </span>\n </div>\n\n @if (isExpanded()) {\n <div \n class=\"tng-expansion-panel__content\"\n @expandCollapse\n >\n <div class=\"tng-expansion-panel__body\">\n <ng-content></ng-content>\n </div>\n </div>\n }\n</div>\n", styles: [".tng-expansion-panel{display:block;margin-bottom:12px}.tng-expansion-panel__container{background-color:var(--tng-surface);border:1px solid var(--tng-border);border-radius:8px;overflow:hidden;transition:box-shadow .2s cubic-bezier(.4,0,.2,1)}.tng-expansion-panel__header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;cursor:pointer;-webkit-user-select:none;user-select:none;background-color:var(--tng-background);transition:background-color .2s ease,transform .1s ease}.tng-expansion-panel__header:hover:not(.tng-expansion-panel__header--disabled){background-color:color-mix(in srgb,var(--tng-background),var(--tng-text) 5%)}.tng-expansion-panel__header:active:not(.tng-expansion-panel__header--disabled){transform:scale(.99)}.tng-expansion-panel__header--disabled{cursor:not-allowed;opacity:.6}.tng-expansion-panel__title{margin:0;font-size:1rem;font-weight:500;color:var(--tng-text, #333);line-height:1.5}.tng-expansion-panel__icon{font-size:24px;color:var(--tng-text-secondary, #666);transition:transform .3s cubic-bezier(.4,0,.2,1)}.tng-expansion-panel__content{overflow:hidden}.tng-expansion-panel__body{padding:20px;color:var(--tng-text, #333);line-height:1.6}.tng-expansion-panel--expanded .tng-expansion-panel__container{box-shadow:0 2px 4px #0000001a}.tng-expansion-panel--expanded .tng-expansion-panel__icon{transform:rotate(180deg)}.tng-expansion-panel--disabled{opacity:.6;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], animations: [
1032
+ trigger('expandCollapse', [
1033
+ transition(':enter', [
1034
+ style({ height: '0', opacity: '0', overflow: 'hidden' }),
1035
+ animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ height: '*', opacity: '1' }))
1036
+ ]),
1037
+ transition(':leave', [
1038
+ style({ height: '*', opacity: '1', overflow: 'hidden' }),
1039
+ animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ height: '0', opacity: '0' }))
1040
+ ])
1041
+ ])
1042
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1043
+ }
1044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngExpansionPanelComponent, decorators: [{
1045
+ type: Component,
1046
+ args: [{ selector: 'tng-expansion-panel', standalone: true, imports: [CommonModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [
1047
+ trigger('expandCollapse', [
1048
+ transition(':enter', [
1049
+ style({ height: '0', opacity: '0', overflow: 'hidden' }),
1050
+ animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ height: '*', opacity: '1' }))
1051
+ ]),
1052
+ transition(':leave', [
1053
+ style({ height: '*', opacity: '1', overflow: 'hidden' }),
1054
+ animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ height: '0', opacity: '0' }))
1055
+ ])
1056
+ ])
1057
+ ], host: {
1058
+ 'class': 'tng-expansion-panel',
1059
+ '[class.tng-expansion-panel--expanded]': 'isExpanded()',
1060
+ '[class.tng-expansion-panel--disabled]': 'disabled()'
1061
+ }, template: "<div class=\"tng-expansion-panel__container\">\n <div \n class=\"tng-expansion-panel__header\" \n (click)=\"toggle()\"\n [class.tng-expansion-panel__header--disabled]=\"disabled()\"\n >\n <h3 class=\"tng-expansion-panel__title\">{{ title() }}</h3>\n <span class=\"tng-expansion-panel__icon material-icons\">\n expand_more\n </span>\n </div>\n\n @if (isExpanded()) {\n <div \n class=\"tng-expansion-panel__content\"\n @expandCollapse\n >\n <div class=\"tng-expansion-panel__body\">\n <ng-content></ng-content>\n </div>\n </div>\n }\n</div>\n", styles: [".tng-expansion-panel{display:block;margin-bottom:12px}.tng-expansion-panel__container{background-color:var(--tng-surface);border:1px solid var(--tng-border);border-radius:8px;overflow:hidden;transition:box-shadow .2s cubic-bezier(.4,0,.2,1)}.tng-expansion-panel__header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;cursor:pointer;-webkit-user-select:none;user-select:none;background-color:var(--tng-background);transition:background-color .2s ease,transform .1s ease}.tng-expansion-panel__header:hover:not(.tng-expansion-panel__header--disabled){background-color:color-mix(in srgb,var(--tng-background),var(--tng-text) 5%)}.tng-expansion-panel__header:active:not(.tng-expansion-panel__header--disabled){transform:scale(.99)}.tng-expansion-panel__header--disabled{cursor:not-allowed;opacity:.6}.tng-expansion-panel__title{margin:0;font-size:1rem;font-weight:500;color:var(--tng-text, #333);line-height:1.5}.tng-expansion-panel__icon{font-size:24px;color:var(--tng-text-secondary, #666);transition:transform .3s cubic-bezier(.4,0,.2,1)}.tng-expansion-panel__content{overflow:hidden}.tng-expansion-panel__body{padding:20px;color:var(--tng-text, #333);line-height:1.6}.tng-expansion-panel--expanded .tng-expansion-panel__container{box-shadow:0 2px 4px #0000001a}.tng-expansion-panel--expanded .tng-expansion-panel__icon{transform:rotate(180deg)}.tng-expansion-panel--disabled{opacity:.6;pointer-events:none}\n"] }]
1062
+ }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], toggled: [{ type: i0.Output, args: ["toggled"] }] } });
1063
+
1064
+ class TngMenuComponent {
1065
+ mode = input('vertical', ...(ngDevMode ? [{ debugName: "mode" }] : []));
1066
+ density = input('comfortable', ...(ngDevMode ? [{ debugName: "density" }] : []));
1067
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1068
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: TngMenuComponent, isStandalone: true, selector: "tng-menu", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1069
+ <nav class="tng-menu"
1070
+ [class.tng-menu--horizontal]="mode() === 'horizontal'"
1071
+ [class.tng-menu--vertical]="mode() === 'vertical'"
1072
+ [class.tng-menu--compact]="density() === 'compact'"
1073
+ [class.tng-menu--comfortable]="density() === 'comfortable'">
1074
+ <ng-content></ng-content>
1075
+ </nav>
1076
+ `, isInline: true, styles: [".tng-menu{display:flex;flex-direction:column;width:100%;padding:8px;background:var(--tng-surface, white)}.tng-menu--horizontal{flex-direction:row;padding:0}.tng-menu--vertical{flex-direction:column}.tng-menu--compact ::ng-deep .tng-menu-item__link{padding-top:8px;padding-bottom:8px;font-size:13px}.tng-menu--comfortable ::ng-deep .tng-menu-item__link{padding-top:12px;padding-bottom:12px;font-size:14px}.tng-menu-group__header{padding:16px 16px 8px;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--tng-text-secondary, #666)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1077
+ }
1078
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngMenuComponent, decorators: [{
1079
+ type: Component,
1080
+ args: [{ selector: 'tng-menu', standalone: true, imports: [CommonModule], template: `
1081
+ <nav class="tng-menu"
1082
+ [class.tng-menu--horizontal]="mode() === 'horizontal'"
1083
+ [class.tng-menu--vertical]="mode() === 'vertical'"
1084
+ [class.tng-menu--compact]="density() === 'compact'"
1085
+ [class.tng-menu--comfortable]="density() === 'comfortable'">
1086
+ <ng-content></ng-content>
1087
+ </nav>
1088
+ `, styles: [".tng-menu{display:flex;flex-direction:column;width:100%;padding:8px;background:var(--tng-surface, white)}.tng-menu--horizontal{flex-direction:row;padding:0}.tng-menu--vertical{flex-direction:column}.tng-menu--compact ::ng-deep .tng-menu-item__link{padding-top:8px;padding-bottom:8px;font-size:13px}.tng-menu--comfortable ::ng-deep .tng-menu-item__link{padding-top:12px;padding-bottom:12px;font-size:14px}.tng-menu-group__header{padding:16px 16px 8px;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--tng-text-secondary, #666)}\n"] }]
1089
+ }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }] } });
1090
+
1091
+ class TngMenuItemComponent {
1092
+ icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
1093
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
1094
+ route = input(...(ngDevMode ? [undefined, { debugName: "route" }] : []));
1095
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1096
+ level = input(0, ...(ngDevMode ? [{ debugName: "level" }] : []));
1097
+ children;
1098
+ expanded = signal(false, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
1099
+ hasChildren = signal(false, ...(ngDevMode ? [{ debugName: "hasChildren" }] : []));
1100
+ ngAfterContentInit() {
1101
+ // Check if there are any projected menu items
1102
+ this.updateHasChildren();
1103
+ // Listen for changes in children
1104
+ this.children.changes.subscribe(() => {
1105
+ this.updateHasChildren();
1106
+ });
1107
+ }
1108
+ updateHasChildren() {
1109
+ this.hasChildren.set(this.children.length > 0);
1110
+ }
1111
+ handleClick(event) {
1112
+ if (this.disabled()) {
1113
+ event.preventDefault();
1114
+ return;
1115
+ }
1116
+ if (this.hasChildren()) {
1117
+ event.preventDefault();
1118
+ this.toggleExpanded();
1119
+ }
1120
+ }
1121
+ toggleExpanded() {
1122
+ this.expanded.update(value => !value);
1123
+ }
1124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngMenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1125
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngMenuItemComponent, isStandalone: true, selector: "tng-menu-item", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, route: { classPropertyName: "route", publicName: "route", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "children", predicate: TngMenuItemComponent }], ngImport: i0, template: `
1126
+ <div class="tng-menu-item"
1127
+ [class.tng-menu-item--disabled]="disabled()"
1128
+ [class.tng-menu-item--has-children]="hasChildren()"
1129
+ [class.tng-menu-item--expanded]="expanded()"
1130
+ [style.--level]="level()">
1131
+
1132
+ <!-- Item content (clickable) -->
1133
+ @if (route() && !hasChildren()) {
1134
+ <a [routerLink]="route()"
1135
+ routerLinkActive="tng-menu-item__link--active"
1136
+ class="tng-menu-item__link"
1137
+ [class.tng-menu-item__link--disabled]="disabled()"
1138
+ (click)="handleClick($event)">
1139
+ @if (icon()) {
1140
+ <span class="tng-menu-item__icon">
1141
+ <span class="material-icons">{{ icon() }}</span>
1142
+ </span>
1143
+ }
1144
+ <span class="tng-menu-item__label">
1145
+ <ng-content select="[menu-item-label]"></ng-content>
1146
+ {{ label() }}
1147
+ </span>
1148
+ @if (hasChildren()) {
1149
+ <span class="tng-menu-item__chevron">
1150
+ <span class="material-icons">expand_more</span>
1151
+ </span>
1152
+ }
1153
+ </a>
1154
+ } @else {
1155
+ <button type="button"
1156
+ class="tng-menu-item__link"
1157
+ [class.tng-menu-item__link--disabled]="disabled()"
1158
+ [disabled]="disabled()"
1159
+ (click)="handleClick($event)">
1160
+ @if (icon()) {
1161
+ <span class="tng-menu-item__icon">
1162
+ <span class="material-icons">{{ icon() }}</span>
1163
+ </span>
1164
+ }
1165
+ <span class="tng-menu-item__label">
1166
+ <ng-content select="[menu-item-label]"></ng-content>
1167
+ {{ label() }}
1168
+ </span>
1169
+ @if (hasChildren()) {
1170
+ <span class="tng-menu-item__chevron">
1171
+ <span class="material-icons">expand_more</span>
1172
+ </span>
1173
+ }
1174
+ </button>
1175
+ }
1176
+
1177
+ <!-- Submenu (content projection for nested items) -->
1178
+ @if (hasChildren() && expanded()) {
1179
+ <div class="tng-menu-item__submenu">
1180
+ <ng-content></ng-content>
1181
+ </div>
1182
+ }
1183
+ </div>
1184
+ `, isInline: true, styles: [".tng-menu-item{display:block;position:relative}.tng-menu-item__link{display:flex;align-items:center;padding:12px 16px;padding-left:calc(16px + var(--level, 0) * 24px);text-decoration:none;color:var(--tng-text, #333);background:transparent;border:none;border-left:3px solid transparent;width:100%;text-align:left;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden;font-family:inherit;font-size:14px}.tng-menu-item__link:before{content:\"\";position:absolute;top:50%;left:50%;width:0;height:0;border-radius:50%;background:#0000000d;transform:translate(-50%,-50%);transition:width .6s,height .6s}.tng-menu-item__link:hover:not(.tng-menu-item__link--disabled){background-color:color-mix(in srgb,var(--tng-primary, #3f51b5),white 95%)}.tng-menu-item__link:hover:not(.tng-menu-item__link--disabled):before{width:300px;height:300px}.tng-menu-item__link:active:not(.tng-menu-item__link--disabled){transform:scale(.98)}.tng-menu-item__link--active{background-color:color-mix(in srgb,var(--tng-primary, #3f51b5),white 90%);border-left-color:var(--tng-primary, #3f51b5);color:var(--tng-primary, #3f51b5);font-weight:500}.tng-menu-item__link--active .tng-menu-item__icon{color:var(--tng-primary, #3f51b5)}.tng-menu-item__link--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tng-menu-item__icon{display:flex;align-items:center;justify-content:center;margin-right:16px;color:var(--tng-text-secondary, #666);transition:color .2s}.tng-menu-item__icon .material-icons{font-size:20px}.tng-menu-item__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tng-menu-item__chevron{display:flex;align-items:center;margin-left:8px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.tng-menu-item__chevron .material-icons{font-size:20px;color:var(--tng-text-secondary, #666)}.tng-menu-item--expanded .tng-menu-item__chevron{transform:rotate(180deg)}.tng-menu-item__submenu{overflow:hidden;animation:slideDown .3s cubic-bezier(.4,0,.2,1);background:color-mix(in srgb,var(--tng-surface, white),black 2%)}.tng-menu-item--has-children .tng-menu-item__link:hover .tng-menu-item__chevron .material-icons{color:var(--tng-primary, #3f51b5)}@keyframes slideDown{0%{max-height:0;opacity:0}to{max-height:500px;opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
1185
+ }
1186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngMenuItemComponent, decorators: [{
1187
+ type: Component,
1188
+ args: [{ selector: 'tng-menu-item', standalone: true, imports: [CommonModule, RouterModule], template: `
1189
+ <div class="tng-menu-item"
1190
+ [class.tng-menu-item--disabled]="disabled()"
1191
+ [class.tng-menu-item--has-children]="hasChildren()"
1192
+ [class.tng-menu-item--expanded]="expanded()"
1193
+ [style.--level]="level()">
1194
+
1195
+ <!-- Item content (clickable) -->
1196
+ @if (route() && !hasChildren()) {
1197
+ <a [routerLink]="route()"
1198
+ routerLinkActive="tng-menu-item__link--active"
1199
+ class="tng-menu-item__link"
1200
+ [class.tng-menu-item__link--disabled]="disabled()"
1201
+ (click)="handleClick($event)">
1202
+ @if (icon()) {
1203
+ <span class="tng-menu-item__icon">
1204
+ <span class="material-icons">{{ icon() }}</span>
1205
+ </span>
1206
+ }
1207
+ <span class="tng-menu-item__label">
1208
+ <ng-content select="[menu-item-label]"></ng-content>
1209
+ {{ label() }}
1210
+ </span>
1211
+ @if (hasChildren()) {
1212
+ <span class="tng-menu-item__chevron">
1213
+ <span class="material-icons">expand_more</span>
1214
+ </span>
1215
+ }
1216
+ </a>
1217
+ } @else {
1218
+ <button type="button"
1219
+ class="tng-menu-item__link"
1220
+ [class.tng-menu-item__link--disabled]="disabled()"
1221
+ [disabled]="disabled()"
1222
+ (click)="handleClick($event)">
1223
+ @if (icon()) {
1224
+ <span class="tng-menu-item__icon">
1225
+ <span class="material-icons">{{ icon() }}</span>
1226
+ </span>
1227
+ }
1228
+ <span class="tng-menu-item__label">
1229
+ <ng-content select="[menu-item-label]"></ng-content>
1230
+ {{ label() }}
1231
+ </span>
1232
+ @if (hasChildren()) {
1233
+ <span class="tng-menu-item__chevron">
1234
+ <span class="material-icons">expand_more</span>
1235
+ </span>
1236
+ }
1237
+ </button>
1238
+ }
1239
+
1240
+ <!-- Submenu (content projection for nested items) -->
1241
+ @if (hasChildren() && expanded()) {
1242
+ <div class="tng-menu-item__submenu">
1243
+ <ng-content></ng-content>
1244
+ </div>
1245
+ }
1246
+ </div>
1247
+ `, styles: [".tng-menu-item{display:block;position:relative}.tng-menu-item__link{display:flex;align-items:center;padding:12px 16px;padding-left:calc(16px + var(--level, 0) * 24px);text-decoration:none;color:var(--tng-text, #333);background:transparent;border:none;border-left:3px solid transparent;width:100%;text-align:left;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden;font-family:inherit;font-size:14px}.tng-menu-item__link:before{content:\"\";position:absolute;top:50%;left:50%;width:0;height:0;border-radius:50%;background:#0000000d;transform:translate(-50%,-50%);transition:width .6s,height .6s}.tng-menu-item__link:hover:not(.tng-menu-item__link--disabled){background-color:color-mix(in srgb,var(--tng-primary, #3f51b5),white 95%)}.tng-menu-item__link:hover:not(.tng-menu-item__link--disabled):before{width:300px;height:300px}.tng-menu-item__link:active:not(.tng-menu-item__link--disabled){transform:scale(.98)}.tng-menu-item__link--active{background-color:color-mix(in srgb,var(--tng-primary, #3f51b5),white 90%);border-left-color:var(--tng-primary, #3f51b5);color:var(--tng-primary, #3f51b5);font-weight:500}.tng-menu-item__link--active .tng-menu-item__icon{color:var(--tng-primary, #3f51b5)}.tng-menu-item__link--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tng-menu-item__icon{display:flex;align-items:center;justify-content:center;margin-right:16px;color:var(--tng-text-secondary, #666);transition:color .2s}.tng-menu-item__icon .material-icons{font-size:20px}.tng-menu-item__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tng-menu-item__chevron{display:flex;align-items:center;margin-left:8px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.tng-menu-item__chevron .material-icons{font-size:20px;color:var(--tng-text-secondary, #666)}.tng-menu-item--expanded .tng-menu-item__chevron{transform:rotate(180deg)}.tng-menu-item__submenu{overflow:hidden;animation:slideDown .3s cubic-bezier(.4,0,.2,1);background:color-mix(in srgb,var(--tng-surface, white),black 2%)}.tng-menu-item--has-children .tng-menu-item__link:hover .tng-menu-item__chevron .material-icons{color:var(--tng-primary, #3f51b5)}@keyframes slideDown{0%{max-height:0;opacity:0}to{max-height:500px;opacity:1}}\n"] }]
1248
+ }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], route: [{ type: i0.Input, args: [{ isSignal: true, alias: "route", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], children: [{
1249
+ type: ContentChildren,
1250
+ args: [TngMenuItemComponent]
1251
+ }] } });
1252
+
1253
+ class TngMenuGroupComponent {
1254
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
1255
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngMenuGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1256
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngMenuGroupComponent, isStandalone: true, selector: "tng-menu-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1257
+ <div class="tng-menu-group">
1258
+ @if (label()) {
1259
+ <div class="tng-menu-group__header">{{ label() }}</div>
1260
+ }
1261
+ <ng-content></ng-content>
1262
+ </div>
1263
+ `, isInline: true, styles: [".tng-menu-group{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1264
+ }
1265
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngMenuGroupComponent, decorators: [{
1266
+ type: Component,
1267
+ args: [{ selector: 'tng-menu-group', standalone: true, imports: [CommonModule], template: `
1268
+ <div class="tng-menu-group">
1269
+ @if (label()) {
1270
+ <div class="tng-menu-group__header">{{ label() }}</div>
1271
+ }
1272
+ <ng-content></ng-content>
1273
+ </div>
1274
+ `, styles: [".tng-menu-group{display:block}\n"] }]
1275
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
1276
+
543
1277
  /*
544
1278
  * Public API Surface of tecnualng
545
1279
  */
@@ -548,5 +1282,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
548
1282
  * Generated bundle index. Do not edit.
549
1283
  */
550
1284
 
551
- export { TecnualDatepickerComponent, TecnualInputComponent, TecnualTableComponent, ThemeService, TngButton, TngCardComponent, TngToolbarComponent };
1285
+ export { TecnualDatepickerComponent, TecnualInputComponent, TecnualTableComponent, ThemeService, TngButton, TngCardComponent, TngExpansionPanelComponent, TngMenuComponent, TngMenuGroupComponent, TngMenuItemComponent, TngTabComponent, TngTabsComponent, TngToolbarComponent, TngTooltipComponent, TngTooltipDirective };
552
1286
  //# sourceMappingURL=tecnualng.mjs.map