@camp2gether/c2g-ui 0.0.7
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 +95 -0
- package/charts/index.d.ts +199 -0
- package/fesm2022/camp2gether-c2g-ui-beach-animation-ipi3OoKW.mjs +54156 -0
- package/fesm2022/camp2gether-c2g-ui-beach-animation-ipi3OoKW.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-camping-animation-DY6XWXyF.mjs +35807 -0
- package/fesm2022/camp2gether-c2g-ui-camping-animation-DY6XWXyF.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-car-animation-DnDp7WfG.mjs +45189 -0
- package/fesm2022/camp2gether-c2g-ui-car-animation-DnDp7WfG.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-car-driving-landscape-animation-CawNeMKD.mjs +43833 -0
- package/fesm2022/camp2gether-c2g-ui-car-driving-landscape-animation-CawNeMKD.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-cat-love-animation-ewC7fZyY.mjs +30789 -0
- package/fesm2022/camp2gether-c2g-ui-cat-love-animation-ewC7fZyY.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-charts.mjs +404 -0
- package/fesm2022/camp2gether-c2g-ui-charts.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-checklist-animation-DqUkcLqI.mjs +19868 -0
- package/fesm2022/camp2gether-c2g-ui-checklist-animation-DqUkcLqI.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-coffee-time-animation-DQilaE0A.mjs +6816 -0
- package/fesm2022/camp2gether-c2g-ui-coffee-time-animation-DQilaE0A.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-error-404-pdjg-EHb.mjs +49742 -0
- package/fesm2022/camp2gether-c2g-ui-error-404-pdjg-EHb.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-fishing-animation-DwE3IF-V.mjs +38941 -0
- package/fesm2022/camp2gether-c2g-ui-fishing-animation-DwE3IF-V.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-layout.mjs +768 -0
- package/fesm2022/camp2gether-c2g-ui-layout.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-maps.mjs +223 -0
- package/fesm2022/camp2gether-c2g-ui-maps.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-mountain-search-animation-TebM1gS4.mjs +69245 -0
- package/fesm2022/camp2gether-c2g-ui-mountain-search-animation-TebM1gS4.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-planning-animation-D8QSsZk6.mjs +28330 -0
- package/fesm2022/camp2gether-c2g-ui-planning-animation-D8QSsZk6.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-presets.mjs +2855 -0
- package/fesm2022/camp2gether-c2g-ui-presets.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-share-animation-qgqs-k59.mjs +59129 -0
- package/fesm2022/camp2gether-c2g-ui-share-animation-qgqs-k59.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-summer-camp-animation-DPzirVNH.mjs +89317 -0
- package/fesm2022/camp2gether-c2g-ui-summer-camp-animation-DPzirVNH.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-theme.mjs +479 -0
- package/fesm2022/camp2gether-c2g-ui-theme.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-thinking-animation--X3er_pf.mjs +27929 -0
- package/fesm2022/camp2gether-c2g-ui-thinking-animation--X3er_pf.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-walking-avocado-animation-CQMU2C9-.mjs +4064 -0
- package/fesm2022/camp2gether-c2g-ui-walking-avocado-animation-CQMU2C9-.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-walking-orange-animation-CTJniCsF.mjs +3113 -0
- package/fesm2022/camp2gether-c2g-ui-walking-orange-animation-CTJniCsF.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui-weather-partly-cloudy-animation-Cnw3W4cS.mjs +1731 -0
- package/fesm2022/camp2gether-c2g-ui-weather-partly-cloudy-animation-Cnw3W4cS.mjs.map +1 -0
- package/fesm2022/camp2gether-c2g-ui.mjs +2099 -0
- package/fesm2022/camp2gether-c2g-ui.mjs.map +1 -0
- package/index.d.ts +578 -0
- package/layout/index.d.ts +443 -0
- package/maps/index.d.ts +62 -0
- package/package.json +51 -0
- package/presets/index.d.ts +1437 -0
- package/src/lib/styles/design-tokens.css +153 -0
- package/src/lib/styles/themes.scss +346 -0
- package/theme/index.d.ts +63 -0
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, ChangeDetectionStrategy, Component, computed, output, signal, forwardRef, model, effect } from '@angular/core';
|
|
3
|
+
import * as i1 from '@ngx-translate/core';
|
|
4
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
5
|
+
import * as i1$1 from '@angular/material/icon';
|
|
6
|
+
import { MatIconModule, MatIcon } from '@angular/material/icon';
|
|
7
|
+
import { ButtonComponent, LottieLoaderComponent } from '@humbeldore/c2g-ui';
|
|
8
|
+
import * as i1$2 from '@angular/material/button';
|
|
9
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
10
|
+
import * as i3 from '@angular/material/tooltip';
|
|
11
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
12
|
+
import * as i1$3 from '@angular/common';
|
|
13
|
+
import { CommonModule, NgClass, NgTemplateOutlet } from '@angular/common';
|
|
14
|
+
import { MatCard } from '@angular/material/card';
|
|
15
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
16
|
+
import * as i1$4 from '@angular/cdk/scrolling';
|
|
17
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
18
|
+
|
|
19
|
+
class ContentPanelComponent {
|
|
20
|
+
eyebrow = input('', ...(ngDevMode ? [{ debugName: "eyebrow" }] : []));
|
|
21
|
+
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
22
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContentPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ContentPanelComponent, isStandalone: true, selector: "app-content-panel", inputs: { eyebrow: { classPropertyName: "eyebrow", publicName: "eyebrow", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<article class=\"content-panel\">\n @if (eyebrow() || title()) {\n <header class=\"content-panel__header\">\n <div class=\"content-panel__header-text\">\n @if (eyebrow()) {\n <span class=\"content-panel__eyebrow\">{{ eyebrow() | translate }}</span>\n }\n @if (title()) {\n <h2 class=\"content-panel__title\">{{ title() | translate }}</h2>\n }\n </div>\n <div class=\"content-panel__actions\">\n <ng-content select=\"[panel-actions]\" />\n </div>\n </header>\n }\n <ng-content />\n</article>\n", styles: [".content-panel{background:var(--c2g-glass-bg, rgba(255, 255, 255, .95));border:1px solid var(--c2g-color-border-soft, rgba(17, 24, 39, .08));border-radius:var(--c2g-radius-xl, 1.125rem);box-shadow:var(--c2g-shadow-sm, 0 1px 2px rgba(15, 23, 42, .08));overflow:hidden}.content-panel__header{display:flex;align-items:flex-end;gap:var(--c2g-space-4, 1rem);padding:var(--c2g-space-6, 1.5rem) var(--c2g-space-6, 1.5rem) 0;flex-wrap:wrap}.content-panel__header-text{flex:1;min-width:0}.content-panel__eyebrow{display:block;font-size:var(--c2g-font-size-xs, .75rem);font-weight:var(--c2g-font-weight-bold, 700);letter-spacing:var(--c2g-letter-spacing-wide, .1em);text-transform:uppercase;color:var(--c2g-primary, #f97316);margin-bottom:var(--c2g-space-1, .25rem)}.content-panel__title{font-size:var(--c2g-font-size-lg, 1.25rem);font-weight:var(--c2g-font-weight-extrabold, 800);color:var(--c2g-text-primary, #1f2937);margin:0;letter-spacing:var(--c2g-letter-spacing-tight, -.02em)}.content-panel__actions{display:flex;align-items:center;gap:var(--c2g-space-2, .5rem);flex-wrap:wrap}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
24
|
+
}
|
|
25
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ContentPanelComponent, decorators: [{
|
|
26
|
+
type: Component,
|
|
27
|
+
args: [{ selector: 'app-content-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslateModule], template: "<article class=\"content-panel\">\n @if (eyebrow() || title()) {\n <header class=\"content-panel__header\">\n <div class=\"content-panel__header-text\">\n @if (eyebrow()) {\n <span class=\"content-panel__eyebrow\">{{ eyebrow() | translate }}</span>\n }\n @if (title()) {\n <h2 class=\"content-panel__title\">{{ title() | translate }}</h2>\n }\n </div>\n <div class=\"content-panel__actions\">\n <ng-content select=\"[panel-actions]\" />\n </div>\n </header>\n }\n <ng-content />\n</article>\n", styles: [".content-panel{background:var(--c2g-glass-bg, rgba(255, 255, 255, .95));border:1px solid var(--c2g-color-border-soft, rgba(17, 24, 39, .08));border-radius:var(--c2g-radius-xl, 1.125rem);box-shadow:var(--c2g-shadow-sm, 0 1px 2px rgba(15, 23, 42, .08));overflow:hidden}.content-panel__header{display:flex;align-items:flex-end;gap:var(--c2g-space-4, 1rem);padding:var(--c2g-space-6, 1.5rem) var(--c2g-space-6, 1.5rem) 0;flex-wrap:wrap}.content-panel__header-text{flex:1;min-width:0}.content-panel__eyebrow{display:block;font-size:var(--c2g-font-size-xs, .75rem);font-weight:var(--c2g-font-weight-bold, 700);letter-spacing:var(--c2g-letter-spacing-wide, .1em);text-transform:uppercase;color:var(--c2g-primary, #f97316);margin-bottom:var(--c2g-space-1, .25rem)}.content-panel__title{font-size:var(--c2g-font-size-lg, 1.25rem);font-weight:var(--c2g-font-weight-extrabold, 800);color:var(--c2g-text-primary, #1f2937);margin:0;letter-spacing:var(--c2g-letter-spacing-tight, -.02em)}.content-panel__actions{display:flex;align-items:center;gap:var(--c2g-space-2, .5rem);flex-wrap:wrap}\n"] }]
|
|
28
|
+
}], propDecorators: { eyebrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyebrow", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }] } });
|
|
29
|
+
|
|
30
|
+
class CoverageKpiComponent {
|
|
31
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
32
|
+
coveragePercent = input(0, ...(ngDevMode ? [{ debugName: "coveragePercent" }] : []));
|
|
33
|
+
ringCircumference = 125.66;
|
|
34
|
+
ringOffset = computed(() => this.ringCircumference * (1 - this.coveragePercent() / 100), ...(ngDevMode ? [{ debugName: "ringOffset" }] : []));
|
|
35
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CoverageKpiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
36
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.19", type: CoverageKpiComponent, isStandalone: true, selector: "app-coverage-kpi", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, coveragePercent: { classPropertyName: "coveragePercent", publicName: "coveragePercent", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"coverage-kpi\" role=\"listitem\">\n <div class=\"coverage-kpi__content\">\n <div class=\"coverage-kpi__ring\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 48 48\">\n <circle class=\"coverage-kpi__ring-bg\" cx=\"24\" cy=\"24\" r=\"20\" />\n <circle\n class=\"coverage-kpi__ring-fill\"\n cx=\"24\"\n cy=\"24\"\n r=\"20\"\n [style.stroke-dasharray]=\"ringCircumference\"\n [style.stroke-dashoffset]=\"ringOffset()\"\n />\n </svg>\n <span class=\"coverage-kpi__percent\">{{ coveragePercent() }}%</span>\n </div>\n\n <span class=\"coverage-kpi__label\">{{ label() }}</span>\n </div>\n</div>", styles: [":host{display:block;width:100%;height:100%}.coverage-kpi{box-sizing:border-box;background:#63b3ed26;border:1px solid rgba(255,255,255,.15);border-radius:14px;padding:16px;display:flex;flex-direction:column;justify-content:space-between;gap:12px;height:100%;position:relative;overflow:hidden}.coverage-kpi__content{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:10px;height:100%}.coverage-kpi__label{font-size:12px;opacity:.8;text-transform:uppercase;letter-spacing:.06em;line-height:1.25;text-align:center}.coverage-kpi__ring{position:relative;width:56px;height:56px;display:flex;align-items:center;justify-content:center}.coverage-kpi__ring svg{width:100%;height:100%;transform:rotate(-90deg)}.coverage-kpi__ring-bg{fill:none;stroke:#ffffff26;stroke-width:4}.coverage-kpi__ring-fill{fill:none;stroke:var(--c2g-color-secondary);stroke-width:4;stroke-linecap:round;transition:stroke-dashoffset .6s ease}.coverage-kpi__percent{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800}@media(max-width:1024px){.coverage-kpi{padding:14px}.coverage-kpi__content{gap:8px}.coverage-kpi__ring{width:54px;height:54px}.coverage-kpi__label,.coverage-kpi__percent{font-size:11px}}@media(max-width:640px){.coverage-kpi{padding:12px 14px}.coverage-kpi__content{gap:6px}.coverage-kpi__ring{width:48px;height:48px}.coverage-kpi__label,.coverage-kpi__percent{font-size:10px}.coverage-kpi__ring-bg,.coverage-kpi__ring-fill{stroke-width:3}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
37
|
+
}
|
|
38
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CoverageKpiComponent, decorators: [{
|
|
39
|
+
type: Component,
|
|
40
|
+
args: [{ selector: 'app-coverage-kpi', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [], template: "<div class=\"coverage-kpi\" role=\"listitem\">\n <div class=\"coverage-kpi__content\">\n <div class=\"coverage-kpi__ring\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 48 48\">\n <circle class=\"coverage-kpi__ring-bg\" cx=\"24\" cy=\"24\" r=\"20\" />\n <circle\n class=\"coverage-kpi__ring-fill\"\n cx=\"24\"\n cy=\"24\"\n r=\"20\"\n [style.stroke-dasharray]=\"ringCircumference\"\n [style.stroke-dashoffset]=\"ringOffset()\"\n />\n </svg>\n <span class=\"coverage-kpi__percent\">{{ coveragePercent() }}%</span>\n </div>\n\n <span class=\"coverage-kpi__label\">{{ label() }}</span>\n </div>\n</div>", styles: [":host{display:block;width:100%;height:100%}.coverage-kpi{box-sizing:border-box;background:#63b3ed26;border:1px solid rgba(255,255,255,.15);border-radius:14px;padding:16px;display:flex;flex-direction:column;justify-content:space-between;gap:12px;height:100%;position:relative;overflow:hidden}.coverage-kpi__content{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:10px;height:100%}.coverage-kpi__label{font-size:12px;opacity:.8;text-transform:uppercase;letter-spacing:.06em;line-height:1.25;text-align:center}.coverage-kpi__ring{position:relative;width:56px;height:56px;display:flex;align-items:center;justify-content:center}.coverage-kpi__ring svg{width:100%;height:100%;transform:rotate(-90deg)}.coverage-kpi__ring-bg{fill:none;stroke:#ffffff26;stroke-width:4}.coverage-kpi__ring-fill{fill:none;stroke:var(--c2g-color-secondary);stroke-width:4;stroke-linecap:round;transition:stroke-dashoffset .6s ease}.coverage-kpi__percent{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800}@media(max-width:1024px){.coverage-kpi{padding:14px}.coverage-kpi__content{gap:8px}.coverage-kpi__ring{width:54px;height:54px}.coverage-kpi__label,.coverage-kpi__percent{font-size:11px}}@media(max-width:640px){.coverage-kpi{padding:12px 14px}.coverage-kpi__content{gap:6px}.coverage-kpi__ring{width:48px;height:48px}.coverage-kpi__label,.coverage-kpi__percent{font-size:10px}.coverage-kpi__ring-bg,.coverage-kpi__ring-fill{stroke-width:3}}\n"] }]
|
|
41
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], coveragePercent: [{ type: i0.Input, args: [{ isSignal: true, alias: "coveragePercent", required: false }] }] } });
|
|
42
|
+
|
|
43
|
+
class HeroComponent {
|
|
44
|
+
eyebrow = input(...(ngDevMode ? [undefined, { debugName: "eyebrow" }] : []));
|
|
45
|
+
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : []));
|
|
46
|
+
lead = input(...(ngDevMode ? [undefined, { debugName: "lead" }] : []));
|
|
47
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: HeroComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
48
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: HeroComponent, isStandalone: true, selector: "app-hero", inputs: { eyebrow: { classPropertyName: "eyebrow", publicName: "eyebrow", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, lead: { classPropertyName: "lead", publicName: "lead", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<section class=\"hero\">\n @if (eyebrow()) {\n <div class=\"hero__eyebrow\">\n <mat-icon class=\"hero__icon\">backpack</mat-icon>\n <span>{{ eyebrow() }}</span>\n </div>\n }\n\n <h1 class=\"hero__title\">{{ title() }}</h1>\n <p class=\"hero__lead\">{{ lead() }}</p>\n\n <ng-content></ng-content>\n</section>\n", styles: [".hero{background:linear-gradient(135deg,var(--c2g-dark-bg, #16213e) 0%,#0f3460 100%);border-radius:20px;padding:32px;margin-bottom:24px;color:#fff}.hero__eyebrow{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;opacity:.7;margin-bottom:8px}.hero__icon{font-size:18px;width:18px;height:18px;flex-shrink:0}.hero__title{font-size:28px;font-weight:700;margin:0 0 24px;line-height:1.2}.hero__lead{font-size:14px;line-height:1.6;color:#ffffffa6;margin:0 0 24px;max-width:560px}@media(max-width:1024px){.hero{padding:28px 22px}.hero__title{font-size:24px}.hero__lead{font-size:13px;margin-bottom:18px}}@media(max-width:640px){.hero{padding:24px 16px}.hero__title{font-size:22px}.hero__lead{font-size:13px;margin-bottom:14px}}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
49
|
+
}
|
|
50
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: HeroComponent, decorators: [{
|
|
51
|
+
type: Component,
|
|
52
|
+
args: [{ selector: 'app-hero', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatIconModule, TranslateModule], template: "<section class=\"hero\">\n @if (eyebrow()) {\n <div class=\"hero__eyebrow\">\n <mat-icon class=\"hero__icon\">backpack</mat-icon>\n <span>{{ eyebrow() }}</span>\n </div>\n }\n\n <h1 class=\"hero__title\">{{ title() }}</h1>\n <p class=\"hero__lead\">{{ lead() }}</p>\n\n <ng-content></ng-content>\n</section>\n", styles: [".hero{background:linear-gradient(135deg,var(--c2g-dark-bg, #16213e) 0%,#0f3460 100%);border-radius:20px;padding:32px;margin-bottom:24px;color:#fff}.hero__eyebrow{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;opacity:.7;margin-bottom:8px}.hero__icon{font-size:18px;width:18px;height:18px;flex-shrink:0}.hero__title{font-size:28px;font-weight:700;margin:0 0 24px;line-height:1.2}.hero__lead{font-size:14px;line-height:1.6;color:#ffffffa6;margin:0 0 24px;max-width:560px}@media(max-width:1024px){.hero{padding:28px 22px}.hero__title{font-size:24px}.hero__lead{font-size:13px;margin-bottom:18px}}@media(max-width:640px){.hero{padding:24px 16px}.hero__title{font-size:22px}.hero__lead{font-size:13px;margin-bottom:14px}}\n"] }]
|
|
53
|
+
}], propDecorators: { eyebrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyebrow", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], lead: [{ type: i0.Input, args: [{ isSignal: true, alias: "lead", required: false }] }] } });
|
|
54
|
+
|
|
55
|
+
class KpiCardComponent {
|
|
56
|
+
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
57
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
58
|
+
icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
59
|
+
tone = input.required(...(ngDevMode ? [{ debugName: "tone" }] : []));
|
|
60
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: KpiCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
61
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.19", type: KpiCardComponent, isStandalone: true, selector: "app-kpi-card", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"kpi-card\" [class]=\"'kpi-card kpi-card--' + tone()\" role=\"listitem\">\n <div class=\"kpi-card__content\">\n <span class=\"kpi-card__value\">{{ value() }}</span>\n <span class=\"kpi-card__label\">{{ label() }}</span>\n </div>\n <mat-icon class=\"kpi-card__icon\">{{ icon() }}</mat-icon>\n</div>", styles: [":host{display:block;width:100%;height:100%}.kpi-card{box-sizing:border-box;background:#ffffff1a;border:1px solid rgba(255,255,255,.15);border-radius:14px;padding:16px;display:flex;flex-direction:column;justify-content:space-between;gap:12px;height:100%;position:relative;overflow:hidden}.kpi-card__content{display:flex;flex-direction:column;gap:6px;padding-right:20px}.kpi-card--owned{background:#48bb7826}.kpi-card--missing{background:#f5656526}.kpi-card--total{background:#ed893626}.kpi-card__value{font-size:28px;font-weight:700;line-height:1.05}.kpi-card__label{font-size:12px;opacity:.8;text-transform:uppercase;letter-spacing:.06em;line-height:1.25}.kpi-card__icon{position:absolute;top:12px;right:12px;font-size:18px;width:18px;height:18px;color:#ffffff40}.kpi-card--owned .kpi-card__icon{color:#3f9d76b3}.kpi-card--missing .kpi-card__icon{color:#dd4c4c99}.kpi-card--total .kpi-card__icon{color:#ff6b3599}@media(max-width:1024px){.kpi-card{padding:14px}.kpi-card__content{gap:4px;padding-right:18px}.kpi-card__value{font-size:25px}.kpi-card__label{font-size:11px}}@media(max-width:640px){.kpi-card{padding:12px 14px}.kpi-card__content{gap:4px;padding-right:18px}.kpi-card__value{font-size:22px}.kpi-card__label{font-size:10px}.kpi-card__icon{font-size:16px;width:16px;height:16px}}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
62
|
+
}
|
|
63
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: KpiCardComponent, decorators: [{
|
|
64
|
+
type: Component,
|
|
65
|
+
args: [{ selector: 'app-kpi-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatIconModule], template: "<div class=\"kpi-card\" [class]=\"'kpi-card kpi-card--' + tone()\" role=\"listitem\">\n <div class=\"kpi-card__content\">\n <span class=\"kpi-card__value\">{{ value() }}</span>\n <span class=\"kpi-card__label\">{{ label() }}</span>\n </div>\n <mat-icon class=\"kpi-card__icon\">{{ icon() }}</mat-icon>\n</div>", styles: [":host{display:block;width:100%;height:100%}.kpi-card{box-sizing:border-box;background:#ffffff1a;border:1px solid rgba(255,255,255,.15);border-radius:14px;padding:16px;display:flex;flex-direction:column;justify-content:space-between;gap:12px;height:100%;position:relative;overflow:hidden}.kpi-card__content{display:flex;flex-direction:column;gap:6px;padding-right:20px}.kpi-card--owned{background:#48bb7826}.kpi-card--missing{background:#f5656526}.kpi-card--total{background:#ed893626}.kpi-card__value{font-size:28px;font-weight:700;line-height:1.05}.kpi-card__label{font-size:12px;opacity:.8;text-transform:uppercase;letter-spacing:.06em;line-height:1.25}.kpi-card__icon{position:absolute;top:12px;right:12px;font-size:18px;width:18px;height:18px;color:#ffffff40}.kpi-card--owned .kpi-card__icon{color:#3f9d76b3}.kpi-card--missing .kpi-card__icon{color:#dd4c4c99}.kpi-card--total .kpi-card__icon{color:#ff6b3599}@media(max-width:1024px){.kpi-card{padding:14px}.kpi-card__content{gap:4px;padding-right:18px}.kpi-card__value{font-size:25px}.kpi-card__label{font-size:11px}}@media(max-width:640px){.kpi-card{padding:12px 14px}.kpi-card__content{gap:4px;padding-right:18px}.kpi-card__value{font-size:22px}.kpi-card__label{font-size:10px}.kpi-card__icon{font-size:16px;width:16px;height:16px}}\n"] }]
|
|
66
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: true }] }] } });
|
|
67
|
+
|
|
68
|
+
class DangerZoneItemComponent {
|
|
69
|
+
item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
|
|
70
|
+
triggered = output();
|
|
71
|
+
titleKey() {
|
|
72
|
+
return this.item().titleKey ?? this.item().title ?? '';
|
|
73
|
+
}
|
|
74
|
+
descriptionKey() {
|
|
75
|
+
return this.item().descriptionKey ?? this.item().description ?? null;
|
|
76
|
+
}
|
|
77
|
+
actionLabelKey() {
|
|
78
|
+
return this.item().action.labelKey ?? this.item().action.label ?? '';
|
|
79
|
+
}
|
|
80
|
+
actionAriaLabelKey() {
|
|
81
|
+
return this.item().action.ariaLabelKey ?? this.item().action.labelKey ?? this.item().action.ariaLabel ?? this.item().action.label ?? '';
|
|
82
|
+
}
|
|
83
|
+
onTriggered() {
|
|
84
|
+
this.triggered.emit(this.item());
|
|
85
|
+
}
|
|
86
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DangerZoneItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
87
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DangerZoneItemComponent, isStandalone: true, selector: "c2g-danger-zone-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { triggered: "triggered" }, ngImport: i0, template: "<div class=\"c2g-danger-zone-item\">\n <div class=\"c2g-danger-zone-item__info\">\n <span class=\"c2g-danger-zone-item__label\">{{ titleKey() | translate }}</span>\n @if (descriptionKey(); as descriptionKey) {\n <span class=\"c2g-danger-zone-item__hint\">{{ descriptionKey | translate }}</span>\n }\n </div>\n\n <c2g-button\n [variant]=\"item().action.variant ?? 'secondary'\"\n [icon]=\"item().action.icon ?? ''\"\n [ariaLabel]=\"actionAriaLabelKey() | translate\"\n [disabled]=\"item().action.disabled ?? false\"\n (clicked)=\"onTriggered()\"\n >\n {{ actionLabelKey() | translate }}\n </c2g-button>\n</div>\n", styles: [".c2g-danger-zone-item{display:flex;align-items:flex-start;gap:1rem;justify-content:space-between;padding:.875rem 1.25rem}.c2g-danger-zone-item__info{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.c2g-danger-zone-item__label{font-size:.9rem;color:var(--c2g-text-primary, #1a1a1a);font-weight:500}.c2g-danger-zone-item__hint{font-size:.8rem;color:var(--c2g-text-muted, #666);line-height:1.4}@media(max-width:639px){.c2g-danger-zone-item{flex-direction:column;align-items:stretch}}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "c2g-button", inputs: ["variant", "size", "disabled", "loading", "icon", "iconPosition", "iconOnly", "ariaLabel", "loadingAriaLabel", "type"], outputs: ["clicked"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
88
|
+
}
|
|
89
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DangerZoneItemComponent, decorators: [{
|
|
90
|
+
type: Component,
|
|
91
|
+
args: [{ selector: 'c2g-danger-zone-item', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ButtonComponent, TranslateModule], template: "<div class=\"c2g-danger-zone-item\">\n <div class=\"c2g-danger-zone-item__info\">\n <span class=\"c2g-danger-zone-item__label\">{{ titleKey() | translate }}</span>\n @if (descriptionKey(); as descriptionKey) {\n <span class=\"c2g-danger-zone-item__hint\">{{ descriptionKey | translate }}</span>\n }\n </div>\n\n <c2g-button\n [variant]=\"item().action.variant ?? 'secondary'\"\n [icon]=\"item().action.icon ?? ''\"\n [ariaLabel]=\"actionAriaLabelKey() | translate\"\n [disabled]=\"item().action.disabled ?? false\"\n (clicked)=\"onTriggered()\"\n >\n {{ actionLabelKey() | translate }}\n </c2g-button>\n</div>\n", styles: [".c2g-danger-zone-item{display:flex;align-items:flex-start;gap:1rem;justify-content:space-between;padding:.875rem 1.25rem}.c2g-danger-zone-item__info{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.c2g-danger-zone-item__label{font-size:.9rem;color:var(--c2g-text-primary, #1a1a1a);font-weight:500}.c2g-danger-zone-item__hint{font-size:.8rem;color:var(--c2g-text-muted, #666);line-height:1.4}@media(max-width:639px){.c2g-danger-zone-item{flex-direction:column;align-items:stretch}}\n"] }]
|
|
92
|
+
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], triggered: [{ type: i0.Output, args: ["triggered"] }] } });
|
|
93
|
+
|
|
94
|
+
class DangerZoneComponent {
|
|
95
|
+
headingKey = input('c2g.danger_zone.default.heading', ...(ngDevMode ? [{ debugName: "headingKey" }] : []));
|
|
96
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
97
|
+
/**
|
|
98
|
+
* Emits the clicked item id so consumers can map actions in their container.
|
|
99
|
+
*
|
|
100
|
+
* Prefer the per-item callback (`item.onTrigger`) when you want action logic to
|
|
101
|
+
* live directly on each item config.
|
|
102
|
+
*
|
|
103
|
+
* Output binding:
|
|
104
|
+
* ```html
|
|
105
|
+
* <c2g-danger-zone [items]="dangerItems" (itemTriggered)="onDangerAction($event)" />
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* Example mapping:
|
|
109
|
+
* ```ts
|
|
110
|
+
* onDangerAction(id: string) {
|
|
111
|
+
* if (id === 'delete-project') {
|
|
112
|
+
* this.openDeleteDialog();
|
|
113
|
+
* }
|
|
114
|
+
* }
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
itemTriggered = output();
|
|
118
|
+
resolvedHeadingKey = computed(() => this.headingKey(), ...(ngDevMode ? [{ debugName: "resolvedHeadingKey" }] : []));
|
|
119
|
+
onItemTriggered(item) {
|
|
120
|
+
item.onTrigger?.(item);
|
|
121
|
+
this.itemTriggered.emit(item.id);
|
|
122
|
+
}
|
|
123
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DangerZoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
124
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: DangerZoneComponent, isStandalone: true, selector: "c2g-danger-zone", inputs: { headingKey: { classPropertyName: "headingKey", publicName: "headingKey", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { itemTriggered: "itemTriggered" }, ngImport: i0, template: "<section class=\"c2g-danger-zone\" aria-labelledby=\"c2g-danger-zone-heading\">\n <h2 id=\"c2g-danger-zone-heading\" class=\"c2g-danger-zone__heading\">\n {{ resolvedHeadingKey() | translate }}\n </h2>\n\n <div class=\"c2g-danger-zone__content\">\n @for (item of items(); track item.id; let last = $last) {\n <c2g-danger-zone-item [item]=\"item\" (triggered)=\"onItemTriggered($event)\" />\n\n @if (!last) {\n <div class=\"c2g-danger-zone__divider\" aria-hidden=\"true\"></div>\n }\n }\n </div>\n</section>", styles: [".c2g-danger-zone{background:var(--c2g-card-background, #fff);border-radius:12px;border:1px solid var(--c2g-outline-variant, #d8d8d8);border-top:3px solid var(--mat-sys-error, #d32f2f);overflow:hidden}.c2g-danger-zone__heading{margin:0;padding:1rem 1.25rem .75rem;font-size:.875rem;font-weight:700;color:var(--mat-sys-error, #d32f2f);letter-spacing:.02em;text-transform:uppercase;background:var(--c2g-bg-primary, #f8f8f8);border-bottom:1px solid var(--c2g-outline-variant, #d8d8d8)}.c2g-danger-zone__content{padding:.25rem 0}.c2g-danger-zone__divider{height:1px;margin:0 1.25rem;background:var(--c2g-outline-variant, #d8d8d8)}\n"], dependencies: [{ kind: "component", type: DangerZoneItemComponent, selector: "c2g-danger-zone-item", inputs: ["item"], outputs: ["triggered"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
125
|
+
}
|
|
126
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DangerZoneComponent, decorators: [{
|
|
127
|
+
type: Component,
|
|
128
|
+
args: [{ selector: 'c2g-danger-zone', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [DangerZoneItemComponent, TranslateModule], template: "<section class=\"c2g-danger-zone\" aria-labelledby=\"c2g-danger-zone-heading\">\n <h2 id=\"c2g-danger-zone-heading\" class=\"c2g-danger-zone__heading\">\n {{ resolvedHeadingKey() | translate }}\n </h2>\n\n <div class=\"c2g-danger-zone__content\">\n @for (item of items(); track item.id; let last = $last) {\n <c2g-danger-zone-item [item]=\"item\" (triggered)=\"onItemTriggered($event)\" />\n\n @if (!last) {\n <div class=\"c2g-danger-zone__divider\" aria-hidden=\"true\"></div>\n }\n }\n </div>\n</section>", styles: [".c2g-danger-zone{background:var(--c2g-card-background, #fff);border-radius:12px;border:1px solid var(--c2g-outline-variant, #d8d8d8);border-top:3px solid var(--mat-sys-error, #d32f2f);overflow:hidden}.c2g-danger-zone__heading{margin:0;padding:1rem 1.25rem .75rem;font-size:.875rem;font-weight:700;color:var(--mat-sys-error, #d32f2f);letter-spacing:.02em;text-transform:uppercase;background:var(--c2g-bg-primary, #f8f8f8);border-bottom:1px solid var(--c2g-outline-variant, #d8d8d8)}.c2g-danger-zone__content{padding:.25rem 0}.c2g-danger-zone__divider{height:1px;margin:0 1.25rem;background:var(--c2g-outline-variant, #d8d8d8)}\n"] }]
|
|
129
|
+
}], propDecorators: { headingKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingKey", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], itemTriggered: [{ type: i0.Output, args: ["itemTriggered"] }] } });
|
|
130
|
+
|
|
131
|
+
class ListItemComponent {
|
|
132
|
+
group = input(null, ...(ngDevMode ? [{ debugName: "group" }] : []));
|
|
133
|
+
active = input(false, ...(ngDevMode ? [{ debugName: "active" }] : []));
|
|
134
|
+
selected = output();
|
|
135
|
+
opened = output();
|
|
136
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
137
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ListItemComponent, isStandalone: true, selector: "c2g-list-item", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected", opened: "opened" }, ngImport: i0, template: "<li\n class=\"c2g-list-item\"\n [class.c2g-list-item--active]=\"active()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"group()?.name\"\n (click)=\"selected.emit(group())\"\n (keyup.enter)=\"selected.emit(group())\"\n (keydown.space)=\"$event.preventDefault(); selected.emit(group())\"\n>\n <div class=\"c2g-list-item__avatar\">\n <mat-icon>group</mat-icon>\n </div>\n\n <div class=\"c2g-list-item__info\">\n <span class=\"c2g-list-item__name\">{{ group()?.name }}</span>\n @if (group()?.description) {\n <span class=\"c2g-list-item__desc\">{{ group()?.description }}</span>\n }\n </div>\n\n <div class=\"c2g-list-item__end\">\n <span class=\"c2g-list-item__members\">\n <mat-icon>group</mat-icon>\n {{ group()?.memberCount ?? group()?.members?.length ?? 0 }}\n </span>\n <button\n mat-icon-button\n class=\"c2g-list-item__open-btn\"\n [matTooltip]=\"'groups.open' | translate\"\n [attr.aria-label]=\"'groups.open' | translate\"\n (click)=\"$event.stopPropagation(); opened.emit(group())\"\n >\n <mat-icon>arrow_forward</mat-icon>\n </button>\n </div>\n</li>\n", styles: [":host{display:contents}.c2g-list-item{display:flex;align-items:center;gap:var(--spacing-3, 12px);padding:var(--spacing-3, 12px) var(--spacing-4, 16px);background:var(--c2g-glass-bg, rgba(255, 255, 255, .95));border:1px solid rgba(0,0,0,.06);border-radius:12px;cursor:pointer;transition:background .15s,border-color .15s,box-shadow .15s;list-style:none}.c2g-list-item:hover{background:#fff;box-shadow:0 2px 8px #00000014}.c2g-list-item--active{border-color:var(--c2g-primary, #16213e);background:#16213e0a;box-shadow:0 0 0 2px #16213e1f}.c2g-list-item:focus-visible{outline:2px solid var(--c2g-primary, #16213e);outline-offset:2px}.c2g-list-item__avatar{width:40px;height:40px;border-radius:50%;background:var(--c2g-primary, #16213e);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff}.c2g-list-item__avatar mat-icon{font-size:20px;width:20px;height:20px}.c2g-list-item__info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.c2g-list-item__name{font-weight:600;font-size:14px;color:var(--c2g-text-primary, #1a1a2e);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c2g-list-item__desc{font-size:12px;color:var(--c2g-text-muted, #6b5e52);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c2g-list-item__end{display:flex;align-items:center;gap:var(--spacing-2, 8px);flex-shrink:0}.c2g-list-item__members{display:flex;align-items:center;gap:4px;font-size:13px;font-weight:500;color:var(--c2g-text-muted, #6b5e52);white-space:nowrap}.c2g-list-item__members mat-icon{font-size:16px;width:16px;height:16px}.c2g-list-item__open-btn{color:var(--c2g-text-muted, #6b5e52);transition:color .15s}.c2g-list-item__open-btn:hover{color:var(--c2g-primary, #16213e)}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
138
|
+
}
|
|
139
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ListItemComponent, decorators: [{
|
|
140
|
+
type: Component,
|
|
141
|
+
args: [{ selector: 'c2g-list-item', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatButtonModule, MatIconModule, MatTooltipModule, TranslateModule], template: "<li\n class=\"c2g-list-item\"\n [class.c2g-list-item--active]=\"active()\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"group()?.name\"\n (click)=\"selected.emit(group())\"\n (keyup.enter)=\"selected.emit(group())\"\n (keydown.space)=\"$event.preventDefault(); selected.emit(group())\"\n>\n <div class=\"c2g-list-item__avatar\">\n <mat-icon>group</mat-icon>\n </div>\n\n <div class=\"c2g-list-item__info\">\n <span class=\"c2g-list-item__name\">{{ group()?.name }}</span>\n @if (group()?.description) {\n <span class=\"c2g-list-item__desc\">{{ group()?.description }}</span>\n }\n </div>\n\n <div class=\"c2g-list-item__end\">\n <span class=\"c2g-list-item__members\">\n <mat-icon>group</mat-icon>\n {{ group()?.memberCount ?? group()?.members?.length ?? 0 }}\n </span>\n <button\n mat-icon-button\n class=\"c2g-list-item__open-btn\"\n [matTooltip]=\"'groups.open' | translate\"\n [attr.aria-label]=\"'groups.open' | translate\"\n (click)=\"$event.stopPropagation(); opened.emit(group())\"\n >\n <mat-icon>arrow_forward</mat-icon>\n </button>\n </div>\n</li>\n", styles: [":host{display:contents}.c2g-list-item{display:flex;align-items:center;gap:var(--spacing-3, 12px);padding:var(--spacing-3, 12px) var(--spacing-4, 16px);background:var(--c2g-glass-bg, rgba(255, 255, 255, .95));border:1px solid rgba(0,0,0,.06);border-radius:12px;cursor:pointer;transition:background .15s,border-color .15s,box-shadow .15s;list-style:none}.c2g-list-item:hover{background:#fff;box-shadow:0 2px 8px #00000014}.c2g-list-item--active{border-color:var(--c2g-primary, #16213e);background:#16213e0a;box-shadow:0 0 0 2px #16213e1f}.c2g-list-item:focus-visible{outline:2px solid var(--c2g-primary, #16213e);outline-offset:2px}.c2g-list-item__avatar{width:40px;height:40px;border-radius:50%;background:var(--c2g-primary, #16213e);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff}.c2g-list-item__avatar mat-icon{font-size:20px;width:20px;height:20px}.c2g-list-item__info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.c2g-list-item__name{font-weight:600;font-size:14px;color:var(--c2g-text-primary, #1a1a2e);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c2g-list-item__desc{font-size:12px;color:var(--c2g-text-muted, #6b5e52);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c2g-list-item__end{display:flex;align-items:center;gap:var(--spacing-2, 8px);flex-shrink:0}.c2g-list-item__members{display:flex;align-items:center;gap:4px;font-size:13px;font-weight:500;color:var(--c2g-text-muted, #6b5e52);white-space:nowrap}.c2g-list-item__members mat-icon{font-size:16px;width:16px;height:16px}.c2g-list-item__open-btn{color:var(--c2g-text-muted, #6b5e52);transition:color .15s}.c2g-list-item__open-btn:hover{color:var(--c2g-primary, #16213e)}\n"] }]
|
|
142
|
+
}], propDecorators: { group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], opened: [{ type: i0.Output, args: ["opened"] }] } });
|
|
143
|
+
|
|
144
|
+
class StatCardComponent {
|
|
145
|
+
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
146
|
+
cardBackgroundStyle = computed(() => {
|
|
147
|
+
const background = this.data().background;
|
|
148
|
+
if (!background) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
if (background.type === 'gradient') {
|
|
152
|
+
return { backgroundImage: background.value };
|
|
153
|
+
}
|
|
154
|
+
const imageUrl = background.value.startsWith('url(')
|
|
155
|
+
? background.value
|
|
156
|
+
: `url('${background.value}')`;
|
|
157
|
+
const overlay = background.overlay ?? 'linear-gradient(rgba(0, 0, 0, 0.34), rgba(0, 0, 0, 0.34))';
|
|
158
|
+
return {
|
|
159
|
+
backgroundImage: `${overlay}, ${imageUrl}`,
|
|
160
|
+
backgroundSize: 'cover',
|
|
161
|
+
backgroundPosition: 'center',
|
|
162
|
+
backgroundRepeat: 'no-repeat',
|
|
163
|
+
};
|
|
164
|
+
}, ...(ngDevMode ? [{ debugName: "cardBackgroundStyle" }] : []));
|
|
165
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: StatCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
166
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: StatCardComponent, isStandalone: true, selector: "c2g-stat-card", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"stat-card\"\n [class]=\"'stat-card--' + (data().iconBackgroundTone || 'neutral')\"\n [class.stat-card--disabled]=\"data().disabled\"\n [class.stat-card--custom-bg]=\"!!data().background\"\n [ngStyle]=\"cardBackgroundStyle()\"\n>\n @if (data().lottiePreset) {\n <div class=\"stat-icon-wrapper stat-icon-wrapper--lottie\">\n <c2g-lottie-loader\n [preset]=\"data().lottiePreset!\"\n width=\"28px\"\n height=\"28px\"\n [showLabel]=\"false\"\n label=\"Animation\"\n ></c2g-lottie-loader>\n </div>\n } @else if (data().icon) {\n <div class=\"stat-icon-wrapper\">\n <mat-icon class=\"stat-icon\">{{ data().icon }}</mat-icon>\n </div>\n }\n\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ data().value }}</div>\n <div class=\"stat-label\">{{ data().label | translate }}</div>\n </div>\n\n @if (data().trend) {\n <div class=\"stat-trend\" [class]=\"'stat-trend--' + data().trend!.direction\">\n <mat-icon class=\"trend-icon\">\n @switch (data().trend!.direction) {\n @case ('up') {\n trending_up\n }\n @case ('down') {\n trending_down\n }\n @case ('neutral') {\n trending_flat\n }\n }\n </mat-icon>\n <span class=\"trend-value\">{{ data().trend!.value }}</span>\n </div>\n }\n</div>\n", styles: [".stat-card{display:flex;align-items:center;gap:var(--c2g-space-4, 1rem);min-height:5rem;padding:var(--c2g-space-5, 1.25rem);border:1px solid var(--c2g-color-border-subtle, #e5dfd7);border-radius:var(--c2g-radius-lg, 12px);background:var(--c2g-color-surface, #ffffff);opacity:1;transition:opacity .2s ease-in-out}.stat-card.stat-card--disabled{opacity:.5;pointer-events:none}.stat-card.stat-card--custom-bg{border-color:color-mix(in srgb,#ffffff 45%,transparent)}.stat-card.stat-card--custom-bg .stat-value,.stat-card.stat-card--custom-bg .stat-label{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.28)}.stat-card.stat-card--custom-bg .stat-icon-wrapper{background-color:#ffffff2e;border:1px solid rgba(255,255,255,.26);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.stat-card.stat-card--custom-bg .stat-icon{color:#fff}.stat-card.stat-card--custom-bg .stat-trend--up{color:#b9f6ca}.stat-card.stat-card--custom-bg .stat-trend--down{color:#ffccbc}.stat-card.stat-card--custom-bg .stat-trend--neutral{color:#eceff1}.stat-card--primary{border-left:4px solid var(--c2g-color-primary, #ff6b35)}.stat-card--primary .stat-value{color:var(--c2g-color-primary, #ff6b35)}.stat-card--primary .stat-icon-wrapper{background-color:color-mix(in srgb,var(--c2g-color-primary, #ff6b35) 10%,#ffffff)}.stat-card--primary .stat-icon{color:var(--c2g-color-primary, #ff6b35)}.stat-card--secondary{border-left:4px solid var(--c2g-color-secondary, #2c5f5d)}.stat-card--secondary .stat-value{color:var(--c2g-color-secondary, #2c5f5d)}.stat-card--secondary .stat-icon-wrapper{background-color:color-mix(in srgb,var(--c2g-color-secondary, #2c5f5d) 10%,#ffffff)}.stat-card--secondary .stat-icon{color:var(--c2g-color-secondary, #2c5f5d)}.stat-card--neutral{border-left:4px solid var(--c2g-color-border-subtle, #d0c6bb)}.stat-card--neutral .stat-value{color:var(--c2g-color-text-primary, #2f2925)}.stat-card--neutral .stat-icon-wrapper{background-color:var(--c2g-color-surface-subtle, #f7f3ef)}.stat-card--neutral .stat-icon{color:var(--c2g-color-text-secondary, #4a423b)}.stat-icon-wrapper{display:flex;align-items:center;justify-content:center;width:3rem;height:3rem;border-radius:var(--c2g-radius-md, 8px);flex-shrink:0}.stat-icon-wrapper--lottie c2g-lottie-loader{display:inline-flex}.stat-icon{font-size:1.5rem;width:1.5rem;height:1.5rem}.stat-content{display:flex;flex:1;flex-direction:column;gap:var(--c2g-space-1, .25rem)}.stat-value{font-size:var(--c2g-font-size-xl, 1.5rem);font-weight:var(--c2g-font-weight-bold, 700);line-height:1.2}.stat-label{color:var(--c2g-color-text-secondary, #4a423b);font-size:var(--c2g-font-size-sm, .875rem);font-weight:var(--c2g-font-weight-medium, 500)}.stat-trend{display:flex;align-items:center;gap:var(--c2g-space-1, .25rem)}.stat-trend--up{color:var(--c2g-color-success, #2e7d32)}.stat-trend--down{color:var(--c2g-color-danger, #c62828)}.stat-trend--neutral{color:var(--c2g-color-text-muted, #7a6f64)}.trend-icon{font-size:1rem;width:1rem;height:1rem}.trend-value{font-size:var(--c2g-font-size-xs, .75rem);font-weight:var(--c2g-font-weight-medium, 500)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: LottieLoaderComponent, selector: "c2g-lottie-loader", inputs: ["preset", "presetMode", "animationPath", "animationData", "loop", "autoplay", "width", "height", "label", "showLabel"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
167
|
+
}
|
|
168
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: StatCardComponent, decorators: [{
|
|
169
|
+
type: Component,
|
|
170
|
+
args: [{ selector: 'c2g-stat-card', standalone: true, imports: [CommonModule, MatIcon, TranslateModule, LottieLoaderComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"stat-card\"\n [class]=\"'stat-card--' + (data().iconBackgroundTone || 'neutral')\"\n [class.stat-card--disabled]=\"data().disabled\"\n [class.stat-card--custom-bg]=\"!!data().background\"\n [ngStyle]=\"cardBackgroundStyle()\"\n>\n @if (data().lottiePreset) {\n <div class=\"stat-icon-wrapper stat-icon-wrapper--lottie\">\n <c2g-lottie-loader\n [preset]=\"data().lottiePreset!\"\n width=\"28px\"\n height=\"28px\"\n [showLabel]=\"false\"\n label=\"Animation\"\n ></c2g-lottie-loader>\n </div>\n } @else if (data().icon) {\n <div class=\"stat-icon-wrapper\">\n <mat-icon class=\"stat-icon\">{{ data().icon }}</mat-icon>\n </div>\n }\n\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ data().value }}</div>\n <div class=\"stat-label\">{{ data().label | translate }}</div>\n </div>\n\n @if (data().trend) {\n <div class=\"stat-trend\" [class]=\"'stat-trend--' + data().trend!.direction\">\n <mat-icon class=\"trend-icon\">\n @switch (data().trend!.direction) {\n @case ('up') {\n trending_up\n }\n @case ('down') {\n trending_down\n }\n @case ('neutral') {\n trending_flat\n }\n }\n </mat-icon>\n <span class=\"trend-value\">{{ data().trend!.value }}</span>\n </div>\n }\n</div>\n", styles: [".stat-card{display:flex;align-items:center;gap:var(--c2g-space-4, 1rem);min-height:5rem;padding:var(--c2g-space-5, 1.25rem);border:1px solid var(--c2g-color-border-subtle, #e5dfd7);border-radius:var(--c2g-radius-lg, 12px);background:var(--c2g-color-surface, #ffffff);opacity:1;transition:opacity .2s ease-in-out}.stat-card.stat-card--disabled{opacity:.5;pointer-events:none}.stat-card.stat-card--custom-bg{border-color:color-mix(in srgb,#ffffff 45%,transparent)}.stat-card.stat-card--custom-bg .stat-value,.stat-card.stat-card--custom-bg .stat-label{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.28)}.stat-card.stat-card--custom-bg .stat-icon-wrapper{background-color:#ffffff2e;border:1px solid rgba(255,255,255,.26);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.stat-card.stat-card--custom-bg .stat-icon{color:#fff}.stat-card.stat-card--custom-bg .stat-trend--up{color:#b9f6ca}.stat-card.stat-card--custom-bg .stat-trend--down{color:#ffccbc}.stat-card.stat-card--custom-bg .stat-trend--neutral{color:#eceff1}.stat-card--primary{border-left:4px solid var(--c2g-color-primary, #ff6b35)}.stat-card--primary .stat-value{color:var(--c2g-color-primary, #ff6b35)}.stat-card--primary .stat-icon-wrapper{background-color:color-mix(in srgb,var(--c2g-color-primary, #ff6b35) 10%,#ffffff)}.stat-card--primary .stat-icon{color:var(--c2g-color-primary, #ff6b35)}.stat-card--secondary{border-left:4px solid var(--c2g-color-secondary, #2c5f5d)}.stat-card--secondary .stat-value{color:var(--c2g-color-secondary, #2c5f5d)}.stat-card--secondary .stat-icon-wrapper{background-color:color-mix(in srgb,var(--c2g-color-secondary, #2c5f5d) 10%,#ffffff)}.stat-card--secondary .stat-icon{color:var(--c2g-color-secondary, #2c5f5d)}.stat-card--neutral{border-left:4px solid var(--c2g-color-border-subtle, #d0c6bb)}.stat-card--neutral .stat-value{color:var(--c2g-color-text-primary, #2f2925)}.stat-card--neutral .stat-icon-wrapper{background-color:var(--c2g-color-surface-subtle, #f7f3ef)}.stat-card--neutral .stat-icon{color:var(--c2g-color-text-secondary, #4a423b)}.stat-icon-wrapper{display:flex;align-items:center;justify-content:center;width:3rem;height:3rem;border-radius:var(--c2g-radius-md, 8px);flex-shrink:0}.stat-icon-wrapper--lottie c2g-lottie-loader{display:inline-flex}.stat-icon{font-size:1.5rem;width:1.5rem;height:1.5rem}.stat-content{display:flex;flex:1;flex-direction:column;gap:var(--c2g-space-1, .25rem)}.stat-value{font-size:var(--c2g-font-size-xl, 1.5rem);font-weight:var(--c2g-font-weight-bold, 700);line-height:1.2}.stat-label{color:var(--c2g-color-text-secondary, #4a423b);font-size:var(--c2g-font-size-sm, .875rem);font-weight:var(--c2g-font-weight-medium, 500)}.stat-trend{display:flex;align-items:center;gap:var(--c2g-space-1, .25rem)}.stat-trend--up{color:var(--c2g-color-success, #2e7d32)}.stat-trend--down{color:var(--c2g-color-danger, #c62828)}.stat-trend--neutral{color:var(--c2g-color-text-muted, #7a6f64)}.trend-icon{font-size:1rem;width:1rem;height:1rem}.trend-value{font-size:var(--c2g-font-size-xs, .75rem);font-weight:var(--c2g-font-weight-medium, 500)}\n"] }]
|
|
171
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }] } });
|
|
172
|
+
|
|
173
|
+
class ActionCardComponent {
|
|
174
|
+
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
175
|
+
clickable = input(true, ...(ngDevMode ? [{ debugName: "clickable" }] : []));
|
|
176
|
+
variant = input('icon-left', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
177
|
+
cardClicked = output();
|
|
178
|
+
effectiveText = computed(() => this.data().text ?? this.data().description ?? '', ...(ngDevMode ? [{ debugName: "effectiveText" }] : []));
|
|
179
|
+
supportingDescription = computed(() => {
|
|
180
|
+
const d = this.data();
|
|
181
|
+
return d.text ? (d.description ?? '') : '';
|
|
182
|
+
}, ...(ngDevMode ? [{ debugName: "supportingDescription" }] : []));
|
|
183
|
+
isInteractive = computed(() => this.clickable() && !this.data().disabled, ...(ngDevMode ? [{ debugName: "isInteractive" }] : []));
|
|
184
|
+
iconToneClass = computed(() => this.data().iconBackgroundTone ?? 'neutral', ...(ngDevMode ? [{ debugName: "iconToneClass" }] : []));
|
|
185
|
+
onCardClick() {
|
|
186
|
+
if (this.isInteractive()) {
|
|
187
|
+
this.cardClicked.emit();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
onKeyDown(event) {
|
|
191
|
+
if (!this.isInteractive()) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
195
|
+
event.preventDefault();
|
|
196
|
+
this.cardClicked.emit();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ActionCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
200
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ActionCardComponent, isStandalone: true, selector: "c2g-action-card", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cardClicked: "cardClicked" }, ngImport: i0, template: "<mat-card\n class=\"action-card\"\n [class.clickable]=\"isInteractive()\"\n [class.disabled]=\"data().disabled\"\n [class.variant-icon-left]=\"variant() === 'icon-left'\"\n [class.variant-hero-top]=\"variant() === 'hero-top'\"\n [class.variant-icon-detail]=\"variant() === 'icon-detail'\"\n (click)=\"onCardClick()\"\n (keydown)=\"onKeyDown($event)\"\n [attr.role]=\"isInteractive() ? 'button' : null\"\n [attr.tabindex]=\"isInteractive() ? '0' : null\">\n\n @if (variant() === 'hero-top') {\n <div class=\"hero-top-header\" [class.has-image]=\"data().image || data().lottiePreset\">\n @if (data().lottiePreset) {\n <div class=\"hero-image hero-image--lottie\">\n <c2g-lottie-loader\n [preset]=\"data().lottiePreset!\"\n [showLabel]=\"false\"\n width=\"100%\"\n height=\"100%\"\n ></c2g-lottie-loader>\n </div>\n } @else if (data().image) {\n <div class=\"hero-image\">\n <img [src]=\"data().image\" [alt]=\"data().title | translate\" />\n </div>\n }\n\n <div class=\"hero-top-title-wrap\">\n <h3 class=\"hero-top-title\">{{ data().title | translate }}</h3>\n @if (effectiveText()) {\n <p class=\"hero-top-description\">{{ effectiveText() | translate }}</p>\n }\n </div>\n </div>\n } @else if (variant() === 'icon-detail') {\n <div class=\"icon-detail-layout\">\n @if (data().icon) {\n <div class=\"icon-chip\" [ngClass]=\"iconToneClass()\">\n <mat-icon class=\"hero-icon\">{{ data().icon }}</mat-icon>\n </div>\n }\n <div class=\"icon-detail-body\">\n <h3 class=\"hero-title\">{{ data().title | translate }}</h3>\n @if (effectiveText()) {\n <p class=\"hero-description\">{{ effectiveText() | translate }}</p>\n }\n <div class=\"icon-detail-cta\" (click)=\"$event.stopPropagation()\">\n @if (data().ctaLabel) {\n <c2g-button variant=\"ghost\" size=\"sm\">{{ data().ctaLabel! | translate }}</c2g-button>\n }\n <ng-content select=\"[ctas]\"></ng-content>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"icon-left-header\">\n @if (data().icon) {\n <div class=\"icon-chip\" [ngClass]=\"iconToneClass()\">\n <mat-icon class=\"hero-icon\">{{ data().icon }}</mat-icon>\n </div>\n }\n\n <div class=\"icon-left-title-wrap\">\n <h3 class=\"hero-title\">{{ data().title | translate }}</h3>\n </div>\n </div>\n }\n\n @if (variant() !== 'icon-detail') {\n <div class=\"content-section\">\n @if (variant() !== 'hero-top' && effectiveText()) {\n <p class=\"hero-description\">{{ effectiveText() | translate }}</p>\n }\n\n @if (supportingDescription()) {\n <p class=\"hero-description supporting\">{{ supportingDescription() | translate }}</p>\n }\n\n <ng-content></ng-content>\n </div>\n }\n\n @if (variant() !== 'icon-detail') {\n <div class=\"cta-section\" (click)=\"$event.stopPropagation()\">\n @if (data().ctaLabel) {\n <c2g-button variant=\"ghost\" size=\"sm\">{{ data().ctaLabel! | translate }}</c2g-button>\n }\n\n <ng-content select=\"[ctas]\"></ng-content>\n </div>\n }\n\n</mat-card>\n", styles: [".action-card{border-radius:var(--c2g-radius-lg);overflow:hidden;transition:all var(--c2g-transition-fast);box-shadow:var(--c2g-shadow-sm);background-color:var(--c2g-neutral-50);border:1px solid var(--c2g-neutral-300);display:flex;flex-direction:column;min-height:100%}.action-card.clickable{cursor:pointer}.action-card.clickable:hover{transform:translateY(-2px);box-shadow:var(--c2g-shadow-md)}.action-card.disabled{opacity:.6;cursor:not-allowed}.action-card.disabled:hover{transform:none;box-shadow:var(--c2g-shadow-sm)}.action-card.variant-hero-top .hero-top-header{min-height:132px}.icon-left-header{display:flex;align-items:center;gap:var(--c2g-space-md);padding:var(--c2g-space-lg)}.icon-detail-layout{display:flex;flex-direction:row;align-items:flex-start;gap:var(--c2g-space-md);padding:var(--c2g-space-lg);flex:1}.icon-detail-body{display:flex;flex-direction:column;flex:1;min-width:0}.icon-detail-cta{display:flex;justify-content:flex-end;margin-top:auto;padding-top:var(--c2g-space-sm)}.icon-chip{width:48px;height:48px;border-radius:var(--c2g-radius-md);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.icon-chip.primary{background:var(--c2g-primary);color:var(--c2g-neutral-50)}.icon-chip.secondary{background:var(--c2g-secondary);color:var(--c2g-neutral-50)}.icon-chip.neutral{background:var(--c2g-neutral-200);color:var(--c2g-neutral-900)}.hero-icon{display:inline-flex!important;align-items:center;justify-content:center;font-size:24px;width:24px;height:24px;vertical-align:middle;flex-shrink:0}.icon-left-title-wrap{min-width:0}.hero-top-header{position:relative;min-height:120px;display:flex;align-items:flex-end;justify-content:flex-end;padding:var(--c2g-space-lg);background:linear-gradient(135deg,var(--c2g-primary-light) 0%,var(--c2g-secondary-light) 100%)}@media(min-width:768px){.hero-top-header{min-height:140px}}.hero-top-header.has-image .hero-top-title-wrap{background:#1f1c199e;border-radius:var(--c2g-radius-sm);padding:var(--c2g-space-sm) var(--c2g-space-md);z-index:1}.hero-top-header.has-image .hero-top-title{color:var(--c2g-neutral-50)}.hero-top-header.has-image .hero-top-description{color:#fffc}.hero-image{position:absolute;top:0;left:0;width:100%;height:120px;overflow:hidden}.hero-image img{width:100%;height:100%;object-fit:cover}@media(min-width:768px){.hero-image{height:140px}}.hero-top-title{margin:0;font-size:16px;font-weight:600;line-height:1.3;color:var(--c2g-neutral-50)}@media(min-width:768px){.hero-top-title{font-size:18px}}.hero-top-description{margin:2px 0 0;font-size:12px;font-weight:500;line-height:1.3;color:#ffffffbf}.hero-title{margin:0;font-size:16px;font-weight:600;line-height:1.3}@media(min-width:768px){.hero-title{font-size:18px}}.content-section{display:flex;flex-direction:column;gap:var(--c2g-space-sm);flex:1}.content-section:empty{display:none}.content-section:not(:empty){padding:var(--c2g-space-lg)}.cta-section:empty{display:none}.cta-section:not(:empty){padding:var(--c2g-space-sm) var(--c2g-space-lg) var(--c2g-space-lg);display:flex;gap:var(--c2g-space-sm);justify-content:flex-start;align-items:center}.cta-section:not(:empty) button mat-icon{display:inline-flex!important;align-items:center;justify-content:center;line-height:1!important;vertical-align:middle;font-size:20px;width:20px;height:20px}.hero-description{margin:0;font-size:14px;line-height:1.4;opacity:.8;color:var(--c2g-neutral-700)}@media(min-width:768px){.hero-description{font-size:15px}}.hero-description.supporting{color:var(--c2g-neutral-600)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ButtonComponent, selector: "c2g-button", inputs: ["variant", "size", "disabled", "loading", "icon", "iconPosition", "iconOnly", "ariaLabel", "loadingAriaLabel", "type"], outputs: ["clicked"] }, { kind: "component", type: LottieLoaderComponent, selector: "c2g-lottie-loader", inputs: ["preset", "presetMode", "animationPath", "animationData", "loop", "autoplay", "width", "height", "label", "showLabel"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
201
|
+
}
|
|
202
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ActionCardComponent, decorators: [{
|
|
203
|
+
type: Component,
|
|
204
|
+
args: [{ selector: 'c2g-action-card', standalone: true, imports: [
|
|
205
|
+
CommonModule,
|
|
206
|
+
TranslateModule,
|
|
207
|
+
MatCard,
|
|
208
|
+
MatIcon,
|
|
209
|
+
ButtonComponent,
|
|
210
|
+
LottieLoaderComponent
|
|
211
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-card\n class=\"action-card\"\n [class.clickable]=\"isInteractive()\"\n [class.disabled]=\"data().disabled\"\n [class.variant-icon-left]=\"variant() === 'icon-left'\"\n [class.variant-hero-top]=\"variant() === 'hero-top'\"\n [class.variant-icon-detail]=\"variant() === 'icon-detail'\"\n (click)=\"onCardClick()\"\n (keydown)=\"onKeyDown($event)\"\n [attr.role]=\"isInteractive() ? 'button' : null\"\n [attr.tabindex]=\"isInteractive() ? '0' : null\">\n\n @if (variant() === 'hero-top') {\n <div class=\"hero-top-header\" [class.has-image]=\"data().image || data().lottiePreset\">\n @if (data().lottiePreset) {\n <div class=\"hero-image hero-image--lottie\">\n <c2g-lottie-loader\n [preset]=\"data().lottiePreset!\"\n [showLabel]=\"false\"\n width=\"100%\"\n height=\"100%\"\n ></c2g-lottie-loader>\n </div>\n } @else if (data().image) {\n <div class=\"hero-image\">\n <img [src]=\"data().image\" [alt]=\"data().title | translate\" />\n </div>\n }\n\n <div class=\"hero-top-title-wrap\">\n <h3 class=\"hero-top-title\">{{ data().title | translate }}</h3>\n @if (effectiveText()) {\n <p class=\"hero-top-description\">{{ effectiveText() | translate }}</p>\n }\n </div>\n </div>\n } @else if (variant() === 'icon-detail') {\n <div class=\"icon-detail-layout\">\n @if (data().icon) {\n <div class=\"icon-chip\" [ngClass]=\"iconToneClass()\">\n <mat-icon class=\"hero-icon\">{{ data().icon }}</mat-icon>\n </div>\n }\n <div class=\"icon-detail-body\">\n <h3 class=\"hero-title\">{{ data().title | translate }}</h3>\n @if (effectiveText()) {\n <p class=\"hero-description\">{{ effectiveText() | translate }}</p>\n }\n <div class=\"icon-detail-cta\" (click)=\"$event.stopPropagation()\">\n @if (data().ctaLabel) {\n <c2g-button variant=\"ghost\" size=\"sm\">{{ data().ctaLabel! | translate }}</c2g-button>\n }\n <ng-content select=\"[ctas]\"></ng-content>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"icon-left-header\">\n @if (data().icon) {\n <div class=\"icon-chip\" [ngClass]=\"iconToneClass()\">\n <mat-icon class=\"hero-icon\">{{ data().icon }}</mat-icon>\n </div>\n }\n\n <div class=\"icon-left-title-wrap\">\n <h3 class=\"hero-title\">{{ data().title | translate }}</h3>\n </div>\n </div>\n }\n\n @if (variant() !== 'icon-detail') {\n <div class=\"content-section\">\n @if (variant() !== 'hero-top' && effectiveText()) {\n <p class=\"hero-description\">{{ effectiveText() | translate }}</p>\n }\n\n @if (supportingDescription()) {\n <p class=\"hero-description supporting\">{{ supportingDescription() | translate }}</p>\n }\n\n <ng-content></ng-content>\n </div>\n }\n\n @if (variant() !== 'icon-detail') {\n <div class=\"cta-section\" (click)=\"$event.stopPropagation()\">\n @if (data().ctaLabel) {\n <c2g-button variant=\"ghost\" size=\"sm\">{{ data().ctaLabel! | translate }}</c2g-button>\n }\n\n <ng-content select=\"[ctas]\"></ng-content>\n </div>\n }\n\n</mat-card>\n", styles: [".action-card{border-radius:var(--c2g-radius-lg);overflow:hidden;transition:all var(--c2g-transition-fast);box-shadow:var(--c2g-shadow-sm);background-color:var(--c2g-neutral-50);border:1px solid var(--c2g-neutral-300);display:flex;flex-direction:column;min-height:100%}.action-card.clickable{cursor:pointer}.action-card.clickable:hover{transform:translateY(-2px);box-shadow:var(--c2g-shadow-md)}.action-card.disabled{opacity:.6;cursor:not-allowed}.action-card.disabled:hover{transform:none;box-shadow:var(--c2g-shadow-sm)}.action-card.variant-hero-top .hero-top-header{min-height:132px}.icon-left-header{display:flex;align-items:center;gap:var(--c2g-space-md);padding:var(--c2g-space-lg)}.icon-detail-layout{display:flex;flex-direction:row;align-items:flex-start;gap:var(--c2g-space-md);padding:var(--c2g-space-lg);flex:1}.icon-detail-body{display:flex;flex-direction:column;flex:1;min-width:0}.icon-detail-cta{display:flex;justify-content:flex-end;margin-top:auto;padding-top:var(--c2g-space-sm)}.icon-chip{width:48px;height:48px;border-radius:var(--c2g-radius-md);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.icon-chip.primary{background:var(--c2g-primary);color:var(--c2g-neutral-50)}.icon-chip.secondary{background:var(--c2g-secondary);color:var(--c2g-neutral-50)}.icon-chip.neutral{background:var(--c2g-neutral-200);color:var(--c2g-neutral-900)}.hero-icon{display:inline-flex!important;align-items:center;justify-content:center;font-size:24px;width:24px;height:24px;vertical-align:middle;flex-shrink:0}.icon-left-title-wrap{min-width:0}.hero-top-header{position:relative;min-height:120px;display:flex;align-items:flex-end;justify-content:flex-end;padding:var(--c2g-space-lg);background:linear-gradient(135deg,var(--c2g-primary-light) 0%,var(--c2g-secondary-light) 100%)}@media(min-width:768px){.hero-top-header{min-height:140px}}.hero-top-header.has-image .hero-top-title-wrap{background:#1f1c199e;border-radius:var(--c2g-radius-sm);padding:var(--c2g-space-sm) var(--c2g-space-md);z-index:1}.hero-top-header.has-image .hero-top-title{color:var(--c2g-neutral-50)}.hero-top-header.has-image .hero-top-description{color:#fffc}.hero-image{position:absolute;top:0;left:0;width:100%;height:120px;overflow:hidden}.hero-image img{width:100%;height:100%;object-fit:cover}@media(min-width:768px){.hero-image{height:140px}}.hero-top-title{margin:0;font-size:16px;font-weight:600;line-height:1.3;color:var(--c2g-neutral-50)}@media(min-width:768px){.hero-top-title{font-size:18px}}.hero-top-description{margin:2px 0 0;font-size:12px;font-weight:500;line-height:1.3;color:#ffffffbf}.hero-title{margin:0;font-size:16px;font-weight:600;line-height:1.3}@media(min-width:768px){.hero-title{font-size:18px}}.content-section{display:flex;flex-direction:column;gap:var(--c2g-space-sm);flex:1}.content-section:empty{display:none}.content-section:not(:empty){padding:var(--c2g-space-lg)}.cta-section:empty{display:none}.cta-section:not(:empty){padding:var(--c2g-space-sm) var(--c2g-space-lg) var(--c2g-space-lg);display:flex;gap:var(--c2g-space-sm);justify-content:flex-start;align-items:center}.cta-section:not(:empty) button mat-icon{display:inline-flex!important;align-items:center;justify-content:center;line-height:1!important;vertical-align:middle;font-size:20px;width:20px;height:20px}.hero-description{margin:0;font-size:14px;line-height:1.4;opacity:.8;color:var(--c2g-neutral-700)}@media(min-width:768px){.hero-description{font-size:15px}}.hero-description.supporting{color:var(--c2g-neutral-600)}\n"] }]
|
|
212
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], cardClicked: [{ type: i0.Output, args: ["cardClicked"] }] } });
|
|
213
|
+
|
|
214
|
+
class ViewToggleComponent {
|
|
215
|
+
options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
216
|
+
activeValue = input(null, ...(ngDevMode ? [{ debugName: "activeValue" }] : []));
|
|
217
|
+
valueChange = output();
|
|
218
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ViewToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
219
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: ViewToggleComponent, isStandalone: true, selector: "app-view-toggle", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, activeValue: { classPropertyName: "activeValue", publicName: "activeValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"view-toggle\" role=\"group\">\n @for (option of options(); track option.value) {\n <button\n mat-icon-button\n [class.active]=\"activeValue() === option.value\"\n (click)=\"valueChange.emit(option.value)\"\n [matTooltip]=\"option.label | translate\"\n [attr.aria-label]=\"option.label | translate\"\n [attr.aria-pressed]=\"activeValue() === option.value\"\n >\n <mat-icon>{{ option.icon }}</mat-icon>\n </button>\n }\n</div>\n", styles: [".view-toggle{display:flex;border:1px solid var(--c2g-color-border-subtle, rgba(17, 24, 39, .12));border-radius:var(--c2g-radius-md, .625rem);overflow:hidden;background:var(--c2g-glass-bg, rgba(255, 255, 255, .95))}.view-toggle button{border-radius:0!important;min-width:2.5rem;width:2.5rem;height:2.5rem;padding:0;border-right:1px solid var(--c2g-color-border-soft, rgba(17, 24, 39, .08));display:flex;align-items:center;justify-content:center;transition:background-color var(--c2g-motion-duration-base, .2s) var(--c2g-motion-ease-standard, ease)}.view-toggle button:last-child{border-right:none}.view-toggle button.active{background:color-mix(in srgb,var(--c2g-color-text-primary) 8%,transparent)}.view-toggle button:hover:not(.active){background:color-mix(in srgb,var(--c2g-color-text-primary) 4%,transparent)}.view-toggle button mat-icon{display:flex;align-items:center;justify-content:center;font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
220
|
+
}
|
|
221
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ViewToggleComponent, decorators: [{
|
|
222
|
+
type: Component,
|
|
223
|
+
args: [{ selector: 'app-view-toggle', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
224
|
+
MatIconModule,
|
|
225
|
+
MatButtonModule,
|
|
226
|
+
MatTooltipModule,
|
|
227
|
+
TranslateModule
|
|
228
|
+
], template: "<div class=\"view-toggle\" role=\"group\">\n @for (option of options(); track option.value) {\n <button\n mat-icon-button\n [class.active]=\"activeValue() === option.value\"\n (click)=\"valueChange.emit(option.value)\"\n [matTooltip]=\"option.label | translate\"\n [attr.aria-label]=\"option.label | translate\"\n [attr.aria-pressed]=\"activeValue() === option.value\"\n >\n <mat-icon>{{ option.icon }}</mat-icon>\n </button>\n }\n</div>\n", styles: [".view-toggle{display:flex;border:1px solid var(--c2g-color-border-subtle, rgba(17, 24, 39, .12));border-radius:var(--c2g-radius-md, .625rem);overflow:hidden;background:var(--c2g-glass-bg, rgba(255, 255, 255, .95))}.view-toggle button{border-radius:0!important;min-width:2.5rem;width:2.5rem;height:2.5rem;padding:0;border-right:1px solid var(--c2g-color-border-soft, rgba(17, 24, 39, .08));display:flex;align-items:center;justify-content:center;transition:background-color var(--c2g-motion-duration-base, .2s) var(--c2g-motion-ease-standard, ease)}.view-toggle button:last-child{border-right:none}.view-toggle button.active{background:color-mix(in srgb,var(--c2g-color-text-primary) 8%,transparent)}.view-toggle button:hover:not(.active){background:color-mix(in srgb,var(--c2g-color-text-primary) 4%,transparent)}.view-toggle button mat-icon{display:flex;align-items:center;justify-content:center;font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem}\n"] }]
|
|
229
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], activeValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeValue", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
230
|
+
|
|
231
|
+
class SegmentedToggleComponent {
|
|
232
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
233
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
234
|
+
ariaLabel = input('Auswahl', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
235
|
+
iconOnly = input(false, ...(ngDevMode ? [{ debugName: "iconOnly" }] : []));
|
|
236
|
+
valueChange = output();
|
|
237
|
+
value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
238
|
+
cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : []));
|
|
239
|
+
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
240
|
+
onChange = () => { };
|
|
241
|
+
onTouched = () => { };
|
|
242
|
+
writeValue(value) {
|
|
243
|
+
this.value.set(value);
|
|
244
|
+
}
|
|
245
|
+
registerOnChange(fn) {
|
|
246
|
+
this.onChange = fn;
|
|
247
|
+
}
|
|
248
|
+
registerOnTouched(fn) {
|
|
249
|
+
this.onTouched = fn;
|
|
250
|
+
}
|
|
251
|
+
setDisabledState(isDisabled) {
|
|
252
|
+
this.cvaDisabled.set(isDisabled);
|
|
253
|
+
}
|
|
254
|
+
tabIndexFor(option) {
|
|
255
|
+
if (this.value() === option) {
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
if (this.value() === null && this.options()[0]?.value === option) {
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
return -1;
|
|
262
|
+
}
|
|
263
|
+
select(next) {
|
|
264
|
+
if (this.isDisabled()) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
this.value.set(next);
|
|
268
|
+
this.onChange(next);
|
|
269
|
+
this.valueChange.emit(next);
|
|
270
|
+
this.onTouched();
|
|
271
|
+
}
|
|
272
|
+
onKeydown(event, index) {
|
|
273
|
+
if (event.key !== 'ArrowRight' &&
|
|
274
|
+
event.key !== 'ArrowLeft' &&
|
|
275
|
+
event.key !== 'ArrowUp' &&
|
|
276
|
+
event.key !== 'ArrowDown' &&
|
|
277
|
+
event.key !== 'Home' &&
|
|
278
|
+
event.key !== 'End') {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
event.preventDefault();
|
|
282
|
+
const enabled = this.options().filter((option) => !option.disabled);
|
|
283
|
+
if (enabled.length === 0) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (event.key === 'Home') {
|
|
287
|
+
const next = enabled[0].value;
|
|
288
|
+
this.select(next);
|
|
289
|
+
this.focusValue(next, event.currentTarget);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (event.key === 'End') {
|
|
293
|
+
const next = enabled[enabled.length - 1].value;
|
|
294
|
+
this.select(next);
|
|
295
|
+
this.focusValue(next, event.currentTarget);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const selectedValue = this.value();
|
|
299
|
+
const fallbackValue = this.options()[index]?.value ?? null;
|
|
300
|
+
const baseValue = selectedValue ?? fallbackValue;
|
|
301
|
+
const currentEnabledIndex = enabled.findIndex((option) => option.value === baseValue);
|
|
302
|
+
const start = currentEnabledIndex >= 0 ? currentEnabledIndex : 0;
|
|
303
|
+
const delta = event.key === 'ArrowRight' || event.key === 'ArrowDown' ? 1 : -1;
|
|
304
|
+
const nextIndex = (start + delta + enabled.length) % enabled.length;
|
|
305
|
+
const next = enabled[nextIndex].value;
|
|
306
|
+
this.select(next);
|
|
307
|
+
this.focusValue(next, event.currentTarget);
|
|
308
|
+
}
|
|
309
|
+
focusValue(next, eventTarget) {
|
|
310
|
+
const trigger = eventTarget instanceof HTMLElement ? eventTarget : null;
|
|
311
|
+
const root = trigger?.closest('.c2g-segmented');
|
|
312
|
+
const allButtons = root?.querySelectorAll('button[role="radio"]');
|
|
313
|
+
if (!allButtons) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const optionIndex = this.options().findIndex((option) => option.value === next);
|
|
317
|
+
if (optionIndex >= 0) {
|
|
318
|
+
allButtons[optionIndex]?.focus();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SegmentedToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
322
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: SegmentedToggleComponent, isStandalone: true, selector: "c2g-segmented-toggle", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, providers: [
|
|
323
|
+
{
|
|
324
|
+
provide: NG_VALUE_ACCESSOR,
|
|
325
|
+
useExisting: forwardRef(() => SegmentedToggleComponent),
|
|
326
|
+
multi: true,
|
|
327
|
+
},
|
|
328
|
+
], ngImport: i0, template: `
|
|
329
|
+
<div class="c2g-segmented" role="radiogroup" [attr.aria-label]="ariaLabel()">
|
|
330
|
+
@for (option of options(); track option.value; let index = $index) {
|
|
331
|
+
<button
|
|
332
|
+
type="button"
|
|
333
|
+
role="radio"
|
|
334
|
+
class="c2g-segmented__item"
|
|
335
|
+
[class.c2g-segmented__item--active]="value() === option.value"
|
|
336
|
+
[attr.aria-checked]="value() === option.value ? 'true' : 'false'"
|
|
337
|
+
[disabled]="isDisabled() || !!option.disabled"
|
|
338
|
+
[attr.tabindex]="tabIndexFor(option.value)"
|
|
339
|
+
(click)="select(option.value)"
|
|
340
|
+
(keydown)="onKeydown($event, index)"
|
|
341
|
+
>
|
|
342
|
+
@if (option.icon || option.iconFontIcon) {
|
|
343
|
+
<mat-icon
|
|
344
|
+
class="c2g-segmented__icon"
|
|
345
|
+
[fontSet]="option.iconFontSet || ''"
|
|
346
|
+
[fontIcon]="option.iconFontIcon || ''"
|
|
347
|
+
[attr.aria-label]="option.iconAriaLabel || null"
|
|
348
|
+
[attr.aria-hidden]="option.iconAriaLabel ? null : 'true'"
|
|
349
|
+
>
|
|
350
|
+
{{ option.icon || '' }}
|
|
351
|
+
</mat-icon>
|
|
352
|
+
}
|
|
353
|
+
<span [class.c2g-segmented__sr-only]="iconOnly()">{{ option.label }}</span>
|
|
354
|
+
</button>
|
|
355
|
+
}
|
|
356
|
+
</div>
|
|
357
|
+
`, isInline: true, styles: [".c2g-segmented{display:inline-flex;align-items:center;border:1px solid var(--c2g-color-border-subtle, rgba(74, 66, 59, .18));border-radius:var(--c2g-radius-md, .625rem);padding:var(--c2g-space-1, .25rem);background:var(--c2g-color-surface, #ffffff);gap:var(--c2g-space-1, .25rem);font-family:var(--c2g-font-family-base, \"Quicksand\", \"Segoe UI\", sans-serif)}.c2g-segmented__item{border:none;background:transparent;border-radius:var(--c2g-radius-sm, .375rem);padding:var(--c2g-space-2, .5rem) var(--c2g-space-3, .75rem);display:inline-flex;align-items:center;gap:var(--c2g-space-2, .5rem);font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-color-text-secondary, #4a423b);cursor:pointer;transition:all var(--c2g-motion-duration-fast, .12s) var(--c2g-motion-ease-standard, ease)}.c2g-segmented__icon{display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;font-size:.875rem;line-height:1}.c2g-segmented__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.c2g-segmented__item--active{background:var(--c2g-color-primary, #ff6b35);color:var(--c2g-color-text-primary, #1a1714);font-weight:var(--c2g-font-weight-semibold, 600)}.c2g-segmented__item:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--c2g-color-focus, #e55623) 24%,transparent)}.c2g-segmented__item:disabled{cursor:not-allowed;opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
358
|
+
}
|
|
359
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SegmentedToggleComponent, decorators: [{
|
|
360
|
+
type: Component,
|
|
361
|
+
args: [{ selector: 'c2g-segmented-toggle', standalone: true, imports: [MatIconModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
362
|
+
{
|
|
363
|
+
provide: NG_VALUE_ACCESSOR,
|
|
364
|
+
useExisting: forwardRef(() => SegmentedToggleComponent),
|
|
365
|
+
multi: true,
|
|
366
|
+
},
|
|
367
|
+
], template: `
|
|
368
|
+
<div class="c2g-segmented" role="radiogroup" [attr.aria-label]="ariaLabel()">
|
|
369
|
+
@for (option of options(); track option.value; let index = $index) {
|
|
370
|
+
<button
|
|
371
|
+
type="button"
|
|
372
|
+
role="radio"
|
|
373
|
+
class="c2g-segmented__item"
|
|
374
|
+
[class.c2g-segmented__item--active]="value() === option.value"
|
|
375
|
+
[attr.aria-checked]="value() === option.value ? 'true' : 'false'"
|
|
376
|
+
[disabled]="isDisabled() || !!option.disabled"
|
|
377
|
+
[attr.tabindex]="tabIndexFor(option.value)"
|
|
378
|
+
(click)="select(option.value)"
|
|
379
|
+
(keydown)="onKeydown($event, index)"
|
|
380
|
+
>
|
|
381
|
+
@if (option.icon || option.iconFontIcon) {
|
|
382
|
+
<mat-icon
|
|
383
|
+
class="c2g-segmented__icon"
|
|
384
|
+
[fontSet]="option.iconFontSet || ''"
|
|
385
|
+
[fontIcon]="option.iconFontIcon || ''"
|
|
386
|
+
[attr.aria-label]="option.iconAriaLabel || null"
|
|
387
|
+
[attr.aria-hidden]="option.iconAriaLabel ? null : 'true'"
|
|
388
|
+
>
|
|
389
|
+
{{ option.icon || '' }}
|
|
390
|
+
</mat-icon>
|
|
391
|
+
}
|
|
392
|
+
<span [class.c2g-segmented__sr-only]="iconOnly()">{{ option.label }}</span>
|
|
393
|
+
</button>
|
|
394
|
+
}
|
|
395
|
+
</div>
|
|
396
|
+
`, styles: [".c2g-segmented{display:inline-flex;align-items:center;border:1px solid var(--c2g-color-border-subtle, rgba(74, 66, 59, .18));border-radius:var(--c2g-radius-md, .625rem);padding:var(--c2g-space-1, .25rem);background:var(--c2g-color-surface, #ffffff);gap:var(--c2g-space-1, .25rem);font-family:var(--c2g-font-family-base, \"Quicksand\", \"Segoe UI\", sans-serif)}.c2g-segmented__item{border:none;background:transparent;border-radius:var(--c2g-radius-sm, .375rem);padding:var(--c2g-space-2, .5rem) var(--c2g-space-3, .75rem);display:inline-flex;align-items:center;gap:var(--c2g-space-2, .5rem);font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-color-text-secondary, #4a423b);cursor:pointer;transition:all var(--c2g-motion-duration-fast, .12s) var(--c2g-motion-ease-standard, ease)}.c2g-segmented__icon{display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;font-size:.875rem;line-height:1}.c2g-segmented__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.c2g-segmented__item--active{background:var(--c2g-color-primary, #ff6b35);color:var(--c2g-color-text-primary, #1a1714);font-weight:var(--c2g-font-weight-semibold, 600)}.c2g-segmented__item:focus-visible{outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--c2g-color-focus, #e55623) 24%,transparent)}.c2g-segmented__item:disabled{cursor:not-allowed;opacity:.5}\n"] }]
|
|
397
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
398
|
+
|
|
399
|
+
class SearchInputComponent {
|
|
400
|
+
searchChange = output();
|
|
401
|
+
onInput(event) {
|
|
402
|
+
const inputEl = event.target;
|
|
403
|
+
this.searchChange.emit(inputEl.value);
|
|
404
|
+
}
|
|
405
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
406
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: SearchInputComponent, isStandalone: true, selector: "app-search-input", outputs: { searchChange: "searchChange" }, ngImport: i0, template: "<div class=\"search-input\">\n <mat-icon class=\"search-input__icon\">search</mat-icon>\n <input\n class=\"search-input__field\"\n type=\"text\"\n [placeholder]=\"'equipment.workspace.search' | translate\"\n [attr.aria-label]=\"'equipment.workspace.search' | translate\"\n (input)=\"onInput($event)\"\n />\n</div>\n", styles: [".search-input{display:flex;align-items:center;gap:var(--c2g-space-2, .5rem);background:var(--c2g-glass-bg, rgba(255, 255, 255, .95));border:1px solid var(--c2g-color-border-subtle, rgba(17, 24, 39, .12));border-radius:var(--c2g-radius-lg, .75rem);padding:0 var(--spacing-3, .75rem);height:2.75rem;flex:1;box-shadow:var(--c2g-shadow-sm, 0 1px 2px rgba(15, 23, 42, .08))}.search-input__icon{font-size:1.25rem;width:1.25rem;height:1.25rem;color:var(--c2g-text-muted, #6b7280);flex-shrink:0}.search-input__field{flex:1;border:none;outline:none;background:transparent;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-text-primary, #1f2937)}.search-input__field::placeholder{color:var(--c2g-text-muted, #6b7280)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
407
|
+
}
|
|
408
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SearchInputComponent, decorators: [{
|
|
409
|
+
type: Component,
|
|
410
|
+
args: [{ selector: 'app-search-input', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
411
|
+
MatIconModule,
|
|
412
|
+
TranslateModule
|
|
413
|
+
], template: "<div class=\"search-input\">\n <mat-icon class=\"search-input__icon\">search</mat-icon>\n <input\n class=\"search-input__field\"\n type=\"text\"\n [placeholder]=\"'equipment.workspace.search' | translate\"\n [attr.aria-label]=\"'equipment.workspace.search' | translate\"\n (input)=\"onInput($event)\"\n />\n</div>\n", styles: [".search-input{display:flex;align-items:center;gap:var(--c2g-space-2, .5rem);background:var(--c2g-glass-bg, rgba(255, 255, 255, .95));border:1px solid var(--c2g-color-border-subtle, rgba(17, 24, 39, .12));border-radius:var(--c2g-radius-lg, .75rem);padding:0 var(--spacing-3, .75rem);height:2.75rem;flex:1;box-shadow:var(--c2g-shadow-sm, 0 1px 2px rgba(15, 23, 42, .08))}.search-input__icon{font-size:1.25rem;width:1.25rem;height:1.25rem;color:var(--c2g-text-muted, #6b7280);flex-shrink:0}.search-input__field{flex:1;border:none;outline:none;background:transparent;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-text-primary, #1f2937)}.search-input__field::placeholder{color:var(--c2g-text-muted, #6b7280)}\n"] }]
|
|
414
|
+
}], propDecorators: { searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
|
|
415
|
+
|
|
416
|
+
class EmptyStateComponent {
|
|
417
|
+
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
418
|
+
actionClicked = output();
|
|
419
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
420
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: EmptyStateComponent, isStandalone: true, selector: "c2g-empty-state", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionClicked: "actionClicked" }, ngImport: i0, template: "<div class=\"c2g-empty-state\">\n @if (data().lottiePreset) {\n <div class=\"c2g-empty-state__lottie\">\n <c2g-lottie-loader\n [preset]=\"data().lottiePreset!\"\n width=\"120px\"\n height=\"120px\"\n [showLabel]=\"false\"\n label=\"Illustration\"\n />\n </div>\n } @else if (data().icon) {\n <span class=\"c2g-empty-state__icon\" aria-hidden=\"true\">{{ data().icon }}</span>\n }\n\n <h3 class=\"c2g-empty-state__title\">{{ data().title }}</h3>\n\n @if (data().description) {\n <p class=\"c2g-empty-state__description\">{{ data().description }}</p>\n }\n\n @if (data().actionLabel) {\n <button\n class=\"c2g-empty-state__action\"\n type=\"button\"\n (click)=\"actionClicked.emit()\">\n {{ data().actionLabel }}\n </button>\n }\n\n <ng-content />\n</div>\n", styles: [".c2g-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:var(--c2g-spacing-8, 2rem) var(--c2g-spacing-4, 1rem);gap:var(--c2g-spacing-3, .75rem);color:var(--c2g-text-primary, #111827)}.c2g-empty-state__lottie{margin-bottom:var(--c2g-spacing-2, .5rem)}.c2g-empty-state__icon{font-size:3rem;line-height:1;margin-bottom:var(--c2g-spacing-2, .5rem)}.c2g-empty-state__title{margin:0;font-size:var(--c2g-font-size-lg, 1.125rem);font-weight:var(--c2g-font-weight-semibold, 600);color:var(--c2g-text-primary, #111827)}.c2g-empty-state__description{margin:0;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-text-secondary, #6b7280);max-width:32ch;line-height:1.6}.c2g-empty-state__action{margin-top:var(--c2g-spacing-2, .5rem);padding:var(--c2g-spacing-2, .5rem) var(--c2g-spacing-5, 1.25rem);background-color:var(--c2g-color-primary, #ff6b35);color:var(--c2g-color-on-primary, #ffffff);border:none;border-radius:var(--c2g-radius-md, .5rem);font-size:var(--c2g-font-size-sm, .875rem);font-weight:var(--c2g-font-weight-medium, 500);cursor:pointer;transition:opacity .15s ease}.c2g-empty-state__action:hover{opacity:.88}.c2g-empty-state__action:focus-visible{outline:2px solid var(--c2g-focus-ring, #3b82f6);outline-offset:2px}\n"], dependencies: [{ kind: "component", type: LottieLoaderComponent, selector: "c2g-lottie-loader", inputs: ["preset", "presetMode", "animationPath", "animationData", "loop", "autoplay", "width", "height", "label", "showLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
421
|
+
}
|
|
422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: EmptyStateComponent, decorators: [{
|
|
423
|
+
type: Component,
|
|
424
|
+
args: [{ selector: 'c2g-empty-state', standalone: true, imports: [LottieLoaderComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c2g-empty-state\">\n @if (data().lottiePreset) {\n <div class=\"c2g-empty-state__lottie\">\n <c2g-lottie-loader\n [preset]=\"data().lottiePreset!\"\n width=\"120px\"\n height=\"120px\"\n [showLabel]=\"false\"\n label=\"Illustration\"\n />\n </div>\n } @else if (data().icon) {\n <span class=\"c2g-empty-state__icon\" aria-hidden=\"true\">{{ data().icon }}</span>\n }\n\n <h3 class=\"c2g-empty-state__title\">{{ data().title }}</h3>\n\n @if (data().description) {\n <p class=\"c2g-empty-state__description\">{{ data().description }}</p>\n }\n\n @if (data().actionLabel) {\n <button\n class=\"c2g-empty-state__action\"\n type=\"button\"\n (click)=\"actionClicked.emit()\">\n {{ data().actionLabel }}\n </button>\n }\n\n <ng-content />\n</div>\n", styles: [".c2g-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:var(--c2g-spacing-8, 2rem) var(--c2g-spacing-4, 1rem);gap:var(--c2g-spacing-3, .75rem);color:var(--c2g-text-primary, #111827)}.c2g-empty-state__lottie{margin-bottom:var(--c2g-spacing-2, .5rem)}.c2g-empty-state__icon{font-size:3rem;line-height:1;margin-bottom:var(--c2g-spacing-2, .5rem)}.c2g-empty-state__title{margin:0;font-size:var(--c2g-font-size-lg, 1.125rem);font-weight:var(--c2g-font-weight-semibold, 600);color:var(--c2g-text-primary, #111827)}.c2g-empty-state__description{margin:0;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-text-secondary, #6b7280);max-width:32ch;line-height:1.6}.c2g-empty-state__action{margin-top:var(--c2g-spacing-2, .5rem);padding:var(--c2g-spacing-2, .5rem) var(--c2g-spacing-5, 1.25rem);background-color:var(--c2g-color-primary, #ff6b35);color:var(--c2g-color-on-primary, #ffffff);border:none;border-radius:var(--c2g-radius-md, .5rem);font-size:var(--c2g-font-size-sm, .875rem);font-weight:var(--c2g-font-weight-medium, 500);cursor:pointer;transition:opacity .15s ease}.c2g-empty-state__action:hover{opacity:.88}.c2g-empty-state__action:focus-visible{outline:2px solid var(--c2g-focus-ring, #3b82f6);outline-offset:2px}\n"] }]
|
|
425
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], actionClicked: [{ type: i0.Output, args: ["actionClicked"] }] } });
|
|
426
|
+
|
|
427
|
+
const MAX_VISIBLE_PAGES = 5;
|
|
428
|
+
class PaginationComponent {
|
|
429
|
+
state = input.required(...(ngDevMode ? [{ debugName: "state" }] : []));
|
|
430
|
+
ariaLabel = input('Seitennavigation', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
431
|
+
pageChanged = output();
|
|
432
|
+
currentPage = computed(() => this.state().currentPage, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
|
|
433
|
+
totalPages = computed(() => this.state().totalPages, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
|
|
434
|
+
hasPrev = computed(() => this.currentPage() > 1, ...(ngDevMode ? [{ debugName: "hasPrev" }] : []));
|
|
435
|
+
hasNext = computed(() => this.currentPage() < this.totalPages(), ...(ngDevMode ? [{ debugName: "hasNext" }] : []));
|
|
436
|
+
visiblePages = computed(() => {
|
|
437
|
+
const total = this.totalPages();
|
|
438
|
+
const current = this.currentPage();
|
|
439
|
+
const half = Math.floor(MAX_VISIBLE_PAGES / 2);
|
|
440
|
+
let start = Math.max(1, current - half);
|
|
441
|
+
let end = Math.min(total, start + MAX_VISIBLE_PAGES - 1);
|
|
442
|
+
if (end - start < MAX_VISIBLE_PAGES - 1) {
|
|
443
|
+
start = Math.max(1, end - MAX_VISIBLE_PAGES + 1);
|
|
444
|
+
}
|
|
445
|
+
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
446
|
+
}, ...(ngDevMode ? [{ debugName: "visiblePages" }] : []));
|
|
447
|
+
showStartEllipsis = computed(() => (this.visiblePages()[0] ?? 1) > 1, ...(ngDevMode ? [{ debugName: "showStartEllipsis" }] : []));
|
|
448
|
+
showEndEllipsis = computed(() => (this.visiblePages().at(-1) ?? this.totalPages()) < this.totalPages(), ...(ngDevMode ? [{ debugName: "showEndEllipsis" }] : []));
|
|
449
|
+
go(page) {
|
|
450
|
+
if (page < 1 || page > this.totalPages() || page === this.currentPage())
|
|
451
|
+
return;
|
|
452
|
+
this.pageChanged.emit(page);
|
|
453
|
+
}
|
|
454
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
455
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: PaginationComponent, isStandalone: true, selector: "c2g-pagination", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChanged: "pageChanged" }, ngImport: i0, template: "<nav class=\"c2g-pagination\" [attr.aria-label]=\"ariaLabel()\">\n <button\n class=\"c2g-pagination__btn c2g-pagination__btn--nav\"\n type=\"button\"\n aria-label=\"Vorherige Seite\"\n [disabled]=\"!hasPrev()\"\n (click)=\"go(currentPage() - 1)\">\n \u2039\n </button>\n\n @if (showStartEllipsis()) {\n <button\n class=\"c2g-pagination__btn\"\n type=\"button\"\n [attr.aria-label]=\"'Seite 1'\"\n (click)=\"go(1)\">\n 1\n </button>\n <span class=\"c2g-pagination__ellipsis\" aria-hidden=\"true\">\u2026</span>\n }\n\n @for (page of visiblePages(); track page) {\n <button\n class=\"c2g-pagination__btn\"\n [class.c2g-pagination__btn--active]=\"page === currentPage()\"\n type=\"button\"\n [attr.aria-label]=\"'Seite ' + page\"\n [attr.aria-current]=\"page === currentPage() ? 'page' : null\"\n (click)=\"go(page)\">\n {{ page }}\n </button>\n }\n\n @if (showEndEllipsis()) {\n <span class=\"c2g-pagination__ellipsis\" aria-hidden=\"true\">\u2026</span>\n <button\n class=\"c2g-pagination__btn\"\n type=\"button\"\n [attr.aria-label]=\"'Seite ' + totalPages()\"\n (click)=\"go(totalPages())\">\n {{ totalPages() }}\n </button>\n }\n\n <button\n class=\"c2g-pagination__btn c2g-pagination__btn--nav\"\n type=\"button\"\n aria-label=\"N\u00E4chste Seite\"\n [disabled]=\"!hasNext()\"\n (click)=\"go(currentPage() + 1)\">\n \u203A\n </button>\n</nav>\n", styles: [".c2g-pagination{display:flex;align-items:center;gap:var(--c2g-spacing-1, .25rem);flex-wrap:wrap}.c2g-pagination__btn{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;padding:0 var(--c2g-spacing-2, .5rem);border:1px solid var(--c2g-border-color, #e5e7eb);border-radius:var(--c2g-radius-md, .5rem);background-color:var(--c2g-surface-bg, #ffffff);color:var(--c2g-text-primary, #111827);font-size:var(--c2g-font-size-sm, .875rem);font-weight:var(--c2g-font-weight-medium, 500);cursor:pointer;transition:background-color .15s ease,border-color .15s ease,color .15s ease;line-height:1}.c2g-pagination__btn:hover:not(:disabled){background-color:var(--c2g-hover-bg, #f3f4f6);border-color:var(--c2g-border-color-strong, #d1d5db)}.c2g-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.c2g-pagination__btn:focus-visible{outline:2px solid var(--c2g-focus-ring, #3b82f6);outline-offset:2px}.c2g-pagination__btn--active{background-color:var(--c2g-color-primary, #ff6b35);border-color:var(--c2g-color-primary, #ff6b35);color:var(--c2g-color-on-primary, #ffffff)}.c2g-pagination__btn--active:hover:not(:disabled){background-color:var(--c2g-color-primary, #ff6b35);opacity:.88}.c2g-pagination__btn--nav{font-size:1.25rem}.c2g-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;color:var(--c2g-text-secondary, #6b7280);font-size:var(--c2g-font-size-sm, .875rem);-webkit-user-select:none;user-select:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
456
|
+
}
|
|
457
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
458
|
+
type: Component,
|
|
459
|
+
args: [{ selector: 'c2g-pagination', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"c2g-pagination\" [attr.aria-label]=\"ariaLabel()\">\n <button\n class=\"c2g-pagination__btn c2g-pagination__btn--nav\"\n type=\"button\"\n aria-label=\"Vorherige Seite\"\n [disabled]=\"!hasPrev()\"\n (click)=\"go(currentPage() - 1)\">\n \u2039\n </button>\n\n @if (showStartEllipsis()) {\n <button\n class=\"c2g-pagination__btn\"\n type=\"button\"\n [attr.aria-label]=\"'Seite 1'\"\n (click)=\"go(1)\">\n 1\n </button>\n <span class=\"c2g-pagination__ellipsis\" aria-hidden=\"true\">\u2026</span>\n }\n\n @for (page of visiblePages(); track page) {\n <button\n class=\"c2g-pagination__btn\"\n [class.c2g-pagination__btn--active]=\"page === currentPage()\"\n type=\"button\"\n [attr.aria-label]=\"'Seite ' + page\"\n [attr.aria-current]=\"page === currentPage() ? 'page' : null\"\n (click)=\"go(page)\">\n {{ page }}\n </button>\n }\n\n @if (showEndEllipsis()) {\n <span class=\"c2g-pagination__ellipsis\" aria-hidden=\"true\">\u2026</span>\n <button\n class=\"c2g-pagination__btn\"\n type=\"button\"\n [attr.aria-label]=\"'Seite ' + totalPages()\"\n (click)=\"go(totalPages())\">\n {{ totalPages() }}\n </button>\n }\n\n <button\n class=\"c2g-pagination__btn c2g-pagination__btn--nav\"\n type=\"button\"\n aria-label=\"N\u00E4chste Seite\"\n [disabled]=\"!hasNext()\"\n (click)=\"go(currentPage() + 1)\">\n \u203A\n </button>\n</nav>\n", styles: [".c2g-pagination{display:flex;align-items:center;gap:var(--c2g-spacing-1, .25rem);flex-wrap:wrap}.c2g-pagination__btn{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;padding:0 var(--c2g-spacing-2, .5rem);border:1px solid var(--c2g-border-color, #e5e7eb);border-radius:var(--c2g-radius-md, .5rem);background-color:var(--c2g-surface-bg, #ffffff);color:var(--c2g-text-primary, #111827);font-size:var(--c2g-font-size-sm, .875rem);font-weight:var(--c2g-font-weight-medium, 500);cursor:pointer;transition:background-color .15s ease,border-color .15s ease,color .15s ease;line-height:1}.c2g-pagination__btn:hover:not(:disabled){background-color:var(--c2g-hover-bg, #f3f4f6);border-color:var(--c2g-border-color-strong, #d1d5db)}.c2g-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.c2g-pagination__btn:focus-visible{outline:2px solid var(--c2g-focus-ring, #3b82f6);outline-offset:2px}.c2g-pagination__btn--active{background-color:var(--c2g-color-primary, #ff6b35);border-color:var(--c2g-color-primary, #ff6b35);color:var(--c2g-color-on-primary, #ffffff)}.c2g-pagination__btn--active:hover:not(:disabled){background-color:var(--c2g-color-primary, #ff6b35);opacity:.88}.c2g-pagination__btn--nav{font-size:1.25rem}.c2g-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;color:var(--c2g-text-secondary, #6b7280);font-size:var(--c2g-font-size-sm, .875rem);-webkit-user-select:none;user-select:none}\n"] }]
|
|
460
|
+
}], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], pageChanged: [{ type: i0.Output, args: ["pageChanged"] }] } });
|
|
461
|
+
|
|
462
|
+
class TableComponent {
|
|
463
|
+
rows = input.required(...(ngDevMode ? [{ debugName: "rows" }] : []));
|
|
464
|
+
columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
465
|
+
rowHeight = input(48, ...(ngDevMode ? [{ debugName: "rowHeight" }] : []));
|
|
466
|
+
maxHeight = input('480px', ...(ngDevMode ? [{ debugName: "maxHeight" }] : []));
|
|
467
|
+
selectable = input(false, ...(ngDevMode ? [{ debugName: "selectable" }] : []));
|
|
468
|
+
virtualScroll = input(true, ...(ngDevMode ? [{ debugName: "virtualScroll" }] : []));
|
|
469
|
+
sortChanged = output();
|
|
470
|
+
rowSelected = output();
|
|
471
|
+
sortState = signal({ key: '', direction: null }, ...(ngDevMode ? [{ debugName: "sortState" }] : []));
|
|
472
|
+
selectedRow = signal(null, ...(ngDevMode ? [{ debugName: "selectedRow" }] : []));
|
|
473
|
+
sortedRows = computed(() => {
|
|
474
|
+
const { key, direction } = this.sortState();
|
|
475
|
+
const rows = [...this.rows()];
|
|
476
|
+
if (!key || !direction)
|
|
477
|
+
return rows;
|
|
478
|
+
return rows.sort((a, b) => {
|
|
479
|
+
const col = this.columns().find(c => c.key === key);
|
|
480
|
+
const av = col?.valueGetter ? col.valueGetter(a) : a[key];
|
|
481
|
+
const bv = col?.valueGetter ? col.valueGetter(b) : b[key];
|
|
482
|
+
const cmp = av < bv ? -1 : av > bv ? 1 : 0;
|
|
483
|
+
return direction === 'asc' ? cmp : -cmp;
|
|
484
|
+
});
|
|
485
|
+
}, ...(ngDevMode ? [{ debugName: "sortedRows" }] : []));
|
|
486
|
+
getCellValue(row, col) {
|
|
487
|
+
return col.valueGetter ? col.valueGetter(row) : row[col.key] ?? '';
|
|
488
|
+
}
|
|
489
|
+
sort(key) {
|
|
490
|
+
const current = this.sortState();
|
|
491
|
+
const direction = current.key === key
|
|
492
|
+
? current.direction === 'asc' ? 'desc' : current.direction === 'desc' ? null : 'asc'
|
|
493
|
+
: 'asc';
|
|
494
|
+
const next = { key, direction };
|
|
495
|
+
this.sortState.set(next);
|
|
496
|
+
this.sortChanged.emit(next);
|
|
497
|
+
}
|
|
498
|
+
select(row) {
|
|
499
|
+
if (!this.selectable())
|
|
500
|
+
return;
|
|
501
|
+
this.selectedRow.set(row);
|
|
502
|
+
this.rowSelected.emit(row);
|
|
503
|
+
}
|
|
504
|
+
isSelected(row) {
|
|
505
|
+
return this.selectedRow() === row;
|
|
506
|
+
}
|
|
507
|
+
sortIcon(key) {
|
|
508
|
+
const s = this.sortState();
|
|
509
|
+
if (s.key !== key || !s.direction)
|
|
510
|
+
return '↕';
|
|
511
|
+
return s.direction === 'asc' ? '↑' : '↓';
|
|
512
|
+
}
|
|
513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
514
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: TableComponent, isStandalone: true, selector: "c2g-table", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChanged: "sortChanged", rowSelected: "rowSelected" }, ngImport: i0, template: "<div class=\"c2g-table-wrapper\" [style.maxHeight]=\"maxHeight()\">\n @if (virtualScroll()) {\n <cdk-virtual-scroll-viewport [itemSize]=\"rowHeight()\" class=\"c2g-table-viewport\" [style.height]=\"maxHeight()\">\n <table class=\"c2g-table\" role=\"grid\">\n <thead class=\"c2g-table__head\">\n <tr>\n @for (col of columns(); track col.key) {\n <th\n class=\"c2g-table__th\"\n [class.c2g-table__th--sortable]=\"col.sortable\"\n [class.c2g-table__th--sorted]=\"sortState().key === col.key\"\n (click)=\"col.sortable && sort(col.key)\"\n [attr.aria-sort]=\"col.sortable ? (sortState().key === col.key ? (sortState().direction ?? 'none') : 'none') : null\"\n >\n <span class=\"c2g-table__th-label\">{{ col.label }}</span>\n @if (col.sortable) {\n <span class=\"c2g-table__sort-icon\" aria-hidden=\"true\">{{ sortIcon(col.key) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n <tr\n *cdkVirtualFor=\"let row of sortedRows()\"\n class=\"c2g-table__row\"\n [class.c2g-table__row--selectable]=\"selectable()\"\n [class.c2g-table__row--selected]=\"selectedRow() === row\"\n (click)=\"select(row)\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (keydown.enter)=\"selectable() && select(row)\"\n >\n @for (col of columns(); track col.key) {\n <td class=\"c2g-table__td\">{{ getCellValue(row, col) }}</td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n } @else {\n <table class=\"c2g-table\" role=\"grid\">\n <thead class=\"c2g-table__head\">\n <tr>\n @for (col of columns(); track col.key) {\n <th\n class=\"c2g-table__th\"\n [class.c2g-table__th--sortable]=\"col.sortable\"\n [class.c2g-table__th--sorted]=\"sortState().key === col.key\"\n (click)=\"col.sortable && sort(col.key)\"\n [attr.aria-sort]=\"col.sortable ? (sortState().key === col.key ? (sortState().direction ?? 'none') : 'none') : null\"\n >\n <span class=\"c2g-table__th-label\">{{ col.label }}</span>\n @if (col.sortable) {\n <span class=\"c2g-table__sort-icon\" aria-hidden=\"true\">{{ sortIcon(col.key) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of sortedRows(); track $index) {\n <tr\n class=\"c2g-table__row\"\n [class.c2g-table__row--selectable]=\"selectable()\"\n [class.c2g-table__row--selected]=\"selectedRow() === row\"\n (click)=\"select(row)\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (keydown.enter)=\"selectable() && select(row)\"\n >\n @for (col of columns(); track col.key) {\n <td class=\"c2g-table__td\">{{ getCellValue(row, col) }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n }\n</div>\n", styles: [":host{display:block;width:100%;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-table-wrapper{overflow:auto;border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-md, 8px);background:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-table-viewport{width:100%}.c2g-table{width:100%;border-collapse:collapse;font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif);font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-table__head{position:sticky;top:0;z-index:1;background:var(--c2g-theme-surface-container, var(--c2g-color-bg-secondary))}.c2g-table__th{padding:12px 16px;text-align:left;font-weight:600;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));border-bottom:2px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));white-space:nowrap;-webkit-user-select:none;user-select:none}.c2g-table__th--sortable{cursor:pointer}.c2g-table__th--sortable:hover{background:var(--c2g-theme-surface-container-low, var(--c2g-color-bg-base));color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-table__th--sorted{color:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-table__th-label{display:inline}.c2g-table__sort-icon{margin-left:6px;opacity:.5;font-size:.75rem}.c2g-table__row{border-bottom:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));transition:background .15s ease}.c2g-table__row:last-child{border-bottom:none}.c2g-table__row--selectable{cursor:pointer}.c2g-table__row--selectable:hover{background:var(--c2g-theme-surface-container-low, var(--c2g-color-bg-base))}.c2g-table__row--selectable:focus{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:-2px}.c2g-table__row--selected,.c2g-table__row--selected:hover{background:var(--c2g-theme-primary-container, var(--c2g-color-primary-container))}.c2g-table__td{padding:12px 16px;color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary));vertical-align:middle}\n"], dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1$4.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1$4.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1$4.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
515
|
+
}
|
|
516
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: TableComponent, decorators: [{
|
|
517
|
+
type: Component,
|
|
518
|
+
args: [{ selector: 'c2g-table', standalone: true, imports: [ScrollingModule, NgClass, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c2g-table-wrapper\" [style.maxHeight]=\"maxHeight()\">\n @if (virtualScroll()) {\n <cdk-virtual-scroll-viewport [itemSize]=\"rowHeight()\" class=\"c2g-table-viewport\" [style.height]=\"maxHeight()\">\n <table class=\"c2g-table\" role=\"grid\">\n <thead class=\"c2g-table__head\">\n <tr>\n @for (col of columns(); track col.key) {\n <th\n class=\"c2g-table__th\"\n [class.c2g-table__th--sortable]=\"col.sortable\"\n [class.c2g-table__th--sorted]=\"sortState().key === col.key\"\n (click)=\"col.sortable && sort(col.key)\"\n [attr.aria-sort]=\"col.sortable ? (sortState().key === col.key ? (sortState().direction ?? 'none') : 'none') : null\"\n >\n <span class=\"c2g-table__th-label\">{{ col.label }}</span>\n @if (col.sortable) {\n <span class=\"c2g-table__sort-icon\" aria-hidden=\"true\">{{ sortIcon(col.key) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n <tr\n *cdkVirtualFor=\"let row of sortedRows()\"\n class=\"c2g-table__row\"\n [class.c2g-table__row--selectable]=\"selectable()\"\n [class.c2g-table__row--selected]=\"selectedRow() === row\"\n (click)=\"select(row)\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (keydown.enter)=\"selectable() && select(row)\"\n >\n @for (col of columns(); track col.key) {\n <td class=\"c2g-table__td\">{{ getCellValue(row, col) }}</td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n } @else {\n <table class=\"c2g-table\" role=\"grid\">\n <thead class=\"c2g-table__head\">\n <tr>\n @for (col of columns(); track col.key) {\n <th\n class=\"c2g-table__th\"\n [class.c2g-table__th--sortable]=\"col.sortable\"\n [class.c2g-table__th--sorted]=\"sortState().key === col.key\"\n (click)=\"col.sortable && sort(col.key)\"\n [attr.aria-sort]=\"col.sortable ? (sortState().key === col.key ? (sortState().direction ?? 'none') : 'none') : null\"\n >\n <span class=\"c2g-table__th-label\">{{ col.label }}</span>\n @if (col.sortable) {\n <span class=\"c2g-table__sort-icon\" aria-hidden=\"true\">{{ sortIcon(col.key) }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of sortedRows(); track $index) {\n <tr\n class=\"c2g-table__row\"\n [class.c2g-table__row--selectable]=\"selectable()\"\n [class.c2g-table__row--selected]=\"selectedRow() === row\"\n (click)=\"select(row)\"\n [attr.tabindex]=\"selectable() ? 0 : null\"\n (keydown.enter)=\"selectable() && select(row)\"\n >\n @for (col of columns(); track col.key) {\n <td class=\"c2g-table__td\">{{ getCellValue(row, col) }}</td>\n }\n </tr>\n }\n </tbody>\n </table>\n }\n</div>\n", styles: [":host{display:block;width:100%;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-table-wrapper{overflow:auto;border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-md, 8px);background:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-table-viewport{width:100%}.c2g-table{width:100%;border-collapse:collapse;font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif);font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-table__head{position:sticky;top:0;z-index:1;background:var(--c2g-theme-surface-container, var(--c2g-color-bg-secondary))}.c2g-table__th{padding:12px 16px;text-align:left;font-weight:600;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));border-bottom:2px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));white-space:nowrap;-webkit-user-select:none;user-select:none}.c2g-table__th--sortable{cursor:pointer}.c2g-table__th--sortable:hover{background:var(--c2g-theme-surface-container-low, var(--c2g-color-bg-base));color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-table__th--sorted{color:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-table__th-label{display:inline}.c2g-table__sort-icon{margin-left:6px;opacity:.5;font-size:.75rem}.c2g-table__row{border-bottom:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));transition:background .15s ease}.c2g-table__row:last-child{border-bottom:none}.c2g-table__row--selectable{cursor:pointer}.c2g-table__row--selectable:hover{background:var(--c2g-theme-surface-container-low, var(--c2g-color-bg-base))}.c2g-table__row--selectable:focus{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:-2px}.c2g-table__row--selected,.c2g-table__row--selected:hover{background:var(--c2g-theme-primary-container, var(--c2g-color-primary-container))}.c2g-table__td{padding:12px 16px;color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary));vertical-align:middle}\n"] }]
|
|
519
|
+
}], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], sortChanged: [{ type: i0.Output, args: ["sortChanged"] }], rowSelected: [{ type: i0.Output, args: ["rowSelected"] }] } });
|
|
520
|
+
|
|
521
|
+
class TabsComponent {
|
|
522
|
+
tabs = input.required(...(ngDevMode ? [{ debugName: "tabs" }] : []));
|
|
523
|
+
activeKey = model('', ...(ngDevMode ? [{ debugName: "activeKey" }] : []));
|
|
524
|
+
tabChanged = output();
|
|
525
|
+
activeTab = computed(() => this.tabs().find(t => t.key === this.activeKey()) ?? this.tabs()[0], ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
526
|
+
select(tab) {
|
|
527
|
+
if (tab.disabled)
|
|
528
|
+
return;
|
|
529
|
+
this.activeKey.set(tab.key);
|
|
530
|
+
this.tabChanged.emit(tab);
|
|
531
|
+
}
|
|
532
|
+
isActive(tab) {
|
|
533
|
+
const key = this.activeKey();
|
|
534
|
+
return key ? tab.key === key : tab === this.tabs()[0];
|
|
535
|
+
}
|
|
536
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: TabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
537
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: TabsComponent, isStandalone: true, selector: "c2g-tabs", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: true, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeKey: "activeKeyChange", tabChanged: "tabChanged" }, ngImport: i0, template: "<div class=\"c2g-tabs\" role=\"tablist\" [attr.aria-label]=\"'Tabs'\">\n <div class=\"c2g-tabs__nav\">\n @for (tab of tabs(); track tab.key) {\n <button\n class=\"c2g-tabs__tab\"\n role=\"tab\"\n [class.c2g-tabs__tab--active]=\"isActive(tab)\"\n [class.c2g-tabs__tab--disabled]=\"tab.disabled\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-disabled]=\"tab.disabled || null\"\n [disabled]=\"tab.disabled || null\"\n (click)=\"select(tab)\"\n >\n @if (tab.icon) {\n <span class=\"c2g-tabs__tab-icon\" aria-hidden=\"true\">{{ tab.icon }}</span>\n }\n <span class=\"c2g-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge !== undefined) {\n <span class=\"c2g-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n </button>\n }\n </div>\n\n <div class=\"c2g-tabs__indicator-bar\" aria-hidden=\"true\"></div>\n\n <div class=\"c2g-tabs__panel\" role=\"tabpanel\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-tabs{font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-tabs__nav{display:flex;gap:4px;border-bottom:2px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));overflow-x:auto;scrollbar-width:none}.c2g-tabs__nav::-webkit-scrollbar{display:none}.c2g-tabs__tab{position:relative;display:inline-flex;align-items:center;gap:6px;padding:10px 16px;border:none;background:none;cursor:pointer;font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);font-weight:500;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));white-space:nowrap;transition:color .15s ease;border-bottom:2px solid transparent;margin-bottom:-2px}.c2g-tabs__tab:hover:not(.c2g-tabs__tab--disabled){color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-tabs__tab--active{color:var(--c2g-theme-primary, var(--c2g-color-primary));border-bottom-color:var(--c2g-theme-primary, var(--c2g-color-primary));font-weight:600}.c2g-tabs__tab--disabled{opacity:.4;cursor:not-allowed}.c2g-tabs__tab:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:2px;border-radius:var(--c2g-radius-sm, 4px)}.c2g-tabs__tab-icon{font-size:1rem}.c2g-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--c2g-theme-primary, var(--c2g-color-primary));color:var(--c2g-theme-surface, var(--c2g-color-surface));font-size:.7rem;font-weight:700;line-height:1}.c2g-tabs__panel{padding-top:16px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
538
|
+
}
|
|
539
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: TabsComponent, decorators: [{
|
|
540
|
+
type: Component,
|
|
541
|
+
args: [{ selector: 'c2g-tabs', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c2g-tabs\" role=\"tablist\" [attr.aria-label]=\"'Tabs'\">\n <div class=\"c2g-tabs__nav\">\n @for (tab of tabs(); track tab.key) {\n <button\n class=\"c2g-tabs__tab\"\n role=\"tab\"\n [class.c2g-tabs__tab--active]=\"isActive(tab)\"\n [class.c2g-tabs__tab--disabled]=\"tab.disabled\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-disabled]=\"tab.disabled || null\"\n [disabled]=\"tab.disabled || null\"\n (click)=\"select(tab)\"\n >\n @if (tab.icon) {\n <span class=\"c2g-tabs__tab-icon\" aria-hidden=\"true\">{{ tab.icon }}</span>\n }\n <span class=\"c2g-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge !== undefined) {\n <span class=\"c2g-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n </button>\n }\n </div>\n\n <div class=\"c2g-tabs__indicator-bar\" aria-hidden=\"true\"></div>\n\n <div class=\"c2g-tabs__panel\" role=\"tabpanel\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-tabs{font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-tabs__nav{display:flex;gap:4px;border-bottom:2px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));overflow-x:auto;scrollbar-width:none}.c2g-tabs__nav::-webkit-scrollbar{display:none}.c2g-tabs__tab{position:relative;display:inline-flex;align-items:center;gap:6px;padding:10px 16px;border:none;background:none;cursor:pointer;font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);font-weight:500;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));white-space:nowrap;transition:color .15s ease;border-bottom:2px solid transparent;margin-bottom:-2px}.c2g-tabs__tab:hover:not(.c2g-tabs__tab--disabled){color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-tabs__tab--active{color:var(--c2g-theme-primary, var(--c2g-color-primary));border-bottom-color:var(--c2g-theme-primary, var(--c2g-color-primary));font-weight:600}.c2g-tabs__tab--disabled{opacity:.4;cursor:not-allowed}.c2g-tabs__tab:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:2px;border-radius:var(--c2g-radius-sm, 4px)}.c2g-tabs__tab-icon{font-size:1rem}.c2g-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--c2g-theme-primary, var(--c2g-color-primary));color:var(--c2g-theme-surface, var(--c2g-color-surface));font-size:.7rem;font-weight:700;line-height:1}.c2g-tabs__panel{padding-top:16px}\n"] }]
|
|
542
|
+
}], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: true }] }], activeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeKey", required: false }] }, { type: i0.Output, args: ["activeKeyChange"] }], tabChanged: [{ type: i0.Output, args: ["tabChanged"] }] } });
|
|
543
|
+
|
|
544
|
+
class BreadcrumbComponent {
|
|
545
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
546
|
+
separator = input('›', ...(ngDevMode ? [{ debugName: "separator" }] : []));
|
|
547
|
+
itemClicked = output();
|
|
548
|
+
navigate(event, item) {
|
|
549
|
+
if (!item.href) {
|
|
550
|
+
event.preventDefault();
|
|
551
|
+
this.itemClicked.emit(item);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
555
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: BreadcrumbComponent, isStandalone: true, selector: "c2g-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, ngImport: i0, template: "<nav class=\"c2g-breadcrumb\" aria-label=\"Breadcrumb\">\n <ol class=\"c2g-breadcrumb__list\">\n @for (item of items(); track item.label; let last = $last) {\n <li class=\"c2g-breadcrumb__item\">\n @if (!last) {\n <a\n class=\"c2g-breadcrumb__link\"\n [href]=\"item.href || '#'\"\n (click)=\"navigate($event, item)\"\n >\n @if (item.icon) {\n <span class=\"c2g-breadcrumb__icon\" aria-hidden=\"true\">{{ item.icon }}</span>\n }\n {{ item.label }}\n </a>\n <span class=\"c2g-breadcrumb__separator\" aria-hidden=\"true\">{{ separator() }}</span>\n } @else {\n <span class=\"c2g-breadcrumb__current\" aria-current=\"page\">\n @if (item.icon) {\n <span class=\"c2g-breadcrumb__icon\" aria-hidden=\"true\">{{ item.icon }}</span>\n }\n {{ item.label }}\n </span>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-breadcrumb{font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-breadcrumb__list{display:flex;align-items:center;flex-wrap:wrap;gap:4px;list-style:none;margin:0;padding:0;font-size:var(--c2g-font-size-sm, .875rem)}.c2g-breadcrumb__item{display:flex;align-items:center;gap:4px}.c2g-breadcrumb__link{color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));text-decoration:none;transition:color .15s ease;display:inline-flex;align-items:center;gap:4px;border-radius:var(--c2g-radius-sm, 4px);padding:2px 4px}.c2g-breadcrumb__link:hover{color:var(--c2g-theme-primary, var(--c2g-color-primary));text-decoration:underline}.c2g-breadcrumb__link:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:2px}.c2g-breadcrumb__separator{color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted));-webkit-user-select:none;user-select:none;font-size:.9em}.c2g-breadcrumb__current{color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary));font-weight:600;display:inline-flex;align-items:center;gap:4px}.c2g-breadcrumb__icon{font-size:1em;line-height:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
556
|
+
}
|
|
557
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BreadcrumbComponent, decorators: [{
|
|
558
|
+
type: Component,
|
|
559
|
+
args: [{ selector: 'c2g-breadcrumb', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"c2g-breadcrumb\" aria-label=\"Breadcrumb\">\n <ol class=\"c2g-breadcrumb__list\">\n @for (item of items(); track item.label; let last = $last) {\n <li class=\"c2g-breadcrumb__item\">\n @if (!last) {\n <a\n class=\"c2g-breadcrumb__link\"\n [href]=\"item.href || '#'\"\n (click)=\"navigate($event, item)\"\n >\n @if (item.icon) {\n <span class=\"c2g-breadcrumb__icon\" aria-hidden=\"true\">{{ item.icon }}</span>\n }\n {{ item.label }}\n </a>\n <span class=\"c2g-breadcrumb__separator\" aria-hidden=\"true\">{{ separator() }}</span>\n } @else {\n <span class=\"c2g-breadcrumb__current\" aria-current=\"page\">\n @if (item.icon) {\n <span class=\"c2g-breadcrumb__icon\" aria-hidden=\"true\">{{ item.icon }}</span>\n }\n {{ item.label }}\n </span>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-breadcrumb{font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-breadcrumb__list{display:flex;align-items:center;flex-wrap:wrap;gap:4px;list-style:none;margin:0;padding:0;font-size:var(--c2g-font-size-sm, .875rem)}.c2g-breadcrumb__item{display:flex;align-items:center;gap:4px}.c2g-breadcrumb__link{color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));text-decoration:none;transition:color .15s ease;display:inline-flex;align-items:center;gap:4px;border-radius:var(--c2g-radius-sm, 4px);padding:2px 4px}.c2g-breadcrumb__link:hover{color:var(--c2g-theme-primary, var(--c2g-color-primary));text-decoration:underline}.c2g-breadcrumb__link:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:2px}.c2g-breadcrumb__separator{color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted));-webkit-user-select:none;user-select:none;font-size:.9em}.c2g-breadcrumb__current{color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary));font-weight:600;display:inline-flex;align-items:center;gap:4px}.c2g-breadcrumb__icon{font-size:1em;line-height:1}\n"] }]
|
|
560
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
561
|
+
|
|
562
|
+
class StepperComponent {
|
|
563
|
+
steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : []));
|
|
564
|
+
activeIndex = model(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
|
|
565
|
+
completedIndices = input([], ...(ngDevMode ? [{ debugName: "completedIndices" }] : []));
|
|
566
|
+
errorIndices = input([], ...(ngDevMode ? [{ debugName: "errorIndices" }] : []));
|
|
567
|
+
orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
568
|
+
stepChanged = output();
|
|
569
|
+
canGoNext = computed(() => this.activeIndex() < this.steps().length - 1, ...(ngDevMode ? [{ debugName: "canGoNext" }] : []));
|
|
570
|
+
canGoPrev = computed(() => this.activeIndex() > 0, ...(ngDevMode ? [{ debugName: "canGoPrev" }] : []));
|
|
571
|
+
getState(index) {
|
|
572
|
+
if (this.errorIndices().includes(index))
|
|
573
|
+
return 'error';
|
|
574
|
+
if (this.completedIndices().includes(index))
|
|
575
|
+
return 'completed';
|
|
576
|
+
if (index === this.activeIndex())
|
|
577
|
+
return 'active';
|
|
578
|
+
return 'pending';
|
|
579
|
+
}
|
|
580
|
+
goTo(index) {
|
|
581
|
+
if (index < 0 || index >= this.steps().length)
|
|
582
|
+
return;
|
|
583
|
+
this.activeIndex.set(index);
|
|
584
|
+
this.stepChanged.emit({ step: this.steps()[index], index });
|
|
585
|
+
}
|
|
586
|
+
next() { this.goTo(this.activeIndex() + 1); }
|
|
587
|
+
prev() { this.goTo(this.activeIndex() - 1); }
|
|
588
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: StepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
589
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: StepperComponent, isStandalone: true, selector: "c2g-stepper", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, completedIndices: { classPropertyName: "completedIndices", publicName: "completedIndices", isSignal: true, isRequired: false, transformFunction: null }, errorIndices: { classPropertyName: "errorIndices", publicName: "errorIndices", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange", stepChanged: "stepChanged" }, ngImport: i0, template: "<div\n class=\"c2g-stepper\"\n [class.c2g-stepper--horizontal]=\"orientation() === 'horizontal'\"\n [class.c2g-stepper--vertical]=\"orientation() === 'vertical'\"\n role=\"list\"\n [attr.aria-label]=\"'Steps'\"\n>\n @for (step of steps(); track step.label; let i = $index; let last = $last) {\n <div\n class=\"c2g-stepper__step\"\n [class.c2g-stepper__step--active]=\"getState(i) === 'active'\"\n [class.c2g-stepper__step--completed]=\"getState(i) === 'completed'\"\n [class.c2g-stepper__step--error]=\"getState(i) === 'error'\"\n [class.c2g-stepper__step--pending]=\"getState(i) === 'pending'\"\n role=\"listitem\"\n >\n <div class=\"c2g-stepper__header\">\n <button\n class=\"c2g-stepper__marker\"\n type=\"button\"\n [attr.aria-label]=\"'Step ' + (i + 1) + ': ' + step.label\"\n [attr.aria-current]=\"getState(i) === 'active' ? 'step' : null\"\n (click)=\"goTo(i)\"\n >\n @if (getState(i) === 'completed') {\n <span class=\"c2g-stepper__check\" aria-hidden=\"true\">\u2713</span>\n } @else if (getState(i) === 'error') {\n <span class=\"c2g-stepper__error-icon\" aria-hidden=\"true\">!</span>\n } @else {\n <span class=\"c2g-stepper__index\" aria-hidden=\"true\">{{ i + 1 }}</span>\n }\n </button>\n\n <div class=\"c2g-stepper__label-group\">\n <span class=\"c2g-stepper__label\">{{ step.label }}</span>\n @if (step.description) {\n <span class=\"c2g-stepper__description\">{{ step.description }}</span>\n }\n </div>\n </div>\n\n @if (!last) {\n <div class=\"c2g-stepper__connector\" aria-hidden=\"true\">\n <div\n class=\"c2g-stepper__connector-line\"\n [class.c2g-stepper__connector-line--filled]=\"getState(i) === 'completed'\"\n ></div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-stepper{font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-stepper--horizontal{display:flex;align-items:flex-start}.c2g-stepper--horizontal .c2g-stepper__step{flex:1;display:flex;flex-direction:column;align-items:center}.c2g-stepper--horizontal .c2g-stepper__header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px}.c2g-stepper--horizontal .c2g-stepper__connector{flex:1;display:flex;align-items:center;padding-top:20px}.c2g-stepper--horizontal .c2g-stepper__connector-line{flex:1;height:2px;background:var(--c2g-theme-outline-variant, var(--c2g-color-outline));margin:0 8px}.c2g-stepper--horizontal .c2g-stepper__connector-line--filled{background:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-stepper--vertical,.c2g-stepper--vertical .c2g-stepper__step{display:flex;flex-direction:column}.c2g-stepper--vertical .c2g-stepper__header{display:flex;align-items:center;gap:12px}.c2g-stepper--vertical .c2g-stepper__connector{display:flex;padding-left:20px;min-height:24px}.c2g-stepper--vertical .c2g-stepper__connector-line{width:2px;flex:1;background:var(--c2g-theme-outline-variant, var(--c2g-color-outline));margin:4px 0}.c2g-stepper--vertical .c2g-stepper__connector-line--filled{background:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-stepper__marker{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;border:2px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));background:var(--c2g-theme-surface, var(--c2g-color-surface));cursor:pointer;font-weight:700;font-size:.875rem;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));transition:border-color .2s ease,background .2s ease,color .2s ease;flex-shrink:0}.c2g-stepper__marker:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:3px}.c2g-stepper__step--active .c2g-stepper__marker{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));background:var(--c2g-theme-primary, var(--c2g-color-primary));color:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-stepper__step--completed .c2g-stepper__marker{border-color:var(--c2g-theme-success, var(--c2g-color-success));background:var(--c2g-theme-success, var(--c2g-color-success));color:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-stepper__step--error .c2g-stepper__marker{border-color:var(--c2g-theme-error, var(--c2g-color-error));background:var(--c2g-theme-error, var(--c2g-color-error));color:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-stepper__label{font-weight:600;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary))}.c2g-stepper__step--active .c2g-stepper__label{color:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-stepper__step--completed .c2g-stepper__label{color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-stepper__description{font-size:var(--c2g-font-size-xs, .75rem);color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted));margin-top:2px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
590
|
+
}
|
|
591
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: StepperComponent, decorators: [{
|
|
592
|
+
type: Component,
|
|
593
|
+
args: [{ selector: 'c2g-stepper', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"c2g-stepper\"\n [class.c2g-stepper--horizontal]=\"orientation() === 'horizontal'\"\n [class.c2g-stepper--vertical]=\"orientation() === 'vertical'\"\n role=\"list\"\n [attr.aria-label]=\"'Steps'\"\n>\n @for (step of steps(); track step.label; let i = $index; let last = $last) {\n <div\n class=\"c2g-stepper__step\"\n [class.c2g-stepper__step--active]=\"getState(i) === 'active'\"\n [class.c2g-stepper__step--completed]=\"getState(i) === 'completed'\"\n [class.c2g-stepper__step--error]=\"getState(i) === 'error'\"\n [class.c2g-stepper__step--pending]=\"getState(i) === 'pending'\"\n role=\"listitem\"\n >\n <div class=\"c2g-stepper__header\">\n <button\n class=\"c2g-stepper__marker\"\n type=\"button\"\n [attr.aria-label]=\"'Step ' + (i + 1) + ': ' + step.label\"\n [attr.aria-current]=\"getState(i) === 'active' ? 'step' : null\"\n (click)=\"goTo(i)\"\n >\n @if (getState(i) === 'completed') {\n <span class=\"c2g-stepper__check\" aria-hidden=\"true\">\u2713</span>\n } @else if (getState(i) === 'error') {\n <span class=\"c2g-stepper__error-icon\" aria-hidden=\"true\">!</span>\n } @else {\n <span class=\"c2g-stepper__index\" aria-hidden=\"true\">{{ i + 1 }}</span>\n }\n </button>\n\n <div class=\"c2g-stepper__label-group\">\n <span class=\"c2g-stepper__label\">{{ step.label }}</span>\n @if (step.description) {\n <span class=\"c2g-stepper__description\">{{ step.description }}</span>\n }\n </div>\n </div>\n\n @if (!last) {\n <div class=\"c2g-stepper__connector\" aria-hidden=\"true\">\n <div\n class=\"c2g-stepper__connector-line\"\n [class.c2g-stepper__connector-line--filled]=\"getState(i) === 'completed'\"\n ></div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-stepper{font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-stepper--horizontal{display:flex;align-items:flex-start}.c2g-stepper--horizontal .c2g-stepper__step{flex:1;display:flex;flex-direction:column;align-items:center}.c2g-stepper--horizontal .c2g-stepper__header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px}.c2g-stepper--horizontal .c2g-stepper__connector{flex:1;display:flex;align-items:center;padding-top:20px}.c2g-stepper--horizontal .c2g-stepper__connector-line{flex:1;height:2px;background:var(--c2g-theme-outline-variant, var(--c2g-color-outline));margin:0 8px}.c2g-stepper--horizontal .c2g-stepper__connector-line--filled{background:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-stepper--vertical,.c2g-stepper--vertical .c2g-stepper__step{display:flex;flex-direction:column}.c2g-stepper--vertical .c2g-stepper__header{display:flex;align-items:center;gap:12px}.c2g-stepper--vertical .c2g-stepper__connector{display:flex;padding-left:20px;min-height:24px}.c2g-stepper--vertical .c2g-stepper__connector-line{width:2px;flex:1;background:var(--c2g-theme-outline-variant, var(--c2g-color-outline));margin:4px 0}.c2g-stepper--vertical .c2g-stepper__connector-line--filled{background:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-stepper__marker{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;border:2px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));background:var(--c2g-theme-surface, var(--c2g-color-surface));cursor:pointer;font-weight:700;font-size:.875rem;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));transition:border-color .2s ease,background .2s ease,color .2s ease;flex-shrink:0}.c2g-stepper__marker:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:3px}.c2g-stepper__step--active .c2g-stepper__marker{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));background:var(--c2g-theme-primary, var(--c2g-color-primary));color:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-stepper__step--completed .c2g-stepper__marker{border-color:var(--c2g-theme-success, var(--c2g-color-success));background:var(--c2g-theme-success, var(--c2g-color-success));color:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-stepper__step--error .c2g-stepper__marker{border-color:var(--c2g-theme-error, var(--c2g-color-error));background:var(--c2g-theme-error, var(--c2g-color-error));color:var(--c2g-theme-surface, var(--c2g-color-surface))}.c2g-stepper__label{font-weight:600;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary))}.c2g-stepper__step--active .c2g-stepper__label{color:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-stepper__step--completed .c2g-stepper__label{color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary))}.c2g-stepper__description{font-size:var(--c2g-font-size-xs, .75rem);color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted));margin-top:2px}\n"] }]
|
|
594
|
+
}], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], completedIndices: [{ type: i0.Input, args: [{ isSignal: true, alias: "completedIndices", required: false }] }], errorIndices: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorIndices", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], stepChanged: [{ type: i0.Output, args: ["stepChanged"] }] } });
|
|
595
|
+
|
|
596
|
+
class C2gKpiCardComponent {
|
|
597
|
+
el;
|
|
598
|
+
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
599
|
+
color = computed(() => this.data().color ?? 'neutral', ...(ngDevMode ? [{ debugName: "color" }] : []));
|
|
600
|
+
hostClass = computed(() => `c2g-kpi-card c2g-kpi-card--${this.color()}`, ...(ngDevMode ? [{ debugName: "hostClass" }] : []));
|
|
601
|
+
// Count-up animation
|
|
602
|
+
displayValue = signal('', ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
|
|
603
|
+
countUpRaf = 0;
|
|
604
|
+
constructor(el) {
|
|
605
|
+
this.el = el;
|
|
606
|
+
effect(() => {
|
|
607
|
+
const raw = this.data().value;
|
|
608
|
+
this.startCountUp(raw);
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
startCountUp(raw) {
|
|
612
|
+
cancelAnimationFrame(this.countUpRaf);
|
|
613
|
+
const target = parseFloat(String(raw).replace(/[^0-9.-]/g, ''));
|
|
614
|
+
if (isNaN(target)) {
|
|
615
|
+
this.displayValue.set(String(raw));
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
const isFloat = String(raw).includes('.');
|
|
619
|
+
const decimals = isFloat ? (String(raw).split('.')[1]?.length ?? 1) : 0;
|
|
620
|
+
const suffix = String(raw).replace(/^[0-9.,\s-]+/, '');
|
|
621
|
+
const prefix = String(raw).replace(/[0-9.,\s]+.*$/, '');
|
|
622
|
+
const duration = 900;
|
|
623
|
+
const start = performance.now();
|
|
624
|
+
const tick = (now) => {
|
|
625
|
+
const progress = Math.min((now - start) / duration, 1);
|
|
626
|
+
const ease = 1 - Math.pow(1 - progress, 3); // ease-out cubic
|
|
627
|
+
const current = ease * target;
|
|
628
|
+
const formatted = decimals > 0
|
|
629
|
+
? current.toFixed(decimals)
|
|
630
|
+
: Math.round(current).toLocaleString('de-DE');
|
|
631
|
+
this.displayValue.set(`${prefix}${formatted}${suffix}`);
|
|
632
|
+
if (progress < 1)
|
|
633
|
+
this.countUpRaf = requestAnimationFrame(tick);
|
|
634
|
+
};
|
|
635
|
+
this.countUpRaf = requestAnimationFrame(tick);
|
|
636
|
+
}
|
|
637
|
+
// Sparkline SVG path
|
|
638
|
+
sparklinePath = computed(() => {
|
|
639
|
+
const pts = this.data().sparkline;
|
|
640
|
+
if (!pts || pts.length < 2)
|
|
641
|
+
return null;
|
|
642
|
+
const w = 80, h = 28;
|
|
643
|
+
const min = Math.min(...pts);
|
|
644
|
+
const max = Math.max(...pts);
|
|
645
|
+
const range = max - min || 1;
|
|
646
|
+
const coords = pts.map((v, i) => ({
|
|
647
|
+
x: (i / (pts.length - 1)) * w,
|
|
648
|
+
y: h - ((v - min) / range) * h,
|
|
649
|
+
}));
|
|
650
|
+
// Smooth bezier
|
|
651
|
+
const d = coords.reduce((acc, p, i) => {
|
|
652
|
+
if (i === 0)
|
|
653
|
+
return `M ${p.x} ${p.y}`;
|
|
654
|
+
const prev = coords[i - 1];
|
|
655
|
+
const cpx = (prev.x + p.x) / 2;
|
|
656
|
+
return `${acc} C ${cpx} ${prev.y} ${cpx} ${p.y} ${p.x} ${p.y}`;
|
|
657
|
+
}, '');
|
|
658
|
+
// Area fill path
|
|
659
|
+
const area = `${d} L ${coords[coords.length - 1].x} ${h} L 0 ${h} Z`;
|
|
660
|
+
return { line: d, area, lastX: coords[coords.length - 1].x, lastY: coords[coords.length - 1].y };
|
|
661
|
+
}, ...(ngDevMode ? [{ debugName: "sparklinePath" }] : []));
|
|
662
|
+
// 3D tilt
|
|
663
|
+
tilt = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "tilt" }] : []));
|
|
664
|
+
onMouseMove(e) {
|
|
665
|
+
const rect = this.el.nativeElement.getBoundingClientRect();
|
|
666
|
+
const cx = rect.left + rect.width / 2;
|
|
667
|
+
const cy = rect.top + rect.height / 2;
|
|
668
|
+
const maxTilt = 6;
|
|
669
|
+
this.tilt.set({
|
|
670
|
+
x: ((e.clientY - cy) / (rect.height / 2)) * -maxTilt,
|
|
671
|
+
y: ((e.clientX - cx) / (rect.width / 2)) * maxTilt,
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
onMouseLeave() {
|
|
675
|
+
this.tilt.set({ x: 0, y: 0 });
|
|
676
|
+
}
|
|
677
|
+
tiltStyle = computed(() => {
|
|
678
|
+
const { x, y } = this.tilt();
|
|
679
|
+
return `perspective(600px) rotateX(${x}deg) rotateY(${y}deg) translateZ(0)`;
|
|
680
|
+
}, ...(ngDevMode ? [{ debugName: "tiltStyle" }] : []));
|
|
681
|
+
trendArrow = computed(() => {
|
|
682
|
+
const t = this.data().trend;
|
|
683
|
+
if (t === 'up')
|
|
684
|
+
return '↑';
|
|
685
|
+
if (t === 'down')
|
|
686
|
+
return '↓';
|
|
687
|
+
return '→';
|
|
688
|
+
}, ...(ngDevMode ? [{ debugName: "trendArrow" }] : []));
|
|
689
|
+
ngOnDestroy() {
|
|
690
|
+
cancelAnimationFrame(this.countUpRaf);
|
|
691
|
+
}
|
|
692
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: C2gKpiCardComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
693
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: C2gKpiCardComponent, isStandalone: true, selector: "c2g-kpi-card", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseleave": "onMouseLeave()" }, properties: { "class": "hostClass()" } }, ngImport: i0, template: "<div class=\"c2g-kpi-card__inner\" [style.transform]=\"tiltStyle()\">\n\n <!-- Glassmorphism icon orb -->\n @if (data().icon) {\n <div class=\"c2g-kpi-card__orb\" aria-hidden=\"true\">\n <span class=\"c2g-kpi-card__orb-icon\">{{ data().icon }}</span>\n </div>\n }\n\n <!-- Decorative blob -->\n <div class=\"c2g-kpi-card__blob\" aria-hidden=\"true\"></div>\n\n <!-- Label -->\n <p class=\"c2g-kpi-card__label\">{{ data().label }}</p>\n\n <!-- Main value -->\n <div class=\"c2g-kpi-card__value-row\">\n <span class=\"c2g-kpi-card__value\">{{ displayValue() }}</span>\n @if (data().unit) {\n <span class=\"c2g-kpi-card__unit\">{{ data().unit }}</span>\n }\n </div>\n\n <!-- Sparkline -->\n @if (sparklinePath(); as sp) {\n <div class=\"c2g-kpi-card__sparkline\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 80 28\" preserveAspectRatio=\"none\" width=\"100%\" height=\"28\">\n <defs>\n <linearGradient [id]=\"'spark-grad-' + color()\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" class=\"c2g-kpi-card__spark-stop-top\" />\n <stop offset=\"100%\" class=\"c2g-kpi-card__spark-stop-bottom\" />\n </linearGradient>\n </defs>\n <path class=\"c2g-kpi-card__spark-area\"\n [attr.d]=\"sp.area\"\n [attr.fill]=\"'url(#spark-grad-' + color() + ')'\" />\n <path class=\"c2g-kpi-card__spark-line\" [attr.d]=\"sp.line\" fill=\"none\" />\n <!-- Dot at latest value -->\n <circle class=\"c2g-kpi-card__spark-dot\"\n [attr.cx]=\"sp.lastX\" [attr.cy]=\"sp.lastY\" r=\"2.5\" />\n </svg>\n </div>\n }\n\n <!-- Trend footer -->\n @if (data().trend || data().change !== undefined) {\n <div class=\"c2g-kpi-card__footer\"\n [class.c2g-kpi-card__footer--up]=\"data().trend === 'up'\"\n [class.c2g-kpi-card__footer--down]=\"data().trend === 'down'\">\n <span class=\"c2g-kpi-card__arrow\">{{ trendArrow() }}</span>\n @if (data().change !== undefined) {\n <span class=\"c2g-kpi-card__change\">{{ data().change }}</span>\n }\n @if (data().changeLabel) {\n <span class=\"c2g-kpi-card__change-label\">{{ data().changeLabel }}</span>\n }\n </div>\n }\n\n</div>\n", styles: [":host{display:block;border-radius:var(--c2g-radius-xl, 20px);position:relative;isolation:isolate;cursor:default;font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif);will-change:transform}:host.c2g-kpi-card--primary{background:linear-gradient(145deg,#ff6b35,#e03e1a);box-shadow:0 4px 24px #ff6b3559,0 1px #ffffff1f inset}:host.c2g-kpi-card--primary:hover{box-shadow:0 8px 40px #ff6b358c,0 1px #ffffff29 inset}:host.c2g-kpi-card--primary .c2g-kpi-card__orb{background:#ff6b352e}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--success{background:linear-gradient(145deg,#22c55e,#16a34a);box-shadow:0 4px 24px #22c55e4d,0 1px #ffffff1f inset}:host.c2g-kpi-card--success:hover{box-shadow:0 8px 40px #22c55e80,0 1px #ffffff29 inset}:host.c2g-kpi-card--success .c2g-kpi-card__orb{background:#22c55e26}:host.c2g-kpi-card--success .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--success .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--success .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--success .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--warning{background:linear-gradient(145deg,#f59e0b,#d97706);box-shadow:0 4px 24px #f59e0b4d,0 1px #ffffff1f inset}:host.c2g-kpi-card--warning:hover{box-shadow:0 8px 40px #f59e0b80,0 1px #ffffff29 inset}:host.c2g-kpi-card--warning .c2g-kpi-card__orb{background:#f59e0b26}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--danger{background:linear-gradient(145deg,#ef4444,#dc2626);box-shadow:0 4px 24px #ef44444d,0 1px #ffffff1f inset}:host.c2g-kpi-card--danger:hover{box-shadow:0 8px 40px #ef444480,0 1px #ffffff29 inset}:host.c2g-kpi-card--danger .c2g-kpi-card__orb{background:#ef444426}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--neutral{background:linear-gradient(145deg,#6b7280,#4b5563);box-shadow:0 4px 24px #6b728033,0 1px #ffffff1f inset}:host.c2g-kpi-card--neutral:hover{box-shadow:0 8px 40px #6b728066,0 1px #ffffff29 inset}:host.c2g-kpi-card--neutral .c2g-kpi-card__orb{background:#6b72801f}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}.c2g-kpi-card__inner{position:relative;padding:22px 22px 18px;border-radius:inherit;transition:transform .12s ease-out;overflow:hidden;color:#fff;min-height:148px;display:flex;flex-direction:column;gap:4px}.c2g-kpi-card__blob{pointer-events:none;position:absolute;top:-48px;right:-48px;width:180px;height:180px;border-radius:50%;background:#ffffff14;animation:c2g-kpi-breathe 4s ease-in-out infinite;z-index:0}.c2g-kpi-card__blob:after{content:\"\";position:absolute;bottom:-60px;left:-30px;width:120px;height:120px;border-radius:50%;background:#ffffff0d}@keyframes c2g-kpi-breathe{0%,to{transform:scale(1) translateY(0)}50%{transform:scale(1.08) translateY(-8px)}}.c2g-kpi-card__orb{position:absolute;top:18px;right:18px;width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.2);z-index:1;transition:transform .2s ease}:host:hover .c2g-kpi-card__orb{transform:scale(1.1) rotate(-4deg)}.c2g-kpi-card__orb-icon{font-size:1.375rem;line-height:1;filter:drop-shadow(0 1px 4px rgba(0,0,0,.25))}.c2g-kpi-card__label{margin:0;font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;opacity:.75;position:relative;z-index:1}.c2g-kpi-card__value-row{display:flex;align-items:baseline;gap:5px;position:relative;z-index:1;margin-top:4px}.c2g-kpi-card__value{font-size:2.6rem;font-weight:900;line-height:1;letter-spacing:-.02em;text-shadow:0 2px 12px rgba(0,0,0,.2)}.c2g-kpi-card__unit{font-size:1.1rem;font-weight:600;opacity:.7;margin-bottom:2px}.c2g-kpi-card__sparkline{position:relative;z-index:1;margin-top:auto;padding-top:8px}.c2g-kpi-card__sparkline svg{display:block;overflow:visible}.c2g-kpi-card__spark-line{stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}.c2g-kpi-card__spark-dot{filter:drop-shadow(0 0 3px rgba(255,255,255,.8))}.c2g-kpi-card__footer{display:flex;align-items:center;gap:4px;font-size:.75rem;font-weight:600;opacity:.85;position:relative;z-index:1;margin-top:6px}.c2g-kpi-card__footer--up,.c2g-kpi-card__footer--down{opacity:1}.c2g-kpi-card__arrow{font-size:.9rem}.c2g-kpi-card__change{font-weight:800}.c2g-kpi-card__change-label{opacity:.7;font-weight:500}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
694
|
+
}
|
|
695
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: C2gKpiCardComponent, decorators: [{
|
|
696
|
+
type: Component,
|
|
697
|
+
args: [{ selector: 'c2g-kpi-card', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
698
|
+
'[class]': 'hostClass()',
|
|
699
|
+
'(mousemove)': 'onMouseMove($event)',
|
|
700
|
+
'(mouseleave)': 'onMouseLeave()',
|
|
701
|
+
}, template: "<div class=\"c2g-kpi-card__inner\" [style.transform]=\"tiltStyle()\">\n\n <!-- Glassmorphism icon orb -->\n @if (data().icon) {\n <div class=\"c2g-kpi-card__orb\" aria-hidden=\"true\">\n <span class=\"c2g-kpi-card__orb-icon\">{{ data().icon }}</span>\n </div>\n }\n\n <!-- Decorative blob -->\n <div class=\"c2g-kpi-card__blob\" aria-hidden=\"true\"></div>\n\n <!-- Label -->\n <p class=\"c2g-kpi-card__label\">{{ data().label }}</p>\n\n <!-- Main value -->\n <div class=\"c2g-kpi-card__value-row\">\n <span class=\"c2g-kpi-card__value\">{{ displayValue() }}</span>\n @if (data().unit) {\n <span class=\"c2g-kpi-card__unit\">{{ data().unit }}</span>\n }\n </div>\n\n <!-- Sparkline -->\n @if (sparklinePath(); as sp) {\n <div class=\"c2g-kpi-card__sparkline\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 80 28\" preserveAspectRatio=\"none\" width=\"100%\" height=\"28\">\n <defs>\n <linearGradient [id]=\"'spark-grad-' + color()\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" class=\"c2g-kpi-card__spark-stop-top\" />\n <stop offset=\"100%\" class=\"c2g-kpi-card__spark-stop-bottom\" />\n </linearGradient>\n </defs>\n <path class=\"c2g-kpi-card__spark-area\"\n [attr.d]=\"sp.area\"\n [attr.fill]=\"'url(#spark-grad-' + color() + ')'\" />\n <path class=\"c2g-kpi-card__spark-line\" [attr.d]=\"sp.line\" fill=\"none\" />\n <!-- Dot at latest value -->\n <circle class=\"c2g-kpi-card__spark-dot\"\n [attr.cx]=\"sp.lastX\" [attr.cy]=\"sp.lastY\" r=\"2.5\" />\n </svg>\n </div>\n }\n\n <!-- Trend footer -->\n @if (data().trend || data().change !== undefined) {\n <div class=\"c2g-kpi-card__footer\"\n [class.c2g-kpi-card__footer--up]=\"data().trend === 'up'\"\n [class.c2g-kpi-card__footer--down]=\"data().trend === 'down'\">\n <span class=\"c2g-kpi-card__arrow\">{{ trendArrow() }}</span>\n @if (data().change !== undefined) {\n <span class=\"c2g-kpi-card__change\">{{ data().change }}</span>\n }\n @if (data().changeLabel) {\n <span class=\"c2g-kpi-card__change-label\">{{ data().changeLabel }}</span>\n }\n </div>\n }\n\n</div>\n", styles: [":host{display:block;border-radius:var(--c2g-radius-xl, 20px);position:relative;isolation:isolate;cursor:default;font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif);will-change:transform}:host.c2g-kpi-card--primary{background:linear-gradient(145deg,#ff6b35,#e03e1a);box-shadow:0 4px 24px #ff6b3559,0 1px #ffffff1f inset}:host.c2g-kpi-card--primary:hover{box-shadow:0 8px 40px #ff6b358c,0 1px #ffffff29 inset}:host.c2g-kpi-card--primary .c2g-kpi-card__orb{background:#ff6b352e}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--primary .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--success{background:linear-gradient(145deg,#22c55e,#16a34a);box-shadow:0 4px 24px #22c55e4d,0 1px #ffffff1f inset}:host.c2g-kpi-card--success:hover{box-shadow:0 8px 40px #22c55e80,0 1px #ffffff29 inset}:host.c2g-kpi-card--success .c2g-kpi-card__orb{background:#22c55e26}:host.c2g-kpi-card--success .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--success .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--success .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--success .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--warning{background:linear-gradient(145deg,#f59e0b,#d97706);box-shadow:0 4px 24px #f59e0b4d,0 1px #ffffff1f inset}:host.c2g-kpi-card--warning:hover{box-shadow:0 8px 40px #f59e0b80,0 1px #ffffff29 inset}:host.c2g-kpi-card--warning .c2g-kpi-card__orb{background:#f59e0b26}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--warning .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--danger{background:linear-gradient(145deg,#ef4444,#dc2626);box-shadow:0 4px 24px #ef44444d,0 1px #ffffff1f inset}:host.c2g-kpi-card--danger:hover{box-shadow:0 8px 40px #ef444480,0 1px #ffffff29 inset}:host.c2g-kpi-card--danger .c2g-kpi-card__orb{background:#ef444426}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--danger .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}:host.c2g-kpi-card--neutral{background:linear-gradient(145deg,#6b7280,#4b5563);box-shadow:0 4px 24px #6b728033,0 1px #ffffff1f inset}:host.c2g-kpi-card--neutral:hover{box-shadow:0 8px 40px #6b728066,0 1px #ffffff29 inset}:host.c2g-kpi-card--neutral .c2g-kpi-card__orb{background:#6b72801f}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-line{stroke:#ffffffe6}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-dot{fill:#fff}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-stop-top{stop-color:#ffffff4d}:host.c2g-kpi-card--neutral .c2g-kpi-card__spark-stop-bottom{stop-color:#fff0}.c2g-kpi-card__inner{position:relative;padding:22px 22px 18px;border-radius:inherit;transition:transform .12s ease-out;overflow:hidden;color:#fff;min-height:148px;display:flex;flex-direction:column;gap:4px}.c2g-kpi-card__blob{pointer-events:none;position:absolute;top:-48px;right:-48px;width:180px;height:180px;border-radius:50%;background:#ffffff14;animation:c2g-kpi-breathe 4s ease-in-out infinite;z-index:0}.c2g-kpi-card__blob:after{content:\"\";position:absolute;bottom:-60px;left:-30px;width:120px;height:120px;border-radius:50%;background:#ffffff0d}@keyframes c2g-kpi-breathe{0%,to{transform:scale(1) translateY(0)}50%{transform:scale(1.08) translateY(-8px)}}.c2g-kpi-card__orb{position:absolute;top:18px;right:18px;width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.2);z-index:1;transition:transform .2s ease}:host:hover .c2g-kpi-card__orb{transform:scale(1.1) rotate(-4deg)}.c2g-kpi-card__orb-icon{font-size:1.375rem;line-height:1;filter:drop-shadow(0 1px 4px rgba(0,0,0,.25))}.c2g-kpi-card__label{margin:0;font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;opacity:.75;position:relative;z-index:1}.c2g-kpi-card__value-row{display:flex;align-items:baseline;gap:5px;position:relative;z-index:1;margin-top:4px}.c2g-kpi-card__value{font-size:2.6rem;font-weight:900;line-height:1;letter-spacing:-.02em;text-shadow:0 2px 12px rgba(0,0,0,.2)}.c2g-kpi-card__unit{font-size:1.1rem;font-weight:600;opacity:.7;margin-bottom:2px}.c2g-kpi-card__sparkline{position:relative;z-index:1;margin-top:auto;padding-top:8px}.c2g-kpi-card__sparkline svg{display:block;overflow:visible}.c2g-kpi-card__spark-line{stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}.c2g-kpi-card__spark-dot{filter:drop-shadow(0 0 3px rgba(255,255,255,.8))}.c2g-kpi-card__footer{display:flex;align-items:center;gap:4px;font-size:.75rem;font-weight:600;opacity:.85;position:relative;z-index:1;margin-top:6px}.c2g-kpi-card__footer--up,.c2g-kpi-card__footer--down{opacity:1}.c2g-kpi-card__arrow{font-size:.9rem}.c2g-kpi-card__change{font-weight:800}.c2g-kpi-card__change-label{opacity:.7;font-weight:500}\n"] }]
|
|
702
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }] } });
|
|
703
|
+
|
|
704
|
+
class FilterBarComponent {
|
|
705
|
+
groups = input.required(...(ngDevMode ? [{ debugName: "groups" }] : []));
|
|
706
|
+
searchPlaceholder = input('Suchen...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
|
|
707
|
+
showSearch = input(true, ...(ngDevMode ? [{ debugName: "showSearch" }] : []));
|
|
708
|
+
search = model('', ...(ngDevMode ? [{ debugName: "search" }] : []));
|
|
709
|
+
activeFilters = model({}, ...(ngDevMode ? [{ debugName: "activeFilters" }] : []));
|
|
710
|
+
filterChanged = output();
|
|
711
|
+
searchChanged = output();
|
|
712
|
+
activeCount = computed(() => Object.values(this.activeFilters()).reduce((sum, v) => sum + v.length, 0), ...(ngDevMode ? [{ debugName: "activeCount" }] : []));
|
|
713
|
+
hasActiveFilters = computed(() => this.activeCount() > 0, ...(ngDevMode ? [{ debugName: "hasActiveFilters" }] : []));
|
|
714
|
+
isSelected(groupKey, optionKey) {
|
|
715
|
+
return (this.activeFilters()[groupKey] ?? []).includes(optionKey);
|
|
716
|
+
}
|
|
717
|
+
toggle(groupKey, optionKey, multiple) {
|
|
718
|
+
const current = { ...this.activeFilters() };
|
|
719
|
+
const selected = current[groupKey] ?? [];
|
|
720
|
+
if (multiple) {
|
|
721
|
+
current[groupKey] = selected.includes(optionKey)
|
|
722
|
+
? selected.filter(k => k !== optionKey)
|
|
723
|
+
: [...selected, optionKey];
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
current[groupKey] = selected.includes(optionKey) ? [] : [optionKey];
|
|
727
|
+
}
|
|
728
|
+
this.activeFilters.set(current);
|
|
729
|
+
this.filterChanged.emit(current);
|
|
730
|
+
}
|
|
731
|
+
clearAll() {
|
|
732
|
+
this.activeFilters.set({});
|
|
733
|
+
this.search.set('');
|
|
734
|
+
this.filterChanged.emit({});
|
|
735
|
+
this.searchChanged.emit('');
|
|
736
|
+
}
|
|
737
|
+
onSearch(value) {
|
|
738
|
+
this.search.set(value);
|
|
739
|
+
this.searchChanged.emit(value);
|
|
740
|
+
}
|
|
741
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilterBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
742
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: FilterBarComponent, isStandalone: true, selector: "c2g-filter-bar", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, activeFilters: { classPropertyName: "activeFilters", publicName: "activeFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { search: "searchChange", activeFilters: "activeFiltersChange", filterChanged: "filterChanged", searchChanged: "searchChanged" }, ngImport: i0, template: "<div class=\"c2g-filter-bar\">\n @if (showSearch()) {\n <div class=\"c2g-filter-bar__search\">\n <input\n class=\"c2g-filter-bar__search-input\"\n type=\"search\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"search()\"\n (input)=\"onSearch($any($event.target).value)\"\n aria-label=\"Suchen\"\n />\n <span class=\"c2g-filter-bar__search-icon\" aria-hidden=\"true\">\uD83D\uDD0D</span>\n </div>\n }\n\n <div class=\"c2g-filter-bar__groups\">\n @for (group of groups(); track group.key) {\n <div class=\"c2g-filter-bar__group\">\n @if (group.label) {\n <span class=\"c2g-filter-bar__group-label\">{{ group.label }}</span>\n }\n <div class=\"c2g-filter-bar__options\" role=\"group\" [attr.aria-label]=\"group.label\">\n @for (option of group.options; track option.key) {\n <button\n class=\"c2g-filter-bar__option\"\n type=\"button\"\n [class.c2g-filter-bar__option--active]=\"isSelected(group.key, option.key)\"\n [attr.aria-pressed]=\"isSelected(group.key, option.key)\"\n (click)=\"toggle(group.key, option.key, group.multiple ?? true)\"\n >\n @if (option.icon) {\n <span class=\"c2g-filter-bar__option-icon\" aria-hidden=\"true\">{{ option.icon }}</span>\n }\n {{ option.label }}\n @if (option.count !== undefined) {\n <span class=\"c2g-filter-bar__option-count\">{{ option.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n @if (hasActiveFilters()) {\n <button\n class=\"c2g-filter-bar__clear\"\n type=\"button\"\n (click)=\"clearAll()\"\n >\n Filter zur\u00FCcksetzen\n <span class=\"c2g-filter-bar__clear-badge\">{{ activeCount() }}</span>\n </button>\n }\n</div>\n", styles: [":host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:12px 16px;background:var(--c2g-theme-surface-container, var(--c2g-color-bg-secondary));border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-md, 8px);font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-filter-bar__search{position:relative;flex:0 0 auto;min-width:200px}.c2g-filter-bar__search-input{width:100%;padding:8px 36px 8px 12px;border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-sm, 6px);font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);background:var(--c2g-theme-surface, var(--c2g-color-surface));color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary));outline:none;transition:border-color .15s ease;box-sizing:border-box}.c2g-filter-bar__search-input:focus{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));box-shadow:0 0 0 3px color-mix(in srgb,var(--c2g-theme-primary, var(--c2g-color-primary)) 12%,transparent)}.c2g-filter-bar__search-input::placeholder{color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted))}.c2g-filter-bar__search-icon{position:absolute;right:10px;top:50%;transform:translateY(-50%);pointer-events:none;font-size:.875rem;opacity:.6}.c2g-filter-bar__groups{display:flex;flex-wrap:wrap;gap:12px;flex:1}.c2g-filter-bar__group{display:flex;align-items:center;gap:8px}.c2g-filter-bar__group-label{font-size:var(--c2g-font-size-xs, .75rem);font-weight:600;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted));text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}.c2g-filter-bar__options{display:flex;flex-wrap:wrap;gap:6px}.c2g-filter-bar__option{display:inline-flex;align-items:center;gap:4px;padding:5px 12px;border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:20px;background:var(--c2g-theme-surface, var(--c2g-color-surface));cursor:pointer;font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));transition:border-color .15s ease,background .15s ease,color .15s ease;white-space:nowrap}.c2g-filter-bar__option:hover{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));color:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-filter-bar__option--active{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));background:var(--c2g-theme-primary-container, var(--c2g-color-primary-container));color:var(--c2g-theme-primary, var(--c2g-color-primary));font-weight:600}.c2g-filter-bar__option:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:2px}.c2g-filter-bar__option-icon{font-size:.875rem;line-height:1}.c2g-filter-bar__option-count{font-size:.75rem;opacity:.7}.c2g-filter-bar__clear{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border:1px solid var(--c2g-theme-error, var(--c2g-color-error));border-radius:20px;background:none;cursor:pointer;font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-error, var(--c2g-color-error));transition:background .15s ease;white-space:nowrap}.c2g-filter-bar__clear:hover{background:var(--c2g-theme-error-container, #fff5f5)}.c2g-filter-bar__clear:focus-visible{outline:2px solid var(--c2g-theme-error, var(--c2g-color-error));outline-offset:2px}.c2g-filter-bar__clear-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 4px;border-radius:9px;background:var(--c2g-theme-error, var(--c2g-color-error));color:var(--c2g-theme-surface, var(--c2g-color-surface));font-size:.7rem;font-weight:700}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
743
|
+
}
|
|
744
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilterBarComponent, decorators: [{
|
|
745
|
+
type: Component,
|
|
746
|
+
args: [{ selector: 'c2g-filter-bar', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c2g-filter-bar\">\n @if (showSearch()) {\n <div class=\"c2g-filter-bar__search\">\n <input\n class=\"c2g-filter-bar__search-input\"\n type=\"search\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"search()\"\n (input)=\"onSearch($any($event.target).value)\"\n aria-label=\"Suchen\"\n />\n <span class=\"c2g-filter-bar__search-icon\" aria-hidden=\"true\">\uD83D\uDD0D</span>\n </div>\n }\n\n <div class=\"c2g-filter-bar__groups\">\n @for (group of groups(); track group.key) {\n <div class=\"c2g-filter-bar__group\">\n @if (group.label) {\n <span class=\"c2g-filter-bar__group-label\">{{ group.label }}</span>\n }\n <div class=\"c2g-filter-bar__options\" role=\"group\" [attr.aria-label]=\"group.label\">\n @for (option of group.options; track option.key) {\n <button\n class=\"c2g-filter-bar__option\"\n type=\"button\"\n [class.c2g-filter-bar__option--active]=\"isSelected(group.key, option.key)\"\n [attr.aria-pressed]=\"isSelected(group.key, option.key)\"\n (click)=\"toggle(group.key, option.key, group.multiple ?? true)\"\n >\n @if (option.icon) {\n <span class=\"c2g-filter-bar__option-icon\" aria-hidden=\"true\">{{ option.icon }}</span>\n }\n {{ option.label }}\n @if (option.count !== undefined) {\n <span class=\"c2g-filter-bar__option-count\">{{ option.count }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n @if (hasActiveFilters()) {\n <button\n class=\"c2g-filter-bar__clear\"\n type=\"button\"\n (click)=\"clearAll()\"\n >\n Filter zur\u00FCcksetzen\n <span class=\"c2g-filter-bar__clear-badge\">{{ activeCount() }}</span>\n </button>\n }\n</div>\n", styles: [":host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:12px 16px;background:var(--c2g-theme-surface-container, var(--c2g-color-bg-secondary));border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-md, 8px);font-family:var(--c2g-font-family-base, \"Quicksand\", sans-serif)}.c2g-filter-bar__search{position:relative;flex:0 0 auto;min-width:200px}.c2g-filter-bar__search-input{width:100%;padding:8px 36px 8px 12px;border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-sm, 6px);font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);background:var(--c2g-theme-surface, var(--c2g-color-surface));color:var(--c2g-theme-on-surface, var(--c2g-color-text-primary));outline:none;transition:border-color .15s ease;box-sizing:border-box}.c2g-filter-bar__search-input:focus{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));box-shadow:0 0 0 3px color-mix(in srgb,var(--c2g-theme-primary, var(--c2g-color-primary)) 12%,transparent)}.c2g-filter-bar__search-input::placeholder{color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted))}.c2g-filter-bar__search-icon{position:absolute;right:10px;top:50%;transform:translateY(-50%);pointer-events:none;font-size:.875rem;opacity:.6}.c2g-filter-bar__groups{display:flex;flex-wrap:wrap;gap:12px;flex:1}.c2g-filter-bar__group{display:flex;align-items:center;gap:8px}.c2g-filter-bar__group-label{font-size:var(--c2g-font-size-xs, .75rem);font-weight:600;color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-muted));text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}.c2g-filter-bar__options{display:flex;flex-wrap:wrap;gap:6px}.c2g-filter-bar__option{display:inline-flex;align-items:center;gap:4px;padding:5px 12px;border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:20px;background:var(--c2g-theme-surface, var(--c2g-color-surface));cursor:pointer;font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-on-surface-variant, var(--c2g-color-text-secondary));transition:border-color .15s ease,background .15s ease,color .15s ease;white-space:nowrap}.c2g-filter-bar__option:hover{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));color:var(--c2g-theme-primary, var(--c2g-color-primary))}.c2g-filter-bar__option--active{border-color:var(--c2g-theme-primary, var(--c2g-color-primary));background:var(--c2g-theme-primary-container, var(--c2g-color-primary-container));color:var(--c2g-theme-primary, var(--c2g-color-primary));font-weight:600}.c2g-filter-bar__option:focus-visible{outline:2px solid var(--c2g-theme-primary, var(--c2g-color-primary));outline-offset:2px}.c2g-filter-bar__option-icon{font-size:.875rem;line-height:1}.c2g-filter-bar__option-count{font-size:.75rem;opacity:.7}.c2g-filter-bar__clear{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border:1px solid var(--c2g-theme-error, var(--c2g-color-error));border-radius:20px;background:none;cursor:pointer;font-family:inherit;font-size:var(--c2g-font-size-sm, .875rem);color:var(--c2g-theme-error, var(--c2g-color-error));transition:background .15s ease;white-space:nowrap}.c2g-filter-bar__clear:hover{background:var(--c2g-theme-error-container, #fff5f5)}.c2g-filter-bar__clear:focus-visible{outline:2px solid var(--c2g-theme-error, var(--c2g-color-error));outline-offset:2px}.c2g-filter-bar__clear-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 4px;border-radius:9px;background:var(--c2g-theme-error, var(--c2g-color-error));color:var(--c2g-theme-surface, var(--c2g-color-surface));font-size:.7rem;font-weight:700}\n"] }]
|
|
747
|
+
}], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], activeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFilters", required: false }] }, { type: i0.Output, args: ["activeFiltersChange"] }], filterChanged: [{ type: i0.Output, args: ["filterChanged"] }], searchChanged: [{ type: i0.Output, args: ["searchChanged"] }] } });
|
|
748
|
+
|
|
749
|
+
class SkeletonTableComponent {
|
|
750
|
+
rows = input(5, ...(ngDevMode ? [{ debugName: "rows" }] : []));
|
|
751
|
+
columns = input(4, ...(ngDevMode ? [{ debugName: "columns" }] : []));
|
|
752
|
+
showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : []));
|
|
753
|
+
rowIndices = Array.from({ length: 10 }).map((_, i) => i);
|
|
754
|
+
colIndices = Array.from({ length: 10 }).map((_, i) => i);
|
|
755
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SkeletonTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
756
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: SkeletonTableComponent, isStandalone: true, selector: "c2g-skeleton-table", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"c2g-skeleton-table\">\n <table class=\"c2g-skeleton-table__table\" aria-busy=\"true\" aria-label=\"Wird geladen...\">\n @if (showHeader()) {\n <thead class=\"c2g-skeleton-table__head\">\n <tr>\n @for (c of colIndices.slice(0, columns()); track c) {\n <th class=\"c2g-skeleton-table__th\">\n <span class=\"c2g-skeleton c2g-skeleton--header\"></span>\n </th>\n }\n </tr>\n </thead>\n }\n <tbody>\n @for (r of rowIndices.slice(0, rows()); track r) {\n <tr class=\"c2g-skeleton-table__row\">\n @for (c of colIndices.slice(0, columns()); track c; let first = $first) {\n <td class=\"c2g-skeleton-table__td\">\n <span\n class=\"c2g-skeleton\"\n [class.c2g-skeleton--wide]=\"first\"\n ></span>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n</div>\n", styles: ["@keyframes c2g-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}:host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-skeleton-table{border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-md, 8px);overflow:hidden}.c2g-skeleton-table__table{width:100%;border-collapse:collapse}.c2g-skeleton-table__head{background:var(--c2g-theme-surface-container, var(--c2g-color-bg-secondary))}.c2g-skeleton-table__th,.c2g-skeleton-table__td{padding:12px 16px;border-bottom:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline))}.c2g-skeleton-table__row:last-child .c2g-skeleton-table__td{border-bottom:none}.c2g-skeleton{display:block;height:12px;border-radius:6px;background:linear-gradient(90deg,var(--c2g-theme-surface-container-high, var(--c2g-color-bg-secondary)) 25%,var(--c2g-theme-surface-container-highest, var(--c2g-color-bg-base)) 50%,var(--c2g-theme-surface-container-high, var(--c2g-color-bg-secondary)) 75%);background-size:200% 100%;animation:c2g-shimmer 1.5s infinite linear;width:60%}.c2g-skeleton--header{height:14px;width:40%}.c2g-skeleton--wide{width:85%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
757
|
+
}
|
|
758
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SkeletonTableComponent, decorators: [{
|
|
759
|
+
type: Component,
|
|
760
|
+
args: [{ selector: 'c2g-skeleton-table', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c2g-skeleton-table\">\n <table class=\"c2g-skeleton-table__table\" aria-busy=\"true\" aria-label=\"Wird geladen...\">\n @if (showHeader()) {\n <thead class=\"c2g-skeleton-table__head\">\n <tr>\n @for (c of colIndices.slice(0, columns()); track c) {\n <th class=\"c2g-skeleton-table__th\">\n <span class=\"c2g-skeleton c2g-skeleton--header\"></span>\n </th>\n }\n </tr>\n </thead>\n }\n <tbody>\n @for (r of rowIndices.slice(0, rows()); track r) {\n <tr class=\"c2g-skeleton-table__row\">\n @for (c of colIndices.slice(0, columns()); track c; let first = $first) {\n <td class=\"c2g-skeleton-table__td\">\n <span\n class=\"c2g-skeleton\"\n [class.c2g-skeleton--wide]=\"first\"\n ></span>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n</div>\n", styles: ["@keyframes c2g-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}:host{display:block;transition:background-color var(--c2g-transition-medium, .25s ease),color var(--c2g-transition-medium, .25s ease),border-color var(--c2g-transition-medium, .25s ease)}.c2g-skeleton-table{border:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline));border-radius:var(--c2g-radius-md, 8px);overflow:hidden}.c2g-skeleton-table__table{width:100%;border-collapse:collapse}.c2g-skeleton-table__head{background:var(--c2g-theme-surface-container, var(--c2g-color-bg-secondary))}.c2g-skeleton-table__th,.c2g-skeleton-table__td{padding:12px 16px;border-bottom:1px solid var(--c2g-theme-outline-variant, var(--c2g-color-outline))}.c2g-skeleton-table__row:last-child .c2g-skeleton-table__td{border-bottom:none}.c2g-skeleton{display:block;height:12px;border-radius:6px;background:linear-gradient(90deg,var(--c2g-theme-surface-container-high, var(--c2g-color-bg-secondary)) 25%,var(--c2g-theme-surface-container-highest, var(--c2g-color-bg-base)) 50%,var(--c2g-theme-surface-container-high, var(--c2g-color-bg-secondary)) 75%);background-size:200% 100%;animation:c2g-shimmer 1.5s infinite linear;width:60%}.c2g-skeleton--header{height:14px;width:40%}.c2g-skeleton--wide{width:85%}\n"] }]
|
|
761
|
+
}], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }] } });
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Generated bundle index. Do not edit.
|
|
765
|
+
*/
|
|
766
|
+
|
|
767
|
+
export { ActionCardComponent, BreadcrumbComponent, C2gKpiCardComponent, ContentPanelComponent, CoverageKpiComponent, DangerZoneComponent, DangerZoneItemComponent, EmptyStateComponent, FilterBarComponent, HeroComponent, KpiCardComponent, ListItemComponent, PaginationComponent, SearchInputComponent, SegmentedToggleComponent, SkeletonTableComponent, StatCardComponent, StepperComponent, TableComponent, TabsComponent, ViewToggleComponent };
|
|
768
|
+
//# sourceMappingURL=camp2gether-c2g-ui-layout.mjs.map
|