@forgeroute/ui 0.3.4 → 0.3.5

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.
@@ -7,8 +7,8 @@ import { Subject, catchError as catchError$1, debounceTime as debounceTime$1, fi
7
7
  import { DOCUMENT, DatePipe, DecimalPipe, NgTemplateOutlet } from "@angular/common";
8
8
  import * as i1 from "@angular/forms";
9
9
  import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR } from "@angular/forms";
10
- import { BarController, BarElement, CategoryScale, Chart, LinearScale, Tooltip } from "chart.js";
11
10
  import { NavigationEnd, Router, RouterLink, RouterLinkActive } from "@angular/router";
11
+ import { BarController, BarElement, CategoryScale, Chart, LinearScale, Tooltip } from "chart.js";
12
12
  import { DomSanitizer } from "@angular/platform-browser";
13
13
  const FORGEROUTE_CONFIG = new InjectionToken("FORGEROUTE_CONFIG");
14
14
  const DROPDOWN_GROUP = new InjectionToken("DROPDOWN_GROUP");
@@ -2719,6 +2719,8 @@ i0.ɵɵngDeclareClassMetadata({
2719
2719
  var ButtonComponent = class ButtonComponent {
2720
2720
  constructor() {
2721
2721
  this.variant = input("primary", ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
2722
+ this.routerLink = input(null, ...ngDevMode ? [{ debugName: "routerLink" }] : /* istanbul ignore next */ []);
2723
+ this.queryParams = input(null, ...ngDevMode ? [{ debugName: "queryParams" }] : /* istanbul ignore next */ []);
2722
2724
  this.color = input(void 0, ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
2723
2725
  this.active = input(false, ...ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []);
2724
2726
  this.size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
@@ -2756,6 +2758,20 @@ var ButtonComponent = class ButtonComponent {
2756
2758
  isRequired: false,
2757
2759
  transformFunction: null
2758
2760
  },
2761
+ routerLink: {
2762
+ classPropertyName: "routerLink",
2763
+ publicName: "routerLink",
2764
+ isSignal: true,
2765
+ isRequired: false,
2766
+ transformFunction: null
2767
+ },
2768
+ queryParams: {
2769
+ classPropertyName: "queryParams",
2770
+ publicName: "queryParams",
2771
+ isSignal: true,
2772
+ isRequired: false,
2773
+ transformFunction: null
2774
+ },
2759
2775
  color: {
2760
2776
  classPropertyName: "color",
2761
2777
  publicName: "color",
@@ -2850,6 +2866,23 @@ var ButtonComponent = class ButtonComponent {
2850
2866
  },
2851
2867
  ngImport: i0,
2852
2868
  template: `
2869
+ <ng-template #content>
2870
+ @if (loading()) {
2871
+ <span class="spinner"></span>
2872
+ }
2873
+ <ng-content />
2874
+ </ng-template>
2875
+ @if (routerLink() !== null) {
2876
+ <!-- A real link (middle-click, open in new tab, screen readers say "link"): same look as the button of this variant, underlined. -->
2877
+ <a
2878
+ [routerLink]="routerLink()"
2879
+ [queryParams]="queryParams()"
2880
+ [class]="'btn btn-anchor btn-' + variant() + ' btn-' + size()"
2881
+ [class.btn-full]="fullWidth()"
2882
+ [attr.aria-label]="ariaLabel()"
2883
+ [attr.aria-describedby]="ariaDescribedBy() || null"
2884
+ ><ng-container [ngTemplateOutlet]="content" /></a>
2885
+ } @else {
2853
2886
  <button
2854
2887
  [type]="type()"
2855
2888
  [class]="'btn btn-' + variant() + ' btn-' + size()"
@@ -2862,15 +2895,39 @@ var ButtonComponent = class ButtonComponent {
2862
2895
  [attr.aria-describedby]="ariaDescribedBy() || null"
2863
2896
  [style.background]="color() || null"
2864
2897
  [style.border-color]="color() || null"
2865
- >
2866
- @if (loading()) {
2867
- <span class="spinner"></span>
2868
- }
2869
- <ng-content />
2870
- </button>
2898
+ ><ng-container [ngTemplateOutlet]="content" /></button>
2899
+ }
2871
2900
  `,
2872
2901
  isInline: true,
2873
- styles: [":host{display:inline-flex}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:8px;font-weight:600;cursor:pointer;font-family:inherit;transition:all .15s ease;white-space:nowrap}.btn:disabled{opacity:.5;cursor:not-allowed}.btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.btn-full{width:100%}.btn-primary{background:#3b82f6;color:#fff;border:1px solid #3B82F6}.btn-primary:hover:not(:disabled){background:#2563eb;border-color:#2563eb}.btn-secondary{background:#fff;color:#334155;border:1px solid #e2e8f0}.btn-secondary:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.btn-ghost{background:transparent;color:#64748b;border:1px solid transparent}.btn-ghost:hover:not(:disabled){background:#f8fafc;color:#334155}.btn-danger{background:#dc2626;color:#fff;border:1px solid #dc2626}.btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.btn-link{background:none;color:#3b82f6;border:none;padding:0;font-weight:500}.btn-link:hover:not(:disabled){color:#60a5fa}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{padding:0}.btn-warning{background:#f97316;color:#fff;border:1px solid #f97316}.btn-warning:hover:not(:disabled){background:#ea6c0a;border-color:#ea6c0a}.btn-tab{background:none;color:#64748b;border:none;border-bottom:2px solid transparent;border-radius:0;font-weight:600;font-size:.875rem;transition:all .15s}.btn-tab:hover:not(:disabled){background:none;color:#1e293b}.btn-tab.active{color:#3b82f6;border-bottom-color:#3b82f6}.btn-tab.btn-xs,.btn-tab.btn-sm,.btn-tab.btn-md,.btn-tab.btn-lg{padding:10px 20px;border-radius:0}.btn-icon{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon:hover:not(:disabled){background:#f1f5f9;color:#334155}.btn-icon-danger{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon-danger:hover:not(:disabled){background:#fee2e2;color:#dc2626}.btn-xs{padding:3px 8px;font-size:.75rem;border-radius:5px;gap:4px}.btn-sm{padding:6px 12px;font-size:.8125rem;border-radius:6px}.btn-md{padding:10px 16px;font-size:.875rem}.btn-lg{padding:14px 20px;font-size:1rem}@media(pointer:coarse),(max-width:480px){.btn-xs,.btn-sm,.btn-md,.btn-lg,.btn-tab{min-height:44px}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{min-height:0}.btn-icon,.btn-icon-danger{position:relative}.btn-icon:after,.btn-icon-danger:after{content:\"\";position:absolute;inset:-8px}}.spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:currentColor;border-radius:50%;animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"],
2902
+ styles: [":host{display:inline-flex}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:8px;font-weight:600;cursor:pointer;font-family:inherit;transition:all .15s ease;white-space:nowrap}.btn:disabled{opacity:.5;cursor:not-allowed}.btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.btn-full{width:100%}.btn-primary{background:#3b82f6;color:#fff;border:1px solid #3B82F6}.btn-primary:hover:not(:disabled){background:#2563eb;border-color:#2563eb}.btn-secondary{background:#fff;color:#334155;border:1px solid #e2e8f0}.btn-secondary:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.btn-ghost{background:transparent;color:#64748b;border:1px solid transparent}.btn-ghost:hover:not(:disabled){background:#f8fafc;color:#334155}.btn-danger{background:#dc2626;color:#fff;border:1px solid #dc2626}.btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.btn-link{background:none;color:#3b82f6;border:none;padding:0;font-weight:500}.btn-link:hover:not(:disabled){color:#60a5fa}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{padding:0}.btn-anchor{text-decoration:none}.btn-anchor.btn-link{text-decoration:underline;text-underline-offset:2px}.btn-warning{background:#f97316;color:#fff;border:1px solid #f97316}.btn-warning:hover:not(:disabled){background:#ea6c0a;border-color:#ea6c0a}.btn-tab{background:none;color:#64748b;border:none;border-bottom:2px solid transparent;border-radius:0;font-weight:600;font-size:.875rem;transition:all .15s}.btn-tab:hover:not(:disabled){background:none;color:#1e293b}.btn-tab.active{color:#3b82f6;border-bottom-color:#3b82f6}.btn-tab.btn-xs,.btn-tab.btn-sm,.btn-tab.btn-md,.btn-tab.btn-lg{padding:10px 20px;border-radius:0}.btn-icon{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon:hover:not(:disabled){background:#f1f5f9;color:#334155}.btn-icon-danger{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon-danger:hover:not(:disabled){background:#fee2e2;color:#dc2626}.btn-xs{padding:3px 8px;font-size:.75rem;border-radius:5px;gap:4px}.btn-sm{padding:6px 12px;font-size:.8125rem;border-radius:6px}.btn-md{padding:10px 16px;font-size:.875rem}.btn-lg{padding:14px 20px;font-size:1rem}@media(pointer:coarse),(max-width:480px){.btn-xs,.btn-sm,.btn-md,.btn-lg,.btn-tab{min-height:44px}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{min-height:0}.btn-icon,.btn-icon-danger{position:relative}.btn-icon:after,.btn-icon-danger:after{content:\"\";position:absolute;inset:-8px}}.spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:currentColor;border-radius:50%;animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"],
2903
+ dependencies: [{
2904
+ kind: "directive",
2905
+ type: NgTemplateOutlet,
2906
+ selector: "[ngTemplateOutlet]",
2907
+ inputs: [
2908
+ "ngTemplateOutletContext",
2909
+ "ngTemplateOutlet",
2910
+ "ngTemplateOutletInjector"
2911
+ ]
2912
+ }, {
2913
+ kind: "directive",
2914
+ type: RouterLink,
2915
+ selector: "[routerLink]",
2916
+ inputs: [
2917
+ "target",
2918
+ "queryParams",
2919
+ "fragment",
2920
+ "queryParamsHandling",
2921
+ "state",
2922
+ "info",
2923
+ "relativeTo",
2924
+ "preserveFragment",
2925
+ "skipLocationChange",
2926
+ "replaceUrl",
2927
+ "browserUrl",
2928
+ "routerLink"
2929
+ ]
2930
+ }],
2874
2931
  changeDetection: i0.ChangeDetectionStrategy.OnPush
2875
2932
  });
2876
2933
  }
@@ -2885,8 +2942,26 @@ i0.ɵɵngDeclareClassMetadata({
2885
2942
  args: [{
2886
2943
  selector: "ui-button",
2887
2944
  standalone: true,
2945
+ imports: [NgTemplateOutlet, RouterLink],
2888
2946
  changeDetection: ChangeDetectionStrategy.OnPush,
2889
2947
  template: `
2948
+ <ng-template #content>
2949
+ @if (loading()) {
2950
+ <span class="spinner"></span>
2951
+ }
2952
+ <ng-content />
2953
+ </ng-template>
2954
+ @if (routerLink() !== null) {
2955
+ <!-- A real link (middle-click, open in new tab, screen readers say "link"): same look as the button of this variant, underlined. -->
2956
+ <a
2957
+ [routerLink]="routerLink()"
2958
+ [queryParams]="queryParams()"
2959
+ [class]="'btn btn-anchor btn-' + variant() + ' btn-' + size()"
2960
+ [class.btn-full]="fullWidth()"
2961
+ [attr.aria-label]="ariaLabel()"
2962
+ [attr.aria-describedby]="ariaDescribedBy() || null"
2963
+ ><ng-container [ngTemplateOutlet]="content" /></a>
2964
+ } @else {
2890
2965
  <button
2891
2966
  [type]="type()"
2892
2967
  [class]="'btn btn-' + variant() + ' btn-' + size()"
@@ -2899,14 +2974,10 @@ i0.ɵɵngDeclareClassMetadata({
2899
2974
  [attr.aria-describedby]="ariaDescribedBy() || null"
2900
2975
  [style.background]="color() || null"
2901
2976
  [style.border-color]="color() || null"
2902
- >
2903
- @if (loading()) {
2904
- <span class="spinner"></span>
2905
- }
2906
- <ng-content />
2907
- </button>
2977
+ ><ng-container [ngTemplateOutlet]="content" /></button>
2978
+ }
2908
2979
  `,
2909
- styles: [":host{display:inline-flex}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:8px;font-weight:600;cursor:pointer;font-family:inherit;transition:all .15s ease;white-space:nowrap}.btn:disabled{opacity:.5;cursor:not-allowed}.btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.btn-full{width:100%}.btn-primary{background:#3b82f6;color:#fff;border:1px solid #3B82F6}.btn-primary:hover:not(:disabled){background:#2563eb;border-color:#2563eb}.btn-secondary{background:#fff;color:#334155;border:1px solid #e2e8f0}.btn-secondary:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.btn-ghost{background:transparent;color:#64748b;border:1px solid transparent}.btn-ghost:hover:not(:disabled){background:#f8fafc;color:#334155}.btn-danger{background:#dc2626;color:#fff;border:1px solid #dc2626}.btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.btn-link{background:none;color:#3b82f6;border:none;padding:0;font-weight:500}.btn-link:hover:not(:disabled){color:#60a5fa}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{padding:0}.btn-warning{background:#f97316;color:#fff;border:1px solid #f97316}.btn-warning:hover:not(:disabled){background:#ea6c0a;border-color:#ea6c0a}.btn-tab{background:none;color:#64748b;border:none;border-bottom:2px solid transparent;border-radius:0;font-weight:600;font-size:.875rem;transition:all .15s}.btn-tab:hover:not(:disabled){background:none;color:#1e293b}.btn-tab.active{color:#3b82f6;border-bottom-color:#3b82f6}.btn-tab.btn-xs,.btn-tab.btn-sm,.btn-tab.btn-md,.btn-tab.btn-lg{padding:10px 20px;border-radius:0}.btn-icon{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon:hover:not(:disabled){background:#f1f5f9;color:#334155}.btn-icon-danger{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon-danger:hover:not(:disabled){background:#fee2e2;color:#dc2626}.btn-xs{padding:3px 8px;font-size:.75rem;border-radius:5px;gap:4px}.btn-sm{padding:6px 12px;font-size:.8125rem;border-radius:6px}.btn-md{padding:10px 16px;font-size:.875rem}.btn-lg{padding:14px 20px;font-size:1rem}@media(pointer:coarse),(max-width:480px){.btn-xs,.btn-sm,.btn-md,.btn-lg,.btn-tab{min-height:44px}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{min-height:0}.btn-icon,.btn-icon-danger{position:relative}.btn-icon:after,.btn-icon-danger:after{content:\"\";position:absolute;inset:-8px}}.spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:currentColor;border-radius:50%;animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"]
2980
+ styles: [":host{display:inline-flex}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:8px;font-weight:600;cursor:pointer;font-family:inherit;transition:all .15s ease;white-space:nowrap}.btn:disabled{opacity:.5;cursor:not-allowed}.btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.btn-full{width:100%}.btn-primary{background:#3b82f6;color:#fff;border:1px solid #3B82F6}.btn-primary:hover:not(:disabled){background:#2563eb;border-color:#2563eb}.btn-secondary{background:#fff;color:#334155;border:1px solid #e2e8f0}.btn-secondary:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.btn-ghost{background:transparent;color:#64748b;border:1px solid transparent}.btn-ghost:hover:not(:disabled){background:#f8fafc;color:#334155}.btn-danger{background:#dc2626;color:#fff;border:1px solid #dc2626}.btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.btn-link{background:none;color:#3b82f6;border:none;padding:0;font-weight:500}.btn-link:hover:not(:disabled){color:#60a5fa}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{padding:0}.btn-anchor{text-decoration:none}.btn-anchor.btn-link{text-decoration:underline;text-underline-offset:2px}.btn-warning{background:#f97316;color:#fff;border:1px solid #f97316}.btn-warning:hover:not(:disabled){background:#ea6c0a;border-color:#ea6c0a}.btn-tab{background:none;color:#64748b;border:none;border-bottom:2px solid transparent;border-radius:0;font-weight:600;font-size:.875rem;transition:all .15s}.btn-tab:hover:not(:disabled){background:none;color:#1e293b}.btn-tab.active{color:#3b82f6;border-bottom-color:#3b82f6}.btn-tab.btn-xs,.btn-tab.btn-sm,.btn-tab.btn-md,.btn-tab.btn-lg{padding:10px 20px;border-radius:0}.btn-icon{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon:hover:not(:disabled){background:#f1f5f9;color:#334155}.btn-icon-danger{width:28px;height:28px;padding:0;border-radius:6px;background:transparent;border:none;color:#94a3b8}.btn-icon-danger:hover:not(:disabled){background:#fee2e2;color:#dc2626}.btn-xs{padding:3px 8px;font-size:.75rem;border-radius:5px;gap:4px}.btn-sm{padding:6px 12px;font-size:.8125rem;border-radius:6px}.btn-md{padding:10px 16px;font-size:.875rem}.btn-lg{padding:14px 20px;font-size:1rem}@media(pointer:coarse),(max-width:480px){.btn-xs,.btn-sm,.btn-md,.btn-lg,.btn-tab{min-height:44px}.btn-link.btn-xs,.btn-link.btn-sm,.btn-link.btn-md,.btn-link.btn-lg{min-height:0}.btn-icon,.btn-icon-danger{position:relative}.btn-icon:after,.btn-icon-danger:after{content:\"\";position:absolute;inset:-8px}}.spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:currentColor;border-radius:50%;animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"]
2910
2981
  }]
2911
2982
  }],
2912
2983
  propDecorators: {
@@ -2918,6 +2989,22 @@ i0.ɵɵngDeclareClassMetadata({
2918
2989
  required: false
2919
2990
  }]
2920
2991
  }],
2992
+ routerLink: [{
2993
+ type: i0.Input,
2994
+ args: [{
2995
+ isSignal: true,
2996
+ alias: "routerLink",
2997
+ required: false
2998
+ }]
2999
+ }],
3000
+ queryParams: [{
3001
+ type: i0.Input,
3002
+ args: [{
3003
+ isSignal: true,
3004
+ alias: "queryParams",
3005
+ required: false
3006
+ }]
3007
+ }],
2921
3008
  color: [{
2922
3009
  type: i0.Input,
2923
3010
  args: [{
@@ -3967,6 +4054,8 @@ var TableToolbarComponent = class TableToolbarComponent {
3967
4054
  selector: "ui-button",
3968
4055
  inputs: [
3969
4056
  "variant",
4057
+ "routerLink",
4058
+ "queryParams",
3970
4059
  "color",
3971
4060
  "active",
3972
4061
  "size",
@@ -4303,6 +4392,30 @@ function decodeFilterValues(raw) {
4303
4392
  out.push(current);
4304
4393
  return out.map((v) => v.trim()).filter(Boolean);
4305
4394
  }
4395
+ var PlusSafeParamCodec = class {
4396
+ encode(v) {
4397
+ return encodeURIComponent(v).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/gi, "$").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%3D/gi, "=").replace(/%3F/gi, "?").replace(/%2F/gi, "/");
4398
+ }
4399
+ encodeKey(key) {
4400
+ return this.encode(key);
4401
+ }
4402
+ encodeValue(value) {
4403
+ return this.encode(value);
4404
+ }
4405
+ decodeKey(key) {
4406
+ return decodeURIComponent(key);
4407
+ }
4408
+ decodeValue(value) {
4409
+ return decodeURIComponent(value);
4410
+ }
4411
+ };
4412
+ const CODEC = new PlusSafeParamCodec();
4413
+ function tableQueryParams(values = {}) {
4414
+ return new HttpParams({
4415
+ encoder: CODEC,
4416
+ fromObject: values
4417
+ });
4418
+ }
4306
4419
  function getEligibleOptions(options, selectedItems, field) {
4307
4420
  if (selectedItems.length === 0) return options;
4308
4421
  return options.filter((opt) => !selectedItems.every((item) => String(item[field] ?? "") === opt.value));
@@ -4716,6 +4829,7 @@ i0.ɵɵngDeclareClassMetadata({
4716
4829
  }]
4717
4830
  }
4718
4831
  });
4832
+ const MIN_VISIBLE_PERCENT = 2;
4719
4833
  var ProgressBarComponent = class ProgressBarComponent {
4720
4834
  constructor() {
4721
4835
  this.value = input(0, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
@@ -4725,7 +4839,10 @@ var ProgressBarComponent = class ProgressBarComponent {
4725
4839
  this.tooltip = input("", ...ngDevMode ? [{ debugName: "tooltip" }] : /* istanbul ignore next */ []);
4726
4840
  this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
4727
4841
  this.clampedValue = computed(() => Math.min(Math.max(this.value(), 0), this.max()), ...ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []);
4728
- this.percent = computed(() => this.max() > 0 ? Math.round(this.clampedValue() / this.max() * 100) : 0, ...ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []);
4842
+ this.percent = computed(() => {
4843
+ if (this.max() <= 0 || this.clampedValue() <= 0) return 0;
4844
+ return Math.max(Math.round(this.clampedValue() / this.max() * 100), MIN_VISIBLE_PERCENT);
4845
+ }, ...ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []);
4729
4846
  this.effectiveVariant = computed(() => {
4730
4847
  const fixed = this.variant();
4731
4848
  if (fixed) return fixed;
@@ -5607,7 +5724,7 @@ var ImportExportComponent = class ImportExportComponent {
5607
5724
  if (this.exporting) return;
5608
5725
  this.exporting = true;
5609
5726
  this.cdr.detectChanges();
5610
- let params = new HttpParams().set("size", "10000");
5727
+ let params = tableQueryParams().set("size", "10000");
5611
5728
  Object.entries(this.exportParams()).forEach(([k, v]) => {
5612
5729
  if (v) params = params.set(k, v);
5613
5730
  });
@@ -6161,6 +6278,8 @@ var ImportExportComponent = class ImportExportComponent {
6161
6278
  selector: "ui-button",
6162
6279
  inputs: [
6163
6280
  "variant",
6281
+ "routerLink",
6282
+ "queryParams",
6164
6283
  "color",
6165
6284
  "active",
6166
6285
  "size",
@@ -6648,6 +6767,8 @@ var ConfirmOutletComponent = class ConfirmOutletComponent {
6648
6767
  selector: "ui-button",
6649
6768
  inputs: [
6650
6769
  "variant",
6770
+ "routerLink",
6771
+ "queryParams",
6651
6772
  "color",
6652
6773
  "active",
6653
6774
  "size",
@@ -6993,6 +7114,8 @@ var ErrorStateComponent = class ErrorStateComponent {
6993
7114
  selector: "ui-button",
6994
7115
  inputs: [
6995
7116
  "variant",
7117
+ "routerLink",
7118
+ "queryParams",
6996
7119
  "color",
6997
7120
  "active",
6998
7121
  "size",
@@ -7747,7 +7870,7 @@ var DataTableComponent = class DataTableComponent {
7747
7870
  this._searchLoading.set(this._searchPending);
7748
7871
  this._searchPending = false;
7749
7872
  this._error.set(null);
7750
- let params = new HttpParams({ fromObject: this._extraParams() }).set("page", this._page() - 1).set("size", this.pageSize());
7873
+ let params = tableQueryParams(this._extraParams()).set("page", this._page() - 1).set("size", this.pageSize());
7751
7874
  if (this._search()) {
7752
7875
  params = params.set("search", this._searchParam());
7753
7876
  const searchFields = this._searchFields();
@@ -7792,7 +7915,7 @@ var DataTableComponent = class DataTableComponent {
7792
7915
  if (ep) {
7793
7916
  const params = this._countParams();
7794
7917
  this._tabCountsSub?.unsubscribe();
7795
- this._tabCountsSub = this.http.get(`${this.config.baseUrl}${ep}`, { params }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
7918
+ this._tabCountsSub = this.http.get(`${this.config.baseUrl}${ep}`, { params: tableQueryParams(params) }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
7796
7919
  next: (counts) => {
7797
7920
  const { all: allCount, ...tabCounts } = counts;
7798
7921
  const total = allCount ?? Object.values(tabCounts).reduce((a, b) => a + b, 0);
@@ -7808,7 +7931,7 @@ var DataTableComponent = class DataTableComponent {
7808
7931
  if (fep) {
7809
7932
  const params = this._countParams();
7810
7933
  this._filterCountsSub?.unsubscribe();
7811
- this._filterCountsSub = this.http.get(`${this.config.baseUrl}${fep}`, { params }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
7934
+ this._filterCountsSub = this.http.get(`${this.config.baseUrl}${fep}`, { params: tableQueryParams(params) }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
7812
7935
  next: (counts) => this._filterCounts.set(counts),
7813
7936
  error: () => {}
7814
7937
  });
@@ -9171,6 +9294,8 @@ var DataTableComponent = class DataTableComponent {
9171
9294
  selector: "ui-button",
9172
9295
  inputs: [
9173
9296
  "variant",
9297
+ "routerLink",
9298
+ "queryParams",
9174
9299
  "color",
9175
9300
  "active",
9176
9301
  "size",
@@ -10767,7 +10892,7 @@ var BarChartComponent = class BarChartComponent {
10767
10892
  ngImport: i0,
10768
10893
  template: `
10769
10894
  <div class="bc-wrap" [class.bc-default-height]="height() === 240" [style.height.px]="height()"
10770
- role="img" [attr.aria-label]="ariaLabel() || null">
10895
+ [attr.role]="ariaLabel() ? 'img' : null" [attr.aria-label]="ariaLabel() || null">
10771
10896
  <canvas #canvas></canvas>
10772
10897
  </div>
10773
10898
  `,
@@ -10790,7 +10915,7 @@ i0.ɵɵngDeclareClassMetadata({
10790
10915
  changeDetection: ChangeDetectionStrategy.OnPush,
10791
10916
  template: `
10792
10917
  <div class="bc-wrap" [class.bc-default-height]="height() === 240" [style.height.px]="height()"
10793
- role="img" [attr.aria-label]="ariaLabel() || null">
10918
+ [attr.role]="ariaLabel() ? 'img' : null" [attr.aria-label]="ariaLabel() || null">
10794
10919
  <canvas #canvas></canvas>
10795
10920
  </div>
10796
10921
  `,
@@ -16717,6 +16842,8 @@ var SendEmailComponent = class SendEmailComponent {
16717
16842
  selector: "ui-button",
16718
16843
  inputs: [
16719
16844
  "variant",
16845
+ "routerLink",
16846
+ "queryParams",
16720
16847
  "color",
16721
16848
  "active",
16722
16849
  "size",
@@ -17937,6 +18064,8 @@ var SendTextComponent = class SendTextComponent {
17937
18064
  selector: "ui-button",
17938
18065
  inputs: [
17939
18066
  "variant",
18067
+ "routerLink",
18068
+ "queryParams",
17940
18069
  "color",
17941
18070
  "active",
17942
18071
  "size",
@@ -22970,6 +23099,8 @@ var QrCodeComponent = class QrCodeComponent {
22970
23099
  selector: "ui-button",
22971
23100
  inputs: [
22972
23101
  "variant",
23102
+ "routerLink",
23103
+ "queryParams",
22973
23104
  "color",
22974
23105
  "active",
22975
23106
  "size",
@@ -23238,6 +23369,8 @@ var PanelInfoListComponent = class PanelInfoListComponent {
23238
23369
  selector: "ui-button",
23239
23370
  inputs: [
23240
23371
  "variant",
23372
+ "routerLink",
23373
+ "queryParams",
23241
23374
  "color",
23242
23375
  "active",
23243
23376
  "size",
@@ -24989,6 +25122,7 @@ var DateRangePickerComponent = class DateRangePickerComponent {
24989
25122
  this.activePreset = input("ytd", ...ngDevMode ? [{ debugName: "activePreset" }] : /* istanbul ignore next */ []);
24990
25123
  this.showPresets = input(true, ...ngDevMode ? [{ debugName: "showPresets" }] : /* istanbul ignore next */ []);
24991
25124
  this.includeAllTime = input(false, ...ngDevMode ? [{ debugName: "includeAllTime" }] : /* istanbul ignore next */ []);
25125
+ this.ariaLabel = input("Date range", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
24992
25126
  this.rangeChange = output();
24993
25127
  this.selectedPreset = linkedSignal(() => this.activePreset(), ...ngDevMode ? [{ debugName: "selectedPreset" }] : /* istanbul ignore next */ []);
24994
25128
  this.customStart = signal("", ...ngDevMode ? [{ debugName: "customStart" }] : /* istanbul ignore next */ []);
@@ -25061,6 +25195,13 @@ var DateRangePickerComponent = class DateRangePickerComponent {
25061
25195
  isSignal: true,
25062
25196
  isRequired: false,
25063
25197
  transformFunction: null
25198
+ },
25199
+ ariaLabel: {
25200
+ classPropertyName: "ariaLabel",
25201
+ publicName: "ariaLabel",
25202
+ isSignal: true,
25203
+ isRequired: false,
25204
+ transformFunction: null
25064
25205
  }
25065
25206
  },
25066
25207
  outputs: { rangeChange: "rangeChange" },
@@ -25068,7 +25209,7 @@ var DateRangePickerComponent = class DateRangePickerComponent {
25068
25209
  template: `
25069
25210
  <div class="date-range-picker">
25070
25211
  @if (showPresets()) {
25071
- <ui-pill-tabs [tabs]="presetTabs()" [activeKey]="selectedPreset()" (tabChange)="selectPreset($any($event))" />
25212
+ <ui-pill-tabs [tabs]="presetTabs()" [activeKey]="selectedPreset()" [ariaLabel]="ariaLabel()" (tabChange)="selectPreset($any($event))" />
25072
25213
  }
25073
25214
  @if (selectedPreset() === 'custom' || !showPresets()) {
25074
25215
  <div class="custom-range">
@@ -25139,6 +25280,8 @@ var DateRangePickerComponent = class DateRangePickerComponent {
25139
25280
  selector: "ui-button",
25140
25281
  inputs: [
25141
25282
  "variant",
25283
+ "routerLink",
25284
+ "queryParams",
25142
25285
  "color",
25143
25286
  "active",
25144
25287
  "size",
@@ -25179,7 +25322,7 @@ i0.ɵɵngDeclareClassMetadata({
25179
25322
  template: `
25180
25323
  <div class="date-range-picker">
25181
25324
  @if (showPresets()) {
25182
- <ui-pill-tabs [tabs]="presetTabs()" [activeKey]="selectedPreset()" (tabChange)="selectPreset($any($event))" />
25325
+ <ui-pill-tabs [tabs]="presetTabs()" [activeKey]="selectedPreset()" [ariaLabel]="ariaLabel()" (tabChange)="selectPreset($any($event))" />
25183
25326
  }
25184
25327
  @if (selectedPreset() === 'custom' || !showPresets()) {
25185
25328
  <div class="custom-range">
@@ -25219,6 +25362,14 @@ i0.ɵɵngDeclareClassMetadata({
25219
25362
  required: false
25220
25363
  }]
25221
25364
  }],
25365
+ ariaLabel: [{
25366
+ type: i0.Input,
25367
+ args: [{
25368
+ isSignal: true,
25369
+ alias: "ariaLabel",
25370
+ required: false
25371
+ }]
25372
+ }],
25222
25373
  rangeChange: [{
25223
25374
  type: i0.Output,
25224
25375
  args: ["rangeChange"]
@@ -27936,6 +28087,8 @@ var DetailCardComponent = class DetailCardComponent {
27936
28087
  selector: "ui-button",
27937
28088
  inputs: [
27938
28089
  "variant",
28090
+ "routerLink",
28091
+ "queryParams",
27939
28092
  "color",
27940
28093
  "active",
27941
28094
  "size",