@forgeroute/ui 0.3.12 → 0.3.13

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.
@@ -11345,6 +11345,278 @@ i0.ɵɵngDeclareClassMetadata({
11345
11345
  }]
11346
11346
  }
11347
11347
  });
11348
+ var ProgressRingComponent = class ProgressRingComponent {
11349
+ constructor() {
11350
+ this.value = input(0, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
11351
+ this.max = input(100, ...ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []);
11352
+ this.size = input(58, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
11353
+ this.strokeWidth = input(5, ...ngDevMode ? [{ debugName: "strokeWidth" }] : /* istanbul ignore next */ []);
11354
+ this.variant = input(null, ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
11355
+ this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
11356
+ this.showValue = input(true, ...ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []);
11357
+ this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
11358
+ this.ariaLabelledby = input("", ...ngDevMode ? [{ debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []);
11359
+ this.valueText = input("", ...ngDevMode ? [{ debugName: "valueText" }] : /* istanbul ignore next */ []);
11360
+ this.safeMax = computed(() => {
11361
+ const m = this.max();
11362
+ return Number.isFinite(m) && m > 0 ? m : 0;
11363
+ }, ...ngDevMode ? [{ debugName: "safeMax" }] : /* istanbul ignore next */ []);
11364
+ this.clampedValue = computed(() => {
11365
+ const v = this.value();
11366
+ return Math.min(Math.max(Number.isNaN(v) ? 0 : v, 0), this.safeMax());
11367
+ }, ...ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []);
11368
+ this.exact = computed(() => this.safeMax() > 0 ? this.clampedValue() / this.safeMax() * 100 : 0, ...ngDevMode ? [{ debugName: "exact" }] : /* istanbul ignore next */ []);
11369
+ this.percent = computed(() => Math.round(this.exact()), ...ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []);
11370
+ this.center = computed(() => this.size() / 2, ...ngDevMode ? [{ debugName: "center" }] : /* istanbul ignore next */ []);
11371
+ this.radius = computed(() => Math.max((this.size() - this.strokeWidth()) / 2, 0), ...ngDevMode ? [{ debugName: "radius" }] : /* istanbul ignore next */ []);
11372
+ this.circumference = computed(() => 2 * Math.PI * this.radius(), ...ngDevMode ? [{ debugName: "circumference" }] : /* istanbul ignore next */ []);
11373
+ this.dashOffset = computed(() => this.circumference() * (1 - this.exact() / 100), ...ngDevMode ? [{ debugName: "dashOffset" }] : /* istanbul ignore next */ []);
11374
+ this.effectiveVariant = computed(() => {
11375
+ const fixed = this.variant();
11376
+ if (fixed) return fixed;
11377
+ const e = this.exact();
11378
+ return e <= 25 ? "red" : e <= 50 ? "amber" : e <= 75 ? "blue" : "green";
11379
+ }, ...ngDevMode ? [{ debugName: "effectiveVariant" }] : /* istanbul ignore next */ []);
11380
+ }
11381
+ static {
11382
+ this.ɵfac = i0.ɵɵngDeclareFactory({
11383
+ minVersion: "12.0.0",
11384
+ version: "22.2.2",
11385
+ ngImport: i0,
11386
+ type: ProgressRingComponent,
11387
+ deps: [],
11388
+ target: i0.ɵɵFactoryTarget.Component
11389
+ });
11390
+ }
11391
+ static {
11392
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
11393
+ minVersion: "17.0.0",
11394
+ version: "22.2.2",
11395
+ type: ProgressRingComponent,
11396
+ isStandalone: true,
11397
+ selector: "ui-progress-ring",
11398
+ inputs: {
11399
+ value: {
11400
+ classPropertyName: "value",
11401
+ publicName: "value",
11402
+ isSignal: true,
11403
+ isRequired: false,
11404
+ transformFunction: null
11405
+ },
11406
+ max: {
11407
+ classPropertyName: "max",
11408
+ publicName: "max",
11409
+ isSignal: true,
11410
+ isRequired: false,
11411
+ transformFunction: null
11412
+ },
11413
+ size: {
11414
+ classPropertyName: "size",
11415
+ publicName: "size",
11416
+ isSignal: true,
11417
+ isRequired: false,
11418
+ transformFunction: null
11419
+ },
11420
+ strokeWidth: {
11421
+ classPropertyName: "strokeWidth",
11422
+ publicName: "strokeWidth",
11423
+ isSignal: true,
11424
+ isRequired: false,
11425
+ transformFunction: null
11426
+ },
11427
+ variant: {
11428
+ classPropertyName: "variant",
11429
+ publicName: "variant",
11430
+ isSignal: true,
11431
+ isRequired: false,
11432
+ transformFunction: null
11433
+ },
11434
+ label: {
11435
+ classPropertyName: "label",
11436
+ publicName: "label",
11437
+ isSignal: true,
11438
+ isRequired: false,
11439
+ transformFunction: null
11440
+ },
11441
+ showValue: {
11442
+ classPropertyName: "showValue",
11443
+ publicName: "showValue",
11444
+ isSignal: true,
11445
+ isRequired: false,
11446
+ transformFunction: null
11447
+ },
11448
+ ariaLabel: {
11449
+ classPropertyName: "ariaLabel",
11450
+ publicName: "ariaLabel",
11451
+ isSignal: true,
11452
+ isRequired: false,
11453
+ transformFunction: null
11454
+ },
11455
+ ariaLabelledby: {
11456
+ classPropertyName: "ariaLabelledby",
11457
+ publicName: "ariaLabelledby",
11458
+ isSignal: true,
11459
+ isRequired: false,
11460
+ transformFunction: null
11461
+ },
11462
+ valueText: {
11463
+ classPropertyName: "valueText",
11464
+ publicName: "valueText",
11465
+ isSignal: true,
11466
+ isRequired: false,
11467
+ transformFunction: null
11468
+ }
11469
+ },
11470
+ ngImport: i0,
11471
+ template: `
11472
+ <div class="pr"
11473
+ role="progressbar"
11474
+ [style.width.px]="size()"
11475
+ [style.height.px]="size()"
11476
+ [attr.aria-valuemin]="0"
11477
+ [attr.aria-valuemax]="safeMax()"
11478
+ [attr.aria-valuenow]="clampedValue()"
11479
+ [attr.aria-valuetext]="valueText() || null"
11480
+ [attr.aria-labelledby]="ariaLabelledby() || null"
11481
+ [attr.aria-label]="ariaLabelledby() ? null : (ariaLabel() || null)">
11482
+ <svg [attr.width]="size()" [attr.height]="size()" [attr.viewBox]="'0 0 ' + size() + ' ' + size()" aria-hidden="true" focusable="false">
11483
+ <circle class="pr-track" [attr.cx]="center()" [attr.cy]="center()" [attr.r]="radius()" fill="none" [attr.stroke-width]="strokeWidth()" />
11484
+ <circle [class]="'pr-arc pr-' + effectiveVariant()" [attr.cx]="center()" [attr.cy]="center()" [attr.r]="radius()" fill="none"
11485
+ [attr.stroke-width]="strokeWidth()" stroke-linecap="round"
11486
+ [attr.stroke-dasharray]="circumference()" [attr.stroke-dashoffset]="dashOffset()"
11487
+ [attr.transform]="'rotate(-90 ' + center() + ' ' + center() + ')'" />
11488
+ </svg>
11489
+ @if (showValue()) {
11490
+ <span class="pr-value" [style.font-size.px]="size() * 0.21">{{ label() || percent() + '%' }}</span>
11491
+ }
11492
+ </div>
11493
+ `,
11494
+ isInline: true,
11495
+ styles: [":host{display:inline-block;line-height:0}.pr{position:relative;display:inline-flex;align-items:center;justify-content:center}.pr svg{position:absolute;inset:0}.pr-track{stroke:#e2e8f0}.pr-arc{transition:stroke-dashoffset .8s ease}@media(prefers-reduced-motion:reduce){.pr-arc{transition:none}}.pr-blue{stroke:#3b82f6}.pr-green{stroke:#16a34a}.pr-amber{stroke:#f59e0b}.pr-red{stroke:#ef4444}.pr-slate{stroke:#94a3b8}.pr-sky{stroke:#0ea5e9}@media(forced-colors:active){.pr-track{stroke:CanvasText;opacity:.35}.pr-arc{stroke:Highlight}}.pr-value{position:relative;font-weight:700;line-height:1;color:#1e293b}\n"],
11496
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
11497
+ });
11498
+ }
11499
+ };
11500
+ i0.ɵɵngDeclareClassMetadata({
11501
+ minVersion: "12.0.0",
11502
+ version: "22.2.2",
11503
+ ngImport: i0,
11504
+ type: ProgressRingComponent,
11505
+ decorators: [{
11506
+ type: Component,
11507
+ args: [{
11508
+ selector: "ui-progress-ring",
11509
+ standalone: true,
11510
+ changeDetection: ChangeDetectionStrategy.OnPush,
11511
+ template: `
11512
+ <div class="pr"
11513
+ role="progressbar"
11514
+ [style.width.px]="size()"
11515
+ [style.height.px]="size()"
11516
+ [attr.aria-valuemin]="0"
11517
+ [attr.aria-valuemax]="safeMax()"
11518
+ [attr.aria-valuenow]="clampedValue()"
11519
+ [attr.aria-valuetext]="valueText() || null"
11520
+ [attr.aria-labelledby]="ariaLabelledby() || null"
11521
+ [attr.aria-label]="ariaLabelledby() ? null : (ariaLabel() || null)">
11522
+ <svg [attr.width]="size()" [attr.height]="size()" [attr.viewBox]="'0 0 ' + size() + ' ' + size()" aria-hidden="true" focusable="false">
11523
+ <circle class="pr-track" [attr.cx]="center()" [attr.cy]="center()" [attr.r]="radius()" fill="none" [attr.stroke-width]="strokeWidth()" />
11524
+ <circle [class]="'pr-arc pr-' + effectiveVariant()" [attr.cx]="center()" [attr.cy]="center()" [attr.r]="radius()" fill="none"
11525
+ [attr.stroke-width]="strokeWidth()" stroke-linecap="round"
11526
+ [attr.stroke-dasharray]="circumference()" [attr.stroke-dashoffset]="dashOffset()"
11527
+ [attr.transform]="'rotate(-90 ' + center() + ' ' + center() + ')'" />
11528
+ </svg>
11529
+ @if (showValue()) {
11530
+ <span class="pr-value" [style.font-size.px]="size() * 0.21">{{ label() || percent() + '%' }}</span>
11531
+ }
11532
+ </div>
11533
+ `,
11534
+ styles: [":host{display:inline-block;line-height:0}.pr{position:relative;display:inline-flex;align-items:center;justify-content:center}.pr svg{position:absolute;inset:0}.pr-track{stroke:#e2e8f0}.pr-arc{transition:stroke-dashoffset .8s ease}@media(prefers-reduced-motion:reduce){.pr-arc{transition:none}}.pr-blue{stroke:#3b82f6}.pr-green{stroke:#16a34a}.pr-amber{stroke:#f59e0b}.pr-red{stroke:#ef4444}.pr-slate{stroke:#94a3b8}.pr-sky{stroke:#0ea5e9}@media(forced-colors:active){.pr-track{stroke:CanvasText;opacity:.35}.pr-arc{stroke:Highlight}}.pr-value{position:relative;font-weight:700;line-height:1;color:#1e293b}\n"]
11535
+ }]
11536
+ }],
11537
+ propDecorators: {
11538
+ value: [{
11539
+ type: i0.Input,
11540
+ args: [{
11541
+ isSignal: true,
11542
+ alias: "value",
11543
+ required: false
11544
+ }]
11545
+ }],
11546
+ max: [{
11547
+ type: i0.Input,
11548
+ args: [{
11549
+ isSignal: true,
11550
+ alias: "max",
11551
+ required: false
11552
+ }]
11553
+ }],
11554
+ size: [{
11555
+ type: i0.Input,
11556
+ args: [{
11557
+ isSignal: true,
11558
+ alias: "size",
11559
+ required: false
11560
+ }]
11561
+ }],
11562
+ strokeWidth: [{
11563
+ type: i0.Input,
11564
+ args: [{
11565
+ isSignal: true,
11566
+ alias: "strokeWidth",
11567
+ required: false
11568
+ }]
11569
+ }],
11570
+ variant: [{
11571
+ type: i0.Input,
11572
+ args: [{
11573
+ isSignal: true,
11574
+ alias: "variant",
11575
+ required: false
11576
+ }]
11577
+ }],
11578
+ label: [{
11579
+ type: i0.Input,
11580
+ args: [{
11581
+ isSignal: true,
11582
+ alias: "label",
11583
+ required: false
11584
+ }]
11585
+ }],
11586
+ showValue: [{
11587
+ type: i0.Input,
11588
+ args: [{
11589
+ isSignal: true,
11590
+ alias: "showValue",
11591
+ required: false
11592
+ }]
11593
+ }],
11594
+ ariaLabel: [{
11595
+ type: i0.Input,
11596
+ args: [{
11597
+ isSignal: true,
11598
+ alias: "ariaLabel",
11599
+ required: false
11600
+ }]
11601
+ }],
11602
+ ariaLabelledby: [{
11603
+ type: i0.Input,
11604
+ args: [{
11605
+ isSignal: true,
11606
+ alias: "ariaLabelledby",
11607
+ required: false
11608
+ }]
11609
+ }],
11610
+ valueText: [{
11611
+ type: i0.Input,
11612
+ args: [{
11613
+ isSignal: true,
11614
+ alias: "valueText",
11615
+ required: false
11616
+ }]
11617
+ }]
11618
+ }
11619
+ });
11348
11620
  var AudioPlayerComponent = class AudioPlayerComponent {
11349
11621
  constructor() {
11350
11622
  this.src = input("", ...ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []);
@@ -33167,6 +33439,14 @@ var KpiCardComponent = class KpiCardComponent {
33167
33439
  this.highlight = input(false, ...ngDevMode ? [{ debugName: "highlight" }] : /* istanbul ignore next */ []);
33168
33440
  this.clickable = input(false, ...ngDevMode ? [{ debugName: "clickable" }] : /* istanbul ignore next */ []);
33169
33441
  this.valueColor = input("default", ...ngDevMode ? [{ debugName: "valueColor" }] : /* istanbul ignore next */ []);
33442
+ this.progress = input(null, ...ngDevMode ? [{ debugName: "progress" }] : /* istanbul ignore next */ []);
33443
+ this.progressMax = input(100, ...ngDevMode ? [{ debugName: "progressMax" }] : /* istanbul ignore next */ []);
33444
+ this.progressSize = input(58, ...ngDevMode ? [{ debugName: "progressSize" }] : /* istanbul ignore next */ []);
33445
+ this.progressStrokeWidth = input(5, ...ngDevMode ? [{ debugName: "progressStrokeWidth" }] : /* istanbul ignore next */ []);
33446
+ this.progressVariant = input(null, ...ngDevMode ? [{ debugName: "progressVariant" }] : /* istanbul ignore next */ []);
33447
+ this.progressAriaLabel = input("", ...ngDevMode ? [{ debugName: "progressAriaLabel" }] : /* istanbul ignore next */ []);
33448
+ this.progressValueText = input("", ...ngDevMode ? [{ debugName: "progressValueText" }] : /* istanbul ignore next */ []);
33449
+ this.hasProgress = computed(() => this.progress() !== null && this.progress() !== void 0, ...ngDevMode ? [{ debugName: "hasProgress" }] : /* istanbul ignore next */ []);
33170
33450
  this.iconSvg = computed(() => {
33171
33451
  const svg = KPI_ICONS[this.icon()];
33172
33452
  return svg ? this.sanitizer.bypassSecurityTrustHtml(svg) : null;
@@ -33250,6 +33530,55 @@ var KpiCardComponent = class KpiCardComponent {
33250
33530
  isSignal: true,
33251
33531
  isRequired: false,
33252
33532
  transformFunction: null
33533
+ },
33534
+ progress: {
33535
+ classPropertyName: "progress",
33536
+ publicName: "progress",
33537
+ isSignal: true,
33538
+ isRequired: false,
33539
+ transformFunction: null
33540
+ },
33541
+ progressMax: {
33542
+ classPropertyName: "progressMax",
33543
+ publicName: "progressMax",
33544
+ isSignal: true,
33545
+ isRequired: false,
33546
+ transformFunction: null
33547
+ },
33548
+ progressSize: {
33549
+ classPropertyName: "progressSize",
33550
+ publicName: "progressSize",
33551
+ isSignal: true,
33552
+ isRequired: false,
33553
+ transformFunction: null
33554
+ },
33555
+ progressStrokeWidth: {
33556
+ classPropertyName: "progressStrokeWidth",
33557
+ publicName: "progressStrokeWidth",
33558
+ isSignal: true,
33559
+ isRequired: false,
33560
+ transformFunction: null
33561
+ },
33562
+ progressVariant: {
33563
+ classPropertyName: "progressVariant",
33564
+ publicName: "progressVariant",
33565
+ isSignal: true,
33566
+ isRequired: false,
33567
+ transformFunction: null
33568
+ },
33569
+ progressAriaLabel: {
33570
+ classPropertyName: "progressAriaLabel",
33571
+ publicName: "progressAriaLabel",
33572
+ isSignal: true,
33573
+ isRequired: false,
33574
+ transformFunction: null
33575
+ },
33576
+ progressValueText: {
33577
+ classPropertyName: "progressValueText",
33578
+ publicName: "progressValueText",
33579
+ isSignal: true,
33580
+ isRequired: false,
33581
+ transformFunction: null
33253
33582
  }
33254
33583
  },
33255
33584
  host: {
@@ -33268,20 +33597,46 @@ var KpiCardComponent = class KpiCardComponent {
33268
33597
  @if (iconSvg()) {
33269
33598
  <div [class]="'kpi-icon ' + color() + '-icon'" aria-hidden="true" [innerHTML]="iconSvg()"></div>
33270
33599
  }
33271
- <span class="kpi-label">{{ label() }}</span>
33600
+ @if (hasProgress()) {
33601
+ <div class="kpi-top">
33602
+ <span class="kpi-label">{{ label() }}</span>
33603
+ <ui-progress-ring class="kpi-ring" [value]="progress()!" [max]="progressMax()" [size]="progressSize()" [strokeWidth]="progressStrokeWidth()"
33604
+ [variant]="progressVariant()" [ariaLabel]="progressAriaLabel() || (label() + ' progress')" [valueText]="progressValueText()" />
33605
+ </div>
33606
+ } @else {
33607
+ <span class="kpi-label">{{ label() }}</span>
33608
+ }
33272
33609
  <span class="kpi-value"
33273
33610
  [class.green-value]="highlight() || valueColor() === 'green'"
33274
33611
  [class.blue-value]="valueColor() === 'blue'">{{ value() }}</span>
33275
33612
  @if (subtitle()) {
33276
33613
  <span class="kpi-subtitle">{{ subtitle() }}</span>
33277
33614
  }
33615
+ <ng-content select="[kpi-footer]" />
33278
33616
  @if (clickable()) {
33279
33617
  <svg class="kpi-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
33280
33618
  }
33281
33619
  </div>
33282
33620
  `,
33283
33621
  isInline: true,
33284
- styles: [":host{display:block;height:100%}.kpi-card{position:relative;background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:4px;min-width:0;height:100%;box-sizing:border-box;transition:border-color .15s ease,box-shadow .15s ease}:host(:focus){outline:none}:host(:focus-visible) .kpi-card{outline:2px solid #3b82f6;outline-offset:2px}.kpi-card.clickable{cursor:pointer}.kpi-card.clickable:hover{border-color:#93c5fd;box-shadow:0 2px 8px #3b82f614}.kpi-card.clickable:hover .kpi-arrow{color:#3b82f6;transform:translate(2px)}.kpi-arrow{position:absolute;bottom:14px;right:14px;color:#94a3b8;transition:color .15s ease,transform .15s ease}.kpi-icon{flex-shrink:0;width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;margin-bottom:8px}.green-icon{background:#dcfce7;color:#16a34a}.blue-icon{background:#dbeafe;color:#2563eb}.amber-icon{background:#fef3c7;color:#d97706}.orange-icon{background:#ffedd5;color:#c2410c}.red-icon{background:#fee2e2;color:#dc2626}.slate-icon{background:#f1f5f9;color:#475569}.kpi-label{font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:.04em}.kpi-value{font-size:1.5rem;font-weight:700;color:#111827;line-height:1.1}.kpi-value.green-value{color:#16a34a}.kpi-value.blue-value{color:#3b82f6}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}\n"],
33622
+ styles: [":host{display:block;height:100%}.kpi-card{position:relative;background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:4px;min-width:0;height:100%;box-sizing:border-box;transition:border-color .15s ease,box-shadow .15s ease}:host(:focus){outline:none}:host(:focus-visible) .kpi-card{outline:2px solid #3b82f6;outline-offset:2px}.kpi-card.clickable{cursor:pointer}.kpi-card.clickable:hover{border-color:#93c5fd;box-shadow:0 2px 8px #3b82f614}.kpi-card.clickable:hover .kpi-arrow{color:#3b82f6;transform:translate(2px)}.kpi-arrow{position:absolute;bottom:14px;right:14px;color:#94a3b8;transition:color .15s ease,transform .15s ease}.kpi-icon{flex-shrink:0;width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;margin-bottom:8px}.green-icon{background:#dcfce7;color:#16a34a}.blue-icon{background:#dbeafe;color:#2563eb}.amber-icon{background:#fef3c7;color:#d97706}.orange-icon{background:#ffedd5;color:#c2410c}.red-icon{background:#fee2e2;color:#dc2626}.slate-icon{background:#f1f5f9;color:#475569}.kpi-label{font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:.04em}.kpi-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-height:36px;margin-bottom:4px}.kpi-ring{flex-shrink:0}.kpi-value{font-size:1.5rem;font-weight:700;color:#111827;line-height:1.1}.kpi-value.green-value{color:#16a34a}.kpi-value.blue-value{color:#3b82f6}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}\n"],
33623
+ dependencies: [{
33624
+ kind: "component",
33625
+ type: ProgressRingComponent,
33626
+ selector: "ui-progress-ring",
33627
+ inputs: [
33628
+ "value",
33629
+ "max",
33630
+ "size",
33631
+ "strokeWidth",
33632
+ "variant",
33633
+ "label",
33634
+ "showValue",
33635
+ "ariaLabel",
33636
+ "ariaLabelledby",
33637
+ "valueText"
33638
+ ]
33639
+ }],
33285
33640
  changeDetection: i0.ChangeDetectionStrategy.OnPush
33286
33641
  });
33287
33642
  }
@@ -33296,6 +33651,7 @@ i0.ɵɵngDeclareClassMetadata({
33296
33651
  args: [{
33297
33652
  selector: "ui-kpi-card",
33298
33653
  standalone: true,
33654
+ imports: [ProgressRingComponent],
33299
33655
  changeDetection: ChangeDetectionStrategy.OnPush,
33300
33656
  host: {
33301
33657
  "[attr.role]": "clickable() ? \"button\" : null",
@@ -33308,19 +33664,28 @@ i0.ɵɵngDeclareClassMetadata({
33308
33664
  @if (iconSvg()) {
33309
33665
  <div [class]="'kpi-icon ' + color() + '-icon'" aria-hidden="true" [innerHTML]="iconSvg()"></div>
33310
33666
  }
33311
- <span class="kpi-label">{{ label() }}</span>
33667
+ @if (hasProgress()) {
33668
+ <div class="kpi-top">
33669
+ <span class="kpi-label">{{ label() }}</span>
33670
+ <ui-progress-ring class="kpi-ring" [value]="progress()!" [max]="progressMax()" [size]="progressSize()" [strokeWidth]="progressStrokeWidth()"
33671
+ [variant]="progressVariant()" [ariaLabel]="progressAriaLabel() || (label() + ' progress')" [valueText]="progressValueText()" />
33672
+ </div>
33673
+ } @else {
33674
+ <span class="kpi-label">{{ label() }}</span>
33675
+ }
33312
33676
  <span class="kpi-value"
33313
33677
  [class.green-value]="highlight() || valueColor() === 'green'"
33314
33678
  [class.blue-value]="valueColor() === 'blue'">{{ value() }}</span>
33315
33679
  @if (subtitle()) {
33316
33680
  <span class="kpi-subtitle">{{ subtitle() }}</span>
33317
33681
  }
33682
+ <ng-content select="[kpi-footer]" />
33318
33683
  @if (clickable()) {
33319
33684
  <svg class="kpi-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
33320
33685
  }
33321
33686
  </div>
33322
33687
  `,
33323
- styles: [":host{display:block;height:100%}.kpi-card{position:relative;background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:4px;min-width:0;height:100%;box-sizing:border-box;transition:border-color .15s ease,box-shadow .15s ease}:host(:focus){outline:none}:host(:focus-visible) .kpi-card{outline:2px solid #3b82f6;outline-offset:2px}.kpi-card.clickable{cursor:pointer}.kpi-card.clickable:hover{border-color:#93c5fd;box-shadow:0 2px 8px #3b82f614}.kpi-card.clickable:hover .kpi-arrow{color:#3b82f6;transform:translate(2px)}.kpi-arrow{position:absolute;bottom:14px;right:14px;color:#94a3b8;transition:color .15s ease,transform .15s ease}.kpi-icon{flex-shrink:0;width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;margin-bottom:8px}.green-icon{background:#dcfce7;color:#16a34a}.blue-icon{background:#dbeafe;color:#2563eb}.amber-icon{background:#fef3c7;color:#d97706}.orange-icon{background:#ffedd5;color:#c2410c}.red-icon{background:#fee2e2;color:#dc2626}.slate-icon{background:#f1f5f9;color:#475569}.kpi-label{font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:.04em}.kpi-value{font-size:1.5rem;font-weight:700;color:#111827;line-height:1.1}.kpi-value.green-value{color:#16a34a}.kpi-value.blue-value{color:#3b82f6}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}\n"]
33688
+ styles: [":host{display:block;height:100%}.kpi-card{position:relative;background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:4px;min-width:0;height:100%;box-sizing:border-box;transition:border-color .15s ease,box-shadow .15s ease}:host(:focus){outline:none}:host(:focus-visible) .kpi-card{outline:2px solid #3b82f6;outline-offset:2px}.kpi-card.clickable{cursor:pointer}.kpi-card.clickable:hover{border-color:#93c5fd;box-shadow:0 2px 8px #3b82f614}.kpi-card.clickable:hover .kpi-arrow{color:#3b82f6;transform:translate(2px)}.kpi-arrow{position:absolute;bottom:14px;right:14px;color:#94a3b8;transition:color .15s ease,transform .15s ease}.kpi-icon{flex-shrink:0;width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;margin-bottom:8px}.green-icon{background:#dcfce7;color:#16a34a}.blue-icon{background:#dbeafe;color:#2563eb}.amber-icon{background:#fef3c7;color:#d97706}.orange-icon{background:#ffedd5;color:#c2410c}.red-icon{background:#fee2e2;color:#dc2626}.slate-icon{background:#f1f5f9;color:#475569}.kpi-label{font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:.04em}.kpi-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-height:36px;margin-bottom:4px}.kpi-ring{flex-shrink:0}.kpi-value{font-size:1.5rem;font-weight:700;color:#111827;line-height:1.1}.kpi-value.green-value{color:#16a34a}.kpi-value.blue-value{color:#3b82f6}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}\n"]
33324
33689
  }]
33325
33690
  }],
33326
33691
  propDecorators: {
@@ -33387,6 +33752,62 @@ i0.ɵɵngDeclareClassMetadata({
33387
33752
  alias: "valueColor",
33388
33753
  required: false
33389
33754
  }]
33755
+ }],
33756
+ progress: [{
33757
+ type: i0.Input,
33758
+ args: [{
33759
+ isSignal: true,
33760
+ alias: "progress",
33761
+ required: false
33762
+ }]
33763
+ }],
33764
+ progressMax: [{
33765
+ type: i0.Input,
33766
+ args: [{
33767
+ isSignal: true,
33768
+ alias: "progressMax",
33769
+ required: false
33770
+ }]
33771
+ }],
33772
+ progressSize: [{
33773
+ type: i0.Input,
33774
+ args: [{
33775
+ isSignal: true,
33776
+ alias: "progressSize",
33777
+ required: false
33778
+ }]
33779
+ }],
33780
+ progressStrokeWidth: [{
33781
+ type: i0.Input,
33782
+ args: [{
33783
+ isSignal: true,
33784
+ alias: "progressStrokeWidth",
33785
+ required: false
33786
+ }]
33787
+ }],
33788
+ progressVariant: [{
33789
+ type: i0.Input,
33790
+ args: [{
33791
+ isSignal: true,
33792
+ alias: "progressVariant",
33793
+ required: false
33794
+ }]
33795
+ }],
33796
+ progressAriaLabel: [{
33797
+ type: i0.Input,
33798
+ args: [{
33799
+ isSignal: true,
33800
+ alias: "progressAriaLabel",
33801
+ required: false
33802
+ }]
33803
+ }],
33804
+ progressValueText: [{
33805
+ type: i0.Input,
33806
+ args: [{
33807
+ isSignal: true,
33808
+ alias: "progressValueText",
33809
+ required: false
33810
+ }]
33390
33811
  }]
33391
33812
  }
33392
33813
  });
@@ -37386,6 +37807,6 @@ i0.ɵɵngDeclareClassMetadata({
37386
37807
  }]
37387
37808
  }
37388
37809
  });
37389
- export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CheckboxComponent, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_DOCUMENT_SUBJECT, DEFAULT_SIGNING_OPTIONS, DOCUMENT_PROVIDER_OPTIONS, DOCUMENT_PURPOSE_OPTIONS, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DocumentMergeCheckComponent, DocumentSendOptionsComponent, DocumentSignersComponent, DropdownComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FileInputComponent, FormRowComponent, FormSectionComponent, HintComponent, IconComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, MAX_CC, MERGE_CHECK_DEBOUNCE_MS, ModalComponent, MoreMenuComponent, MultiSelectComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PaginationComponent, PanelInfoListComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SIGNER_ROLES, SIGNER_ROLE_LABEL_DEFAULT, SIGNING_LIMITS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SendMessagePanelComponent, SidePanelComponent, SkeletonComponent, SortableItemDirective, SortableListComponent, StackComponent, StepperComponent, TableToolbarComponent, TemplatePickerComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, VideoPickerComponent, acceptLabel, appShellGroupsStorageKey, appendVideoLink, applyVideoLine, autoVariant, buildDefaultSchedule, buildSigners, buildVideoLink, builtInActionIcon, businessTimeOptions, countersignLine, countersignPlaceLabel, createFieldReveal, decodeFilterValues, describeDocumentSigners, digitsOnly, effectiveRoles, encodeFilterValue, encodeFilterValues, errorContextInterceptor, fileMatchesAccept, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, forwardContext, getEligibleIds, getEligibleOptions, getErrorMessage, hasMappedDataFields, humanReadableMessage, iconPath, isoKey, issueToErrors, maxLengthIssue, mergeFieldText, mergeWarningLines, messagePreviewHtml, normalizeHexColor, normalizeRoles, parseBizHours, parseCcList, parseIso, parseTime, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, roleNumber, sendExistingEnvelope, serializeBizHours, signerProblems, signerRoleLabel, stripVideoLink, suggestDocumentSubject, videoMessageLine };
37810
+ export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CheckboxComponent, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_DOCUMENT_SUBJECT, DEFAULT_SIGNING_OPTIONS, DOCUMENT_PROVIDER_OPTIONS, DOCUMENT_PURPOSE_OPTIONS, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DocumentMergeCheckComponent, DocumentSendOptionsComponent, DocumentSignersComponent, DropdownComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FileInputComponent, FormRowComponent, FormSectionComponent, HintComponent, IconComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, MAX_CC, MERGE_CHECK_DEBOUNCE_MS, ModalComponent, MoreMenuComponent, MultiSelectComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PaginationComponent, PanelInfoListComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SIGNER_ROLES, SIGNER_ROLE_LABEL_DEFAULT, SIGNING_LIMITS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SendMessagePanelComponent, SidePanelComponent, SkeletonComponent, SortableItemDirective, SortableListComponent, StackComponent, StepperComponent, TableToolbarComponent, TemplatePickerComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, VideoPickerComponent, acceptLabel, appShellGroupsStorageKey, appendVideoLink, applyVideoLine, autoVariant, buildDefaultSchedule, buildSigners, buildVideoLink, builtInActionIcon, businessTimeOptions, countersignLine, countersignPlaceLabel, createFieldReveal, decodeFilterValues, describeDocumentSigners, digitsOnly, effectiveRoles, encodeFilterValue, encodeFilterValues, errorContextInterceptor, fileMatchesAccept, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, forwardContext, getEligibleIds, getEligibleOptions, getErrorMessage, hasMappedDataFields, humanReadableMessage, iconPath, isoKey, issueToErrors, maxLengthIssue, mergeFieldText, mergeWarningLines, messagePreviewHtml, normalizeHexColor, normalizeRoles, parseBizHours, parseCcList, parseIso, parseTime, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, roleNumber, sendExistingEnvelope, serializeBizHours, signerProblems, signerRoleLabel, stripVideoLink, suggestDocumentSubject, videoMessageLine };
37390
37811
 
37391
37812
  //# sourceMappingURL=forgeroute-ui.mjs.map