@avora-labs/meta-forge 1.0.5 → 1.1.2

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.
Files changed (20) hide show
  1. package/README.md +0 -0
  2. package/fesm2022/{avora-labs-meta-forge-amf-auth-shell.component-BWSdjBUS.mjs → avora-labs-meta-forge-amf-auth-shell.component-C89gSPc9.mjs} +59 -59
  3. package/fesm2022/avora-labs-meta-forge-amf-auth-shell.component-C89gSPc9.mjs.map +1 -0
  4. package/fesm2022/{avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs → avora-labs-meta-forge-contact-support.page-C_kdmzhL.mjs} +148 -148
  5. package/fesm2022/avora-labs-meta-forge-contact-support.page-C_kdmzhL.mjs.map +1 -0
  6. package/fesm2022/{avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs → avora-labs-meta-forge-forgot-password.page-PY9_K4M-.mjs} +240 -240
  7. package/fesm2022/avora-labs-meta-forge-forgot-password.page-PY9_K4M-.mjs.map +1 -0
  8. package/fesm2022/{avora-labs-meta-forge-login.page-etTr5NqJ.mjs → avora-labs-meta-forge-login.page-BW-RWCQM.mjs} +76 -76
  9. package/fesm2022/avora-labs-meta-forge-login.page-BW-RWCQM.mjs.map +1 -0
  10. package/fesm2022/avora-labs-meta-forge.mjs +2098 -2098
  11. package/fesm2022/avora-labs-meta-forge.mjs.map +1 -1
  12. package/package.json +13 -6
  13. package/styles/_palettes.scss +84 -84
  14. package/styles/_themes.scss +96 -96
  15. package/styles/_variables.scss +56 -56
  16. package/styles/styles.scss +295 -295
  17. package/fesm2022/avora-labs-meta-forge-amf-auth-shell.component-BWSdjBUS.mjs.map +0 -1
  18. package/fesm2022/avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs.map +0 -1
  19. package/fesm2022/avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs.map +0 -1
  20. package/fesm2022/avora-labs-meta-forge-login.page-etTr5NqJ.mjs.map +0 -1
@@ -156,10 +156,10 @@ class NotificationService {
156
156
  remove(id) {
157
157
  this._notifications.update(n => n.filter(item => item.id !== id));
158
158
  }
159
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
160
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NotificationService, providedIn: 'root' });
159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
160
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotificationService, providedIn: 'root' });
161
161
  }
162
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NotificationService, decorators: [{
162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotificationService, decorators: [{
163
163
  type: Injectable,
164
164
  args: [{
165
165
  providedIn: 'root'
@@ -336,10 +336,10 @@ class MetaStateService {
336
336
  return undefined;
337
337
  }
338
338
  }
339
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
340
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaStateService, providedIn: 'root' });
339
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
340
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaStateService, providedIn: 'root' });
341
341
  }
342
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaStateService, decorators: [{
342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaStateService, decorators: [{
343
343
  type: Injectable,
344
344
  args: [{ providedIn: 'root' }]
345
345
  }] });
@@ -759,10 +759,10 @@ class MetaApiService {
759
759
  }
760
760
  return formData;
761
761
  }
762
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
763
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaApiService, providedIn: 'root' });
762
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
763
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaApiService, providedIn: 'root' });
764
764
  }
765
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaApiService, decorators: [{
765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaApiService, decorators: [{
766
766
  type: Injectable,
767
767
  args: [{ providedIn: 'root' }]
768
768
  }] });
@@ -957,10 +957,10 @@ class ConditionEvaluatorService {
957
957
  return obj;
958
958
  return path.split('.').reduce((current, key) => current?.[key], obj);
959
959
  }
960
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConditionEvaluatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
961
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConditionEvaluatorService, providedIn: 'root' });
960
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConditionEvaluatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
961
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConditionEvaluatorService, providedIn: 'root' });
962
962
  }
963
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConditionEvaluatorService, decorators: [{
963
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConditionEvaluatorService, decorators: [{
964
964
  type: Injectable,
965
965
  args: [{ providedIn: 'root' }]
966
966
  }] });
@@ -995,10 +995,10 @@ class AmfDialogService {
995
995
  });
996
996
  });
997
997
  }
998
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
999
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDialogService, providedIn: 'root' });
998
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
999
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDialogService, providedIn: 'root' });
1000
1000
  }
1001
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDialogService, decorators: [{
1001
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDialogService, decorators: [{
1002
1002
  type: Injectable,
1003
1003
  args: [{ providedIn: 'root' }]
1004
1004
  }] });
@@ -1526,10 +1526,10 @@ class ActionDispatcherService {
1526
1526
  if (el) {
1527
1527
  const printWindow = window.open('', '_blank');
1528
1528
  if (printWindow) {
1529
- printWindow.document.write(`
1530
- <html><head><title>${config.title || 'Print'}</title>
1531
- <style>body { font-family: system-ui, sans-serif; padding: 20px; }</style>
1532
- </head><body>${el.innerHTML}</body></html>
1529
+ printWindow.document.write(`
1530
+ <html><head><title>${config.title || 'Print'}</title>
1531
+ <style>body { font-family: system-ui, sans-serif; padding: 20px; }</style>
1532
+ </head><body>${el.innerHTML}</body></html>
1533
1533
  `);
1534
1534
  printWindow.document.close();
1535
1535
  printWindow.print();
@@ -1624,10 +1624,10 @@ class ActionDispatcherService {
1624
1624
  return undefined;
1625
1625
  return path.split('.').reduce((obj, key) => obj?.[key], context);
1626
1626
  }
1627
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ActionDispatcherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1628
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ActionDispatcherService, providedIn: 'root' });
1627
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActionDispatcherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1628
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActionDispatcherService, providedIn: 'root' });
1629
1629
  }
1630
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ActionDispatcherService, decorators: [{
1630
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ActionDispatcherService, decorators: [{
1631
1631
  type: Injectable,
1632
1632
  args: [{ providedIn: 'root' }]
1633
1633
  }] });
@@ -1645,10 +1645,10 @@ class ComponentRegistryService {
1645
1645
  has(key) { return this.registry.has(key); }
1646
1646
  keys() { return Array.from(this.registry.keys()); }
1647
1647
  unregister(key) { return this.registry.delete(key); }
1648
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1649
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentRegistryService, providedIn: 'root' });
1648
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ComponentRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1649
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ComponentRegistryService, providedIn: 'root' });
1650
1650
  }
1651
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentRegistryService, decorators: [{
1651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ComponentRegistryService, decorators: [{
1652
1652
  type: Injectable,
1653
1653
  args: [{ providedIn: 'root' }]
1654
1654
  }] });
@@ -1696,10 +1696,10 @@ class MetaRendererComponent {
1696
1696
  if (this.section.gridRow)
1697
1697
  hostEl.style.gridRow = this.section.gridRow;
1698
1698
  }
1699
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1700
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: MetaRendererComponent, isStandalone: true, selector: "amf-renderer", inputs: { section: "section", context: "context" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: ["outlet"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: `<ng-container #outlet></ng-container>`, isInline: true, styles: [":host{display:block}\n"] });
1699
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1700
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: MetaRendererComponent, isStandalone: true, selector: "amf-renderer", inputs: { section: "section", context: "context" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: ["outlet"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: `<ng-container #outlet></ng-container>`, isInline: true, styles: [":host{display:block}\n"] });
1701
1701
  }
1702
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaRendererComponent, decorators: [{
1702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaRendererComponent, decorators: [{
1703
1703
  type: Component,
1704
1704
  args: [{ selector: 'amf-renderer', standalone: true, template: `<ng-container #outlet></ng-container>`, styles: [":host{display:block}\n"] }]
1705
1705
  }], propDecorators: { section: [{
@@ -1830,33 +1830,33 @@ class MetaPageComponent {
1830
1830
  }
1831
1831
  return true;
1832
1832
  }
1833
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1834
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: MetaPageComponent, isStandalone: true, selector: "amf-page", ngImport: i0, template: `
1835
- @if (pageMeta()) {
1836
- <div class="amf-page-wrapper" [class]="pageMeta()!.cssClass || ''"
1837
- [class.amf-animate-fade]="pageMeta()!.animation === 'fade'"
1838
- [class.amf-animate-slide-up]="pageMeta()!.animation === 'slide-up'"
1839
- [class.amf-animate-zoom]="pageMeta()!.animation === 'zoom'">
1840
- @for (section of pageMeta()!.sections; track $index) {
1841
- <amf-renderer [section]="section" [context]="context()" class="amf-section"></amf-renderer>
1842
- }
1843
- </div>
1844
- }
1833
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1834
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: MetaPageComponent, isStandalone: true, selector: "amf-page", ngImport: i0, template: `
1835
+ @if (pageMeta()) {
1836
+ <div class="amf-page-wrapper" [class]="pageMeta()!.cssClass || ''"
1837
+ [class.amf-animate-fade]="pageMeta()!.animation === 'fade'"
1838
+ [class.amf-animate-slide-up]="pageMeta()!.animation === 'slide-up'"
1839
+ [class.amf-animate-zoom]="pageMeta()!.animation === 'zoom'">
1840
+ @for (section of pageMeta()!.sections; track $index) {
1841
+ <amf-renderer [section]="section" [context]="context()" class="amf-section"></amf-renderer>
1842
+ }
1843
+ </div>
1844
+ }
1845
1845
  `, isInline: true, styles: [".amf-page-wrapper{display:flex;flex-direction:column;gap:24px;width:100%}.amf-section{display:block;width:100%}.amf-animate-fade{animation:amfFadeIn .3s ease-out}.amf-animate-slide-up{animation:amfSlideUp .3s ease-out}.amf-animate-zoom{animation:amfZoom .3s ease-out}@keyframes amfFadeIn{0%{opacity:0}to{opacity:1}}@keyframes amfSlideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes amfZoom{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}\n"], dependencies: [{ kind: "component", type: MetaRendererComponent, selector: "amf-renderer", inputs: ["section", "context"] }] });
1846
1846
  }
1847
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaPageComponent, decorators: [{
1847
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaPageComponent, decorators: [{
1848
1848
  type: Component,
1849
- args: [{ selector: 'amf-page', standalone: true, imports: [MetaRendererComponent], template: `
1850
- @if (pageMeta()) {
1851
- <div class="amf-page-wrapper" [class]="pageMeta()!.cssClass || ''"
1852
- [class.amf-animate-fade]="pageMeta()!.animation === 'fade'"
1853
- [class.amf-animate-slide-up]="pageMeta()!.animation === 'slide-up'"
1854
- [class.amf-animate-zoom]="pageMeta()!.animation === 'zoom'">
1855
- @for (section of pageMeta()!.sections; track $index) {
1856
- <amf-renderer [section]="section" [context]="context()" class="amf-section"></amf-renderer>
1857
- }
1858
- </div>
1859
- }
1849
+ args: [{ selector: 'amf-page', standalone: true, imports: [MetaRendererComponent], template: `
1850
+ @if (pageMeta()) {
1851
+ <div class="amf-page-wrapper" [class]="pageMeta()!.cssClass || ''"
1852
+ [class.amf-animate-fade]="pageMeta()!.animation === 'fade'"
1853
+ [class.amf-animate-slide-up]="pageMeta()!.animation === 'slide-up'"
1854
+ [class.amf-animate-zoom]="pageMeta()!.animation === 'zoom'">
1855
+ @for (section of pageMeta()!.sections; track $index) {
1856
+ <amf-renderer [section]="section" [context]="context()" class="amf-section"></amf-renderer>
1857
+ }
1858
+ </div>
1859
+ }
1860
1860
  `, styles: [".amf-page-wrapper{display:flex;flex-direction:column;gap:24px;width:100%}.amf-section{display:block;width:100%}.amf-animate-fade{animation:amfFadeIn .3s ease-out}.amf-animate-slide-up{animation:amfSlideUp .3s ease-out}.amf-animate-zoom{animation:amfZoom .3s ease-out}@keyframes amfFadeIn{0%{opacity:0}to{opacity:1}}@keyframes amfSlideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes amfZoom{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}\n"] }]
1861
1861
  }], ctorParameters: () => [] });
1862
1862
 
@@ -2010,10 +2010,10 @@ class AuthService {
2010
2010
  return true;
2011
2011
  }
2012
2012
  }
2013
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AuthService, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
2014
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AuthService, providedIn: 'root' });
2013
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AuthService, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
2014
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AuthService, providedIn: 'root' });
2015
2015
  }
2016
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AuthService, decorators: [{
2016
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AuthService, decorators: [{
2017
2017
  type: Injectable,
2018
2018
  args: [{ providedIn: 'root' }]
2019
2019
  }], ctorParameters: () => [{ type: i1.Router }] });
@@ -2030,10 +2030,10 @@ class PluginRegistryService {
2030
2030
  }
2031
2031
  getAll() { return Array.from(this.plugins.values()); }
2032
2032
  get(name) { return this.plugins.get(name); }
2033
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PluginRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2034
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PluginRegistryService, providedIn: 'root' });
2033
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PluginRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2034
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PluginRegistryService, providedIn: 'root' });
2035
2035
  }
2036
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PluginRegistryService, decorators: [{
2036
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PluginRegistryService, decorators: [{
2037
2037
  type: Injectable,
2038
2038
  args: [{ providedIn: 'root' }]
2039
2039
  }] });
@@ -2250,10 +2250,10 @@ class MetaRouterService {
2250
2250
  return route;
2251
2251
  });
2252
2252
  }
2253
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaRouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2254
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaRouterService, providedIn: 'root' });
2253
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaRouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2254
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaRouterService, providedIn: 'root' });
2255
2255
  }
2256
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaRouterService, decorators: [{
2256
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaRouterService, decorators: [{
2257
2257
  type: Injectable,
2258
2258
  args: [{ providedIn: 'root' }]
2259
2259
  }] });
@@ -2277,21 +2277,21 @@ function getAmfAuthRoutes(meta) {
2277
2277
  if (pages.includes('login')) {
2278
2278
  routes.push({
2279
2279
  path: 'login',
2280
- loadComponent: () => import('./avora-labs-meta-forge-login.page-etTr5NqJ.mjs').then(m => m.LoginComponent),
2280
+ loadComponent: () => import('./avora-labs-meta-forge-login.page-BW-RWCQM.mjs').then(m => m.LoginComponent),
2281
2281
  data: { layout: 'empty' },
2282
2282
  });
2283
2283
  }
2284
2284
  if (pages.includes('forgot-password')) {
2285
2285
  routes.push({
2286
2286
  path: 'forgot-password',
2287
- loadComponent: () => import('./avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs').then(m => m.ForgotPasswordComponent),
2287
+ loadComponent: () => import('./avora-labs-meta-forge-forgot-password.page-PY9_K4M-.mjs').then(m => m.ForgotPasswordComponent),
2288
2288
  data: { layout: 'empty' },
2289
2289
  });
2290
2290
  }
2291
2291
  if (pages.includes('contact-support')) {
2292
2292
  routes.push({
2293
2293
  path: 'contact-support',
2294
- loadComponent: () => import('./avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs').then(m => m.ContactSupportComponent),
2294
+ loadComponent: () => import('./avora-labs-meta-forge-contact-support.page-C_kdmzhL.mjs').then(m => m.ContactSupportComponent),
2295
2295
  data: { layout: 'empty' },
2296
2296
  });
2297
2297
  }
@@ -2346,101 +2346,101 @@ class AccordionSectionComponent {
2346
2346
  }
2347
2347
  this.openPanels.set(current);
2348
2348
  }
2349
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2350
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AccordionSectionComponent, isStandalone: true, selector: "amf-accordion-section", inputs: { config: "config", context: "context" }, usesOnChanges: true, ngImport: i0, template: `
2351
- <div class="amf-accordion"
2352
- [class]="'variant-' + (config.variant || 'default')"
2353
- [class.accordion-bordered]="config.variant === 'bordered'">
2354
- @for (panel of visiblePanels(); track $index) {
2355
- <div class="accordion-panel"
2356
- [class.open]="isOpen($index)"
2357
- [class.disabled]="panel.disabled">
2358
-
2359
- <!-- Panel Header -->
2360
- <button
2361
- type="button"
2362
- class="accordion-header"
2363
- [attr.aria-expanded]="isOpen($index)"
2364
- [disabled]="panel.disabled"
2365
- (click)="togglePanel($index)">
2366
-
2367
- <div class="accordion-header-left">
2368
- @if (panel.icon) {
2369
- <svg class="panel-icon" viewBox="0 0 24 24">
2370
- <path [attr.d]="panel.icon"/>
2371
- </svg>
2372
- }
2373
- <span class="panel-title">{{ panel.title }}</span>
2374
- </div>
2375
-
2376
- <div class="accordion-header-right">
2377
- <svg class="chevron-icon" viewBox="0 0 24 24">
2378
- <path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/>
2379
- </svg>
2380
- </div>
2381
- </button>
2382
-
2383
- <!-- Panel Content -->
2384
- <div class="accordion-body" [class.open]="isOpen($index)">
2385
- <div class="accordion-body-inner">
2386
- @for (section of panel.sections; track $index) {
2387
- <amf-renderer [section]="section" [context]="context" class="amf-section">
2388
- </amf-renderer>
2389
- }
2390
- </div>
2391
- </div>
2392
- </div>
2393
- }
2394
- </div>
2349
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AccordionSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2350
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AccordionSectionComponent, isStandalone: true, selector: "amf-accordion-section", inputs: { config: "config", context: "context" }, usesOnChanges: true, ngImport: i0, template: `
2351
+ <div class="amf-accordion"
2352
+ [class]="'variant-' + (config.variant || 'default')"
2353
+ [class.accordion-bordered]="config.variant === 'bordered'">
2354
+ @for (panel of visiblePanels(); track $index) {
2355
+ <div class="accordion-panel"
2356
+ [class.open]="isOpen($index)"
2357
+ [class.disabled]="panel.disabled">
2358
+
2359
+ <!-- Panel Header -->
2360
+ <button
2361
+ type="button"
2362
+ class="accordion-header"
2363
+ [attr.aria-expanded]="isOpen($index)"
2364
+ [disabled]="panel.disabled"
2365
+ (click)="togglePanel($index)">
2366
+
2367
+ <div class="accordion-header-left">
2368
+ @if (panel.icon) {
2369
+ <svg class="panel-icon" viewBox="0 0 24 24">
2370
+ <path [attr.d]="panel.icon"/>
2371
+ </svg>
2372
+ }
2373
+ <span class="panel-title">{{ panel.title }}</span>
2374
+ </div>
2375
+
2376
+ <div class="accordion-header-right">
2377
+ <svg class="chevron-icon" viewBox="0 0 24 24">
2378
+ <path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/>
2379
+ </svg>
2380
+ </div>
2381
+ </button>
2382
+
2383
+ <!-- Panel Content -->
2384
+ <div class="accordion-body" [class.open]="isOpen($index)">
2385
+ <div class="accordion-body-inner">
2386
+ @for (section of panel.sections; track $index) {
2387
+ <amf-renderer [section]="section" [context]="context" class="amf-section">
2388
+ </amf-renderer>
2389
+ }
2390
+ </div>
2391
+ </div>
2392
+ </div>
2393
+ }
2394
+ </div>
2395
2395
  `, isInline: true, styles: [".amf-accordion{display:flex;flex-direction:column;border-radius:16px;overflow:hidden;border:1px solid var(--app-border);background:var(--app-surface)}.amf-accordion.variant-flush{border:none;border-radius:0;gap:0}.amf-accordion.variant-bordered{gap:8px;border:none;background:transparent;overflow:visible}.accordion-panel{overflow:hidden;transition:box-shadow .2s}.variant-default .accordion-panel+.accordion-panel{border-top:1px solid var(--app-border)}.variant-bordered .accordion-panel{border:1px solid var(--app-border);border-radius:12px;overflow:hidden;background:var(--app-surface);transition:box-shadow .25s}.variant-bordered .accordion-panel.open{box-shadow:0 4px 20px #0000001f;border-color:var(--app-primary)}.accordion-panel.disabled{opacity:.5;pointer-events:none}.accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;background:transparent;border:none;cursor:pointer;text-align:left;transition:background .2s;gap:12px}.accordion-header:hover{background:var(--glass-bg)}.accordion-header:disabled{cursor:not-allowed}.accordion-panel.open .accordion-header{background:var(--glass-bg)}.accordion-header-left{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.panel-icon{width:18px;height:18px;fill:var(--app-primary);flex-shrink:0}.panel-title{font-size:.9375rem;font-weight:600;color:var(--app-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.accordion-header-right{flex-shrink:0}.chevron-icon{width:20px;height:20px;fill:var(--app-text-muted);transition:transform .3s cubic-bezier(.4,0,.2,1)}.accordion-panel.open .chevron-icon{transform:rotate(180deg);fill:var(--app-primary)}.accordion-body{max-height:0;overflow:hidden;transition:max-height .45s cubic-bezier(.4,0,.2,1)}.accordion-body.open{max-height:4000px}.accordion-body-inner{display:flex;flex-direction:column;gap:16px;padding:16px 20px 20px;border-top:1px solid var(--app-border);animation:accordionFadeIn .3s ease-out}@keyframes accordionFadeIn{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}:host{display:block}.amf-section{display:block}\n"], dependencies: [{ kind: "component", type: MetaRendererComponent, selector: "amf-renderer", inputs: ["section", "context"] }] });
2396
2396
  }
2397
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionSectionComponent, decorators: [{
2397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AccordionSectionComponent, decorators: [{
2398
2398
  type: Component,
2399
- args: [{ selector: 'amf-accordion-section', standalone: true, imports: [MetaRendererComponent], template: `
2400
- <div class="amf-accordion"
2401
- [class]="'variant-' + (config.variant || 'default')"
2402
- [class.accordion-bordered]="config.variant === 'bordered'">
2403
- @for (panel of visiblePanels(); track $index) {
2404
- <div class="accordion-panel"
2405
- [class.open]="isOpen($index)"
2406
- [class.disabled]="panel.disabled">
2407
-
2408
- <!-- Panel Header -->
2409
- <button
2410
- type="button"
2411
- class="accordion-header"
2412
- [attr.aria-expanded]="isOpen($index)"
2413
- [disabled]="panel.disabled"
2414
- (click)="togglePanel($index)">
2415
-
2416
- <div class="accordion-header-left">
2417
- @if (panel.icon) {
2418
- <svg class="panel-icon" viewBox="0 0 24 24">
2419
- <path [attr.d]="panel.icon"/>
2420
- </svg>
2421
- }
2422
- <span class="panel-title">{{ panel.title }}</span>
2423
- </div>
2424
-
2425
- <div class="accordion-header-right">
2426
- <svg class="chevron-icon" viewBox="0 0 24 24">
2427
- <path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/>
2428
- </svg>
2429
- </div>
2430
- </button>
2431
-
2432
- <!-- Panel Content -->
2433
- <div class="accordion-body" [class.open]="isOpen($index)">
2434
- <div class="accordion-body-inner">
2435
- @for (section of panel.sections; track $index) {
2436
- <amf-renderer [section]="section" [context]="context" class="amf-section">
2437
- </amf-renderer>
2438
- }
2439
- </div>
2440
- </div>
2441
- </div>
2442
- }
2443
- </div>
2399
+ args: [{ selector: 'amf-accordion-section', standalone: true, imports: [MetaRendererComponent], template: `
2400
+ <div class="amf-accordion"
2401
+ [class]="'variant-' + (config.variant || 'default')"
2402
+ [class.accordion-bordered]="config.variant === 'bordered'">
2403
+ @for (panel of visiblePanels(); track $index) {
2404
+ <div class="accordion-panel"
2405
+ [class.open]="isOpen($index)"
2406
+ [class.disabled]="panel.disabled">
2407
+
2408
+ <!-- Panel Header -->
2409
+ <button
2410
+ type="button"
2411
+ class="accordion-header"
2412
+ [attr.aria-expanded]="isOpen($index)"
2413
+ [disabled]="panel.disabled"
2414
+ (click)="togglePanel($index)">
2415
+
2416
+ <div class="accordion-header-left">
2417
+ @if (panel.icon) {
2418
+ <svg class="panel-icon" viewBox="0 0 24 24">
2419
+ <path [attr.d]="panel.icon"/>
2420
+ </svg>
2421
+ }
2422
+ <span class="panel-title">{{ panel.title }}</span>
2423
+ </div>
2424
+
2425
+ <div class="accordion-header-right">
2426
+ <svg class="chevron-icon" viewBox="0 0 24 24">
2427
+ <path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/>
2428
+ </svg>
2429
+ </div>
2430
+ </button>
2431
+
2432
+ <!-- Panel Content -->
2433
+ <div class="accordion-body" [class.open]="isOpen($index)">
2434
+ <div class="accordion-body-inner">
2435
+ @for (section of panel.sections; track $index) {
2436
+ <amf-renderer [section]="section" [context]="context" class="amf-section">
2437
+ </amf-renderer>
2438
+ }
2439
+ </div>
2440
+ </div>
2441
+ </div>
2442
+ }
2443
+ </div>
2444
2444
  `, styles: [".amf-accordion{display:flex;flex-direction:column;border-radius:16px;overflow:hidden;border:1px solid var(--app-border);background:var(--app-surface)}.amf-accordion.variant-flush{border:none;border-radius:0;gap:0}.amf-accordion.variant-bordered{gap:8px;border:none;background:transparent;overflow:visible}.accordion-panel{overflow:hidden;transition:box-shadow .2s}.variant-default .accordion-panel+.accordion-panel{border-top:1px solid var(--app-border)}.variant-bordered .accordion-panel{border:1px solid var(--app-border);border-radius:12px;overflow:hidden;background:var(--app-surface);transition:box-shadow .25s}.variant-bordered .accordion-panel.open{box-shadow:0 4px 20px #0000001f;border-color:var(--app-primary)}.accordion-panel.disabled{opacity:.5;pointer-events:none}.accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;background:transparent;border:none;cursor:pointer;text-align:left;transition:background .2s;gap:12px}.accordion-header:hover{background:var(--glass-bg)}.accordion-header:disabled{cursor:not-allowed}.accordion-panel.open .accordion-header{background:var(--glass-bg)}.accordion-header-left{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.panel-icon{width:18px;height:18px;fill:var(--app-primary);flex-shrink:0}.panel-title{font-size:.9375rem;font-weight:600;color:var(--app-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.accordion-header-right{flex-shrink:0}.chevron-icon{width:20px;height:20px;fill:var(--app-text-muted);transition:transform .3s cubic-bezier(.4,0,.2,1)}.accordion-panel.open .chevron-icon{transform:rotate(180deg);fill:var(--app-primary)}.accordion-body{max-height:0;overflow:hidden;transition:max-height .45s cubic-bezier(.4,0,.2,1)}.accordion-body.open{max-height:4000px}.accordion-body-inner{display:flex;flex-direction:column;gap:16px;padding:16px 20px 20px;border-top:1px solid var(--app-border);animation:accordionFadeIn .3s ease-out}@keyframes accordionFadeIn{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}:host{display:block}.amf-section{display:block}\n"] }]
2445
2445
  }], propDecorators: { config: [{
2446
2446
  type: Input
@@ -2479,61 +2479,61 @@ class MetaModalHostComponent {
2479
2479
  dispatchAction(actionMeta) {
2480
2480
  this.dispatcher.dispatch(actionMeta, {});
2481
2481
  }
2482
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaModalHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2483
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: MetaModalHostComponent, isStandalone: true, selector: "amf-modal-host", ngImport: i0, template: `
2484
- @if (isOpen()) {
2485
- <div class="amf-modal-backdrop" (click)="closeOnBackdrop($event)">
2486
- <div class="amf-modal-dialog" [ngClass]="['size-' + (config()?.size || 'md')]" (click)="$event.stopPropagation()">
2487
- <div class="amf-modal-header">
2488
- <h3>{{ config()?.title }}</h3>
2489
- <button class="amf-modal-close" (click)="close()">&times;</button>
2490
- </div>
2491
- <div class="amf-modal-content">
2492
- @if (config()?.content) {
2493
- <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2494
- }
2495
- </div>
2496
- @if (config()?.actions?.length) {
2497
- <div class="amf-modal-footer">
2498
- @for (action of config()!.actions; track action.label) {
2499
- <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2500
- {{ action.label }}
2501
- </button>
2502
- }
2503
- </div>
2504
- }
2505
- </div>
2506
- </div>
2507
- }
2482
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaModalHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2483
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: MetaModalHostComponent, isStandalone: true, selector: "amf-modal-host", ngImport: i0, template: `
2484
+ @if (isOpen()) {
2485
+ <div class="amf-modal-backdrop" (click)="closeOnBackdrop($event)">
2486
+ <div class="amf-modal-dialog" [ngClass]="['size-' + (config()?.size || 'md')]" (click)="$event.stopPropagation()">
2487
+ <div class="amf-modal-header">
2488
+ <h3>{{ config()?.title }}</h3>
2489
+ <button class="amf-modal-close" (click)="close()">&times;</button>
2490
+ </div>
2491
+ <div class="amf-modal-content">
2492
+ @if (config()?.content) {
2493
+ <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2494
+ }
2495
+ </div>
2496
+ @if (config()?.actions?.length) {
2497
+ <div class="amf-modal-footer">
2498
+ @for (action of config()!.actions; track action.label) {
2499
+ <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2500
+ {{ action.label }}
2501
+ </button>
2502
+ }
2503
+ </div>
2504
+ }
2505
+ </div>
2506
+ </div>
2507
+ }
2508
2508
  `, isInline: true, styles: [".amf-modal-backdrop{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .2s ease-out}.amf-modal-dialog{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:16px;box-shadow:0 25px 50px -12px #00000080;width:100%;max-height:90vh;overflow-y:auto;display:flex;flex-direction:column;animation:slideUp .3s cubic-bezier(.16,1,.3,1)}.size-sm{max-width:400px}.size-md{max-width:600px}.size-lg{max-width:800px}.size-full{max-width:95vw;height:95vh}.amf-modal-header{padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:space-between;align-items:center}.amf-modal-header h3{font-size:1.25rem;margin:0;color:#fff}.amf-modal-close{background:transparent;border:none;color:#94a3b8;font-size:1.5rem;cursor:pointer;line-height:1;padding:0 4px}.amf-modal-close:hover{color:#fff}.amf-modal-content{padding:24px;flex-grow:1;color:#94a3b8}.amf-modal-footer{padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:flex-end;gap:12px}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MetaRendererComponent, selector: "amf-renderer", inputs: ["section", "context"] }] });
2509
2509
  }
2510
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaModalHostComponent, decorators: [{
2510
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaModalHostComponent, decorators: [{
2511
2511
  type: Component,
2512
- args: [{ selector: 'amf-modal-host', standalone: true, imports: [CommonModule, MetaRendererComponent], template: `
2513
- @if (isOpen()) {
2514
- <div class="amf-modal-backdrop" (click)="closeOnBackdrop($event)">
2515
- <div class="amf-modal-dialog" [ngClass]="['size-' + (config()?.size || 'md')]" (click)="$event.stopPropagation()">
2516
- <div class="amf-modal-header">
2517
- <h3>{{ config()?.title }}</h3>
2518
- <button class="amf-modal-close" (click)="close()">&times;</button>
2519
- </div>
2520
- <div class="amf-modal-content">
2521
- @if (config()?.content) {
2522
- <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2523
- }
2524
- </div>
2525
- @if (config()?.actions?.length) {
2526
- <div class="amf-modal-footer">
2527
- @for (action of config()!.actions; track action.label) {
2528
- <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2529
- {{ action.label }}
2530
- </button>
2531
- }
2532
- </div>
2533
- }
2534
- </div>
2535
- </div>
2536
- }
2512
+ args: [{ selector: 'amf-modal-host', standalone: true, imports: [CommonModule, MetaRendererComponent], template: `
2513
+ @if (isOpen()) {
2514
+ <div class="amf-modal-backdrop" (click)="closeOnBackdrop($event)">
2515
+ <div class="amf-modal-dialog" [ngClass]="['size-' + (config()?.size || 'md')]" (click)="$event.stopPropagation()">
2516
+ <div class="amf-modal-header">
2517
+ <h3>{{ config()?.title }}</h3>
2518
+ <button class="amf-modal-close" (click)="close()">&times;</button>
2519
+ </div>
2520
+ <div class="amf-modal-content">
2521
+ @if (config()?.content) {
2522
+ <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2523
+ }
2524
+ </div>
2525
+ @if (config()?.actions?.length) {
2526
+ <div class="amf-modal-footer">
2527
+ @for (action of config()!.actions; track action.label) {
2528
+ <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2529
+ {{ action.label }}
2530
+ </button>
2531
+ }
2532
+ </div>
2533
+ }
2534
+ </div>
2535
+ </div>
2536
+ }
2537
2537
  `, styles: [".amf-modal-backdrop{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .2s ease-out}.amf-modal-dialog{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:16px;box-shadow:0 25px 50px -12px #00000080;width:100%;max-height:90vh;overflow-y:auto;display:flex;flex-direction:column;animation:slideUp .3s cubic-bezier(.16,1,.3,1)}.size-sm{max-width:400px}.size-md{max-width:600px}.size-lg{max-width:800px}.size-full{max-width:95vw;height:95vh}.amf-modal-header{padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:space-between;align-items:center}.amf-modal-header h3{font-size:1.25rem;margin:0;color:#fff}.amf-modal-close{background:transparent;border:none;color:#94a3b8;font-size:1.5rem;cursor:pointer;line-height:1;padding:0 4px}.amf-modal-close:hover{color:#fff}.amf-modal-content{padding:24px;flex-grow:1;color:#94a3b8}.amf-modal-footer{padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.1));display:flex;justify-content:flex-end;gap:12px}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] }]
2538
2538
  }] });
2539
2539
 
@@ -2594,10 +2594,10 @@ class IconRegistryService {
2594
2594
  this.register('dollar-sign', 'M11.8 10.9c-2.27-.59-3-1.2-3-2.15 0-1.09 1.01-1.85 2.7-1.85 1.78 0 2.44.85 2.5 2.1h2.21c-.07-1.72-1.12-3.3-3.21-3.81V3h-3v2.16c-1.94.42-3.5 1.68-3.5 3.61 0 2.31 1.91 3.46 4.7 4.13 2.5.6 3 1.48 3 2.41 0 .69-.49 1.79-2.7 1.79-2.06 0-2.87-.92-2.98-2.1h-2.2c.12 2.19 1.76 3.42 3.68 3.83V21h3v-2.15c1.95-.37 3.5-1.5 3.5-3.55 0-2.84-2.43-3.81-4.7-4.4z');
2595
2595
  this.register('activity', 'M22 12h-4l-3 9L9 3l-3 9H2');
2596
2596
  }
2597
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IconRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2598
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IconRegistryService, providedIn: 'root' });
2597
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IconRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2598
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IconRegistryService, providedIn: 'root' });
2599
2599
  }
2600
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IconRegistryService, decorators: [{
2600
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: IconRegistryService, decorators: [{
2601
2601
  type: Injectable,
2602
2602
  args: [{ providedIn: 'root' }]
2603
2603
  }], ctorParameters: () => [] });
@@ -2634,85 +2634,85 @@ class AmfDialogHostComponent {
2634
2634
  this.currentDialog.set(null); // Clear the dialog visually
2635
2635
  }
2636
2636
  }
2637
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDialogHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2638
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AmfDialogHostComponent, isStandalone: true, selector: "amf-dialog-host", ngImport: i0, template: `
2639
- @if (currentDialog()) {
2640
- <div class="amf-dialog-backdrop" (click)="onBackdropClick()">
2641
- <div class="amf-dialog-box" (click)="$event.stopPropagation()">
2642
-
2643
- <div class="dialog-header">
2644
- <div class="dialog-icon-wrapper" [ngClass]="'variant-' + (currentDialog()?.config?.variant || 'info')">
2645
- @if (currentDialog()?.config?.icon) {
2646
- <svg viewBox="0 0 24 24" class="icon-element">
2647
- <path [attr.d]="iconPath"></path>
2648
- </svg>
2649
- } @else {
2650
- <span class="icon-fallback">!</span>
2651
- }
2652
- </div>
2653
- @if (currentDialog()?.config?.title) {
2654
- <h3 class="dialog-title">{{ currentDialog()!.config!.title }}</h3>
2655
- }
2656
- </div>
2657
-
2658
- <div class="dialog-content">
2659
- <p class="dialog-message">{{ currentDialog()!.config!.message }}</p>
2660
- </div>
2661
-
2662
- <div class="dialog-actions">
2663
- @if (currentDialog()?.config?.showCancel) {
2664
- <button class="btn btn-cancel" (click)="close(false)">
2665
- {{ currentDialog()?.config?.cancelLabel || 'Cancel' }}
2666
- </button>
2667
- }
2668
- <button class="btn btn-confirm" [ngClass]="'btn-variant-' + (currentDialog()?.config?.variant || 'info')" (click)="close(true)">
2669
- {{ currentDialog()?.config?.confirmLabel || 'OK' }}
2670
- </button>
2671
- </div>
2672
- </div>
2673
- </div>
2674
- }
2637
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDialogHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AmfDialogHostComponent, isStandalone: true, selector: "amf-dialog-host", ngImport: i0, template: `
2639
+ @if (currentDialog()) {
2640
+ <div class="amf-dialog-backdrop" (click)="onBackdropClick()">
2641
+ <div class="amf-dialog-box" (click)="$event.stopPropagation()">
2642
+
2643
+ <div class="dialog-header">
2644
+ <div class="dialog-icon-wrapper" [ngClass]="'variant-' + (currentDialog()?.config?.variant || 'info')">
2645
+ @if (currentDialog()?.config?.icon) {
2646
+ <svg viewBox="0 0 24 24" class="icon-element">
2647
+ <path [attr.d]="iconPath"></path>
2648
+ </svg>
2649
+ } @else {
2650
+ <span class="icon-fallback">!</span>
2651
+ }
2652
+ </div>
2653
+ @if (currentDialog()?.config?.title) {
2654
+ <h3 class="dialog-title">{{ currentDialog()!.config!.title }}</h3>
2655
+ }
2656
+ </div>
2657
+
2658
+ <div class="dialog-content">
2659
+ <p class="dialog-message">{{ currentDialog()!.config!.message }}</p>
2660
+ </div>
2661
+
2662
+ <div class="dialog-actions">
2663
+ @if (currentDialog()?.config?.showCancel) {
2664
+ <button class="btn btn-cancel" (click)="close(false)">
2665
+ {{ currentDialog()?.config?.cancelLabel || 'Cancel' }}
2666
+ </button>
2667
+ }
2668
+ <button class="btn btn-confirm" [ngClass]="'btn-variant-' + (currentDialog()?.config?.variant || 'info')" (click)="close(true)">
2669
+ {{ currentDialog()?.config?.confirmLabel || 'OK' }}
2670
+ </button>
2671
+ </div>
2672
+ </div>
2673
+ </div>
2674
+ }
2675
2675
  `, isInline: true, styles: [".amf-dialog-backdrop{position:fixed;inset:0;background:#0a0f1ebf;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:10000;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .25s ease-out}.amf-dialog-box{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:20px;box-shadow:0 25px 50px -12px #0009,0 0 0 1px #ffffff0d inset;width:100%;max-width:420px;display:flex;flex-direction:column;animation:popIn .3s cubic-bezier(.16,1,.3,1);overflow:hidden}.dialog-header{padding:32px 32px 16px;display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.dialog-icon-wrapper{width:64px;height:64px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:32px;color:#fff;box-shadow:0 8px 16px -4px #0000004d}.dialog-icon-wrapper.variant-info{background:linear-gradient(135deg,#3b82f6,#2563eb);box-shadow:0 8px 24px -6px #3b82f680}.dialog-icon-wrapper.variant-success{background:linear-gradient(135deg,#10b981,#059669);box-shadow:0 8px 24px -6px #10b98180}.dialog-icon-wrapper.variant-warning{background:linear-gradient(135deg,#f59e0b,#d97706);box-shadow:0 8px 24px -6px #f59e0b80}.dialog-icon-wrapper.variant-danger{background:linear-gradient(135deg,#ef4444,#dc2626);box-shadow:0 8px 24px -6px #ef444480}.icon-element{width:32px;height:32px;display:block;filter:drop-shadow(0 2px 2px rgba(0,0,0,.2))}.icon-fallback{font-family:monospace;font-weight:700}.dialog-title{margin:0;color:var(--app-text, #ffffff);font-size:1.25rem;font-weight:700;letter-spacing:-.02em}.dialog-content{padding:0 32px 32px;text-align:center}.dialog-message{margin:0;color:var(--app-text-muted, #94a3b8);font-size:.95rem;line-height:1.5}.dialog-actions{display:flex;gap:12px;padding:24px 32px;background:#0003;border-top:1px solid var(--app-border, rgba(255,255,255,.05))}.btn{flex:1;padding:12px 20px;border-radius:12px;font-size:.9rem;font-weight:600;cursor:pointer;transition:all .2s;border:none;display:inline-flex;align-items:center;justify-content:center}.btn-cancel{background:#ffffff0d;color:var(--app-text, #ffffff);border:1px solid rgba(255,255,255,.1)}.btn-cancel:hover{background:#ffffff1a}.btn-confirm{color:#fff;box-shadow:0 4px 12px transparent}.btn-confirm:hover{transform:translateY(-1px)}.btn-variant-info{background:#3b82f6;box-shadow:0 4px 12px #3b82f64d}.btn-variant-info:hover{background:#60a5fa;box-shadow:0 6px 16px #3b82f666}.btn-variant-success{background:#10b981;box-shadow:0 4px 12px #10b9814d}.btn-variant-success:hover{background:#34d399;box-shadow:0 6px 16px #10b98166}.btn-variant-warning{background:#f59e0b;box-shadow:0 4px 12px #f59e0b4d}.btn-variant-warning:hover{background:#fbbf24;box-shadow:0 6px 16px #f59e0b66}.btn-variant-danger{background:#ef4444;box-shadow:0 4px 12px #ef44444d}.btn-variant-danger:hover{background:#f87171;box-shadow:0 6px 16px #ef444466}@keyframes fadeIn{0%{opacity:0;-webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px)}to{opacity:1;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}}@keyframes popIn{0%{opacity:0;transform:scale(.9) translateY(10px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
2676
2676
  }
2677
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDialogHostComponent, decorators: [{
2677
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDialogHostComponent, decorators: [{
2678
2678
  type: Component,
2679
- args: [{ selector: 'amf-dialog-host', standalone: true, imports: [CommonModule], template: `
2680
- @if (currentDialog()) {
2681
- <div class="amf-dialog-backdrop" (click)="onBackdropClick()">
2682
- <div class="amf-dialog-box" (click)="$event.stopPropagation()">
2683
-
2684
- <div class="dialog-header">
2685
- <div class="dialog-icon-wrapper" [ngClass]="'variant-' + (currentDialog()?.config?.variant || 'info')">
2686
- @if (currentDialog()?.config?.icon) {
2687
- <svg viewBox="0 0 24 24" class="icon-element">
2688
- <path [attr.d]="iconPath"></path>
2689
- </svg>
2690
- } @else {
2691
- <span class="icon-fallback">!</span>
2692
- }
2693
- </div>
2694
- @if (currentDialog()?.config?.title) {
2695
- <h3 class="dialog-title">{{ currentDialog()!.config!.title }}</h3>
2696
- }
2697
- </div>
2698
-
2699
- <div class="dialog-content">
2700
- <p class="dialog-message">{{ currentDialog()!.config!.message }}</p>
2701
- </div>
2702
-
2703
- <div class="dialog-actions">
2704
- @if (currentDialog()?.config?.showCancel) {
2705
- <button class="btn btn-cancel" (click)="close(false)">
2706
- {{ currentDialog()?.config?.cancelLabel || 'Cancel' }}
2707
- </button>
2708
- }
2709
- <button class="btn btn-confirm" [ngClass]="'btn-variant-' + (currentDialog()?.config?.variant || 'info')" (click)="close(true)">
2710
- {{ currentDialog()?.config?.confirmLabel || 'OK' }}
2711
- </button>
2712
- </div>
2713
- </div>
2714
- </div>
2715
- }
2679
+ args: [{ selector: 'amf-dialog-host', standalone: true, imports: [CommonModule], template: `
2680
+ @if (currentDialog()) {
2681
+ <div class="amf-dialog-backdrop" (click)="onBackdropClick()">
2682
+ <div class="amf-dialog-box" (click)="$event.stopPropagation()">
2683
+
2684
+ <div class="dialog-header">
2685
+ <div class="dialog-icon-wrapper" [ngClass]="'variant-' + (currentDialog()?.config?.variant || 'info')">
2686
+ @if (currentDialog()?.config?.icon) {
2687
+ <svg viewBox="0 0 24 24" class="icon-element">
2688
+ <path [attr.d]="iconPath"></path>
2689
+ </svg>
2690
+ } @else {
2691
+ <span class="icon-fallback">!</span>
2692
+ }
2693
+ </div>
2694
+ @if (currentDialog()?.config?.title) {
2695
+ <h3 class="dialog-title">{{ currentDialog()!.config!.title }}</h3>
2696
+ }
2697
+ </div>
2698
+
2699
+ <div class="dialog-content">
2700
+ <p class="dialog-message">{{ currentDialog()!.config!.message }}</p>
2701
+ </div>
2702
+
2703
+ <div class="dialog-actions">
2704
+ @if (currentDialog()?.config?.showCancel) {
2705
+ <button class="btn btn-cancel" (click)="close(false)">
2706
+ {{ currentDialog()?.config?.cancelLabel || 'Cancel' }}
2707
+ </button>
2708
+ }
2709
+ <button class="btn btn-confirm" [ngClass]="'btn-variant-' + (currentDialog()?.config?.variant || 'info')" (click)="close(true)">
2710
+ {{ currentDialog()?.config?.confirmLabel || 'OK' }}
2711
+ </button>
2712
+ </div>
2713
+ </div>
2714
+ </div>
2715
+ }
2716
2716
  `, styles: [".amf-dialog-backdrop{position:fixed;inset:0;background:#0a0f1ebf;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:10000;display:flex;align-items:center;justify-content:center;padding:20px;animation:fadeIn .25s ease-out}.amf-dialog-box{background:var(--glass-bg, rgba(20,25,40,.9));border:1px solid var(--app-border, rgba(255,255,255,.1));border-radius:20px;box-shadow:0 25px 50px -12px #0009,0 0 0 1px #ffffff0d inset;width:100%;max-width:420px;display:flex;flex-direction:column;animation:popIn .3s cubic-bezier(.16,1,.3,1);overflow:hidden}.dialog-header{padding:32px 32px 16px;display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.dialog-icon-wrapper{width:64px;height:64px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:32px;color:#fff;box-shadow:0 8px 16px -4px #0000004d}.dialog-icon-wrapper.variant-info{background:linear-gradient(135deg,#3b82f6,#2563eb);box-shadow:0 8px 24px -6px #3b82f680}.dialog-icon-wrapper.variant-success{background:linear-gradient(135deg,#10b981,#059669);box-shadow:0 8px 24px -6px #10b98180}.dialog-icon-wrapper.variant-warning{background:linear-gradient(135deg,#f59e0b,#d97706);box-shadow:0 8px 24px -6px #f59e0b80}.dialog-icon-wrapper.variant-danger{background:linear-gradient(135deg,#ef4444,#dc2626);box-shadow:0 8px 24px -6px #ef444480}.icon-element{width:32px;height:32px;display:block;filter:drop-shadow(0 2px 2px rgba(0,0,0,.2))}.icon-fallback{font-family:monospace;font-weight:700}.dialog-title{margin:0;color:var(--app-text, #ffffff);font-size:1.25rem;font-weight:700;letter-spacing:-.02em}.dialog-content{padding:0 32px 32px;text-align:center}.dialog-message{margin:0;color:var(--app-text-muted, #94a3b8);font-size:.95rem;line-height:1.5}.dialog-actions{display:flex;gap:12px;padding:24px 32px;background:#0003;border-top:1px solid var(--app-border, rgba(255,255,255,.05))}.btn{flex:1;padding:12px 20px;border-radius:12px;font-size:.9rem;font-weight:600;cursor:pointer;transition:all .2s;border:none;display:inline-flex;align-items:center;justify-content:center}.btn-cancel{background:#ffffff0d;color:var(--app-text, #ffffff);border:1px solid rgba(255,255,255,.1)}.btn-cancel:hover{background:#ffffff1a}.btn-confirm{color:#fff;box-shadow:0 4px 12px transparent}.btn-confirm:hover{transform:translateY(-1px)}.btn-variant-info{background:#3b82f6;box-shadow:0 4px 12px #3b82f64d}.btn-variant-info:hover{background:#60a5fa;box-shadow:0 6px 16px #3b82f666}.btn-variant-success{background:#10b981;box-shadow:0 4px 12px #10b9814d}.btn-variant-success:hover{background:#34d399;box-shadow:0 6px 16px #10b98166}.btn-variant-warning{background:#f59e0b;box-shadow:0 4px 12px #f59e0b4d}.btn-variant-warning:hover{background:#fbbf24;box-shadow:0 6px 16px #f59e0b66}.btn-variant-danger{background:#ef4444;box-shadow:0 4px 12px #ef44444d}.btn-variant-danger:hover{background:#f87171;box-shadow:0 6px 16px #ef444466}@keyframes fadeIn{0%{opacity:0;-webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px)}to{opacity:1;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}}@keyframes popIn{0%{opacity:0;transform:scale(.9) translateY(10px)}to{opacity:1;transform:scale(1) translateY(0)}}\n"] }]
2717
2717
  }] });
2718
2718
 
@@ -2749,75 +2749,75 @@ class AmfDrawerHostComponent {
2749
2749
  dispatchAction(actionMeta) {
2750
2750
  this.dispatcher.dispatch(actionMeta, {});
2751
2751
  }
2752
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDrawerHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2753
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AmfDrawerHostComponent, isStandalone: true, selector: "amf-drawer-host", ngImport: i0, template: `
2754
- @if (isOpen()) {
2755
- <!-- Backdrop -->
2756
- <div class="amf-drawer-backdrop" (click)="closeOnBackdrop()"></div>
2757
- }
2758
- <!-- Drawer panel — always in DOM so the CSS slide animation works -->
2759
- <div class="amf-drawer-panel"
2760
- [class.is-open]="isOpen()"
2761
- [style.width]="config()?.size || '420px'"
2762
- [class.position-left]="config()?.position === 'left'"
2763
- (click)="$event.stopPropagation()">
2764
- @if (isOpen() && config()) {
2765
- <div class="amf-drawer-header">
2766
- <h3>{{ config()?.title }}</h3>
2767
- <button class="amf-drawer-close" (click)="close()" aria-label="Close drawer">&times;</button>
2768
- </div>
2769
- <div class="amf-drawer-content">
2770
- @if (config()?.content) {
2771
- <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2772
- }
2773
- </div>
2774
- @if (config()?.actions?.length) {
2775
- <div class="amf-drawer-footer">
2776
- @for (action of config()!.actions; track action.label) {
2777
- <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2778
- {{ action.label }}
2779
- </button>
2780
- }
2781
- </div>
2782
- }
2783
- }
2784
- </div>
2752
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDrawerHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2753
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AmfDrawerHostComponent, isStandalone: true, selector: "amf-drawer-host", ngImport: i0, template: `
2754
+ @if (isOpen()) {
2755
+ <!-- Backdrop -->
2756
+ <div class="amf-drawer-backdrop" (click)="closeOnBackdrop()"></div>
2757
+ }
2758
+ <!-- Drawer panel — always in DOM so the CSS slide animation works -->
2759
+ <div class="amf-drawer-panel"
2760
+ [class.is-open]="isOpen()"
2761
+ [style.width]="config()?.size || '420px'"
2762
+ [class.position-left]="config()?.position === 'left'"
2763
+ (click)="$event.stopPropagation()">
2764
+ @if (isOpen() && config()) {
2765
+ <div class="amf-drawer-header">
2766
+ <h3>{{ config()?.title }}</h3>
2767
+ <button class="amf-drawer-close" (click)="close()" aria-label="Close drawer">&times;</button>
2768
+ </div>
2769
+ <div class="amf-drawer-content">
2770
+ @if (config()?.content) {
2771
+ <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2772
+ }
2773
+ </div>
2774
+ @if (config()?.actions?.length) {
2775
+ <div class="amf-drawer-footer">
2776
+ @for (action of config()!.actions; track action.label) {
2777
+ <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2778
+ {{ action.label }}
2779
+ </button>
2780
+ }
2781
+ </div>
2782
+ }
2783
+ }
2784
+ </div>
2785
2785
  `, isInline: true, styles: [".amf-drawer-backdrop{position:fixed;inset:0;background:#0000008c;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1200;animation:fadeIn .25s ease-out}.amf-drawer-panel{position:fixed;top:0;right:0;height:100%;max-width:95vw;background:var(--glass-bg, rgba(15, 20, 40, .97));border-left:1px solid var(--app-border, rgba(255,255,255,.08));box-shadow:-20px 0 60px #00000080;z-index:1201;display:flex;flex-direction:column;transform:translate(100%);transition:transform .35s cubic-bezier(.16,1,.3,1);will-change:transform;overflow:hidden}.amf-drawer-panel.position-left{right:auto;left:0;border-left:none;border-right:1px solid var(--app-border, rgba(255,255,255,.08));transform:translate(-100%)}.amf-drawer-panel.is-open{transform:translate(0)}.amf-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.08));flex-shrink:0}.amf-drawer-header h3{margin:0;font-size:1.125rem;font-weight:700;color:var(--app-text, #f1f5f9);letter-spacing:-.01em}.amf-drawer-close{background:#ffffff0f;border:1px solid rgba(255,255,255,.08);color:var(--app-text-muted, #94a3b8);font-size:1.25rem;line-height:1;width:32px;height:32px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.amf-drawer-close:hover{background:#ffffff1f;color:var(--app-text, #f1f5f9)}.amf-drawer-content{flex:1;overflow-y:auto;padding:24px}.amf-drawer-footer{flex-shrink:0;padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.08));display:flex;justify-content:flex-end;gap:12px;background:#00000026}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px var(--app-glow)}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600;transition:all .2s}.btn-outline:hover{background:#ffffff0f}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "component", type: MetaRendererComponent, selector: "amf-renderer", inputs: ["section", "context"] }] });
2786
2786
  }
2787
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AmfDrawerHostComponent, decorators: [{
2787
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AmfDrawerHostComponent, decorators: [{
2788
2788
  type: Component,
2789
- args: [{ selector: 'amf-drawer-host', standalone: true, imports: [MetaRendererComponent], template: `
2790
- @if (isOpen()) {
2791
- <!-- Backdrop -->
2792
- <div class="amf-drawer-backdrop" (click)="closeOnBackdrop()"></div>
2793
- }
2794
- <!-- Drawer panel — always in DOM so the CSS slide animation works -->
2795
- <div class="amf-drawer-panel"
2796
- [class.is-open]="isOpen()"
2797
- [style.width]="config()?.size || '420px'"
2798
- [class.position-left]="config()?.position === 'left'"
2799
- (click)="$event.stopPropagation()">
2800
- @if (isOpen() && config()) {
2801
- <div class="amf-drawer-header">
2802
- <h3>{{ config()?.title }}</h3>
2803
- <button class="amf-drawer-close" (click)="close()" aria-label="Close drawer">&times;</button>
2804
- </div>
2805
- <div class="amf-drawer-content">
2806
- @if (config()?.content) {
2807
- <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2808
- }
2809
- </div>
2810
- @if (config()?.actions?.length) {
2811
- <div class="amf-drawer-footer">
2812
- @for (action of config()!.actions; track action.label) {
2813
- <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2814
- {{ action.label }}
2815
- </button>
2816
- }
2817
- </div>
2818
- }
2819
- }
2820
- </div>
2789
+ args: [{ selector: 'amf-drawer-host', standalone: true, imports: [MetaRendererComponent], template: `
2790
+ @if (isOpen()) {
2791
+ <!-- Backdrop -->
2792
+ <div class="amf-drawer-backdrop" (click)="closeOnBackdrop()"></div>
2793
+ }
2794
+ <!-- Drawer panel — always in DOM so the CSS slide animation works -->
2795
+ <div class="amf-drawer-panel"
2796
+ [class.is-open]="isOpen()"
2797
+ [style.width]="config()?.size || '420px'"
2798
+ [class.position-left]="config()?.position === 'left'"
2799
+ (click)="$event.stopPropagation()">
2800
+ @if (isOpen() && config()) {
2801
+ <div class="amf-drawer-header">
2802
+ <h3>{{ config()?.title }}</h3>
2803
+ <button class="amf-drawer-close" (click)="close()" aria-label="Close drawer">&times;</button>
2804
+ </div>
2805
+ <div class="amf-drawer-content">
2806
+ @if (config()?.content) {
2807
+ <amf-renderer [section]="config()!.content" [context]="{}"></amf-renderer>
2808
+ }
2809
+ </div>
2810
+ @if (config()?.actions?.length) {
2811
+ <div class="amf-drawer-footer">
2812
+ @for (action of config()!.actions; track action.label) {
2813
+ <button [class]="'btn-' + (action.color || 'primary')" (click)="dispatchAction(action.action)">
2814
+ {{ action.label }}
2815
+ </button>
2816
+ }
2817
+ </div>
2818
+ }
2819
+ }
2820
+ </div>
2821
2821
  `, styles: [".amf-drawer-backdrop{position:fixed;inset:0;background:#0000008c;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1200;animation:fadeIn .25s ease-out}.amf-drawer-panel{position:fixed;top:0;right:0;height:100%;max-width:95vw;background:var(--glass-bg, rgba(15, 20, 40, .97));border-left:1px solid var(--app-border, rgba(255,255,255,.08));box-shadow:-20px 0 60px #00000080;z-index:1201;display:flex;flex-direction:column;transform:translate(100%);transition:transform .35s cubic-bezier(.16,1,.3,1);will-change:transform;overflow:hidden}.amf-drawer-panel.position-left{right:auto;left:0;border-left:none;border-right:1px solid var(--app-border, rgba(255,255,255,.08));transform:translate(-100%)}.amf-drawer-panel.is-open{transform:translate(0)}.amf-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--app-border, rgba(255,255,255,.08));flex-shrink:0}.amf-drawer-header h3{margin:0;font-size:1.125rem;font-weight:700;color:var(--app-text, #f1f5f9);letter-spacing:-.01em}.amf-drawer-close{background:#ffffff0f;border:1px solid rgba(255,255,255,.08);color:var(--app-text-muted, #94a3b8);font-size:1.25rem;line-height:1;width:32px;height:32px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.amf-drawer-close:hover{background:#ffffff1f;color:var(--app-text, #f1f5f9)}.amf-drawer-content{flex:1;overflow-y:auto;padding:24px}.amf-drawer-footer{flex-shrink:0;padding:16px 24px;border-top:1px solid var(--app-border, rgba(255,255,255,.08));display:flex;justify-content:flex-end;gap:12px;background:#00000026}.btn-primary{background:linear-gradient(135deg,var(--app-primary, #6366f1),var(--app-accent, #c084fc));color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px var(--app-glow)}.btn-outline{background:transparent;border:1px solid #475569;color:#e2e8f0;padding:10px 20px;border-radius:8px;cursor:pointer;font-weight:600;transition:all .2s}.btn-outline:hover{background:#ffffff0f}.btn-danger{background:#ef4444;color:#fff;padding:10px 20px;border-radius:8px;border:none;cursor:pointer;font-weight:600}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
2822
2822
  }] });
2823
2823
 
@@ -3035,10 +3035,10 @@ class MetaAuthService {
3035
3035
  const storage = this.getStorage();
3036
3036
  return storage.getItem(key);
3037
3037
  }
3038
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3039
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaAuthService, providedIn: 'root' });
3038
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3039
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaAuthService, providedIn: 'root' });
3040
3040
  }
3041
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: MetaAuthService, decorators: [{
3041
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MetaAuthService, decorators: [{
3042
3042
  type: Injectable,
3043
3043
  args: [{ providedIn: 'root' }]
3044
3044
  }] });
@@ -3096,10 +3096,10 @@ class ValidatorFactoryService {
3096
3096
  return error.message;
3097
3097
  return 'Invalid field';
3098
3098
  }
3099
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ValidatorFactoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3100
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ValidatorFactoryService, providedIn: 'root' });
3099
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ValidatorFactoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3100
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ValidatorFactoryService, providedIn: 'root' });
3101
3101
  }
3102
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ValidatorFactoryService, decorators: [{
3102
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ValidatorFactoryService, decorators: [{
3103
3103
  type: Injectable,
3104
3104
  args: [{ providedIn: 'root' }]
3105
3105
  }] });
@@ -3147,119 +3147,119 @@ class RepeaterFieldComponent {
3147
3147
  return;
3148
3148
  this.formArray.removeAt(index);
3149
3149
  }
3150
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RepeaterFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3151
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: RepeaterFieldComponent, isStandalone: true, selector: "amf-repeater-field", inputs: { field: "field", formArray: "formArray", formDisabled: "formDisabled", actionDispatcher: "actionDispatcher", context: "context" }, ngImport: i0, template: `
3152
- <div class="amf-repeater" [class]="field.cssClass">
3153
- <!-- ── Header & Global Add ── -->
3154
- <div class="repeater-header">
3155
- <label class="repeater-label">{{ field.label }}</label>
3156
- @if (canAdd) {
3157
- <button type="button" class="btn-repeater-add" (click)="addItem()" [disabled]="formDisabled">
3158
- <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3159
- {{ field.addLabel || 'Add Item' }}
3160
- </button>
3161
- }
3162
- </div>
3163
-
3164
- @if (field.description) {
3165
- <p class="repeater-description">{{ field.description }}</p>
3166
- }
3167
-
3168
- <div class="repeater-list">
3169
- @for (ctrl of formArray.controls; track $index) {
3170
- <div class="repeater-item-card">
3171
- <div class="repeater-item-header">
3172
- <span class="item-title">Item {{ $index + 1 }}</span>
3173
- @if (canRemove) {
3174
- <button type="button" class="btn-repeater-remove" (click)="removeItem($index)" [disabled]="formDisabled" title="Remove Item">
3175
- <svg viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.12-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/></svg>
3176
- </button>
3177
- }
3178
- </div>
3179
-
3180
- <div class="repeater-item-body">
3181
- <div class="repeater-fields-grid" [style.grid-template-columns]="getGridStyle(field)">
3182
- @for (child of field.children || []; track child.key) {
3183
- <amf-field-renderer
3184
- [field]="child"
3185
- [form]="getFormGroup(ctrl)"
3186
- [formDisabled]="formDisabled"
3187
- [actionDispatcher]="actionDispatcher"
3188
- [context]="context"
3189
- [style.grid-column]="child.colSpan ? 'span ' + child.colSpan : null">
3190
- </amf-field-renderer>
3191
- }
3192
- </div>
3193
- </div>
3194
- </div>
3195
- }
3196
-
3197
- @if (formArray.controls.length === 0) {
3198
- <div class="repeater-empty-state">
3199
- <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3200
- <p>No items added yet. Click "{{ field.addLabel || 'Add Item' }}" to begin.</p>
3201
- </div>
3202
- }
3203
- </div>
3204
- </div>
3150
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RepeaterFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3151
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: RepeaterFieldComponent, isStandalone: true, selector: "amf-repeater-field", inputs: { field: "field", formArray: "formArray", formDisabled: "formDisabled", actionDispatcher: "actionDispatcher", context: "context" }, ngImport: i0, template: `
3152
+ <div class="amf-repeater" [class]="field.cssClass">
3153
+ <!-- ── Header & Global Add ── -->
3154
+ <div class="repeater-header">
3155
+ <label class="repeater-label">{{ field.label }}</label>
3156
+ @if (canAdd) {
3157
+ <button type="button" class="btn-repeater-add" (click)="addItem()" [disabled]="formDisabled">
3158
+ <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3159
+ {{ field.addLabel || 'Add Item' }}
3160
+ </button>
3161
+ }
3162
+ </div>
3163
+
3164
+ @if (field.description) {
3165
+ <p class="repeater-description">{{ field.description }}</p>
3166
+ }
3167
+
3168
+ <div class="repeater-list">
3169
+ @for (ctrl of formArray.controls; track $index) {
3170
+ <div class="repeater-item-card">
3171
+ <div class="repeater-item-header">
3172
+ <span class="item-title">Item {{ $index + 1 }}</span>
3173
+ @if (canRemove) {
3174
+ <button type="button" class="btn-repeater-remove" (click)="removeItem($index)" [disabled]="formDisabled" title="Remove Item">
3175
+ <svg viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.12-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/></svg>
3176
+ </button>
3177
+ }
3178
+ </div>
3179
+
3180
+ <div class="repeater-item-body">
3181
+ <div class="repeater-fields-grid" [style.grid-template-columns]="getGridStyle(field)">
3182
+ @for (child of field.children || []; track child.key) {
3183
+ <amf-field-renderer
3184
+ [field]="child"
3185
+ [form]="getFormGroup(ctrl)"
3186
+ [formDisabled]="formDisabled"
3187
+ [actionDispatcher]="actionDispatcher"
3188
+ [context]="context"
3189
+ [style.grid-column]="child.colSpan ? 'span ' + child.colSpan : null">
3190
+ </amf-field-renderer>
3191
+ }
3192
+ </div>
3193
+ </div>
3194
+ </div>
3195
+ }
3196
+
3197
+ @if (formArray.controls.length === 0) {
3198
+ <div class="repeater-empty-state">
3199
+ <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3200
+ <p>No items added yet. Click "{{ field.addLabel || 'Add Item' }}" to begin.</p>
3201
+ </div>
3202
+ }
3203
+ </div>
3204
+ </div>
3205
3205
  `, isInline: true, styles: [".amf-repeater{margin-bottom:24px}.repeater-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.repeater-label{font-size:.9375rem;font-weight:600;color:var(--app-text);margin:0}.repeater-description{font-size:.8125rem;color:var(--app-text-muted);margin:0 0 16px}.btn-repeater-add{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;font-size:.8125rem;font-weight:500;font-family:inherit;cursor:pointer;border:1px solid rgba(59,130,246,.3);border-radius:6px;background:#3b82f61a;color:#3b82f6;transition:all .2s}.btn-repeater-add svg{width:14px;height:14px;fill:currentColor}.btn-repeater-add:hover:not(:disabled){background:#3b82f633}.btn-repeater-add:disabled{opacity:.5;cursor:not-allowed}.repeater-list{display:flex;flex-direction:column;gap:16px}.repeater-item-card{background:var(--app-surface-hover);border:1px solid var(--app-border);border-radius:8px;overflow:hidden;transition:box-shadow .2s}.repeater-item-card:hover{border-color:#3b82f64d}.repeater-item-header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--app-border);background:#00000005}:host-context(body.amf-dark) .repeater-item-header{background:#ffffff05}.item-title{font-size:.8125rem;font-weight:600;color:var(--app-text);text-transform:uppercase;letter-spacing:.5px}.btn-repeater-remove{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:4px;background:transparent;color:#ef4444;cursor:pointer;transition:background .2s}.btn-repeater-remove svg{width:18px;height:18px;fill:currentColor}.btn-repeater-remove:hover:not(:disabled){background:#ef44441a}.btn-repeater-remove:disabled{opacity:.5;cursor:not-allowed}.repeater-item-body{padding:16px}.repeater-fields-grid{display:grid;gap:16px}.repeater-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px 16px;text-align:center;border:1.5px dashed var(--app-border);border-radius:8px;color:var(--app-text-muted);background:var(--app-surface-hover)}.repeater-empty-state svg{width:32px;height:32px;fill:currentColor;opacity:.5;margin-bottom:12px}.repeater-empty-state p{font-size:.875rem;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "component", type: i0.forwardRef(() => FieldRendererComponent), selector: "amf-field-renderer", inputs: ["field", "form", "formDisabled", "actionDispatcher", "context"] }] });
3206
3206
  }
3207
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RepeaterFieldComponent, decorators: [{
3207
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RepeaterFieldComponent, decorators: [{
3208
3208
  type: Component,
3209
- args: [{ selector: 'amf-repeater-field', standalone: true, imports: [ReactiveFormsModule, forwardRef(() => FieldRendererComponent)], template: `
3210
- <div class="amf-repeater" [class]="field.cssClass">
3211
- <!-- ── Header & Global Add ── -->
3212
- <div class="repeater-header">
3213
- <label class="repeater-label">{{ field.label }}</label>
3214
- @if (canAdd) {
3215
- <button type="button" class="btn-repeater-add" (click)="addItem()" [disabled]="formDisabled">
3216
- <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3217
- {{ field.addLabel || 'Add Item' }}
3218
- </button>
3219
- }
3220
- </div>
3221
-
3222
- @if (field.description) {
3223
- <p class="repeater-description">{{ field.description }}</p>
3224
- }
3225
-
3226
- <div class="repeater-list">
3227
- @for (ctrl of formArray.controls; track $index) {
3228
- <div class="repeater-item-card">
3229
- <div class="repeater-item-header">
3230
- <span class="item-title">Item {{ $index + 1 }}</span>
3231
- @if (canRemove) {
3232
- <button type="button" class="btn-repeater-remove" (click)="removeItem($index)" [disabled]="formDisabled" title="Remove Item">
3233
- <svg viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.12-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/></svg>
3234
- </button>
3235
- }
3236
- </div>
3237
-
3238
- <div class="repeater-item-body">
3239
- <div class="repeater-fields-grid" [style.grid-template-columns]="getGridStyle(field)">
3240
- @for (child of field.children || []; track child.key) {
3241
- <amf-field-renderer
3242
- [field]="child"
3243
- [form]="getFormGroup(ctrl)"
3244
- [formDisabled]="formDisabled"
3245
- [actionDispatcher]="actionDispatcher"
3246
- [context]="context"
3247
- [style.grid-column]="child.colSpan ? 'span ' + child.colSpan : null">
3248
- </amf-field-renderer>
3249
- }
3250
- </div>
3251
- </div>
3252
- </div>
3253
- }
3254
-
3255
- @if (formArray.controls.length === 0) {
3256
- <div class="repeater-empty-state">
3257
- <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3258
- <p>No items added yet. Click "{{ field.addLabel || 'Add Item' }}" to begin.</p>
3259
- </div>
3260
- }
3261
- </div>
3262
- </div>
3209
+ args: [{ selector: 'amf-repeater-field', standalone: true, imports: [ReactiveFormsModule, forwardRef(() => FieldRendererComponent)], template: `
3210
+ <div class="amf-repeater" [class]="field.cssClass">
3211
+ <!-- ── Header & Global Add ── -->
3212
+ <div class="repeater-header">
3213
+ <label class="repeater-label">{{ field.label }}</label>
3214
+ @if (canAdd) {
3215
+ <button type="button" class="btn-repeater-add" (click)="addItem()" [disabled]="formDisabled">
3216
+ <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3217
+ {{ field.addLabel || 'Add Item' }}
3218
+ </button>
3219
+ }
3220
+ </div>
3221
+
3222
+ @if (field.description) {
3223
+ <p class="repeater-description">{{ field.description }}</p>
3224
+ }
3225
+
3226
+ <div class="repeater-list">
3227
+ @for (ctrl of formArray.controls; track $index) {
3228
+ <div class="repeater-item-card">
3229
+ <div class="repeater-item-header">
3230
+ <span class="item-title">Item {{ $index + 1 }}</span>
3231
+ @if (canRemove) {
3232
+ <button type="button" class="btn-repeater-remove" (click)="removeItem($index)" [disabled]="formDisabled" title="Remove Item">
3233
+ <svg viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.12-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/></svg>
3234
+ </button>
3235
+ }
3236
+ </div>
3237
+
3238
+ <div class="repeater-item-body">
3239
+ <div class="repeater-fields-grid" [style.grid-template-columns]="getGridStyle(field)">
3240
+ @for (child of field.children || []; track child.key) {
3241
+ <amf-field-renderer
3242
+ [field]="child"
3243
+ [form]="getFormGroup(ctrl)"
3244
+ [formDisabled]="formDisabled"
3245
+ [actionDispatcher]="actionDispatcher"
3246
+ [context]="context"
3247
+ [style.grid-column]="child.colSpan ? 'span ' + child.colSpan : null">
3248
+ </amf-field-renderer>
3249
+ }
3250
+ </div>
3251
+ </div>
3252
+ </div>
3253
+ }
3254
+
3255
+ @if (formArray.controls.length === 0) {
3256
+ <div class="repeater-empty-state">
3257
+ <svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
3258
+ <p>No items added yet. Click "{{ field.addLabel || 'Add Item' }}" to begin.</p>
3259
+ </div>
3260
+ }
3261
+ </div>
3262
+ </div>
3263
3263
  `, styles: [".amf-repeater{margin-bottom:24px}.repeater-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.repeater-label{font-size:.9375rem;font-weight:600;color:var(--app-text);margin:0}.repeater-description{font-size:.8125rem;color:var(--app-text-muted);margin:0 0 16px}.btn-repeater-add{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;font-size:.8125rem;font-weight:500;font-family:inherit;cursor:pointer;border:1px solid rgba(59,130,246,.3);border-radius:6px;background:#3b82f61a;color:#3b82f6;transition:all .2s}.btn-repeater-add svg{width:14px;height:14px;fill:currentColor}.btn-repeater-add:hover:not(:disabled){background:#3b82f633}.btn-repeater-add:disabled{opacity:.5;cursor:not-allowed}.repeater-list{display:flex;flex-direction:column;gap:16px}.repeater-item-card{background:var(--app-surface-hover);border:1px solid var(--app-border);border-radius:8px;overflow:hidden;transition:box-shadow .2s}.repeater-item-card:hover{border-color:#3b82f64d}.repeater-item-header{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--app-border);background:#00000005}:host-context(body.amf-dark) .repeater-item-header{background:#ffffff05}.item-title{font-size:.8125rem;font-weight:600;color:var(--app-text);text-transform:uppercase;letter-spacing:.5px}.btn-repeater-remove{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:4px;background:transparent;color:#ef4444;cursor:pointer;transition:background .2s}.btn-repeater-remove svg{width:18px;height:18px;fill:currentColor}.btn-repeater-remove:hover:not(:disabled){background:#ef44441a}.btn-repeater-remove:disabled{opacity:.5;cursor:not-allowed}.repeater-item-body{padding:16px}.repeater-fields-grid{display:grid;gap:16px}.repeater-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px 16px;text-align:center;border:1.5px dashed var(--app-border);border-radius:8px;color:var(--app-text-muted);background:var(--app-surface-hover)}.repeater-empty-state svg{width:32px;height:32px;fill:currentColor;opacity:.5;margin-bottom:12px}.repeater-empty-state p{font-size:.875rem;margin:0}\n"] }]
3264
3264
  }], propDecorators: { field: [{
3265
3265
  type: Input
@@ -3388,231 +3388,231 @@ class FieldRendererComponent {
3388
3388
  this.actionDispatcher.dispatch(onClick, this.context);
3389
3389
  }
3390
3390
  }
3391
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3392
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: FieldRendererComponent, isStandalone: true, selector: "amf-field-renderer", inputs: { field: "field", form: "form", formDisabled: "formDisabled", actionDispatcher: "actionDispatcher", context: "context" }, ngImport: i0, template: `
3393
- @if (field.type !== 'hidden') {
3394
- <div class="amf-field" [class]="field.cssClass" [class.has-error]="hasError" [class.field-disabled]="isFieldDisabled">
3395
- @if (field.type === 'heading') { <h3 class="field-heading">{{ field.text || field.label }}</h3> }
3396
- @else if (field.type === 'divider') { <hr class="field-divider" /> }
3397
- @else {
3398
- @if (field.label && field.type !== 'repeater') { <label class="field-label" [for]="field.key">{{ field.label }} @if (isRequired) { <span class="required-mark">*</span> } </label> }
3399
- <div class="field-input-wrapper" [class.has-prefix]="!!field.prefix" [class.has-suffix]="!!field.suffix">
3400
- @if (field.prefix) { <span class="field-prefix">{{ field.prefix }}</span> }
3401
- @switch (field.type) {
3402
- @case ('button') {
3403
- <button type="button" class="field-button" [class]="'btn-' + (field.color || 'primary')" [disabled]="isFieldDisabled" (click)="handleButtonClick()">
3404
- {{ field.label }}
3405
- </button>
3406
- }
3407
- @case ('textarea') { <textarea class="field-input field-textarea" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [rows]="field.rows || 3" [readOnly]="field.readOnly || false"></textarea> }
3408
- @case ('select') {
3409
- <select class="field-input field-select" [id]="field.key" [formControl]="control">
3410
- <option value="" disabled>{{ field.placeholder || 'Select...' }}</option>
3411
- @for (opt of field.options || []; track opt.value) { <option [value]="opt.value" [disabled]="opt.disabled || false">{{ opt.label }}</option> }
3412
- </select>
3413
- }
3414
- @case ('checkbox') {
3415
- <label class="field-checkbox-label"><input type="checkbox" class="field-checkbox" [id]="field.key" [formControl]="control" /><span>{{ field.placeholder || field.label }}</span></label>
3416
- }
3417
- @case ('toggle') {
3418
- <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3419
- }
3420
- @case ('switch') {
3421
- <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3422
- }
3423
- @case ('radio') {
3424
- <div class="field-radio-group">
3425
- @for (opt of field.options || []; track opt.value) {
3426
- <label class="field-radio-label"><input type="radio" [name]="field.key" [value]="opt.value" [formControl]="control" [attr.disabled]="opt.disabled ? '' : null" /><span>{{ opt.label }}</span></label>
3427
- }
3428
- </div>
3429
- }
3430
- @case ('otp') {
3431
- <div class="field-otp-group">
3432
- @for (val of otpArray; track $index) {
3433
- <input class="field-input otp-digit" type="text" inputmode="numeric" [value]="val" (input)="onOtpInput($event, $index)" (keydown)="onOtpKeydown($event, $index)" [disabled]="isFieldDisabled" placeholder="•" />
3434
- }
3435
- </div>
3436
- }
3437
- @case ('repeater') {
3438
- <amf-repeater-field
3439
- [field]="field"
3440
- [formArray]="getFormArray(field.key)"
3441
- [formDisabled]="isFieldDisabled"
3442
- [actionDispatcher]="actionDispatcher"
3443
- [context]="context">
3444
- </amf-repeater-field>
3445
- }
3446
- @case ('password') {
3447
- <div class="password-wrapper">
3448
- <input
3449
- class="field-input password-input"
3450
- [type]="showPassword() ? 'text' : 'password'"
3451
- [id]="field.key"
3452
- [formControl]="control"
3453
- [placeholder]="field.placeholder || ''"
3454
- [readOnly]="field.readOnly || false"
3455
- [attr.autocomplete]="field.autocomplete" />
3456
- <button
3457
- type="button"
3458
- class="pwd-toggle-btn"
3459
- [attr.aria-label]="showPassword() ? 'Hide password' : 'Show password'"
3460
- (click)="togglePasswordVisibility()">
3461
- @if (showPassword()) {
3462
- <!-- Eye-slash: password visible -->
3463
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3464
- <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/>
3465
- <path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/>
3466
- <line x1="1" y1="1" x2="23" y2="23"/>
3467
- </svg>
3468
- } @else {
3469
- <!-- Eye: password hidden -->
3470
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3471
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
3472
- <circle cx="12" cy="12" r="3"/>
3473
- </svg>
3474
- }
3475
- </button>
3476
- </div>
3477
- }
3478
- @case ('currency') {
3479
- <div class="currency-wrapper">
3480
- <span class="currency-symbol">{{ currencySymbol }}</span>
3481
- <input
3482
- class="field-input currency-input"
3483
- type="text"
3484
- inputmode="decimal"
3485
- [id]="field.key"
3486
- [value]="formattedCurrencyValue"
3487
- [placeholder]="field.placeholder || '0.00'"
3488
- [disabled]="isFieldDisabled"
3489
- (input)="onCurrencyInput($event)"
3490
- (blur)="onCurrencyBlur($event)" />
3491
- </div>
3492
- }
3493
- @default { <input class="field-input" [type]="field.type" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [readOnly]="field.readOnly || false" [attr.min]="field.min" [attr.max]="field.max" [attr.step]="field.step" [attr.accept]="field.accept" [attr.multiple]="field.multiple ? '' : null" [attr.autocomplete]="field.autocomplete" /> }
3494
- }
3495
- @if (field.suffix) { <span class="field-suffix">{{ field.suffix }}</span> }
3496
- </div>
3497
- @if (field.hint && !hasError) { <span class="field-hint">{{ field.hint }}</span> }
3498
- @if (hasError) { <span class="field-error">{{ errorMessage }}</span> }
3499
- }
3500
- </div>
3501
- }
3391
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FieldRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3392
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: FieldRendererComponent, isStandalone: true, selector: "amf-field-renderer", inputs: { field: "field", form: "form", formDisabled: "formDisabled", actionDispatcher: "actionDispatcher", context: "context" }, ngImport: i0, template: `
3393
+ @if (field.type !== 'hidden') {
3394
+ <div class="amf-field" [class]="field.cssClass" [class.has-error]="hasError" [class.field-disabled]="isFieldDisabled">
3395
+ @if (field.type === 'heading') { <h3 class="field-heading">{{ field.text || field.label }}</h3> }
3396
+ @else if (field.type === 'divider') { <hr class="field-divider" /> }
3397
+ @else {
3398
+ @if (field.label && field.type !== 'repeater') { <label class="field-label" [for]="field.key">{{ field.label }} @if (isRequired) { <span class="required-mark">*</span> } </label> }
3399
+ <div class="field-input-wrapper" [class.has-prefix]="!!field.prefix" [class.has-suffix]="!!field.suffix">
3400
+ @if (field.prefix) { <span class="field-prefix">{{ field.prefix }}</span> }
3401
+ @switch (field.type) {
3402
+ @case ('button') {
3403
+ <button type="button" class="field-button" [class]="'btn-' + (field.color || 'primary')" [disabled]="isFieldDisabled" (click)="handleButtonClick()">
3404
+ {{ field.label }}
3405
+ </button>
3406
+ }
3407
+ @case ('textarea') { <textarea class="field-input field-textarea" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [rows]="field.rows || 3" [readOnly]="field.readOnly || false"></textarea> }
3408
+ @case ('select') {
3409
+ <select class="field-input field-select" [id]="field.key" [formControl]="control">
3410
+ <option value="" disabled>{{ field.placeholder || 'Select...' }}</option>
3411
+ @for (opt of field.options || []; track opt.value) { <option [value]="opt.value" [disabled]="opt.disabled || false">{{ opt.label }}</option> }
3412
+ </select>
3413
+ }
3414
+ @case ('checkbox') {
3415
+ <label class="field-checkbox-label"><input type="checkbox" class="field-checkbox" [id]="field.key" [formControl]="control" /><span>{{ field.placeholder || field.label }}</span></label>
3416
+ }
3417
+ @case ('toggle') {
3418
+ <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3419
+ }
3420
+ @case ('switch') {
3421
+ <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3422
+ }
3423
+ @case ('radio') {
3424
+ <div class="field-radio-group">
3425
+ @for (opt of field.options || []; track opt.value) {
3426
+ <label class="field-radio-label"><input type="radio" [name]="field.key" [value]="opt.value" [formControl]="control" [attr.disabled]="opt.disabled ? '' : null" /><span>{{ opt.label }}</span></label>
3427
+ }
3428
+ </div>
3429
+ }
3430
+ @case ('otp') {
3431
+ <div class="field-otp-group">
3432
+ @for (val of otpArray; track $index) {
3433
+ <input class="field-input otp-digit" type="text" inputmode="numeric" [value]="val" (input)="onOtpInput($event, $index)" (keydown)="onOtpKeydown($event, $index)" [disabled]="isFieldDisabled" placeholder="•" />
3434
+ }
3435
+ </div>
3436
+ }
3437
+ @case ('repeater') {
3438
+ <amf-repeater-field
3439
+ [field]="field"
3440
+ [formArray]="getFormArray(field.key)"
3441
+ [formDisabled]="isFieldDisabled"
3442
+ [actionDispatcher]="actionDispatcher"
3443
+ [context]="context">
3444
+ </amf-repeater-field>
3445
+ }
3446
+ @case ('password') {
3447
+ <div class="password-wrapper">
3448
+ <input
3449
+ class="field-input password-input"
3450
+ [type]="showPassword() ? 'text' : 'password'"
3451
+ [id]="field.key"
3452
+ [formControl]="control"
3453
+ [placeholder]="field.placeholder || ''"
3454
+ [readOnly]="field.readOnly || false"
3455
+ [attr.autocomplete]="field.autocomplete" />
3456
+ <button
3457
+ type="button"
3458
+ class="pwd-toggle-btn"
3459
+ [attr.aria-label]="showPassword() ? 'Hide password' : 'Show password'"
3460
+ (click)="togglePasswordVisibility()">
3461
+ @if (showPassword()) {
3462
+ <!-- Eye-slash: password visible -->
3463
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3464
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/>
3465
+ <path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/>
3466
+ <line x1="1" y1="1" x2="23" y2="23"/>
3467
+ </svg>
3468
+ } @else {
3469
+ <!-- Eye: password hidden -->
3470
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3471
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
3472
+ <circle cx="12" cy="12" r="3"/>
3473
+ </svg>
3474
+ }
3475
+ </button>
3476
+ </div>
3477
+ }
3478
+ @case ('currency') {
3479
+ <div class="currency-wrapper">
3480
+ <span class="currency-symbol">{{ currencySymbol }}</span>
3481
+ <input
3482
+ class="field-input currency-input"
3483
+ type="text"
3484
+ inputmode="decimal"
3485
+ [id]="field.key"
3486
+ [value]="formattedCurrencyValue"
3487
+ [placeholder]="field.placeholder || '0.00'"
3488
+ [disabled]="isFieldDisabled"
3489
+ (input)="onCurrencyInput($event)"
3490
+ (blur)="onCurrencyBlur($event)" />
3491
+ </div>
3492
+ }
3493
+ @default { <input class="field-input" [type]="field.type" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [readOnly]="field.readOnly || false" [attr.min]="field.min" [attr.max]="field.max" [attr.step]="field.step" [attr.accept]="field.accept" [attr.multiple]="field.multiple ? '' : null" [attr.autocomplete]="field.autocomplete" /> }
3494
+ }
3495
+ @if (field.suffix) { <span class="field-suffix">{{ field.suffix }}</span> }
3496
+ </div>
3497
+ @if (field.hint && !hasError) { <span class="field-hint">{{ field.hint }}</span> }
3498
+ @if (hasError) { <span class="field-error">{{ errorMessage }}</span> }
3499
+ }
3500
+ </div>
3501
+ }
3502
3502
  `, isInline: true, styles: [".amf-field{display:flex;flex-direction:column;gap:6px}.amf-field.field-disabled{opacity:.5;pointer-events:none}.field-label{font-size:.875rem;font-weight:600;color:var(--app-text)}.required-mark{color:#f43f5e;margin-left:2px}.field-input-wrapper{display:flex;align-items:stretch;position:relative}.field-prefix,.field-suffix{padding:10px 12px;font-size:.875rem;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);display:flex;align-items:center;justify-content:center;white-space:nowrap;box-sizing:border-box}.field-prefix{border-right:none;border-radius:8px 0 0 8px}.field-suffix{border-left:none;border-radius:0 8px 8px 0}.field-input{flex:1;width:100%;padding:10px 14px;border:1px solid var(--app-border);border-radius:8px;background:var(--glass-bg);color:var(--app-text);font-size:.875rem;font-family:inherit;outline:none;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.has-prefix .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.has-suffix .field-input{border-top-right-radius:0;border-bottom-right-radius:0}.field-input:focus{border-color:var(--app-primary);box-shadow:0 0 0 3px var(--app-primary-light);z-index:3;position:relative}.field-input::placeholder{color:var(--app-text-muted);opacity:.6}.field-input[readonly]{opacity:.7;cursor:not-allowed}.field-input:disabled{opacity:.5;cursor:not-allowed}.has-error .field-input{border-color:#f43f5e}.has-error .field-input:focus{box-shadow:0 0 0 3px #f43f5e26}.field-select{appearance:none;cursor:pointer;padding-right:36px;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%2394a3b8' d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 12px center;color-scheme:dark}.field-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .field-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .field-select option{background-color:#fff;color:#000}.field-textarea{resize:vertical;min-height:80px}.field-checkbox-label,.field-radio-label{display:flex;align-items:center;gap:8px;font-size:.875rem;color:var(--app-text);cursor:pointer}.field-radio-group{display:flex;flex-direction:column;gap:8px}.field-otp-group{display:flex;gap:8px;justify-content:center;width:100%}.otp-digit{width:44px;height:50px;text-align:center;font-size:1.25rem;font-weight:600;padding:0;letter-spacing:0}.field-toggle-label{display:flex;align-items:center;gap:10px;cursor:pointer}.field-toggle-input{display:none}.field-toggle-track{width:44px;height:24px;background:var(--app-border);border-radius:12px;position:relative;transition:background .2s}.field-toggle-input:checked+.field-toggle-track{background:var(--app-primary)}.field-toggle-thumb{position:absolute;top:2px;left:2px;width:20px;height:20px;background:#fff;border-radius:50%;transition:transform .2s}.field-toggle-input:checked+.field-toggle-track .field-toggle-thumb{transform:translate(20px)}.field-toggle-text{font-size:.875rem;color:var(--app-text)}.field-hint{font-size:.75rem;color:var(--app-text-muted)}.field-error{font-size:.75rem;color:#f43f5e;font-weight:500}.field-heading{font-size:1.125rem;margin-top:8px;color:var(--app-text)}.field-divider{border:none;border-top:1px solid var(--app-border);margin:8px 0}.field-button{padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);border:none;width:100%}.field-button.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff}.field-button.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.field-button.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-secondary:hover:not(:disabled){background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.field-button.btn-outline{background:transparent;color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-outline:hover:not(:disabled){background:var(--glass-bg-hover)}.field-button.btn-success{background:linear-gradient(135deg,#10b981,#34d399);color:#fff}.field-button.btn-success:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #10b9814d}.field-button.btn-accent{background:linear-gradient(135deg,var(--app-accent),var(--app-primary));color:#fff}.field-button.btn-accent:hover:not(:disabled){transform:translateY(-2px)}.field-button:disabled{opacity:.5;cursor:not-allowed;transform:none}.password-wrapper{position:relative;display:flex;align-items:stretch;width:100%}.password-input{padding-right:44px!important}.pwd-toggle-btn{position:absolute;right:0;top:0;bottom:0;width:42px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--app-text-muted);border-radius:0 8px 8px 0;transition:color .2s;z-index:2}.pwd-toggle-btn:hover{color:var(--app-primary)}.pwd-toggle-btn svg{width:18px;height:18px}.currency-wrapper{display:flex;align-items:stretch;width:100%}.currency-symbol{padding:10px 12px;font-size:.875rem;font-weight:600;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);border-right:none;border-radius:8px 0 0 8px;display:flex;align-items:center;white-space:nowrap;box-sizing:border-box}.currency-input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormArrayDirective, selector: "[formArray]", inputs: ["formArray"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: RepeaterFieldComponent, selector: "amf-repeater-field", inputs: ["field", "formArray", "formDisabled", "actionDispatcher", "context"] }] });
3503
3503
  }
3504
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FieldRendererComponent, decorators: [{
3504
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FieldRendererComponent, decorators: [{
3505
3505
  type: Component,
3506
- args: [{ selector: 'amf-field-renderer', standalone: true, imports: [ReactiveFormsModule, RepeaterFieldComponent], template: `
3507
- @if (field.type !== 'hidden') {
3508
- <div class="amf-field" [class]="field.cssClass" [class.has-error]="hasError" [class.field-disabled]="isFieldDisabled">
3509
- @if (field.type === 'heading') { <h3 class="field-heading">{{ field.text || field.label }}</h3> }
3510
- @else if (field.type === 'divider') { <hr class="field-divider" /> }
3511
- @else {
3512
- @if (field.label && field.type !== 'repeater') { <label class="field-label" [for]="field.key">{{ field.label }} @if (isRequired) { <span class="required-mark">*</span> } </label> }
3513
- <div class="field-input-wrapper" [class.has-prefix]="!!field.prefix" [class.has-suffix]="!!field.suffix">
3514
- @if (field.prefix) { <span class="field-prefix">{{ field.prefix }}</span> }
3515
- @switch (field.type) {
3516
- @case ('button') {
3517
- <button type="button" class="field-button" [class]="'btn-' + (field.color || 'primary')" [disabled]="isFieldDisabled" (click)="handleButtonClick()">
3518
- {{ field.label }}
3519
- </button>
3520
- }
3521
- @case ('textarea') { <textarea class="field-input field-textarea" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [rows]="field.rows || 3" [readOnly]="field.readOnly || false"></textarea> }
3522
- @case ('select') {
3523
- <select class="field-input field-select" [id]="field.key" [formControl]="control">
3524
- <option value="" disabled>{{ field.placeholder || 'Select...' }}</option>
3525
- @for (opt of field.options || []; track opt.value) { <option [value]="opt.value" [disabled]="opt.disabled || false">{{ opt.label }}</option> }
3526
- </select>
3527
- }
3528
- @case ('checkbox') {
3529
- <label class="field-checkbox-label"><input type="checkbox" class="field-checkbox" [id]="field.key" [formControl]="control" /><span>{{ field.placeholder || field.label }}</span></label>
3530
- }
3531
- @case ('toggle') {
3532
- <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3533
- }
3534
- @case ('switch') {
3535
- <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3536
- }
3537
- @case ('radio') {
3538
- <div class="field-radio-group">
3539
- @for (opt of field.options || []; track opt.value) {
3540
- <label class="field-radio-label"><input type="radio" [name]="field.key" [value]="opt.value" [formControl]="control" [attr.disabled]="opt.disabled ? '' : null" /><span>{{ opt.label }}</span></label>
3541
- }
3542
- </div>
3543
- }
3544
- @case ('otp') {
3545
- <div class="field-otp-group">
3546
- @for (val of otpArray; track $index) {
3547
- <input class="field-input otp-digit" type="text" inputmode="numeric" [value]="val" (input)="onOtpInput($event, $index)" (keydown)="onOtpKeydown($event, $index)" [disabled]="isFieldDisabled" placeholder="•" />
3548
- }
3549
- </div>
3550
- }
3551
- @case ('repeater') {
3552
- <amf-repeater-field
3553
- [field]="field"
3554
- [formArray]="getFormArray(field.key)"
3555
- [formDisabled]="isFieldDisabled"
3556
- [actionDispatcher]="actionDispatcher"
3557
- [context]="context">
3558
- </amf-repeater-field>
3559
- }
3560
- @case ('password') {
3561
- <div class="password-wrapper">
3562
- <input
3563
- class="field-input password-input"
3564
- [type]="showPassword() ? 'text' : 'password'"
3565
- [id]="field.key"
3566
- [formControl]="control"
3567
- [placeholder]="field.placeholder || ''"
3568
- [readOnly]="field.readOnly || false"
3569
- [attr.autocomplete]="field.autocomplete" />
3570
- <button
3571
- type="button"
3572
- class="pwd-toggle-btn"
3573
- [attr.aria-label]="showPassword() ? 'Hide password' : 'Show password'"
3574
- (click)="togglePasswordVisibility()">
3575
- @if (showPassword()) {
3576
- <!-- Eye-slash: password visible -->
3577
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3578
- <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/>
3579
- <path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/>
3580
- <line x1="1" y1="1" x2="23" y2="23"/>
3581
- </svg>
3582
- } @else {
3583
- <!-- Eye: password hidden -->
3584
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3585
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
3586
- <circle cx="12" cy="12" r="3"/>
3587
- </svg>
3588
- }
3589
- </button>
3590
- </div>
3591
- }
3592
- @case ('currency') {
3593
- <div class="currency-wrapper">
3594
- <span class="currency-symbol">{{ currencySymbol }}</span>
3595
- <input
3596
- class="field-input currency-input"
3597
- type="text"
3598
- inputmode="decimal"
3599
- [id]="field.key"
3600
- [value]="formattedCurrencyValue"
3601
- [placeholder]="field.placeholder || '0.00'"
3602
- [disabled]="isFieldDisabled"
3603
- (input)="onCurrencyInput($event)"
3604
- (blur)="onCurrencyBlur($event)" />
3605
- </div>
3606
- }
3607
- @default { <input class="field-input" [type]="field.type" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [readOnly]="field.readOnly || false" [attr.min]="field.min" [attr.max]="field.max" [attr.step]="field.step" [attr.accept]="field.accept" [attr.multiple]="field.multiple ? '' : null" [attr.autocomplete]="field.autocomplete" /> }
3608
- }
3609
- @if (field.suffix) { <span class="field-suffix">{{ field.suffix }}</span> }
3610
- </div>
3611
- @if (field.hint && !hasError) { <span class="field-hint">{{ field.hint }}</span> }
3612
- @if (hasError) { <span class="field-error">{{ errorMessage }}</span> }
3613
- }
3614
- </div>
3615
- }
3506
+ args: [{ selector: 'amf-field-renderer', standalone: true, imports: [ReactiveFormsModule, RepeaterFieldComponent], template: `
3507
+ @if (field.type !== 'hidden') {
3508
+ <div class="amf-field" [class]="field.cssClass" [class.has-error]="hasError" [class.field-disabled]="isFieldDisabled">
3509
+ @if (field.type === 'heading') { <h3 class="field-heading">{{ field.text || field.label }}</h3> }
3510
+ @else if (field.type === 'divider') { <hr class="field-divider" /> }
3511
+ @else {
3512
+ @if (field.label && field.type !== 'repeater') { <label class="field-label" [for]="field.key">{{ field.label }} @if (isRequired) { <span class="required-mark">*</span> } </label> }
3513
+ <div class="field-input-wrapper" [class.has-prefix]="!!field.prefix" [class.has-suffix]="!!field.suffix">
3514
+ @if (field.prefix) { <span class="field-prefix">{{ field.prefix }}</span> }
3515
+ @switch (field.type) {
3516
+ @case ('button') {
3517
+ <button type="button" class="field-button" [class]="'btn-' + (field.color || 'primary')" [disabled]="isFieldDisabled" (click)="handleButtonClick()">
3518
+ {{ field.label }}
3519
+ </button>
3520
+ }
3521
+ @case ('textarea') { <textarea class="field-input field-textarea" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [rows]="field.rows || 3" [readOnly]="field.readOnly || false"></textarea> }
3522
+ @case ('select') {
3523
+ <select class="field-input field-select" [id]="field.key" [formControl]="control">
3524
+ <option value="" disabled>{{ field.placeholder || 'Select...' }}</option>
3525
+ @for (opt of field.options || []; track opt.value) { <option [value]="opt.value" [disabled]="opt.disabled || false">{{ opt.label }}</option> }
3526
+ </select>
3527
+ }
3528
+ @case ('checkbox') {
3529
+ <label class="field-checkbox-label"><input type="checkbox" class="field-checkbox" [id]="field.key" [formControl]="control" /><span>{{ field.placeholder || field.label }}</span></label>
3530
+ }
3531
+ @case ('toggle') {
3532
+ <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3533
+ }
3534
+ @case ('switch') {
3535
+ <label class="field-toggle-label"><input type="checkbox" class="field-toggle-input" [id]="field.key" [formControl]="control" /><span class="field-toggle-track"><span class="field-toggle-thumb"></span></span>@if (field.placeholder) { <span class="field-toggle-text">{{ field.placeholder }}</span> }</label>
3536
+ }
3537
+ @case ('radio') {
3538
+ <div class="field-radio-group">
3539
+ @for (opt of field.options || []; track opt.value) {
3540
+ <label class="field-radio-label"><input type="radio" [name]="field.key" [value]="opt.value" [formControl]="control" [attr.disabled]="opt.disabled ? '' : null" /><span>{{ opt.label }}</span></label>
3541
+ }
3542
+ </div>
3543
+ }
3544
+ @case ('otp') {
3545
+ <div class="field-otp-group">
3546
+ @for (val of otpArray; track $index) {
3547
+ <input class="field-input otp-digit" type="text" inputmode="numeric" [value]="val" (input)="onOtpInput($event, $index)" (keydown)="onOtpKeydown($event, $index)" [disabled]="isFieldDisabled" placeholder="•" />
3548
+ }
3549
+ </div>
3550
+ }
3551
+ @case ('repeater') {
3552
+ <amf-repeater-field
3553
+ [field]="field"
3554
+ [formArray]="getFormArray(field.key)"
3555
+ [formDisabled]="isFieldDisabled"
3556
+ [actionDispatcher]="actionDispatcher"
3557
+ [context]="context">
3558
+ </amf-repeater-field>
3559
+ }
3560
+ @case ('password') {
3561
+ <div class="password-wrapper">
3562
+ <input
3563
+ class="field-input password-input"
3564
+ [type]="showPassword() ? 'text' : 'password'"
3565
+ [id]="field.key"
3566
+ [formControl]="control"
3567
+ [placeholder]="field.placeholder || ''"
3568
+ [readOnly]="field.readOnly || false"
3569
+ [attr.autocomplete]="field.autocomplete" />
3570
+ <button
3571
+ type="button"
3572
+ class="pwd-toggle-btn"
3573
+ [attr.aria-label]="showPassword() ? 'Hide password' : 'Show password'"
3574
+ (click)="togglePasswordVisibility()">
3575
+ @if (showPassword()) {
3576
+ <!-- Eye-slash: password visible -->
3577
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3578
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/>
3579
+ <path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/>
3580
+ <line x1="1" y1="1" x2="23" y2="23"/>
3581
+ </svg>
3582
+ } @else {
3583
+ <!-- Eye: password hidden -->
3584
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3585
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
3586
+ <circle cx="12" cy="12" r="3"/>
3587
+ </svg>
3588
+ }
3589
+ </button>
3590
+ </div>
3591
+ }
3592
+ @case ('currency') {
3593
+ <div class="currency-wrapper">
3594
+ <span class="currency-symbol">{{ currencySymbol }}</span>
3595
+ <input
3596
+ class="field-input currency-input"
3597
+ type="text"
3598
+ inputmode="decimal"
3599
+ [id]="field.key"
3600
+ [value]="formattedCurrencyValue"
3601
+ [placeholder]="field.placeholder || '0.00'"
3602
+ [disabled]="isFieldDisabled"
3603
+ (input)="onCurrencyInput($event)"
3604
+ (blur)="onCurrencyBlur($event)" />
3605
+ </div>
3606
+ }
3607
+ @default { <input class="field-input" [type]="field.type" [id]="field.key" [formControl]="control" [placeholder]="field.placeholder || ''" [readOnly]="field.readOnly || false" [attr.min]="field.min" [attr.max]="field.max" [attr.step]="field.step" [attr.accept]="field.accept" [attr.multiple]="field.multiple ? '' : null" [attr.autocomplete]="field.autocomplete" /> }
3608
+ }
3609
+ @if (field.suffix) { <span class="field-suffix">{{ field.suffix }}</span> }
3610
+ </div>
3611
+ @if (field.hint && !hasError) { <span class="field-hint">{{ field.hint }}</span> }
3612
+ @if (hasError) { <span class="field-error">{{ errorMessage }}</span> }
3613
+ }
3614
+ </div>
3615
+ }
3616
3616
  `, styles: [".amf-field{display:flex;flex-direction:column;gap:6px}.amf-field.field-disabled{opacity:.5;pointer-events:none}.field-label{font-size:.875rem;font-weight:600;color:var(--app-text)}.required-mark{color:#f43f5e;margin-left:2px}.field-input-wrapper{display:flex;align-items:stretch;position:relative}.field-prefix,.field-suffix{padding:10px 12px;font-size:.875rem;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);display:flex;align-items:center;justify-content:center;white-space:nowrap;box-sizing:border-box}.field-prefix{border-right:none;border-radius:8px 0 0 8px}.field-suffix{border-left:none;border-radius:0 8px 8px 0}.field-input{flex:1;width:100%;padding:10px 14px;border:1px solid var(--app-border);border-radius:8px;background:var(--glass-bg);color:var(--app-text);font-size:.875rem;font-family:inherit;outline:none;transition:border-color .2s,box-shadow .2s;box-sizing:border-box}.has-prefix .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.has-suffix .field-input{border-top-right-radius:0;border-bottom-right-radius:0}.field-input:focus{border-color:var(--app-primary);box-shadow:0 0 0 3px var(--app-primary-light);z-index:3;position:relative}.field-input::placeholder{color:var(--app-text-muted);opacity:.6}.field-input[readonly]{opacity:.7;cursor:not-allowed}.field-input:disabled{opacity:.5;cursor:not-allowed}.has-error .field-input{border-color:#f43f5e}.has-error .field-input:focus{box-shadow:0 0 0 3px #f43f5e26}.field-select{appearance:none;cursor:pointer;padding-right:36px;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%2394a3b8' d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 12px center;color-scheme:dark}.field-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .field-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .field-select option{background-color:#fff;color:#000}.field-textarea{resize:vertical;min-height:80px}.field-checkbox-label,.field-radio-label{display:flex;align-items:center;gap:8px;font-size:.875rem;color:var(--app-text);cursor:pointer}.field-radio-group{display:flex;flex-direction:column;gap:8px}.field-otp-group{display:flex;gap:8px;justify-content:center;width:100%}.otp-digit{width:44px;height:50px;text-align:center;font-size:1.25rem;font-weight:600;padding:0;letter-spacing:0}.field-toggle-label{display:flex;align-items:center;gap:10px;cursor:pointer}.field-toggle-input{display:none}.field-toggle-track{width:44px;height:24px;background:var(--app-border);border-radius:12px;position:relative;transition:background .2s}.field-toggle-input:checked+.field-toggle-track{background:var(--app-primary)}.field-toggle-thumb{position:absolute;top:2px;left:2px;width:20px;height:20px;background:#fff;border-radius:50%;transition:transform .2s}.field-toggle-input:checked+.field-toggle-track .field-toggle-thumb{transform:translate(20px)}.field-toggle-text{font-size:.875rem;color:var(--app-text)}.field-hint{font-size:.75rem;color:var(--app-text-muted)}.field-error{font-size:.75rem;color:#f43f5e;font-weight:500}.field-heading{font-size:1.125rem;margin-top:8px;color:var(--app-text)}.field-divider{border:none;border-top:1px solid var(--app-border);margin:8px 0}.field-button{padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);border:none;width:100%}.field-button.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff}.field-button.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.field-button.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-secondary:hover:not(:disabled){background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.field-button.btn-outline{background:transparent;color:var(--app-text);border:1px solid var(--app-border)}.field-button.btn-outline:hover:not(:disabled){background:var(--glass-bg-hover)}.field-button.btn-success{background:linear-gradient(135deg,#10b981,#34d399);color:#fff}.field-button.btn-success:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #10b9814d}.field-button.btn-accent{background:linear-gradient(135deg,var(--app-accent),var(--app-primary));color:#fff}.field-button.btn-accent:hover:not(:disabled){transform:translateY(-2px)}.field-button:disabled{opacity:.5;cursor:not-allowed;transform:none}.password-wrapper{position:relative;display:flex;align-items:stretch;width:100%}.password-input{padding-right:44px!important}.pwd-toggle-btn{position:absolute;right:0;top:0;bottom:0;width:42px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--app-text-muted);border-radius:0 8px 8px 0;transition:color .2s;z-index:2}.pwd-toggle-btn:hover{color:var(--app-primary)}.pwd-toggle-btn svg{width:18px;height:18px}.currency-wrapper{display:flex;align-items:stretch;width:100%}.currency-symbol{padding:10px 12px;font-size:.875rem;font-weight:600;color:var(--app-text-muted);background:var(--glass-bg);border:1px solid var(--app-border);border-right:none;border-radius:8px 0 0 8px;display:flex;align-items:center;white-space:nowrap;box-sizing:border-box}.currency-input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}\n"] }]
3617
3617
  }], propDecorators: { field: [{
3618
3618
  type: Input
@@ -3757,41 +3757,41 @@ class FormRendererComponent {
3757
3757
  return controls;
3758
3758
  }
3759
3759
  markAllTouched() { Object.values(this.formGroup.controls).forEach(c => c.markAsTouched()); }
3760
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3761
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: FormRendererComponent, isStandalone: true, selector: "amf-form-renderer", inputs: { config: "config", context: "context" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", formChange: "formChange" }, usesOnChanges: true, ngImport: i0, template: `
3762
- <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="amf-form" [class]="config.cssClass" [class.form-disabled]="config.disabled">
3763
- <div class="amf-form-fields" [class]="layoutClass" [style.grid-template-columns]="gridColumns">
3764
- @for (field of visibleFields; track field.key) {
3765
- <amf-field-renderer [field]="field" [form]="formGroup" [formDisabled]="!!config.disabled" [actionDispatcher]="actionDispatcher" [context]="context" [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null"></amf-field-renderer>
3766
- }
3767
- </div>
3768
- @if (!config.hideSubmit) {
3769
- <div class="amf-form-actions">
3770
- @if (config.showCancel) { <button type="button" class="btn-secondary" (click)="handleCancel()" [disabled]="config.disabled">{{ config.cancelLabel || 'Cancel' }}</button> }
3771
- @if (config.showReset) { <button type="button" class="btn-secondary" (click)="formGroup.reset()" [disabled]="config.disabled">Reset</button> }
3772
- <button type="submit" class="btn-primary" [disabled]="formGroup.invalid || config.disabled">{{ config.submitLabel || 'Submit' }}</button>
3773
- </div>
3774
- }
3775
- </form>
3760
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3761
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: FormRendererComponent, isStandalone: true, selector: "amf-form-renderer", inputs: { config: "config", context: "context" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", formChange: "formChange" }, usesOnChanges: true, ngImport: i0, template: `
3762
+ <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="amf-form" [class]="config.cssClass" [class.form-disabled]="config.disabled">
3763
+ <div class="amf-form-fields" [class]="layoutClass" [style.grid-template-columns]="gridColumns">
3764
+ @for (field of visibleFields; track field.key) {
3765
+ <amf-field-renderer [field]="field" [form]="formGroup" [formDisabled]="!!config.disabled" [actionDispatcher]="actionDispatcher" [context]="context" [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null"></amf-field-renderer>
3766
+ }
3767
+ </div>
3768
+ @if (!config.hideSubmit) {
3769
+ <div class="amf-form-actions">
3770
+ @if (config.showCancel) { <button type="button" class="btn-secondary" (click)="handleCancel()" [disabled]="config.disabled">{{ config.cancelLabel || 'Cancel' }}</button> }
3771
+ @if (config.showReset) { <button type="button" class="btn-secondary" (click)="formGroup.reset()" [disabled]="config.disabled">Reset</button> }
3772
+ <button type="submit" class="btn-primary" [disabled]="formGroup.invalid || config.disabled">{{ config.submitLabel || 'Submit' }}</button>
3773
+ </div>
3774
+ }
3775
+ </form>
3776
3776
  `, isInline: true, styles: [".amf-form{display:flex;flex-direction:column;gap:24px}.amf-form.form-disabled{opacity:.6;pointer-events:none}.amf-form-fields{display:flex;flex-direction:column;gap:20px}.amf-form-fields.layout-grid{display:grid;gap:20px}.amf-form-fields.layout-horizontal{flex-direction:row;flex-wrap:wrap;gap:16px}.amf-form-fields.layout-horizontal>*{flex:1;min-width:200px}.amf-form-fields.layout-inline{flex-direction:row;align-items:flex-end;gap:12px}.amf-form-actions{display:flex;justify-content:flex-end;gap:12px;padding-top:8px;border-top:1px solid var(--app-border)}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:var(--app-on-primary, #fff);border:none;padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-primary:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FieldRendererComponent, selector: "amf-field-renderer", inputs: ["field", "form", "formDisabled", "actionDispatcher", "context"] }] });
3777
3777
  }
3778
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FormRendererComponent, decorators: [{
3778
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FormRendererComponent, decorators: [{
3779
3779
  type: Component,
3780
- args: [{ selector: 'amf-form-renderer', standalone: true, imports: [ReactiveFormsModule, FieldRendererComponent], template: `
3781
- <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="amf-form" [class]="config.cssClass" [class.form-disabled]="config.disabled">
3782
- <div class="amf-form-fields" [class]="layoutClass" [style.grid-template-columns]="gridColumns">
3783
- @for (field of visibleFields; track field.key) {
3784
- <amf-field-renderer [field]="field" [form]="formGroup" [formDisabled]="!!config.disabled" [actionDispatcher]="actionDispatcher" [context]="context" [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null"></amf-field-renderer>
3785
- }
3786
- </div>
3787
- @if (!config.hideSubmit) {
3788
- <div class="amf-form-actions">
3789
- @if (config.showCancel) { <button type="button" class="btn-secondary" (click)="handleCancel()" [disabled]="config.disabled">{{ config.cancelLabel || 'Cancel' }}</button> }
3790
- @if (config.showReset) { <button type="button" class="btn-secondary" (click)="formGroup.reset()" [disabled]="config.disabled">Reset</button> }
3791
- <button type="submit" class="btn-primary" [disabled]="formGroup.invalid || config.disabled">{{ config.submitLabel || 'Submit' }}</button>
3792
- </div>
3793
- }
3794
- </form>
3780
+ args: [{ selector: 'amf-form-renderer', standalone: true, imports: [ReactiveFormsModule, FieldRendererComponent], template: `
3781
+ <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="amf-form" [class]="config.cssClass" [class.form-disabled]="config.disabled">
3782
+ <div class="amf-form-fields" [class]="layoutClass" [style.grid-template-columns]="gridColumns">
3783
+ @for (field of visibleFields; track field.key) {
3784
+ <amf-field-renderer [field]="field" [form]="formGroup" [formDisabled]="!!config.disabled" [actionDispatcher]="actionDispatcher" [context]="context" [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null"></amf-field-renderer>
3785
+ }
3786
+ </div>
3787
+ @if (!config.hideSubmit) {
3788
+ <div class="amf-form-actions">
3789
+ @if (config.showCancel) { <button type="button" class="btn-secondary" (click)="handleCancel()" [disabled]="config.disabled">{{ config.cancelLabel || 'Cancel' }}</button> }
3790
+ @if (config.showReset) { <button type="button" class="btn-secondary" (click)="formGroup.reset()" [disabled]="config.disabled">Reset</button> }
3791
+ <button type="submit" class="btn-primary" [disabled]="formGroup.invalid || config.disabled">{{ config.submitLabel || 'Submit' }}</button>
3792
+ </div>
3793
+ }
3794
+ </form>
3795
3795
  `, styles: [".amf-form{display:flex;flex-direction:column;gap:24px}.amf-form.form-disabled{opacity:.6;pointer-events:none}.amf-form-fields{display:flex;flex-direction:column;gap:20px}.amf-form-fields.layout-grid{display:grid;gap:20px}.amf-form-fields.layout-horizontal{flex-direction:row;flex-wrap:wrap;gap:16px}.amf-form-fields.layout-horizontal>*{flex:1;min-width:200px}.amf-form-fields.layout-inline{flex-direction:row;align-items:flex-end;gap:12px}.amf-form-actions{display:flex;justify-content:flex-end;gap:12px;padding-top:8px;border-top:1px solid var(--app-border)}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:var(--app-on-primary, #fff);border:none;padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-primary:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-primary:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-secondary{background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 24px;border-radius:10px;font-weight:600;cursor:pointer;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}\n"] }]
3796
3796
  }], propDecorators: { config: [{
3797
3797
  type: Input
@@ -4045,215 +4045,215 @@ class StepperFormRendererComponent {
4045
4045
  }
4046
4046
  return controls;
4047
4047
  }
4048
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: StepperFormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4049
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: StepperFormRendererComponent, isStandalone: true, selector: "amf-stepper-form-renderer", inputs: { config: "config", context: "context" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel" }, usesOnChanges: true, ngImport: i0, template: `
4050
- <div class="amf-stepper" [class]="config.cssClass" [class.stepper-disabled]="config.disabled">
4051
-
4052
- <!-- ─── Step Header ──────────────────────────────────── -->
4053
- <div class="stepper-header">
4054
- @for (step of resolvedSteps(); track $index) {
4055
- <div class="step-item"
4056
- [class.active]="$index === currentStep()"
4057
- [class.completed]="isCompleted($index)"
4058
- [class.skipped]="isSkipped($index)"
4059
- [class.navigable]="canNavigateTo($index)"
4060
- (click)="canNavigateTo($index) && goToStep($index)">
4061
- <div class="step-indicator">
4062
- @if (isCompleted($index)) {
4063
- <svg class="check-icon" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4064
- } @else if (isSkipped($index)) {
4065
- <svg class="skip-icon" viewBox="0 0 24 24"><path d="M6 18l8.5-6L6 6v12zm2-8.14L11.03 12 8 14.14V9.86zM16 6h2v12h-2z"/></svg>
4066
- } @else {
4067
- <span class="step-number">{{ $index + 1 }}</span>
4068
- }
4069
- </div>
4070
- <div class="step-label-group">
4071
- <span class="step-title">{{ step.title }}</span>
4072
- @if (step.description) { <span class="step-description">{{ step.description }}</span> }
4073
- </div>
4074
- @if ($index < resolvedSteps().length - 1) {
4075
- <div class="step-connector" [class.completed]="isCompleted($index)"></div>
4076
- }
4077
- </div>
4078
- }
4079
- </div>
4080
-
4081
- <!-- ─── Mobile Progress Bar ───────────────────────────── -->
4082
- <div class="stepper-progress-mobile">
4083
- <span class="progress-label">Step {{ currentStep() + 1 }} of {{ resolvedSteps().length }}: {{ resolvedSteps()[currentStep()]?.title }}</span>
4084
- <div class="progress-bar-track">
4085
- <div class="progress-bar-fill" [style.width.%]="progressPercent()"></div>
4086
- </div>
4087
- </div>
4088
-
4089
- <!-- ─── Step Content ─────────────────────────────────── -->
4090
- <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="stepper-form-body">
4091
- <div class="step-content">
4092
- <div class="step-fields" [style.grid-template-columns]="currentGridColumns()">
4093
- @for (field of currentStepVisibleFields(); track field.key) {
4094
- <amf-field-renderer
4095
- [field]="field"
4096
- [form]="formGroup"
4097
- [formDisabled]="!!config.disabled"
4098
- [actionDispatcher]="actionDispatcher"
4099
- [context]="context"
4100
- [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null">
4101
- </amf-field-renderer>
4102
- }
4103
- </div>
4104
-
4105
- <!-- Step-level validation error summary -->
4106
- @if (stepErrors().length) {
4107
- <div class="step-error-summary">
4108
- <svg viewBox="0 0 24 24" class="error-summary-icon"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
4109
- <span>Please fix {{ stepErrors().length }} error{{ stepErrors().length > 1 ? 's' : '' }} before continuing.</span>
4110
- </div>
4111
- }
4112
- </div>
4113
-
4114
- <!-- ─── Navigation Actions ────────────────────────────── -->
4115
- <div class="stepper-actions">
4116
- <div class="stepper-actions-left">
4117
- @if (config.showReset) {
4118
- <button type="button" class="btn-reset" (click)="resetForm()" [disabled]="config.disabled">
4119
- <svg viewBox="0 0 24 24"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
4120
- {{ config.resetLabel || 'Start Over' }}
4121
- </button>
4122
- }
4123
- @if (currentStep() > 0) {
4124
- <button type="button" class="btn-back" (click)="goBack()" [disabled]="config.disabled">
4125
- <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
4126
- Back
4127
- </button>
4128
- }
4129
- </div>
4130
- <div class="stepper-actions-right">
4131
- @if (resolvedSteps()[currentStep()]?.optional) {
4132
- <button type="button" class="btn-skip" (click)="skipStep()" [disabled]="config.disabled">Skip</button>
4133
- }
4134
- @if (currentStep() < resolvedSteps().length - 1) {
4135
- <button type="button" class="btn-next" (click)="goNext()" [disabled]="config.disabled">
4136
- {{ resolvedSteps()[currentStep() + 1] ? 'Next' : 'Review' }}
4137
- <svg viewBox="0 0 24 24"><path d="M4 11v2h12l-5.59 5.59L12 20l8-8-8-8-1.41 1.41L16 11H4z"/></svg>
4138
- </button>
4139
- } @else {
4140
- @if (!config.hideSubmit) {
4141
- <button type="submit" class="btn-submit" [disabled]="formGroup.invalid || config.disabled">
4142
- {{ config.submitLabel || 'Submit' }}
4143
- <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4144
- </button>
4145
- }
4146
- }
4147
- </div>
4148
- </div>
4149
- </form>
4150
- </div>
4048
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: StepperFormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4049
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: StepperFormRendererComponent, isStandalone: true, selector: "amf-stepper-form-renderer", inputs: { config: "config", context: "context" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel" }, usesOnChanges: true, ngImport: i0, template: `
4050
+ <div class="amf-stepper" [class]="config.cssClass" [class.stepper-disabled]="config.disabled">
4051
+
4052
+ <!-- ─── Step Header ──────────────────────────────────── -->
4053
+ <div class="stepper-header">
4054
+ @for (step of resolvedSteps(); track $index) {
4055
+ <div class="step-item"
4056
+ [class.active]="$index === currentStep()"
4057
+ [class.completed]="isCompleted($index)"
4058
+ [class.skipped]="isSkipped($index)"
4059
+ [class.navigable]="canNavigateTo($index)"
4060
+ (click)="canNavigateTo($index) && goToStep($index)">
4061
+ <div class="step-indicator">
4062
+ @if (isCompleted($index)) {
4063
+ <svg class="check-icon" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4064
+ } @else if (isSkipped($index)) {
4065
+ <svg class="skip-icon" viewBox="0 0 24 24"><path d="M6 18l8.5-6L6 6v12zm2-8.14L11.03 12 8 14.14V9.86zM16 6h2v12h-2z"/></svg>
4066
+ } @else {
4067
+ <span class="step-number">{{ $index + 1 }}</span>
4068
+ }
4069
+ </div>
4070
+ <div class="step-label-group">
4071
+ <span class="step-title">{{ step.title }}</span>
4072
+ @if (step.description) { <span class="step-description">{{ step.description }}</span> }
4073
+ </div>
4074
+ @if ($index < resolvedSteps().length - 1) {
4075
+ <div class="step-connector" [class.completed]="isCompleted($index)"></div>
4076
+ }
4077
+ </div>
4078
+ }
4079
+ </div>
4080
+
4081
+ <!-- ─── Mobile Progress Bar ───────────────────────────── -->
4082
+ <div class="stepper-progress-mobile">
4083
+ <span class="progress-label">Step {{ currentStep() + 1 }} of {{ resolvedSteps().length }}: {{ resolvedSteps()[currentStep()]?.title }}</span>
4084
+ <div class="progress-bar-track">
4085
+ <div class="progress-bar-fill" [style.width.%]="progressPercent()"></div>
4086
+ </div>
4087
+ </div>
4088
+
4089
+ <!-- ─── Step Content ─────────────────────────────────── -->
4090
+ <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="stepper-form-body">
4091
+ <div class="step-content">
4092
+ <div class="step-fields" [style.grid-template-columns]="currentGridColumns()">
4093
+ @for (field of currentStepVisibleFields(); track field.key) {
4094
+ <amf-field-renderer
4095
+ [field]="field"
4096
+ [form]="formGroup"
4097
+ [formDisabled]="!!config.disabled"
4098
+ [actionDispatcher]="actionDispatcher"
4099
+ [context]="context"
4100
+ [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null">
4101
+ </amf-field-renderer>
4102
+ }
4103
+ </div>
4104
+
4105
+ <!-- Step-level validation error summary -->
4106
+ @if (stepErrors().length) {
4107
+ <div class="step-error-summary">
4108
+ <svg viewBox="0 0 24 24" class="error-summary-icon"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
4109
+ <span>Please fix {{ stepErrors().length }} error{{ stepErrors().length > 1 ? 's' : '' }} before continuing.</span>
4110
+ </div>
4111
+ }
4112
+ </div>
4113
+
4114
+ <!-- ─── Navigation Actions ────────────────────────────── -->
4115
+ <div class="stepper-actions">
4116
+ <div class="stepper-actions-left">
4117
+ @if (config.showReset) {
4118
+ <button type="button" class="btn-reset" (click)="resetForm()" [disabled]="config.disabled">
4119
+ <svg viewBox="0 0 24 24"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
4120
+ {{ config.resetLabel || 'Start Over' }}
4121
+ </button>
4122
+ }
4123
+ @if (currentStep() > 0) {
4124
+ <button type="button" class="btn-back" (click)="goBack()" [disabled]="config.disabled">
4125
+ <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
4126
+ Back
4127
+ </button>
4128
+ }
4129
+ </div>
4130
+ <div class="stepper-actions-right">
4131
+ @if (resolvedSteps()[currentStep()]?.optional) {
4132
+ <button type="button" class="btn-skip" (click)="skipStep()" [disabled]="config.disabled">Skip</button>
4133
+ }
4134
+ @if (currentStep() < resolvedSteps().length - 1) {
4135
+ <button type="button" class="btn-next" (click)="goNext()" [disabled]="config.disabled">
4136
+ {{ resolvedSteps()[currentStep() + 1] ? 'Next' : 'Review' }}
4137
+ <svg viewBox="0 0 24 24"><path d="M4 11v2h12l-5.59 5.59L12 20l8-8-8-8-1.41 1.41L16 11H4z"/></svg>
4138
+ </button>
4139
+ } @else {
4140
+ @if (!config.hideSubmit) {
4141
+ <button type="submit" class="btn-submit" [disabled]="formGroup.invalid || config.disabled">
4142
+ {{ config.submitLabel || 'Submit' }}
4143
+ <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4144
+ </button>
4145
+ }
4146
+ }
4147
+ </div>
4148
+ </div>
4149
+ </form>
4150
+ </div>
4151
4151
  `, isInline: true, styles: [".amf-stepper{display:flex;flex-direction:column;gap:0}.amf-stepper.stepper-disabled{opacity:.6;pointer-events:none}.stepper-header{display:flex;align-items:flex-start;gap:0;padding:20px 24px 0;overflow-x:auto;scrollbar-width:none}.stepper-header::-webkit-scrollbar{display:none}.step-item{display:flex;align-items:center;flex:1;min-width:0;cursor:default;position:relative}.step-item.navigable{cursor:pointer}.step-item.navigable:hover .step-indicator{border-color:var(--app-primary)}.step-item.navigable:hover .step-title{color:var(--app-text)}.step-indicator{flex-shrink:0;width:36px;height:36px;border-radius:50%;border:2px solid var(--app-border);background:var(--app-surface);display:flex;align-items:center;justify-content:center;transition:all .35s cubic-bezier(.4,0,.2,1);position:relative;z-index:1}.step-item.active .step-indicator{border-color:var(--app-primary);background:var(--app-primary);box-shadow:0 0 0 4px rgba(var(--app-primary-rgb, 99 102 241),.18)}.step-item.completed .step-indicator{border-color:#22c55e;background:#22c55e}.step-item.skipped .step-indicator{border-color:var(--app-text-muted);background:var(--glass-bg)}.step-number{font-size:.8125rem;font-weight:700;color:var(--app-text-muted)}.step-item.active .step-number{color:#fff}.check-icon,.skip-icon{width:18px;height:18px;fill:#fff}.skip-icon{fill:var(--app-text-muted)}.step-label-group{display:flex;flex-direction:column;margin-left:10px;min-width:0;flex-shrink:0}.step-title{font-size:.8125rem;font-weight:600;color:var(--app-text-muted);white-space:nowrap;transition:color .2s}.step-item.active .step-title{color:var(--app-text)}.step-item.completed .step-title{color:var(--app-text-muted)}.step-description{font-size:.6875rem;color:var(--app-text-muted);opacity:.7;white-space:nowrap;margin-top:1px}.step-connector{flex:1;height:2px;background:var(--app-border);margin:0 10px 14px;border-radius:1px;transition:background .4s ease;align-self:center}.step-connector.completed{background:linear-gradient(90deg,#22c55e,var(--app-primary))}.stepper-progress-mobile{display:none;flex-direction:column;gap:8px;padding:16px 24px 0}@media(max-width:640px){.stepper-header{display:none}.stepper-progress-mobile{display:flex}}.progress-label{font-size:.8125rem;font-weight:600;color:var(--app-text)}.progress-bar-track{width:100%;height:6px;background:var(--app-border);border-radius:3px;overflow:hidden}.progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .4s cubic-bezier(.4,0,.2,1)}.stepper-form-body{display:flex;flex-direction:column;gap:24px;padding:24px}.step-content{animation:stepFadeIn .3s ease-out}@keyframes stepFadeIn{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}.step-fields{display:grid;grid-template-columns:1fr;gap:20px}.step-error-summary{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#f43f5e14;border:1px solid rgba(244,63,94,.25);border-radius:10px;margin-top:8px;animation:stepFadeIn .2s ease-out}.error-summary-icon{width:18px;height:18px;fill:#f43f5e;flex-shrink:0}.step-error-summary span{font-size:.8125rem;color:#f43f5e;font-weight:500}.stepper-actions{display:flex;justify-content:space-between;align-items:center;padding-top:8px;border-top:1px solid var(--app-border)}.stepper-actions-left,.stepper-actions-right{display:flex;gap:10px;align-items:center}.btn-reset{display:flex;align-items:center;gap:6px;background:transparent;color:#ef4444;border:1px solid rgba(239,68,68,.3);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-reset svg{width:16px;height:16px;fill:currentColor}.btn-reset:hover{background:#ef44441a;border-color:#ef444480}.btn-reset:disabled{opacity:.5;cursor:not-allowed}.btn-back{display:flex;align-items:center;gap:6px;background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-back svg{width:16px;height:16px;fill:currentColor}.btn-back:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.btn-back:disabled{opacity:.5;cursor:not-allowed}.btn-skip{background:transparent;color:var(--app-text-muted);border:none;padding:10px 16px;border-radius:10px;font-weight:500;font-size:.8125rem;cursor:pointer;transition:color .2s}.btn-skip:hover{color:var(--app-primary)}.btn-skip:disabled{opacity:.5;cursor:not-allowed}.btn-next{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:10px 24px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-next svg{width:16px;height:16px;fill:currentColor}.btn-next:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-next:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-submit{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,#22c55e,#16a34a);color:#fff;border:none;padding:10px 28px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-submit svg{width:16px;height:16px;fill:currentColor}.btn-submit:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #22c55e59}.btn-submit:disabled{opacity:.5;cursor:not-allowed;transform:none}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FieldRendererComponent, selector: "amf-field-renderer", inputs: ["field", "form", "formDisabled", "actionDispatcher", "context"] }] });
4152
4152
  }
4153
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: StepperFormRendererComponent, decorators: [{
4153
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: StepperFormRendererComponent, decorators: [{
4154
4154
  type: Component,
4155
- args: [{ selector: 'amf-stepper-form-renderer', standalone: true, imports: [ReactiveFormsModule, FieldRendererComponent], template: `
4156
- <div class="amf-stepper" [class]="config.cssClass" [class.stepper-disabled]="config.disabled">
4157
-
4158
- <!-- ─── Step Header ──────────────────────────────────── -->
4159
- <div class="stepper-header">
4160
- @for (step of resolvedSteps(); track $index) {
4161
- <div class="step-item"
4162
- [class.active]="$index === currentStep()"
4163
- [class.completed]="isCompleted($index)"
4164
- [class.skipped]="isSkipped($index)"
4165
- [class.navigable]="canNavigateTo($index)"
4166
- (click)="canNavigateTo($index) && goToStep($index)">
4167
- <div class="step-indicator">
4168
- @if (isCompleted($index)) {
4169
- <svg class="check-icon" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4170
- } @else if (isSkipped($index)) {
4171
- <svg class="skip-icon" viewBox="0 0 24 24"><path d="M6 18l8.5-6L6 6v12zm2-8.14L11.03 12 8 14.14V9.86zM16 6h2v12h-2z"/></svg>
4172
- } @else {
4173
- <span class="step-number">{{ $index + 1 }}</span>
4174
- }
4175
- </div>
4176
- <div class="step-label-group">
4177
- <span class="step-title">{{ step.title }}</span>
4178
- @if (step.description) { <span class="step-description">{{ step.description }}</span> }
4179
- </div>
4180
- @if ($index < resolvedSteps().length - 1) {
4181
- <div class="step-connector" [class.completed]="isCompleted($index)"></div>
4182
- }
4183
- </div>
4184
- }
4185
- </div>
4186
-
4187
- <!-- ─── Mobile Progress Bar ───────────────────────────── -->
4188
- <div class="stepper-progress-mobile">
4189
- <span class="progress-label">Step {{ currentStep() + 1 }} of {{ resolvedSteps().length }}: {{ resolvedSteps()[currentStep()]?.title }}</span>
4190
- <div class="progress-bar-track">
4191
- <div class="progress-bar-fill" [style.width.%]="progressPercent()"></div>
4192
- </div>
4193
- </div>
4194
-
4195
- <!-- ─── Step Content ─────────────────────────────────── -->
4196
- <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="stepper-form-body">
4197
- <div class="step-content">
4198
- <div class="step-fields" [style.grid-template-columns]="currentGridColumns()">
4199
- @for (field of currentStepVisibleFields(); track field.key) {
4200
- <amf-field-renderer
4201
- [field]="field"
4202
- [form]="formGroup"
4203
- [formDisabled]="!!config.disabled"
4204
- [actionDispatcher]="actionDispatcher"
4205
- [context]="context"
4206
- [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null">
4207
- </amf-field-renderer>
4208
- }
4209
- </div>
4210
-
4211
- <!-- Step-level validation error summary -->
4212
- @if (stepErrors().length) {
4213
- <div class="step-error-summary">
4214
- <svg viewBox="0 0 24 24" class="error-summary-icon"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
4215
- <span>Please fix {{ stepErrors().length }} error{{ stepErrors().length > 1 ? 's' : '' }} before continuing.</span>
4216
- </div>
4217
- }
4218
- </div>
4219
-
4220
- <!-- ─── Navigation Actions ────────────────────────────── -->
4221
- <div class="stepper-actions">
4222
- <div class="stepper-actions-left">
4223
- @if (config.showReset) {
4224
- <button type="button" class="btn-reset" (click)="resetForm()" [disabled]="config.disabled">
4225
- <svg viewBox="0 0 24 24"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
4226
- {{ config.resetLabel || 'Start Over' }}
4227
- </button>
4228
- }
4229
- @if (currentStep() > 0) {
4230
- <button type="button" class="btn-back" (click)="goBack()" [disabled]="config.disabled">
4231
- <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
4232
- Back
4233
- </button>
4234
- }
4235
- </div>
4236
- <div class="stepper-actions-right">
4237
- @if (resolvedSteps()[currentStep()]?.optional) {
4238
- <button type="button" class="btn-skip" (click)="skipStep()" [disabled]="config.disabled">Skip</button>
4239
- }
4240
- @if (currentStep() < resolvedSteps().length - 1) {
4241
- <button type="button" class="btn-next" (click)="goNext()" [disabled]="config.disabled">
4242
- {{ resolvedSteps()[currentStep() + 1] ? 'Next' : 'Review' }}
4243
- <svg viewBox="0 0 24 24"><path d="M4 11v2h12l-5.59 5.59L12 20l8-8-8-8-1.41 1.41L16 11H4z"/></svg>
4244
- </button>
4245
- } @else {
4246
- @if (!config.hideSubmit) {
4247
- <button type="submit" class="btn-submit" [disabled]="formGroup.invalid || config.disabled">
4248
- {{ config.submitLabel || 'Submit' }}
4249
- <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4250
- </button>
4251
- }
4252
- }
4253
- </div>
4254
- </div>
4255
- </form>
4256
- </div>
4155
+ args: [{ selector: 'amf-stepper-form-renderer', standalone: true, imports: [ReactiveFormsModule, FieldRendererComponent], template: `
4156
+ <div class="amf-stepper" [class]="config.cssClass" [class.stepper-disabled]="config.disabled">
4157
+
4158
+ <!-- ─── Step Header ──────────────────────────────────── -->
4159
+ <div class="stepper-header">
4160
+ @for (step of resolvedSteps(); track $index) {
4161
+ <div class="step-item"
4162
+ [class.active]="$index === currentStep()"
4163
+ [class.completed]="isCompleted($index)"
4164
+ [class.skipped]="isSkipped($index)"
4165
+ [class.navigable]="canNavigateTo($index)"
4166
+ (click)="canNavigateTo($index) && goToStep($index)">
4167
+ <div class="step-indicator">
4168
+ @if (isCompleted($index)) {
4169
+ <svg class="check-icon" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4170
+ } @else if (isSkipped($index)) {
4171
+ <svg class="skip-icon" viewBox="0 0 24 24"><path d="M6 18l8.5-6L6 6v12zm2-8.14L11.03 12 8 14.14V9.86zM16 6h2v12h-2z"/></svg>
4172
+ } @else {
4173
+ <span class="step-number">{{ $index + 1 }}</span>
4174
+ }
4175
+ </div>
4176
+ <div class="step-label-group">
4177
+ <span class="step-title">{{ step.title }}</span>
4178
+ @if (step.description) { <span class="step-description">{{ step.description }}</span> }
4179
+ </div>
4180
+ @if ($index < resolvedSteps().length - 1) {
4181
+ <div class="step-connector" [class.completed]="isCompleted($index)"></div>
4182
+ }
4183
+ </div>
4184
+ }
4185
+ </div>
4186
+
4187
+ <!-- ─── Mobile Progress Bar ───────────────────────────── -->
4188
+ <div class="stepper-progress-mobile">
4189
+ <span class="progress-label">Step {{ currentStep() + 1 }} of {{ resolvedSteps().length }}: {{ resolvedSteps()[currentStep()]?.title }}</span>
4190
+ <div class="progress-bar-track">
4191
+ <div class="progress-bar-fill" [style.width.%]="progressPercent()"></div>
4192
+ </div>
4193
+ </div>
4194
+
4195
+ <!-- ─── Step Content ─────────────────────────────────── -->
4196
+ <form [formGroup]="formGroup" (ngSubmit)="onSubmit()" class="stepper-form-body">
4197
+ <div class="step-content">
4198
+ <div class="step-fields" [style.grid-template-columns]="currentGridColumns()">
4199
+ @for (field of currentStepVisibleFields(); track field.key) {
4200
+ <amf-field-renderer
4201
+ [field]="field"
4202
+ [form]="formGroup"
4203
+ [formDisabled]="!!config.disabled"
4204
+ [actionDispatcher]="actionDispatcher"
4205
+ [context]="context"
4206
+ [style.grid-column]="field.colSpan ? 'span ' + field.colSpan : null">
4207
+ </amf-field-renderer>
4208
+ }
4209
+ </div>
4210
+
4211
+ <!-- Step-level validation error summary -->
4212
+ @if (stepErrors().length) {
4213
+ <div class="step-error-summary">
4214
+ <svg viewBox="0 0 24 24" class="error-summary-icon"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
4215
+ <span>Please fix {{ stepErrors().length }} error{{ stepErrors().length > 1 ? 's' : '' }} before continuing.</span>
4216
+ </div>
4217
+ }
4218
+ </div>
4219
+
4220
+ <!-- ─── Navigation Actions ────────────────────────────── -->
4221
+ <div class="stepper-actions">
4222
+ <div class="stepper-actions-left">
4223
+ @if (config.showReset) {
4224
+ <button type="button" class="btn-reset" (click)="resetForm()" [disabled]="config.disabled">
4225
+ <svg viewBox="0 0 24 24"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
4226
+ {{ config.resetLabel || 'Start Over' }}
4227
+ </button>
4228
+ }
4229
+ @if (currentStep() > 0) {
4230
+ <button type="button" class="btn-back" (click)="goBack()" [disabled]="config.disabled">
4231
+ <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
4232
+ Back
4233
+ </button>
4234
+ }
4235
+ </div>
4236
+ <div class="stepper-actions-right">
4237
+ @if (resolvedSteps()[currentStep()]?.optional) {
4238
+ <button type="button" class="btn-skip" (click)="skipStep()" [disabled]="config.disabled">Skip</button>
4239
+ }
4240
+ @if (currentStep() < resolvedSteps().length - 1) {
4241
+ <button type="button" class="btn-next" (click)="goNext()" [disabled]="config.disabled">
4242
+ {{ resolvedSteps()[currentStep() + 1] ? 'Next' : 'Review' }}
4243
+ <svg viewBox="0 0 24 24"><path d="M4 11v2h12l-5.59 5.59L12 20l8-8-8-8-1.41 1.41L16 11H4z"/></svg>
4244
+ </button>
4245
+ } @else {
4246
+ @if (!config.hideSubmit) {
4247
+ <button type="submit" class="btn-submit" [disabled]="formGroup.invalid || config.disabled">
4248
+ {{ config.submitLabel || 'Submit' }}
4249
+ <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4250
+ </button>
4251
+ }
4252
+ }
4253
+ </div>
4254
+ </div>
4255
+ </form>
4256
+ </div>
4257
4257
  `, styles: [".amf-stepper{display:flex;flex-direction:column;gap:0}.amf-stepper.stepper-disabled{opacity:.6;pointer-events:none}.stepper-header{display:flex;align-items:flex-start;gap:0;padding:20px 24px 0;overflow-x:auto;scrollbar-width:none}.stepper-header::-webkit-scrollbar{display:none}.step-item{display:flex;align-items:center;flex:1;min-width:0;cursor:default;position:relative}.step-item.navigable{cursor:pointer}.step-item.navigable:hover .step-indicator{border-color:var(--app-primary)}.step-item.navigable:hover .step-title{color:var(--app-text)}.step-indicator{flex-shrink:0;width:36px;height:36px;border-radius:50%;border:2px solid var(--app-border);background:var(--app-surface);display:flex;align-items:center;justify-content:center;transition:all .35s cubic-bezier(.4,0,.2,1);position:relative;z-index:1}.step-item.active .step-indicator{border-color:var(--app-primary);background:var(--app-primary);box-shadow:0 0 0 4px rgba(var(--app-primary-rgb, 99 102 241),.18)}.step-item.completed .step-indicator{border-color:#22c55e;background:#22c55e}.step-item.skipped .step-indicator{border-color:var(--app-text-muted);background:var(--glass-bg)}.step-number{font-size:.8125rem;font-weight:700;color:var(--app-text-muted)}.step-item.active .step-number{color:#fff}.check-icon,.skip-icon{width:18px;height:18px;fill:#fff}.skip-icon{fill:var(--app-text-muted)}.step-label-group{display:flex;flex-direction:column;margin-left:10px;min-width:0;flex-shrink:0}.step-title{font-size:.8125rem;font-weight:600;color:var(--app-text-muted);white-space:nowrap;transition:color .2s}.step-item.active .step-title{color:var(--app-text)}.step-item.completed .step-title{color:var(--app-text-muted)}.step-description{font-size:.6875rem;color:var(--app-text-muted);opacity:.7;white-space:nowrap;margin-top:1px}.step-connector{flex:1;height:2px;background:var(--app-border);margin:0 10px 14px;border-radius:1px;transition:background .4s ease;align-self:center}.step-connector.completed{background:linear-gradient(90deg,#22c55e,var(--app-primary))}.stepper-progress-mobile{display:none;flex-direction:column;gap:8px;padding:16px 24px 0}@media(max-width:640px){.stepper-header{display:none}.stepper-progress-mobile{display:flex}}.progress-label{font-size:.8125rem;font-weight:600;color:var(--app-text)}.progress-bar-track{width:100%;height:6px;background:var(--app-border);border-radius:3px;overflow:hidden}.progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .4s cubic-bezier(.4,0,.2,1)}.stepper-form-body{display:flex;flex-direction:column;gap:24px;padding:24px}.step-content{animation:stepFadeIn .3s ease-out}@keyframes stepFadeIn{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}.step-fields{display:grid;grid-template-columns:1fr;gap:20px}.step-error-summary{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#f43f5e14;border:1px solid rgba(244,63,94,.25);border-radius:10px;margin-top:8px;animation:stepFadeIn .2s ease-out}.error-summary-icon{width:18px;height:18px;fill:#f43f5e;flex-shrink:0}.step-error-summary span{font-size:.8125rem;color:#f43f5e;font-weight:500}.stepper-actions{display:flex;justify-content:space-between;align-items:center;padding-top:8px;border-top:1px solid var(--app-border)}.stepper-actions-left,.stepper-actions-right{display:flex;gap:10px;align-items:center}.btn-reset{display:flex;align-items:center;gap:6px;background:transparent;color:#ef4444;border:1px solid rgba(239,68,68,.3);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-reset svg{width:16px;height:16px;fill:currentColor}.btn-reset:hover{background:#ef44441a;border-color:#ef444480}.btn-reset:disabled{opacity:.5;cursor:not-allowed}.btn-back{display:flex;align-items:center;gap:6px;background:var(--glass-bg);color:var(--app-text);border:1px solid var(--app-border);padding:10px 20px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .2s}.btn-back svg{width:16px;height:16px;fill:currentColor}.btn-back:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light)}.btn-back:disabled{opacity:.5;cursor:not-allowed}.btn-skip{background:transparent;color:var(--app-text-muted);border:none;padding:10px 16px;border-radius:10px;font-weight:500;font-size:.8125rem;cursor:pointer;transition:color .2s}.btn-skip:hover{color:var(--app-primary)}.btn-skip:disabled{opacity:.5;cursor:not-allowed}.btn-next{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:10px 24px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-next svg{width:16px;height:16px;fill:currentColor}.btn-next:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-next:disabled{opacity:.5;cursor:not-allowed;transform:none}.btn-submit{display:flex;align-items:center;gap:6px;background:linear-gradient(135deg,#22c55e,#16a34a);color:#fff;border:none;padding:10px 28px;border-radius:10px;font-weight:600;font-size:.875rem;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.btn-submit svg{width:16px;height:16px;fill:currentColor}.btn-submit:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 24px -4px #22c55e59}.btn-submit:disabled{opacity:.5;cursor:not-allowed;transform:none}\n"] }]
4258
4258
  }], propDecorators: { config: [{
4259
4259
  type: Input
@@ -4285,61 +4285,61 @@ class CellRendererComponent {
4285
4285
  return '';
4286
4286
  return path.split('.').reduce((c, k) => c?.[k], obj) ?? '';
4287
4287
  }
4288
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CellRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4289
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: CellRendererComponent, isStandalone: true, selector: "amf-cell-renderer", inputs: { column: "column", row: "row", value: "value" }, ngImport: i0, template: `
4290
- @switch (column.type || 'text') {
4291
- @case ('badge') { <span class="cell-badge" [class]="getBadgeClass()">{{ value | titlecase }}</span> }
4292
- @case ('avatar') {
4293
- <div class="cell-avatar">
4294
- <div class="avatar-circle">{{ getInitial() }}</div>
4295
- <div class="avatar-info">
4296
- <span class="avatar-name">{{ value }}</span>
4297
- @if (column.subtitleKey) { <span class="avatar-subtitle">{{ getNestedValue(row, column.subtitleKey) }}</span> }
4298
- </div>
4299
- </div>
4300
- }
4301
- @case ('date') { <span>{{ value | date:(column.dateFormat || 'mediumDate') }}</span> }
4302
- @case ('datetime') { <span>{{ value | date:(column.dateFormat || 'medium') }}</span> }
4303
- @case ('currency') { <span>{{ value | currency:(column.currencyCodeKey ? getNestedValue(row, column.currencyCodeKey) : (column.currencyCode || 'USD')):(column.currencyDisplay !== undefined ? column.currencyDisplay : 'symbol') }}</span> }
4304
- @case ('boolean') { <span class="cell-boolean" [class.is-true]="value">{{ value ? '✓' : '✗' }}</span> }
4305
- @case ('number') { <span class="cell-number">{{ value }}</span> }
4306
- @case ('progress') {
4307
- <div class="cell-progress">
4308
- <div class="progress-bar"><div class="progress-fill" [style.width.%]="value"></div></div>
4309
- <span class="progress-text">{{ value }}%</span>
4310
- </div>
4311
- }
4312
- @default { <span>{{ value }}</span> }
4313
- }
4288
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CellRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4289
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: CellRendererComponent, isStandalone: true, selector: "amf-cell-renderer", inputs: { column: "column", row: "row", value: "value" }, ngImport: i0, template: `
4290
+ @switch (column.type || 'text') {
4291
+ @case ('badge') { <span class="cell-badge" [class]="getBadgeClass()">{{ value | titlecase }}</span> }
4292
+ @case ('avatar') {
4293
+ <div class="cell-avatar">
4294
+ <div class="avatar-circle">{{ getInitial() }}</div>
4295
+ <div class="avatar-info">
4296
+ <span class="avatar-name">{{ value }}</span>
4297
+ @if (column.subtitleKey) { <span class="avatar-subtitle">{{ getNestedValue(row, column.subtitleKey) }}</span> }
4298
+ </div>
4299
+ </div>
4300
+ }
4301
+ @case ('date') { <span>{{ value | date:(column.dateFormat || 'mediumDate') }}</span> }
4302
+ @case ('datetime') { <span>{{ value | date:(column.dateFormat || 'medium') }}</span> }
4303
+ @case ('currency') { <span>{{ value | currency:(column.currencyCodeKey ? getNestedValue(row, column.currencyCodeKey) : (column.currencyCode || 'USD')):(column.currencyDisplay !== undefined ? column.currencyDisplay : 'symbol') }}</span> }
4304
+ @case ('boolean') { <span class="cell-boolean" [class.is-true]="value">{{ value ? '✓' : '✗' }}</span> }
4305
+ @case ('number') { <span class="cell-number">{{ value }}</span> }
4306
+ @case ('progress') {
4307
+ <div class="cell-progress">
4308
+ <div class="progress-bar"><div class="progress-fill" [style.width.%]="value"></div></div>
4309
+ <span class="progress-text">{{ value }}%</span>
4310
+ </div>
4311
+ }
4312
+ @default { <span>{{ value }}</span> }
4313
+ }
4314
4314
  `, isInline: true, styles: [":host{display:contents}.cell-badge{padding:4px 10px;border-radius:6px;font-size:.75rem;font-weight:600;display:inline-block}.cell-badge.success,.cell-badge.active{background:#34d39926;color:#34d399}.cell-badge.danger,.cell-badge.inactive{background:#f43f5e26;color:#fb7185}.cell-badge.warning,.cell-badge.pending{background:#fbbf2426;color:#fbbf24}.cell-badge.info{background:#3b82f626;color:#60a5fa}.cell-badge.muted{background:var(--glass-bg);color:var(--app-text-muted)}.cell-avatar{display:flex;align-items:center;gap:12px}.avatar-circle{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.875rem;flex-shrink:0}.avatar-info{display:flex;flex-direction:column}.avatar-name{font-weight:600;color:var(--app-text);font-size:.875rem}.avatar-subtitle{font-size:.75rem;color:var(--app-text-muted)}.cell-boolean{font-weight:700}.cell-boolean.is-true{color:#34d399}.cell-boolean:not(.is-true){color:#fb7185}.cell-number{font-variant-numeric:tabular-nums}.cell-progress{display:flex;align-items:center;gap:8px}.progress-bar{flex:1;height:6px;background:var(--glass-bg);border-radius:3px;overflow:hidden}.progress-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .3s}.progress-text{font-size:.75rem;color:var(--app-text-muted);min-width:36px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: i1$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }] });
4315
4315
  }
4316
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CellRendererComponent, decorators: [{
4316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CellRendererComponent, decorators: [{
4317
4317
  type: Component,
4318
- args: [{ selector: 'amf-cell-renderer', standalone: true, imports: [CommonModule, TitleCasePipe, DatePipe, CurrencyPipe], template: `
4319
- @switch (column.type || 'text') {
4320
- @case ('badge') { <span class="cell-badge" [class]="getBadgeClass()">{{ value | titlecase }}</span> }
4321
- @case ('avatar') {
4322
- <div class="cell-avatar">
4323
- <div class="avatar-circle">{{ getInitial() }}</div>
4324
- <div class="avatar-info">
4325
- <span class="avatar-name">{{ value }}</span>
4326
- @if (column.subtitleKey) { <span class="avatar-subtitle">{{ getNestedValue(row, column.subtitleKey) }}</span> }
4327
- </div>
4328
- </div>
4329
- }
4330
- @case ('date') { <span>{{ value | date:(column.dateFormat || 'mediumDate') }}</span> }
4331
- @case ('datetime') { <span>{{ value | date:(column.dateFormat || 'medium') }}</span> }
4332
- @case ('currency') { <span>{{ value | currency:(column.currencyCodeKey ? getNestedValue(row, column.currencyCodeKey) : (column.currencyCode || 'USD')):(column.currencyDisplay !== undefined ? column.currencyDisplay : 'symbol') }}</span> }
4333
- @case ('boolean') { <span class="cell-boolean" [class.is-true]="value">{{ value ? '✓' : '✗' }}</span> }
4334
- @case ('number') { <span class="cell-number">{{ value }}</span> }
4335
- @case ('progress') {
4336
- <div class="cell-progress">
4337
- <div class="progress-bar"><div class="progress-fill" [style.width.%]="value"></div></div>
4338
- <span class="progress-text">{{ value }}%</span>
4339
- </div>
4340
- }
4341
- @default { <span>{{ value }}</span> }
4342
- }
4318
+ args: [{ selector: 'amf-cell-renderer', standalone: true, imports: [CommonModule, TitleCasePipe, DatePipe, CurrencyPipe], template: `
4319
+ @switch (column.type || 'text') {
4320
+ @case ('badge') { <span class="cell-badge" [class]="getBadgeClass()">{{ value | titlecase }}</span> }
4321
+ @case ('avatar') {
4322
+ <div class="cell-avatar">
4323
+ <div class="avatar-circle">{{ getInitial() }}</div>
4324
+ <div class="avatar-info">
4325
+ <span class="avatar-name">{{ value }}</span>
4326
+ @if (column.subtitleKey) { <span class="avatar-subtitle">{{ getNestedValue(row, column.subtitleKey) }}</span> }
4327
+ </div>
4328
+ </div>
4329
+ }
4330
+ @case ('date') { <span>{{ value | date:(column.dateFormat || 'mediumDate') }}</span> }
4331
+ @case ('datetime') { <span>{{ value | date:(column.dateFormat || 'medium') }}</span> }
4332
+ @case ('currency') { <span>{{ value | currency:(column.currencyCodeKey ? getNestedValue(row, column.currencyCodeKey) : (column.currencyCode || 'USD')):(column.currencyDisplay !== undefined ? column.currencyDisplay : 'symbol') }}</span> }
4333
+ @case ('boolean') { <span class="cell-boolean" [class.is-true]="value">{{ value ? '✓' : '✗' }}</span> }
4334
+ @case ('number') { <span class="cell-number">{{ value }}</span> }
4335
+ @case ('progress') {
4336
+ <div class="cell-progress">
4337
+ <div class="progress-bar"><div class="progress-fill" [style.width.%]="value"></div></div>
4338
+ <span class="progress-text">{{ value }}%</span>
4339
+ </div>
4340
+ }
4341
+ @default { <span>{{ value }}</span> }
4342
+ }
4343
4343
  `, styles: [":host{display:contents}.cell-badge{padding:4px 10px;border-radius:6px;font-size:.75rem;font-weight:600;display:inline-block}.cell-badge.success,.cell-badge.active{background:#34d39926;color:#34d399}.cell-badge.danger,.cell-badge.inactive{background:#f43f5e26;color:#fb7185}.cell-badge.warning,.cell-badge.pending{background:#fbbf2426;color:#fbbf24}.cell-badge.info{background:#3b82f626;color:#60a5fa}.cell-badge.muted{background:var(--glass-bg);color:var(--app-text-muted)}.cell-avatar{display:flex;align-items:center;gap:12px}.avatar-circle{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.875rem;flex-shrink:0}.avatar-info{display:flex;flex-direction:column}.avatar-name{font-weight:600;color:var(--app-text);font-size:.875rem}.avatar-subtitle{font-size:.75rem;color:var(--app-text-muted)}.cell-boolean{font-weight:700}.cell-boolean.is-true{color:#34d399}.cell-boolean:not(.is-true){color:#fb7185}.cell-number{font-variant-numeric:tabular-nums}.cell-progress{display:flex;align-items:center;gap:8px}.progress-bar{flex:1;height:6px;background:var(--glass-bg);border-radius:3px;overflow:hidden}.progress-fill{height:100%;background:linear-gradient(90deg,var(--app-primary),var(--app-accent));border-radius:3px;transition:width .3s}.progress-text{font-size:.75rem;color:var(--app-text-muted);min-width:36px}\n"] }]
4344
4344
  }], propDecorators: { column: [{
4345
4345
  type: Input
@@ -4776,405 +4776,405 @@ class TableRendererComponent {
4776
4776
  this.actionDispatcher.dispatch(this.config.onReorder, { ...this.context, previousIndex: event.previousIndex, currentIndex: event.currentIndex });
4777
4777
  }
4778
4778
  }
4779
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: TableRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4780
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: TableRendererComponent, isStandalone: true, selector: "amf-table-renderer", inputs: { config: "config", context: "context" }, outputs: { rowAction: "rowAction" }, ngImport: i0, template: `
4781
- <div class="amf-table-card" [class]="'variant-' + (config.variant || 'default') + ' ' + (config.cssClass || '')">
4782
- <div class="table-header">
4783
- <div class="table-header-left">
4784
- @if (config.searchable) {
4785
- <div class="search-box">
4786
- <svg viewBox="0 0 24 24" class="search-icon"><path [attr.d]="iconRegistry.getIcon('search')"></path></svg>
4787
- <input type="text" [placeholder]="config.searchPlaceholder || 'Search...'" [ngModel]="searchQuery()" (ngModelChange)="searchQuery.set($event)" />
4788
- </div>
4789
- }
4790
- @for (filter of config.filters || []; track filter.key) {
4791
- <select class="filter-select" [ngModel]="getFilterValue(filter.key)" (ngModelChange)="setFilterValue(filter.key, $event)">
4792
- <option value="">{{ filter.label }}</option>
4793
- @for (opt of filter.options; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
4794
- </select>
4795
- }
4796
- </div>
4797
- <div class="table-header-right">
4798
- @for (action of config.headerActions || []; track action.id) {
4799
- <button class="btn-primary btn-sm" (click)="handleAction(action, null)">
4800
- @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
4801
- {{ action.label }}
4802
- </button>
4803
- }
4804
-
4805
- @if (config.exportable) {
4806
- <div class="export-container">
4807
- <button class="btn-ghost btn-sm" (click)="exportMenuOpen.set(!exportMenuOpen())">
4808
- <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon('download')"></path></svg>
4809
- Export
4810
- </button>
4811
- @if (exportMenuOpen()) {
4812
- <div class="dropdown-menu export-menu">
4813
- @for (format of config.exportFormats || ['csv', 'json']; track format) {
4814
- <div class="dropdown-item" (click)="exportData(format); exportMenuOpen.set(false)">
4815
- Export as {{ format | uppercase }}
4816
- </div>
4817
- }
4818
- </div>
4819
- }
4820
- </div>
4821
- }
4822
- </div>
4823
- </div>
4824
- <div class="table-wrapper">
4825
- <table class="data-table" [class.striped]="config.striped" [class.hoverable]="config.hoverable !== false">
4826
- <thead>
4827
- <tr cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="dropColumn($event)">
4828
- @if (config.reorderable) { <th class="drag-col" style="width: 40px; text-align: center;"></th> }
4829
- @if (config.selectionMode === 'checkbox') {
4830
- <th class="selection-col" style="width: 40px; text-align: center;">
4831
- @if (config.showSelectAll !== false) {
4832
- <input type="checkbox"
4833
- class="amf-checkbox"
4834
- [checked]="selectedRows().size > 0 && selectedRows().size === filteredData().length"
4835
- (change)="toggleAllSelection($event)" />
4836
- }
4837
- </th>
4838
- }
4839
- @if (config.expandable) {
4840
- <th style="width: 36px;"></th>
4841
- }
4842
- @for (col of visibleColumns(); track col.key) {
4843
- <th cdkDrag [cdkDragDisabled]="!config.columnReorder" [style.width]="col.width" [style.min-width]="col.minWidth" [style.text-align]="col.align || 'left'" [class.sortable]="col.sortable" (click)="col.sortable ? toggleSort(col.key) : null">
4844
- {{ col.label }} @if (col.sortable && sortKey() === col.key) { <span class="sort-indicator">{{ sortDirection() === 'asc' ? '↑' : '↓' }}</span> }
4845
- </th>
4846
- }
4847
- @if (config.actions?.length) { <th class="actions-col">Actions</th> }
4848
- </tr>
4849
- </thead>
4850
- <tbody cdkDropList (cdkDropListDropped)="dropRow($event)">
4851
- @for (row of groupedRows(); track $index) {
4852
- @if (row.__isGroupHeader) {
4853
- <tr class="group-header-row">
4854
- <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + (config.expandable ? 1 : 0) + (config.actions?.length ? 1 : 0)">
4855
- <button class="group-toggle" (click)="toggleGroup(row.__groupKey)">
4856
- <span class="group-chevron" [class.open]="!collapsedGroups().has(row.__groupKey)">▶</span>
4857
- {{ config.groupBy }}: <strong>{{ row.__groupKey }}</strong>
4858
- <span class="group-count">({{ row.__count }} items)</span>
4859
- </button>
4860
- </td>
4861
- </tr>
4862
- } @else {
4863
- <tr cdkDrag [cdkDragDisabled]="!config.reorderable" (click)="handleRowClick(row)" [class.clickable]="config.rowClick || config.selectionMode === 'single' || config.selectionMode === 'multi'" [class.selected]="selectedRows().has(row)" [class.expanded]="expandedRows().has(row)">
4864
- @if (config.reorderable) {
4865
- <td class="drag-cell" (click)="$event.stopPropagation()" cdkDragHandle>
4866
- <svg viewBox="0 0 24 24" style="width:16px;height:16px;fill:var(--app-text-muted)"><path [attr.d]="iconRegistry.getIcon('menu')"></path></svg>
4867
- </td>
4868
- }
4869
- @if (config.selectionMode === 'checkbox') {
4870
- <td class="selection-cell" (click)="$event.stopPropagation(); toggleSelection(row)">
4871
- <input type="checkbox" class="amf-checkbox" [checked]="selectedRows().has(row)" (click)="$event.stopPropagation()" (change)="$event.stopPropagation(); toggleSelection(row)" />
4872
- </td>
4873
- }
4874
- @if (config.expandable) {
4875
- <td class="expand-cell" (click)="$event.stopPropagation(); toggleRowExpand(row)">
4876
- <span class="expand-chevron" [class.open]="expandedRows().has(row)">▶</span>
4877
- </td>
4878
- }
4879
- @for (col of visibleColumns(); track col.key) {
4880
- <td [style.text-align]="col.align || 'left'" (dblclick)="config.inlineEdit && col.editable !== false ? startEdit(row, col.key, $event) : null" [class.editable-cell]="config.inlineEdit && col.editable !== false">
4881
- @if (isEditing(row, col.key)) {
4882
- <div class="inline-edit-wrap" (click)="$event.stopPropagation()">
4883
- <div class="inline-edit-row">
4884
- @if (col.editType === 'select' && col.editOptions) {
4885
- <select class="inline-input" [(ngModel)]="editBuffer[col.key]">
4886
- @for (opt of col.editOptions; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
4887
- </select>
4888
- } @else {
4889
- <input class="inline-input" [type]="col.editType || 'text'" [(ngModel)]="editBuffer[col.key]" (keydown.enter)="commitEdit(row, col.key)" (keydown.escape)="cancelEdit()" />
4890
- }
4891
- <div class="inline-edit-actions">
4892
- <button class="ie-btn ie-save" title="Save (Enter)" (click)="commitEdit(row, col.key)">
4893
- <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4894
- </button>
4895
- <button class="ie-btn ie-cancel" title="Cancel (Esc)" (click)="cancelEdit()">
4896
- <svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
4897
- </button>
4898
- </div>
4899
- </div>
4900
- @if (editError()) {
4901
- <span class="inline-edit-error">{{ editError() }}</span>
4902
- }
4903
- </div>
4904
- } @else {
4905
- <amf-cell-renderer [column]="col" [row]="row" [value]="getCellValue(row, col.key)"></amf-cell-renderer>
4906
- }
4907
- </td>
4908
- }
4909
- @if (config.actions?.length) {
4910
- <td class="actions-cell">
4911
- <div class="action-btns">
4912
- @for (action of config.actions; track action.id) {
4913
- <button class="action-btn" [class]="action.variant || 'ghost'" [title]="action.label" (click)="handleAction(action, row); $event.stopPropagation()">
4914
- @if (action.icon) { <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> } @else { {{ action.label }} }
4915
- </button>
4916
- }
4917
- </div>
4918
- </td>
4919
- }
4920
- </tr>
4921
- @if (config.expandable && expandedRows().has(row)) {
4922
- <tr class="expanded-row">
4923
- <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + 1 + (config.actions?.length ? 1 : 0)" class="expanded-content">
4924
- @if (config.expandSection) {
4925
- <div class="expand-section">Row detail: {{ row | json }}</div>
4926
- } @else {
4927
- <div class="expand-section">
4928
- @for (col of visibleColumns(); track col.key) {
4929
- <div class="expand-field"><span class="expand-label">{{ col.label }}:</span> <span>{{ getCellValue(row, col.key) }}</span></div>
4930
- }
4931
- </div>
4932
- }
4933
- </td>
4934
- </tr>
4935
- }
4936
- }
4937
- } @empty { <tr><td [attr.colspan]="visibleColumns().length + (config.actions?.length ? 1 : 0)" class="empty-state">{{ config.emptyMessage || 'No data found.' }}</td></tr> }
4938
- @if (config.aggregates?.length) {
4939
- <tr class="aggregate-row">
4940
- @if (config.reorderable) { <td></td> }
4941
- @if (config.selectionMode === 'checkbox') { <td></td> }
4942
- @if (config.expandable) { <td></td> }
4943
- @for (col of visibleColumns(); track col.key) {
4944
- <td class="aggregate-cell" [style.text-align]="col.align || 'right'">
4945
- @if (getAggregate(col.key); as agg) { <span class="agg-value">{{ agg.label ? agg.label + ': ' : '' }}{{ agg.value }}</span> }
4946
- </td>
4947
- }
4948
- @if (config.actions?.length) { <td></td> }
4949
- </tr>
4950
- }
4951
- </tbody>
4952
- </table>
4953
- </div>
4954
- @if (config.pagination?.enabled) {
4955
- <div class="table-footer">
4956
- <div class="footer-left">
4957
- <span class="results-count">Showing {{ paginatedData().length }} of {{ filteredData().length }} @if (config.pagination?.showTotal) { (total: {{ allData().length }}) }</span>
4958
- @if ((config.pagination?.pageSizeOptions || [5, 10, 25, 50]).length > 1) {
4959
- <div class="page-size-wrap">
4960
- <label class="page-size-label">Rows:</label>
4961
- <select class="page-size-select" [ngModel]="activePageSize()" (ngModelChange)="setPageSize($event)">
4962
- @for (opt of config.pagination?.pageSizeOptions || [5, 10, 25, 50]; track opt) {
4963
- <option [value]="opt">{{ opt }}</option>
4964
- }
4965
- </select>
4966
- </div>
4967
- }
4968
- </div>
4969
- <div class="pagination">
4970
- <button class="btn-page-nav" [disabled]="currentPage() <= 1" (click)="currentPage.set(currentPage() - 1)">Previous</button>
4971
- @for (p of pageNumbers(); track p) { <button class="btn-page" [class.active]="p === currentPage()" (click)="currentPage.set(p)">{{ p }}</button> }
4972
- <button class="btn-page-nav" [disabled]="currentPage() >= totalPages()" (click)="currentPage.set(currentPage() + 1)">Next</button>
4973
- </div>
4974
- </div>
4975
- }
4976
- </div>
4779
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4780
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TableRendererComponent, isStandalone: true, selector: "amf-table-renderer", inputs: { config: "config", context: "context" }, outputs: { rowAction: "rowAction" }, ngImport: i0, template: `
4781
+ <div class="amf-table-card" [class]="'variant-' + (config.variant || 'default') + ' ' + (config.cssClass || '')">
4782
+ <div class="table-header">
4783
+ <div class="table-header-left">
4784
+ @if (config.searchable) {
4785
+ <div class="search-box">
4786
+ <svg viewBox="0 0 24 24" class="search-icon"><path [attr.d]="iconRegistry.getIcon('search')"></path></svg>
4787
+ <input type="text" [placeholder]="config.searchPlaceholder || 'Search...'" [ngModel]="searchQuery()" (ngModelChange)="searchQuery.set($event)" />
4788
+ </div>
4789
+ }
4790
+ @for (filter of config.filters || []; track filter.key) {
4791
+ <select class="filter-select" [ngModel]="getFilterValue(filter.key)" (ngModelChange)="setFilterValue(filter.key, $event)">
4792
+ <option value="">{{ filter.label }}</option>
4793
+ @for (opt of filter.options; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
4794
+ </select>
4795
+ }
4796
+ </div>
4797
+ <div class="table-header-right">
4798
+ @for (action of config.headerActions || []; track action.id) {
4799
+ <button class="btn-primary btn-sm" (click)="handleAction(action, null)">
4800
+ @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
4801
+ {{ action.label }}
4802
+ </button>
4803
+ }
4804
+
4805
+ @if (config.exportable) {
4806
+ <div class="export-container">
4807
+ <button class="btn-ghost btn-sm" (click)="exportMenuOpen.set(!exportMenuOpen())">
4808
+ <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon('download')"></path></svg>
4809
+ Export
4810
+ </button>
4811
+ @if (exportMenuOpen()) {
4812
+ <div class="dropdown-menu export-menu">
4813
+ @for (format of config.exportFormats || ['csv', 'json']; track format) {
4814
+ <div class="dropdown-item" (click)="exportData(format); exportMenuOpen.set(false)">
4815
+ Export as {{ format | uppercase }}
4816
+ </div>
4817
+ }
4818
+ </div>
4819
+ }
4820
+ </div>
4821
+ }
4822
+ </div>
4823
+ </div>
4824
+ <div class="table-wrapper">
4825
+ <table class="data-table" [class.striped]="config.striped" [class.hoverable]="config.hoverable !== false">
4826
+ <thead>
4827
+ <tr cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="dropColumn($event)">
4828
+ @if (config.reorderable) { <th class="drag-col" style="width: 40px; text-align: center;"></th> }
4829
+ @if (config.selectionMode === 'checkbox') {
4830
+ <th class="selection-col" style="width: 40px; text-align: center;">
4831
+ @if (config.showSelectAll !== false) {
4832
+ <input type="checkbox"
4833
+ class="amf-checkbox"
4834
+ [checked]="selectedRows().size > 0 && selectedRows().size === filteredData().length"
4835
+ (change)="toggleAllSelection($event)" />
4836
+ }
4837
+ </th>
4838
+ }
4839
+ @if (config.expandable) {
4840
+ <th style="width: 36px;"></th>
4841
+ }
4842
+ @for (col of visibleColumns(); track col.key) {
4843
+ <th cdkDrag [cdkDragDisabled]="!config.columnReorder" [style.width]="col.width" [style.min-width]="col.minWidth" [style.text-align]="col.align || 'left'" [class.sortable]="col.sortable" (click)="col.sortable ? toggleSort(col.key) : null">
4844
+ {{ col.label }} @if (col.sortable && sortKey() === col.key) { <span class="sort-indicator">{{ sortDirection() === 'asc' ? '↑' : '↓' }}</span> }
4845
+ </th>
4846
+ }
4847
+ @if (config.actions?.length) { <th class="actions-col">Actions</th> }
4848
+ </tr>
4849
+ </thead>
4850
+ <tbody cdkDropList (cdkDropListDropped)="dropRow($event)">
4851
+ @for (row of groupedRows(); track $index) {
4852
+ @if (row.__isGroupHeader) {
4853
+ <tr class="group-header-row">
4854
+ <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + (config.expandable ? 1 : 0) + (config.actions?.length ? 1 : 0)">
4855
+ <button class="group-toggle" (click)="toggleGroup(row.__groupKey)">
4856
+ <span class="group-chevron" [class.open]="!collapsedGroups().has(row.__groupKey)">▶</span>
4857
+ {{ config.groupBy }}: <strong>{{ row.__groupKey }}</strong>
4858
+ <span class="group-count">({{ row.__count }} items)</span>
4859
+ </button>
4860
+ </td>
4861
+ </tr>
4862
+ } @else {
4863
+ <tr cdkDrag [cdkDragDisabled]="!config.reorderable" (click)="handleRowClick(row)" [class.clickable]="config.rowClick || config.selectionMode === 'single' || config.selectionMode === 'multi'" [class.selected]="selectedRows().has(row)" [class.expanded]="expandedRows().has(row)">
4864
+ @if (config.reorderable) {
4865
+ <td class="drag-cell" (click)="$event.stopPropagation()" cdkDragHandle>
4866
+ <svg viewBox="0 0 24 24" style="width:16px;height:16px;fill:var(--app-text-muted)"><path [attr.d]="iconRegistry.getIcon('menu')"></path></svg>
4867
+ </td>
4868
+ }
4869
+ @if (config.selectionMode === 'checkbox') {
4870
+ <td class="selection-cell" (click)="$event.stopPropagation(); toggleSelection(row)">
4871
+ <input type="checkbox" class="amf-checkbox" [checked]="selectedRows().has(row)" (click)="$event.stopPropagation()" (change)="$event.stopPropagation(); toggleSelection(row)" />
4872
+ </td>
4873
+ }
4874
+ @if (config.expandable) {
4875
+ <td class="expand-cell" (click)="$event.stopPropagation(); toggleRowExpand(row)">
4876
+ <span class="expand-chevron" [class.open]="expandedRows().has(row)">▶</span>
4877
+ </td>
4878
+ }
4879
+ @for (col of visibleColumns(); track col.key) {
4880
+ <td [style.text-align]="col.align || 'left'" (dblclick)="config.inlineEdit && col.editable !== false ? startEdit(row, col.key, $event) : null" [class.editable-cell]="config.inlineEdit && col.editable !== false">
4881
+ @if (isEditing(row, col.key)) {
4882
+ <div class="inline-edit-wrap" (click)="$event.stopPropagation()">
4883
+ <div class="inline-edit-row">
4884
+ @if (col.editType === 'select' && col.editOptions) {
4885
+ <select class="inline-input" [(ngModel)]="editBuffer[col.key]">
4886
+ @for (opt of col.editOptions; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
4887
+ </select>
4888
+ } @else {
4889
+ <input class="inline-input" [type]="col.editType || 'text'" [(ngModel)]="editBuffer[col.key]" (keydown.enter)="commitEdit(row, col.key)" (keydown.escape)="cancelEdit()" />
4890
+ }
4891
+ <div class="inline-edit-actions">
4892
+ <button class="ie-btn ie-save" title="Save (Enter)" (click)="commitEdit(row, col.key)">
4893
+ <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
4894
+ </button>
4895
+ <button class="ie-btn ie-cancel" title="Cancel (Esc)" (click)="cancelEdit()">
4896
+ <svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
4897
+ </button>
4898
+ </div>
4899
+ </div>
4900
+ @if (editError()) {
4901
+ <span class="inline-edit-error">{{ editError() }}</span>
4902
+ }
4903
+ </div>
4904
+ } @else {
4905
+ <amf-cell-renderer [column]="col" [row]="row" [value]="getCellValue(row, col.key)"></amf-cell-renderer>
4906
+ }
4907
+ </td>
4908
+ }
4909
+ @if (config.actions?.length) {
4910
+ <td class="actions-cell">
4911
+ <div class="action-btns">
4912
+ @for (action of config.actions; track action.id) {
4913
+ <button class="action-btn" [class]="action.variant || 'ghost'" [title]="action.label" (click)="handleAction(action, row); $event.stopPropagation()">
4914
+ @if (action.icon) { <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> } @else { {{ action.label }} }
4915
+ </button>
4916
+ }
4917
+ </div>
4918
+ </td>
4919
+ }
4920
+ </tr>
4921
+ @if (config.expandable && expandedRows().has(row)) {
4922
+ <tr class="expanded-row">
4923
+ <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + 1 + (config.actions?.length ? 1 : 0)" class="expanded-content">
4924
+ @if (config.expandSection) {
4925
+ <div class="expand-section">Row detail: {{ row | json }}</div>
4926
+ } @else {
4927
+ <div class="expand-section">
4928
+ @for (col of visibleColumns(); track col.key) {
4929
+ <div class="expand-field"><span class="expand-label">{{ col.label }}:</span> <span>{{ getCellValue(row, col.key) }}</span></div>
4930
+ }
4931
+ </div>
4932
+ }
4933
+ </td>
4934
+ </tr>
4935
+ }
4936
+ }
4937
+ } @empty { <tr><td [attr.colspan]="visibleColumns().length + (config.actions?.length ? 1 : 0)" class="empty-state">{{ config.emptyMessage || 'No data found.' }}</td></tr> }
4938
+ @if (config.aggregates?.length) {
4939
+ <tr class="aggregate-row">
4940
+ @if (config.reorderable) { <td></td> }
4941
+ @if (config.selectionMode === 'checkbox') { <td></td> }
4942
+ @if (config.expandable) { <td></td> }
4943
+ @for (col of visibleColumns(); track col.key) {
4944
+ <td class="aggregate-cell" [style.text-align]="col.align || 'right'">
4945
+ @if (getAggregate(col.key); as agg) { <span class="agg-value">{{ agg.label ? agg.label + ': ' : '' }}{{ agg.value }}</span> }
4946
+ </td>
4947
+ }
4948
+ @if (config.actions?.length) { <td></td> }
4949
+ </tr>
4950
+ }
4951
+ </tbody>
4952
+ </table>
4953
+ </div>
4954
+ @if (config.pagination?.enabled) {
4955
+ <div class="table-footer">
4956
+ <div class="footer-left">
4957
+ <span class="results-count">Showing {{ paginatedData().length }} of {{ filteredData().length }} @if (config.pagination?.showTotal) { (total: {{ allData().length }}) }</span>
4958
+ @if ((config.pagination?.pageSizeOptions || [5, 10, 25, 50]).length > 1) {
4959
+ <div class="page-size-wrap">
4960
+ <label class="page-size-label">Rows:</label>
4961
+ <select class="page-size-select" [ngModel]="activePageSize()" (ngModelChange)="setPageSize($event)">
4962
+ @for (opt of config.pagination?.pageSizeOptions || [5, 10, 25, 50]; track opt) {
4963
+ <option [value]="opt">{{ opt }}</option>
4964
+ }
4965
+ </select>
4966
+ </div>
4967
+ }
4968
+ </div>
4969
+ <div class="pagination">
4970
+ <button class="btn-page-nav" [disabled]="currentPage() <= 1" (click)="currentPage.set(currentPage() - 1)">Previous</button>
4971
+ @for (p of pageNumbers(); track p) { <button class="btn-page" [class.active]="p === currentPage()" (click)="currentPage.set(p)">{{ p }}</button> }
4972
+ <button class="btn-page-nav" [disabled]="currentPage() >= totalPages()" (click)="currentPage.set(currentPage() + 1)">Next</button>
4973
+ </div>
4974
+ </div>
4975
+ }
4976
+ </div>
4977
4977
  `, isInline: true, styles: [".amf-table-card{background:var(--app-surface);border:1px solid var(--app-border);border-radius:16px;overflow:hidden;box-shadow:0 1px 3px #0000000d}.table-header{padding:16px 20px;display:flex;justify-content:space-between;align-items:center;gap:16px;border-bottom:1px solid var(--app-border);flex-wrap:wrap}.table-header-left,.table-header-right{display:flex;align-items:center;gap:12px}.search-box{position:relative;min-width:240px}.search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:16px;height:16px;fill:var(--app-text-muted)}.search-box input{width:100%;padding:8px 12px 8px 36px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text)}.search-box input:focus{border-color:var(--app-primary)}.filter-select{padding:8px 12px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text);color-scheme:dark}.filter-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .filter-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .filter-select option{background-color:#fff;color:#000}.table-wrapper{width:100%;overflow-x:auto}.data-table{width:100%;border-collapse:collapse;white-space:normal;word-break:break-word}.data-table th{background:var(--app-bg);padding:10px 20px;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--app-text-muted);border-bottom:1px solid var(--app-border);-webkit-user-select:none;user-select:none}.data-table th.sortable{cursor:pointer}.data-table th.sortable:hover{color:var(--app-primary)}.sort-indicator{margin-left:4px;font-size:.75rem}.data-table td{padding:14px 20px;border-bottom:1px solid var(--app-border);font-size:.875rem;color:var(--app-text)}.data-table.hoverable tbody tr:hover{background:var(--glass-bg)}.data-table.striped tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-striped .data-table tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-borderless{border:none!important;box-shadow:none!important;background:transparent!important}.variant-borderless .table-header{border-bottom:none;padding:0 0 16px}.variant-borderless .data-table th{background:transparent;border-bottom:2px solid var(--app-border)}.variant-borderless .data-table td{border-bottom:1px dashed var(--app-border)}.variant-borderless .table-footer{border-top:none;background:transparent;padding:16px 0 0}.variant-glass{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);box-shadow:var(--glass-shadow-sm)}.variant-glass .table-header,.variant-glass .table-footer,.variant-glass .data-table th{background:transparent;border-color:var(--glass-border)}.variant-glass .data-table td{border-bottom:1px solid var(--glass-border)}.variant-elevated{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-2px);transition:all .3s ease}.variant-compact .table-header{padding:12px 16px}.variant-compact .data-table th{padding:8px 16px;font-size:.625rem}.variant-compact .data-table td{padding:8px 16px;font-size:.8125rem}.variant-compact .table-footer{padding:8px 16px}tr.clickable{cursor:pointer}.amf-checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--app-primary)}.data-table tbody tr.selected{background:#3b82f626!important}.actions-col{text-align:right!important;width:120px}.actions-cell{text-align:right}.action-btns{display:flex;justify-content:flex-end;gap:6px}.action-btn{width:30px;height:30px;border-radius:6px;border:1px solid var(--app-border);background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s}.action-btn svg{width:14px;height:14px;fill:var(--app-text-muted)}.action-btn:hover{border-color:var(--app-primary)}.action-btn:hover svg{fill:var(--app-primary)}.action-btn.danger:hover{border-color:#f43f5e}.action-btn.danger:hover svg{fill:#f43f5e}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 4px 12px var(--app-glow)}.btn-icon{width:16px;height:16px;fill:currentColor}.btn-sm{padding:6px 12px;font-size:.75rem;border-radius:6px}.btn-ghost{background:transparent;border:1px solid var(--app-border);color:var(--app-text);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;display:flex;align-items:center;gap:6px;cursor:pointer;transition:all .2s}.btn-ghost:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.export-container{position:relative}.export-menu{position:absolute;top:calc(100% + 8px);right:0;background:var(--app-surface);border:1px solid var(--app-border);border-radius:12px;box-shadow:0 10px 40px #00000080;min-width:160px;z-index:100;overflow:hidden;animation:slideInDown .2s ease-out backwards}.export-menu .dropdown-item{padding:10px 16px;font-size:.8125rem;font-weight:500;cursor:pointer;color:var(--app-text);transition:background .2s}.export-menu .dropdown-item:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.empty-state{text-align:center;padding:40px!important;color:var(--app-text-muted)}.table-footer{padding:12px 20px;display:flex;justify-content:space-between;align-items:center;background:var(--app-bg);border-top:1px solid var(--app-border)}.footer-left{display:flex;align-items:center;gap:16px}.results-count{font-size:.75rem;color:var(--app-text-muted)}.page-size-wrap{display:flex;align-items:center;gap:6px}.page-size-label{font-size:.75rem;color:var(--app-text-muted);white-space:nowrap}.page-size-select{padding:4px 8px;border:1px solid var(--app-border);border-radius:6px;font-size:.75rem;background:var(--glass-bg);color:var(--app-text);outline:none;cursor:pointer;color-scheme:dark}.page-size-select option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) .page-size-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .page-size-select option{background-color:#fff;color:#000}.pagination{display:flex;gap:4px}.btn-page,.btn-page-nav{padding:6px 10px;border:1px solid var(--app-border);background:transparent;border-radius:6px;font-size:.75rem;font-weight:500;color:var(--app-text);cursor:pointer}.btn-page.active{background:var(--app-primary);border-color:var(--app-primary);color:#fff}.btn-page-nav:disabled{opacity:.4;cursor:not-allowed}.editable-cell{position:relative}.editable-cell:hover{background:#3b82f614;cursor:text}.inline-edit-wrap{display:flex;flex-direction:column;gap:4px;min-width:0}.inline-edit-row{display:flex;align-items:center;gap:4px}.inline-input{flex:1;min-width:0;padding:5px 8px;border:1.5px solid var(--app-primary);border-radius:6px;background:var(--app-surface);color:var(--app-text);font-size:.875rem;outline:none}.inline-input.input-invalid{border-color:#f43f5e}.inline-edit-error{font-size:.6875rem;color:#f43f5e;font-weight:500;padding:0 2px;animation:fadeIn .15s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.inline-edit-actions{display:flex;gap:3px;flex-shrink:0}.ie-btn{width:26px;height:26px;border-radius:5px;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s}.ie-btn svg{width:14px;height:14px;fill:currentColor}.ie-btn:hover{opacity:.85}.ie-save{background:#22c55e;color:#fff}.ie-cancel{background:var(--app-border);color:var(--app-text-muted)}select.inline-input{color-scheme:dark;cursor:pointer}select.inline-input option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) select.inline-input{color-scheme:light}:host-context([data-color-scheme=\"light\"]) select.inline-input option{background-color:#fff;color:#000}.expand-cell{width:36px;text-align:center;cursor:pointer}.expand-chevron{display:inline-block;transition:transform .2s;font-size:.625rem;color:var(--app-text-muted)}.expand-chevron.open{transform:rotate(90deg)}.expanded-row td,.expanded-content{padding:0!important}.expand-section{padding:14px 24px;display:flex;flex-wrap:wrap;gap:16px;background:var(--glass-bg);animation:fadeInUp .2s ease-out}.expand-field{display:flex;gap:8px;font-size:.8125rem}.expand-label{color:var(--app-text-muted);font-weight:600}.group-header-row td{background:var(--app-bg)}.group-toggle{display:flex;align-items:center;gap:8px;background:none;border:none;color:var(--app-text);cursor:pointer;font-size:.8125rem;padding:8px 16px}.group-chevron{display:inline-block;font-size:.625rem;transition:transform .2s;color:var(--app-text-muted)}.group-chevron.open{transform:rotate(90deg)}.group-count{color:var(--app-text-muted);font-size:.75rem}.aggregate-row td{background:var(--app-bg);border-top:2px solid var(--app-border)}.aggregate-cell{padding:10px 20px!important}.agg-value{font-size:.8125rem;font-weight:700;color:var(--app-primary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i2.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CellRendererComponent, selector: "amf-cell-renderer", inputs: ["column", "row", "value"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] });
4978
4978
  }
4979
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: TableRendererComponent, decorators: [{
4979
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableRendererComponent, decorators: [{
4980
4980
  type: Component,
4981
- args: [{ selector: 'amf-table-renderer', standalone: true, imports: [CommonModule, FormsModule, DragDropModule, CellRendererComponent], template: `
4982
- <div class="amf-table-card" [class]="'variant-' + (config.variant || 'default') + ' ' + (config.cssClass || '')">
4983
- <div class="table-header">
4984
- <div class="table-header-left">
4985
- @if (config.searchable) {
4986
- <div class="search-box">
4987
- <svg viewBox="0 0 24 24" class="search-icon"><path [attr.d]="iconRegistry.getIcon('search')"></path></svg>
4988
- <input type="text" [placeholder]="config.searchPlaceholder || 'Search...'" [ngModel]="searchQuery()" (ngModelChange)="searchQuery.set($event)" />
4989
- </div>
4990
- }
4991
- @for (filter of config.filters || []; track filter.key) {
4992
- <select class="filter-select" [ngModel]="getFilterValue(filter.key)" (ngModelChange)="setFilterValue(filter.key, $event)">
4993
- <option value="">{{ filter.label }}</option>
4994
- @for (opt of filter.options; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
4995
- </select>
4996
- }
4997
- </div>
4998
- <div class="table-header-right">
4999
- @for (action of config.headerActions || []; track action.id) {
5000
- <button class="btn-primary btn-sm" (click)="handleAction(action, null)">
5001
- @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
5002
- {{ action.label }}
5003
- </button>
5004
- }
5005
-
5006
- @if (config.exportable) {
5007
- <div class="export-container">
5008
- <button class="btn-ghost btn-sm" (click)="exportMenuOpen.set(!exportMenuOpen())">
5009
- <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon('download')"></path></svg>
5010
- Export
5011
- </button>
5012
- @if (exportMenuOpen()) {
5013
- <div class="dropdown-menu export-menu">
5014
- @for (format of config.exportFormats || ['csv', 'json']; track format) {
5015
- <div class="dropdown-item" (click)="exportData(format); exportMenuOpen.set(false)">
5016
- Export as {{ format | uppercase }}
5017
- </div>
5018
- }
5019
- </div>
5020
- }
5021
- </div>
5022
- }
5023
- </div>
5024
- </div>
5025
- <div class="table-wrapper">
5026
- <table class="data-table" [class.striped]="config.striped" [class.hoverable]="config.hoverable !== false">
5027
- <thead>
5028
- <tr cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="dropColumn($event)">
5029
- @if (config.reorderable) { <th class="drag-col" style="width: 40px; text-align: center;"></th> }
5030
- @if (config.selectionMode === 'checkbox') {
5031
- <th class="selection-col" style="width: 40px; text-align: center;">
5032
- @if (config.showSelectAll !== false) {
5033
- <input type="checkbox"
5034
- class="amf-checkbox"
5035
- [checked]="selectedRows().size > 0 && selectedRows().size === filteredData().length"
5036
- (change)="toggleAllSelection($event)" />
5037
- }
5038
- </th>
5039
- }
5040
- @if (config.expandable) {
5041
- <th style="width: 36px;"></th>
5042
- }
5043
- @for (col of visibleColumns(); track col.key) {
5044
- <th cdkDrag [cdkDragDisabled]="!config.columnReorder" [style.width]="col.width" [style.min-width]="col.minWidth" [style.text-align]="col.align || 'left'" [class.sortable]="col.sortable" (click)="col.sortable ? toggleSort(col.key) : null">
5045
- {{ col.label }} @if (col.sortable && sortKey() === col.key) { <span class="sort-indicator">{{ sortDirection() === 'asc' ? '↑' : '↓' }}</span> }
5046
- </th>
5047
- }
5048
- @if (config.actions?.length) { <th class="actions-col">Actions</th> }
5049
- </tr>
5050
- </thead>
5051
- <tbody cdkDropList (cdkDropListDropped)="dropRow($event)">
5052
- @for (row of groupedRows(); track $index) {
5053
- @if (row.__isGroupHeader) {
5054
- <tr class="group-header-row">
5055
- <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + (config.expandable ? 1 : 0) + (config.actions?.length ? 1 : 0)">
5056
- <button class="group-toggle" (click)="toggleGroup(row.__groupKey)">
5057
- <span class="group-chevron" [class.open]="!collapsedGroups().has(row.__groupKey)">▶</span>
5058
- {{ config.groupBy }}: <strong>{{ row.__groupKey }}</strong>
5059
- <span class="group-count">({{ row.__count }} items)</span>
5060
- </button>
5061
- </td>
5062
- </tr>
5063
- } @else {
5064
- <tr cdkDrag [cdkDragDisabled]="!config.reorderable" (click)="handleRowClick(row)" [class.clickable]="config.rowClick || config.selectionMode === 'single' || config.selectionMode === 'multi'" [class.selected]="selectedRows().has(row)" [class.expanded]="expandedRows().has(row)">
5065
- @if (config.reorderable) {
5066
- <td class="drag-cell" (click)="$event.stopPropagation()" cdkDragHandle>
5067
- <svg viewBox="0 0 24 24" style="width:16px;height:16px;fill:var(--app-text-muted)"><path [attr.d]="iconRegistry.getIcon('menu')"></path></svg>
5068
- </td>
5069
- }
5070
- @if (config.selectionMode === 'checkbox') {
5071
- <td class="selection-cell" (click)="$event.stopPropagation(); toggleSelection(row)">
5072
- <input type="checkbox" class="amf-checkbox" [checked]="selectedRows().has(row)" (click)="$event.stopPropagation()" (change)="$event.stopPropagation(); toggleSelection(row)" />
5073
- </td>
5074
- }
5075
- @if (config.expandable) {
5076
- <td class="expand-cell" (click)="$event.stopPropagation(); toggleRowExpand(row)">
5077
- <span class="expand-chevron" [class.open]="expandedRows().has(row)">▶</span>
5078
- </td>
5079
- }
5080
- @for (col of visibleColumns(); track col.key) {
5081
- <td [style.text-align]="col.align || 'left'" (dblclick)="config.inlineEdit && col.editable !== false ? startEdit(row, col.key, $event) : null" [class.editable-cell]="config.inlineEdit && col.editable !== false">
5082
- @if (isEditing(row, col.key)) {
5083
- <div class="inline-edit-wrap" (click)="$event.stopPropagation()">
5084
- <div class="inline-edit-row">
5085
- @if (col.editType === 'select' && col.editOptions) {
5086
- <select class="inline-input" [(ngModel)]="editBuffer[col.key]">
5087
- @for (opt of col.editOptions; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
5088
- </select>
5089
- } @else {
5090
- <input class="inline-input" [type]="col.editType || 'text'" [(ngModel)]="editBuffer[col.key]" (keydown.enter)="commitEdit(row, col.key)" (keydown.escape)="cancelEdit()" />
5091
- }
5092
- <div class="inline-edit-actions">
5093
- <button class="ie-btn ie-save" title="Save (Enter)" (click)="commitEdit(row, col.key)">
5094
- <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
5095
- </button>
5096
- <button class="ie-btn ie-cancel" title="Cancel (Esc)" (click)="cancelEdit()">
5097
- <svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
5098
- </button>
5099
- </div>
5100
- </div>
5101
- @if (editError()) {
5102
- <span class="inline-edit-error">{{ editError() }}</span>
5103
- }
5104
- </div>
5105
- } @else {
5106
- <amf-cell-renderer [column]="col" [row]="row" [value]="getCellValue(row, col.key)"></amf-cell-renderer>
5107
- }
5108
- </td>
5109
- }
5110
- @if (config.actions?.length) {
5111
- <td class="actions-cell">
5112
- <div class="action-btns">
5113
- @for (action of config.actions; track action.id) {
5114
- <button class="action-btn" [class]="action.variant || 'ghost'" [title]="action.label" (click)="handleAction(action, row); $event.stopPropagation()">
5115
- @if (action.icon) { <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> } @else { {{ action.label }} }
5116
- </button>
5117
- }
5118
- </div>
5119
- </td>
5120
- }
5121
- </tr>
5122
- @if (config.expandable && expandedRows().has(row)) {
5123
- <tr class="expanded-row">
5124
- <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + 1 + (config.actions?.length ? 1 : 0)" class="expanded-content">
5125
- @if (config.expandSection) {
5126
- <div class="expand-section">Row detail: {{ row | json }}</div>
5127
- } @else {
5128
- <div class="expand-section">
5129
- @for (col of visibleColumns(); track col.key) {
5130
- <div class="expand-field"><span class="expand-label">{{ col.label }}:</span> <span>{{ getCellValue(row, col.key) }}</span></div>
5131
- }
5132
- </div>
5133
- }
5134
- </td>
5135
- </tr>
5136
- }
5137
- }
5138
- } @empty { <tr><td [attr.colspan]="visibleColumns().length + (config.actions?.length ? 1 : 0)" class="empty-state">{{ config.emptyMessage || 'No data found.' }}</td></tr> }
5139
- @if (config.aggregates?.length) {
5140
- <tr class="aggregate-row">
5141
- @if (config.reorderable) { <td></td> }
5142
- @if (config.selectionMode === 'checkbox') { <td></td> }
5143
- @if (config.expandable) { <td></td> }
5144
- @for (col of visibleColumns(); track col.key) {
5145
- <td class="aggregate-cell" [style.text-align]="col.align || 'right'">
5146
- @if (getAggregate(col.key); as agg) { <span class="agg-value">{{ agg.label ? agg.label + ': ' : '' }}{{ agg.value }}</span> }
5147
- </td>
5148
- }
5149
- @if (config.actions?.length) { <td></td> }
5150
- </tr>
5151
- }
5152
- </tbody>
5153
- </table>
5154
- </div>
5155
- @if (config.pagination?.enabled) {
5156
- <div class="table-footer">
5157
- <div class="footer-left">
5158
- <span class="results-count">Showing {{ paginatedData().length }} of {{ filteredData().length }} @if (config.pagination?.showTotal) { (total: {{ allData().length }}) }</span>
5159
- @if ((config.pagination?.pageSizeOptions || [5, 10, 25, 50]).length > 1) {
5160
- <div class="page-size-wrap">
5161
- <label class="page-size-label">Rows:</label>
5162
- <select class="page-size-select" [ngModel]="activePageSize()" (ngModelChange)="setPageSize($event)">
5163
- @for (opt of config.pagination?.pageSizeOptions || [5, 10, 25, 50]; track opt) {
5164
- <option [value]="opt">{{ opt }}</option>
5165
- }
5166
- </select>
5167
- </div>
5168
- }
5169
- </div>
5170
- <div class="pagination">
5171
- <button class="btn-page-nav" [disabled]="currentPage() <= 1" (click)="currentPage.set(currentPage() - 1)">Previous</button>
5172
- @for (p of pageNumbers(); track p) { <button class="btn-page" [class.active]="p === currentPage()" (click)="currentPage.set(p)">{{ p }}</button> }
5173
- <button class="btn-page-nav" [disabled]="currentPage() >= totalPages()" (click)="currentPage.set(currentPage() + 1)">Next</button>
5174
- </div>
5175
- </div>
5176
- }
5177
- </div>
4981
+ args: [{ selector: 'amf-table-renderer', standalone: true, imports: [CommonModule, FormsModule, DragDropModule, CellRendererComponent], template: `
4982
+ <div class="amf-table-card" [class]="'variant-' + (config.variant || 'default') + ' ' + (config.cssClass || '')">
4983
+ <div class="table-header">
4984
+ <div class="table-header-left">
4985
+ @if (config.searchable) {
4986
+ <div class="search-box">
4987
+ <svg viewBox="0 0 24 24" class="search-icon"><path [attr.d]="iconRegistry.getIcon('search')"></path></svg>
4988
+ <input type="text" [placeholder]="config.searchPlaceholder || 'Search...'" [ngModel]="searchQuery()" (ngModelChange)="searchQuery.set($event)" />
4989
+ </div>
4990
+ }
4991
+ @for (filter of config.filters || []; track filter.key) {
4992
+ <select class="filter-select" [ngModel]="getFilterValue(filter.key)" (ngModelChange)="setFilterValue(filter.key, $event)">
4993
+ <option value="">{{ filter.label }}</option>
4994
+ @for (opt of filter.options; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
4995
+ </select>
4996
+ }
4997
+ </div>
4998
+ <div class="table-header-right">
4999
+ @for (action of config.headerActions || []; track action.id) {
5000
+ <button class="btn-primary btn-sm" (click)="handleAction(action, null)">
5001
+ @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
5002
+ {{ action.label }}
5003
+ </button>
5004
+ }
5005
+
5006
+ @if (config.exportable) {
5007
+ <div class="export-container">
5008
+ <button class="btn-ghost btn-sm" (click)="exportMenuOpen.set(!exportMenuOpen())">
5009
+ <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon('download')"></path></svg>
5010
+ Export
5011
+ </button>
5012
+ @if (exportMenuOpen()) {
5013
+ <div class="dropdown-menu export-menu">
5014
+ @for (format of config.exportFormats || ['csv', 'json']; track format) {
5015
+ <div class="dropdown-item" (click)="exportData(format); exportMenuOpen.set(false)">
5016
+ Export as {{ format | uppercase }}
5017
+ </div>
5018
+ }
5019
+ </div>
5020
+ }
5021
+ </div>
5022
+ }
5023
+ </div>
5024
+ </div>
5025
+ <div class="table-wrapper">
5026
+ <table class="data-table" [class.striped]="config.striped" [class.hoverable]="config.hoverable !== false">
5027
+ <thead>
5028
+ <tr cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="dropColumn($event)">
5029
+ @if (config.reorderable) { <th class="drag-col" style="width: 40px; text-align: center;"></th> }
5030
+ @if (config.selectionMode === 'checkbox') {
5031
+ <th class="selection-col" style="width: 40px; text-align: center;">
5032
+ @if (config.showSelectAll !== false) {
5033
+ <input type="checkbox"
5034
+ class="amf-checkbox"
5035
+ [checked]="selectedRows().size > 0 && selectedRows().size === filteredData().length"
5036
+ (change)="toggleAllSelection($event)" />
5037
+ }
5038
+ </th>
5039
+ }
5040
+ @if (config.expandable) {
5041
+ <th style="width: 36px;"></th>
5042
+ }
5043
+ @for (col of visibleColumns(); track col.key) {
5044
+ <th cdkDrag [cdkDragDisabled]="!config.columnReorder" [style.width]="col.width" [style.min-width]="col.minWidth" [style.text-align]="col.align || 'left'" [class.sortable]="col.sortable" (click)="col.sortable ? toggleSort(col.key) : null">
5045
+ {{ col.label }} @if (col.sortable && sortKey() === col.key) { <span class="sort-indicator">{{ sortDirection() === 'asc' ? '↑' : '↓' }}</span> }
5046
+ </th>
5047
+ }
5048
+ @if (config.actions?.length) { <th class="actions-col">Actions</th> }
5049
+ </tr>
5050
+ </thead>
5051
+ <tbody cdkDropList (cdkDropListDropped)="dropRow($event)">
5052
+ @for (row of groupedRows(); track $index) {
5053
+ @if (row.__isGroupHeader) {
5054
+ <tr class="group-header-row">
5055
+ <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + (config.expandable ? 1 : 0) + (config.actions?.length ? 1 : 0)">
5056
+ <button class="group-toggle" (click)="toggleGroup(row.__groupKey)">
5057
+ <span class="group-chevron" [class.open]="!collapsedGroups().has(row.__groupKey)">▶</span>
5058
+ {{ config.groupBy }}: <strong>{{ row.__groupKey }}</strong>
5059
+ <span class="group-count">({{ row.__count }} items)</span>
5060
+ </button>
5061
+ </td>
5062
+ </tr>
5063
+ } @else {
5064
+ <tr cdkDrag [cdkDragDisabled]="!config.reorderable" (click)="handleRowClick(row)" [class.clickable]="config.rowClick || config.selectionMode === 'single' || config.selectionMode === 'multi'" [class.selected]="selectedRows().has(row)" [class.expanded]="expandedRows().has(row)">
5065
+ @if (config.reorderable) {
5066
+ <td class="drag-cell" (click)="$event.stopPropagation()" cdkDragHandle>
5067
+ <svg viewBox="0 0 24 24" style="width:16px;height:16px;fill:var(--app-text-muted)"><path [attr.d]="iconRegistry.getIcon('menu')"></path></svg>
5068
+ </td>
5069
+ }
5070
+ @if (config.selectionMode === 'checkbox') {
5071
+ <td class="selection-cell" (click)="$event.stopPropagation(); toggleSelection(row)">
5072
+ <input type="checkbox" class="amf-checkbox" [checked]="selectedRows().has(row)" (click)="$event.stopPropagation()" (change)="$event.stopPropagation(); toggleSelection(row)" />
5073
+ </td>
5074
+ }
5075
+ @if (config.expandable) {
5076
+ <td class="expand-cell" (click)="$event.stopPropagation(); toggleRowExpand(row)">
5077
+ <span class="expand-chevron" [class.open]="expandedRows().has(row)">▶</span>
5078
+ </td>
5079
+ }
5080
+ @for (col of visibleColumns(); track col.key) {
5081
+ <td [style.text-align]="col.align || 'left'" (dblclick)="config.inlineEdit && col.editable !== false ? startEdit(row, col.key, $event) : null" [class.editable-cell]="config.inlineEdit && col.editable !== false">
5082
+ @if (isEditing(row, col.key)) {
5083
+ <div class="inline-edit-wrap" (click)="$event.stopPropagation()">
5084
+ <div class="inline-edit-row">
5085
+ @if (col.editType === 'select' && col.editOptions) {
5086
+ <select class="inline-input" [(ngModel)]="editBuffer[col.key]">
5087
+ @for (opt of col.editOptions; track opt.value) { <option [value]="opt.value">{{ opt.label }}</option> }
5088
+ </select>
5089
+ } @else {
5090
+ <input class="inline-input" [type]="col.editType || 'text'" [(ngModel)]="editBuffer[col.key]" (keydown.enter)="commitEdit(row, col.key)" (keydown.escape)="cancelEdit()" />
5091
+ }
5092
+ <div class="inline-edit-actions">
5093
+ <button class="ie-btn ie-save" title="Save (Enter)" (click)="commitEdit(row, col.key)">
5094
+ <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
5095
+ </button>
5096
+ <button class="ie-btn ie-cancel" title="Cancel (Esc)" (click)="cancelEdit()">
5097
+ <svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
5098
+ </button>
5099
+ </div>
5100
+ </div>
5101
+ @if (editError()) {
5102
+ <span class="inline-edit-error">{{ editError() }}</span>
5103
+ }
5104
+ </div>
5105
+ } @else {
5106
+ <amf-cell-renderer [column]="col" [row]="row" [value]="getCellValue(row, col.key)"></amf-cell-renderer>
5107
+ }
5108
+ </td>
5109
+ }
5110
+ @if (config.actions?.length) {
5111
+ <td class="actions-cell">
5112
+ <div class="action-btns">
5113
+ @for (action of config.actions; track action.id) {
5114
+ <button class="action-btn" [class]="action.variant || 'ghost'" [title]="action.label" (click)="handleAction(action, row); $event.stopPropagation()">
5115
+ @if (action.icon) { <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> } @else { {{ action.label }} }
5116
+ </button>
5117
+ }
5118
+ </div>
5119
+ </td>
5120
+ }
5121
+ </tr>
5122
+ @if (config.expandable && expandedRows().has(row)) {
5123
+ <tr class="expanded-row">
5124
+ <td [attr.colspan]="visibleColumns().length + (config.reorderable ? 1 : 0) + (config.selectionMode === 'checkbox' ? 1 : 0) + 1 + (config.actions?.length ? 1 : 0)" class="expanded-content">
5125
+ @if (config.expandSection) {
5126
+ <div class="expand-section">Row detail: {{ row | json }}</div>
5127
+ } @else {
5128
+ <div class="expand-section">
5129
+ @for (col of visibleColumns(); track col.key) {
5130
+ <div class="expand-field"><span class="expand-label">{{ col.label }}:</span> <span>{{ getCellValue(row, col.key) }}</span></div>
5131
+ }
5132
+ </div>
5133
+ }
5134
+ </td>
5135
+ </tr>
5136
+ }
5137
+ }
5138
+ } @empty { <tr><td [attr.colspan]="visibleColumns().length + (config.actions?.length ? 1 : 0)" class="empty-state">{{ config.emptyMessage || 'No data found.' }}</td></tr> }
5139
+ @if (config.aggregates?.length) {
5140
+ <tr class="aggregate-row">
5141
+ @if (config.reorderable) { <td></td> }
5142
+ @if (config.selectionMode === 'checkbox') { <td></td> }
5143
+ @if (config.expandable) { <td></td> }
5144
+ @for (col of visibleColumns(); track col.key) {
5145
+ <td class="aggregate-cell" [style.text-align]="col.align || 'right'">
5146
+ @if (getAggregate(col.key); as agg) { <span class="agg-value">{{ agg.label ? agg.label + ': ' : '' }}{{ agg.value }}</span> }
5147
+ </td>
5148
+ }
5149
+ @if (config.actions?.length) { <td></td> }
5150
+ </tr>
5151
+ }
5152
+ </tbody>
5153
+ </table>
5154
+ </div>
5155
+ @if (config.pagination?.enabled) {
5156
+ <div class="table-footer">
5157
+ <div class="footer-left">
5158
+ <span class="results-count">Showing {{ paginatedData().length }} of {{ filteredData().length }} @if (config.pagination?.showTotal) { (total: {{ allData().length }}) }</span>
5159
+ @if ((config.pagination?.pageSizeOptions || [5, 10, 25, 50]).length > 1) {
5160
+ <div class="page-size-wrap">
5161
+ <label class="page-size-label">Rows:</label>
5162
+ <select class="page-size-select" [ngModel]="activePageSize()" (ngModelChange)="setPageSize($event)">
5163
+ @for (opt of config.pagination?.pageSizeOptions || [5, 10, 25, 50]; track opt) {
5164
+ <option [value]="opt">{{ opt }}</option>
5165
+ }
5166
+ </select>
5167
+ </div>
5168
+ }
5169
+ </div>
5170
+ <div class="pagination">
5171
+ <button class="btn-page-nav" [disabled]="currentPage() <= 1" (click)="currentPage.set(currentPage() - 1)">Previous</button>
5172
+ @for (p of pageNumbers(); track p) { <button class="btn-page" [class.active]="p === currentPage()" (click)="currentPage.set(p)">{{ p }}</button> }
5173
+ <button class="btn-page-nav" [disabled]="currentPage() >= totalPages()" (click)="currentPage.set(currentPage() + 1)">Next</button>
5174
+ </div>
5175
+ </div>
5176
+ }
5177
+ </div>
5178
5178
  `, styles: [".amf-table-card{background:var(--app-surface);border:1px solid var(--app-border);border-radius:16px;overflow:hidden;box-shadow:0 1px 3px #0000000d}.table-header{padding:16px 20px;display:flex;justify-content:space-between;align-items:center;gap:16px;border-bottom:1px solid var(--app-border);flex-wrap:wrap}.table-header-left,.table-header-right{display:flex;align-items:center;gap:12px}.search-box{position:relative;min-width:240px}.search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:16px;height:16px;fill:var(--app-text-muted)}.search-box input{width:100%;padding:8px 12px 8px 36px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text)}.search-box input:focus{border-color:var(--app-primary)}.filter-select{padding:8px 12px;border:1px solid var(--app-border);border-radius:8px;font-size:.8125rem;outline:none;background:var(--glass-bg);color:var(--app-text);color-scheme:dark}.filter-select option{background-color:#1e1e2d;color:#fff}:host-context([data-color-scheme=\"light\"]) .filter-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .filter-select option{background-color:#fff;color:#000}.table-wrapper{width:100%;overflow-x:auto}.data-table{width:100%;border-collapse:collapse;white-space:normal;word-break:break-word}.data-table th{background:var(--app-bg);padding:10px 20px;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--app-text-muted);border-bottom:1px solid var(--app-border);-webkit-user-select:none;user-select:none}.data-table th.sortable{cursor:pointer}.data-table th.sortable:hover{color:var(--app-primary)}.sort-indicator{margin-left:4px;font-size:.75rem}.data-table td{padding:14px 20px;border-bottom:1px solid var(--app-border);font-size:.875rem;color:var(--app-text)}.data-table.hoverable tbody tr:hover{background:var(--glass-bg)}.data-table.striped tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-striped .data-table tbody tr:nth-child(2n){background:var(--glass-bg)}.variant-borderless{border:none!important;box-shadow:none!important;background:transparent!important}.variant-borderless .table-header{border-bottom:none;padding:0 0 16px}.variant-borderless .data-table th{background:transparent;border-bottom:2px solid var(--app-border)}.variant-borderless .data-table td{border-bottom:1px dashed var(--app-border)}.variant-borderless .table-footer{border-top:none;background:transparent;padding:16px 0 0}.variant-glass{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);box-shadow:var(--glass-shadow-sm)}.variant-glass .table-header,.variant-glass .table-footer,.variant-glass .data-table th{background:transparent;border-color:var(--glass-border)}.variant-glass .data-table td{border-bottom:1px solid var(--glass-border)}.variant-elevated{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-2px);transition:all .3s ease}.variant-compact .table-header{padding:12px 16px}.variant-compact .data-table th{padding:8px 16px;font-size:.625rem}.variant-compact .data-table td{padding:8px 16px;font-size:.8125rem}.variant-compact .table-footer{padding:8px 16px}tr.clickable{cursor:pointer}.amf-checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--app-primary)}.data-table tbody tr.selected{background:#3b82f626!important}.actions-col{text-align:right!important;width:120px}.actions-cell{text-align:right}.action-btns{display:flex;justify-content:flex-end;gap:6px}.action-btn{width:30px;height:30px;border-radius:6px;border:1px solid var(--app-border);background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s}.action-btn svg{width:14px;height:14px;fill:var(--app-text-muted)}.action-btn:hover{border-color:var(--app-primary)}.action-btn:hover svg{fill:var(--app-primary)}.action-btn.danger:hover{border-color:#f43f5e}.action-btn.danger:hover svg{fill:#f43f5e}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 4px 12px var(--app-glow)}.btn-icon{width:16px;height:16px;fill:currentColor}.btn-sm{padding:6px 12px;font-size:.75rem;border-radius:6px}.btn-ghost{background:transparent;border:1px solid var(--app-border);color:var(--app-text);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;display:flex;align-items:center;gap:6px;cursor:pointer;transition:all .2s}.btn-ghost:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.export-container{position:relative}.export-menu{position:absolute;top:calc(100% + 8px);right:0;background:var(--app-surface);border:1px solid var(--app-border);border-radius:12px;box-shadow:0 10px 40px #00000080;min-width:160px;z-index:100;overflow:hidden;animation:slideInDown .2s ease-out backwards}.export-menu .dropdown-item{padding:10px 16px;font-size:.8125rem;font-weight:500;cursor:pointer;color:var(--app-text);transition:background .2s}.export-menu .dropdown-item:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.empty-state{text-align:center;padding:40px!important;color:var(--app-text-muted)}.table-footer{padding:12px 20px;display:flex;justify-content:space-between;align-items:center;background:var(--app-bg);border-top:1px solid var(--app-border)}.footer-left{display:flex;align-items:center;gap:16px}.results-count{font-size:.75rem;color:var(--app-text-muted)}.page-size-wrap{display:flex;align-items:center;gap:6px}.page-size-label{font-size:.75rem;color:var(--app-text-muted);white-space:nowrap}.page-size-select{padding:4px 8px;border:1px solid var(--app-border);border-radius:6px;font-size:.75rem;background:var(--glass-bg);color:var(--app-text);outline:none;cursor:pointer;color-scheme:dark}.page-size-select option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) .page-size-select{color-scheme:light}:host-context([data-color-scheme=\"light\"]) .page-size-select option{background-color:#fff;color:#000}.pagination{display:flex;gap:4px}.btn-page,.btn-page-nav{padding:6px 10px;border:1px solid var(--app-border);background:transparent;border-radius:6px;font-size:.75rem;font-weight:500;color:var(--app-text);cursor:pointer}.btn-page.active{background:var(--app-primary);border-color:var(--app-primary);color:#fff}.btn-page-nav:disabled{opacity:.4;cursor:not-allowed}.editable-cell{position:relative}.editable-cell:hover{background:#3b82f614;cursor:text}.inline-edit-wrap{display:flex;flex-direction:column;gap:4px;min-width:0}.inline-edit-row{display:flex;align-items:center;gap:4px}.inline-input{flex:1;min-width:0;padding:5px 8px;border:1.5px solid var(--app-primary);border-radius:6px;background:var(--app-surface);color:var(--app-text);font-size:.875rem;outline:none}.inline-input.input-invalid{border-color:#f43f5e}.inline-edit-error{font-size:.6875rem;color:#f43f5e;font-weight:500;padding:0 2px;animation:fadeIn .15s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.inline-edit-actions{display:flex;gap:3px;flex-shrink:0}.ie-btn{width:26px;height:26px;border-radius:5px;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s}.ie-btn svg{width:14px;height:14px;fill:currentColor}.ie-btn:hover{opacity:.85}.ie-save{background:#22c55e;color:#fff}.ie-cancel{background:var(--app-border);color:var(--app-text-muted)}select.inline-input{color-scheme:dark;cursor:pointer}select.inline-input option{background-color:#1a1a2e;color:#fff}:host-context([data-color-scheme=\"light\"]) select.inline-input{color-scheme:light}:host-context([data-color-scheme=\"light\"]) select.inline-input option{background-color:#fff;color:#000}.expand-cell{width:36px;text-align:center;cursor:pointer}.expand-chevron{display:inline-block;transition:transform .2s;font-size:.625rem;color:var(--app-text-muted)}.expand-chevron.open{transform:rotate(90deg)}.expanded-row td,.expanded-content{padding:0!important}.expand-section{padding:14px 24px;display:flex;flex-wrap:wrap;gap:16px;background:var(--glass-bg);animation:fadeInUp .2s ease-out}.expand-field{display:flex;gap:8px;font-size:.8125rem}.expand-label{color:var(--app-text-muted);font-weight:600}.group-header-row td{background:var(--app-bg)}.group-toggle{display:flex;align-items:center;gap:8px;background:none;border:none;color:var(--app-text);cursor:pointer;font-size:.8125rem;padding:8px 16px}.group-chevron{display:inline-block;font-size:.625rem;transition:transform .2s;color:var(--app-text-muted)}.group-chevron.open{transform:rotate(90deg)}.group-count{color:var(--app-text-muted);font-size:.75rem}.aggregate-row td{background:var(--app-bg);border-top:2px solid var(--app-border)}.aggregate-cell{padding:10px 20px!important}.agg-value{font-size:.8125rem;font-weight:700;color:var(--app-primary)}\n"] }]
5179
5179
  }], propDecorators: { config: [{
5180
5180
  type: Input
@@ -5195,45 +5195,45 @@ class CardSectionComponent {
5195
5195
  get trustedContent() {
5196
5196
  return this.sanitizer.bypassSecurityTrustHtml(this.config.content || '');
5197
5197
  }
5198
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CardSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5199
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: CardSectionComponent, isStandalone: true, selector: "amf-card", inputs: { config: "config", context: "context" }, ngImport: i0, template: `
5200
- <div class="amf-card" [class]="'variant-' + (config.variant || 'glass')">
5201
- @if (config.title) { <h2 class="card-title">{{ config.title }}</h2> }
5202
- @if (config.content) { <div class="card-content" [innerHTML]="trustedContent"></div> }
5203
- @if (config.sections?.length) {
5204
- <div class="card-sections">
5205
- @for (nested of config.sections; track nested.id) {
5206
- <amf-renderer [section]="nested" [context]="context" class="card-nested-section"></amf-renderer>
5207
- }
5208
- </div>
5209
- }
5210
- @if (config.actions?.length) {
5211
- <div class="card-actions">
5212
- @for (action of config.actions; track action.label) { <button [class]="'btn-' + (action.variant || 'secondary')" (click)="actionDispatcher.dispatch(action.action, context)">{{ action.label }}</button> }
5213
- </div>
5214
- }
5215
- </div>
5198
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CardSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5199
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: CardSectionComponent, isStandalone: true, selector: "amf-card", inputs: { config: "config", context: "context" }, ngImport: i0, template: `
5200
+ <div class="amf-card" [class]="'variant-' + (config.variant || 'glass')">
5201
+ @if (config.title) { <h2 class="card-title">{{ config.title }}</h2> }
5202
+ @if (config.content) { <div class="card-content" [innerHTML]="trustedContent"></div> }
5203
+ @if (config.sections?.length) {
5204
+ <div class="card-sections">
5205
+ @for (nested of config.sections; track nested.id) {
5206
+ <amf-renderer [section]="nested" [context]="context" class="card-nested-section"></amf-renderer>
5207
+ }
5208
+ </div>
5209
+ }
5210
+ @if (config.actions?.length) {
5211
+ <div class="card-actions">
5212
+ @for (action of config.actions; track action.label) { <button [class]="'btn-' + (action.variant || 'secondary')" (click)="actionDispatcher.dispatch(action.action, context)">{{ action.label }}</button> }
5213
+ </div>
5214
+ }
5215
+ </div>
5216
5216
  `, isInline: true, styles: [".amf-card{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);border-radius:16px;padding:24px;box-shadow:var(--glass-shadow-sm);transition:all .3s cubic-bezier(.4,0,.2,1)}.amf-card:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light);box-shadow:var(--glass-shadow);transform:translateY(-2px)}.variant-default{background:var(--app-surface);border:1px solid var(--app-border);backdrop-filter:none;-webkit-backdrop-filter:none}.variant-outlined{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.variant-elevated{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-4px)}.variant-gradient{background:linear-gradient(135deg,#3b82f626,#8b5cf626);border:1px solid rgba(139,92,246,.3)}.card-title{font-size:1.25rem;margin-bottom:16px}.card-content{color:var(--app-text-muted);font-size:.9375rem;line-height:1.6}.card-sections{display:flex;flex-direction:column;gap:16px;margin-top:16px}.card-nested-section{display:block}.card-actions{margin-top:20px;display:flex;gap:12px}.btn-secondary{background:var(--glass-bg);border:1px solid var(--app-border);color:var(--app-text);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover)}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 4px 12px var(--app-glow)}.btn-danger{background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-danger:hover{transform:translateY(-1px);box-shadow:0 4px 12px #ef444466}.btn-success{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-success:hover{transform:translateY(-1px);box-shadow:0 4px 12px #10b98166}.btn-ghost{background:transparent;border:1px solid transparent;color:var(--app-text-muted);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-ghost:hover{background:#ffffff0d;color:var(--app-text)}\n"], dependencies: [{ kind: "component", type: MetaRendererComponent, selector: "amf-renderer", inputs: ["section", "context"] }] });
5217
5217
  }
5218
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CardSectionComponent, decorators: [{
5218
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CardSectionComponent, decorators: [{
5219
5219
  type: Component,
5220
- args: [{ selector: 'amf-card', standalone: true, imports: [MetaRendererComponent], template: `
5221
- <div class="amf-card" [class]="'variant-' + (config.variant || 'glass')">
5222
- @if (config.title) { <h2 class="card-title">{{ config.title }}</h2> }
5223
- @if (config.content) { <div class="card-content" [innerHTML]="trustedContent"></div> }
5224
- @if (config.sections?.length) {
5225
- <div class="card-sections">
5226
- @for (nested of config.sections; track nested.id) {
5227
- <amf-renderer [section]="nested" [context]="context" class="card-nested-section"></amf-renderer>
5228
- }
5229
- </div>
5230
- }
5231
- @if (config.actions?.length) {
5232
- <div class="card-actions">
5233
- @for (action of config.actions; track action.label) { <button [class]="'btn-' + (action.variant || 'secondary')" (click)="actionDispatcher.dispatch(action.action, context)">{{ action.label }}</button> }
5234
- </div>
5235
- }
5236
- </div>
5220
+ args: [{ selector: 'amf-card', standalone: true, imports: [MetaRendererComponent], template: `
5221
+ <div class="amf-card" [class]="'variant-' + (config.variant || 'glass')">
5222
+ @if (config.title) { <h2 class="card-title">{{ config.title }}</h2> }
5223
+ @if (config.content) { <div class="card-content" [innerHTML]="trustedContent"></div> }
5224
+ @if (config.sections?.length) {
5225
+ <div class="card-sections">
5226
+ @for (nested of config.sections; track nested.id) {
5227
+ <amf-renderer [section]="nested" [context]="context" class="card-nested-section"></amf-renderer>
5228
+ }
5229
+ </div>
5230
+ }
5231
+ @if (config.actions?.length) {
5232
+ <div class="card-actions">
5233
+ @for (action of config.actions; track action.label) { <button [class]="'btn-' + (action.variant || 'secondary')" (click)="actionDispatcher.dispatch(action.action, context)">{{ action.label }}</button> }
5234
+ </div>
5235
+ }
5236
+ </div>
5237
5237
  `, styles: [".amf-card{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);border-radius:16px;padding:24px;box-shadow:var(--glass-shadow-sm);transition:all .3s cubic-bezier(.4,0,.2,1)}.amf-card:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light);box-shadow:var(--glass-shadow);transform:translateY(-2px)}.variant-default{background:var(--app-surface);border:1px solid var(--app-border);backdrop-filter:none;-webkit-backdrop-filter:none}.variant-outlined{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.variant-elevated{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-4px)}.variant-gradient{background:linear-gradient(135deg,#3b82f626,#8b5cf626);border:1px solid rgba(139,92,246,.3)}.card-title{font-size:1.25rem;margin-bottom:16px}.card-content{color:var(--app-text-muted);font-size:.9375rem;line-height:1.6}.card-sections{display:flex;flex-direction:column;gap:16px;margin-top:16px}.card-nested-section{display:block}.card-actions{margin-top:20px;display:flex;gap:12px}.btn-secondary{background:var(--glass-bg);border:1px solid var(--app-border);color:var(--app-text);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover)}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 4px 12px var(--app-glow)}.btn-danger{background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-danger:hover{transform:translateY(-1px);box-shadow:0 4px 12px #ef444466}.btn-success{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border:none;padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-success:hover{transform:translateY(-1px);box-shadow:0 4px 12px #10b98166}.btn-ghost{background:transparent;border:1px solid transparent;color:var(--app-text-muted);padding:8px 16px;border-radius:8px;font-weight:600;font-size:.8125rem;cursor:pointer;transition:all .2s}.btn-ghost:hover{background:#ffffff0d;color:var(--app-text)}\n"] }]
5238
5238
  }], propDecorators: { config: [{
5239
5239
  type: Input
@@ -5249,47 +5249,47 @@ class StatsGridSectionComponent {
5249
5249
  context = {};
5250
5250
  iconRegistry = inject(IconRegistryService);
5251
5251
  get gridCols() { return `repeat(auto-fit, minmax(280px, 1fr))`; }
5252
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: StatsGridSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5253
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: StatsGridSectionComponent, isStandalone: true, selector: "amf-stats-grid", inputs: { config: "config", context: "context" }, ngImport: i0, template: `
5254
- <div class="amf-stats-grid" [style.grid-template-columns]="gridCols" [class]="'variant-' + (config.variant || 'glass')">
5255
- @for (stat of config.stats; track stat.label; let i = $index) {
5256
- <div class="stat-card" [style.animation-delay]="(i * 0.1) + 's'">
5257
- <div class="stat-glow" [style.background]="stat.glowColor || stat.color"></div>
5258
- @if (stat.icon) {
5259
- <div class="stat-icon" [style.color]="stat.color" [style.background]="stat.bgColor">
5260
- <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(stat.icon)"></path></svg>
5261
- </div>
5262
- }
5263
- <div class="stat-data">
5264
- <span class="stat-label">{{ stat.label }}</span>
5265
- <span class="stat-value">{{ stat.value }}</span>
5266
- @if (stat.trend) { <span class="stat-trend" [class.positive]="stat.trendPositive" [class.negative]="!stat.trendPositive">{{ stat.trend }}</span> }
5267
- </div>
5268
- </div>
5269
- }
5270
- </div>
5252
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: StatsGridSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5253
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: StatsGridSectionComponent, isStandalone: true, selector: "amf-stats-grid", inputs: { config: "config", context: "context" }, ngImport: i0, template: `
5254
+ <div class="amf-stats-grid" [style.grid-template-columns]="gridCols" [class]="'variant-' + (config.variant || 'glass')">
5255
+ @for (stat of config.stats; track stat.label; let i = $index) {
5256
+ <div class="stat-card" [style.animation-delay]="(i * 0.1) + 's'">
5257
+ <div class="stat-glow" [style.background]="stat.glowColor || stat.color"></div>
5258
+ @if (stat.icon) {
5259
+ <div class="stat-icon" [style.color]="stat.color" [style.background]="stat.bgColor">
5260
+ <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(stat.icon)"></path></svg>
5261
+ </div>
5262
+ }
5263
+ <div class="stat-data">
5264
+ <span class="stat-label">{{ stat.label }}</span>
5265
+ <span class="stat-value">{{ stat.value }}</span>
5266
+ @if (stat.trend) { <span class="stat-trend" [class.positive]="stat.trendPositive" [class.negative]="!stat.trendPositive">{{ stat.trend }}</span> }
5267
+ </div>
5268
+ </div>
5269
+ }
5270
+ </div>
5271
5271
  `, isInline: true, styles: [".amf-stats-grid{display:grid;gap:20px}.stat-card{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);border-radius:16px;padding:24px;display:flex;align-items:center;gap:20px;position:relative;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);animation:fadeInUp .5s ease-out backwards}.stat-card:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light);transform:translateY(-4px);box-shadow:var(--glass-shadow)}.variant-default .stat-card{background:var(--app-surface);border:1px solid var(--app-border);backdrop-filter:none;-webkit-backdrop-filter:none}.variant-compact .stat-card{padding:14px 16px;gap:14px;min-height:80px}.variant-compact .stat-icon{width:38px;height:38px;border-radius:10px}.variant-compact .stat-icon svg{width:18px;height:18px}.variant-compact .stat-value{font-size:1.25rem;font-weight:800}.variant-compact .stat-glow{width:60px;height:60px;top:-10px;right:-10px}.variant-outlined .stat-card{background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none}.variant-elevated .stat-card{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-2px);border-color:var(--glass-border-light)}.stat-glow{position:absolute;width:100px;height:100px;border-radius:50%;filter:blur(40px);opacity:.15;top:-20px;right:-20px;pointer-events:none;transition:opacity .3s}.stat-card:hover .stat-glow{opacity:.3}.stat-icon{width:52px;height:52px;border-radius:14px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.stat-icon svg{width:26px;height:26px;fill:currentColor}.stat-data{display:flex;flex-direction:column}.stat-label{font-size:.8125rem;color:var(--app-text-muted);font-weight:500}.stat-value{font-size:1.5rem;font-weight:700;color:var(--app-text);margin:2px 0}.stat-trend{font-size:.75rem;font-weight:600}.stat-trend.positive{color:#34d399}.stat-trend.negative{color:#fb7185}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}\n"] });
5272
5272
  }
5273
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: StatsGridSectionComponent, decorators: [{
5273
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: StatsGridSectionComponent, decorators: [{
5274
5274
  type: Component,
5275
- args: [{ selector: 'amf-stats-grid', standalone: true, imports: [], template: `
5276
- <div class="amf-stats-grid" [style.grid-template-columns]="gridCols" [class]="'variant-' + (config.variant || 'glass')">
5277
- @for (stat of config.stats; track stat.label; let i = $index) {
5278
- <div class="stat-card" [style.animation-delay]="(i * 0.1) + 's'">
5279
- <div class="stat-glow" [style.background]="stat.glowColor || stat.color"></div>
5280
- @if (stat.icon) {
5281
- <div class="stat-icon" [style.color]="stat.color" [style.background]="stat.bgColor">
5282
- <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(stat.icon)"></path></svg>
5283
- </div>
5284
- }
5285
- <div class="stat-data">
5286
- <span class="stat-label">{{ stat.label }}</span>
5287
- <span class="stat-value">{{ stat.value }}</span>
5288
- @if (stat.trend) { <span class="stat-trend" [class.positive]="stat.trendPositive" [class.negative]="!stat.trendPositive">{{ stat.trend }}</span> }
5289
- </div>
5290
- </div>
5291
- }
5292
- </div>
5275
+ args: [{ selector: 'amf-stats-grid', standalone: true, imports: [], template: `
5276
+ <div class="amf-stats-grid" [style.grid-template-columns]="gridCols" [class]="'variant-' + (config.variant || 'glass')">
5277
+ @for (stat of config.stats; track stat.label; let i = $index) {
5278
+ <div class="stat-card" [style.animation-delay]="(i * 0.1) + 's'">
5279
+ <div class="stat-glow" [style.background]="stat.glowColor || stat.color"></div>
5280
+ @if (stat.icon) {
5281
+ <div class="stat-icon" [style.color]="stat.color" [style.background]="stat.bgColor">
5282
+ <svg viewBox="0 0 24 24"><path [attr.d]="iconRegistry.getIcon(stat.icon)"></path></svg>
5283
+ </div>
5284
+ }
5285
+ <div class="stat-data">
5286
+ <span class="stat-label">{{ stat.label }}</span>
5287
+ <span class="stat-value">{{ stat.value }}</span>
5288
+ @if (stat.trend) { <span class="stat-trend" [class.positive]="stat.trendPositive" [class.negative]="!stat.trendPositive">{{ stat.trend }}</span> }
5289
+ </div>
5290
+ </div>
5291
+ }
5292
+ </div>
5293
5293
  `, styles: [".amf-stats-grid{display:grid;gap:20px}.stat-card{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);border-radius:16px;padding:24px;display:flex;align-items:center;gap:20px;position:relative;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);animation:fadeInUp .5s ease-out backwards}.stat-card:hover{background:var(--glass-bg-hover);border-color:var(--glass-border-light);transform:translateY(-4px);box-shadow:var(--glass-shadow)}.variant-default .stat-card{background:var(--app-surface);border:1px solid var(--app-border);backdrop-filter:none;-webkit-backdrop-filter:none}.variant-compact .stat-card{padding:14px 16px;gap:14px;min-height:80px}.variant-compact .stat-icon{width:38px;height:38px;border-radius:10px}.variant-compact .stat-icon svg{width:18px;height:18px}.variant-compact .stat-value{font-size:1.25rem;font-weight:800}.variant-compact .stat-glow{width:60px;height:60px;top:-10px;right:-10px}.variant-outlined .stat-card{background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none}.variant-elevated .stat-card{box-shadow:0 20px 40px var(--glass-shadow);transform:translateY(-2px);border-color:var(--glass-border-light)}.stat-glow{position:absolute;width:100px;height:100px;border-radius:50%;filter:blur(40px);opacity:.15;top:-20px;right:-20px;pointer-events:none;transition:opacity .3s}.stat-card:hover .stat-glow{opacity:.3}.stat-icon{width:52px;height:52px;border-radius:14px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.stat-icon svg{width:26px;height:26px;fill:currentColor}.stat-data{display:flex;flex-direction:column}.stat-label{font-size:.8125rem;color:var(--app-text-muted);font-weight:500}.stat-value{font-size:1.5rem;font-weight:700;color:var(--app-text);margin:2px 0}.stat-trend{font-size:.75rem;font-weight:600}.stat-trend.positive{color:#34d399}.stat-trend.negative{color:#fb7185}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}\n"] }]
5294
5294
  }], propDecorators: { config: [{
5295
5295
  type: Input
@@ -5313,41 +5313,41 @@ class PageHeaderSectionComponent {
5313
5313
  }
5314
5314
  return this.config.title;
5315
5315
  }
5316
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PageHeaderSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5317
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PageHeaderSectionComponent, isStandalone: true, selector: "amf-page-header", inputs: { config: "config", context: "context" }, ngImport: i0, template: `
5318
- <header class="amf-page-header">
5319
- <div class="header-content">
5320
- <h1>{{ resolvedTitle }}</h1>
5321
- @if (config.subtitle) { <p>{{ config.subtitle }}</p> }
5322
- </div>
5323
- <div class="header-actions">
5324
- @for (action of config.actions || []; track action.label) {
5325
- <button [class]="'btn-' + (action.variant || 'primary')" (click)="actionDispatcher.dispatch(action.action, context)">
5326
- @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
5327
- {{ action.label }}
5328
- </button>
5329
- }
5330
- </div>
5331
- </header>
5316
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PageHeaderSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5317
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: PageHeaderSectionComponent, isStandalone: true, selector: "amf-page-header", inputs: { config: "config", context: "context" }, ngImport: i0, template: `
5318
+ <header class="amf-page-header">
5319
+ <div class="header-content">
5320
+ <h1>{{ resolvedTitle }}</h1>
5321
+ @if (config.subtitle) { <p>{{ config.subtitle }}</p> }
5322
+ </div>
5323
+ <div class="header-actions">
5324
+ @for (action of config.actions || []; track action.label) {
5325
+ <button [class]="'btn-' + (action.variant || 'primary')" (click)="actionDispatcher.dispatch(action.action, context)">
5326
+ @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
5327
+ {{ action.label }}
5328
+ </button>
5329
+ }
5330
+ </div>
5331
+ </header>
5332
5332
  `, isInline: true, styles: [".amf-page-header{display:flex;justify-content:space-between;align-items:center;animation:fadeInUp .4s ease-out}.header-content h1{font-size:1.875rem;margin-bottom:4px}.header-content p{color:var(--app-text-muted);font-size:.9375rem}.header-actions{display:flex;gap:12px}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:10px 20px;border-radius:10px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all .3s}.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-secondary{background:var(--glass-bg);border:1px solid var(--app-border);color:var(--app-text);padding:10px 20px;border-radius:10px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover)}.btn-ghost{background:transparent;border:none;color:var(--app-text-muted);padding:10px 20px;border-radius:10px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all .2s}.btn-ghost:hover{color:var(--app-primary);background:var(--glass-bg)}.btn-icon{width:18px;height:18px;fill:currentColor}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}\n"] });
5333
5333
  }
5334
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PageHeaderSectionComponent, decorators: [{
5334
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: PageHeaderSectionComponent, decorators: [{
5335
5335
  type: Component,
5336
- args: [{ selector: 'amf-page-header', standalone: true, imports: [], template: `
5337
- <header class="amf-page-header">
5338
- <div class="header-content">
5339
- <h1>{{ resolvedTitle }}</h1>
5340
- @if (config.subtitle) { <p>{{ config.subtitle }}</p> }
5341
- </div>
5342
- <div class="header-actions">
5343
- @for (action of config.actions || []; track action.label) {
5344
- <button [class]="'btn-' + (action.variant || 'primary')" (click)="actionDispatcher.dispatch(action.action, context)">
5345
- @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
5346
- {{ action.label }}
5347
- </button>
5348
- }
5349
- </div>
5350
- </header>
5336
+ args: [{ selector: 'amf-page-header', standalone: true, imports: [], template: `
5337
+ <header class="amf-page-header">
5338
+ <div class="header-content">
5339
+ <h1>{{ resolvedTitle }}</h1>
5340
+ @if (config.subtitle) { <p>{{ config.subtitle }}</p> }
5341
+ </div>
5342
+ <div class="header-actions">
5343
+ @for (action of config.actions || []; track action.label) {
5344
+ <button [class]="'btn-' + (action.variant || 'primary')" (click)="actionDispatcher.dispatch(action.action, context)">
5345
+ @if (action.icon) { <svg viewBox="0 0 24 24" class="btn-icon"><path [attr.d]="iconRegistry.getIcon(action.icon)"></path></svg> }
5346
+ {{ action.label }}
5347
+ </button>
5348
+ }
5349
+ </div>
5350
+ </header>
5351
5351
  `, styles: [".amf-page-header{display:flex;justify-content:space-between;align-items:center;animation:fadeInUp .4s ease-out}.header-content h1{font-size:1.875rem;margin-bottom:4px}.header-content p{color:var(--app-text-muted);font-size:.9375rem}.header-actions{display:flex;gap:12px}.btn-primary{background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;border:none;padding:10px 20px;border-radius:10px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all .3s}.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 24px -4px var(--app-glow)}.btn-secondary{background:var(--glass-bg);border:1px solid var(--app-border);color:var(--app-text);padding:10px 20px;border-radius:10px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all .2s}.btn-secondary:hover{background:var(--glass-bg-hover)}.btn-ghost{background:transparent;border:none;color:var(--app-text-muted);padding:10px 20px;border-radius:10px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;transition:all .2s}.btn-ghost:hover{color:var(--app-primary);background:var(--glass-bg)}.btn-icon{width:18px;height:18px;fill:currentColor}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}\n"] }]
5352
5352
  }], propDecorators: { config: [{
5353
5353
  type: Input
@@ -5361,10 +5361,10 @@ class NavigationService {
5361
5361
  setMenuItems(groups) {
5362
5362
  this.menuItems.set(groups);
5363
5363
  }
5364
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5365
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavigationService, providedIn: 'root' });
5364
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5365
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavigationService, providedIn: 'root' });
5366
5366
  }
5367
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavigationService, decorators: [{
5367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavigationService, decorators: [{
5368
5368
  type: Injectable,
5369
5369
  args: [{ providedIn: 'root' }]
5370
5370
  }] });
@@ -5531,10 +5531,10 @@ class AppConfigService {
5531
5531
  html.setAttribute('data-color-scheme', 'light');
5532
5532
  }
5533
5533
  }
5534
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AppConfigService, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
5535
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AppConfigService, providedIn: 'root' });
5534
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
5535
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, providedIn: 'root' });
5536
5536
  }
5537
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AppConfigService, decorators: [{
5537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AppConfigService, decorators: [{
5538
5538
  type: Injectable,
5539
5539
  args: [{ providedIn: 'root' }]
5540
5540
  }], ctorParameters: () => [{ type: i1.Router }] });
@@ -5770,10 +5770,10 @@ class ThemeService {
5770
5770
  const next = themes[(idx + 1) % themes.length];
5771
5771
  this.setTheme(next.name);
5772
5772
  }
5773
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5774
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
5773
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5774
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeService, providedIn: 'root' });
5775
5775
  }
5776
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ThemeService, decorators: [{
5776
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ThemeService, decorators: [{
5777
5777
  type: Injectable,
5778
5778
  args: [{ providedIn: 'root' }]
5779
5779
  }], ctorParameters: () => [] });
@@ -5793,141 +5793,141 @@ class SidebarComponent {
5793
5793
  }
5794
5794
  }
5795
5795
  }
5796
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5797
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: SidebarComponent, isStandalone: true, selector: "app-sidebar", ngImport: i0, template: `
5798
- <div class="sidebar-container" [class.collapsed]="config.sidebarCollapsed()">
5799
- <div class="sidebar-header">
5800
- <div class="logo">
5801
- <div class="logo-glow">
5802
- <svg viewBox="0 0 24 24" class="logo-icon">
5803
- <path [attr.d]="iconRegistry.getIcon('dashboard')"></path>
5804
- </svg>
5805
- </div>
5806
- <span class="logo-text">{{ config.appName() }}</span>
5807
- </div>
5808
- </div>
5809
-
5810
- <nav class="sidebar-nav">
5811
- @for (group of navigation.menuItems(); track group.label) {
5812
- <div class="nav-group">
5813
- <h3 class="group-title">{{ group.label }}</h3>
5814
- <ul>
5815
- <ng-container *ngTemplateOutlet="menuList; context: { $implicit: group.items }"></ng-container>
5816
- </ul>
5817
- </div>
5818
- }
5819
- </nav>
5820
-
5821
- <ng-template #menuList let-listItems>
5822
- @for (node of listItems; track node.label) {
5823
- <li class="nav-item-wrapper">
5824
- <div
5825
- class="nav-item"
5826
- [routerLink]="node.route ? node.route : null"
5827
- routerLinkActive="active"
5828
- [class.has-children]="node.children?.length"
5829
- (click)="toggleExpand(node)"
5830
- >
5831
- <div class="nav-link-content">
5832
- @if (node.icon) {
5833
- <svg viewBox="0 0 24 24" class="nav-icon">
5834
- <path [attr.d]="iconRegistry.getIcon(node.icon)"></path>
5835
- </svg>
5836
- }
5837
- <span class="nav-label">{{ node.label }}</span>
5838
- </div>
5839
-
5840
- @if (node.badge) {
5841
- <span class="badge" [style.background]="'linear-gradient(135deg, ' + node.badgeColor + ', ' + node.badgeColor + '88)'">
5842
- {{ node.badge }}
5843
- </span>
5844
- }
5845
-
5846
- @if (node.children?.length) {
5847
- <svg viewBox="0 0 24 24" class="chevron" [class.rotated]="expandedItems.has(node)">
5848
- <path [attr.d]="iconRegistry.getIcon('chevron-right')"></path>
5849
- </svg>
5850
- }
5851
- </div>
5852
-
5853
- @if (node.children?.length && expandedItems.has(node)) {
5854
- <ul class="sub-menu">
5855
- <ng-container *ngTemplateOutlet="menuList; context: { $implicit: node.children }"></ng-container>
5856
- </ul>
5857
- }
5858
- </li>
5859
- }
5860
- </ng-template>
5861
- </div>
5796
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5797
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SidebarComponent, isStandalone: true, selector: "app-sidebar", ngImport: i0, template: `
5798
+ <div class="sidebar-container" [class.collapsed]="config.sidebarCollapsed()">
5799
+ <div class="sidebar-header">
5800
+ <div class="logo">
5801
+ <div class="logo-glow">
5802
+ <svg viewBox="0 0 24 24" class="logo-icon">
5803
+ <path [attr.d]="iconRegistry.getIcon('dashboard')"></path>
5804
+ </svg>
5805
+ </div>
5806
+ <span class="logo-text">{{ config.appName() }}</span>
5807
+ </div>
5808
+ </div>
5809
+
5810
+ <nav class="sidebar-nav">
5811
+ @for (group of navigation.menuItems(); track group.label) {
5812
+ <div class="nav-group">
5813
+ <h3 class="group-title">{{ group.label }}</h3>
5814
+ <ul>
5815
+ <ng-container *ngTemplateOutlet="menuList; context: { $implicit: group.items }"></ng-container>
5816
+ </ul>
5817
+ </div>
5818
+ }
5819
+ </nav>
5820
+
5821
+ <ng-template #menuList let-listItems>
5822
+ @for (node of listItems; track node.label) {
5823
+ <li class="nav-item-wrapper">
5824
+ <div
5825
+ class="nav-item"
5826
+ [routerLink]="node.route ? node.route : null"
5827
+ routerLinkActive="active"
5828
+ [class.has-children]="node.children?.length"
5829
+ (click)="toggleExpand(node)"
5830
+ >
5831
+ <div class="nav-link-content">
5832
+ @if (node.icon) {
5833
+ <svg viewBox="0 0 24 24" class="nav-icon">
5834
+ <path [attr.d]="iconRegistry.getIcon(node.icon)"></path>
5835
+ </svg>
5836
+ }
5837
+ <span class="nav-label">{{ node.label }}</span>
5838
+ </div>
5839
+
5840
+ @if (node.badge) {
5841
+ <span class="badge" [style.background]="'linear-gradient(135deg, ' + node.badgeColor + ', ' + node.badgeColor + '88)'">
5842
+ {{ node.badge }}
5843
+ </span>
5844
+ }
5845
+
5846
+ @if (node.children?.length) {
5847
+ <svg viewBox="0 0 24 24" class="chevron" [class.rotated]="expandedItems.has(node)">
5848
+ <path [attr.d]="iconRegistry.getIcon('chevron-right')"></path>
5849
+ </svg>
5850
+ }
5851
+ </div>
5852
+
5853
+ @if (node.children?.length && expandedItems.has(node)) {
5854
+ <ul class="sub-menu">
5855
+ <ng-container *ngTemplateOutlet="menuList; context: { $implicit: node.children }"></ng-container>
5856
+ </ul>
5857
+ }
5858
+ </li>
5859
+ }
5860
+ </ng-template>
5861
+ </div>
5862
5862
  `, isInline: true, styles: [":host{display:block;height:100%}.sidebar-container{width:var(--sidebar-width, 260px);height:100%;background:var(--app-sidebar-bg);backdrop-filter:blur(var(--glass-blur-heavy));-webkit-backdrop-filter:blur(var(--glass-blur-heavy));border-right:1px solid var(--glass-border);display:flex;flex-direction:column;transition:width var(--transition-smooth);overflow:hidden;position:relative}.sidebar-container:after{content:\"\";position:absolute;top:0;right:0;width:1px;height:100%;background:linear-gradient(to bottom,transparent,var(--app-primary-light),transparent);pointer-events:none}.sidebar-container.collapsed{width:80px}.sidebar-header{height:68px;display:flex;align-items:center;padding:0 20px;border-bottom:1px solid var(--glass-border)}.logo{display:flex;align-items:center;gap:12px;font-weight:700;font-size:1.25rem;color:var(--app-text);white-space:nowrap}.logo-glow{width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));display:flex;align-items:center;justify-content:center;box-shadow:0 0 20px var(--app-glow);animation:pulseGlow 4s ease-in-out infinite;flex-shrink:0}.logo-icon{width:20px;height:20px;fill:#fff}.sidebar-container.collapsed .logo-text{display:none}.sidebar-nav{flex:1;overflow-y:auto;padding:16px 0}.nav-group{margin-top:28px}.nav-group:first-child{margin-top:0}.group-title{font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--app-text-muted);padding:0 24px 8px;opacity:.6}.sidebar-container.collapsed .group-title{display:none}ul{list-style:none;padding:0;margin:0}.nav-item-wrapper{margin-bottom:2px;padding:0 10px}.nav-item{display:flex;align-items:center;justify-content:space-between;height:44px;padding:0 14px;border-radius:10px;color:var(--app-sidebar-text);cursor:pointer;transition:all var(--transition-smooth);text-decoration:none;position:relative}.nav-item:hover{background:var(--glass-bg-hover);color:var(--app-text)}.nav-item.active{background:linear-gradient(135deg,var(--app-primary-light),var(--app-accent-light));color:var(--app-primary);box-shadow:0 0 20px var(--app-glow)}.nav-item.active:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:20px;border-radius:0 3px 3px 0;background:linear-gradient(to bottom,var(--app-primary),var(--app-accent))}.nav-item.active .nav-icon{filter:drop-shadow(0 0 6px var(--app-glow))}.nav-link-content{display:flex;align-items:center;gap:12px}.nav-icon{width:20px;height:20px;fill:currentColor;flex-shrink:0;transition:all var(--transition-fast)}.sidebar-container.collapsed .nav-label,.sidebar-container.collapsed .chevron,.sidebar-container.collapsed .badge{display:none}.chevron{width:16px;height:16px;fill:currentColor;transition:transform var(--transition-smooth);opacity:.5}.chevron.rotated{transform:rotate(90deg)}.badge{font-size:10px;padding:2px 8px;border-radius:10px;color:#fff;font-weight:600;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.sub-menu{padding-left:24px;margin-top:4px;animation:fadeInUp .2s ease-out}.sidebar-container.collapsed .sub-menu{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
5863
5863
  }
5864
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SidebarComponent, decorators: [{
5864
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarComponent, decorators: [{
5865
5865
  type: Component,
5866
- args: [{ selector: 'app-sidebar', standalone: true, imports: [CommonModule, RouterLink, RouterLinkActive], template: `
5867
- <div class="sidebar-container" [class.collapsed]="config.sidebarCollapsed()">
5868
- <div class="sidebar-header">
5869
- <div class="logo">
5870
- <div class="logo-glow">
5871
- <svg viewBox="0 0 24 24" class="logo-icon">
5872
- <path [attr.d]="iconRegistry.getIcon('dashboard')"></path>
5873
- </svg>
5874
- </div>
5875
- <span class="logo-text">{{ config.appName() }}</span>
5876
- </div>
5877
- </div>
5878
-
5879
- <nav class="sidebar-nav">
5880
- @for (group of navigation.menuItems(); track group.label) {
5881
- <div class="nav-group">
5882
- <h3 class="group-title">{{ group.label }}</h3>
5883
- <ul>
5884
- <ng-container *ngTemplateOutlet="menuList; context: { $implicit: group.items }"></ng-container>
5885
- </ul>
5886
- </div>
5887
- }
5888
- </nav>
5889
-
5890
- <ng-template #menuList let-listItems>
5891
- @for (node of listItems; track node.label) {
5892
- <li class="nav-item-wrapper">
5893
- <div
5894
- class="nav-item"
5895
- [routerLink]="node.route ? node.route : null"
5896
- routerLinkActive="active"
5897
- [class.has-children]="node.children?.length"
5898
- (click)="toggleExpand(node)"
5899
- >
5900
- <div class="nav-link-content">
5901
- @if (node.icon) {
5902
- <svg viewBox="0 0 24 24" class="nav-icon">
5903
- <path [attr.d]="iconRegistry.getIcon(node.icon)"></path>
5904
- </svg>
5905
- }
5906
- <span class="nav-label">{{ node.label }}</span>
5907
- </div>
5908
-
5909
- @if (node.badge) {
5910
- <span class="badge" [style.background]="'linear-gradient(135deg, ' + node.badgeColor + ', ' + node.badgeColor + '88)'">
5911
- {{ node.badge }}
5912
- </span>
5913
- }
5914
-
5915
- @if (node.children?.length) {
5916
- <svg viewBox="0 0 24 24" class="chevron" [class.rotated]="expandedItems.has(node)">
5917
- <path [attr.d]="iconRegistry.getIcon('chevron-right')"></path>
5918
- </svg>
5919
- }
5920
- </div>
5921
-
5922
- @if (node.children?.length && expandedItems.has(node)) {
5923
- <ul class="sub-menu">
5924
- <ng-container *ngTemplateOutlet="menuList; context: { $implicit: node.children }"></ng-container>
5925
- </ul>
5926
- }
5927
- </li>
5928
- }
5929
- </ng-template>
5930
- </div>
5866
+ args: [{ selector: 'app-sidebar', standalone: true, imports: [CommonModule, RouterLink, RouterLinkActive], template: `
5867
+ <div class="sidebar-container" [class.collapsed]="config.sidebarCollapsed()">
5868
+ <div class="sidebar-header">
5869
+ <div class="logo">
5870
+ <div class="logo-glow">
5871
+ <svg viewBox="0 0 24 24" class="logo-icon">
5872
+ <path [attr.d]="iconRegistry.getIcon('dashboard')"></path>
5873
+ </svg>
5874
+ </div>
5875
+ <span class="logo-text">{{ config.appName() }}</span>
5876
+ </div>
5877
+ </div>
5878
+
5879
+ <nav class="sidebar-nav">
5880
+ @for (group of navigation.menuItems(); track group.label) {
5881
+ <div class="nav-group">
5882
+ <h3 class="group-title">{{ group.label }}</h3>
5883
+ <ul>
5884
+ <ng-container *ngTemplateOutlet="menuList; context: { $implicit: group.items }"></ng-container>
5885
+ </ul>
5886
+ </div>
5887
+ }
5888
+ </nav>
5889
+
5890
+ <ng-template #menuList let-listItems>
5891
+ @for (node of listItems; track node.label) {
5892
+ <li class="nav-item-wrapper">
5893
+ <div
5894
+ class="nav-item"
5895
+ [routerLink]="node.route ? node.route : null"
5896
+ routerLinkActive="active"
5897
+ [class.has-children]="node.children?.length"
5898
+ (click)="toggleExpand(node)"
5899
+ >
5900
+ <div class="nav-link-content">
5901
+ @if (node.icon) {
5902
+ <svg viewBox="0 0 24 24" class="nav-icon">
5903
+ <path [attr.d]="iconRegistry.getIcon(node.icon)"></path>
5904
+ </svg>
5905
+ }
5906
+ <span class="nav-label">{{ node.label }}</span>
5907
+ </div>
5908
+
5909
+ @if (node.badge) {
5910
+ <span class="badge" [style.background]="'linear-gradient(135deg, ' + node.badgeColor + ', ' + node.badgeColor + '88)'">
5911
+ {{ node.badge }}
5912
+ </span>
5913
+ }
5914
+
5915
+ @if (node.children?.length) {
5916
+ <svg viewBox="0 0 24 24" class="chevron" [class.rotated]="expandedItems.has(node)">
5917
+ <path [attr.d]="iconRegistry.getIcon('chevron-right')"></path>
5918
+ </svg>
5919
+ }
5920
+ </div>
5921
+
5922
+ @if (node.children?.length && expandedItems.has(node)) {
5923
+ <ul class="sub-menu">
5924
+ <ng-container *ngTemplateOutlet="menuList; context: { $implicit: node.children }"></ng-container>
5925
+ </ul>
5926
+ }
5927
+ </li>
5928
+ }
5929
+ </ng-template>
5930
+ </div>
5931
5931
  `, styles: [":host{display:block;height:100%}.sidebar-container{width:var(--sidebar-width, 260px);height:100%;background:var(--app-sidebar-bg);backdrop-filter:blur(var(--glass-blur-heavy));-webkit-backdrop-filter:blur(var(--glass-blur-heavy));border-right:1px solid var(--glass-border);display:flex;flex-direction:column;transition:width var(--transition-smooth);overflow:hidden;position:relative}.sidebar-container:after{content:\"\";position:absolute;top:0;right:0;width:1px;height:100%;background:linear-gradient(to bottom,transparent,var(--app-primary-light),transparent);pointer-events:none}.sidebar-container.collapsed{width:80px}.sidebar-header{height:68px;display:flex;align-items:center;padding:0 20px;border-bottom:1px solid var(--glass-border)}.logo{display:flex;align-items:center;gap:12px;font-weight:700;font-size:1.25rem;color:var(--app-text);white-space:nowrap}.logo-glow{width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));display:flex;align-items:center;justify-content:center;box-shadow:0 0 20px var(--app-glow);animation:pulseGlow 4s ease-in-out infinite;flex-shrink:0}.logo-icon{width:20px;height:20px;fill:#fff}.sidebar-container.collapsed .logo-text{display:none}.sidebar-nav{flex:1;overflow-y:auto;padding:16px 0}.nav-group{margin-top:28px}.nav-group:first-child{margin-top:0}.group-title{font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--app-text-muted);padding:0 24px 8px;opacity:.6}.sidebar-container.collapsed .group-title{display:none}ul{list-style:none;padding:0;margin:0}.nav-item-wrapper{margin-bottom:2px;padding:0 10px}.nav-item{display:flex;align-items:center;justify-content:space-between;height:44px;padding:0 14px;border-radius:10px;color:var(--app-sidebar-text);cursor:pointer;transition:all var(--transition-smooth);text-decoration:none;position:relative}.nav-item:hover{background:var(--glass-bg-hover);color:var(--app-text)}.nav-item.active{background:linear-gradient(135deg,var(--app-primary-light),var(--app-accent-light));color:var(--app-primary);box-shadow:0 0 20px var(--app-glow)}.nav-item.active:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:20px;border-radius:0 3px 3px 0;background:linear-gradient(to bottom,var(--app-primary),var(--app-accent))}.nav-item.active .nav-icon{filter:drop-shadow(0 0 6px var(--app-glow))}.nav-link-content{display:flex;align-items:center;gap:12px}.nav-icon{width:20px;height:20px;fill:currentColor;flex-shrink:0;transition:all var(--transition-fast)}.sidebar-container.collapsed .nav-label,.sidebar-container.collapsed .chevron,.sidebar-container.collapsed .badge{display:none}.chevron{width:16px;height:16px;fill:currentColor;transition:transform var(--transition-smooth);opacity:.5}.chevron.rotated{transform:rotate(90deg)}.badge{font-size:10px;padding:2px 8px;border-radius:10px;color:#fff;font-weight:600;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.sub-menu{padding-left:24px;margin-top:4px;animation:fadeInUp .2s ease-out}.sidebar-container.collapsed .sub-menu{display:none}\n"] }]
5932
5932
  }] });
5933
5933
 
@@ -5946,437 +5946,437 @@ class NavbarComponent {
5946
5946
  };
5947
5947
  return colors[name] || '#06b6d4';
5948
5948
  }
5949
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5950
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: NavbarComponent, isStandalone: true, selector: "app-navbar", ngImport: i0, template: `
5951
- <header class="navbar-container">
5952
- <div class="left-section">
5953
- <button class="icon-btn" (click)="config.toggleSidebar()" title="Toggle Sidebar">
5954
- <svg viewBox="0 0 24 24">
5955
- <path [attr.d]="iconRegistry.getIcon('menu')"></path>
5956
- </svg>
5957
- </button>
5958
-
5959
- <div class="search-box">
5960
- <svg viewBox="0 0 24 24" class="search-icon">
5961
- <path [attr.d]="iconRegistry.getIcon('search')"></path>
5962
- </svg>
5963
- <input type="text" placeholder="Search anything...">
5964
- </div>
5965
- </div>
5966
-
5967
- <div class="right-section">
5968
- <!-- Theme Switcher -->
5969
- <button class="icon-btn theme-btn" (click)="themeToggleOpen.set(!themeToggleOpen())" title="Change Theme">
5970
- <svg viewBox="0 0 24 24">
5971
- <path [attr.d]="iconRegistry.getIcon('palette')"></path>
5972
- </svg>
5973
-
5974
- @if (themeToggleOpen()) {
5975
- <div class="dropdown theme-dropdown">
5976
- @for (theme of themeService.availableThemes; track theme.name) {
5977
- <div
5978
- class="dropdown-item"
5979
- [class.active]="themeService.currentTheme() === theme.name"
5980
- (click)="themeService.setTheme(theme.name); themeToggleOpen.set(false)"
5981
- >
5982
- <span class="theme-dot" [style.background]="getThemeColor(theme.name)"></span>
5983
- {{ theme.label }}
5984
- </div>
5985
- }
5986
- </div>
5987
- }
5988
- </button>
5989
-
5990
- <!-- User Profile -->
5991
- <div class="user-profile" (click)="userMenuOpen.set(!userMenuOpen())">
5992
- <div class="user-info">
5993
- <span class="user-name">{{ auth.user()?.name }}</span>
5994
- <span class="user-role">{{ auth.user()?.role }}</span>
5995
- </div>
5996
- <div class="avatar">
5997
- @if (auth.user()?.avatar) {
5998
- <img [src]="auth.user()?.avatar" [alt]="auth.user()?.name">
5999
- } @else {
6000
- <svg viewBox="0 0 24 24">
6001
- <path [attr.d]="iconRegistry.getIcon('person')"></path>
6002
- </svg>
6003
- }
6004
- </div>
6005
-
6006
- @if (userMenuOpen()) {
6007
- <div class="dropdown user-dropdown">
6008
- <div class="dropdown-header">
6009
- <strong>{{ auth.user()?.name }}</strong>
6010
- <span>{{ auth.user()?.email }}</span>
6011
- </div>
6012
- <div class="divider"></div>
6013
- <div class="dropdown-item">Your Profile</div>
6014
- <div class="dropdown-item">Settings</div>
6015
- <div class="divider"></div>
6016
- <div class="dropdown-item logout" (click)="auth.logout()">
6017
- <svg viewBox="0 0 24 24" class="logout-icon">
6018
- <path [attr.d]="iconRegistry.getIcon('logout')"></path>
6019
- </svg>
6020
- Logout
6021
- </div>
6022
- </div>
6023
- }
6024
- </div>
6025
- </div>
6026
- </header>
5949
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5950
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: NavbarComponent, isStandalone: true, selector: "app-navbar", ngImport: i0, template: `
5951
+ <header class="navbar-container">
5952
+ <div class="left-section">
5953
+ <button class="icon-btn" (click)="config.toggleSidebar()" title="Toggle Sidebar">
5954
+ <svg viewBox="0 0 24 24">
5955
+ <path [attr.d]="iconRegistry.getIcon('menu')"></path>
5956
+ </svg>
5957
+ </button>
5958
+
5959
+ <div class="search-box">
5960
+ <svg viewBox="0 0 24 24" class="search-icon">
5961
+ <path [attr.d]="iconRegistry.getIcon('search')"></path>
5962
+ </svg>
5963
+ <input type="text" placeholder="Search anything...">
5964
+ </div>
5965
+ </div>
5966
+
5967
+ <div class="right-section">
5968
+ <!-- Theme Switcher -->
5969
+ <button class="icon-btn theme-btn" (click)="themeToggleOpen.set(!themeToggleOpen())" title="Change Theme">
5970
+ <svg viewBox="0 0 24 24">
5971
+ <path [attr.d]="iconRegistry.getIcon('palette')"></path>
5972
+ </svg>
5973
+
5974
+ @if (themeToggleOpen()) {
5975
+ <div class="dropdown theme-dropdown">
5976
+ @for (theme of themeService.availableThemes; track theme.name) {
5977
+ <div
5978
+ class="dropdown-item"
5979
+ [class.active]="themeService.currentTheme() === theme.name"
5980
+ (click)="themeService.setTheme(theme.name); themeToggleOpen.set(false)"
5981
+ >
5982
+ <span class="theme-dot" [style.background]="getThemeColor(theme.name)"></span>
5983
+ {{ theme.label }}
5984
+ </div>
5985
+ }
5986
+ </div>
5987
+ }
5988
+ </button>
5989
+
5990
+ <!-- User Profile -->
5991
+ <div class="user-profile" (click)="userMenuOpen.set(!userMenuOpen())">
5992
+ <div class="user-info">
5993
+ <span class="user-name">{{ auth.user()?.name }}</span>
5994
+ <span class="user-role">{{ auth.user()?.role }}</span>
5995
+ </div>
5996
+ <div class="avatar">
5997
+ @if (auth.user()?.avatar) {
5998
+ <img [src]="auth.user()?.avatar" [alt]="auth.user()?.name">
5999
+ } @else {
6000
+ <svg viewBox="0 0 24 24">
6001
+ <path [attr.d]="iconRegistry.getIcon('person')"></path>
6002
+ </svg>
6003
+ }
6004
+ </div>
6005
+
6006
+ @if (userMenuOpen()) {
6007
+ <div class="dropdown user-dropdown">
6008
+ <div class="dropdown-header">
6009
+ <strong>{{ auth.user()?.name }}</strong>
6010
+ <span>{{ auth.user()?.email }}</span>
6011
+ </div>
6012
+ <div class="divider"></div>
6013
+ <div class="dropdown-item">Your Profile</div>
6014
+ <div class="dropdown-item">Settings</div>
6015
+ <div class="divider"></div>
6016
+ <div class="dropdown-item logout" (click)="auth.logout()">
6017
+ <svg viewBox="0 0 24 24" class="logout-icon">
6018
+ <path [attr.d]="iconRegistry.getIcon('logout')"></path>
6019
+ </svg>
6020
+ Logout
6021
+ </div>
6022
+ </div>
6023
+ }
6024
+ </div>
6025
+ </div>
6026
+ </header>
6027
6027
  `, isInline: true, styles: [":host{display:block;width:100%}.navbar-container{height:68px;padding:0 24px;background:var(--app-navbar-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border-bottom:1px solid var(--glass-border);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100}.left-section,.right-section{display:flex;align-items:center;gap:16px}.icon-btn{width:40px;height:40px;border-radius:10px;border:1px solid transparent;background:transparent;color:var(--app-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--transition-smooth);position:relative}.icon-btn:hover{background:var(--glass-bg-hover);border-color:var(--glass-border);color:var(--app-primary);box-shadow:0 0 16px var(--app-glow)}.icon-btn svg{width:22px;height:22px;fill:currentColor}.search-box{display:flex;align-items:center;background:var(--glass-bg);border:1px solid var(--glass-border);border-radius:10px;padding:0 14px;width:300px;height:40px;transition:all var(--transition-smooth)}.search-box:focus-within{border-color:var(--app-primary);background:var(--glass-bg-hover);box-shadow:0 0 20px var(--app-glow)}.search-icon{width:18px;height:18px;fill:var(--app-text-muted);flex-shrink:0;transition:fill var(--transition-fast)}.search-box:focus-within .search-icon{fill:var(--app-primary)}.search-box input{border:none;background:transparent;padding:8px;outline:none;flex:1;font-size:.875rem;color:var(--app-text)}.search-box input::placeholder{color:var(--app-text-muted)}.user-profile{display:flex;align-items:center;gap:12px;cursor:pointer;padding:4px 12px;border-radius:12px;border:1px solid transparent;transition:all var(--transition-smooth);position:relative}.user-profile:hover{background:var(--glass-bg-hover);border-color:var(--glass-border)}.user-info{display:flex;flex-direction:column;align-items:flex-end}.user-name{font-size:.875rem;font-weight:600;color:var(--app-text)}.user-role{font-size:.6875rem;color:var(--app-text-muted);text-transform:uppercase;letter-spacing:.05em}.avatar{width:38px;height:38px;border-radius:12px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:box-shadow var(--transition-smooth)}.user-profile:hover .avatar{box-shadow:0 0 20px var(--app-glow)}.avatar img{width:100%;height:100%;object-fit:cover}.avatar svg{width:22px;height:22px;fill:currentColor}.dropdown{position:absolute;top:calc(100% + 8px);right:0;background:var(--app-bg-secondary);backdrop-filter:blur(var(--glass-blur-heavy));-webkit-backdrop-filter:blur(var(--glass-blur-heavy));border:1px solid var(--glass-border-light);border-radius:14px;box-shadow:var(--glass-shadow),0 0 30px #0006;min-width:220px;overflow:hidden;animation:slideInDown .25s ease-out}.dropdown-header{padding:14px 16px;display:flex;flex-direction:column}.dropdown-header strong{color:var(--app-text);font-size:.9375rem}.dropdown-header span{font-size:.75rem;color:var(--app-text-muted);margin-top:2px}.dropdown-item{padding:10px 16px;font-size:.875rem;cursor:pointer;transition:all var(--transition-fast);color:var(--app-text-muted);display:flex;align-items:center;gap:10px}.dropdown-item:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.dropdown-item.active{background:var(--app-primary-light);color:var(--app-primary);font-weight:600}.theme-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}.divider{height:1px;background:var(--glass-border);margin:4px 0}.logout{color:#f43f5e!important}.logout:hover{background:#f43f5e1a!important;color:#fb7185!important}.logout-icon{width:18px;height:18px;fill:currentColor}\n"] });
6028
6028
  }
6029
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavbarComponent, decorators: [{
6029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NavbarComponent, decorators: [{
6030
6030
  type: Component,
6031
- args: [{ selector: 'app-navbar', standalone: true, imports: [], template: `
6032
- <header class="navbar-container">
6033
- <div class="left-section">
6034
- <button class="icon-btn" (click)="config.toggleSidebar()" title="Toggle Sidebar">
6035
- <svg viewBox="0 0 24 24">
6036
- <path [attr.d]="iconRegistry.getIcon('menu')"></path>
6037
- </svg>
6038
- </button>
6039
-
6040
- <div class="search-box">
6041
- <svg viewBox="0 0 24 24" class="search-icon">
6042
- <path [attr.d]="iconRegistry.getIcon('search')"></path>
6043
- </svg>
6044
- <input type="text" placeholder="Search anything...">
6045
- </div>
6046
- </div>
6047
-
6048
- <div class="right-section">
6049
- <!-- Theme Switcher -->
6050
- <button class="icon-btn theme-btn" (click)="themeToggleOpen.set(!themeToggleOpen())" title="Change Theme">
6051
- <svg viewBox="0 0 24 24">
6052
- <path [attr.d]="iconRegistry.getIcon('palette')"></path>
6053
- </svg>
6054
-
6055
- @if (themeToggleOpen()) {
6056
- <div class="dropdown theme-dropdown">
6057
- @for (theme of themeService.availableThemes; track theme.name) {
6058
- <div
6059
- class="dropdown-item"
6060
- [class.active]="themeService.currentTheme() === theme.name"
6061
- (click)="themeService.setTheme(theme.name); themeToggleOpen.set(false)"
6062
- >
6063
- <span class="theme-dot" [style.background]="getThemeColor(theme.name)"></span>
6064
- {{ theme.label }}
6065
- </div>
6066
- }
6067
- </div>
6068
- }
6069
- </button>
6070
-
6071
- <!-- User Profile -->
6072
- <div class="user-profile" (click)="userMenuOpen.set(!userMenuOpen())">
6073
- <div class="user-info">
6074
- <span class="user-name">{{ auth.user()?.name }}</span>
6075
- <span class="user-role">{{ auth.user()?.role }}</span>
6076
- </div>
6077
- <div class="avatar">
6078
- @if (auth.user()?.avatar) {
6079
- <img [src]="auth.user()?.avatar" [alt]="auth.user()?.name">
6080
- } @else {
6081
- <svg viewBox="0 0 24 24">
6082
- <path [attr.d]="iconRegistry.getIcon('person')"></path>
6083
- </svg>
6084
- }
6085
- </div>
6086
-
6087
- @if (userMenuOpen()) {
6088
- <div class="dropdown user-dropdown">
6089
- <div class="dropdown-header">
6090
- <strong>{{ auth.user()?.name }}</strong>
6091
- <span>{{ auth.user()?.email }}</span>
6092
- </div>
6093
- <div class="divider"></div>
6094
- <div class="dropdown-item">Your Profile</div>
6095
- <div class="dropdown-item">Settings</div>
6096
- <div class="divider"></div>
6097
- <div class="dropdown-item logout" (click)="auth.logout()">
6098
- <svg viewBox="0 0 24 24" class="logout-icon">
6099
- <path [attr.d]="iconRegistry.getIcon('logout')"></path>
6100
- </svg>
6101
- Logout
6102
- </div>
6103
- </div>
6104
- }
6105
- </div>
6106
- </div>
6107
- </header>
6031
+ args: [{ selector: 'app-navbar', standalone: true, imports: [], template: `
6032
+ <header class="navbar-container">
6033
+ <div class="left-section">
6034
+ <button class="icon-btn" (click)="config.toggleSidebar()" title="Toggle Sidebar">
6035
+ <svg viewBox="0 0 24 24">
6036
+ <path [attr.d]="iconRegistry.getIcon('menu')"></path>
6037
+ </svg>
6038
+ </button>
6039
+
6040
+ <div class="search-box">
6041
+ <svg viewBox="0 0 24 24" class="search-icon">
6042
+ <path [attr.d]="iconRegistry.getIcon('search')"></path>
6043
+ </svg>
6044
+ <input type="text" placeholder="Search anything...">
6045
+ </div>
6046
+ </div>
6047
+
6048
+ <div class="right-section">
6049
+ <!-- Theme Switcher -->
6050
+ <button class="icon-btn theme-btn" (click)="themeToggleOpen.set(!themeToggleOpen())" title="Change Theme">
6051
+ <svg viewBox="0 0 24 24">
6052
+ <path [attr.d]="iconRegistry.getIcon('palette')"></path>
6053
+ </svg>
6054
+
6055
+ @if (themeToggleOpen()) {
6056
+ <div class="dropdown theme-dropdown">
6057
+ @for (theme of themeService.availableThemes; track theme.name) {
6058
+ <div
6059
+ class="dropdown-item"
6060
+ [class.active]="themeService.currentTheme() === theme.name"
6061
+ (click)="themeService.setTheme(theme.name); themeToggleOpen.set(false)"
6062
+ >
6063
+ <span class="theme-dot" [style.background]="getThemeColor(theme.name)"></span>
6064
+ {{ theme.label }}
6065
+ </div>
6066
+ }
6067
+ </div>
6068
+ }
6069
+ </button>
6070
+
6071
+ <!-- User Profile -->
6072
+ <div class="user-profile" (click)="userMenuOpen.set(!userMenuOpen())">
6073
+ <div class="user-info">
6074
+ <span class="user-name">{{ auth.user()?.name }}</span>
6075
+ <span class="user-role">{{ auth.user()?.role }}</span>
6076
+ </div>
6077
+ <div class="avatar">
6078
+ @if (auth.user()?.avatar) {
6079
+ <img [src]="auth.user()?.avatar" [alt]="auth.user()?.name">
6080
+ } @else {
6081
+ <svg viewBox="0 0 24 24">
6082
+ <path [attr.d]="iconRegistry.getIcon('person')"></path>
6083
+ </svg>
6084
+ }
6085
+ </div>
6086
+
6087
+ @if (userMenuOpen()) {
6088
+ <div class="dropdown user-dropdown">
6089
+ <div class="dropdown-header">
6090
+ <strong>{{ auth.user()?.name }}</strong>
6091
+ <span>{{ auth.user()?.email }}</span>
6092
+ </div>
6093
+ <div class="divider"></div>
6094
+ <div class="dropdown-item">Your Profile</div>
6095
+ <div class="dropdown-item">Settings</div>
6096
+ <div class="divider"></div>
6097
+ <div class="dropdown-item logout" (click)="auth.logout()">
6098
+ <svg viewBox="0 0 24 24" class="logout-icon">
6099
+ <path [attr.d]="iconRegistry.getIcon('logout')"></path>
6100
+ </svg>
6101
+ Logout
6102
+ </div>
6103
+ </div>
6104
+ }
6105
+ </div>
6106
+ </div>
6107
+ </header>
6108
6108
  `, styles: [":host{display:block;width:100%}.navbar-container{height:68px;padding:0 24px;background:var(--app-navbar-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border-bottom:1px solid var(--glass-border);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100}.left-section,.right-section{display:flex;align-items:center;gap:16px}.icon-btn{width:40px;height:40px;border-radius:10px;border:1px solid transparent;background:transparent;color:var(--app-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all var(--transition-smooth);position:relative}.icon-btn:hover{background:var(--glass-bg-hover);border-color:var(--glass-border);color:var(--app-primary);box-shadow:0 0 16px var(--app-glow)}.icon-btn svg{width:22px;height:22px;fill:currentColor}.search-box{display:flex;align-items:center;background:var(--glass-bg);border:1px solid var(--glass-border);border-radius:10px;padding:0 14px;width:300px;height:40px;transition:all var(--transition-smooth)}.search-box:focus-within{border-color:var(--app-primary);background:var(--glass-bg-hover);box-shadow:0 0 20px var(--app-glow)}.search-icon{width:18px;height:18px;fill:var(--app-text-muted);flex-shrink:0;transition:fill var(--transition-fast)}.search-box:focus-within .search-icon{fill:var(--app-primary)}.search-box input{border:none;background:transparent;padding:8px;outline:none;flex:1;font-size:.875rem;color:var(--app-text)}.search-box input::placeholder{color:var(--app-text-muted)}.user-profile{display:flex;align-items:center;gap:12px;cursor:pointer;padding:4px 12px;border-radius:12px;border:1px solid transparent;transition:all var(--transition-smooth);position:relative}.user-profile:hover{background:var(--glass-bg-hover);border-color:var(--glass-border)}.user-info{display:flex;flex-direction:column;align-items:flex-end}.user-name{font-size:.875rem;font-weight:600;color:var(--app-text)}.user-role{font-size:.6875rem;color:var(--app-text-muted);text-transform:uppercase;letter-spacing:.05em}.avatar{width:38px;height:38px;border-radius:12px;background:linear-gradient(135deg,var(--app-primary),var(--app-accent));color:#fff;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:box-shadow var(--transition-smooth)}.user-profile:hover .avatar{box-shadow:0 0 20px var(--app-glow)}.avatar img{width:100%;height:100%;object-fit:cover}.avatar svg{width:22px;height:22px;fill:currentColor}.dropdown{position:absolute;top:calc(100% + 8px);right:0;background:var(--app-bg-secondary);backdrop-filter:blur(var(--glass-blur-heavy));-webkit-backdrop-filter:blur(var(--glass-blur-heavy));border:1px solid var(--glass-border-light);border-radius:14px;box-shadow:var(--glass-shadow),0 0 30px #0006;min-width:220px;overflow:hidden;animation:slideInDown .25s ease-out}.dropdown-header{padding:14px 16px;display:flex;flex-direction:column}.dropdown-header strong{color:var(--app-text);font-size:.9375rem}.dropdown-header span{font-size:.75rem;color:var(--app-text-muted);margin-top:2px}.dropdown-item{padding:10px 16px;font-size:.875rem;cursor:pointer;transition:all var(--transition-fast);color:var(--app-text-muted);display:flex;align-items:center;gap:10px}.dropdown-item:hover{background:var(--glass-bg-hover);color:var(--app-primary)}.dropdown-item.active{background:var(--app-primary-light);color:var(--app-primary);font-weight:600}.theme-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}.divider{height:1px;background:var(--glass-border);margin:4px 0}.logout{color:#f43f5e!important}.logout:hover{background:#f43f5e1a!important;color:#fb7185!important}.logout-icon{width:18px;height:18px;fill:currentColor}\n"] }]
6109
6109
  }] });
6110
6110
 
6111
6111
  class FooterComponent {
6112
6112
  config = inject(AppConfigService);
6113
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6114
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: FooterComponent, isStandalone: true, selector: "app-footer", ngImport: i0, template: `
6115
- <footer class="footer-container">
6116
- <div class="footer-content">
6117
- <p class="copyright">{{ config.copyrightText() }}</p>
6118
- <div class="links">
6119
- <a href="#">Terms</a>
6120
- <a href="#">Privacy</a>
6121
- <a href="#">Support</a>
6122
- </div>
6123
- </div>
6124
- </footer>
6113
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6114
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: FooterComponent, isStandalone: true, selector: "app-footer", ngImport: i0, template: `
6115
+ <footer class="footer-container">
6116
+ <div class="footer-content">
6117
+ <p class="copyright">{{ config.copyrightText() }}</p>
6118
+ <div class="links">
6119
+ <a href="#">Terms</a>
6120
+ <a href="#">Privacy</a>
6121
+ <a href="#">Support</a>
6122
+ </div>
6123
+ </div>
6124
+ </footer>
6125
6125
  `, isInline: true, styles: [".footer-container{height:52px;padding:0 28px;background:var(--app-navbar-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border-top:1px solid var(--glass-border);display:flex;align-items:center;margin-top:auto;position:relative}.footer-container:before{content:\"\";position:absolute;top:0;left:10%;right:10%;height:1px;background:linear-gradient(to right,transparent,var(--app-primary-light),transparent)}.footer-content{width:100%;display:flex;justify-content:space-between;align-items:center}.copyright{font-size:.8125rem;color:var(--app-text-muted);opacity:.6}.links{display:flex;gap:20px}.links a{font-size:.8125rem;color:var(--app-text-muted);text-decoration:none;transition:all var(--transition-fast);opacity:.6}.links a:hover{color:var(--app-primary);opacity:1}\n"] });
6126
6126
  }
6127
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FooterComponent, decorators: [{
6127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FooterComponent, decorators: [{
6128
6128
  type: Component,
6129
- args: [{ selector: 'app-footer', standalone: true, imports: [], template: `
6130
- <footer class="footer-container">
6131
- <div class="footer-content">
6132
- <p class="copyright">{{ config.copyrightText() }}</p>
6133
- <div class="links">
6134
- <a href="#">Terms</a>
6135
- <a href="#">Privacy</a>
6136
- <a href="#">Support</a>
6137
- </div>
6138
- </div>
6139
- </footer>
6129
+ args: [{ selector: 'app-footer', standalone: true, imports: [], template: `
6130
+ <footer class="footer-container">
6131
+ <div class="footer-content">
6132
+ <p class="copyright">{{ config.copyrightText() }}</p>
6133
+ <div class="links">
6134
+ <a href="#">Terms</a>
6135
+ <a href="#">Privacy</a>
6136
+ <a href="#">Support</a>
6137
+ </div>
6138
+ </div>
6139
+ </footer>
6140
6140
  `, styles: [".footer-container{height:52px;padding:0 28px;background:var(--app-navbar-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border-top:1px solid var(--glass-border);display:flex;align-items:center;margin-top:auto;position:relative}.footer-container:before{content:\"\";position:absolute;top:0;left:10%;right:10%;height:1px;background:linear-gradient(to right,transparent,var(--app-primary-light),transparent)}.footer-content{width:100%;display:flex;justify-content:space-between;align-items:center}.copyright{font-size:.8125rem;color:var(--app-text-muted);opacity:.6}.links{display:flex;gap:20px}.links a{font-size:.8125rem;color:var(--app-text-muted);text-decoration:none;transition:all var(--transition-fast);opacity:.6}.links a:hover{color:var(--app-primary);opacity:1}\n"] }]
6141
6141
  }] });
6142
6142
 
6143
6143
  class VerticalLayoutComponent {
6144
6144
  config = inject(AppConfigService);
6145
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: VerticalLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6146
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: VerticalLayoutComponent, isStandalone: true, selector: "app-vertical-layout", ngImport: i0, template: `
6147
- <div class="layout-wrapper" [class.collapsed]="config.sidebarCollapsed()">
6148
- <!-- Animated Gradient Mesh Background -->
6149
- <div class="gradient-mesh" aria-hidden="true">
6150
- <div class="blob blob-1"></div>
6151
- <div class="blob blob-2"></div>
6152
- <div class="blob blob-3"></div>
6153
- </div>
6154
-
6155
- <!-- Sidebar -->
6156
- <app-sidebar class="layout-sidebar"></app-sidebar>
6157
-
6158
- <!-- Main Content Area -->
6159
- <div class="layout-main">
6160
- <app-navbar></app-navbar>
6161
-
6162
- <main class="content-body">
6163
- <router-outlet></router-outlet>
6164
- </main>
6165
-
6166
- <app-footer></app-footer>
6167
- </div>
6168
- </div>
6145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: VerticalLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: VerticalLayoutComponent, isStandalone: true, selector: "app-vertical-layout", ngImport: i0, template: `
6147
+ <div class="layout-wrapper" [class.collapsed]="config.sidebarCollapsed()">
6148
+ <!-- Animated Gradient Mesh Background -->
6149
+ <div class="gradient-mesh" aria-hidden="true">
6150
+ <div class="blob blob-1"></div>
6151
+ <div class="blob blob-2"></div>
6152
+ <div class="blob blob-3"></div>
6153
+ </div>
6154
+
6155
+ <!-- Sidebar -->
6156
+ <app-sidebar class="layout-sidebar"></app-sidebar>
6157
+
6158
+ <!-- Main Content Area -->
6159
+ <div class="layout-main">
6160
+ <app-navbar></app-navbar>
6161
+
6162
+ <main class="content-body">
6163
+ <router-outlet></router-outlet>
6164
+ </main>
6165
+
6166
+ <app-footer></app-footer>
6167
+ </div>
6168
+ </div>
6169
6169
  `, isInline: true, styles: [":host{display:block;height:100vh;width:100%}.layout-wrapper{display:flex;height:100vh;overflow:hidden;background:var(--app-bg);position:relative}.gradient-mesh{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none}.blob{position:absolute;border-radius:50%;filter:blur(80px);opacity:.35;will-change:transform}.blob-1{width:500px;height:500px;background:var(--app-gradient-1);top:-10%;right:-5%;animation:blobMove1 20s ease-in-out infinite}.blob-2{width:400px;height:400px;background:var(--app-gradient-2);bottom:-10%;left:10%;animation:blobMove2 25s ease-in-out infinite}.blob-3{width:350px;height:350px;background:var(--app-gradient-3);top:40%;left:40%;animation:blobMove3 22s ease-in-out infinite}.layout-sidebar{flex-shrink:0;z-index:100;position:relative}.layout-main{flex:1;display:flex;flex-direction:column;overflow-y:auto;position:relative;z-index:1;transition:margin-left var(--transition-smooth)}.content-body{padding:28px;flex:1;max-width:1600px;width:100%;margin:0 auto;animation:fadeInUp .4s ease-out}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: SidebarComponent, selector: "app-sidebar" }, { kind: "component", type: NavbarComponent, selector: "app-navbar" }, { kind: "component", type: FooterComponent, selector: "app-footer" }] });
6170
6170
  }
6171
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: VerticalLayoutComponent, decorators: [{
6171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: VerticalLayoutComponent, decorators: [{
6172
6172
  type: Component,
6173
- args: [{ selector: 'app-vertical-layout', standalone: true, imports: [RouterOutlet, SidebarComponent, NavbarComponent, FooterComponent], template: `
6174
- <div class="layout-wrapper" [class.collapsed]="config.sidebarCollapsed()">
6175
- <!-- Animated Gradient Mesh Background -->
6176
- <div class="gradient-mesh" aria-hidden="true">
6177
- <div class="blob blob-1"></div>
6178
- <div class="blob blob-2"></div>
6179
- <div class="blob blob-3"></div>
6180
- </div>
6181
-
6182
- <!-- Sidebar -->
6183
- <app-sidebar class="layout-sidebar"></app-sidebar>
6184
-
6185
- <!-- Main Content Area -->
6186
- <div class="layout-main">
6187
- <app-navbar></app-navbar>
6188
-
6189
- <main class="content-body">
6190
- <router-outlet></router-outlet>
6191
- </main>
6192
-
6193
- <app-footer></app-footer>
6194
- </div>
6195
- </div>
6173
+ args: [{ selector: 'app-vertical-layout', standalone: true, imports: [RouterOutlet, SidebarComponent, NavbarComponent, FooterComponent], template: `
6174
+ <div class="layout-wrapper" [class.collapsed]="config.sidebarCollapsed()">
6175
+ <!-- Animated Gradient Mesh Background -->
6176
+ <div class="gradient-mesh" aria-hidden="true">
6177
+ <div class="blob blob-1"></div>
6178
+ <div class="blob blob-2"></div>
6179
+ <div class="blob blob-3"></div>
6180
+ </div>
6181
+
6182
+ <!-- Sidebar -->
6183
+ <app-sidebar class="layout-sidebar"></app-sidebar>
6184
+
6185
+ <!-- Main Content Area -->
6186
+ <div class="layout-main">
6187
+ <app-navbar></app-navbar>
6188
+
6189
+ <main class="content-body">
6190
+ <router-outlet></router-outlet>
6191
+ </main>
6192
+
6193
+ <app-footer></app-footer>
6194
+ </div>
6195
+ </div>
6196
6196
  `, styles: [":host{display:block;height:100vh;width:100%}.layout-wrapper{display:flex;height:100vh;overflow:hidden;background:var(--app-bg);position:relative}.gradient-mesh{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none}.blob{position:absolute;border-radius:50%;filter:blur(80px);opacity:.35;will-change:transform}.blob-1{width:500px;height:500px;background:var(--app-gradient-1);top:-10%;right:-5%;animation:blobMove1 20s ease-in-out infinite}.blob-2{width:400px;height:400px;background:var(--app-gradient-2);bottom:-10%;left:10%;animation:blobMove2 25s ease-in-out infinite}.blob-3{width:350px;height:350px;background:var(--app-gradient-3);top:40%;left:40%;animation:blobMove3 22s ease-in-out infinite}.layout-sidebar{flex-shrink:0;z-index:100;position:relative}.layout-main{flex:1;display:flex;flex-direction:column;overflow-y:auto;position:relative;z-index:1;transition:margin-left var(--transition-smooth)}.content-body{padding:28px;flex:1;max-width:1600px;width:100%;margin:0 auto;animation:fadeInUp .4s ease-out}\n"] }]
6197
6197
  }] });
6198
6198
 
6199
6199
  class HorizontalLayoutComponent {
6200
6200
  navigation = inject(NavigationService);
6201
6201
  iconRegistry = inject(IconRegistryService);
6202
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: HorizontalLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6203
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: HorizontalLayoutComponent, isStandalone: true, selector: "app-horizontal-layout", ngImport: i0, template: `
6204
- <div class="layout-wrapper">
6205
- <app-navbar>
6206
- <!-- Horizontal Menu Injection (Conceptual - in a full app we'd use a dedicated component or slot) -->
6207
- </app-navbar>
6208
-
6209
- <nav class="horizontal-nav">
6210
- <div class="nav-container">
6211
- <ul>
6212
- @for (group of navigation.menuItems(); track group.label) {
6213
- @for (item of group.items; track item.label) {
6214
- <li class="nav-item">
6215
- <a [routerLink]="item.route" routerLinkActive="active" class="nav-link">
6216
- @if (item.icon) {
6217
- <svg viewBox="0 0 24 24" class="nav-icon">
6218
- <path [attr.d]="iconRegistry.getIcon(item.icon)"></path>
6219
- </svg>
6220
- }
6221
- {{ item.label }}
6222
- </a>
6223
- </li>
6224
- }
6225
- }
6226
- </ul>
6227
- </div>
6228
- </nav>
6229
-
6230
- <main class="content-body">
6231
- <router-outlet></router-outlet>
6232
- </main>
6233
-
6234
- <app-footer></app-footer>
6235
- </div>
6202
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HorizontalLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6203
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: HorizontalLayoutComponent, isStandalone: true, selector: "app-horizontal-layout", ngImport: i0, template: `
6204
+ <div class="layout-wrapper">
6205
+ <app-navbar>
6206
+ <!-- Horizontal Menu Injection (Conceptual - in a full app we'd use a dedicated component or slot) -->
6207
+ </app-navbar>
6208
+
6209
+ <nav class="horizontal-nav">
6210
+ <div class="nav-container">
6211
+ <ul>
6212
+ @for (group of navigation.menuItems(); track group.label) {
6213
+ @for (item of group.items; track item.label) {
6214
+ <li class="nav-item">
6215
+ <a [routerLink]="item.route" routerLinkActive="active" class="nav-link">
6216
+ @if (item.icon) {
6217
+ <svg viewBox="0 0 24 24" class="nav-icon">
6218
+ <path [attr.d]="iconRegistry.getIcon(item.icon)"></path>
6219
+ </svg>
6220
+ }
6221
+ {{ item.label }}
6222
+ </a>
6223
+ </li>
6224
+ }
6225
+ }
6226
+ </ul>
6227
+ </div>
6228
+ </nav>
6229
+
6230
+ <main class="content-body">
6231
+ <router-outlet></router-outlet>
6232
+ </main>
6233
+
6234
+ <app-footer></app-footer>
6235
+ </div>
6236
6236
  `, isInline: true, styles: [".layout-wrapper{display:flex;flex-direction:column;min-height:100vh;background:var(--app-bg, #f9fafb)}.horizontal-nav{background:var(--app-navbar-bg, #ffffff);border-bottom:1px solid var(--app-border, #e5e7eb);height:48px}.nav-container{max-width:1600px;margin:0 auto;height:100%;padding:0 24px}ul{display:flex;list-style:none;padding:0;margin:0;height:100%;gap:32px}.nav-item{height:100%}.nav-link{display:flex;align-items:center;gap:8px;height:100%;color:var(--app-text, #374151);text-decoration:none;font-size:.875rem;font-weight:500;border-bottom:2px solid transparent;transition:all .2s}.nav-link:hover{color:var(--app-primary, #3b82f6)}.nav-link.active{color:var(--app-primary, #3b82f6);border-bottom-color:var(--app-primary, #3b82f6)}.nav-icon{width:18px;height:18px;fill:currentColor}.content-body{padding:24px;flex:1;max-width:1600px;width:100%;margin:0 auto}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: NavbarComponent, selector: "app-navbar" }, { kind: "component", type: FooterComponent, selector: "app-footer" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
6237
6237
  }
6238
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: HorizontalLayoutComponent, decorators: [{
6238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HorizontalLayoutComponent, decorators: [{
6239
6239
  type: Component,
6240
- args: [{ selector: 'app-horizontal-layout', standalone: true, imports: [RouterOutlet, NavbarComponent, FooterComponent, RouterLink, RouterLinkActive], template: `
6241
- <div class="layout-wrapper">
6242
- <app-navbar>
6243
- <!-- Horizontal Menu Injection (Conceptual - in a full app we'd use a dedicated component or slot) -->
6244
- </app-navbar>
6245
-
6246
- <nav class="horizontal-nav">
6247
- <div class="nav-container">
6248
- <ul>
6249
- @for (group of navigation.menuItems(); track group.label) {
6250
- @for (item of group.items; track item.label) {
6251
- <li class="nav-item">
6252
- <a [routerLink]="item.route" routerLinkActive="active" class="nav-link">
6253
- @if (item.icon) {
6254
- <svg viewBox="0 0 24 24" class="nav-icon">
6255
- <path [attr.d]="iconRegistry.getIcon(item.icon)"></path>
6256
- </svg>
6257
- }
6258
- {{ item.label }}
6259
- </a>
6260
- </li>
6261
- }
6262
- }
6263
- </ul>
6264
- </div>
6265
- </nav>
6266
-
6267
- <main class="content-body">
6268
- <router-outlet></router-outlet>
6269
- </main>
6270
-
6271
- <app-footer></app-footer>
6272
- </div>
6240
+ args: [{ selector: 'app-horizontal-layout', standalone: true, imports: [RouterOutlet, NavbarComponent, FooterComponent, RouterLink, RouterLinkActive], template: `
6241
+ <div class="layout-wrapper">
6242
+ <app-navbar>
6243
+ <!-- Horizontal Menu Injection (Conceptual - in a full app we'd use a dedicated component or slot) -->
6244
+ </app-navbar>
6245
+
6246
+ <nav class="horizontal-nav">
6247
+ <div class="nav-container">
6248
+ <ul>
6249
+ @for (group of navigation.menuItems(); track group.label) {
6250
+ @for (item of group.items; track item.label) {
6251
+ <li class="nav-item">
6252
+ <a [routerLink]="item.route" routerLinkActive="active" class="nav-link">
6253
+ @if (item.icon) {
6254
+ <svg viewBox="0 0 24 24" class="nav-icon">
6255
+ <path [attr.d]="iconRegistry.getIcon(item.icon)"></path>
6256
+ </svg>
6257
+ }
6258
+ {{ item.label }}
6259
+ </a>
6260
+ </li>
6261
+ }
6262
+ }
6263
+ </ul>
6264
+ </div>
6265
+ </nav>
6266
+
6267
+ <main class="content-body">
6268
+ <router-outlet></router-outlet>
6269
+ </main>
6270
+
6271
+ <app-footer></app-footer>
6272
+ </div>
6273
6273
  `, styles: [".layout-wrapper{display:flex;flex-direction:column;min-height:100vh;background:var(--app-bg, #f9fafb)}.horizontal-nav{background:var(--app-navbar-bg, #ffffff);border-bottom:1px solid var(--app-border, #e5e7eb);height:48px}.nav-container{max-width:1600px;margin:0 auto;height:100%;padding:0 24px}ul{display:flex;list-style:none;padding:0;margin:0;height:100%;gap:32px}.nav-item{height:100%}.nav-link{display:flex;align-items:center;gap:8px;height:100%;color:var(--app-text, #374151);text-decoration:none;font-size:.875rem;font-weight:500;border-bottom:2px solid transparent;transition:all .2s}.nav-link:hover{color:var(--app-primary, #3b82f6)}.nav-link.active{color:var(--app-primary, #3b82f6);border-bottom-color:var(--app-primary, #3b82f6)}.nav-icon{width:18px;height:18px;fill:currentColor}.content-body{padding:24px;flex:1;max-width:1600px;width:100%;margin:0 auto}\n"] }]
6274
6274
  }] });
6275
6275
 
6276
6276
  class EmptyLayoutComponent {
6277
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EmptyLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6278
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: EmptyLayoutComponent, isStandalone: true, selector: "app-empty-layout", ngImport: i0, template: `
6279
- <div class="empty-layout-container">
6280
- <router-outlet></router-outlet>
6281
- </div>
6277
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: EmptyLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6278
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: EmptyLayoutComponent, isStandalone: true, selector: "app-empty-layout", ngImport: i0, template: `
6279
+ <div class="empty-layout-container">
6280
+ <router-outlet></router-outlet>
6281
+ </div>
6282
6282
  `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%}.empty-layout-container{height:100%;display:flex;flex-direction:column;background:var(--app-bg, #f9fafb);color:var(--app-text, #111827)}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
6283
6283
  }
6284
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EmptyLayoutComponent, decorators: [{
6284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: EmptyLayoutComponent, decorators: [{
6285
6285
  type: Component,
6286
- args: [{ selector: 'app-empty-layout', standalone: true, imports: [RouterOutlet], template: `
6287
- <div class="empty-layout-container">
6288
- <router-outlet></router-outlet>
6289
- </div>
6286
+ args: [{ selector: 'app-empty-layout', standalone: true, imports: [RouterOutlet], template: `
6287
+ <div class="empty-layout-container">
6288
+ <router-outlet></router-outlet>
6289
+ </div>
6290
6290
  `, styles: [":host{display:flex;flex-direction:column;height:100%}.empty-layout-container{height:100%;display:flex;flex-direction:column;background:var(--app-bg, #f9fafb);color:var(--app-text, #111827)}\n"] }]
6291
6291
  }] });
6292
6292
 
6293
6293
  class CenteredLayoutComponent {
6294
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CenteredLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6295
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: CenteredLayoutComponent, isStandalone: true, selector: "app-centered-layout", ngImport: i0, template: `
6296
- <div class="centered-container">
6297
- <div class="centered-content glass-panel">
6298
- <router-outlet></router-outlet>
6299
- </div>
6300
- </div>
6294
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CenteredLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6295
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: CenteredLayoutComponent, isStandalone: true, selector: "app-centered-layout", ngImport: i0, template: `
6296
+ <div class="centered-container">
6297
+ <div class="centered-content glass-panel">
6298
+ <router-outlet></router-outlet>
6299
+ </div>
6300
+ </div>
6301
6301
  `, isInline: true, styles: [".centered-container{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--app-bg, #f9fafb);padding:2rem}.centered-content{width:100%;max-width:600px;padding:2rem;border-radius:1rem}.glass-panel{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);box-shadow:var(--glass-shadow)}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
6302
6302
  }
6303
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CenteredLayoutComponent, decorators: [{
6303
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CenteredLayoutComponent, decorators: [{
6304
6304
  type: Component,
6305
- args: [{ selector: 'app-centered-layout', standalone: true, imports: [RouterOutlet], template: `
6306
- <div class="centered-container">
6307
- <div class="centered-content glass-panel">
6308
- <router-outlet></router-outlet>
6309
- </div>
6310
- </div>
6305
+ args: [{ selector: 'app-centered-layout', standalone: true, imports: [RouterOutlet], template: `
6306
+ <div class="centered-container">
6307
+ <div class="centered-content glass-panel">
6308
+ <router-outlet></router-outlet>
6309
+ </div>
6310
+ </div>
6311
6311
  `, styles: [".centered-container{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--app-bg, #f9fafb);padding:2rem}.centered-content{width:100%;max-width:600px;padding:2rem;border-radius:1rem}.glass-panel{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur));border:1px solid var(--glass-border);box-shadow:var(--glass-shadow)}\n"] }]
6312
6312
  }] });
6313
6313
 
6314
6314
  class TwoColumnLayoutComponent {
6315
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: TwoColumnLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6316
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: TwoColumnLayoutComponent, isStandalone: true, selector: "app-two-column-layout", ngImport: i0, template: `
6317
- <div class="two-column-container">
6318
- <aside class="left-panel glass-panel">
6319
- <!-- Master list or secondary navigation ideally goes here -->
6320
- <div class="placeholder-nav">Navigation / List</div>
6321
- </aside>
6322
- <main class="right-panel">
6323
- <router-outlet></router-outlet>
6324
- </main>
6325
- </div>
6315
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TwoColumnLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6316
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: TwoColumnLayoutComponent, isStandalone: true, selector: "app-two-column-layout", ngImport: i0, template: `
6317
+ <div class="two-column-container">
6318
+ <aside class="left-panel glass-panel">
6319
+ <!-- Master list or secondary navigation ideally goes here -->
6320
+ <div class="placeholder-nav">Navigation / List</div>
6321
+ </aside>
6322
+ <main class="right-panel">
6323
+ <router-outlet></router-outlet>
6324
+ </main>
6325
+ </div>
6326
6326
  `, isInline: true, styles: [".two-column-container{display:flex;min-height:100vh;background:var(--app-bg)}.left-panel{width:300px;flex-shrink:0;border-right:1px solid var(--glass-border);padding:1rem;display:flex;flex-direction:column}.right-panel{flex:1;padding:2rem;overflow-y:auto}.glass-panel{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}.placeholder-nav{color:var(--app-text-muted);font-size:.875rem;text-align:center;margin-top:2rem}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
6327
6327
  }
6328
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: TwoColumnLayoutComponent, decorators: [{
6328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TwoColumnLayoutComponent, decorators: [{
6329
6329
  type: Component,
6330
- args: [{ selector: 'app-two-column-layout', standalone: true, imports: [RouterOutlet], template: `
6331
- <div class="two-column-container">
6332
- <aside class="left-panel glass-panel">
6333
- <!-- Master list or secondary navigation ideally goes here -->
6334
- <div class="placeholder-nav">Navigation / List</div>
6335
- </aside>
6336
- <main class="right-panel">
6337
- <router-outlet></router-outlet>
6338
- </main>
6339
- </div>
6330
+ args: [{ selector: 'app-two-column-layout', standalone: true, imports: [RouterOutlet], template: `
6331
+ <div class="two-column-container">
6332
+ <aside class="left-panel glass-panel">
6333
+ <!-- Master list or secondary navigation ideally goes here -->
6334
+ <div class="placeholder-nav">Navigation / List</div>
6335
+ </aside>
6336
+ <main class="right-panel">
6337
+ <router-outlet></router-outlet>
6338
+ </main>
6339
+ </div>
6340
6340
  `, styles: [".two-column-container{display:flex;min-height:100vh;background:var(--app-bg)}.left-panel{width:300px;flex-shrink:0;border-right:1px solid var(--glass-border);padding:1rem;display:flex;flex-direction:column}.right-panel{flex:1;padding:2rem;overflow-y:auto}.glass-panel{background:var(--glass-bg);backdrop-filter:blur(var(--glass-blur));-webkit-backdrop-filter:blur(var(--glass-blur))}.placeholder-nav{color:var(--app-text-muted);font-size:.875rem;text-align:center;margin-top:2rem}\n"] }]
6341
6341
  }] });
6342
6342
 
6343
6343
  class DashboardGridLayoutComponent {
6344
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DashboardGridLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6345
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: DashboardGridLayoutComponent, isStandalone: true, selector: "app-dashboard-grid-layout", ngImport: i0, template: `
6346
- <div class="dashboard-grid-container">
6347
- <router-outlet></router-outlet>
6348
- </div>
6344
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DashboardGridLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6345
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: DashboardGridLayoutComponent, isStandalone: true, selector: "app-dashboard-grid-layout", ngImport: i0, template: `
6346
+ <div class="dashboard-grid-container">
6347
+ <router-outlet></router-outlet>
6348
+ </div>
6349
6349
  `, isInline: true, styles: [".dashboard-grid-container{display:grid;grid-template-columns:repeat(12,1fr);gap:1.5rem;padding:2rem;min-height:100vh;background:var(--app-bg)}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
6350
6350
  }
6351
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DashboardGridLayoutComponent, decorators: [{
6351
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DashboardGridLayoutComponent, decorators: [{
6352
6352
  type: Component,
6353
- args: [{ selector: 'app-dashboard-grid-layout', standalone: true, imports: [RouterOutlet], template: `
6354
- <div class="dashboard-grid-container">
6355
- <router-outlet></router-outlet>
6356
- </div>
6353
+ args: [{ selector: 'app-dashboard-grid-layout', standalone: true, imports: [RouterOutlet], template: `
6354
+ <div class="dashboard-grid-container">
6355
+ <router-outlet></router-outlet>
6356
+ </div>
6357
6357
  `, styles: [".dashboard-grid-container{display:grid;grid-template-columns:repeat(12,1fr);gap:1.5rem;padding:2rem;min-height:100vh;background:var(--app-bg)}\n"] }]
6358
6358
  }] });
6359
6359
 
6360
6360
  class CompactLayoutComponent {
6361
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CompactLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6362
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: CompactLayoutComponent, isStandalone: true, selector: "app-compact-layout", ngImport: i0, template: `
6363
- <div class="compact-container">
6364
- <!-- Minimal or no header -->
6365
- <main class="compact-content">
6366
- <router-outlet></router-outlet>
6367
- </main>
6368
- </div>
6361
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CompactLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6362
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: CompactLayoutComponent, isStandalone: true, selector: "app-compact-layout", ngImport: i0, template: `
6363
+ <div class="compact-container">
6364
+ <!-- Minimal or no header -->
6365
+ <main class="compact-content">
6366
+ <router-outlet></router-outlet>
6367
+ </main>
6368
+ </div>
6369
6369
  `, isInline: true, styles: [".compact-container{display:flex;flex-direction:column;min-height:100vh;background:var(--app-bg)}.compact-content{flex:1;padding:1rem;max-width:100%;overflow-x:hidden}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
6370
6370
  }
6371
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CompactLayoutComponent, decorators: [{
6371
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CompactLayoutComponent, decorators: [{
6372
6372
  type: Component,
6373
- args: [{ selector: 'app-compact-layout', standalone: true, imports: [RouterOutlet], template: `
6374
- <div class="compact-container">
6375
- <!-- Minimal or no header -->
6376
- <main class="compact-content">
6377
- <router-outlet></router-outlet>
6378
- </main>
6379
- </div>
6373
+ args: [{ selector: 'app-compact-layout', standalone: true, imports: [RouterOutlet], template: `
6374
+ <div class="compact-container">
6375
+ <!-- Minimal or no header -->
6376
+ <main class="compact-content">
6377
+ <router-outlet></router-outlet>
6378
+ </main>
6379
+ </div>
6380
6380
  `, styles: [".compact-container{display:flex;flex-direction:column;min-height:100vh;background:var(--app-bg)}.compact-content{flex:1;padding:1rem;max-width:100%;overflow-x:hidden}\n"] }]
6381
6381
  }] });
6382
6382
 
@@ -6391,51 +6391,51 @@ class NotificationContainerComponent {
6391
6391
  default: return this.iconRegistry.getIcon('info');
6392
6392
  }
6393
6393
  }
6394
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NotificationContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6395
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: NotificationContainerComponent, isStandalone: true, selector: "app-notification-container", ngImport: i0, template: `
6396
- <div class="notification-wrapper">
6397
- @for (n of service.notifications(); track n.id) {
6398
- <div class="toast" [class]="n.type" (click)="service.remove(n.id)">
6399
- <div class="toast-icon">
6400
- <svg viewBox="0 0 24 24">
6401
- <path [attr.d]="getIcon(n.type)"></path>
6402
- </svg>
6403
- </div>
6404
- <div class="toast-content">
6405
- {{ n.message }}
6406
- </div>
6407
- <button class="toast-close">
6408
- <svg viewBox="0 0 24 24">
6409
- <path [attr.d]="iconRegistry.getIcon('close')"></path>
6410
- </svg>
6411
- </button>
6412
- </div>
6413
- }
6414
- </div>
6394
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotificationContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6395
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: NotificationContainerComponent, isStandalone: true, selector: "app-notification-container", ngImport: i0, template: `
6396
+ <div class="notification-wrapper">
6397
+ @for (n of service.notifications(); track n.id) {
6398
+ <div class="toast" [class]="n.type" (click)="service.remove(n.id)">
6399
+ <div class="toast-icon">
6400
+ <svg viewBox="0 0 24 24">
6401
+ <path [attr.d]="getIcon(n.type)"></path>
6402
+ </svg>
6403
+ </div>
6404
+ <div class="toast-content">
6405
+ {{ n.message }}
6406
+ </div>
6407
+ <button class="toast-close">
6408
+ <svg viewBox="0 0 24 24">
6409
+ <path [attr.d]="iconRegistry.getIcon('close')"></path>
6410
+ </svg>
6411
+ </button>
6412
+ </div>
6413
+ }
6414
+ </div>
6415
6415
  `, isInline: true, styles: [".notification-wrapper{position:fixed;top:24px;right:24px;z-index:9999;display:flex;flex-direction:column;gap:12px;pointer-events:none}.toast{pointer-events:auto;min-width:300px;max-width:450px;background:var(--app-surface, #ffffff);border-radius:12px;padding:16px;display:flex;align-items:center;gap:12px;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;border-left:4px solid #e5e7eb;cursor:pointer;animation:slideIn .3s cubic-bezier(.4,0,.2,1);transition:all .2s}.toast:hover{transform:translateY(-2px);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.toast.success{border-left-color:#10b981}.toast.error{border-left-color:#ef4444}.toast.warning{border-left-color:#f59e0b}.toast.info{border-left-color:#3b82f6}.toast-icon{width:24px;height:24px;flex-shrink:0}.toast.success .toast-icon{fill:#10b981}.toast.error .toast-icon{fill:#ef4444}.toast.warning .toast-icon{fill:#f59e0b}.toast.info .toast-icon{fill:#3b82f6}.toast-content{flex:1;font-size:.875rem;font-weight:500;color:var(--app-text, #1f2937);line-height:1.4}.toast-close{background:none;border:none;padding:4px;cursor:pointer;color:var(--app-text-muted, #6b7280);opacity:.5;transition:opacity .2s}.toast-close:hover{opacity:1}.toast-close svg{width:16px;height:16px;fill:currentColor}@keyframes slideIn{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}\n"] });
6416
6416
  }
6417
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NotificationContainerComponent, decorators: [{
6417
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotificationContainerComponent, decorators: [{
6418
6418
  type: Component,
6419
- args: [{ selector: 'app-notification-container', standalone: true, imports: [], template: `
6420
- <div class="notification-wrapper">
6421
- @for (n of service.notifications(); track n.id) {
6422
- <div class="toast" [class]="n.type" (click)="service.remove(n.id)">
6423
- <div class="toast-icon">
6424
- <svg viewBox="0 0 24 24">
6425
- <path [attr.d]="getIcon(n.type)"></path>
6426
- </svg>
6427
- </div>
6428
- <div class="toast-content">
6429
- {{ n.message }}
6430
- </div>
6431
- <button class="toast-close">
6432
- <svg viewBox="0 0 24 24">
6433
- <path [attr.d]="iconRegistry.getIcon('close')"></path>
6434
- </svg>
6435
- </button>
6436
- </div>
6437
- }
6438
- </div>
6419
+ args: [{ selector: 'app-notification-container', standalone: true, imports: [], template: `
6420
+ <div class="notification-wrapper">
6421
+ @for (n of service.notifications(); track n.id) {
6422
+ <div class="toast" [class]="n.type" (click)="service.remove(n.id)">
6423
+ <div class="toast-icon">
6424
+ <svg viewBox="0 0 24 24">
6425
+ <path [attr.d]="getIcon(n.type)"></path>
6426
+ </svg>
6427
+ </div>
6428
+ <div class="toast-content">
6429
+ {{ n.message }}
6430
+ </div>
6431
+ <button class="toast-close">
6432
+ <svg viewBox="0 0 24 24">
6433
+ <path [attr.d]="iconRegistry.getIcon('close')"></path>
6434
+ </svg>
6435
+ </button>
6436
+ </div>
6437
+ }
6438
+ </div>
6439
6439
  `, styles: [".notification-wrapper{position:fixed;top:24px;right:24px;z-index:9999;display:flex;flex-direction:column;gap:12px;pointer-events:none}.toast{pointer-events:auto;min-width:300px;max-width:450px;background:var(--app-surface, #ffffff);border-radius:12px;padding:16px;display:flex;align-items:center;gap:12px;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;border-left:4px solid #e5e7eb;cursor:pointer;animation:slideIn .3s cubic-bezier(.4,0,.2,1);transition:all .2s}.toast:hover{transform:translateY(-2px);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.toast.success{border-left-color:#10b981}.toast.error{border-left-color:#ef4444}.toast.warning{border-left-color:#f59e0b}.toast.info{border-left-color:#3b82f6}.toast-icon{width:24px;height:24px;flex-shrink:0}.toast.success .toast-icon{fill:#10b981}.toast.error .toast-icon{fill:#ef4444}.toast.warning .toast-icon{fill:#f59e0b}.toast.info .toast-icon{fill:#3b82f6}.toast-content{flex:1;font-size:.875rem;font-weight:500;color:var(--app-text, #1f2937);line-height:1.4}.toast-close{background:none;border:none;padding:4px;cursor:pointer;color:var(--app-text-muted, #6b7280);opacity:.5;transition:opacity .2s}.toast-close:hover{opacity:1}.toast-close svg{width:16px;height:16px;fill:currentColor}@keyframes slideIn{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}\n"] }]
6440
6440
  }] });
6441
6441
 
@@ -6446,41 +6446,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
6446
6446
  class LayoutComponent {
6447
6447
  config = inject(AppConfigService);
6448
6448
  LayoutType = LayoutType;
6449
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6450
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: LayoutComponent, isStandalone: true, selector: "app-layout", ngImport: i0, template: `
6451
- <app-notification-container></app-notification-container>
6452
- <amf-modal-host></amf-modal-host>
6453
- <amf-dialog-host></amf-dialog-host>
6454
- <amf-drawer-host></amf-drawer-host>
6455
- @switch (config.currentLayout()) {
6456
- @case (LayoutType.VERTICAL) {
6457
- <app-vertical-layout></app-vertical-layout>
6458
- }
6459
- @case (LayoutType.HORIZONTAL) {
6460
- <app-horizontal-layout></app-horizontal-layout>
6461
- }
6462
- @case (LayoutType.EMPTY) {
6463
- <app-empty-layout></app-empty-layout>
6464
- }
6465
- @case (LayoutType.CENTERED) {
6466
- <app-centered-layout></app-centered-layout>
6467
- }
6468
- @case (LayoutType.TWO_COLUMN) {
6469
- <app-two-column-layout></app-two-column-layout>
6470
- }
6471
- @case (LayoutType.DASHBOARD_GRID) {
6472
- <app-dashboard-grid-layout></app-dashboard-grid-layout>
6473
- }
6474
- @case (LayoutType.COMPACT) {
6475
- <app-compact-layout></app-compact-layout>
6476
- }
6477
- @default {
6478
- <app-vertical-layout></app-vertical-layout>
6479
- }
6480
- }
6449
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6450
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: LayoutComponent, isStandalone: true, selector: "app-layout", ngImport: i0, template: `
6451
+ <app-notification-container></app-notification-container>
6452
+ <amf-modal-host></amf-modal-host>
6453
+ <amf-dialog-host></amf-dialog-host>
6454
+ <amf-drawer-host></amf-drawer-host>
6455
+ @switch (config.currentLayout()) {
6456
+ @case (LayoutType.VERTICAL) {
6457
+ <app-vertical-layout></app-vertical-layout>
6458
+ }
6459
+ @case (LayoutType.HORIZONTAL) {
6460
+ <app-horizontal-layout></app-horizontal-layout>
6461
+ }
6462
+ @case (LayoutType.EMPTY) {
6463
+ <app-empty-layout></app-empty-layout>
6464
+ }
6465
+ @case (LayoutType.CENTERED) {
6466
+ <app-centered-layout></app-centered-layout>
6467
+ }
6468
+ @case (LayoutType.TWO_COLUMN) {
6469
+ <app-two-column-layout></app-two-column-layout>
6470
+ }
6471
+ @case (LayoutType.DASHBOARD_GRID) {
6472
+ <app-dashboard-grid-layout></app-dashboard-grid-layout>
6473
+ }
6474
+ @case (LayoutType.COMPACT) {
6475
+ <app-compact-layout></app-compact-layout>
6476
+ }
6477
+ @default {
6478
+ <app-vertical-layout></app-vertical-layout>
6479
+ }
6480
+ }
6481
6481
  `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "component", type: VerticalLayoutComponent, selector: "app-vertical-layout" }, { kind: "component", type: HorizontalLayoutComponent, selector: "app-horizontal-layout" }, { kind: "component", type: EmptyLayoutComponent, selector: "app-empty-layout" }, { kind: "component", type: CenteredLayoutComponent, selector: "app-centered-layout" }, { kind: "component", type: TwoColumnLayoutComponent, selector: "app-two-column-layout" }, { kind: "component", type: DashboardGridLayoutComponent, selector: "app-dashboard-grid-layout" }, { kind: "component", type: CompactLayoutComponent, selector: "app-compact-layout" }, { kind: "component", type: NotificationContainerComponent, selector: "app-notification-container" }, { kind: "component", type: MetaModalHostComponent, selector: "amf-modal-host" }, { kind: "component", type: AmfDialogHostComponent, selector: "amf-dialog-host" }, { kind: "component", type: AmfDrawerHostComponent, selector: "amf-drawer-host" }] });
6482
6482
  }
6483
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LayoutComponent, decorators: [{
6483
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LayoutComponent, decorators: [{
6484
6484
  type: Component,
6485
6485
  args: [{ selector: 'app-layout', standalone: true, imports: [
6486
6486
  VerticalLayoutComponent,
@@ -6494,37 +6494,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
6494
6494
  MetaModalHostComponent,
6495
6495
  AmfDialogHostComponent,
6496
6496
  AmfDrawerHostComponent
6497
- ], template: `
6498
- <app-notification-container></app-notification-container>
6499
- <amf-modal-host></amf-modal-host>
6500
- <amf-dialog-host></amf-dialog-host>
6501
- <amf-drawer-host></amf-drawer-host>
6502
- @switch (config.currentLayout()) {
6503
- @case (LayoutType.VERTICAL) {
6504
- <app-vertical-layout></app-vertical-layout>
6505
- }
6506
- @case (LayoutType.HORIZONTAL) {
6507
- <app-horizontal-layout></app-horizontal-layout>
6508
- }
6509
- @case (LayoutType.EMPTY) {
6510
- <app-empty-layout></app-empty-layout>
6511
- }
6512
- @case (LayoutType.CENTERED) {
6513
- <app-centered-layout></app-centered-layout>
6514
- }
6515
- @case (LayoutType.TWO_COLUMN) {
6516
- <app-two-column-layout></app-two-column-layout>
6517
- }
6518
- @case (LayoutType.DASHBOARD_GRID) {
6519
- <app-dashboard-grid-layout></app-dashboard-grid-layout>
6520
- }
6521
- @case (LayoutType.COMPACT) {
6522
- <app-compact-layout></app-compact-layout>
6523
- }
6524
- @default {
6525
- <app-vertical-layout></app-vertical-layout>
6526
- }
6527
- }
6497
+ ], template: `
6498
+ <app-notification-container></app-notification-container>
6499
+ <amf-modal-host></amf-modal-host>
6500
+ <amf-dialog-host></amf-dialog-host>
6501
+ <amf-drawer-host></amf-drawer-host>
6502
+ @switch (config.currentLayout()) {
6503
+ @case (LayoutType.VERTICAL) {
6504
+ <app-vertical-layout></app-vertical-layout>
6505
+ }
6506
+ @case (LayoutType.HORIZONTAL) {
6507
+ <app-horizontal-layout></app-horizontal-layout>
6508
+ }
6509
+ @case (LayoutType.EMPTY) {
6510
+ <app-empty-layout></app-empty-layout>
6511
+ }
6512
+ @case (LayoutType.CENTERED) {
6513
+ <app-centered-layout></app-centered-layout>
6514
+ }
6515
+ @case (LayoutType.TWO_COLUMN) {
6516
+ <app-two-column-layout></app-two-column-layout>
6517
+ }
6518
+ @case (LayoutType.DASHBOARD_GRID) {
6519
+ <app-dashboard-grid-layout></app-dashboard-grid-layout>
6520
+ }
6521
+ @case (LayoutType.COMPACT) {
6522
+ <app-compact-layout></app-compact-layout>
6523
+ }
6524
+ @default {
6525
+ <app-vertical-layout></app-vertical-layout>
6526
+ }
6527
+ }
6528
6528
  `, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}\n"] }]
6529
6529
  }] });
6530
6530