@avora-labs/meta-forge 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -63
- package/fesm2022/{avora-labs-meta-forge-amf-auth-shell.component-BWSdjBUS.mjs → avora-labs-meta-forge-amf-auth-shell.component-FCubZyZ1.mjs} +57 -57
- package/fesm2022/avora-labs-meta-forge-amf-auth-shell.component-FCubZyZ1.mjs.map +1 -0
- package/fesm2022/{avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs → avora-labs-meta-forge-contact-support.page-CgcSAr0x.mjs} +146 -146
- package/fesm2022/avora-labs-meta-forge-contact-support.page-CgcSAr0x.mjs.map +1 -0
- package/fesm2022/{avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs → avora-labs-meta-forge-forgot-password.page-CWdWX-mj.mjs} +238 -238
- package/fesm2022/avora-labs-meta-forge-forgot-password.page-CWdWX-mj.mjs.map +1 -0
- package/fesm2022/{avora-labs-meta-forge-login.page-etTr5NqJ.mjs → avora-labs-meta-forge-login.page-LCW-ofz1.mjs} +74 -74
- package/fesm2022/avora-labs-meta-forge-login.page-LCW-ofz1.mjs.map +1 -0
- package/fesm2022/avora-labs-meta-forge.mjs +1995 -1995
- package/fesm2022/avora-labs-meta-forge.mjs.map +1 -1
- package/package.json +3 -1
- package/styles/_palettes.scss +84 -84
- package/styles/_themes.scss +96 -96
- package/styles/_variables.scss +56 -56
- package/styles/styles.scss +295 -295
- package/fesm2022/avora-labs-meta-forge-amf-auth-shell.component-BWSdjBUS.mjs.map +0 -1
- package/fesm2022/avora-labs-meta-forge-contact-support.page-BAUiKm3P.mjs.map +0 -1
- package/fesm2022/avora-labs-meta-forge-forgot-password.page-0XLiBrV1.mjs.map +0 -1
- package/fesm2022/avora-labs-meta-forge-login.page-etTr5NqJ.mjs.map +0 -1
|
@@ -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();
|
|
@@ -1831,32 +1831,32 @@ class MetaPageComponent {
|
|
|
1831
1831
|
return true;
|
|
1832
1832
|
}
|
|
1833
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
|
-
}
|
|
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
|
+
}
|
|
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
1847
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
|
@@ -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-
|
|
2280
|
+
loadComponent: () => import('./avora-labs-meta-forge-login.page-LCW-ofz1.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-
|
|
2287
|
+
loadComponent: () => import('./avora-labs-meta-forge-forgot-password.page-CWdWX-mj.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-
|
|
2294
|
+
loadComponent: () => import('./avora-labs-meta-forge-contact-support.page-CgcSAr0x.mjs').then(m => m.ContactSupportComponent),
|
|
2295
2295
|
data: { layout: 'empty' },
|
|
2296
2296
|
});
|
|
2297
2297
|
}
|
|
@@ -2347,100 +2347,100 @@ class AccordionSectionComponent {
|
|
|
2347
2347
|
this.openPanels.set(current);
|
|
2348
2348
|
}
|
|
2349
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>
|
|
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>
|
|
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
2397
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -2480,60 +2480,60 @@ class MetaModalHostComponent {
|
|
|
2480
2480
|
this.dispatcher.dispatch(actionMeta, {});
|
|
2481
2481
|
}
|
|
2482
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()">×</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
|
-
}
|
|
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()">×</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
2510
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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()">×</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()">×</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
|
|
|
@@ -2635,84 +2635,84 @@ class AmfDialogHostComponent {
|
|
|
2635
2635
|
}
|
|
2636
2636
|
}
|
|
2637
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
|
-
}
|
|
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
|
+
}
|
|
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
2677
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
|
@@ -2750,74 +2750,74 @@ class AmfDrawerHostComponent {
|
|
|
2750
2750
|
this.dispatcher.dispatch(actionMeta, {});
|
|
2751
2751
|
}
|
|
2752
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">×</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>
|
|
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">×</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
2787
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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">×</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">×</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
|
|
|
@@ -3148,118 +3148,118 @@ class RepeaterFieldComponent {
|
|
|
3148
3148
|
this.formArray.removeAt(index);
|
|
3149
3149
|
}
|
|
3150
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>
|
|
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>
|
|
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
3207
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -3389,230 +3389,230 @@ class FieldRendererComponent {
|
|
|
3389
3389
|
}
|
|
3390
3390
|
}
|
|
3391
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
|
-
}
|
|
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
|
+
}
|
|
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
3504
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -3758,40 +3758,40 @@ class FormRendererComponent {
|
|
|
3758
3758
|
}
|
|
3759
3759
|
markAllTouched() { Object.values(this.formGroup.controls).forEach(c => c.markAsTouched()); }
|
|
3760
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>
|
|
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>
|
|
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
3778
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -4046,214 +4046,214 @@ class StepperFormRendererComponent {
|
|
|
4046
4046
|
return controls;
|
|
4047
4047
|
}
|
|
4048
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>
|
|
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>
|
|
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
4153
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -4286,60 +4286,60 @@ class CellRendererComponent {
|
|
|
4286
4286
|
return path.split('.').reduce((c, k) => c?.[k], obj) ?? '';
|
|
4287
4287
|
}
|
|
4288
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
|
-
}
|
|
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
|
+
}
|
|
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
4316
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -4777,404 +4777,404 @@ class TableRendererComponent {
|
|
|
4777
4777
|
}
|
|
4778
4778
|
}
|
|
4779
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>
|
|
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>
|
|
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
4979
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -5196,44 +5196,44 @@ class CardSectionComponent {
|
|
|
5196
5196
|
return this.sanitizer.bypassSecurityTrustHtml(this.config.content || '');
|
|
5197
5197
|
}
|
|
5198
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>
|
|
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>
|
|
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
5218
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -5250,46 +5250,46 @@ class StatsGridSectionComponent {
|
|
|
5250
5250
|
iconRegistry = inject(IconRegistryService);
|
|
5251
5251
|
get gridCols() { return `repeat(auto-fit, minmax(280px, 1fr))`; }
|
|
5252
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>
|
|
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>
|
|
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
5273
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -5314,40 +5314,40 @@ class PageHeaderSectionComponent {
|
|
|
5314
5314
|
return this.config.title;
|
|
5315
5315
|
}
|
|
5316
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>
|
|
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>
|
|
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
5334
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
@@ -5794,140 +5794,140 @@ class SidebarComponent {
|
|
|
5794
5794
|
}
|
|
5795
5795
|
}
|
|
5796
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>
|
|
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>
|
|
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
5864
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
|
@@ -5947,252 +5947,252 @@ class NavbarComponent {
|
|
|
5947
5947
|
return colors[name] || '#06b6d4';
|
|
5948
5948
|
}
|
|
5949
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>
|
|
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>
|
|
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
6029
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6171
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
|
@@ -6200,183 +6200,183 @@ class HorizontalLayoutComponent {
|
|
|
6200
6200
|
navigation = inject(NavigationService);
|
|
6201
6201
|
iconRegistry = inject(IconRegistryService);
|
|
6202
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>
|
|
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>
|
|
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
6238
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6284
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6303
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6328
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6351
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
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>
|
|
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>
|
|
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
6371
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
|
@@ -6392,50 +6392,50 @@ class NotificationContainerComponent {
|
|
|
6392
6392
|
}
|
|
6393
6393
|
}
|
|
6394
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>
|
|
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>
|
|
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
6417
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", 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
|
|
|
@@ -6447,37 +6447,37 @@ class LayoutComponent {
|
|
|
6447
6447
|
config = inject(AppConfigService);
|
|
6448
6448
|
LayoutType = LayoutType;
|
|
6449
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
|
-
}
|
|
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
|
+
}
|
|
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
6483
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LayoutComponent, decorators: [{
|
|
@@ -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
|
|