@forgeroute/ui 0.4.72 → 0.4.74

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.
@@ -1385,15 +1385,49 @@ i0.ɵɵngDeclareClassMetadata({
1385
1385
  }]
1386
1386
  }
1387
1387
  });
1388
+ const HEX = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
1389
+ const BADGE_INK_DARK = "#0f172a";
1390
+ const BADGE_INK_LIGHT = "#ffffff";
1391
+ function normalizeBadgeColor(value) {
1392
+ const raw = (value ?? "").trim();
1393
+ if (!HEX.test(raw)) return null;
1394
+ const hex = raw.slice(1).toLowerCase();
1395
+ return "#" + (hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex);
1396
+ }
1397
+ function channel(v) {
1398
+ const s = v / 255;
1399
+ return s <= .03928 ? s / 12.92 : Math.pow((s + .055) / 1.055, 2.4);
1400
+ }
1401
+ function relativeLuminance(hex) {
1402
+ const n = parseInt(hex.slice(1), 16);
1403
+ return .2126 * channel(n >> 16 & 255) + .7152 * channel(n >> 8 & 255) + .0722 * channel(n & 255);
1404
+ }
1405
+ function contrastRatio(a, b) {
1406
+ const la = relativeLuminance(a), lb = relativeLuminance(b);
1407
+ const [hi, lo] = la >= lb ? [la, lb] : [lb, la];
1408
+ return (hi + .05) / (lo + .05);
1409
+ }
1410
+ function readableInk(background) {
1411
+ return contrastRatio(background, "#0f172a") >= contrastRatio(background, "#ffffff") ? BADGE_INK_DARK : BADGE_INK_LIGHT;
1412
+ }
1413
+ function customBadgeStyles(value) {
1414
+ const bg = normalizeBadgeColor(value);
1415
+ return bg ? {
1416
+ bg,
1417
+ color: readableInk(bg)
1418
+ } : null;
1419
+ }
1388
1420
  var BadgeComponent = class BadgeComponent {
1389
1421
  constructor() {
1390
1422
  this.label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
1391
1423
  this.variant = input(null, ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
1424
+ this.color = input(null, ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
1392
1425
  this.resolvedVariant = computed(() => {
1393
1426
  if (this.variant()) return this.variant();
1394
1427
  return SEMANTIC_BADGE_MAP[this.label()] ?? autoVariant(this.label());
1395
1428
  }, ...ngDevMode ? [{ debugName: "resolvedVariant" }] : /* istanbul ignore next */ []);
1396
- this.styles = computed(() => BADGE_VARIANT_STYLES[this.resolvedVariant()] ?? BADGE_VARIANT_STYLES["gray"], ...ngDevMode ? [{ debugName: "styles" }] : /* istanbul ignore next */ []);
1429
+ this.customStyles = computed(() => customBadgeStyles(this.color()), ...ngDevMode ? [{ debugName: "customStyles" }] : /* istanbul ignore next */ []);
1430
+ this.styles = computed(() => this.customStyles() ?? BADGE_VARIANT_STYLES[this.resolvedVariant()] ?? BADGE_VARIANT_STYLES["gray"], ...ngDevMode ? [{ debugName: "styles" }] : /* istanbul ignore next */ []);
1397
1431
  }
1398
1432
  static {
1399
1433
  this.ɵfac = i0.ɵɵngDeclareFactory({
@@ -1426,13 +1460,20 @@ var BadgeComponent = class BadgeComponent {
1426
1460
  isSignal: true,
1427
1461
  isRequired: false,
1428
1462
  transformFunction: null
1463
+ },
1464
+ color: {
1465
+ classPropertyName: "color",
1466
+ publicName: "color",
1467
+ isSignal: true,
1468
+ isRequired: false,
1469
+ transformFunction: null
1429
1470
  }
1430
1471
  },
1431
1472
  ngImport: i0,
1432
1473
  template: `
1433
1474
  <span
1434
1475
  class="badge"
1435
- [class.badge-gray]="resolvedVariant() === 'gray'"
1476
+ [class.badge-gray]="!customStyles() && resolvedVariant() === 'gray'"
1436
1477
  [style.background]="styles().bg"
1437
1478
  [style.color]="styles().color">
1438
1479
  {{ label() }}
@@ -1458,7 +1499,7 @@ i0.ɵɵngDeclareClassMetadata({
1458
1499
  template: `
1459
1500
  <span
1460
1501
  class="badge"
1461
- [class.badge-gray]="resolvedVariant() === 'gray'"
1502
+ [class.badge-gray]="!customStyles() && resolvedVariant() === 'gray'"
1462
1503
  [style.background]="styles().bg"
1463
1504
  [style.color]="styles().color">
1464
1505
  {{ label() }}
@@ -1483,6 +1524,14 @@ i0.ɵɵngDeclareClassMetadata({
1483
1524
  alias: "variant",
1484
1525
  required: false
1485
1526
  }]
1527
+ }],
1528
+ color: [{
1529
+ type: i0.Input,
1530
+ args: [{
1531
+ isSignal: true,
1532
+ alias: "color",
1533
+ required: false
1534
+ }]
1486
1535
  }]
1487
1536
  }
1488
1537
  });
@@ -1829,6 +1878,9 @@ const BUILT_IN_ICONS = {
1829
1878
  "create-invoice": "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8",
1830
1879
  "create-estimate": "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M12 18v-6 M9 15h6",
1831
1880
  "add-note": "M12 20h9 M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z",
1881
+ "history": "M3 3v5h5 M3.05 13A9 9 0 1 0 6 5.3L3 8 M12 7v5l4 2",
1882
+ "move-up": "M12 19V5 M5 12l7-7 7 7",
1883
+ "move-down": "M12 5v14 M19 12l-7 7-7-7",
1832
1884
  "invite-portal": "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z M15 9l3 3-3 3 M18 12H8"
1833
1885
  };
1834
1886
  function builtInActionIcon(type) {
@@ -2085,6 +2137,7 @@ var MoreMenuComponent = class MoreMenuComponent {
2085
2137
  <div class="mm-wrapper">
2086
2138
  <button
2087
2139
  class="mm-trigger"
2140
+ data-testid="more-menu-trigger"
2088
2141
  [attr.aria-expanded]="open()"
2089
2142
  aria-haspopup="menu"
2090
2143
  [attr.aria-label]="ariaLabel()"
@@ -2101,6 +2154,7 @@ var MoreMenuComponent = class MoreMenuComponent {
2101
2154
  @for (action of visibleActions(); track action.type) {
2102
2155
  <button
2103
2156
  class="mm-item"
2157
+ data-testid="more-menu-item"
2104
2158
  [class.mm-danger]="action.variant === 'danger'"
2105
2159
  [disabled]="isDisabled(action)"
2106
2160
  role="menuitem"
@@ -2141,6 +2195,7 @@ i0.ɵɵngDeclareClassMetadata({
2141
2195
  <div class="mm-wrapper">
2142
2196
  <button
2143
2197
  class="mm-trigger"
2198
+ data-testid="more-menu-trigger"
2144
2199
  [attr.aria-expanded]="open()"
2145
2200
  aria-haspopup="menu"
2146
2201
  [attr.aria-label]="ariaLabel()"
@@ -2157,6 +2212,7 @@ i0.ɵɵngDeclareClassMetadata({
2157
2212
  @for (action of visibleActions(); track action.type) {
2158
2213
  <button
2159
2214
  class="mm-item"
2215
+ data-testid="more-menu-item"
2160
2216
  [class.mm-danger]="action.variant === 'danger'"
2161
2217
  [disabled]="isDisabled(action)"
2162
2218
  role="menuitem"
@@ -3827,6 +3883,9 @@ i0.ɵɵngDeclareClassMetadata({
3827
3883
  }
3828
3884
  });
3829
3885
  var ButtonComponent = class ButtonComponent {
3886
+ focus(options) {
3887
+ this._hostEl.nativeElement.querySelector("button.btn, a.btn")?.focus(options);
3888
+ }
3830
3889
  constructor() {
3831
3890
  this.variant = input("primary", ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
3832
3891
  this.routerLink = input(null, ...ngDevMode ? [{ debugName: "routerLink" }] : /* istanbul ignore next */ []);
@@ -3878,6 +3937,7 @@ var ButtonComponent = class ButtonComponent {
3878
3937
  this.ariaExpanded = input(void 0, ...ngDevMode ? [{ debugName: "ariaExpanded" }] : /* istanbul ignore next */ []);
3879
3938
  this.ariaPressed = input(void 0, ...ngDevMode ? [{ debugName: "ariaPressed" }] : /* istanbul ignore next */ []);
3880
3939
  this.ariaDescribedBy = input(void 0, ...ngDevMode ? [{ debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []);
3940
+ this._hostEl = inject(ElementRef);
3881
3941
  effect((onCleanup) => {
3882
3942
  const below = this.shortBelow();
3883
3943
  if (!this.shortLabel() || typeof below !== "number" || !Number.isFinite(below) || typeof window === "undefined" || typeof window.matchMedia !== "function") {
@@ -4640,8 +4700,12 @@ const EXTRA_ICONS = {
4640
4700
  "bank": "M3 21h18 M3 10h18 M5 6l7-3 7 3 M4 10v11 M20 10v11 M8 14v3 M12 14v3 M16 14v3",
4641
4701
  "unlink": "M18.84 12.25l1.72-1.71a5 5 0 0 0-7.07-7.07l-1.72 1.71 M5.17 11.75l-1.72 1.71a5 5 0 0 0 7.07 7.07l1.71-1.71 M3 3l18 18",
4642
4702
  "send": "M22 2L11 13 M22 2l-7 20-4-9-9-4 20-7z",
4643
- "refresh": "M23 4v6h-6 M1 20v-6h6 M3.51 9a9 9 0 0 1 14.85-3.36L23 10 M1 14l4.64 4.36A9 9 0 0 0 20.49 15"
4703
+ "refresh": "M23 4v6h-6 M1 20v-6h6 M3.51 9a9 9 0 0 1 14.85-3.36L23 10 M1 14l4.64 4.36A9 9 0 0 0 20.49 15",
4704
+ "search": "M11 3a8 8 0 1 0 0 16 8 8 0 0 0 0-16z M21 21l-4.35-4.35",
4705
+ "cup": "M18 8h1a4 4 0 0 1 0 8h-1 M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z M6 1v3 M10 1v3 M14 1v3",
4706
+ "wrench": "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
4644
4707
  };
4708
+ const ICON_NAMES = Object.freeze(Object.keys(EXTRA_ICONS));
4645
4709
  function iconPath(name) {
4646
4710
  return Object.prototype.hasOwnProperty.call(EXTRA_ICONS, name) ? EXTRA_ICONS[name] : builtInActionIcon(name);
4647
4711
  }
@@ -5063,6 +5127,9 @@ var TextInputComponent = class TextInputComponent {
5063
5127
  static {
5064
5128
  this._EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
5065
5129
  }
5130
+ focus(options) {
5131
+ this._fieldEl()?.nativeElement.focus(options);
5132
+ }
5066
5133
  constructor() {
5067
5134
  this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
5068
5135
  this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
@@ -5070,6 +5137,7 @@ var TextInputComponent = class TextInputComponent {
5070
5137
  this.inputName = input("", ...ngDevMode ? [{ debugName: "inputName" }] : /* istanbul ignore next */ []);
5071
5138
  this.placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
5072
5139
  this.prefix = input("", ...ngDevMode ? [{ debugName: "prefix" }] : /* istanbul ignore next */ []);
5140
+ this.leadingIcon = input("", ...ngDevMode ? [{ debugName: "leadingIcon" }] : /* istanbul ignore next */ []);
5073
5141
  this.revealable = input(false, ...ngDevMode ? [{ debugName: "revealable" }] : /* istanbul ignore next */ []);
5074
5142
  this.passwordRequirements = input(false, ...ngDevMode ? [{ debugName: "passwordRequirements" }] : /* istanbul ignore next */ []);
5075
5143
  this.passwordRules = input(void 0, ...ngDevMode ? [{ debugName: "passwordRules" }] : /* istanbul ignore next */ []);
@@ -5103,7 +5171,16 @@ var TextInputComponent = class TextInputComponent {
5103
5171
  this.disabled = computed(() => this._disabledInput() || this._cvaDisabled(), ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
5104
5172
  this._value = signal("", ...ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []);
5105
5173
  this._reveal = createFieldReveal(this.showErrors);
5106
- this._prefixPadding = computed(() => this.prefix() ? `calc(12px + ${this.prefix().length}ch + 6px)` : null, ...ngDevMode ? [{ debugName: "_prefixPadding" }] : /* istanbul ignore next */ []);
5174
+ this._leadingD = computed(() => {
5175
+ const key = this.leadingIcon().trim();
5176
+ return key ? iconPath(key) ?? null : null;
5177
+ }, ...ngDevMode ? [{ debugName: "_leadingD" }] : /* istanbul ignore next */ []);
5178
+ this._prefixPadding = computed(() => {
5179
+ const icon = !!this._leadingD();
5180
+ if (this.prefix()) return icon ? `calc(36px + ${this.prefix().length}ch + 6px)` : `calc(12px + ${this.prefix().length}ch + 6px)`;
5181
+ return icon ? "36px" : null;
5182
+ }, ...ngDevMode ? [{ debugName: "_prefixPadding" }] : /* istanbul ignore next */ []);
5183
+ this._fieldEl = viewChild("field", ...ngDevMode ? [{ debugName: "_fieldEl" }] : /* istanbul ignore next */ []);
5107
5184
  this._numeric = computed(() => this.valueType() === "number" && this.type() === "number", ...ngDevMode ? [{ debugName: "_numeric" }] : /* istanbul ignore next */ []);
5108
5185
  this._stepAttr = computed(() => {
5109
5186
  const step = this.step();
@@ -5348,6 +5425,13 @@ var TextInputComponent = class TextInputComponent {
5348
5425
  isRequired: false,
5349
5426
  transformFunction: null
5350
5427
  },
5428
+ leadingIcon: {
5429
+ classPropertyName: "leadingIcon",
5430
+ publicName: "leadingIcon",
5431
+ isSignal: true,
5432
+ isRequired: false,
5433
+ transformFunction: null
5434
+ },
5351
5435
  revealable: {
5352
5436
  classPropertyName: "revealable",
5353
5437
  publicName: "revealable",
@@ -5525,11 +5609,18 @@ var TextInputComponent = class TextInputComponent {
5525
5609
  useExisting: forwardRef(() => TextInputComponent)
5526
5610
  }
5527
5611
  ],
5612
+ viewQueries: [{
5613
+ propertyName: "_fieldEl",
5614
+ first: true,
5615
+ predicate: ["field"],
5616
+ descendants: true,
5617
+ isSignal: true
5618
+ }],
5528
5619
  usesOnChanges: true,
5529
5620
  ngImport: i0,
5530
5621
  template: `
5531
5622
  <div class="ti-field" [class.ti-error]="_activeError()" [class.ti-disabled]="disabled()"
5532
- [class.ti-prefixed]="!!prefix() || _revealable()" [style.--ti-input-row]="(prefix() || _revealable()) ? (label() ? 2 : 1) : null">
5623
+ [class.ti-prefixed]="!!prefix() || _revealable() || !!_leadingD()" [style.--ti-input-row]="(prefix() || _revealable() || _leadingD()) ? (label() ? 2 : 1) : null">
5533
5624
  @if (label()) {
5534
5625
  <div class="ti-label-row">
5535
5626
  <label class="ti-label" [for]="_inputId">
@@ -5540,6 +5631,7 @@ var TextInputComponent = class TextInputComponent {
5540
5631
  </div>
5541
5632
  }
5542
5633
  <input
5634
+ #field
5543
5635
  class="ti-input"
5544
5636
  [style.padding-left]="_prefixPadding()"
5545
5637
  [style.padding-right]="_revealable() ? '44px' : null"
@@ -5563,9 +5655,13 @@ var TextInputComponent = class TextInputComponent {
5563
5655
  (focus)="onFocus()"
5564
5656
  (blur)="onBlur()"
5565
5657
  />
5658
+ @if (_leadingD(); as d) {
5659
+ <!-- Optional leading icon (library source 2026-11-04): decorative, laid over the input's left padding by the same grid as the prefix. -->
5660
+ <svg class="ti-leading-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="d" /></svg>
5661
+ }
5566
5662
  @if (prefix()) {
5567
5663
  <!-- Optional leading mark ("$"): a sibling after the input, laid over it by the grid of .ti-prefixed, so toggling it never recreates the input (focus and caret stay). -->
5568
- <span class="ti-prefix" aria-hidden="true">{{ prefix() }}</span>
5664
+ <span class="ti-prefix" aria-hidden="true" [style.margin-left]="_leadingD() ? '36px' : null">{{ prefix() }}</span>
5569
5665
  }
5570
5666
  @if (_revealable()) {
5571
5667
  <!-- Show / hide toggle laid over the end of the input by the grid of .ti-prefixed. The name stays "Show password"; aria-pressed carries the state. -->
@@ -5587,7 +5683,7 @@ var TextInputComponent = class TextInputComponent {
5587
5683
  </div>
5588
5684
  `,
5589
5685
  isInline: true,
5590
- styles: [":host{display:block}.ti-field{display:flex;flex-direction:column;gap:6px}.ti-label-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.ti-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.ti-required{color:#dc2626;margin-left:2px}.ti-prefixed{display:grid;grid-template-columns:minmax(0,1fr)}.ti-prefixed .ti-input{grid-row:var(--ti-input-row);grid-column:1}.ti-prefix{grid-row:var(--ti-input-row);grid-column:1;justify-self:start;align-self:center;margin-left:12px;font-size:.875rem;line-height:1;color:#64748b;pointer-events:none}@media(pointer:coarse),(max-width:480px){.ti-prefix{font-size:1rem}}.ti-disabled .ti-prefix{opacity:.5}.ti-reveal{grid-row:var(--ti-input-row);grid-column:1;justify-self:end;align-self:center;margin-right:6px;position:relative;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:6px;background:transparent;color:#64748b;cursor:pointer}.ti-reveal:hover:not(:disabled){color:#1e293b;background:#f1f5f9}.ti-reveal:focus-visible{outline:2px solid #3b82f6;outline-offset:0}.ti-reveal:disabled{opacity:.5;cursor:not-allowed}@media(pointer:coarse),(max-width:480px){.ti-reveal{width:44px;height:44px;margin-right:0}}.ti-input{width:100%;box-sizing:border-box;padding:9px 12px;font-size:.875rem;font-family:inherit;color:#1e293b;background:#fff;border:1px solid #7c8ba1;border-radius:8px;outline:none;transition:border-color .15s,box-shadow .15s}.ti-input::placeholder{color:#64748b;opacity:1}.ti-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.ti-input:read-only{background:#f8fafc;cursor:default}.ti-error .ti-input{border-color:#ef4444}.ti-error .ti-input:focus{box-shadow:0 0 0 3px #ef44441f}.ti-disabled .ti-input{opacity:.5;cursor:not-allowed}.ti-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.ti-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.ti-input{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.ti-input{min-height:44px}}\n"],
5686
+ styles: [":host{display:block}.ti-field{display:flex;flex-direction:column;gap:6px}.ti-label-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.ti-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.ti-required{color:#dc2626;margin-left:2px}.ti-prefixed{display:grid;grid-template-columns:minmax(0,1fr)}.ti-prefixed .ti-input{grid-row:var(--ti-input-row);grid-column:1}.ti-prefix{grid-row:var(--ti-input-row);grid-column:1;justify-self:start;align-self:center;margin-left:12px;font-size:.875rem;line-height:1;color:#64748b;pointer-events:none}@media(pointer:coarse),(max-width:480px){.ti-prefix{font-size:1rem}}.ti-disabled .ti-prefix{opacity:.5}.ti-leading-icon{grid-row:var(--ti-input-row);grid-column:1;justify-self:start;align-self:center;margin-left:12px;color:#64748b;pointer-events:none}.ti-disabled .ti-leading-icon{opacity:.5}.ti-reveal{grid-row:var(--ti-input-row);grid-column:1;justify-self:end;align-self:center;margin-right:6px;position:relative;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:6px;background:transparent;color:#64748b;cursor:pointer}.ti-reveal:hover:not(:disabled){color:#1e293b;background:#f1f5f9}.ti-reveal:focus-visible{outline:2px solid #3b82f6;outline-offset:0}.ti-reveal:disabled{opacity:.5;cursor:not-allowed}@media(pointer:coarse),(max-width:480px){.ti-reveal{width:44px;height:44px;margin-right:0}}.ti-input{width:100%;box-sizing:border-box;padding:9px 12px;font-size:.875rem;font-family:inherit;color:#1e293b;background:#fff;border:1px solid #7c8ba1;border-radius:8px;outline:none;transition:border-color .15s,box-shadow .15s}.ti-input::placeholder{color:#64748b;opacity:1}.ti-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.ti-input:read-only{background:#f8fafc;cursor:default}.ti-error .ti-input{border-color:#ef4444}.ti-error .ti-input:focus{box-shadow:0 0 0 3px #ef44441f}.ti-disabled .ti-input{opacity:.5;cursor:not-allowed}.ti-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.ti-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.ti-input{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.ti-input{min-height:44px}}\n"],
5591
5687
  dependencies: [{
5592
5688
  kind: "component",
5593
5689
  type: PasswordRequirementsComponent,
@@ -5632,7 +5728,7 @@ i0.ɵɵngDeclareClassMetadata({
5632
5728
  ],
5633
5729
  template: `
5634
5730
  <div class="ti-field" [class.ti-error]="_activeError()" [class.ti-disabled]="disabled()"
5635
- [class.ti-prefixed]="!!prefix() || _revealable()" [style.--ti-input-row]="(prefix() || _revealable()) ? (label() ? 2 : 1) : null">
5731
+ [class.ti-prefixed]="!!prefix() || _revealable() || !!_leadingD()" [style.--ti-input-row]="(prefix() || _revealable() || _leadingD()) ? (label() ? 2 : 1) : null">
5636
5732
  @if (label()) {
5637
5733
  <div class="ti-label-row">
5638
5734
  <label class="ti-label" [for]="_inputId">
@@ -5643,6 +5739,7 @@ i0.ɵɵngDeclareClassMetadata({
5643
5739
  </div>
5644
5740
  }
5645
5741
  <input
5742
+ #field
5646
5743
  class="ti-input"
5647
5744
  [style.padding-left]="_prefixPadding()"
5648
5745
  [style.padding-right]="_revealable() ? '44px' : null"
@@ -5666,9 +5763,13 @@ i0.ɵɵngDeclareClassMetadata({
5666
5763
  (focus)="onFocus()"
5667
5764
  (blur)="onBlur()"
5668
5765
  />
5766
+ @if (_leadingD(); as d) {
5767
+ <!-- Optional leading icon (library source 2026-11-04): decorative, laid over the input's left padding by the same grid as the prefix. -->
5768
+ <svg class="ti-leading-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="d" /></svg>
5769
+ }
5669
5770
  @if (prefix()) {
5670
5771
  <!-- Optional leading mark ("$"): a sibling after the input, laid over it by the grid of .ti-prefixed, so toggling it never recreates the input (focus and caret stay). -->
5671
- <span class="ti-prefix" aria-hidden="true">{{ prefix() }}</span>
5772
+ <span class="ti-prefix" aria-hidden="true" [style.margin-left]="_leadingD() ? '36px' : null">{{ prefix() }}</span>
5672
5773
  }
5673
5774
  @if (_revealable()) {
5674
5775
  <!-- Show / hide toggle laid over the end of the input by the grid of .ti-prefixed. The name stays "Show password"; aria-pressed carries the state. -->
@@ -5689,7 +5790,7 @@ i0.ɵɵngDeclareClassMetadata({
5689
5790
  }
5690
5791
  </div>
5691
5792
  `,
5692
- styles: [":host{display:block}.ti-field{display:flex;flex-direction:column;gap:6px}.ti-label-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.ti-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.ti-required{color:#dc2626;margin-left:2px}.ti-prefixed{display:grid;grid-template-columns:minmax(0,1fr)}.ti-prefixed .ti-input{grid-row:var(--ti-input-row);grid-column:1}.ti-prefix{grid-row:var(--ti-input-row);grid-column:1;justify-self:start;align-self:center;margin-left:12px;font-size:.875rem;line-height:1;color:#64748b;pointer-events:none}@media(pointer:coarse),(max-width:480px){.ti-prefix{font-size:1rem}}.ti-disabled .ti-prefix{opacity:.5}.ti-reveal{grid-row:var(--ti-input-row);grid-column:1;justify-self:end;align-self:center;margin-right:6px;position:relative;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:6px;background:transparent;color:#64748b;cursor:pointer}.ti-reveal:hover:not(:disabled){color:#1e293b;background:#f1f5f9}.ti-reveal:focus-visible{outline:2px solid #3b82f6;outline-offset:0}.ti-reveal:disabled{opacity:.5;cursor:not-allowed}@media(pointer:coarse),(max-width:480px){.ti-reveal{width:44px;height:44px;margin-right:0}}.ti-input{width:100%;box-sizing:border-box;padding:9px 12px;font-size:.875rem;font-family:inherit;color:#1e293b;background:#fff;border:1px solid #7c8ba1;border-radius:8px;outline:none;transition:border-color .15s,box-shadow .15s}.ti-input::placeholder{color:#64748b;opacity:1}.ti-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.ti-input:read-only{background:#f8fafc;cursor:default}.ti-error .ti-input{border-color:#ef4444}.ti-error .ti-input:focus{box-shadow:0 0 0 3px #ef44441f}.ti-disabled .ti-input{opacity:.5;cursor:not-allowed}.ti-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.ti-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.ti-input{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.ti-input{min-height:44px}}\n"]
5793
+ styles: [":host{display:block}.ti-field{display:flex;flex-direction:column;gap:6px}.ti-label-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.ti-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.ti-required{color:#dc2626;margin-left:2px}.ti-prefixed{display:grid;grid-template-columns:minmax(0,1fr)}.ti-prefixed .ti-input{grid-row:var(--ti-input-row);grid-column:1}.ti-prefix{grid-row:var(--ti-input-row);grid-column:1;justify-self:start;align-self:center;margin-left:12px;font-size:.875rem;line-height:1;color:#64748b;pointer-events:none}@media(pointer:coarse),(max-width:480px){.ti-prefix{font-size:1rem}}.ti-disabled .ti-prefix{opacity:.5}.ti-leading-icon{grid-row:var(--ti-input-row);grid-column:1;justify-self:start;align-self:center;margin-left:12px;color:#64748b;pointer-events:none}.ti-disabled .ti-leading-icon{opacity:.5}.ti-reveal{grid-row:var(--ti-input-row);grid-column:1;justify-self:end;align-self:center;margin-right:6px;position:relative;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:6px;background:transparent;color:#64748b;cursor:pointer}.ti-reveal:hover:not(:disabled){color:#1e293b;background:#f1f5f9}.ti-reveal:focus-visible{outline:2px solid #3b82f6;outline-offset:0}.ti-reveal:disabled{opacity:.5;cursor:not-allowed}@media(pointer:coarse),(max-width:480px){.ti-reveal{width:44px;height:44px;margin-right:0}}.ti-input{width:100%;box-sizing:border-box;padding:9px 12px;font-size:.875rem;font-family:inherit;color:#1e293b;background:#fff;border:1px solid #7c8ba1;border-radius:8px;outline:none;transition:border-color .15s,box-shadow .15s}.ti-input::placeholder{color:#64748b;opacity:1}.ti-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.ti-input:read-only{background:#f8fafc;cursor:default}.ti-error .ti-input{border-color:#ef4444}.ti-error .ti-input:focus{box-shadow:0 0 0 3px #ef44441f}.ti-disabled .ti-input{opacity:.5;cursor:not-allowed}.ti-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.ti-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.ti-input{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.ti-input{min-height:44px}}\n"]
5693
5794
  }]
5694
5795
  }],
5695
5796
  ctorParameters: () => [],
@@ -5742,6 +5843,14 @@ i0.ɵɵngDeclareClassMetadata({
5742
5843
  required: false
5743
5844
  }]
5744
5845
  }],
5846
+ leadingIcon: [{
5847
+ type: i0.Input,
5848
+ args: [{
5849
+ isSignal: true,
5850
+ alias: "leadingIcon",
5851
+ required: false
5852
+ }]
5853
+ }],
5745
5854
  revealable: [{
5746
5855
  type: i0.Input,
5747
5856
  args: [{
@@ -5933,6 +6042,10 @@ i0.ɵɵngDeclareClassMetadata({
5933
6042
  alias: "disabled",
5934
6043
  required: false
5935
6044
  }]
6045
+ }],
6046
+ _fieldEl: [{
6047
+ type: i0.ViewChild,
6048
+ args: ["field", { isSignal: true }]
5936
6049
  }]
5937
6050
  }
5938
6051
  });
@@ -6274,7 +6387,7 @@ var TableToolbarComponent = class TableToolbarComponent {
6274
6387
  </ui-modal>
6275
6388
  `,
6276
6389
  isInline: true,
6277
- styles: [":host{display:inline-flex;max-width:100%}.toolbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.toolbar-item{position:relative}.toolbar-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:6px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#334155;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s,border-color .1s}.toolbar-btn:hover{background:#f8fafc}.toolbar-btn.toolbar-btn-active{border-color:#1e293b;background:#f8fafc}.toolbar-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.toolbar-badge{display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.toolbar-primary-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:6px;border:none;background:#2563eb;color:#fff;font-size:.8125rem;font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s}.toolbar-primary-btn:hover{background:#1d4ed8}.toolbar-primary-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.more-dropdown{position:absolute;top:calc(100% + 6px);right:0;z-index:200;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 4px 6px #0000000a,0 12px 28px #0000001a;min-width:200px;overflow:hidden}.more-option{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;background:none;border:none;border-bottom:1px solid #f1f5f9;font-size:.875rem;color:#1e293b;font-family:inherit;text-align:left;cursor:pointer;transition:background .1s}.more-option:last-child{border-bottom:none}.more-option:hover{background:#f8fafc}.more-option:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.more-badge{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.more-divider{height:1px;background:#f1f5f9;margin:2px 0}.more-view-name{font-size:.75rem;color:#64748b;max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-list{display:grid;grid-template-columns:1fr 1fr;max-height:340px;overflow-y:auto}@media(max-width:480px){.col-list{grid-template-columns:1fr}}@media(max-width:1024px){.toolbar-btn{padding:8px 12px}.toolbar-primary-btn{padding:8px 14px}}@media(pointer:coarse){.toolbar-btn,.toolbar-primary-btn{min-height:44px}}@media(max-width:640px){:host{display:flex;width:100%}.toolbar{width:100%;justify-content:flex-end}.toolbar-btn{padding:10px 12px;font-size:.8125rem;min-height:44px}.toolbar-primary-btn{padding:10px 14px;font-size:.8125rem;min-height:44px}.more-dropdown{max-height:calc(100vh - 140px);overflow-y:auto}.more-option{padding:12px 16px;font-size:.9375rem}}.col-option{display:flex;padding:9px 4px;border-bottom:1px solid #f1f5f9;transition:background .1s;border-radius:6px}.col-option:hover{background:#f8fafc}.col-option:nth-last-child(-n+2){border-bottom:none}.view-list{max-height:360px;overflow-y:auto;margin:0 -24px}.view-empty{padding:16px 24px;font-size:.9rem;color:#94a3b8;margin:0}.view-option{display:flex;align-items:center;padding-right:16px;border-bottom:1px solid #f1f5f9;transition:background .1s}.view-option:last-child{border-bottom:none}.view-option:hover{background:#f8fafc}.view-option.view-active{background:#eff6ff}.view-select-btn{flex:1;padding:12px 8px 12px 24px;background:none;border:none;font-size:.9rem;color:#334155;cursor:pointer;font-family:inherit;text-align:left}.view-delete-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:5px;background:none;border:none;cursor:pointer;color:#94a3b8}.view-delete-btn:hover{color:#dc2626;background:#fef2f2}\n"],
6390
+ styles: [":host{display:inline-flex;max-width:100%}.toolbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.toolbar-item{position:relative}.toolbar-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:6px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#334155;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s,border-color .1s}.toolbar-btn:hover{background:#f8fafc}.toolbar-btn.toolbar-btn-active{border-color:#1e293b;background:#f8fafc}.toolbar-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.toolbar-badge{display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.toolbar-primary-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:6px;border:none;background:#2563eb;color:#fff;font-size:.8125rem;font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s}.toolbar-primary-btn:hover{background:#1d4ed8}.toolbar-primary-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.more-dropdown{position:absolute;top:calc(100% + 6px);right:0;z-index:200;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 4px 6px #0000000a,0 12px 28px #0000001a;min-width:200px;overflow:hidden}.more-option{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;background:none;border:none;border-bottom:1px solid #f1f5f9;font-size:.875rem;color:#1e293b;font-family:inherit;text-align:left;cursor:pointer;transition:background .1s}.more-option:last-child{border-bottom:none}.more-option:hover{background:#f8fafc}.more-option:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.more-badge{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.more-divider{height:1px;background:#f1f5f9;margin:2px 0}.more-view-name{font-size:.75rem;color:#64748b;max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-list{display:grid;grid-template-columns:1fr 1fr;max-height:340px;overflow-y:auto}@media(max-width:480px){.col-list{grid-template-columns:1fr}}@media(max-width:1024px){.toolbar-btn{padding:8px 12px}.toolbar-primary-btn{padding:8px 14px}}@media(pointer:coarse){.toolbar-btn,.toolbar-primary-btn{min-height:44px}}@media(max-width:640px){:host{display:flex;width:100%;min-width:0}.toolbar{width:100%;min-width:0;justify-content:flex-end;flex-wrap:wrap}.toolbar-btn{padding:10px 12px;font-size:.8125rem;min-height:44px}.toolbar-primary-btn{padding:10px 14px;font-size:.8125rem;min-height:44px}.toolbar-btn,.toolbar-primary-btn{max-width:100%;white-space:normal;text-align:center;justify-content:center;line-height:1.25;overflow-wrap:anywhere}.toolbar-item{min-width:0;max-width:100%;display:flex}.more-dropdown{max-height:calc(100vh - 140px);overflow-y:auto}.more-option{padding:12px 16px;font-size:.9375rem}}.col-option{display:flex;padding:9px 4px;border-bottom:1px solid #f1f5f9;transition:background .1s;border-radius:6px}.col-option:hover{background:#f8fafc}.col-option:nth-last-child(-n+2){border-bottom:none}.view-list{max-height:360px;overflow-y:auto;margin:0 -24px}.view-empty{padding:16px 24px;font-size:.9rem;color:#94a3b8;margin:0}.view-option{display:flex;align-items:center;padding-right:16px;border-bottom:1px solid #f1f5f9;transition:background .1s}.view-option:last-child{border-bottom:none}.view-option:hover{background:#f8fafc}.view-option.view-active{background:#eff6ff}.view-select-btn{flex:1;padding:12px 8px 12px 24px;background:none;border:none;font-size:.9rem;color:#334155;cursor:pointer;font-family:inherit;text-align:left}.view-delete-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:5px;background:none;border:none;cursor:pointer;color:#94a3b8}.view-delete-btn:hover{color:#dc2626;background:#fef2f2}\n"],
6278
6391
  dependencies: [
6279
6392
  {
6280
6393
  kind: "ngmodule",
@@ -6398,6 +6511,7 @@ var TableToolbarComponent = class TableToolbarComponent {
6398
6511
  "inputName",
6399
6512
  "placeholder",
6400
6513
  "prefix",
6514
+ "leadingIcon",
6401
6515
  "revealable",
6402
6516
  "passwordRequirements",
6403
6517
  "passwordRules",
@@ -6594,7 +6708,7 @@ i0.ɵɵngDeclareClassMetadata({
6594
6708
  <ui-button modal-footer-right variant="primary" size="sm" [disabled]="!_saveViewName.trim()" (click)="confirmSaveName()"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Save</ui-button>
6595
6709
  </ui-modal>
6596
6710
  `,
6597
- styles: [":host{display:inline-flex;max-width:100%}.toolbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.toolbar-item{position:relative}.toolbar-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:6px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#334155;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s,border-color .1s}.toolbar-btn:hover{background:#f8fafc}.toolbar-btn.toolbar-btn-active{border-color:#1e293b;background:#f8fafc}.toolbar-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.toolbar-badge{display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.toolbar-primary-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:6px;border:none;background:#2563eb;color:#fff;font-size:.8125rem;font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s}.toolbar-primary-btn:hover{background:#1d4ed8}.toolbar-primary-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.more-dropdown{position:absolute;top:calc(100% + 6px);right:0;z-index:200;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 4px 6px #0000000a,0 12px 28px #0000001a;min-width:200px;overflow:hidden}.more-option{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;background:none;border:none;border-bottom:1px solid #f1f5f9;font-size:.875rem;color:#1e293b;font-family:inherit;text-align:left;cursor:pointer;transition:background .1s}.more-option:last-child{border-bottom:none}.more-option:hover{background:#f8fafc}.more-option:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.more-badge{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.more-divider{height:1px;background:#f1f5f9;margin:2px 0}.more-view-name{font-size:.75rem;color:#64748b;max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-list{display:grid;grid-template-columns:1fr 1fr;max-height:340px;overflow-y:auto}@media(max-width:480px){.col-list{grid-template-columns:1fr}}@media(max-width:1024px){.toolbar-btn{padding:8px 12px}.toolbar-primary-btn{padding:8px 14px}}@media(pointer:coarse){.toolbar-btn,.toolbar-primary-btn{min-height:44px}}@media(max-width:640px){:host{display:flex;width:100%}.toolbar{width:100%;justify-content:flex-end}.toolbar-btn{padding:10px 12px;font-size:.8125rem;min-height:44px}.toolbar-primary-btn{padding:10px 14px;font-size:.8125rem;min-height:44px}.more-dropdown{max-height:calc(100vh - 140px);overflow-y:auto}.more-option{padding:12px 16px;font-size:.9375rem}}.col-option{display:flex;padding:9px 4px;border-bottom:1px solid #f1f5f9;transition:background .1s;border-radius:6px}.col-option:hover{background:#f8fafc}.col-option:nth-last-child(-n+2){border-bottom:none}.view-list{max-height:360px;overflow-y:auto;margin:0 -24px}.view-empty{padding:16px 24px;font-size:.9rem;color:#94a3b8;margin:0}.view-option{display:flex;align-items:center;padding-right:16px;border-bottom:1px solid #f1f5f9;transition:background .1s}.view-option:last-child{border-bottom:none}.view-option:hover{background:#f8fafc}.view-option.view-active{background:#eff6ff}.view-select-btn{flex:1;padding:12px 8px 12px 24px;background:none;border:none;font-size:.9rem;color:#334155;cursor:pointer;font-family:inherit;text-align:left}.view-delete-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:5px;background:none;border:none;cursor:pointer;color:#94a3b8}.view-delete-btn:hover{color:#dc2626;background:#fef2f2}\n"]
6711
+ styles: [":host{display:inline-flex;max-width:100%}.toolbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.toolbar-item{position:relative}.toolbar-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:6px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#334155;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s,border-color .1s}.toolbar-btn:hover{background:#f8fafc}.toolbar-btn.toolbar-btn-active{border-color:#1e293b;background:#f8fafc}.toolbar-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.toolbar-badge{display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.toolbar-primary-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:6px;border:none;background:#2563eb;color:#fff;font-size:.8125rem;font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap;transition:background .1s}.toolbar-primary-btn:hover{background:#1d4ed8}.toolbar-primary-btn:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.more-dropdown{position:absolute;top:calc(100% + 6px);right:0;z-index:200;background:#fff;border:1px solid #e2e8f0;border-radius:10px;box-shadow:0 4px 6px #0000000a,0 12px 28px #0000001a;min-width:200px;overflow:hidden}.more-option{display:flex;align-items:center;gap:10px;width:100%;padding:10px 14px;background:none;border:none;border-bottom:1px solid #f1f5f9;font-size:.875rem;color:#1e293b;font-family:inherit;text-align:left;cursor:pointer;transition:background .1s}.more-option:last-child{border-bottom:none}.more-option:hover{background:#f8fafc}.more-option:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.more-badge{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;background:#1e293b;color:#fff;border-radius:999px;font-size:.625rem;font-weight:700;min-width:16px;height:16px;padding:0 4px}.more-divider{height:1px;background:#f1f5f9;margin:2px 0}.more-view-name{font-size:.75rem;color:#64748b;max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-list{display:grid;grid-template-columns:1fr 1fr;max-height:340px;overflow-y:auto}@media(max-width:480px){.col-list{grid-template-columns:1fr}}@media(max-width:1024px){.toolbar-btn{padding:8px 12px}.toolbar-primary-btn{padding:8px 14px}}@media(pointer:coarse){.toolbar-btn,.toolbar-primary-btn{min-height:44px}}@media(max-width:640px){:host{display:flex;width:100%;min-width:0}.toolbar{width:100%;min-width:0;justify-content:flex-end;flex-wrap:wrap}.toolbar-btn{padding:10px 12px;font-size:.8125rem;min-height:44px}.toolbar-primary-btn{padding:10px 14px;font-size:.8125rem;min-height:44px}.toolbar-btn,.toolbar-primary-btn{max-width:100%;white-space:normal;text-align:center;justify-content:center;line-height:1.25;overflow-wrap:anywhere}.toolbar-item{min-width:0;max-width:100%;display:flex}.more-dropdown{max-height:calc(100vh - 140px);overflow-y:auto}.more-option{padding:12px 16px;font-size:.9375rem}}.col-option{display:flex;padding:9px 4px;border-bottom:1px solid #f1f5f9;transition:background .1s;border-radius:6px}.col-option:hover{background:#f8fafc}.col-option:nth-last-child(-n+2){border-bottom:none}.view-list{max-height:360px;overflow-y:auto;margin:0 -24px}.view-empty{padding:16px 24px;font-size:.9rem;color:#94a3b8;margin:0}.view-option{display:flex;align-items:center;padding-right:16px;border-bottom:1px solid #f1f5f9;transition:background .1s}.view-option:last-child{border-bottom:none}.view-option:hover{background:#f8fafc}.view-option.view-active{background:#eff6ff}.view-select-btn{flex:1;padding:12px 8px 12px 24px;background:none;border:none;font-size:.9rem;color:#334155;cursor:pointer;font-family:inherit;text-align:left}.view-delete-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:5px;background:none;border:none;cursor:pointer;color:#94a3b8}.view-delete-btn:hover{color:#dc2626;background:#fef2f2}\n"]
6598
6712
  }]
6599
6713
  }],
6600
6714
  propDecorators: {
@@ -7355,7 +7469,7 @@ var ProgressBarComponent = class ProgressBarComponent {
7355
7469
  </div>
7356
7470
  `,
7357
7471
  isInline: true,
7358
- styles: [":host{display:block}.pb{display:flex;align-items:center;gap:8px;min-width:100px}.pb-track{flex:1;height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden}.pb-fill{height:100%;border-radius:3px;transition:width .3s}@media(prefers-reduced-motion:reduce){.pb-fill{transition:none}}.pb-blue{background:var(--ui-progress-fill, var(--ui-accent, #3b82f6))}.pb-green{background:#16a34a}.pb-amber{background:#f59e0b}.pb-red{background:#ef4444}.pb-slate{background:#94a3b8}@media(forced-colors:active){.pb-track{background:Canvas;border:1px solid CanvasText}.pb-fill{background:Highlight;forced-color-adjust:none}}.pb-label{font-size:.75rem;font-weight:500;color:#64748b;white-space:nowrap}\n"],
7472
+ styles: [":host{display:block}.pb{display:flex;align-items:center;gap:8px;min-width:100px}.pb-track{flex:1;height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden}.pb-fill{height:100%;border-radius:3px;transition:width .3s}@media(prefers-reduced-motion:reduce){.pb-fill{transition:none}}.pb-blue{background:var(--ui-progress-fill, var(--ui-accent, #3b82f6))}.pb-green{background:#16a34a}.pb-amber{background:#f59e0b}.pb-orange{background:#f97316}.pb-red{background:#ef4444}.pb-slate{background:#94a3b8}@media(forced-colors:active){.pb-track{background:Canvas;border:1px solid CanvasText}.pb-fill{background:Highlight;forced-color-adjust:none}}.pb-label{font-size:.75rem;font-weight:500;color:#64748b;white-space:nowrap}\n"],
7359
7473
  dependencies: [{
7360
7474
  kind: "directive",
7361
7475
  type: TooltipDirective,
@@ -7393,7 +7507,7 @@ i0.ɵɵngDeclareClassMetadata({
7393
7507
  @if (label()) { <span class="pb-label">{{ label() }}</span> }
7394
7508
  </div>
7395
7509
  `,
7396
- styles: [":host{display:block}.pb{display:flex;align-items:center;gap:8px;min-width:100px}.pb-track{flex:1;height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden}.pb-fill{height:100%;border-radius:3px;transition:width .3s}@media(prefers-reduced-motion:reduce){.pb-fill{transition:none}}.pb-blue{background:var(--ui-progress-fill, var(--ui-accent, #3b82f6))}.pb-green{background:#16a34a}.pb-amber{background:#f59e0b}.pb-red{background:#ef4444}.pb-slate{background:#94a3b8}@media(forced-colors:active){.pb-track{background:Canvas;border:1px solid CanvasText}.pb-fill{background:Highlight;forced-color-adjust:none}}.pb-label{font-size:.75rem;font-weight:500;color:#64748b;white-space:nowrap}\n"]
7510
+ styles: [":host{display:block}.pb{display:flex;align-items:center;gap:8px;min-width:100px}.pb-track{flex:1;height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden}.pb-fill{height:100%;border-radius:3px;transition:width .3s}@media(prefers-reduced-motion:reduce){.pb-fill{transition:none}}.pb-blue{background:var(--ui-progress-fill, var(--ui-accent, #3b82f6))}.pb-green{background:#16a34a}.pb-amber{background:#f59e0b}.pb-orange{background:#f97316}.pb-red{background:#ef4444}.pb-slate{background:#94a3b8}@media(forced-colors:active){.pb-track{background:Canvas;border:1px solid CanvasText}.pb-fill{background:Highlight;forced-color-adjust:none}}.pb-label{font-size:.75rem;font-weight:500;color:#64748b;white-space:nowrap}\n"]
7397
7511
  }]
7398
7512
  }],
7399
7513
  propDecorators: {
@@ -7475,6 +7589,7 @@ var SelectComponent = class SelectComponent {
7475
7589
  constructor() {
7476
7590
  this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
7477
7591
  this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
7592
+ this.labelHidden = input(false, ...ngDevMode ? [{ debugName: "labelHidden" }] : /* istanbul ignore next */ []);
7478
7593
  this.inputName = input("", ...ngDevMode ? [{ debugName: "inputName" }] : /* istanbul ignore next */ []);
7479
7594
  this.placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
7480
7595
  this.options = input([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
@@ -7507,6 +7622,7 @@ var SelectComponent = class SelectComponent {
7507
7622
  this._activeError = computed(() => this.error() || (this._reveal.revealed() ? this.errorMessage() : ""), ...ngDevMode ? [{ debugName: "_activeError" }] : /* istanbul ignore next */ []);
7508
7623
  this._onValidatorChange = () => {};
7509
7624
  this._selectId = `sl-${Math.random().toString(36).slice(2, 8)}`;
7625
+ this._hostEl = inject(ElementRef);
7510
7626
  this._onChange = (_) => {};
7511
7627
  this._warned = false;
7512
7628
  this._onTouched = () => {};
@@ -7523,6 +7639,9 @@ var SelectComponent = class SelectComponent {
7523
7639
  registerOnValidatorChange(fn) {
7524
7640
  this._onValidatorChange = fn;
7525
7641
  }
7642
+ focus(options) {
7643
+ this._hostEl.nativeElement.querySelector("select")?.focus(options);
7644
+ }
7526
7645
  _norm(key) {
7527
7646
  if (this.valueType() !== "number") return key;
7528
7647
  const t = key.trim();
@@ -7611,6 +7730,13 @@ var SelectComponent = class SelectComponent {
7611
7730
  isRequired: false,
7612
7731
  transformFunction: null
7613
7732
  },
7733
+ labelHidden: {
7734
+ classPropertyName: "labelHidden",
7735
+ publicName: "labelHidden",
7736
+ isSignal: true,
7737
+ isRequired: false,
7738
+ transformFunction: null
7739
+ },
7614
7740
  inputName: {
7615
7741
  classPropertyName: "inputName",
7616
7742
  publicName: "inputName",
@@ -7713,7 +7839,7 @@ var SelectComponent = class SelectComponent {
7713
7839
  ngImport: i0,
7714
7840
  template: `
7715
7841
  <div class="sl-field" [class.sl-error]="_activeError()" [class.sl-disabled]="disabled()">
7716
- @if (label()) {
7842
+ @if (label() && !labelHidden()) {
7717
7843
  <label class="sl-label" [for]="_selectId">
7718
7844
  {{ label() }}
7719
7845
  @if (required()) { <span class="sl-required" aria-hidden="true">*</span> }
@@ -7726,7 +7852,7 @@ var SelectComponent = class SelectComponent {
7726
7852
  [attr.name]="inputName() || null"
7727
7853
  [disabled]="disabled()"
7728
7854
  [attr.required]="required() || null"
7729
- [attr.aria-label]="ariaLabel() || null"
7855
+ [attr.aria-label]="ariaLabel() || (labelHidden() ? label() : '') || null"
7730
7856
  [attr.aria-invalid]="_activeError() ? 'true' : null"
7731
7857
  [attr.aria-describedby]="_describedBy() || null"
7732
7858
  (change)="onChange($event)"
@@ -7785,7 +7911,7 @@ i0.ɵɵngDeclareClassMetadata({
7785
7911
  ],
7786
7912
  template: `
7787
7913
  <div class="sl-field" [class.sl-error]="_activeError()" [class.sl-disabled]="disabled()">
7788
- @if (label()) {
7914
+ @if (label() && !labelHidden()) {
7789
7915
  <label class="sl-label" [for]="_selectId">
7790
7916
  {{ label() }}
7791
7917
  @if (required()) { <span class="sl-required" aria-hidden="true">*</span> }
@@ -7798,7 +7924,7 @@ i0.ɵɵngDeclareClassMetadata({
7798
7924
  [attr.name]="inputName() || null"
7799
7925
  [disabled]="disabled()"
7800
7926
  [attr.required]="required() || null"
7801
- [attr.aria-label]="ariaLabel() || null"
7927
+ [attr.aria-label]="ariaLabel() || (labelHidden() ? label() : '') || null"
7802
7928
  [attr.aria-invalid]="_activeError() ? 'true' : null"
7803
7929
  [attr.aria-describedby]="_describedBy() || null"
7804
7930
  (change)="onChange($event)"
@@ -7843,6 +7969,14 @@ i0.ɵɵngDeclareClassMetadata({
7843
7969
  required: false
7844
7970
  }]
7845
7971
  }],
7972
+ labelHidden: [{
7973
+ type: i0.Input,
7974
+ args: [{
7975
+ isSignal: true,
7976
+ alias: "labelHidden",
7977
+ required: false
7978
+ }]
7979
+ }],
7846
7980
  inputName: [{
7847
7981
  type: i0.Input,
7848
7982
  args: [{
@@ -7952,6 +8086,7 @@ var ToastService = class ToastService {
7952
8086
  this.dismissible = signal(false, ...ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []);
7953
8087
  this.persistentLiveRegion = signal(false, ...ngDevMode ? [{ debugName: "persistentLiveRegion" }] : /* istanbul ignore next */ []);
7954
8088
  this.details = signal(null, ...ngDevMode ? [{ debugName: "details" }] : /* istanbul ignore next */ []);
8089
+ this.repeatTick = signal(0, ...ngDevMode ? [{ debugName: "repeatTick" }] : /* istanbul ignore next */ []);
7955
8090
  this.queuedCount = signal(0, ...ngDevMode ? [{ debugName: "queuedCount" }] : /* istanbul ignore next */ []);
7956
8091
  this.queueDefault = signal(false, ...ngDevMode ? [{ debugName: "queueDefault" }] : /* istanbul ignore next */ []);
7957
8092
  this.countdownDefault = signal(false, ...ngDevMode ? [{ debugName: "countdownDefault" }] : /* istanbul ignore next */ []);
@@ -8069,6 +8204,12 @@ var ToastService = class ToastService {
8069
8204
  duration: options.duration ?? defaultDuration,
8070
8205
  details
8071
8206
  };
8207
+ if (options.repeat && this.message() === msg && this.type() === type) {
8208
+ this._clearAdvance();
8209
+ this.repeatTick.update((n) => n + 1);
8210
+ this._present(pending);
8211
+ return;
8212
+ }
8072
8213
  const queue = options.queue ?? this.queueDefault();
8073
8214
  const busy = this.message() !== null || this._advanceTimer !== null;
8074
8215
  if (queue && busy) {
@@ -8202,6 +8343,7 @@ var ToastComponent = class ToastComponent {
8202
8343
  this.countdownLabel = input("Dismissing in {n}s", ...ngDevMode ? [{ debugName: "countdownLabel" }] : /* istanbul ignore next */ []);
8203
8344
  this.queueLabel = input("+{n} more", ...ngDevMode ? [{ debugName: "queueLabel" }] : /* istanbul ignore next */ []);
8204
8345
  this.action = output();
8346
+ this.repeatKeys = computed(() => [this.toast.repeatTick()], ...ngDevMode ? [{ debugName: "repeatKeys" }] : /* istanbul ignore next */ []);
8205
8347
  this.isRich = computed(() => {
8206
8348
  const d = this.toast.details();
8207
8349
  return !!d && (!!d.title || d.actions.length > 0 || d.countdown);
@@ -8217,6 +8359,7 @@ var ToastComponent = class ToastComponent {
8217
8359
  const m = this._adoptedMessage();
8218
8360
  return m !== null && m === this.toast.message();
8219
8361
  }, ...ngDevMode ? [{ debugName: "adopted" }] : /* istanbul ignore next */ []);
8362
+ this._lastRepeatTick = this.toast.repeatTick();
8220
8363
  this._wasWaiting = false;
8221
8364
  this._hover = false;
8222
8365
  this._focus = false;
@@ -8237,7 +8380,13 @@ var ToastComponent = class ToastComponent {
8237
8380
  effect(() => {
8238
8381
  const host = this.isHost();
8239
8382
  const msg = this.toast.message();
8383
+ const tick = this.toast.repeatTick();
8240
8384
  untracked(() => {
8385
+ if (tick !== this._lastRepeatTick) {
8386
+ this._lastRepeatTick = tick;
8387
+ if (host) this._adoptedMessage.set(null);
8388
+ this._focus = false;
8389
+ }
8241
8390
  if (msg === null) {
8242
8391
  this._hover = false;
8243
8392
  this._focus = false;
@@ -8337,6 +8486,7 @@ var ToastComponent = class ToastComponent {
8337
8486
  }
8338
8487
 
8339
8488
  <ng-template #card>
8489
+ @for (k of repeatKeys(); track k) {
8340
8490
  <div
8341
8491
  class="t-toast"
8342
8492
  [class.t-rich]="isRich()"
@@ -8397,6 +8547,7 @@ var ToastComponent = class ToastComponent {
8397
8547
  }
8398
8548
  }
8399
8549
  </div>
8550
+ }
8400
8551
  </ng-template>
8401
8552
  `,
8402
8553
  isInline: true,
@@ -8441,6 +8592,7 @@ i0.ɵɵngDeclareClassMetadata({
8441
8592
  }
8442
8593
 
8443
8594
  <ng-template #card>
8595
+ @for (k of repeatKeys(); track k) {
8444
8596
  <div
8445
8597
  class="t-toast"
8446
8598
  [class.t-rich]="isRich()"
@@ -8501,6 +8653,7 @@ i0.ɵɵngDeclareClassMetadata({
8501
8653
  }
8502
8654
  }
8503
8655
  </div>
8656
+ }
8504
8657
  </ng-template>
8505
8658
  `,
8506
8659
  styles: [".t-live{position:absolute;width:0;height:0;margin:0;padding:0;overflow:visible}.t-toast{position:fixed;bottom:max(24px,env(safe-area-inset-bottom,0px));left:50%;transform:translate(-50%);background:#047857;color:#fff;padding:11px 20px;border-radius:12px;font-size:.875rem;font-weight:500;z-index:9999;box-shadow:0 4px 16px #0000002e;animation:t-in .28s cubic-bezier(.16,1,.3,1);display:flex;align-items:center;gap:8px;max-width:calc(100vw - 32px - env(safe-area-inset-left,0px) - env(safe-area-inset-right,0px));overflow-wrap:anywhere;word-break:break-word}.t-error{background:#dc2626}.t-info{background:#2563eb}.t-adopted{animation:none}.t-text{min-width:0}.t-close{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;margin:-4px -10px -4px 0;padding:0;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer}.t-close:after{content:\"\";position:absolute;inset:-8px}.t-close:hover{background:#fff3}.t-close:focus-visible{outline:2px solid #fff;outline-offset:1px}.t-rich{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:start;column-gap:8px;row-gap:10px;min-width:min(320px,calc(100vw - 32px))}.t-rich>svg:first-child{margin-top:2px}.t-content{display:flex;flex-direction:column;gap:2px;min-width:0}.t-title{font-weight:700}.t-queue{grid-column:1 / -1;justify-self:end;font-size:.75rem;font-weight:600;padding:1px 8px;border-radius:999px;background:#ffffff38}.t-actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:8px}.t-action{min-height:32px;padding:6px 14px;border-radius:8px;font:inherit;font-size:.8125rem;font-weight:600;cursor:pointer;color:#fff;background:#ffffff2e;border:1px solid rgba(255,255,255,.6)}.t-action:hover:not(:disabled){background:#ffffff4d}.t-action:focus-visible{outline:2px solid #fff;outline-offset:2px}.t-action:disabled{opacity:.5;cursor:not-allowed}.t-action-primary{background:#fff;color:#0f172a;border-color:#fff}.t-action-primary:hover:not(:disabled){background:#f1f5f9}.t-action-danger{background:#7f1d1d;border-color:#ffffffb3}.t-action-danger:hover:not(:disabled){background:#991b1b}.t-countdown{grid-column:1 / -1;display:flex;flex-direction:column;gap:4px}.t-countdown-bar{height:4px;border-radius:2px;background:#ffffff47;overflow:hidden}.t-countdown-fill{height:100%;background:#fff;transition:width .2s linear}.t-countdown-label{font-size:.75rem;opacity:.85;font-variant-numeric:tabular-nums}@media(prefers-reduced-motion:reduce){.t-countdown-fill{transition:none}}@media(pointer:coarse),(max-width:480px){.t-action{min-height:44px}}@keyframes t-in{0%{opacity:0;transform:translate(-50%) translateY(10px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.t-toast{animation:none}}@media(max-width:480px){.t-toast{bottom:max(16px,env(safe-area-inset-bottom,16px));font-size:.8125rem;padding:10px 16px}}\n"]
@@ -8636,6 +8789,7 @@ var DetailCardComponent = class DetailCardComponent {
8636
8789
  this.background = input("", ...ngDevMode ? [{ debugName: "background" }] : /* istanbul ignore next */ []);
8637
8790
  this.headerBackground = input("", ...ngDevMode ? [{ debugName: "headerBackground" }] : /* istanbul ignore next */ []);
8638
8791
  this.footerBackground = input("", ...ngDevMode ? [{ debugName: "footerBackground" }] : /* istanbul ignore next */ []);
8792
+ this.footerAlign = input("start", ...ngDevMode ? [{ debugName: "footerAlign" }] : /* istanbul ignore next */ []);
8639
8793
  this.textColor = input("", ...ngDevMode ? [{ debugName: "textColor" }] : /* istanbul ignore next */ []);
8640
8794
  this.showHeader = input(true, ...ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []);
8641
8795
  this.collapsible = input(true, ...ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []);
@@ -8760,6 +8914,13 @@ var DetailCardComponent = class DetailCardComponent {
8760
8914
  isRequired: false,
8761
8915
  transformFunction: null
8762
8916
  },
8917
+ footerAlign: {
8918
+ classPropertyName: "footerAlign",
8919
+ publicName: "footerAlign",
8920
+ isSignal: true,
8921
+ isRequired: false,
8922
+ transformFunction: null
8923
+ },
8763
8924
  textColor: {
8764
8925
  classPropertyName: "textColor",
8765
8926
  publicName: "textColor",
@@ -8924,11 +9085,11 @@ var DetailCardComponent = class DetailCardComponent {
8924
9085
  <ng-content />
8925
9086
  </div>
8926
9087
  </div>
8927
- <div class="dc-footer" [class.dc-footer--hidden]="!isOpen()" [style.background]="footerBackground() || null"><ng-content select="[card-footer]" /></div>
9088
+ <div class="dc-footer" [class.dc-footer--hidden]="!isOpen()" [class.dc-footer--end]="footerAlign() === 'end'" [style.background]="footerBackground() || null"><ng-content select="[card-footer]" /></div>
8928
9089
  </div>
8929
9090
  `,
8930
9091
  isInline: true,
8931
- styles: [":host{display:block;margin-bottom:16px}:host(:last-child){margin-bottom:0}:host(.dc-fill-host){height:100%;margin-bottom:0}.dc.dc-fill{height:100%;box-sizing:border-box;display:flex;flex-direction:column}.dc.dc-fill .dc-body-wrap{flex:1 1 auto;min-height:0}.dc.dc-fill .dc-body{display:flex;flex-direction:column}.dc-selectable{cursor:pointer}.dc-selected{outline:2px solid #3b82f6;outline-offset:-1px}.dc{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden}.dc-header{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;padding:14px 18px}.dc-header.open{border-bottom:1px solid #f1f5f9}.dc-has-bg .dc-header.open{border-bottom-color:#94a3b859}.dc-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}@media(hover:hover){.dc-header.collapsible:hover{background:#f8fafc}}.dc-chevron{flex-shrink:0;color:var(--dc-text, #64748b)}.dc-chevron svg{transition:transform .2s}.dc-chevron svg.rotated{transform:rotate(-90deg)}.dc-header-text{display:flex;flex-direction:column;gap:2px;flex:1 1 160px;min-width:0;word-break:break-word;overflow-wrap:anywhere}.dc-title{font-size:.8125rem;font-weight:800;letter-spacing:.07em;color:var(--dc-text, #1e293b);line-height:1.3;text-transform:uppercase}.dc-title--as-written{text-transform:none}.dc-subtitle{font-size:.8125rem;color:var(--dc-text, #475569)}.dc-has-text-color .dc-subtitle{opacity:.8}.dc-has-text-color .dc-header.open{border-bottom-color:#94a3b859}.dc-edit{flex-shrink:0;margin-left:auto}.dc-edit-action{display:inline-flex;align-items:center;justify-content:center;gap:5px;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;color:#64748b;background:none;border:1px solid #e2e8f0;border-radius:6px;padding:4px 10px;cursor:pointer;white-space:nowrap;transition:background-color .15s ease,color .15s ease}.dc-edit-action:hover{background:#f1f5f9;color:#1e293b}.dc-edit-action:focus-visible{outline:2px solid var(--ui-focus, #3b82f6);outline-offset:2px}@media(pointer:coarse),(max-width:480px){.dc-edit-action{min-height:44px}}.dc-body-wrap{display:grid;grid-template-rows:1fr;transition:grid-template-rows .25s ease}.dc-body-wrap.collapsed{grid-template-rows:0fr}.dc-body{box-sizing:border-box;padding:16px 18px;min-height:0;overflow-x:hidden;overflow-y:auto;max-height:var(--dc-body-max-height, none)}.dc-footer{padding:10px 18px;border-top:1px solid #f1f5f9}.dc-footer:empty,.dc-footer.dc-footer--hidden{display:none}.dc-has-bg .dc-footer{border-top-color:#94a3b859}@media(max-width:480px){.dc-footer{padding:10px 14px}.dc-header{padding:12px 14px}.dc-body{padding:14px}.dc-edit{margin-left:0}}@media(prefers-reduced-motion:reduce){.dc-body-wrap,.dc-chevron svg{transition:none}}\n"],
9092
+ styles: [":host{display:block;margin-bottom:16px}:host(:last-child){margin-bottom:0}:host(.dc-fill-host){height:100%;margin-bottom:0}.dc.dc-fill{height:100%;box-sizing:border-box;display:flex;flex-direction:column}.dc.dc-fill .dc-body-wrap{flex:1 1 auto;min-height:0}.dc.dc-fill .dc-body{display:flex;flex-direction:column}.dc-selectable{cursor:pointer}.dc-selected{outline:2px solid #3b82f6;outline-offset:-1px}.dc{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden}.dc-header{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;padding:14px 18px}.dc-header.open{border-bottom:1px solid #f1f5f9}.dc-has-bg .dc-header.open{border-bottom-color:#94a3b859}.dc-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}@media(hover:hover){.dc-header.collapsible:hover{background:#f8fafc}}.dc-chevron{flex-shrink:0;color:var(--dc-text, #64748b)}.dc-chevron svg{transition:transform .2s}.dc-chevron svg.rotated{transform:rotate(-90deg)}.dc-header-text{display:flex;flex-direction:column;gap:2px;flex:1 1 160px;min-width:0;word-break:break-word;overflow-wrap:anywhere}.dc-title{font-size:.8125rem;font-weight:800;letter-spacing:.07em;color:var(--dc-text, #1e293b);line-height:1.3;text-transform:uppercase}.dc-title--as-written{text-transform:none}.dc-subtitle{font-size:.8125rem;color:var(--dc-text, #475569)}.dc-has-text-color .dc-subtitle{opacity:.8}.dc-has-text-color .dc-header.open{border-bottom-color:#94a3b859}.dc-edit{flex-shrink:0;margin-left:auto}.dc-edit-action{display:inline-flex;align-items:center;justify-content:center;gap:5px;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;color:#64748b;background:none;border:1px solid #e2e8f0;border-radius:6px;padding:4px 10px;cursor:pointer;white-space:nowrap;transition:background-color .15s ease,color .15s ease}.dc-edit-action:hover{background:#f1f5f9;color:#1e293b}.dc-edit-action:focus-visible{outline:2px solid var(--ui-focus, #3b82f6);outline-offset:2px}@media(pointer:coarse),(max-width:480px){.dc-edit-action{min-height:44px}}.dc-body-wrap{display:grid;grid-template-rows:1fr;transition:grid-template-rows .25s ease}.dc-body-wrap.collapsed{grid-template-rows:0fr}.dc-body{box-sizing:border-box;padding:16px 18px;min-height:0;overflow-x:hidden;overflow-y:auto;max-height:var(--dc-body-max-height, none)}.dc-footer{padding:10px 18px;border-top:1px solid #f1f5f9}.dc-footer:empty,.dc-footer.dc-footer--hidden{display:none}.dc-footer.dc-footer--end:not(:empty):not(.dc-footer--hidden){display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px}.dc-has-bg .dc-footer{border-top-color:#94a3b859}@media(max-width:480px){.dc-footer{padding:10px 14px}.dc-header{padding:12px 14px}.dc-body{padding:14px}.dc-edit{margin-left:0}}@media(prefers-reduced-motion:reduce){.dc-body-wrap,.dc-chevron svg{transition:none}}\n"],
8932
9093
  dependencies: [{
8933
9094
  kind: "component",
8934
9095
  type: ButtonComponent,
@@ -9025,10 +9186,10 @@ i0.ɵɵngDeclareClassMetadata({
9025
9186
  <ng-content />
9026
9187
  </div>
9027
9188
  </div>
9028
- <div class="dc-footer" [class.dc-footer--hidden]="!isOpen()" [style.background]="footerBackground() || null"><ng-content select="[card-footer]" /></div>
9189
+ <div class="dc-footer" [class.dc-footer--hidden]="!isOpen()" [class.dc-footer--end]="footerAlign() === 'end'" [style.background]="footerBackground() || null"><ng-content select="[card-footer]" /></div>
9029
9190
  </div>
9030
9191
  `,
9031
- styles: [":host{display:block;margin-bottom:16px}:host(:last-child){margin-bottom:0}:host(.dc-fill-host){height:100%;margin-bottom:0}.dc.dc-fill{height:100%;box-sizing:border-box;display:flex;flex-direction:column}.dc.dc-fill .dc-body-wrap{flex:1 1 auto;min-height:0}.dc.dc-fill .dc-body{display:flex;flex-direction:column}.dc-selectable{cursor:pointer}.dc-selected{outline:2px solid #3b82f6;outline-offset:-1px}.dc{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden}.dc-header{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;padding:14px 18px}.dc-header.open{border-bottom:1px solid #f1f5f9}.dc-has-bg .dc-header.open{border-bottom-color:#94a3b859}.dc-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}@media(hover:hover){.dc-header.collapsible:hover{background:#f8fafc}}.dc-chevron{flex-shrink:0;color:var(--dc-text, #64748b)}.dc-chevron svg{transition:transform .2s}.dc-chevron svg.rotated{transform:rotate(-90deg)}.dc-header-text{display:flex;flex-direction:column;gap:2px;flex:1 1 160px;min-width:0;word-break:break-word;overflow-wrap:anywhere}.dc-title{font-size:.8125rem;font-weight:800;letter-spacing:.07em;color:var(--dc-text, #1e293b);line-height:1.3;text-transform:uppercase}.dc-title--as-written{text-transform:none}.dc-subtitle{font-size:.8125rem;color:var(--dc-text, #475569)}.dc-has-text-color .dc-subtitle{opacity:.8}.dc-has-text-color .dc-header.open{border-bottom-color:#94a3b859}.dc-edit{flex-shrink:0;margin-left:auto}.dc-edit-action{display:inline-flex;align-items:center;justify-content:center;gap:5px;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;color:#64748b;background:none;border:1px solid #e2e8f0;border-radius:6px;padding:4px 10px;cursor:pointer;white-space:nowrap;transition:background-color .15s ease,color .15s ease}.dc-edit-action:hover{background:#f1f5f9;color:#1e293b}.dc-edit-action:focus-visible{outline:2px solid var(--ui-focus, #3b82f6);outline-offset:2px}@media(pointer:coarse),(max-width:480px){.dc-edit-action{min-height:44px}}.dc-body-wrap{display:grid;grid-template-rows:1fr;transition:grid-template-rows .25s ease}.dc-body-wrap.collapsed{grid-template-rows:0fr}.dc-body{box-sizing:border-box;padding:16px 18px;min-height:0;overflow-x:hidden;overflow-y:auto;max-height:var(--dc-body-max-height, none)}.dc-footer{padding:10px 18px;border-top:1px solid #f1f5f9}.dc-footer:empty,.dc-footer.dc-footer--hidden{display:none}.dc-has-bg .dc-footer{border-top-color:#94a3b859}@media(max-width:480px){.dc-footer{padding:10px 14px}.dc-header{padding:12px 14px}.dc-body{padding:14px}.dc-edit{margin-left:0}}@media(prefers-reduced-motion:reduce){.dc-body-wrap,.dc-chevron svg{transition:none}}\n"]
9192
+ styles: [":host{display:block;margin-bottom:16px}:host(:last-child){margin-bottom:0}:host(.dc-fill-host){height:100%;margin-bottom:0}.dc.dc-fill{height:100%;box-sizing:border-box;display:flex;flex-direction:column}.dc.dc-fill .dc-body-wrap{flex:1 1 auto;min-height:0}.dc.dc-fill .dc-body{display:flex;flex-direction:column}.dc-selectable{cursor:pointer}.dc-selected{outline:2px solid #3b82f6;outline-offset:-1px}.dc{background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden}.dc-header{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;padding:14px 18px}.dc-header.open{border-bottom:1px solid #f1f5f9}.dc-has-bg .dc-header.open{border-bottom-color:#94a3b859}.dc-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}@media(hover:hover){.dc-header.collapsible:hover{background:#f8fafc}}.dc-chevron{flex-shrink:0;color:var(--dc-text, #64748b)}.dc-chevron svg{transition:transform .2s}.dc-chevron svg.rotated{transform:rotate(-90deg)}.dc-header-text{display:flex;flex-direction:column;gap:2px;flex:1 1 160px;min-width:0;word-break:break-word;overflow-wrap:anywhere}.dc-title{font-size:.8125rem;font-weight:800;letter-spacing:.07em;color:var(--dc-text, #1e293b);line-height:1.3;text-transform:uppercase}.dc-title--as-written{text-transform:none}.dc-subtitle{font-size:.8125rem;color:var(--dc-text, #475569)}.dc-has-text-color .dc-subtitle{opacity:.8}.dc-has-text-color .dc-header.open{border-bottom-color:#94a3b859}.dc-edit{flex-shrink:0;margin-left:auto}.dc-edit-action{display:inline-flex;align-items:center;justify-content:center;gap:5px;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;color:#64748b;background:none;border:1px solid #e2e8f0;border-radius:6px;padding:4px 10px;cursor:pointer;white-space:nowrap;transition:background-color .15s ease,color .15s ease}.dc-edit-action:hover{background:#f1f5f9;color:#1e293b}.dc-edit-action:focus-visible{outline:2px solid var(--ui-focus, #3b82f6);outline-offset:2px}@media(pointer:coarse),(max-width:480px){.dc-edit-action{min-height:44px}}.dc-body-wrap{display:grid;grid-template-rows:1fr;transition:grid-template-rows .25s ease}.dc-body-wrap.collapsed{grid-template-rows:0fr}.dc-body{box-sizing:border-box;padding:16px 18px;min-height:0;overflow-x:hidden;overflow-y:auto;max-height:var(--dc-body-max-height, none)}.dc-footer{padding:10px 18px;border-top:1px solid #f1f5f9}.dc-footer:empty,.dc-footer.dc-footer--hidden{display:none}.dc-footer.dc-footer--end:not(:empty):not(.dc-footer--hidden){display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px}.dc-has-bg .dc-footer{border-top-color:#94a3b859}@media(max-width:480px){.dc-footer{padding:10px 14px}.dc-header{padding:12px 14px}.dc-body{padding:14px}.dc-edit{margin-left:0}}@media(prefers-reduced-motion:reduce){.dc-body-wrap,.dc-chevron svg{transition:none}}\n"]
9032
9193
  }]
9033
9194
  }],
9034
9195
  propDecorators: {
@@ -9104,6 +9265,14 @@ i0.ɵɵngDeclareClassMetadata({
9104
9265
  required: false
9105
9266
  }]
9106
9267
  }],
9268
+ footerAlign: [{
9269
+ type: i0.Input,
9270
+ args: [{
9271
+ isSignal: true,
9272
+ alias: "footerAlign",
9273
+ required: false
9274
+ }]
9275
+ }],
9107
9276
  textColor: [{
9108
9277
  type: i0.Input,
9109
9278
  args: [{
@@ -9415,6 +9584,7 @@ var OptionCardComponent = class OptionCardComponent {
9415
9584
  "background",
9416
9585
  "headerBackground",
9417
9586
  "footerBackground",
9587
+ "footerAlign",
9418
9588
  "textColor",
9419
9589
  "showHeader",
9420
9590
  "collapsible",
@@ -9791,6 +9961,48 @@ i0.ɵɵngDeclareClassMetadata({
9791
9961
  }]
9792
9962
  }
9793
9963
  });
9964
+ var HintComponent = class HintComponent {
9965
+ static {
9966
+ this.ɵfac = i0.ɵɵngDeclareFactory({
9967
+ minVersion: "12.0.0",
9968
+ version: "22.2.2",
9969
+ ngImport: i0,
9970
+ type: HintComponent,
9971
+ deps: [],
9972
+ target: i0.ɵɵFactoryTarget.Component
9973
+ });
9974
+ }
9975
+ static {
9976
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
9977
+ minVersion: "14.0.0",
9978
+ version: "22.2.2",
9979
+ type: HintComponent,
9980
+ isStandalone: true,
9981
+ selector: "ui-hint",
9982
+ ngImport: i0,
9983
+ template: `<p class="hint"><ng-content /></p>`,
9984
+ isInline: true,
9985
+ styles: [":host{display:block}.hint{font-size:.75rem;line-height:1.4;color:#64748b;margin:0}\n"],
9986
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
9987
+ });
9988
+ }
9989
+ };
9990
+ i0.ɵɵngDeclareClassMetadata({
9991
+ minVersion: "12.0.0",
9992
+ version: "22.2.2",
9993
+ ngImport: i0,
9994
+ type: HintComponent,
9995
+ decorators: [{
9996
+ type: Component,
9997
+ args: [{
9998
+ selector: "ui-hint",
9999
+ standalone: true,
10000
+ changeDetection: ChangeDetectionStrategy.OnPush,
10001
+ template: `<p class="hint"><ng-content /></p>`,
10002
+ styles: [":host{display:block}.hint{font-size:.75rem;line-height:1.4;color:#64748b;margin:0}\n"]
10003
+ }]
10004
+ }]
10005
+ });
9794
10006
  function detectCsvDelimiter(text) {
9795
10007
  const counts = {
9796
10008
  ",": 0,
@@ -9900,6 +10112,7 @@ var ImportExportComponent = class ImportExportComponent {
9900
10112
  this.importing = false;
9901
10113
  this.importResult = null;
9902
10114
  this.csvFile = null;
10115
+ this.idPrefix = `ie-ex-${ImportExportComponent.nextId++}-`;
9903
10116
  this.destroyRef.onDestroy(() => this.stopImportTimer());
9904
10117
  effect(() => {
9905
10118
  const v = this._configInput();
@@ -10095,6 +10308,12 @@ var ImportExportComponent = class ImportExportComponent {
10095
10308
  if (new Set(candidates).size === 1) this.columnMapping[field.key] = candidates[0];
10096
10309
  }
10097
10310
  }
10311
+ static {
10312
+ this.nextId = 0;
10313
+ }
10314
+ exampleId(field) {
10315
+ return this.idPrefix + field.key;
10316
+ }
10098
10317
  get canSubmit() {
10099
10318
  return (this.config.importFields ?? []).filter((f) => f.required).every((f) => !!this.columnMapping[f.key]);
10100
10319
  }
@@ -10382,10 +10601,12 @@ var ImportExportComponent = class ImportExportComponent {
10382
10601
  }
10383
10602
  {{ field.label }}
10384
10603
  @if (field.required) { <span class="ie-required" aria-hidden="true">*</span> }
10604
+ @if (field.example) { <ui-hint class="ie-field-example" [attr.id]="exampleId(field)">e.g. {{ field.example }}</ui-hint> }
10385
10605
  </span>
10386
10606
  <div role="cell">
10387
10607
  <ui-select
10388
10608
  [ariaLabel]="field.label + ' column' + (field.required ? ', required' : '')"
10609
+ [ariaDescribedBy]="field.example ? exampleId(field) : ''"
10389
10610
  [options]="csvHeaderOptions"
10390
10611
  [(ngModel)]="columnMapping[field.key]"
10391
10612
  [error]="field.required && !columnMapping[field.key] ? 'Required' : ''" />
@@ -10539,7 +10760,7 @@ var ImportExportComponent = class ImportExportComponent {
10539
10760
  </ui-modal>
10540
10761
  `,
10541
10762
  isInline: true,
10542
- styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#64748b;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step:not(:last-child){flex:1 1 auto}.ie-step:not(:last-child):after{content:\"\";flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;opacity:0;overflow:hidden;cursor:pointer}.ie-dropzone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #7c8ba1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone:focus-within{outline:2px solid #3b82f6;outline-offset:2px}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#64748b}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ie-result:focus,.ie-source-step:focus,.ie-upload-area:focus,.ie-mapping:focus,.ie-preview:focus{outline:none}.ie-result-list{list-style:none;margin:0;padding:0}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-progress{margin-top:14px}.ie-progress-track{height:6px;border-radius:999px;background:#e2e8f0;overflow:hidden;position:relative}.ie-progress-bar{position:absolute;inset:0 auto 0 0;width:35%;border-radius:999px;background:#2563eb;animation:ie-progress-slide 1.2s ease-in-out infinite}.ie-progress-text{margin:8px 0 0;font-size:.8125rem;color:#475569}@keyframes ie-progress-slide{0%{left:-35%}to{left:100%}}@media(prefers-reduced-motion:reduce){.ie-progress-bar{animation:none;width:100%;opacity:.5}}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"],
10763
+ styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#64748b;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step:not(:last-child){flex:1 1 auto}.ie-step:not(:last-child):after{content:\"\";flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;opacity:0;overflow:hidden;cursor:pointer}.ie-dropzone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #7c8ba1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone:focus-within{outline:2px solid #3b82f6;outline-offset:2px}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#64748b}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;flex-wrap:wrap;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-field-example{flex-basis:100%;font-weight:400}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ie-result:focus,.ie-source-step:focus,.ie-upload-area:focus,.ie-mapping:focus,.ie-preview:focus{outline:none}.ie-result-list{list-style:none;margin:0;padding:0}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-progress{margin-top:14px}.ie-progress-track{height:6px;border-radius:999px;background:#e2e8f0;overflow:hidden;position:relative}.ie-progress-bar{position:absolute;inset:0 auto 0 0;width:35%;border-radius:999px;background:#2563eb;animation:ie-progress-slide 1.2s ease-in-out infinite}.ie-progress-text{margin:8px 0 0;font-size:.8125rem;color:#475569}@keyframes ie-progress-slide{0%{left:-35%}to{left:100%}}@media(prefers-reduced-motion:reduce){.ie-progress-bar{animation:none;width:100%;opacity:.5}}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"],
10543
10764
  dependencies: [
10544
10765
  {
10545
10766
  kind: "ngmodule",
@@ -10622,6 +10843,7 @@ var ImportExportComponent = class ImportExportComponent {
10622
10843
  inputs: [
10623
10844
  "label",
10624
10845
  "ariaLabel",
10846
+ "labelHidden",
10625
10847
  "inputName",
10626
10848
  "placeholder",
10627
10849
  "options",
@@ -10649,6 +10871,11 @@ var ImportExportComponent = class ImportExportComponent {
10649
10871
  "ariaLabel"
10650
10872
  ],
10651
10873
  outputs: ["sourceSelect"]
10874
+ },
10875
+ {
10876
+ kind: "component",
10877
+ type: HintComponent,
10878
+ selector: "ui-hint"
10652
10879
  }
10653
10880
  ],
10654
10881
  changeDetection: i0.ChangeDetectionStrategy.OnPush
@@ -10671,7 +10898,8 @@ i0.ɵɵngDeclareClassMetadata({
10671
10898
  ModalComponent,
10672
10899
  ButtonComponent,
10673
10900
  SelectComponent,
10674
- ImportSourceGridComponent
10901
+ ImportSourceGridComponent,
10902
+ HintComponent
10675
10903
  ],
10676
10904
  template: `
10677
10905
  <!-- Trigger buttons -->
@@ -10757,10 +10985,12 @@ i0.ɵɵngDeclareClassMetadata({
10757
10985
  }
10758
10986
  {{ field.label }}
10759
10987
  @if (field.required) { <span class="ie-required" aria-hidden="true">*</span> }
10988
+ @if (field.example) { <ui-hint class="ie-field-example" [attr.id]="exampleId(field)">e.g. {{ field.example }}</ui-hint> }
10760
10989
  </span>
10761
10990
  <div role="cell">
10762
10991
  <ui-select
10763
10992
  [ariaLabel]="field.label + ' column' + (field.required ? ', required' : '')"
10993
+ [ariaDescribedBy]="field.example ? exampleId(field) : ''"
10764
10994
  [options]="csvHeaderOptions"
10765
10995
  [(ngModel)]="columnMapping[field.key]"
10766
10996
  [error]="field.required && !columnMapping[field.key] ? 'Required' : ''" />
@@ -10913,7 +11143,7 @@ i0.ɵɵngDeclareClassMetadata({
10913
11143
 
10914
11144
  </ui-modal>
10915
11145
  `,
10916
- styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#64748b;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step:not(:last-child){flex:1 1 auto}.ie-step:not(:last-child):after{content:\"\";flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;opacity:0;overflow:hidden;cursor:pointer}.ie-dropzone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #7c8ba1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone:focus-within{outline:2px solid #3b82f6;outline-offset:2px}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#64748b}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ie-result:focus,.ie-source-step:focus,.ie-upload-area:focus,.ie-mapping:focus,.ie-preview:focus{outline:none}.ie-result-list{list-style:none;margin:0;padding:0}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-progress{margin-top:14px}.ie-progress-track{height:6px;border-radius:999px;background:#e2e8f0;overflow:hidden;position:relative}.ie-progress-bar{position:absolute;inset:0 auto 0 0;width:35%;border-radius:999px;background:#2563eb;animation:ie-progress-slide 1.2s ease-in-out infinite}.ie-progress-text{margin:8px 0 0;font-size:.8125rem;color:#475569}@keyframes ie-progress-slide{0%{left:-35%}to{left:100%}}@media(prefers-reduced-motion:reduce){.ie-progress-bar{animation:none;width:100%;opacity:.5}}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"]
11146
+ styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#64748b;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step:not(:last-child){flex:1 1 auto}.ie-step:not(:last-child):after{content:\"\";flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;opacity:0;overflow:hidden;cursor:pointer}.ie-dropzone{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #7c8ba1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone:focus-within{outline:2px solid #3b82f6;outline-offset:2px}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#64748b}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;flex-wrap:wrap;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-field-example{flex-basis:100%;font-weight:400}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ie-result:focus,.ie-source-step:focus,.ie-upload-area:focus,.ie-mapping:focus,.ie-preview:focus{outline:none}.ie-result-list{list-style:none;margin:0;padding:0}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-progress{margin-top:14px}.ie-progress-track{height:6px;border-radius:999px;background:#e2e8f0;overflow:hidden;position:relative}.ie-progress-bar{position:absolute;inset:0 auto 0 0;width:35%;border-radius:999px;background:#2563eb;animation:ie-progress-slide 1.2s ease-in-out infinite}.ie-progress-text{margin:8px 0 0;font-size:.8125rem;color:#475569}@keyframes ie-progress-slide{0%{left:-35%}to{left:100%}}@media(prefers-reduced-motion:reduce){.ie-progress-bar{animation:none;width:100%;opacity:.5}}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"]
10917
11147
  }]
10918
11148
  }],
10919
11149
  ctorParameters: () => [],
@@ -10984,73 +11214,6 @@ i0.ɵɵngDeclareClassMetadata({
10984
11214
  }]
10985
11215
  }
10986
11216
  });
10987
- var ConfirmService = class ConfirmService {
10988
- constructor() {
10989
- this._open = signal(false, ...ngDevMode ? [{ debugName: "_open" }] : /* istanbul ignore next */ []);
10990
- this._active = signal(null, ...ngDevMode ? [{ debugName: "_active" }] : /* istanbul ignore next */ []);
10991
- this._resolve = null;
10992
- this.open = this._open.asReadonly();
10993
- this.active = this._active.asReadonly();
10994
- this._outlets = signal([], ...ngDevMode ? [{ debugName: "_outlets" }] : /* istanbul ignore next */ []);
10995
- this.primaryOutlet = computed(() => this._outlets()[0] ?? null, ...ngDevMode ? [{ debugName: "primaryOutlet" }] : /* istanbul ignore next */ []);
10996
- }
10997
- registerOutlet(outlet) {
10998
- this._outlets.update((list) => [...list, outlet]);
10999
- }
11000
- unregisterOutlet(outlet) {
11001
- this._outlets.update((list) => list.filter((o) => o !== outlet));
11002
- }
11003
- confirm(config) {
11004
- return new Promise((resolve) => {
11005
- this._resolve = resolve;
11006
- this._active.set({
11007
- title: config.title,
11008
- message: config.message,
11009
- confirmLabel: config.confirmLabel ?? "Confirm",
11010
- cancelLabel: config.cancelLabel ?? "Cancel",
11011
- variant: config.variant ?? "danger",
11012
- details: config.details ?? []
11013
- });
11014
- this._open.set(true);
11015
- });
11016
- }
11017
- dismiss(confirmed) {
11018
- this._open.set(false);
11019
- const res = this._resolve;
11020
- this._resolve = null;
11021
- this._active.set(null);
11022
- res?.(confirmed);
11023
- }
11024
- static {
11025
- this.ɵfac = i0.ɵɵngDeclareFactory({
11026
- minVersion: "12.0.0",
11027
- version: "22.2.2",
11028
- ngImport: i0,
11029
- type: ConfirmService,
11030
- deps: [],
11031
- target: i0.ɵɵFactoryTarget.Injectable
11032
- });
11033
- }
11034
- static {
11035
- this.ɵprov = i0.ɵɵngDeclareInjectable({
11036
- minVersion: "12.0.0",
11037
- version: "22.2.2",
11038
- ngImport: i0,
11039
- type: ConfirmService,
11040
- providedIn: "root"
11041
- });
11042
- }
11043
- };
11044
- i0.ɵɵngDeclareClassMetadata({
11045
- minVersion: "12.0.0",
11046
- version: "22.2.2",
11047
- ngImport: i0,
11048
- type: ConfirmService,
11049
- decorators: [{
11050
- type: Injectable,
11051
- args: [{ providedIn: "root" }]
11052
- }]
11053
- });
11054
11217
  var ConfirmOutletComponent = class ConfirmOutletComponent {
11055
11218
  constructor() {
11056
11219
  this.svc = inject(ConfirmService);
@@ -11088,6 +11251,7 @@ var ConfirmOutletComponent = class ConfirmOutletComponent {
11088
11251
  @if (_isPrimary() && svc.active()) {
11089
11252
  <ui-modal
11090
11253
  data-testid="confirm-modal"
11254
+ dialogTestId="confirm-dialog"
11091
11255
  [open]="svc.open()"
11092
11256
  [title]="svc.active()!.title"
11093
11257
  maxWidth="420px"
@@ -11186,6 +11350,7 @@ i0.ɵɵngDeclareClassMetadata({
11186
11350
  @if (_isPrimary() && svc.active()) {
11187
11351
  <ui-modal
11188
11352
  data-testid="confirm-modal"
11353
+ dialogTestId="confirm-dialog"
11189
11354
  [open]="svc.open()"
11190
11355
  [title]="svc.active()!.title"
11191
11356
  maxWidth="420px"
@@ -11215,6 +11380,107 @@ i0.ɵɵngDeclareClassMetadata({
11215
11380
  }]
11216
11381
  }]
11217
11382
  });
11383
+ var ConfirmService = class ConfirmService {
11384
+ constructor() {
11385
+ this._appRef = inject(ApplicationRef);
11386
+ this._envInjector = inject(EnvironmentInjector);
11387
+ this._doc = inject(DOCUMENT);
11388
+ this._browser = isPlatformBrowser(inject(PLATFORM_ID));
11389
+ this._open = signal(false, ...ngDevMode ? [{ debugName: "_open" }] : /* istanbul ignore next */ []);
11390
+ this._active = signal(null, ...ngDevMode ? [{ debugName: "_active" }] : /* istanbul ignore next */ []);
11391
+ this._resolve = null;
11392
+ this.open = this._open.asReadonly();
11393
+ this.active = this._active.asReadonly();
11394
+ this._outlets = signal([], ...ngDevMode ? [{ debugName: "_outlets" }] : /* istanbul ignore next */ []);
11395
+ this.primaryOutlet = computed(() => this._outlets()[0] ?? null, ...ngDevMode ? [{ debugName: "primaryOutlet" }] : /* istanbul ignore next */ []);
11396
+ this._auto = null;
11397
+ this._retireAutoOnDismiss = false;
11398
+ }
11399
+ registerOutlet(outlet) {
11400
+ this._outlets.update((list) => [...list, outlet]);
11401
+ if (this._auto && outlet !== this._auto.instance) {
11402
+ if (this._open()) this._retireAutoOnDismiss = true;
11403
+ else this._destroyAuto();
11404
+ }
11405
+ }
11406
+ unregisterOutlet(outlet) {
11407
+ this._outlets.update((list) => list.filter((o) => o !== outlet));
11408
+ }
11409
+ ngOnDestroy() {
11410
+ this._destroyAuto();
11411
+ }
11412
+ _ensureOutlet() {
11413
+ if (this._outlets().length > 0) return;
11414
+ if (!this._browser) return;
11415
+ const body = this._doc.body;
11416
+ const ref = createComponent(ConfirmOutletComponent, { environmentInjector: this._envInjector });
11417
+ this._appRef.attachView(ref.hostView);
11418
+ body.appendChild(ref.location.nativeElement);
11419
+ this._auto = ref;
11420
+ ref.changeDetectorRef.detectChanges();
11421
+ }
11422
+ _destroyAuto() {
11423
+ const ref = this._auto;
11424
+ if (!ref) return;
11425
+ this._auto = null;
11426
+ this._retireAutoOnDismiss = false;
11427
+ const el = ref.location.nativeElement;
11428
+ ref.destroy();
11429
+ el.remove();
11430
+ }
11431
+ confirm(config) {
11432
+ return new Promise((resolve) => {
11433
+ this._resolve = resolve;
11434
+ this._active.set({
11435
+ title: config.title,
11436
+ message: config.message,
11437
+ confirmLabel: config.confirmLabel ?? "Confirm",
11438
+ cancelLabel: config.cancelLabel ?? "Cancel",
11439
+ variant: config.variant ?? "danger",
11440
+ details: config.details ?? []
11441
+ });
11442
+ this._open.set(true);
11443
+ this._ensureOutlet();
11444
+ });
11445
+ }
11446
+ dismiss(confirmed) {
11447
+ this._open.set(false);
11448
+ const res = this._resolve;
11449
+ this._resolve = null;
11450
+ this._active.set(null);
11451
+ res?.(confirmed);
11452
+ if (this._retireAutoOnDismiss) this._destroyAuto();
11453
+ }
11454
+ static {
11455
+ this.ɵfac = i0.ɵɵngDeclareFactory({
11456
+ minVersion: "12.0.0",
11457
+ version: "22.2.2",
11458
+ ngImport: i0,
11459
+ type: ConfirmService,
11460
+ deps: [],
11461
+ target: i0.ɵɵFactoryTarget.Injectable
11462
+ });
11463
+ }
11464
+ static {
11465
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
11466
+ minVersion: "12.0.0",
11467
+ version: "22.2.2",
11468
+ ngImport: i0,
11469
+ type: ConfirmService,
11470
+ providedIn: "root"
11471
+ });
11472
+ }
11473
+ };
11474
+ i0.ɵɵngDeclareClassMetadata({
11475
+ minVersion: "12.0.0",
11476
+ version: "22.2.2",
11477
+ ngImport: i0,
11478
+ type: ConfirmService,
11479
+ decorators: [{
11480
+ type: Injectable,
11481
+ args: [{ providedIn: "root" }]
11482
+ }]
11483
+ });
11218
11484
  var EmptyStateComponent = class EmptyStateComponent {
11219
11485
  constructor() {
11220
11486
  this.message = input("", ...ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []);
@@ -11443,6 +11709,7 @@ i0.ɵɵngDeclareClassMetadata({
11443
11709
  });
11444
11710
  var ErrorStateComponent = class ErrorStateComponent {
11445
11711
  constructor() {
11712
+ this.title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
11446
11713
  this.message = input("", ...ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []);
11447
11714
  this.retryLabel = input("Try again", ...ngDevMode ? [{ debugName: "retryLabel" }] : /* istanbul ignore next */ []);
11448
11715
  this.retrying = input(false, ...ngDevMode ? [{ debugName: "retrying" }] : /* istanbul ignore next */ []);
@@ -11466,6 +11733,13 @@ var ErrorStateComponent = class ErrorStateComponent {
11466
11733
  isStandalone: true,
11467
11734
  selector: "ui-error-state",
11468
11735
  inputs: {
11736
+ title: {
11737
+ classPropertyName: "title",
11738
+ publicName: "title",
11739
+ isSignal: true,
11740
+ isRequired: false,
11741
+ transformFunction: null
11742
+ },
11469
11743
  message: {
11470
11744
  classPropertyName: "message",
11471
11745
  publicName: "message",
@@ -11499,6 +11773,9 @@ var ErrorStateComponent = class ErrorStateComponent {
11499
11773
  <line x1="12" y1="16" x2="12.01" y2="16" stroke-width="2.5"/>
11500
11774
  </svg>
11501
11775
  </div>
11776
+ @if (title()) {
11777
+ <p class="es-title">{{ title() }}</p>
11778
+ }
11502
11779
  <p class="es-message">{{ message() || 'Something went wrong. Please try again.' }}</p>
11503
11780
  @if (retryLabel()) {
11504
11781
  <ui-button variant="secondary" size="sm" [loading]="retrying()" (click)="retry.emit()">
@@ -11508,7 +11785,7 @@ var ErrorStateComponent = class ErrorStateComponent {
11508
11785
  </div>
11509
11786
  `,
11510
11787
  isInline: true,
11511
- styles: [":host{display:flex;flex:1}.es-wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px;text-align:center;flex:1;min-height:160px}.es-icon{width:56px;height:56px;border-radius:50%;background:#fee2e2;color:#ef4444;display:flex;align-items:center;justify-content:center;flex-shrink:0}.es-message{margin:0;font-size:.875rem;color:#64748b;max-width:360px;line-height:1.5}\n"],
11788
+ styles: [":host{display:flex;flex:1}.es-wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px;text-align:center;flex:1;min-height:160px}.es-icon{width:56px;height:56px;border-radius:50%;background:#fee2e2;color:#ef4444;display:flex;align-items:center;justify-content:center;flex-shrink:0}.es-title{margin:0;font-size:1rem;font-weight:600;color:#1e293b;line-height:1.4}.es-message{margin:0;font-size:.875rem;color:#64748b;max-width:360px;line-height:1.5}\n"],
11512
11789
  dependencies: [{
11513
11790
  kind: "component",
11514
11791
  type: ButtonComponent,
@@ -11564,6 +11841,9 @@ i0.ɵɵngDeclareClassMetadata({
11564
11841
  <line x1="12" y1="16" x2="12.01" y2="16" stroke-width="2.5"/>
11565
11842
  </svg>
11566
11843
  </div>
11844
+ @if (title()) {
11845
+ <p class="es-title">{{ title() }}</p>
11846
+ }
11567
11847
  <p class="es-message">{{ message() || 'Something went wrong. Please try again.' }}</p>
11568
11848
  @if (retryLabel()) {
11569
11849
  <ui-button variant="secondary" size="sm" [loading]="retrying()" (click)="retry.emit()">
@@ -11572,10 +11852,18 @@ i0.ɵɵngDeclareClassMetadata({
11572
11852
  }
11573
11853
  </div>
11574
11854
  `,
11575
- styles: [":host{display:flex;flex:1}.es-wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px;text-align:center;flex:1;min-height:160px}.es-icon{width:56px;height:56px;border-radius:50%;background:#fee2e2;color:#ef4444;display:flex;align-items:center;justify-content:center;flex-shrink:0}.es-message{margin:0;font-size:.875rem;color:#64748b;max-width:360px;line-height:1.5}\n"]
11855
+ styles: [":host{display:flex;flex:1}.es-wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px;text-align:center;flex:1;min-height:160px}.es-icon{width:56px;height:56px;border-radius:50%;background:#fee2e2;color:#ef4444;display:flex;align-items:center;justify-content:center;flex-shrink:0}.es-title{margin:0;font-size:1rem;font-weight:600;color:#1e293b;line-height:1.4}.es-message{margin:0;font-size:.875rem;color:#64748b;max-width:360px;line-height:1.5}\n"]
11576
11856
  }]
11577
11857
  }],
11578
11858
  propDecorators: {
11859
+ title: [{
11860
+ type: i0.Input,
11861
+ args: [{
11862
+ isSignal: true,
11863
+ alias: "title",
11864
+ required: false
11865
+ }]
11866
+ }],
11579
11867
  message: [{
11580
11868
  type: i0.Input,
11581
11869
  args: [{
@@ -12284,6 +12572,7 @@ var DataTableComponent = class DataTableComponent {
12284
12572
  this.tabChange = output();
12285
12573
  this.bulkAction = output();
12286
12574
  this.bulkPanelClick = output();
12575
+ this.loaded = output();
12287
12576
  this.rowDeleted = output();
12288
12577
  this.reorderable = input(false, ...ngDevMode ? [{ debugName: "reorderable" }] : /* istanbul ignore next */ []);
12289
12578
  this.rowReorder = output();
@@ -12312,7 +12601,7 @@ var DataTableComponent = class DataTableComponent {
12312
12601
  const active = this._activeTab();
12313
12602
  const keys = Object.keys(counts).length > 0 && active && !present.includes(active) ? [...present, active] : present;
12314
12603
  if (!keys.length) return [];
12315
- const toLabel = (s) => this._columnBadgeLabel(s) ?? (/[a-z]/.test(s) ? s : s.toLowerCase()).replace(/([a-z])([A-Z])/g, "$1 $2").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
12604
+ const toLabel = (s) => this._columnBadgeLabel(s) ?? (/[a-z]/.test(s) ? s : s.toLowerCase()).replace(/([a-z])([A-Z])/g, "$1 $2").replace(/-/g, " ").replace(/(^|\s)\p{L}/gu, (c) => c.toUpperCase());
12316
12605
  const singleValue = keys.length === 1;
12317
12606
  return [{
12318
12607
  value: "",
@@ -12653,6 +12942,10 @@ var DataTableComponent = class DataTableComponent {
12653
12942
  }
12654
12943
  this._loading.set(false);
12655
12944
  this._searchLoading.set(false);
12945
+ this.loaded.emit({
12946
+ ok: response !== null,
12947
+ total: this._total()
12948
+ });
12656
12949
  });
12657
12950
  }
12658
12951
  _countParams() {
@@ -13431,6 +13724,7 @@ var DataTableComponent = class DataTableComponent {
13431
13724
  tabChange: "tabChange",
13432
13725
  bulkAction: "bulkAction",
13433
13726
  bulkPanelClick: "bulkPanelClick",
13727
+ loaded: "loaded",
13434
13728
  rowDeleted: "rowDeleted",
13435
13729
  rowReorder: "rowReorder"
13436
13730
  },
@@ -13812,7 +14106,8 @@ var DataTableComponent = class DataTableComponent {
13812
14106
  <span class="dt-tags">
13813
14107
  <ui-badge
13814
14108
  [label]="tags[0].name"
13815
- [variant]="tags[0].variant ?? null" />
14109
+ [variant]="tags[0].variant ?? null"
14110
+ [color]="tags[0].color ?? null" />
13816
14111
  @if (tags.length > 1) {
13817
14112
  <span
13818
14113
  class="dt-tags-more"
@@ -14125,7 +14420,7 @@ var DataTableComponent = class DataTableComponent {
14125
14420
  [style.left.px]="_tagTooltip()!.x"
14126
14421
  [style.top.px]="_tagTooltip()!.y">
14127
14422
  @for (tag of _tagTooltip()!.tags; track tag.name) {
14128
- <ui-badge [label]="tag.name" [variant]="tag.variant ?? 'gray'" />
14423
+ <ui-badge [label]="tag.name" [variant]="tag.variant ?? 'gray'" [color]="tag.color ?? null" />
14129
14424
  }
14130
14425
  </div>
14131
14426
  }
@@ -14261,7 +14556,11 @@ var DataTableComponent = class DataTableComponent {
14261
14556
  kind: "component",
14262
14557
  type: BadgeComponent,
14263
14558
  selector: "ui-badge",
14264
- inputs: ["label", "variant"]
14559
+ inputs: [
14560
+ "label",
14561
+ "variant",
14562
+ "color"
14563
+ ]
14265
14564
  },
14266
14565
  {
14267
14566
  kind: "component",
@@ -14393,6 +14692,7 @@ var DataTableComponent = class DataTableComponent {
14393
14692
  inputs: [
14394
14693
  "label",
14395
14694
  "ariaLabel",
14695
+ "labelHidden",
14396
14696
  "inputName",
14397
14697
  "placeholder",
14398
14698
  "options",
@@ -14478,6 +14778,7 @@ var DataTableComponent = class DataTableComponent {
14478
14778
  type: ErrorStateComponent,
14479
14779
  selector: "ui-error-state",
14480
14780
  inputs: [
14781
+ "title",
14481
14782
  "message",
14482
14783
  "retryLabel",
14483
14784
  "retrying"
@@ -14900,7 +15201,8 @@ i0.ɵɵngDeclareClassMetadata({
14900
15201
  <span class="dt-tags">
14901
15202
  <ui-badge
14902
15203
  [label]="tags[0].name"
14903
- [variant]="tags[0].variant ?? null" />
15204
+ [variant]="tags[0].variant ?? null"
15205
+ [color]="tags[0].color ?? null" />
14904
15206
  @if (tags.length > 1) {
14905
15207
  <span
14906
15208
  class="dt-tags-more"
@@ -15213,7 +15515,7 @@ i0.ɵɵngDeclareClassMetadata({
15213
15515
  [style.left.px]="_tagTooltip()!.x"
15214
15516
  [style.top.px]="_tagTooltip()!.y">
15215
15517
  @for (tag of _tagTooltip()!.tags; track tag.name) {
15216
- <ui-badge [label]="tag.name" [variant]="tag.variant ?? 'gray'" />
15518
+ <ui-badge [label]="tag.name" [variant]="tag.variant ?? 'gray'" [color]="tag.color ?? null" />
15217
15519
  }
15218
15520
  </div>
15219
15521
  }
@@ -15512,6 +15814,10 @@ i0.ɵɵngDeclareClassMetadata({
15512
15814
  type: i0.Output,
15513
15815
  args: ["bulkPanelClick"]
15514
15816
  }],
15817
+ loaded: [{
15818
+ type: i0.Output,
15819
+ args: ["loaded"]
15820
+ }],
15515
15821
  rowDeleted: [{
15516
15822
  type: i0.Output,
15517
15823
  args: ["rowDeleted"]
@@ -15552,6 +15858,9 @@ var SidePanelComponent = class SidePanelComponent {
15552
15858
  this.closed = output();
15553
15859
  this.primaryClick = output();
15554
15860
  this.titleId = `sp-title-${Math.random().toString(36).slice(2, 8)}`;
15861
+ this.bodyScrollable = signal(false, ...ngDevMode ? [{ debugName: "bodyScrollable" }] : /* istanbul ignore next */ []);
15862
+ this._bodyRef = viewChild("spBody", ...ngDevMode ? [{ debugName: "_bodyRef" }] : /* istanbul ignore next */ []);
15863
+ this._bodyObservers = null;
15555
15864
  this._el = inject(ElementRef);
15556
15865
  this._doc = inject(DOCUMENT);
15557
15866
  this._overlays = inject(OverlayStack);
@@ -15561,6 +15870,10 @@ var SidePanelComponent = class SidePanelComponent {
15561
15870
  this._stopIframeKeys = null;
15562
15871
  this._interaction = inject(LastInteraction);
15563
15872
  this._interaction.acquire(this._doc);
15873
+ effect(() => {
15874
+ const body = this._bodyRef()?.nativeElement ?? null;
15875
+ untracked(() => this._watchBody(body));
15876
+ });
15564
15877
  effect(() => {
15565
15878
  if (this.open()) {
15566
15879
  this._overlays.push(this);
@@ -15588,6 +15901,41 @@ var SidePanelComponent = class SidePanelComponent {
15588
15901
  }
15589
15902
  });
15590
15903
  }
15904
+ refreshScrollable() {
15905
+ const el = this._bodyRef()?.nativeElement;
15906
+ this.bodyScrollable.set(!!el && el.scrollHeight - el.clientHeight > 1);
15907
+ }
15908
+ _watchBody(body) {
15909
+ this._stopWatchingBody();
15910
+ if (!body) {
15911
+ this.bodyScrollable.set(false);
15912
+ return;
15913
+ }
15914
+ this.refreshScrollable();
15915
+ const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => this.refreshScrollable());
15916
+ const mo = typeof MutationObserver === "undefined" ? null : new MutationObserver(() => {
15917
+ if (ro) for (const child of Array.from(body.children)) ro.observe(child);
15918
+ this.refreshScrollable();
15919
+ });
15920
+ if (ro) {
15921
+ ro.observe(body);
15922
+ for (const child of Array.from(body.children)) ro.observe(child);
15923
+ }
15924
+ mo?.observe(body, {
15925
+ childList: true,
15926
+ subtree: true,
15927
+ characterData: true
15928
+ });
15929
+ this._bodyObservers = {
15930
+ ro,
15931
+ mo
15932
+ };
15933
+ }
15934
+ _stopWatchingBody() {
15935
+ this._bodyObservers?.ro?.disconnect();
15936
+ this._bodyObservers?.mo?.disconnect();
15937
+ this._bodyObservers = null;
15938
+ }
15591
15939
  onKeydown(event) {
15592
15940
  if (!this.open() || !this._overlays.isTop(this)) return;
15593
15941
  if (event.key === "Escape") {
@@ -15627,6 +15975,7 @@ var SidePanelComponent = class SidePanelComponent {
15627
15975
  return tabbables(this._el.nativeElement);
15628
15976
  }
15629
15977
  ngOnDestroy() {
15978
+ this._stopWatchingBody();
15630
15979
  this._interaction.release();
15631
15980
  this._stopIframeKeys?.();
15632
15981
  this._stopIframeKeys = null;
@@ -15750,6 +16099,13 @@ var SidePanelComponent = class SidePanelComponent {
15750
16099
  primaryClick: "primaryClick"
15751
16100
  },
15752
16101
  host: { listeners: { "document:keydown": "onKeydown($event)" } },
16102
+ viewQueries: [{
16103
+ propertyName: "_bodyRef",
16104
+ first: true,
16105
+ predicate: ["spBody"],
16106
+ descendants: true,
16107
+ isSignal: true
16108
+ }],
15753
16109
  ngImport: i0,
15754
16110
  template: `
15755
16111
  @if (open()) {
@@ -15767,8 +16123,8 @@ var SidePanelComponent = class SidePanelComponent {
15767
16123
  <!-- Header -->
15768
16124
  <div class="sp-header">
15769
16125
  <div class="sp-header-text">
15770
- <h2 class="sp-title" [id]="titleId">{{ title() }}</h2>
15771
- @if (subtitle()) { <p class="sp-subtitle">{{ subtitle() }}</p> }
16126
+ <h2 class="sp-title" data-testid="side-panel-title" [id]="titleId">{{ title() }}</h2>
16127
+ @if (subtitle()) { <p class="sp-subtitle" data-testid="side-panel-subtitle">{{ subtitle() }}</p> }
15772
16128
  </div>
15773
16129
  <button class="sp-close" type="button" (click)="closed.emit()" aria-label="Dismiss panel">
15774
16130
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
@@ -15778,7 +16134,12 @@ var SidePanelComponent = class SidePanelComponent {
15778
16134
  </div>
15779
16135
 
15780
16136
  <!-- Body -->
15781
- <div class="sp-body">
16137
+ <div
16138
+ class="sp-body"
16139
+ #spBody
16140
+ [attr.tabindex]="bodyScrollable() ? 0 : null"
16141
+ [attr.role]="bodyScrollable() ? 'group' : null"
16142
+ [attr.aria-labelledby]="bodyScrollable() ? titleId : null">
15782
16143
  <ng-content />
15783
16144
  </div>
15784
16145
 
@@ -15821,7 +16182,7 @@ var SidePanelComponent = class SidePanelComponent {
15821
16182
  }
15822
16183
  `,
15823
16184
  isInline: true,
15824
- styles: [".sp-backdrop{position:fixed;inset:0;background:#0000004d;z-index:90;animation:sp-fade .2s ease}.sp-panel{position:fixed;top:0;right:0;bottom:var(--ui-kb, 0px);width:480px;max-width:100vw;max-height:100vh;max-height:var(--ui-vvh, 100dvh);background:#fff;z-index:100;box-shadow:-4px 0 20px #0000001a;display:flex;flex-direction:column;animation:sp-slide .25s ease}.sp-panel:focus{outline:none}.sp-focus-guard{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;outline:none}.sp-wide{width:620px}.sp-extra-wide{width:760px}.sp-header{display:flex;justify-content:space-between;align-items:center;padding:24px 24px 20px;gap:12px;flex-shrink:0;background:linear-gradient(135deg,#1e293b,#334155)}.sp-header-text{flex:1;min-width:0}.sp-title{font-size:1.125rem;font-weight:700;color:#fff;margin:0}.sp-subtitle{font-size:.8125rem;color:#94a3b8;margin:4px 0 0}.sp-close{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:36px;height:36px;border-radius:8px;border:1px solid rgba(255,255,255,.2);background:#ffffff1a;cursor:pointer;color:#cbd5e1;transition:background .15s,border-color .15s}.sp-close:hover{background:#fff3;border-color:#ffffff4d;color:#fff}.sp-close:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-body{padding:20px 24px 24px;flex:1;overflow-y:auto;overflow-x:hidden}.sp-footer{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:14px 24px calc(14px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#f8fafc}.sp-footer-extra{display:flex;align-items:center;justify-content:center;gap:8px;flex:1 1 auto;margin:0 8px;min-width:0}.sp-footer-extra:empty{display:none}.sp-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 18px;border-radius:7px;font-size:.875rem;font-weight:500;font-family:inherit;cursor:pointer;white-space:nowrap;transition:background .1s,border-color .1s,opacity .1s}.sp-btn:disabled{opacity:.5;cursor:default}.sp-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-btn-cancel{background:#fff;border:1px solid #e2e8f0;color:#475569}.sp-btn-cancel:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.sp-btn-primary{background:var(--ui-accent, #2563eb);border:1px solid var(--ui-accent, #2563eb);color:var(--ui-on-accent, #fff)}.sp-btn-primary:hover:not(:disabled){background:var(--ui-accent-hover, #1d4ed8);border-color:var(--ui-accent-hover, #1d4ed8)}.sp-btn-danger{background:#dc2626;border:1px solid #dc2626;color:#fff}.sp-btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.sp-btn-warning{background:#d97706;border:1px solid #d97706;color:#fff}.sp-btn-warning:hover:not(:disabled){background:#b45309;border-color:#b45309}.sp-spinner{display:inline-block;width:13px;height:13px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:sp-spin .55s linear infinite;flex-shrink:0}@media(max-width:768px){.sp-panel,.sp-wide,.sp-extra-wide{width:100vw}}@media(max-width:480px){.sp-panel,.sp-wide,.sp-extra-wide{inset:auto 0 0;width:100vw;max-height:90vh;max-height:min(90dvh,var(--ui-vvh, 100dvh));border-radius:16px 16px 0 0;box-shadow:0 -4px 24px #00000026;animation:sp-up .25s ease}.sp-header{padding:16px 16px 14px}.sp-body{padding:16px}.sp-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px))}}@media(pointer:coarse),(max-width:480px){.sp-close{position:relative}.sp-close:after{content:\"\";position:absolute;inset:-5px}.sp-btn{min-height:44px;justify-content:center}}@keyframes sp-slide{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes sp-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sp-fade{0%{opacity:0}to{opacity:1}}@keyframes sp-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.sp-backdrop,.sp-panel,.sp-wide,.sp-extra-wide{animation:none}.sp-spinner{animation-duration:2s}}\n"],
16185
+ styles: [".sp-backdrop{position:fixed;inset:0;background:#0000004d;z-index:90;animation:sp-fade .2s ease}.sp-panel{position:fixed;top:0;right:0;bottom:var(--ui-kb, 0px);width:480px;max-width:100vw;max-height:100vh;max-height:var(--ui-vvh, 100dvh);background:#fff;z-index:100;box-shadow:-4px 0 20px #0000001a;display:flex;flex-direction:column;animation:sp-slide .25s ease}.sp-panel:focus{outline:none}.sp-focus-guard{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;outline:none}.sp-wide{width:620px}.sp-extra-wide{width:760px}.sp-header{display:flex;justify-content:space-between;align-items:center;padding:24px 24px 20px;gap:12px;flex-shrink:0;background:linear-gradient(135deg,#1e293b,#334155)}.sp-header-text{flex:1;min-width:0}.sp-title{font-size:1.125rem;font-weight:700;color:#fff;margin:0}.sp-subtitle{font-size:.8125rem;color:#94a3b8;margin:4px 0 0}.sp-close{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:36px;height:36px;border-radius:8px;border:1px solid rgba(255,255,255,.2);background:#ffffff1a;cursor:pointer;color:#cbd5e1;transition:background .15s,border-color .15s}.sp-close:hover{background:#fff3;border-color:#ffffff4d;color:#fff}.sp-close:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-body{padding:20px 24px 24px;flex:1;overflow-y:auto;overflow-x:hidden}.sp-body:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.sp-footer{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:14px 24px calc(14px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#f8fafc}.sp-footer-extra{display:flex;align-items:center;justify-content:center;gap:8px;flex:1 1 auto;margin:0 8px;min-width:0}.sp-footer-extra:empty{display:none}.sp-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 18px;border-radius:7px;font-size:.875rem;font-weight:500;font-family:inherit;cursor:pointer;white-space:nowrap;transition:background .1s,border-color .1s,opacity .1s}.sp-btn:disabled{opacity:.5;cursor:default}.sp-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-btn-cancel{background:#fff;border:1px solid #e2e8f0;color:#475569}.sp-btn-cancel:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.sp-btn-primary{background:var(--ui-accent, #2563eb);border:1px solid var(--ui-accent, #2563eb);color:var(--ui-on-accent, #fff)}.sp-btn-primary:hover:not(:disabled){background:var(--ui-accent-hover, #1d4ed8);border-color:var(--ui-accent-hover, #1d4ed8)}.sp-btn-danger{background:#dc2626;border:1px solid #dc2626;color:#fff}.sp-btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.sp-btn-warning{background:#d97706;border:1px solid #d97706;color:#fff}.sp-btn-warning:hover:not(:disabled){background:#b45309;border-color:#b45309}.sp-spinner{display:inline-block;width:13px;height:13px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:sp-spin .55s linear infinite;flex-shrink:0}@media(max-width:768px){.sp-panel,.sp-wide,.sp-extra-wide{width:100vw}}@media(max-width:480px){.sp-panel,.sp-wide,.sp-extra-wide{inset:auto 0 0;width:100vw;max-height:90vh;max-height:min(90dvh,var(--ui-vvh, 100dvh));border-radius:16px 16px 0 0;box-shadow:0 -4px 24px #00000026;animation:sp-up .25s ease}.sp-header{padding:16px 16px 14px}.sp-body{padding:16px}.sp-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px))}}@media(pointer:coarse),(max-width:480px){.sp-close{position:relative}.sp-close:after{content:\"\";position:absolute;inset:-5px}.sp-btn{min-height:44px;justify-content:center}}@keyframes sp-slide{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes sp-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sp-fade{0%{opacity:0}to{opacity:1}}@keyframes sp-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.sp-backdrop,.sp-panel,.sp-wide,.sp-extra-wide{animation:none}.sp-spinner{animation-duration:2s}}\n"],
15825
16186
  changeDetection: i0.ChangeDetectionStrategy.OnPush
15826
16187
  });
15827
16188
  }
@@ -15854,8 +16215,8 @@ i0.ɵɵngDeclareClassMetadata({
15854
16215
  <!-- Header -->
15855
16216
  <div class="sp-header">
15856
16217
  <div class="sp-header-text">
15857
- <h2 class="sp-title" [id]="titleId">{{ title() }}</h2>
15858
- @if (subtitle()) { <p class="sp-subtitle">{{ subtitle() }}</p> }
16218
+ <h2 class="sp-title" data-testid="side-panel-title" [id]="titleId">{{ title() }}</h2>
16219
+ @if (subtitle()) { <p class="sp-subtitle" data-testid="side-panel-subtitle">{{ subtitle() }}</p> }
15859
16220
  </div>
15860
16221
  <button class="sp-close" type="button" (click)="closed.emit()" aria-label="Dismiss panel">
15861
16222
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
@@ -15865,7 +16226,12 @@ i0.ɵɵngDeclareClassMetadata({
15865
16226
  </div>
15866
16227
 
15867
16228
  <!-- Body -->
15868
- <div class="sp-body">
16229
+ <div
16230
+ class="sp-body"
16231
+ #spBody
16232
+ [attr.tabindex]="bodyScrollable() ? 0 : null"
16233
+ [attr.role]="bodyScrollable() ? 'group' : null"
16234
+ [attr.aria-labelledby]="bodyScrollable() ? titleId : null">
15869
16235
  <ng-content />
15870
16236
  </div>
15871
16237
 
@@ -15907,7 +16273,7 @@ i0.ɵɵngDeclareClassMetadata({
15907
16273
  </div>
15908
16274
  }
15909
16275
  `,
15910
- styles: [".sp-backdrop{position:fixed;inset:0;background:#0000004d;z-index:90;animation:sp-fade .2s ease}.sp-panel{position:fixed;top:0;right:0;bottom:var(--ui-kb, 0px);width:480px;max-width:100vw;max-height:100vh;max-height:var(--ui-vvh, 100dvh);background:#fff;z-index:100;box-shadow:-4px 0 20px #0000001a;display:flex;flex-direction:column;animation:sp-slide .25s ease}.sp-panel:focus{outline:none}.sp-focus-guard{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;outline:none}.sp-wide{width:620px}.sp-extra-wide{width:760px}.sp-header{display:flex;justify-content:space-between;align-items:center;padding:24px 24px 20px;gap:12px;flex-shrink:0;background:linear-gradient(135deg,#1e293b,#334155)}.sp-header-text{flex:1;min-width:0}.sp-title{font-size:1.125rem;font-weight:700;color:#fff;margin:0}.sp-subtitle{font-size:.8125rem;color:#94a3b8;margin:4px 0 0}.sp-close{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:36px;height:36px;border-radius:8px;border:1px solid rgba(255,255,255,.2);background:#ffffff1a;cursor:pointer;color:#cbd5e1;transition:background .15s,border-color .15s}.sp-close:hover{background:#fff3;border-color:#ffffff4d;color:#fff}.sp-close:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-body{padding:20px 24px 24px;flex:1;overflow-y:auto;overflow-x:hidden}.sp-footer{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:14px 24px calc(14px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#f8fafc}.sp-footer-extra{display:flex;align-items:center;justify-content:center;gap:8px;flex:1 1 auto;margin:0 8px;min-width:0}.sp-footer-extra:empty{display:none}.sp-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 18px;border-radius:7px;font-size:.875rem;font-weight:500;font-family:inherit;cursor:pointer;white-space:nowrap;transition:background .1s,border-color .1s,opacity .1s}.sp-btn:disabled{opacity:.5;cursor:default}.sp-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-btn-cancel{background:#fff;border:1px solid #e2e8f0;color:#475569}.sp-btn-cancel:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.sp-btn-primary{background:var(--ui-accent, #2563eb);border:1px solid var(--ui-accent, #2563eb);color:var(--ui-on-accent, #fff)}.sp-btn-primary:hover:not(:disabled){background:var(--ui-accent-hover, #1d4ed8);border-color:var(--ui-accent-hover, #1d4ed8)}.sp-btn-danger{background:#dc2626;border:1px solid #dc2626;color:#fff}.sp-btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.sp-btn-warning{background:#d97706;border:1px solid #d97706;color:#fff}.sp-btn-warning:hover:not(:disabled){background:#b45309;border-color:#b45309}.sp-spinner{display:inline-block;width:13px;height:13px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:sp-spin .55s linear infinite;flex-shrink:0}@media(max-width:768px){.sp-panel,.sp-wide,.sp-extra-wide{width:100vw}}@media(max-width:480px){.sp-panel,.sp-wide,.sp-extra-wide{inset:auto 0 0;width:100vw;max-height:90vh;max-height:min(90dvh,var(--ui-vvh, 100dvh));border-radius:16px 16px 0 0;box-shadow:0 -4px 24px #00000026;animation:sp-up .25s ease}.sp-header{padding:16px 16px 14px}.sp-body{padding:16px}.sp-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px))}}@media(pointer:coarse),(max-width:480px){.sp-close{position:relative}.sp-close:after{content:\"\";position:absolute;inset:-5px}.sp-btn{min-height:44px;justify-content:center}}@keyframes sp-slide{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes sp-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sp-fade{0%{opacity:0}to{opacity:1}}@keyframes sp-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.sp-backdrop,.sp-panel,.sp-wide,.sp-extra-wide{animation:none}.sp-spinner{animation-duration:2s}}\n"]
16276
+ styles: [".sp-backdrop{position:fixed;inset:0;background:#0000004d;z-index:90;animation:sp-fade .2s ease}.sp-panel{position:fixed;top:0;right:0;bottom:var(--ui-kb, 0px);width:480px;max-width:100vw;max-height:100vh;max-height:var(--ui-vvh, 100dvh);background:#fff;z-index:100;box-shadow:-4px 0 20px #0000001a;display:flex;flex-direction:column;animation:sp-slide .25s ease}.sp-panel:focus{outline:none}.sp-focus-guard{position:absolute;width:1px;height:1px;padding:0;margin:-1px;border:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;outline:none}.sp-wide{width:620px}.sp-extra-wide{width:760px}.sp-header{display:flex;justify-content:space-between;align-items:center;padding:24px 24px 20px;gap:12px;flex-shrink:0;background:linear-gradient(135deg,#1e293b,#334155)}.sp-header-text{flex:1;min-width:0}.sp-title{font-size:1.125rem;font-weight:700;color:#fff;margin:0}.sp-subtitle{font-size:.8125rem;color:#94a3b8;margin:4px 0 0}.sp-close{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:36px;height:36px;border-radius:8px;border:1px solid rgba(255,255,255,.2);background:#ffffff1a;cursor:pointer;color:#cbd5e1;transition:background .15s,border-color .15s}.sp-close:hover{background:#fff3;border-color:#ffffff4d;color:#fff}.sp-close:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-body{padding:20px 24px 24px;flex:1;overflow-y:auto;overflow-x:hidden}.sp-body:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.sp-footer{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:14px 24px calc(14px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#f8fafc}.sp-footer-extra{display:flex;align-items:center;justify-content:center;gap:8px;flex:1 1 auto;margin:0 8px;min-width:0}.sp-footer-extra:empty{display:none}.sp-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 18px;border-radius:7px;font-size:.875rem;font-weight:500;font-family:inherit;cursor:pointer;white-space:nowrap;transition:background .1s,border-color .1s,opacity .1s}.sp-btn:disabled{opacity:.5;cursor:default}.sp-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.sp-btn-cancel{background:#fff;border:1px solid #e2e8f0;color:#475569}.sp-btn-cancel:hover:not(:disabled){background:#f8fafc;border-color:#cbd5e1}.sp-btn-primary{background:var(--ui-accent, #2563eb);border:1px solid var(--ui-accent, #2563eb);color:var(--ui-on-accent, #fff)}.sp-btn-primary:hover:not(:disabled){background:var(--ui-accent-hover, #1d4ed8);border-color:var(--ui-accent-hover, #1d4ed8)}.sp-btn-danger{background:#dc2626;border:1px solid #dc2626;color:#fff}.sp-btn-danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c}.sp-btn-warning{background:#d97706;border:1px solid #d97706;color:#fff}.sp-btn-warning:hover:not(:disabled){background:#b45309;border-color:#b45309}.sp-spinner{display:inline-block;width:13px;height:13px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:sp-spin .55s linear infinite;flex-shrink:0}@media(max-width:768px){.sp-panel,.sp-wide,.sp-extra-wide{width:100vw}}@media(max-width:480px){.sp-panel,.sp-wide,.sp-extra-wide{inset:auto 0 0;width:100vw;max-height:90vh;max-height:min(90dvh,var(--ui-vvh, 100dvh));border-radius:16px 16px 0 0;box-shadow:0 -4px 24px #00000026;animation:sp-up .25s ease}.sp-header{padding:16px 16px 14px}.sp-body{padding:16px}.sp-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px))}}@media(pointer:coarse),(max-width:480px){.sp-close{position:relative}.sp-close:after{content:\"\";position:absolute;inset:-5px}.sp-btn{min-height:44px;justify-content:center}}@keyframes sp-slide{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes sp-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sp-fade{0%{opacity:0}to{opacity:1}}@keyframes sp-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.sp-backdrop,.sp-panel,.sp-wide,.sp-extra-wide{animation:none}.sp-spinner{animation-duration:2s}}\n"]
15911
16277
  }]
15912
16278
  }],
15913
16279
  ctorParameters: () => [],
@@ -16023,6 +16389,10 @@ i0.ɵɵngDeclareClassMetadata({
16023
16389
  primaryClick: [{
16024
16390
  type: i0.Output,
16025
16391
  args: ["primaryClick"]
16392
+ }],
16393
+ _bodyRef: [{
16394
+ type: i0.ViewChild,
16395
+ args: ["spBody", { isSignal: true }]
16026
16396
  }]
16027
16397
  }
16028
16398
  });
@@ -16680,6 +17050,7 @@ var ToggleComponent = class ToggleComponent {
16680
17050
  this.hint = input("", ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
16681
17051
  this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
16682
17052
  this.ariaDescribedBy = input("", ...ngDevMode ? [{ debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []);
17053
+ this.inputTestId = input("", ...ngDevMode ? [{ debugName: "inputTestId" }] : /* istanbul ignore next */ []);
16683
17054
  this.checked = model(false, ...ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []);
16684
17055
  this._disabledInput = input(false, {
16685
17056
  ...ngDevMode ? { debugName: "_disabledInput" } : /* istanbul ignore next */ {},
@@ -16769,6 +17140,13 @@ var ToggleComponent = class ToggleComponent {
16769
17140
  isRequired: false,
16770
17141
  transformFunction: null
16771
17142
  },
17143
+ inputTestId: {
17144
+ classPropertyName: "inputTestId",
17145
+ publicName: "inputTestId",
17146
+ isSignal: true,
17147
+ isRequired: false,
17148
+ transformFunction: null
17149
+ },
16772
17150
  checked: {
16773
17151
  classPropertyName: "checked",
16774
17152
  publicName: "checked",
@@ -16805,6 +17183,7 @@ var ToggleComponent = class ToggleComponent {
16805
17183
  role="switch"
16806
17184
  class="tg-input"
16807
17185
  [id]="_inputId"
17186
+ [attr.data-testid]="inputTestId() || null"
16808
17187
  [checked]="checked()"
16809
17188
  [disabled]="disabled()"
16810
17189
  [attr.aria-checked]="checked() ? 'true' : 'false'"
@@ -16853,6 +17232,7 @@ i0.ɵɵngDeclareClassMetadata({
16853
17232
  role="switch"
16854
17233
  class="tg-input"
16855
17234
  [id]="_inputId"
17235
+ [attr.data-testid]="inputTestId() || null"
16856
17236
  [checked]="checked()"
16857
17237
  [disabled]="disabled()"
16858
17238
  [attr.aria-checked]="checked() ? 'true' : 'false'"
@@ -16901,6 +17281,14 @@ i0.ɵɵngDeclareClassMetadata({
16901
17281
  required: false
16902
17282
  }]
16903
17283
  }],
17284
+ inputTestId: [{
17285
+ type: i0.Input,
17286
+ args: [{
17287
+ isSignal: true,
17288
+ alias: "inputTestId",
17289
+ required: false
17290
+ }]
17291
+ }],
16904
17292
  checked: [{
16905
17293
  type: i0.Input,
16906
17294
  args: [{
@@ -18006,6 +18394,7 @@ var BusinessHoursComponent = class BusinessHoursComponent {
18006
18394
  inputs: [
18007
18395
  "label",
18008
18396
  "ariaLabel",
18397
+ "labelHidden",
18009
18398
  "inputName",
18010
18399
  "placeholder",
18011
18400
  "options",
@@ -18208,6 +18597,7 @@ var RadioComponent = class RadioComponent {
18208
18597
  constructor() {
18209
18598
  this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
18210
18599
  this.description = input("", ...ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []);
18600
+ this.icon = input("", ...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
18211
18601
  this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
18212
18602
  this.testId = input("", ...ngDevMode ? [{ debugName: "testId" }] : /* istanbul ignore next */ []);
18213
18603
  this.value = input("", ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
@@ -18221,6 +18611,11 @@ var RadioComponent = class RadioComponent {
18221
18611
  alias: "disabled"
18222
18612
  });
18223
18613
  this.disabled = this._disabledInput;
18614
+ this._iconD = computed(() => {
18615
+ const v = this.icon().trim();
18616
+ if (!v) return null;
18617
+ return iconPath(v) ?? (/^[Mm][\d\s.,\-MmLlHhVvCcSsQqTtAaZz]+$/.test(v) ? v : null);
18618
+ }, ...ngDevMode ? [{ debugName: "_iconD" }] : /* istanbul ignore next */ []);
18224
18619
  this.labelId = input("", ...ngDevMode ? [{ debugName: "labelId" }] : /* istanbul ignore next */ []);
18225
18620
  this._generatedLabelId = `rd-${Math.random().toString(36).slice(2, 8)}-label`;
18226
18621
  this._labelId = computed(() => this.labelId() || this._generatedLabelId, ...ngDevMode ? [{ debugName: "_labelId" }] : /* istanbul ignore next */ []);
@@ -18266,6 +18661,13 @@ var RadioComponent = class RadioComponent {
18266
18661
  isRequired: false,
18267
18662
  transformFunction: null
18268
18663
  },
18664
+ icon: {
18665
+ classPropertyName: "icon",
18666
+ publicName: "icon",
18667
+ isSignal: true,
18668
+ isRequired: false,
18669
+ transformFunction: null
18670
+ },
18269
18671
  ariaLabel: {
18270
18672
  classPropertyName: "ariaLabel",
18271
18673
  publicName: "ariaLabel",
@@ -18359,6 +18761,10 @@ var RadioComponent = class RadioComponent {
18359
18761
  [attr.aria-controls]="controls() || null"
18360
18762
  (change)="onChange($event)"
18361
18763
  />
18764
+ @if (_iconD(); as d) {
18765
+ <!-- Optional icon in front of the label (library source 2026-11-04): decorative, so the radio's accessible name is unchanged. -->
18766
+ <svg class="rd-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="d" /></svg>
18767
+ }
18362
18768
  <span class="rd-text">
18363
18769
  @if (label()) { <span class="rd-label" [id]="_labelId()">{{ label() }}</span> }
18364
18770
  @if (description()) { <span class="rd-description" [id]="_descriptionId">{{ description() }}</span> }
@@ -18367,7 +18773,7 @@ var RadioComponent = class RadioComponent {
18367
18773
  </label>
18368
18774
  `,
18369
18775
  isInline: true,
18370
- styles: [":host{display:block}.rd-wrap{position:relative;display:inline-flex;align-items:flex-start;gap:9px;vertical-align:top;cursor:pointer;-webkit-user-select:none;user-select:none}.rd-wrap.rd-disabled{cursor:not-allowed;opacity:.5}.rd-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.rd-wrap:has(.rd-hidden:focus-visible) .rd-dot{outline:2px solid #3b82f6;outline-offset:2px}@media(pointer:coarse),(max-width:480px){.rd-wrap{position:relative}.rd-hidden{width:44px;height:44px;margin:0;clip:auto;overflow:visible;left:-12px;top:-2px;opacity:0;cursor:pointer;z-index:1}.rd-wrap.rd-disabled .rd-hidden{cursor:not-allowed}}.rd-dot{flex-shrink:0;width:20px;height:20px;box-sizing:border-box;border:2px solid #7c8ba1;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;transition:background .12s,border-color .12s}.rd-dot.rd-checked{background:#3b82f6;border-color:#3b82f6}.rd-dot.rd-invalid:not(.rd-checked){border-color:#ef4444}.rd-wrap:hover .rd-dot:not(.rd-checked):not(.rd-disabled){border-color:#3b82f6}.rd-core{width:8px;height:8px;border-radius:50%;background:#fff}@media(max-width:640px),(pointer:coarse){.rd-dot{position:relative}.rd-dot:after{content:\"\";position:absolute;inset:-12px}}.rd-text{display:flex;flex-direction:column;gap:2px}.rd-label{font-size:.875rem;color:#334155;line-height:1.4}.rd-description{font-size:.75rem;color:#64748b;line-height:1.4}\n"],
18776
+ styles: [":host{display:block}.rd-wrap{position:relative;display:inline-flex;align-items:flex-start;gap:9px;vertical-align:top;cursor:pointer;-webkit-user-select:none;user-select:none}.rd-wrap.rd-disabled{cursor:not-allowed;opacity:.5}.rd-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.rd-wrap:has(.rd-hidden:focus-visible) .rd-dot{outline:2px solid #3b82f6;outline-offset:2px}@media(pointer:coarse),(max-width:480px){.rd-wrap{position:relative}.rd-hidden{width:44px;height:44px;margin:0;clip:auto;overflow:visible;left:-12px;top:-2px;opacity:0;cursor:pointer;z-index:1}.rd-wrap.rd-disabled .rd-hidden{cursor:not-allowed}}.rd-dot{flex-shrink:0;width:20px;height:20px;box-sizing:border-box;border:2px solid #7c8ba1;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;transition:background .12s,border-color .12s}.rd-dot.rd-checked{background:#3b82f6;border-color:#3b82f6}.rd-dot.rd-invalid:not(.rd-checked){border-color:#ef4444}.rd-wrap:hover .rd-dot:not(.rd-checked):not(.rd-disabled){border-color:#3b82f6}.rd-core{width:8px;height:8px;border-radius:50%;background:#fff}@media(max-width:640px),(pointer:coarse){.rd-dot{position:relative}.rd-dot:after{content:\"\";position:absolute;inset:-12px}}.rd-icon{flex-shrink:0;margin-top:1px;color:#64748b}.rd-text{display:flex;flex-direction:column;gap:2px}.rd-label{font-size:.875rem;color:#334155;line-height:1.4}.rd-description{font-size:.75rem;color:#64748b;line-height:1.4}\n"],
18371
18777
  changeDetection: i0.ChangeDetectionStrategy.OnPush
18372
18778
  });
18373
18779
  }
@@ -18403,6 +18809,10 @@ i0.ɵɵngDeclareClassMetadata({
18403
18809
  [attr.aria-controls]="controls() || null"
18404
18810
  (change)="onChange($event)"
18405
18811
  />
18812
+ @if (_iconD(); as d) {
18813
+ <!-- Optional icon in front of the label (library source 2026-11-04): decorative, so the radio's accessible name is unchanged. -->
18814
+ <svg class="rd-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="d" /></svg>
18815
+ }
18406
18816
  <span class="rd-text">
18407
18817
  @if (label()) { <span class="rd-label" [id]="_labelId()">{{ label() }}</span> }
18408
18818
  @if (description()) { <span class="rd-description" [id]="_descriptionId">{{ description() }}</span> }
@@ -18410,7 +18820,7 @@ i0.ɵɵngDeclareClassMetadata({
18410
18820
  </span>
18411
18821
  </label>
18412
18822
  `,
18413
- styles: [":host{display:block}.rd-wrap{position:relative;display:inline-flex;align-items:flex-start;gap:9px;vertical-align:top;cursor:pointer;-webkit-user-select:none;user-select:none}.rd-wrap.rd-disabled{cursor:not-allowed;opacity:.5}.rd-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.rd-wrap:has(.rd-hidden:focus-visible) .rd-dot{outline:2px solid #3b82f6;outline-offset:2px}@media(pointer:coarse),(max-width:480px){.rd-wrap{position:relative}.rd-hidden{width:44px;height:44px;margin:0;clip:auto;overflow:visible;left:-12px;top:-2px;opacity:0;cursor:pointer;z-index:1}.rd-wrap.rd-disabled .rd-hidden{cursor:not-allowed}}.rd-dot{flex-shrink:0;width:20px;height:20px;box-sizing:border-box;border:2px solid #7c8ba1;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;transition:background .12s,border-color .12s}.rd-dot.rd-checked{background:#3b82f6;border-color:#3b82f6}.rd-dot.rd-invalid:not(.rd-checked){border-color:#ef4444}.rd-wrap:hover .rd-dot:not(.rd-checked):not(.rd-disabled){border-color:#3b82f6}.rd-core{width:8px;height:8px;border-radius:50%;background:#fff}@media(max-width:640px),(pointer:coarse){.rd-dot{position:relative}.rd-dot:after{content:\"\";position:absolute;inset:-12px}}.rd-text{display:flex;flex-direction:column;gap:2px}.rd-label{font-size:.875rem;color:#334155;line-height:1.4}.rd-description{font-size:.75rem;color:#64748b;line-height:1.4}\n"]
18823
+ styles: [":host{display:block}.rd-wrap{position:relative;display:inline-flex;align-items:flex-start;gap:9px;vertical-align:top;cursor:pointer;-webkit-user-select:none;user-select:none}.rd-wrap.rd-disabled{cursor:not-allowed;opacity:.5}.rd-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.rd-wrap:has(.rd-hidden:focus-visible) .rd-dot{outline:2px solid #3b82f6;outline-offset:2px}@media(pointer:coarse),(max-width:480px){.rd-wrap{position:relative}.rd-hidden{width:44px;height:44px;margin:0;clip:auto;overflow:visible;left:-12px;top:-2px;opacity:0;cursor:pointer;z-index:1}.rd-wrap.rd-disabled .rd-hidden{cursor:not-allowed}}.rd-dot{flex-shrink:0;width:20px;height:20px;box-sizing:border-box;border:2px solid #7c8ba1;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;transition:background .12s,border-color .12s}.rd-dot.rd-checked{background:#3b82f6;border-color:#3b82f6}.rd-dot.rd-invalid:not(.rd-checked){border-color:#ef4444}.rd-wrap:hover .rd-dot:not(.rd-checked):not(.rd-disabled){border-color:#3b82f6}.rd-core{width:8px;height:8px;border-radius:50%;background:#fff}@media(max-width:640px),(pointer:coarse){.rd-dot{position:relative}.rd-dot:after{content:\"\";position:absolute;inset:-12px}}.rd-icon{flex-shrink:0;margin-top:1px;color:#64748b}.rd-text{display:flex;flex-direction:column;gap:2px}.rd-label{font-size:.875rem;color:#334155;line-height:1.4}.rd-description{font-size:.75rem;color:#64748b;line-height:1.4}\n"]
18414
18824
  }]
18415
18825
  }],
18416
18826
  propDecorators: {
@@ -18430,6 +18840,14 @@ i0.ɵɵngDeclareClassMetadata({
18430
18840
  required: false
18431
18841
  }]
18432
18842
  }],
18843
+ icon: [{
18844
+ type: i0.Input,
18845
+ args: [{
18846
+ isSignal: true,
18847
+ alias: "icon",
18848
+ required: false
18849
+ }]
18850
+ }],
18433
18851
  ariaLabel: [{
18434
18852
  type: i0.Input,
18435
18853
  args: [{
@@ -18790,6 +19208,7 @@ var RadioGroupComponent = class RadioGroupComponent {
18790
19208
  [value]="opt.value"
18791
19209
  [label]="opt.label"
18792
19210
  [description]="opt.description ?? ''"
19211
+ [icon]="opt.icon ?? ''"
18793
19212
  [checked]="_value() === opt.value"
18794
19213
  [disabled]="disabled() || !!opt.disabled"
18795
19214
  [invalid]="!!_activeError()"
@@ -18819,6 +19238,7 @@ var RadioGroupComponent = class RadioGroupComponent {
18819
19238
  inputs: [
18820
19239
  "label",
18821
19240
  "description",
19241
+ "icon",
18822
19242
  "ariaLabel",
18823
19243
  "testId",
18824
19244
  "value",
@@ -18897,6 +19317,7 @@ i0.ɵɵngDeclareClassMetadata({
18897
19317
  [value]="opt.value"
18898
19318
  [label]="opt.label"
18899
19319
  [description]="opt.description ?? ''"
19320
+ [icon]="opt.icon ?? ''"
18900
19321
  [checked]="_value() === opt.value"
18901
19322
  [disabled]="disabled() || !!opt.disabled"
18902
19323
  [invalid]="!!_activeError()"
@@ -19700,6 +20121,7 @@ var PhoneNumberPickerComponent = class PhoneNumberPickerComponent {
19700
20121
  "inputName",
19701
20122
  "placeholder",
19702
20123
  "prefix",
20124
+ "leadingIcon",
19703
20125
  "revealable",
19704
20126
  "passwordRequirements",
19705
20127
  "passwordRules",
@@ -19797,7 +20219,11 @@ var PhoneNumberPickerComponent = class PhoneNumberPickerComponent {
19797
20219
  kind: "component",
19798
20220
  type: BadgeComponent,
19799
20221
  selector: "ui-badge",
19800
- inputs: ["label", "variant"]
20222
+ inputs: [
20223
+ "label",
20224
+ "variant",
20225
+ "color"
20226
+ ]
19801
20227
  },
19802
20228
  {
19803
20229
  kind: "component",
@@ -20196,7 +20622,180 @@ i0.ɵɵngDeclareClassMetadata({
20196
20622
  }]
20197
20623
  }
20198
20624
  });
20625
+ function pillTabId(name, key) {
20626
+ return `${name}-${key}`;
20627
+ }
20628
+ function pillTabPanelId(name, key) {
20629
+ return `${name}-panel-${key}`;
20630
+ }
20631
+ function pillTabTitleId(name) {
20632
+ return `${name}--title`;
20633
+ }
20634
+ function pillTabDescriptionId(name) {
20635
+ return `${name}--description`;
20636
+ }
20637
+ var PillTabPanelDirective = class PillTabPanelDirective {
20638
+ constructor() {
20639
+ this.key = input.required({
20640
+ ...ngDevMode ? { debugName: "key" } : /* istanbul ignore next */ {},
20641
+ alias: "uiTabPanel"
20642
+ });
20643
+ this.tabsName = input.required(...ngDevMode ? [{ debugName: "tabsName" }] : /* istanbul ignore next */ []);
20644
+ this.activeKey = input(null, ...ngDevMode ? [{ debugName: "activeKey" }] : /* istanbul ignore next */ []);
20645
+ this.tabbable = input(false, ...ngDevMode ? [{ debugName: "tabbable" }] : /* istanbul ignore next */ []);
20646
+ this.describedByHeader = input(false, ...ngDevMode ? [{ debugName: "describedByHeader" }] : /* istanbul ignore next */ []);
20647
+ }
20648
+ describedId() {
20649
+ return this.describedByHeader() && !this.isHidden() ? pillTabDescriptionId(this.tabsName()) : null;
20650
+ }
20651
+ panelId() {
20652
+ return pillTabPanelId(this.tabsName(), this.key());
20653
+ }
20654
+ tabId() {
20655
+ return pillTabId(this.tabsName(), this.key());
20656
+ }
20657
+ isHidden() {
20658
+ const a = this.activeKey();
20659
+ return a !== null && a !== this.key();
20660
+ }
20661
+ static {
20662
+ this.ɵfac = i0.ɵɵngDeclareFactory({
20663
+ minVersion: "12.0.0",
20664
+ version: "22.2.2",
20665
+ ngImport: i0,
20666
+ type: PillTabPanelDirective,
20667
+ deps: [],
20668
+ target: i0.ɵɵFactoryTarget.Directive
20669
+ });
20670
+ }
20671
+ static {
20672
+ this.ɵdir = i0.ɵɵngDeclareDirective({
20673
+ minVersion: "17.1.0",
20674
+ version: "22.2.2",
20675
+ type: PillTabPanelDirective,
20676
+ isStandalone: true,
20677
+ selector: "[uiTabPanel]",
20678
+ inputs: {
20679
+ key: {
20680
+ classPropertyName: "key",
20681
+ publicName: "uiTabPanel",
20682
+ isSignal: true,
20683
+ isRequired: true,
20684
+ transformFunction: null
20685
+ },
20686
+ tabsName: {
20687
+ classPropertyName: "tabsName",
20688
+ publicName: "tabsName",
20689
+ isSignal: true,
20690
+ isRequired: true,
20691
+ transformFunction: null
20692
+ },
20693
+ activeKey: {
20694
+ classPropertyName: "activeKey",
20695
+ publicName: "activeKey",
20696
+ isSignal: true,
20697
+ isRequired: false,
20698
+ transformFunction: null
20699
+ },
20700
+ tabbable: {
20701
+ classPropertyName: "tabbable",
20702
+ publicName: "tabbable",
20703
+ isSignal: true,
20704
+ isRequired: false,
20705
+ transformFunction: null
20706
+ },
20707
+ describedByHeader: {
20708
+ classPropertyName: "describedByHeader",
20709
+ publicName: "describedByHeader",
20710
+ isSignal: true,
20711
+ isRequired: false,
20712
+ transformFunction: null
20713
+ }
20714
+ },
20715
+ host: {
20716
+ attributes: { "role": "tabpanel" },
20717
+ properties: {
20718
+ "id": "panelId()",
20719
+ "attr.aria-labelledby": "tabId()",
20720
+ "attr.hidden": "isHidden() ? '' : null",
20721
+ "attr.aria-describedby": "describedId()",
20722
+ "attr.tabindex": "tabbable() ? 0 : null"
20723
+ }
20724
+ },
20725
+ ngImport: i0
20726
+ });
20727
+ }
20728
+ };
20729
+ i0.ɵɵngDeclareClassMetadata({
20730
+ minVersion: "12.0.0",
20731
+ version: "22.2.2",
20732
+ ngImport: i0,
20733
+ type: PillTabPanelDirective,
20734
+ decorators: [{
20735
+ type: Directive,
20736
+ args: [{
20737
+ selector: "[uiTabPanel]",
20738
+ standalone: true,
20739
+ host: {
20740
+ role: "tabpanel",
20741
+ "[id]": "panelId()",
20742
+ "[attr.aria-labelledby]": "tabId()",
20743
+ "[attr.hidden]": "isHidden() ? '' : null",
20744
+ "[attr.aria-describedby]": "describedId()",
20745
+ "[attr.tabindex]": "tabbable() ? 0 : null"
20746
+ }
20747
+ }]
20748
+ }],
20749
+ propDecorators: {
20750
+ key: [{
20751
+ type: i0.Input,
20752
+ args: [{
20753
+ isSignal: true,
20754
+ alias: "uiTabPanel",
20755
+ required: true
20756
+ }]
20757
+ }],
20758
+ tabsName: [{
20759
+ type: i0.Input,
20760
+ args: [{
20761
+ isSignal: true,
20762
+ alias: "tabsName",
20763
+ required: true
20764
+ }]
20765
+ }],
20766
+ activeKey: [{
20767
+ type: i0.Input,
20768
+ args: [{
20769
+ isSignal: true,
20770
+ alias: "activeKey",
20771
+ required: false
20772
+ }]
20773
+ }],
20774
+ tabbable: [{
20775
+ type: i0.Input,
20776
+ args: [{
20777
+ isSignal: true,
20778
+ alias: "tabbable",
20779
+ required: false
20780
+ }]
20781
+ }],
20782
+ describedByHeader: [{
20783
+ type: i0.Input,
20784
+ args: [{
20785
+ isSignal: true,
20786
+ alias: "describedByHeader",
20787
+ required: false
20788
+ }]
20789
+ }]
20790
+ }
20791
+ });
20199
20792
  var PillTabsComponent = class PillTabsComponent {
20793
+ titleId() {
20794
+ return pillTabTitleId(this.name());
20795
+ }
20796
+ descriptionId() {
20797
+ return pillTabDescriptionId(this.name());
20798
+ }
20200
20799
  constructor() {
20201
20800
  this.host = inject(ElementRef);
20202
20801
  this.tabs = input([], ...ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []);
@@ -20206,10 +20805,26 @@ var PillTabsComponent = class PillTabsComponent {
20206
20805
  this.noWrap = input(false, ...ngDevMode ? [{ debugName: "noWrap" }] : /* istanbul ignore next */ []);
20207
20806
  this.orientation = input("horizontal", ...ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []);
20208
20807
  this.vertical = () => this.orientation() === "vertical";
20808
+ this.controlsPanels = input(false, ...ngDevMode ? [{ debugName: "controlsPanels" }] : /* istanbul ignore next */ []);
20809
+ this.showDescription = input(false, ...ngDevMode ? [{ debugName: "showDescription" }] : /* istanbul ignore next */ []);
20810
+ this.headingLevel = input(2, ...ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []);
20209
20811
  this.tabChange = output();
20812
+ this.activeTab = computed(() => this.tabs().find((t) => t.key === this.activeKey()) ?? null, ...ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []);
20210
20813
  this.canScrollStart = signal(false, ...ngDevMode ? [{ debugName: "canScrollStart" }] : /* istanbul ignore next */ []);
20211
20814
  this.canScrollEnd = signal(false, ...ngDevMode ? [{ debugName: "canScrollEnd" }] : /* istanbul ignore next */ []);
20212
20815
  const destroyRef = inject(DestroyRef);
20816
+ const warned = /* @__PURE__ */ new Set();
20817
+ effect(() => {
20818
+ const on = this.controlsPanels(), tabs = this.tabs(), name = this.name();
20819
+ if (!on || !isDevMode()) return;
20820
+ untracked(() => {
20821
+ for (const t of tabs) {
20822
+ if (!t.key.startsWith("panel-") || warned.has(name + "|" + t.key)) continue;
20823
+ warned.add(name + "|" + t.key);
20824
+ console.warn(`ui-pill-tabs "${name}": the tab key "${t.key}" starts with "panel-", so its id "${pillTabId(name, t.key)}" can equal the panel id of the key "${t.key.slice(6)}" (${pillTabPanelId(name, t.key.slice(6))}) when controlsPanels is on. Rename the key.`);
20825
+ }
20826
+ });
20827
+ });
20213
20828
  effect(() => {
20214
20829
  this.tabs();
20215
20830
  queueMicrotask(() => this.updateOverflow());
@@ -20224,6 +20839,12 @@ var PillTabsComponent = class PillTabsComponent {
20224
20839
  }
20225
20840
  });
20226
20841
  }
20842
+ tabId(key) {
20843
+ return pillTabId(this.name(), key);
20844
+ }
20845
+ panelId(key) {
20846
+ return pillTabPanelId(this.name(), key);
20847
+ }
20227
20848
  updateOverflow() {
20228
20849
  const el = this.host.nativeElement.querySelector(".pill-tabs");
20229
20850
  if (!el) return;
@@ -20254,7 +20875,7 @@ var PillTabsComponent = class PillTabsComponent {
20254
20875
  e.preventDefault();
20255
20876
  const key = enabled[next].key;
20256
20877
  this.select(key);
20257
- this.host.nativeElement.querySelector(`#${CSS.escape(this.name() + "-" + key)}`)?.focus();
20878
+ this.host.nativeElement.querySelector(`#${CSS.escape(this.tabId(key))}`)?.focus();
20258
20879
  }
20259
20880
  static {
20260
20881
  this.ɵfac = i0.ɵɵngDeclareFactory({
@@ -20315,6 +20936,27 @@ var PillTabsComponent = class PillTabsComponent {
20315
20936
  isSignal: true,
20316
20937
  isRequired: false,
20317
20938
  transformFunction: null
20939
+ },
20940
+ controlsPanels: {
20941
+ classPropertyName: "controlsPanels",
20942
+ publicName: "controlsPanels",
20943
+ isSignal: true,
20944
+ isRequired: false,
20945
+ transformFunction: null
20946
+ },
20947
+ showDescription: {
20948
+ classPropertyName: "showDescription",
20949
+ publicName: "showDescription",
20950
+ isSignal: true,
20951
+ isRequired: false,
20952
+ transformFunction: null
20953
+ },
20954
+ headingLevel: {
20955
+ classPropertyName: "headingLevel",
20956
+ publicName: "headingLevel",
20957
+ isSignal: true,
20958
+ isRequired: false,
20959
+ transformFunction: null
20318
20960
  }
20319
20961
  },
20320
20962
  outputs: { tabChange: "tabChange" },
@@ -20324,13 +20966,14 @@ var PillTabsComponent = class PillTabsComponent {
20324
20966
  <div class="pill-tabs" [class.pill-tabs--nowrap]="noWrap()" [class.pill-tabs--vertical]="vertical()" role="tablist" [attr.aria-label]="ariaLabel()" [attr.aria-orientation]="vertical() ? 'vertical' : null" (keydown)="onKeydown($event)" (scroll)="updateOverflow()">
20325
20967
  @for (tab of tabs(); track tab.key) {
20326
20968
  <button type="button" class="pill-tab" role="tab"
20327
- [id]="name() + '-' + tab.key"
20969
+ [id]="tabId(tab.key)"
20328
20970
  [class.active]="activeKey() === tab.key"
20329
20971
  [class.disabled]="tab.disabled"
20330
20972
  [disabled]="tab.disabled ?? false"
20331
20973
  [attr.aria-selected]="activeKey() === tab.key"
20332
20974
  [attr.tabindex]="tabIndexFor(tab)"
20333
- [attr.aria-describedby]="tab.info ? name() + '-' + tab.key + '-info' : null"
20975
+ [attr.aria-describedby]="tab.info ? tabId(tab.key) + '-info' : null"
20976
+ [attr.aria-controls]="controlsPanels() ? panelId(tab.key) : null"
20334
20977
  (click)="select(tab.key)">
20335
20978
  <span>{{ tab.label }}</span>
20336
20979
  @if (tab.count !== undefined) {
@@ -20340,7 +20983,7 @@ var PillTabsComponent = class PillTabsComponent {
20340
20983
  <svg class="pill-info-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-testid="pill-info-icon">
20341
20984
  <circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/>
20342
20985
  </svg>
20343
- <span class="pill-info-tip" role="tooltip" aria-hidden="true" [id]="name() + '-' + tab.key + '-info'" data-testid="pill-info-tip">{{ tab.info }}</span>
20986
+ <span class="pill-info-tip" role="tooltip" aria-hidden="true" [id]="tabId(tab.key) + '-info'" data-testid="pill-info-tip">{{ tab.info }}</span>
20344
20987
  }
20345
20988
  </button>
20346
20989
  }
@@ -20348,9 +20991,23 @@ var PillTabsComponent = class PillTabsComponent {
20348
20991
  <span class="pill-fade pill-fade--start" [class.visible]="canScrollStart()" aria-hidden="true" data-testid="pill-fade-start"></span>
20349
20992
  <span class="pill-fade pill-fade--end" [class.visible]="canScrollEnd()" aria-hidden="true" data-testid="pill-fade-end"></span>
20350
20993
  </div>
20994
+ @if (showDescription() && (activeTab()?.title || activeTab()?.description)) {
20995
+ <div class="pill-header" data-testid="pill-header">
20996
+ @if (activeTab()?.title) {
20997
+ @if (headingLevel() === 3) {
20998
+ <h3 class="pill-header-title" [id]="titleId()" data-testid="pill-header-title">{{ activeTab()!.title }}</h3>
20999
+ } @else {
21000
+ <h2 class="pill-header-title" [id]="titleId()" data-testid="pill-header-title">{{ activeTab()!.title }}</h2>
21001
+ }
21002
+ }
21003
+ @if (activeTab()?.description) {
21004
+ <p class="pill-header-description" [id]="descriptionId()" data-testid="pill-header-description">{{ activeTab()!.description }}</p>
21005
+ }
21006
+ </div>
21007
+ }
20351
21008
  `,
20352
21009
  isInline: true,
20353
- styles: [".pill-wrap{position:relative}.pill-fade{position:absolute;top:0;bottom:0;width:28px;pointer-events:none;opacity:0;transition:opacity .15s}.pill-fade.visible{opacity:1}.pill-fade--start{left:0;background:linear-gradient(to right,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-fade--end{right:0;background:linear-gradient(to left,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-tabs{display:flex;gap:8px;flex-wrap:wrap}@media(max-width:768px){.pill-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px;scrollbar-width:none}.pill-tabs::-webkit-scrollbar{display:none}}.pill-tabs--nowrap .pill-tab{flex:0 0 auto;white-space:nowrap}.pill-tab{position:relative;display:inline-flex;align-items:center;gap:6px;padding:7px 16px;border-radius:999px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#64748b;cursor:pointer;transition:all .15s;font-family:inherit}.pill-tab:hover:not(.disabled):not(.active){background:#f8fafc;border-color:#94a3b8}.pill-tab:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.pill-tab .pill-count{background:#e2e8f0;color:#475569;font-size:.7rem;font-weight:600;padding:1px 6px;border-radius:999px;line-height:1.4}.pill-tab.active{background:#1e293b;color:#fff;border-color:#1e293b}.pill-tab.active .pill-count{background:#fff3;color:#fff}.pill-tab.active:hover{background:#1e293b;color:#fff}.pill-tab.disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.pill-tab .pill-info-icon{flex-shrink:0;opacity:.7}.pill-tab:hover .pill-info-icon,.pill-tab:focus-visible .pill-info-icon{opacity:1}.pill-tab .pill-info-tip{position:absolute;left:0;top:calc(100% + 8px);z-index:20;width:max-content;max-width:280px;padding:8px 12px;border-radius:8px;background:#1e293b;color:#fff;font-size:.75rem;font-weight:400;line-height:1.45;text-align:left;white-space:normal;box-shadow:0 4px 12px #0f172a40;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s,visibility .12s}.pill-tab:hover .pill-info-tip,.pill-tab:focus-visible .pill-info-tip{opacity:1;visibility:visible}.pill-tab:last-child .pill-info-tip{left:auto;right:0}.pill-wrap--vertical .pill-fade{display:none}.pill-tabs.pill-tabs--vertical{flex-direction:column;flex-wrap:nowrap;overflow:visible;gap:4px;padding-bottom:0}.pill-tabs--vertical .pill-tab{width:100%;justify-content:flex-start;border-radius:10px;text-align:left}.pill-tabs--vertical .pill-tab .pill-count{margin-left:auto}.pill-tabs--vertical .pill-tab .pill-info-tip{left:calc(100% + 8px);top:50%;transform:translateY(-50%)}.pill-tabs--vertical .pill-tab:last-child .pill-info-tip{left:calc(100% + 8px);right:auto}@media(pointer:coarse),(max-width:480px){.pill-tab{min-height:44px}}\n"],
21010
+ styles: [".pill-header{margin-top:16px;min-width:0}.pill-header-title{margin:0;font-size:1.125rem;font-weight:600;line-height:1.3;color:var(--ui-text, #1e293b);overflow-wrap:anywhere}.pill-header-description{margin:4px 0 0;font-size:.875rem;line-height:1.5;color:var(--ui-text-muted, #475569);overflow-wrap:anywhere}.pill-wrap{position:relative}.pill-fade{position:absolute;top:0;bottom:0;width:28px;pointer-events:none;opacity:0;transition:opacity .15s}.pill-fade.visible{opacity:1}.pill-fade--start{left:0;background:linear-gradient(to right,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-fade--end{right:0;background:linear-gradient(to left,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-tabs{display:flex;gap:8px;flex-wrap:wrap}@media(max-width:768px){.pill-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px;scrollbar-width:none}.pill-tabs::-webkit-scrollbar{display:none}}.pill-tabs--nowrap .pill-tab{flex:0 0 auto;white-space:nowrap}.pill-tab{position:relative;display:inline-flex;align-items:center;gap:6px;padding:7px 16px;border-radius:999px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#64748b;cursor:pointer;transition:all .15s;font-family:inherit}.pill-tab:hover:not(.disabled):not(.active){background:#f8fafc;border-color:#94a3b8}.pill-tab:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.pill-tab .pill-count{background:#e2e8f0;color:#475569;font-size:.7rem;font-weight:600;padding:1px 6px;border-radius:999px;line-height:1.4}.pill-tab.active{background:#1e293b;color:#fff;border-color:#1e293b}.pill-tab.active .pill-count{background:#fff3;color:#fff}.pill-tab.active:hover{background:#1e293b;color:#fff}.pill-tab.disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.pill-tab .pill-info-icon{flex-shrink:0;opacity:.7}.pill-tab:hover .pill-info-icon,.pill-tab:focus-visible .pill-info-icon{opacity:1}.pill-tab .pill-info-tip{position:absolute;left:0;top:calc(100% + 8px);z-index:20;width:max-content;max-width:280px;padding:8px 12px;border-radius:8px;background:#1e293b;color:#fff;font-size:.75rem;font-weight:400;line-height:1.45;text-align:left;white-space:normal;box-shadow:0 4px 12px #0f172a40;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s,visibility .12s}.pill-tab:hover .pill-info-tip,.pill-tab:focus-visible .pill-info-tip{opacity:1;visibility:visible}.pill-tab:last-child .pill-info-tip{left:auto;right:0}.pill-wrap--vertical .pill-fade{display:none}.pill-tabs.pill-tabs--vertical{flex-direction:column;flex-wrap:nowrap;overflow:visible;gap:4px;padding-bottom:0}.pill-tabs--vertical .pill-tab{width:100%;justify-content:flex-start;border-radius:10px;text-align:left}.pill-tabs--vertical .pill-tab .pill-count{margin-left:auto}.pill-tabs--vertical .pill-tab .pill-info-tip{left:calc(100% + 8px);top:50%;transform:translateY(-50%)}.pill-tabs--vertical .pill-tab:last-child .pill-info-tip{left:calc(100% + 8px);right:auto}@media(pointer:coarse),(max-width:480px){.pill-tab{min-height:44px}}\n"],
20354
21011
  changeDetection: i0.ChangeDetectionStrategy.OnPush
20355
21012
  });
20356
21013
  }
@@ -20371,13 +21028,14 @@ i0.ɵɵngDeclareClassMetadata({
20371
21028
  <div class="pill-tabs" [class.pill-tabs--nowrap]="noWrap()" [class.pill-tabs--vertical]="vertical()" role="tablist" [attr.aria-label]="ariaLabel()" [attr.aria-orientation]="vertical() ? 'vertical' : null" (keydown)="onKeydown($event)" (scroll)="updateOverflow()">
20372
21029
  @for (tab of tabs(); track tab.key) {
20373
21030
  <button type="button" class="pill-tab" role="tab"
20374
- [id]="name() + '-' + tab.key"
21031
+ [id]="tabId(tab.key)"
20375
21032
  [class.active]="activeKey() === tab.key"
20376
21033
  [class.disabled]="tab.disabled"
20377
21034
  [disabled]="tab.disabled ?? false"
20378
21035
  [attr.aria-selected]="activeKey() === tab.key"
20379
21036
  [attr.tabindex]="tabIndexFor(tab)"
20380
- [attr.aria-describedby]="tab.info ? name() + '-' + tab.key + '-info' : null"
21037
+ [attr.aria-describedby]="tab.info ? tabId(tab.key) + '-info' : null"
21038
+ [attr.aria-controls]="controlsPanels() ? panelId(tab.key) : null"
20381
21039
  (click)="select(tab.key)">
20382
21040
  <span>{{ tab.label }}</span>
20383
21041
  @if (tab.count !== undefined) {
@@ -20387,7 +21045,7 @@ i0.ɵɵngDeclareClassMetadata({
20387
21045
  <svg class="pill-info-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-testid="pill-info-icon">
20388
21046
  <circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/>
20389
21047
  </svg>
20390
- <span class="pill-info-tip" role="tooltip" aria-hidden="true" [id]="name() + '-' + tab.key + '-info'" data-testid="pill-info-tip">{{ tab.info }}</span>
21048
+ <span class="pill-info-tip" role="tooltip" aria-hidden="true" [id]="tabId(tab.key) + '-info'" data-testid="pill-info-tip">{{ tab.info }}</span>
20391
21049
  }
20392
21050
  </button>
20393
21051
  }
@@ -20395,8 +21053,22 @@ i0.ɵɵngDeclareClassMetadata({
20395
21053
  <span class="pill-fade pill-fade--start" [class.visible]="canScrollStart()" aria-hidden="true" data-testid="pill-fade-start"></span>
20396
21054
  <span class="pill-fade pill-fade--end" [class.visible]="canScrollEnd()" aria-hidden="true" data-testid="pill-fade-end"></span>
20397
21055
  </div>
21056
+ @if (showDescription() && (activeTab()?.title || activeTab()?.description)) {
21057
+ <div class="pill-header" data-testid="pill-header">
21058
+ @if (activeTab()?.title) {
21059
+ @if (headingLevel() === 3) {
21060
+ <h3 class="pill-header-title" [id]="titleId()" data-testid="pill-header-title">{{ activeTab()!.title }}</h3>
21061
+ } @else {
21062
+ <h2 class="pill-header-title" [id]="titleId()" data-testid="pill-header-title">{{ activeTab()!.title }}</h2>
21063
+ }
21064
+ }
21065
+ @if (activeTab()?.description) {
21066
+ <p class="pill-header-description" [id]="descriptionId()" data-testid="pill-header-description">{{ activeTab()!.description }}</p>
21067
+ }
21068
+ </div>
21069
+ }
20398
21070
  `,
20399
- styles: [".pill-wrap{position:relative}.pill-fade{position:absolute;top:0;bottom:0;width:28px;pointer-events:none;opacity:0;transition:opacity .15s}.pill-fade.visible{opacity:1}.pill-fade--start{left:0;background:linear-gradient(to right,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-fade--end{right:0;background:linear-gradient(to left,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-tabs{display:flex;gap:8px;flex-wrap:wrap}@media(max-width:768px){.pill-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px;scrollbar-width:none}.pill-tabs::-webkit-scrollbar{display:none}}.pill-tabs--nowrap .pill-tab{flex:0 0 auto;white-space:nowrap}.pill-tab{position:relative;display:inline-flex;align-items:center;gap:6px;padding:7px 16px;border-radius:999px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#64748b;cursor:pointer;transition:all .15s;font-family:inherit}.pill-tab:hover:not(.disabled):not(.active){background:#f8fafc;border-color:#94a3b8}.pill-tab:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.pill-tab .pill-count{background:#e2e8f0;color:#475569;font-size:.7rem;font-weight:600;padding:1px 6px;border-radius:999px;line-height:1.4}.pill-tab.active{background:#1e293b;color:#fff;border-color:#1e293b}.pill-tab.active .pill-count{background:#fff3;color:#fff}.pill-tab.active:hover{background:#1e293b;color:#fff}.pill-tab.disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.pill-tab .pill-info-icon{flex-shrink:0;opacity:.7}.pill-tab:hover .pill-info-icon,.pill-tab:focus-visible .pill-info-icon{opacity:1}.pill-tab .pill-info-tip{position:absolute;left:0;top:calc(100% + 8px);z-index:20;width:max-content;max-width:280px;padding:8px 12px;border-radius:8px;background:#1e293b;color:#fff;font-size:.75rem;font-weight:400;line-height:1.45;text-align:left;white-space:normal;box-shadow:0 4px 12px #0f172a40;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s,visibility .12s}.pill-tab:hover .pill-info-tip,.pill-tab:focus-visible .pill-info-tip{opacity:1;visibility:visible}.pill-tab:last-child .pill-info-tip{left:auto;right:0}.pill-wrap--vertical .pill-fade{display:none}.pill-tabs.pill-tabs--vertical{flex-direction:column;flex-wrap:nowrap;overflow:visible;gap:4px;padding-bottom:0}.pill-tabs--vertical .pill-tab{width:100%;justify-content:flex-start;border-radius:10px;text-align:left}.pill-tabs--vertical .pill-tab .pill-count{margin-left:auto}.pill-tabs--vertical .pill-tab .pill-info-tip{left:calc(100% + 8px);top:50%;transform:translateY(-50%)}.pill-tabs--vertical .pill-tab:last-child .pill-info-tip{left:calc(100% + 8px);right:auto}@media(pointer:coarse),(max-width:480px){.pill-tab{min-height:44px}}\n"]
21071
+ styles: [".pill-header{margin-top:16px;min-width:0}.pill-header-title{margin:0;font-size:1.125rem;font-weight:600;line-height:1.3;color:var(--ui-text, #1e293b);overflow-wrap:anywhere}.pill-header-description{margin:4px 0 0;font-size:.875rem;line-height:1.5;color:var(--ui-text-muted, #475569);overflow-wrap:anywhere}.pill-wrap{position:relative}.pill-fade{position:absolute;top:0;bottom:0;width:28px;pointer-events:none;opacity:0;transition:opacity .15s}.pill-fade.visible{opacity:1}.pill-fade--start{left:0;background:linear-gradient(to right,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-fade--end{right:0;background:linear-gradient(to left,var(--ui-pill-tabs-fade, #fff),transparent)}.pill-tabs{display:flex;gap:8px;flex-wrap:wrap}@media(max-width:768px){.pill-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px;scrollbar-width:none}.pill-tabs::-webkit-scrollbar{display:none}}.pill-tabs--nowrap .pill-tab{flex:0 0 auto;white-space:nowrap}.pill-tab{position:relative;display:inline-flex;align-items:center;gap:6px;padding:7px 16px;border-radius:999px;border:1px solid #e2e8f0;background:#fff;font-size:.8125rem;font-weight:500;color:#64748b;cursor:pointer;transition:all .15s;font-family:inherit}.pill-tab:hover:not(.disabled):not(.active){background:#f8fafc;border-color:#94a3b8}.pill-tab:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.pill-tab .pill-count{background:#e2e8f0;color:#475569;font-size:.7rem;font-weight:600;padding:1px 6px;border-radius:999px;line-height:1.4}.pill-tab.active{background:#1e293b;color:#fff;border-color:#1e293b}.pill-tab.active .pill-count{background:#fff3;color:#fff}.pill-tab.active:hover{background:#1e293b;color:#fff}.pill-tab.disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.pill-tab .pill-info-icon{flex-shrink:0;opacity:.7}.pill-tab:hover .pill-info-icon,.pill-tab:focus-visible .pill-info-icon{opacity:1}.pill-tab .pill-info-tip{position:absolute;left:0;top:calc(100% + 8px);z-index:20;width:max-content;max-width:280px;padding:8px 12px;border-radius:8px;background:#1e293b;color:#fff;font-size:.75rem;font-weight:400;line-height:1.45;text-align:left;white-space:normal;box-shadow:0 4px 12px #0f172a40;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s,visibility .12s}.pill-tab:hover .pill-info-tip,.pill-tab:focus-visible .pill-info-tip{opacity:1;visibility:visible}.pill-tab:last-child .pill-info-tip{left:auto;right:0}.pill-wrap--vertical .pill-fade{display:none}.pill-tabs.pill-tabs--vertical{flex-direction:column;flex-wrap:nowrap;overflow:visible;gap:4px;padding-bottom:0}.pill-tabs--vertical .pill-tab{width:100%;justify-content:flex-start;border-radius:10px;text-align:left}.pill-tabs--vertical .pill-tab .pill-count{margin-left:auto}.pill-tabs--vertical .pill-tab .pill-info-tip{left:calc(100% + 8px);top:50%;transform:translateY(-50%)}.pill-tabs--vertical .pill-tab:last-child .pill-info-tip{left:calc(100% + 8px);right:auto}@media(pointer:coarse),(max-width:480px){.pill-tab{min-height:44px}}\n"]
20400
21072
  }]
20401
21073
  }],
20402
21074
  ctorParameters: () => [],
@@ -20449,6 +21121,30 @@ i0.ɵɵngDeclareClassMetadata({
20449
21121
  required: false
20450
21122
  }]
20451
21123
  }],
21124
+ controlsPanels: [{
21125
+ type: i0.Input,
21126
+ args: [{
21127
+ isSignal: true,
21128
+ alias: "controlsPanels",
21129
+ required: false
21130
+ }]
21131
+ }],
21132
+ showDescription: [{
21133
+ type: i0.Input,
21134
+ args: [{
21135
+ isSignal: true,
21136
+ alias: "showDescription",
21137
+ required: false
21138
+ }]
21139
+ }],
21140
+ headingLevel: [{
21141
+ type: i0.Input,
21142
+ args: [{
21143
+ isSignal: true,
21144
+ alias: "headingLevel",
21145
+ required: false
21146
+ }]
21147
+ }],
20452
21148
  tabChange: [{
20453
21149
  type: i0.Output,
20454
21150
  args: ["tabChange"]
@@ -21338,6 +22034,7 @@ var TextareaInputComponent = class TextareaInputComponent {
21338
22034
  this._activeError = computed(() => this.error() || (this._reveal.revealed() ? this.errorMessage() : ""), ...ngDevMode ? [{ debugName: "_activeError" }] : /* istanbul ignore next */ []);
21339
22035
  this._onValidatorChange = () => {};
21340
22036
  this._inputId = `ta-${Math.random().toString(36).slice(2, 8)}`;
22037
+ this._hostEl = inject(ElementRef);
21341
22038
  this._onChange = (_) => {};
21342
22039
  this._onTouched = () => {};
21343
22040
  effect(() => {
@@ -21354,6 +22051,9 @@ var TextareaInputComponent = class TextareaInputComponent {
21354
22051
  registerOnValidatorChange(fn) {
21355
22052
  this._onValidatorChange = fn;
21356
22053
  }
22054
+ focus(options) {
22055
+ this._hostEl.nativeElement.querySelector("textarea")?.focus(options);
22056
+ }
21357
22057
  writeValue(val) {
21358
22058
  this._value.set(val ?? "");
21359
22059
  }
@@ -21984,6 +22684,7 @@ var BulkMessagePanelComponent = class BulkMessagePanelComponent {
21984
22684
  "inputName",
21985
22685
  "placeholder",
21986
22686
  "prefix",
22687
+ "leadingIcon",
21987
22688
  "revealable",
21988
22689
  "passwordRequirements",
21989
22690
  "passwordRules",
@@ -22630,6 +23331,7 @@ var BankAccountFormComponent = class BankAccountFormComponent {
22630
23331
  inputs: [
22631
23332
  "label",
22632
23333
  "ariaLabel",
23334
+ "labelHidden",
22633
23335
  "inputName",
22634
23336
  "placeholder",
22635
23337
  "options",
@@ -22655,6 +23357,7 @@ var BankAccountFormComponent = class BankAccountFormComponent {
22655
23357
  "inputName",
22656
23358
  "placeholder",
22657
23359
  "prefix",
23360
+ "leadingIcon",
22658
23361
  "revealable",
22659
23362
  "passwordRequirements",
22660
23363
  "passwordRules",
@@ -25409,6 +26112,7 @@ var TimeInputComponent = class TimeInputComponent {
25409
26112
  [id]="_inputId"
25410
26113
  [value]="_value()"
25411
26114
  [disabled]="disabled()"
26115
+ [attr.aria-disabled]="disabled() ? 'true' : null"
25412
26116
  [attr.min]="min() || null"
25413
26117
  [attr.max]="max() || null"
25414
26118
  [attr.required]="required() || null"
@@ -25473,6 +26177,7 @@ i0.ɵɵngDeclareClassMetadata({
25473
26177
  [id]="_inputId"
25474
26178
  [value]="_value()"
25475
26179
  [disabled]="disabled()"
26180
+ [attr.aria-disabled]="disabled() ? 'true' : null"
25476
26181
  [attr.min]="min() || null"
25477
26182
  [attr.max]="max() || null"
25478
26183
  [attr.required]="required() || null"
@@ -25658,6 +26363,14 @@ var ComboboxComponent = class ComboboxComponent {
25658
26363
  effect(() => {
25659
26364
  this.invalidChange.emit(this.invalid());
25660
26365
  });
26366
+ effect(() => {
26367
+ if (this.disabled()) untracked(() => {
26368
+ this._cancelTimer();
26369
+ this._open.set(false);
26370
+ this._editing.set(false);
26371
+ this._text.set("");
26372
+ });
26373
+ });
25661
26374
  this._destroyRef.onDestroy(() => this._cancelTimer());
25662
26375
  }
25663
26376
  ngOnChanges() {
@@ -25734,6 +26447,7 @@ var ComboboxComponent = class ComboboxComponent {
25734
26447
  }, { injector: this._injector });
25735
26448
  }
25736
26449
  onInput(event) {
26450
+ if (this.disabled()) return;
25737
26451
  this._text.set(event.target.value);
25738
26452
  this._editing.set(true);
25739
26453
  this._open.set(true);
@@ -25813,6 +26527,7 @@ var ComboboxComponent = class ComboboxComponent {
25813
26527
  if (!o.disabled && i !== this._activeIndex()) this._activeIndex.set(i);
25814
26528
  }
25815
26529
  choose(o) {
26530
+ if (this.disabled()) return;
25816
26531
  const sel = {
25817
26532
  value: o.value,
25818
26533
  label: o.label
@@ -25824,6 +26539,7 @@ var ComboboxComponent = class ComboboxComponent {
25824
26539
  this.valueChange.emit(o);
25825
26540
  }
25826
26541
  clear() {
26542
+ if (this.disabled()) return;
25827
26543
  this._selected.set(null);
25828
26544
  this._revert();
25829
26545
  this._open.set(false);
@@ -26015,6 +26731,7 @@ var ComboboxComponent = class ComboboxComponent {
26015
26731
  [placeholder]="placeholder()"
26016
26732
  [value]="_inputText()"
26017
26733
  [disabled]="disabled()"
26734
+ [attr.aria-disabled]="disabled() ? 'true' : null"
26018
26735
  [attr.aria-label]="ariaLabel() || null"
26019
26736
  [attr.aria-expanded]="_open() ? 'true' : 'false'"
26020
26737
  [attr.aria-controls]="_open() ? _listId : null"
@@ -26119,6 +26836,7 @@ i0.ɵɵngDeclareClassMetadata({
26119
26836
  [placeholder]="placeholder()"
26120
26837
  [value]="_inputText()"
26121
26838
  [disabled]="disabled()"
26839
+ [attr.aria-disabled]="disabled() ? 'true' : null"
26122
26840
  [attr.aria-label]="ariaLabel() || null"
26123
26841
  [attr.aria-expanded]="_open() ? 'true' : 'false'"
26124
26842
  [attr.aria-controls]="_open() ? _listId : null"
@@ -28351,6 +29069,7 @@ i0.ɵɵngDeclareClassMetadata({
28351
29069
  });
28352
29070
  var ListItemComponent = class ListItemComponent {
28353
29071
  constructor() {
29072
+ this.host = inject(ElementRef);
28354
29073
  this.leading = input("none", ...ngDevMode ? [{ debugName: "leading" }] : /* istanbul ignore next */ []);
28355
29074
  this.inputName = input("", ...ngDevMode ? [{ debugName: "inputName" }] : /* istanbul ignore next */ []);
28356
29075
  this.inputId = input("", ...ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []);
@@ -28360,6 +29079,8 @@ var ListItemComponent = class ListItemComponent {
28360
29079
  this.interactive = input(true, ...ngDevMode ? [{ debugName: "interactive" }] : /* istanbul ignore next */ []);
28361
29080
  this.alwaysShowBadge = input(false, ...ngDevMode ? [{ debugName: "alwaysShowBadge" }] : /* istanbul ignore next */ []);
28362
29081
  this.wrapText = input(false, ...ngDevMode ? [{ debugName: "wrapText" }] : /* istanbul ignore next */ []);
29082
+ this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
29083
+ this.busy = input(false, ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
28363
29084
  this.title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
28364
29085
  this.badge = input(null, ...ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []);
28365
29086
  this.badgeVariant = input("green", ...ngDevMode ? [{ debugName: "badgeVariant" }] : /* istanbul ignore next */ []);
@@ -28369,6 +29090,7 @@ var ListItemComponent = class ListItemComponent {
28369
29090
  this.iconD = () => this.icon() ? iconPath(this.icon()) ?? null : null;
28370
29091
  this.select = output();
28371
29092
  this.pressable = () => this.interactive() && this.leading() === "none";
29093
+ this.hasImage = signal(false, ...ngDevMode ? [{ debugName: "hasImage" }] : /* istanbul ignore next */ []);
28372
29094
  this.visibleDetails = () => this.details().map((d) => typeof d === "string" ? {
28373
29095
  text: d,
28374
29096
  d: null,
@@ -28382,14 +29104,43 @@ var ListItemComponent = class ListItemComponent {
28382
29104
  get _borderedClass() {
28383
29105
  return this.bordered();
28384
29106
  }
29107
+ get _disabledClass() {
29108
+ return this.disabled();
29109
+ }
29110
+ ngAfterContentChecked() {
29111
+ const kids = this.host.nativeElement.firstElementChild?.children;
29112
+ let has = false;
29113
+ if (kids) {
29114
+ for (let i = 0; i < kids.length; i++) if (kids[i].hasAttribute("list-item-image")) {
29115
+ has = true;
29116
+ break;
29117
+ }
29118
+ }
29119
+ if (has !== this.hasImage()) this.hasImage.set(has);
29120
+ }
29121
+ onInputClick(e) {
29122
+ if (this.disabled() || this.busy()) e.preventDefault();
29123
+ }
29124
+ onInputKey(e) {
29125
+ if ((this.disabled() || this.busy()) && (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "ArrowLeft" || e.key === "ArrowRight")) e.preventDefault();
29126
+ }
29127
+ onInputChange(e) {
29128
+ const input = e.target;
29129
+ if (this.disabled() || this.busy()) {
29130
+ input.checked = this.checked();
29131
+ return;
29132
+ }
29133
+ this.select.emit();
29134
+ }
28385
29135
  onRowClick(e) {
28386
- if (!this.pressable()) return;
29136
+ if (!this.pressable() || this.disabled() || this.busy()) return;
28387
29137
  if (e.target.closest("[list-item-action], [li-action]")) return;
28388
29138
  this.select.emit();
28389
29139
  }
28390
29140
  onRowKey(e) {
28391
29141
  if (!this.pressable() || e.target !== e.currentTarget) return;
28392
29142
  e.preventDefault();
29143
+ if (this.disabled() || this.busy()) return;
28393
29144
  this.select.emit();
28394
29145
  }
28395
29146
  static {
@@ -28473,6 +29224,20 @@ var ListItemComponent = class ListItemComponent {
28473
29224
  isRequired: false,
28474
29225
  transformFunction: null
28475
29226
  },
29227
+ disabled: {
29228
+ classPropertyName: "disabled",
29229
+ publicName: "disabled",
29230
+ isSignal: true,
29231
+ isRequired: false,
29232
+ transformFunction: null
29233
+ },
29234
+ busy: {
29235
+ classPropertyName: "busy",
29236
+ publicName: "busy",
29237
+ isSignal: true,
29238
+ isRequired: false,
29239
+ transformFunction: null
29240
+ },
28476
29241
  title: {
28477
29242
  classPropertyName: "title",
28478
29243
  publicName: "title",
@@ -28517,7 +29282,10 @@ var ListItemComponent = class ListItemComponent {
28517
29282
  }
28518
29283
  },
28519
29284
  outputs: { select: "select" },
28520
- host: { properties: { "class.li-bordered": "this._borderedClass" } },
29285
+ host: { properties: {
29286
+ "class.li-bordered": "this._borderedClass",
29287
+ "class.li-disabled": "this._disabledClass"
29288
+ } },
28521
29289
  ngImport: i0,
28522
29290
  template: `
28523
29291
  <ng-template #tile>
@@ -28529,7 +29297,7 @@ var ListItemComponent = class ListItemComponent {
28529
29297
  </ng-template>
28530
29298
  <ng-template #content>
28531
29299
  <div class="li-title-row">
28532
- <span class="li-title">{{ title() }}</span>
29300
+ <span class="li-title" data-testid="list-item-title">{{ title() }}</span>
28533
29301
  @if (badge() && (checked() || alwaysShowBadge())) {
28534
29302
  <ui-badge [label]="badge()!" [variant]="badgeVariant()" />
28535
29303
  }
@@ -28541,7 +29309,7 @@ var ListItemComponent = class ListItemComponent {
28541
29309
  @if (detail.d) {
28542
29310
  <svg class="li-detail-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="detail.d" /></svg>
28543
29311
  }
28544
- <span class="li-detail-text">{{ detail.text }}</span>
29312
+ <span class="li-detail-text" data-testid="list-item-detail">{{ detail.text }}</span>
28545
29313
  </span>
28546
29314
  }
28547
29315
  </div>
@@ -28549,51 +29317,67 @@ var ListItemComponent = class ListItemComponent {
28549
29317
  </ng-template>
28550
29318
 
28551
29319
  <div class="li-row" [class.li-row--highlighted]="highlighted()" [class.li-row--pressable]="pressable()"
28552
- [attr.role]="pressable() ? 'button' : null" [attr.tabindex]="pressable() ? 0 : null"
29320
+ [class.li-row--disabled]="disabled()" [class.li-row--busy]="busy()"
29321
+ [attr.role]="pressable() ? 'button' : null" [attr.tabindex]="pressable() && !disabled() ? 0 : null"
29322
+ [attr.aria-disabled]="disabled() && pressable() ? 'true' : null" [attr.aria-busy]="busy() ? 'true' : null"
28553
29323
  (click)="onRowClick($event)" (keydown.enter)="onRowKey($event)" (keydown.space)="onRowKey($event)" [class.li-row--static]="!interactive()" [class.li-row--wrap]="wrapText() || !interactive()">
28554
29324
 
28555
- @if (!interactive()) {
28556
- <ng-container [ngTemplateOutlet]="tile" />
28557
- <div class="li-body li-body--static">
28558
- <ng-container [ngTemplateOutlet]="content" />
28559
- </div>
28560
- } @else {
28561
- @if (leading() === 'radio') {
29325
+ @if (interactive() && leading() === 'radio') {
28562
29326
  <input
28563
29327
  type="radio"
28564
29328
  class="li-input"
28565
29329
  [id]="inputId()"
28566
29330
  [name]="inputName()"
28567
29331
  [checked]="checked()"
28568
- (change)="select.emit()"
29332
+ [disabled]="disabled()"
29333
+ (click)="onInputClick($event)"
29334
+ (keydown)="onInputKey($event)"
29335
+ (change)="onInputChange($event)"
28569
29336
  />
28570
- } @else if (leading() === 'checkbox') {
29337
+ } @else if (interactive() && leading() === 'checkbox') {
28571
29338
  <input
28572
29339
  type="checkbox"
28573
29340
  class="li-input"
28574
29341
  [id]="inputId()"
28575
29342
  [checked]="checked()"
28576
- (change)="select.emit()"
29343
+ [disabled]="disabled()"
29344
+ (click)="onInputClick($event)"
29345
+ (keydown)="onInputKey($event)"
29346
+ (change)="onInputChange($event)"
28577
29347
  />
28578
29348
  }
28579
29349
 
28580
- <ng-container [ngTemplateOutlet]="tile" />
28581
- <label class="li-body" [attr.for]="inputId() || null">
28582
- <ng-container [ngTemplateOutlet]="content" />
28583
- </label>
29350
+ <!-- Leading image slot (library source 2026-11-04): a product photo in front of the text. Replaces the icon tile. -->
29351
+ <ng-content select="[list-item-image]" />
29352
+ @if (!hasImage()) { <ng-container [ngTemplateOutlet]="tile" /> }
29353
+ @if (!interactive()) {
29354
+ <div class="li-body li-body--static">
29355
+ <ng-container [ngTemplateOutlet]="content" />
29356
+ </div>
29357
+ } @else {
29358
+ <label class="li-body" [attr.for]="inputId() || null">
29359
+ <ng-container [ngTemplateOutlet]="content" />
29360
+ </label>
28584
29361
  }
28585
29362
 
29363
+ @if (busy()) {
29364
+ <span class="li-spinner" aria-hidden="true"></span>
29365
+ }
28586
29366
  <ng-content select="[list-item-action], [li-action]" />
28587
29367
 
28588
29368
  </div>
28589
29369
  `,
28590
29370
  isInline: true,
28591
- styles: ["ui-list-item{display:block}ui-list-item.li-bordered{border:1px solid var(--border, #e2e8f0);border-radius:12px;overflow:hidden;background:var(--surface, #fff);box-shadow:0 1px 2px #0f172a0a;margin-bottom:8px;transition:border-color .15s ease,box-shadow .15s ease}ui-list-item.li-bordered:last-child{margin-bottom:0}ui-list-item.li-bordered:hover{border-color:#cbd5e1;box-shadow:0 2px 6px #0f172a12}@media(prefers-reduced-motion:reduce){ui-list-item.li-bordered{transition:none}}.li-row{display:flex;align-items:flex-start;gap:14px;padding:12px 16px;border-bottom:1px solid var(--border, #e2e8f0);transition:background .12s}.li-row:last-child{border-bottom:none}.li-row:hover{background:var(--surface-hover, #f8fafc)}ui-list-item.li-bordered .li-row{border-bottom:none;padding:14px 16px}.li-row.li-row--highlighted{background:#f0fdf4}.li-row.li-row--highlighted:hover{background:#dcfce7}.li-row.li-row--static:hover{background:transparent}.li-row.li-row--static.li-row--highlighted,.li-row.li-row--static.li-row--highlighted:hover{background:#f0fdf4}.li-row.li-row--pressable{cursor:pointer}.li-row.li-row--pressable:focus-visible{outline:2px solid var(--primary, #2563eb);outline-offset:-2px}.li-body.li-body--static{cursor:default}.li-row [list-item-action],.li-row [li-action]{flex-shrink:0;align-self:center}.li-input{margin-top:3px;flex-shrink:0;accent-color:#16a34a;width:1rem;height:1rem;cursor:pointer}.li-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:12px}.li-icon--slate{background:#f1f5f9;color:#475569}.li-icon--amber{background:#fef3c7;color:#b45309}.li-icon--orange{background:#ffedd5;color:#c2410c}.li-icon--red{background:#fee2e2;color:#b91c1c}.li-icon--blue{background:#dbeafe;color:#1d4ed8}.li-icon--green{background:#dcfce7;color:#15803d}.li-icon--purple{background:#f3e8ff;color:#7e22ce}.li-icon--teal{background:#ccfbf1;color:#0f766e}.li-body{flex:1;min-width:0;cursor:pointer;display:flex;flex-direction:column;gap:6px}.li-title-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.li-title{font-size:.9375rem;font-weight:600;line-height:1.4;letter-spacing:-.005em;color:var(--text-primary, #0f172a)}.li-row--wrap .li-title{min-width:0;word-break:break-word;overflow-wrap:anywhere}.li-details{display:flex;flex-direction:column;gap:3px;font-size:.8125rem;line-height:1.4;color:var(--text-secondary, #64748b)}.li-detail{display:flex;align-items:center;gap:6px;min-width:0}.li-detail-icon{flex:0 0 auto;color:#94a3b8}.li-detail--warning,.li-detail--warning .li-detail-icon{color:#b45309}.li-detail--danger,.li-detail--danger .li-detail-icon{color:#b91c1c}.li-row--wrap .li-detail-text{min-width:0;word-break:break-word;overflow-wrap:anywhere}\n"],
29371
+ styles: ["ui-list-item{display:block}ui-list-item.li-bordered{border:1px solid var(--border, #e2e8f0);border-radius:12px;overflow:hidden;background:var(--surface, #fff);box-shadow:0 1px 2px #0f172a0a;margin-bottom:8px;transition:border-color .15s ease,box-shadow .15s ease}ui-list-item.li-bordered:last-child{margin-bottom:0}ui-list-item.li-bordered:hover{border-color:#cbd5e1;box-shadow:0 2px 6px #0f172a12}@media(prefers-reduced-motion:reduce){ui-list-item.li-bordered{transition:none}}.li-row{display:flex;align-items:flex-start;gap:14px;padding:12px 16px;border-bottom:1px solid var(--border, #e2e8f0);transition:background .12s}.li-row:last-child{border-bottom:none}.li-row:hover{background:var(--surface-hover, #f8fafc)}ui-list-item.li-bordered .li-row{border-bottom:none;padding:14px 16px}.li-row.li-row--highlighted{background:#f0fdf4}.li-row.li-row--highlighted:hover{background:#dcfce7}.li-row.li-row--static:hover{background:transparent}.li-row.li-row--static.li-row--highlighted,.li-row.li-row--static.li-row--highlighted:hover{background:#f0fdf4}.li-row.li-row--pressable{cursor:pointer}.li-row.li-row--pressable:focus-visible{outline:2px solid var(--primary, #2563eb);outline-offset:-2px}.li-body.li-body--static{cursor:default}.li-row [list-item-action],.li-row [li-action]{flex-shrink:0;align-self:center}.li-row>[list-item-image]{flex:0 0 auto;align-self:center}.li-row.li-row--disabled,.li-row.li-row--disabled:hover{opacity:.72;cursor:not-allowed;background-color:var(--surface-muted, #f8fafc);background-image:repeating-linear-gradient(135deg,transparent 0,transparent 6px,rgba(100,116,139,.1) 6px,rgba(100,116,139,.1) 12px)}.li-row.li-row--disabled .li-body,.li-row.li-row--disabled .li-input,.li-row.li-row--disabled.li-row--pressable{cursor:not-allowed}ui-list-item.li-disabled.li-bordered,ui-list-item.li-disabled.li-bordered:hover{border-style:dashed;box-shadow:none}.li-row.li-row--busy,.li-row.li-row--busy .li-body{cursor:progress}.li-spinner{flex:0 0 auto;align-self:center;box-sizing:border-box;width:16px;height:16px;border:2px solid rgba(100,116,139,.3);border-top-color:var(--text-secondary, #475569);border-radius:50%;animation:li-spin .6s linear infinite}@keyframes li-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.li-spinner{animation-duration:2s}}.li-input{margin-top:3px;flex-shrink:0;accent-color:#16a34a;width:1rem;height:1rem;cursor:pointer}.li-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:12px}.li-icon--slate{background:#f1f5f9;color:#475569}.li-icon--amber{background:#fef3c7;color:#b45309}.li-icon--orange{background:#ffedd5;color:#c2410c}.li-icon--red{background:#fee2e2;color:#b91c1c}.li-icon--blue{background:#dbeafe;color:#1d4ed8}.li-icon--green{background:#dcfce7;color:#15803d}.li-icon--purple{background:#f3e8ff;color:#7e22ce}.li-icon--teal{background:#ccfbf1;color:#0f766e}.li-body{flex:1;min-width:0;cursor:pointer;display:flex;flex-direction:column;gap:6px}.li-title-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.li-title{font-size:.9375rem;font-weight:600;line-height:1.4;letter-spacing:-.005em;color:var(--text-primary, #0f172a)}.li-row--wrap .li-title{min-width:0;word-break:break-word;overflow-wrap:anywhere}.li-details{display:flex;flex-direction:column;gap:3px;font-size:.8125rem;line-height:1.4;color:var(--text-secondary, #64748b)}.li-detail{display:flex;align-items:center;gap:6px;min-width:0}.li-detail-icon{flex:0 0 auto;color:#94a3b8}.li-detail--warning,.li-detail--warning .li-detail-icon{color:#b45309}.li-detail--danger,.li-detail--danger .li-detail-icon{color:#b91c1c}.li-row--wrap .li-detail-text{min-width:0;word-break:break-word;overflow-wrap:anywhere}\n"],
28592
29372
  dependencies: [{
28593
29373
  kind: "component",
28594
29374
  type: BadgeComponent,
28595
29375
  selector: "ui-badge",
28596
- inputs: ["label", "variant"]
29376
+ inputs: [
29377
+ "label",
29378
+ "variant",
29379
+ "color"
29380
+ ]
28597
29381
  }, {
28598
29382
  kind: "directive",
28599
29383
  type: NgTemplateOutlet,
@@ -28632,7 +29416,7 @@ i0.ɵɵngDeclareClassMetadata({
28632
29416
  </ng-template>
28633
29417
  <ng-template #content>
28634
29418
  <div class="li-title-row">
28635
- <span class="li-title">{{ title() }}</span>
29419
+ <span class="li-title" data-testid="list-item-title">{{ title() }}</span>
28636
29420
  @if (badge() && (checked() || alwaysShowBadge())) {
28637
29421
  <ui-badge [label]="badge()!" [variant]="badgeVariant()" />
28638
29422
  }
@@ -28644,7 +29428,7 @@ i0.ɵɵngDeclareClassMetadata({
28644
29428
  @if (detail.d) {
28645
29429
  <svg class="li-detail-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="detail.d" /></svg>
28646
29430
  }
28647
- <span class="li-detail-text">{{ detail.text }}</span>
29431
+ <span class="li-detail-text" data-testid="list-item-detail">{{ detail.text }}</span>
28648
29432
  </span>
28649
29433
  }
28650
29434
  </div>
@@ -28652,45 +29436,57 @@ i0.ɵɵngDeclareClassMetadata({
28652
29436
  </ng-template>
28653
29437
 
28654
29438
  <div class="li-row" [class.li-row--highlighted]="highlighted()" [class.li-row--pressable]="pressable()"
28655
- [attr.role]="pressable() ? 'button' : null" [attr.tabindex]="pressable() ? 0 : null"
29439
+ [class.li-row--disabled]="disabled()" [class.li-row--busy]="busy()"
29440
+ [attr.role]="pressable() ? 'button' : null" [attr.tabindex]="pressable() && !disabled() ? 0 : null"
29441
+ [attr.aria-disabled]="disabled() && pressable() ? 'true' : null" [attr.aria-busy]="busy() ? 'true' : null"
28656
29442
  (click)="onRowClick($event)" (keydown.enter)="onRowKey($event)" (keydown.space)="onRowKey($event)" [class.li-row--static]="!interactive()" [class.li-row--wrap]="wrapText() || !interactive()">
28657
29443
 
28658
- @if (!interactive()) {
28659
- <ng-container [ngTemplateOutlet]="tile" />
28660
- <div class="li-body li-body--static">
28661
- <ng-container [ngTemplateOutlet]="content" />
28662
- </div>
28663
- } @else {
28664
- @if (leading() === 'radio') {
29444
+ @if (interactive() && leading() === 'radio') {
28665
29445
  <input
28666
29446
  type="radio"
28667
29447
  class="li-input"
28668
29448
  [id]="inputId()"
28669
29449
  [name]="inputName()"
28670
29450
  [checked]="checked()"
28671
- (change)="select.emit()"
29451
+ [disabled]="disabled()"
29452
+ (click)="onInputClick($event)"
29453
+ (keydown)="onInputKey($event)"
29454
+ (change)="onInputChange($event)"
28672
29455
  />
28673
- } @else if (leading() === 'checkbox') {
29456
+ } @else if (interactive() && leading() === 'checkbox') {
28674
29457
  <input
28675
29458
  type="checkbox"
28676
29459
  class="li-input"
28677
29460
  [id]="inputId()"
28678
29461
  [checked]="checked()"
28679
- (change)="select.emit()"
29462
+ [disabled]="disabled()"
29463
+ (click)="onInputClick($event)"
29464
+ (keydown)="onInputKey($event)"
29465
+ (change)="onInputChange($event)"
28680
29466
  />
28681
29467
  }
28682
29468
 
28683
- <ng-container [ngTemplateOutlet]="tile" />
28684
- <label class="li-body" [attr.for]="inputId() || null">
28685
- <ng-container [ngTemplateOutlet]="content" />
28686
- </label>
29469
+ <!-- Leading image slot (library source 2026-11-04): a product photo in front of the text. Replaces the icon tile. -->
29470
+ <ng-content select="[list-item-image]" />
29471
+ @if (!hasImage()) { <ng-container [ngTemplateOutlet]="tile" /> }
29472
+ @if (!interactive()) {
29473
+ <div class="li-body li-body--static">
29474
+ <ng-container [ngTemplateOutlet]="content" />
29475
+ </div>
29476
+ } @else {
29477
+ <label class="li-body" [attr.for]="inputId() || null">
29478
+ <ng-container [ngTemplateOutlet]="content" />
29479
+ </label>
28687
29480
  }
28688
29481
 
29482
+ @if (busy()) {
29483
+ <span class="li-spinner" aria-hidden="true"></span>
29484
+ }
28689
29485
  <ng-content select="[list-item-action], [li-action]" />
28690
29486
 
28691
29487
  </div>
28692
29488
  `,
28693
- styles: ["ui-list-item{display:block}ui-list-item.li-bordered{border:1px solid var(--border, #e2e8f0);border-radius:12px;overflow:hidden;background:var(--surface, #fff);box-shadow:0 1px 2px #0f172a0a;margin-bottom:8px;transition:border-color .15s ease,box-shadow .15s ease}ui-list-item.li-bordered:last-child{margin-bottom:0}ui-list-item.li-bordered:hover{border-color:#cbd5e1;box-shadow:0 2px 6px #0f172a12}@media(prefers-reduced-motion:reduce){ui-list-item.li-bordered{transition:none}}.li-row{display:flex;align-items:flex-start;gap:14px;padding:12px 16px;border-bottom:1px solid var(--border, #e2e8f0);transition:background .12s}.li-row:last-child{border-bottom:none}.li-row:hover{background:var(--surface-hover, #f8fafc)}ui-list-item.li-bordered .li-row{border-bottom:none;padding:14px 16px}.li-row.li-row--highlighted{background:#f0fdf4}.li-row.li-row--highlighted:hover{background:#dcfce7}.li-row.li-row--static:hover{background:transparent}.li-row.li-row--static.li-row--highlighted,.li-row.li-row--static.li-row--highlighted:hover{background:#f0fdf4}.li-row.li-row--pressable{cursor:pointer}.li-row.li-row--pressable:focus-visible{outline:2px solid var(--primary, #2563eb);outline-offset:-2px}.li-body.li-body--static{cursor:default}.li-row [list-item-action],.li-row [li-action]{flex-shrink:0;align-self:center}.li-input{margin-top:3px;flex-shrink:0;accent-color:#16a34a;width:1rem;height:1rem;cursor:pointer}.li-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:12px}.li-icon--slate{background:#f1f5f9;color:#475569}.li-icon--amber{background:#fef3c7;color:#b45309}.li-icon--orange{background:#ffedd5;color:#c2410c}.li-icon--red{background:#fee2e2;color:#b91c1c}.li-icon--blue{background:#dbeafe;color:#1d4ed8}.li-icon--green{background:#dcfce7;color:#15803d}.li-icon--purple{background:#f3e8ff;color:#7e22ce}.li-icon--teal{background:#ccfbf1;color:#0f766e}.li-body{flex:1;min-width:0;cursor:pointer;display:flex;flex-direction:column;gap:6px}.li-title-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.li-title{font-size:.9375rem;font-weight:600;line-height:1.4;letter-spacing:-.005em;color:var(--text-primary, #0f172a)}.li-row--wrap .li-title{min-width:0;word-break:break-word;overflow-wrap:anywhere}.li-details{display:flex;flex-direction:column;gap:3px;font-size:.8125rem;line-height:1.4;color:var(--text-secondary, #64748b)}.li-detail{display:flex;align-items:center;gap:6px;min-width:0}.li-detail-icon{flex:0 0 auto;color:#94a3b8}.li-detail--warning,.li-detail--warning .li-detail-icon{color:#b45309}.li-detail--danger,.li-detail--danger .li-detail-icon{color:#b91c1c}.li-row--wrap .li-detail-text{min-width:0;word-break:break-word;overflow-wrap:anywhere}\n"]
29489
+ styles: ["ui-list-item{display:block}ui-list-item.li-bordered{border:1px solid var(--border, #e2e8f0);border-radius:12px;overflow:hidden;background:var(--surface, #fff);box-shadow:0 1px 2px #0f172a0a;margin-bottom:8px;transition:border-color .15s ease,box-shadow .15s ease}ui-list-item.li-bordered:last-child{margin-bottom:0}ui-list-item.li-bordered:hover{border-color:#cbd5e1;box-shadow:0 2px 6px #0f172a12}@media(prefers-reduced-motion:reduce){ui-list-item.li-bordered{transition:none}}.li-row{display:flex;align-items:flex-start;gap:14px;padding:12px 16px;border-bottom:1px solid var(--border, #e2e8f0);transition:background .12s}.li-row:last-child{border-bottom:none}.li-row:hover{background:var(--surface-hover, #f8fafc)}ui-list-item.li-bordered .li-row{border-bottom:none;padding:14px 16px}.li-row.li-row--highlighted{background:#f0fdf4}.li-row.li-row--highlighted:hover{background:#dcfce7}.li-row.li-row--static:hover{background:transparent}.li-row.li-row--static.li-row--highlighted,.li-row.li-row--static.li-row--highlighted:hover{background:#f0fdf4}.li-row.li-row--pressable{cursor:pointer}.li-row.li-row--pressable:focus-visible{outline:2px solid var(--primary, #2563eb);outline-offset:-2px}.li-body.li-body--static{cursor:default}.li-row [list-item-action],.li-row [li-action]{flex-shrink:0;align-self:center}.li-row>[list-item-image]{flex:0 0 auto;align-self:center}.li-row.li-row--disabled,.li-row.li-row--disabled:hover{opacity:.72;cursor:not-allowed;background-color:var(--surface-muted, #f8fafc);background-image:repeating-linear-gradient(135deg,transparent 0,transparent 6px,rgba(100,116,139,.1) 6px,rgba(100,116,139,.1) 12px)}.li-row.li-row--disabled .li-body,.li-row.li-row--disabled .li-input,.li-row.li-row--disabled.li-row--pressable{cursor:not-allowed}ui-list-item.li-disabled.li-bordered,ui-list-item.li-disabled.li-bordered:hover{border-style:dashed;box-shadow:none}.li-row.li-row--busy,.li-row.li-row--busy .li-body{cursor:progress}.li-spinner{flex:0 0 auto;align-self:center;box-sizing:border-box;width:16px;height:16px;border:2px solid rgba(100,116,139,.3);border-top-color:var(--text-secondary, #475569);border-radius:50%;animation:li-spin .6s linear infinite}@keyframes li-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.li-spinner{animation-duration:2s}}.li-input{margin-top:3px;flex-shrink:0;accent-color:#16a34a;width:1rem;height:1rem;cursor:pointer}.li-icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:12px}.li-icon--slate{background:#f1f5f9;color:#475569}.li-icon--amber{background:#fef3c7;color:#b45309}.li-icon--orange{background:#ffedd5;color:#c2410c}.li-icon--red{background:#fee2e2;color:#b91c1c}.li-icon--blue{background:#dbeafe;color:#1d4ed8}.li-icon--green{background:#dcfce7;color:#15803d}.li-icon--purple{background:#f3e8ff;color:#7e22ce}.li-icon--teal{background:#ccfbf1;color:#0f766e}.li-body{flex:1;min-width:0;cursor:pointer;display:flex;flex-direction:column;gap:6px}.li-title-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.li-title{font-size:.9375rem;font-weight:600;line-height:1.4;letter-spacing:-.005em;color:var(--text-primary, #0f172a)}.li-row--wrap .li-title{min-width:0;word-break:break-word;overflow-wrap:anywhere}.li-details{display:flex;flex-direction:column;gap:3px;font-size:.8125rem;line-height:1.4;color:var(--text-secondary, #64748b)}.li-detail{display:flex;align-items:center;gap:6px;min-width:0}.li-detail-icon{flex:0 0 auto;color:#94a3b8}.li-detail--warning,.li-detail--warning .li-detail-icon{color:#b45309}.li-detail--danger,.li-detail--danger .li-detail-icon{color:#b91c1c}.li-row--wrap .li-detail-text{min-width:0;word-break:break-word;overflow-wrap:anywhere}\n"]
28694
29490
  }]
28695
29491
  }],
28696
29492
  propDecorators: {
@@ -28766,10 +29562,30 @@ i0.ɵɵngDeclareClassMetadata({
28766
29562
  required: false
28767
29563
  }]
28768
29564
  }],
29565
+ disabled: [{
29566
+ type: i0.Input,
29567
+ args: [{
29568
+ isSignal: true,
29569
+ alias: "disabled",
29570
+ required: false
29571
+ }]
29572
+ }],
29573
+ busy: [{
29574
+ type: i0.Input,
29575
+ args: [{
29576
+ isSignal: true,
29577
+ alias: "busy",
29578
+ required: false
29579
+ }]
29580
+ }],
28769
29581
  _borderedClass: [{
28770
29582
  type: HostBinding,
28771
29583
  args: ["class.li-bordered"]
28772
29584
  }],
29585
+ _disabledClass: [{
29586
+ type: HostBinding,
29587
+ args: ["class.li-disabled"]
29588
+ }],
28773
29589
  title: [{
28774
29590
  type: i0.Input,
28775
29591
  args: [{
@@ -29107,7 +29923,11 @@ var CardListItemComponent = class CardListItemComponent {
29107
29923
  kind: "component",
29108
29924
  type: BadgeComponent,
29109
29925
  selector: "ui-badge",
29110
- inputs: ["label", "variant"]
29926
+ inputs: [
29927
+ "label",
29928
+ "variant",
29929
+ "color"
29930
+ ]
29111
29931
  }, {
29112
29932
  kind: "directive",
29113
29933
  type: TooltipDirective,
@@ -30066,6 +30886,7 @@ var ListComponent = class ListComponent {
30066
30886
  this.injector = inject(Injector);
30067
30887
  this.items = input([], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
30068
30888
  this.ordered = input(false, ...ngDevMode ? [{ debugName: "ordered" }] : /* istanbul ignore next */ []);
30889
+ this.bulleted = input(false, ...ngDevMode ? [{ debugName: "bulleted" }] : /* istanbul ignore next */ []);
30069
30890
  this.layout = input("list", ...ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []);
30070
30891
  this.gridMin = input(130, ...ngDevMode ? [{ debugName: "gridMin" }] : /* istanbul ignore next */ []);
30071
30892
  this.gap = input(void 0, ...ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []);
@@ -30361,6 +31182,13 @@ var ListComponent = class ListComponent {
30361
31182
  isRequired: false,
30362
31183
  transformFunction: null
30363
31184
  },
31185
+ bulleted: {
31186
+ classPropertyName: "bulleted",
31187
+ publicName: "bulleted",
31188
+ isSignal: true,
31189
+ isRequired: false,
31190
+ transformFunction: null
31191
+ },
30364
31192
  layout: {
30365
31193
  classPropertyName: "layout",
30366
31194
  publicName: "layout",
@@ -30545,7 +31373,7 @@ var ListComponent = class ListComponent {
30545
31373
  <ng-container [ngTemplateOutlet]="rowsTpl" />
30546
31374
  </ol>
30547
31375
  } @else {
30548
- <ul class="ul-list ul-list--unordered" role="list" [class.ul-list--grid]="isGrid()"
31376
+ <ul class="ul-list ul-list--unordered" role="list" [class.ul-list--grid]="isGrid()" [class.ul-list--bulleted]="bulleted() && !isGrid()"
30549
31377
  [style.--ul-gap]="gapCss()" [style.--ul-min.px]="isGrid() ? gridMin() : null"
30550
31378
  [attr.aria-label]="ariaLabel() || null" [attr.aria-labelledby]="ariaLabelledby() || null"
30551
31379
  (keydown)="onKeydown($event)" (click)="onClick($event)" (focusout)="onFocusOut($event)"
@@ -30565,7 +31393,7 @@ var ListComponent = class ListComponent {
30565
31393
  }
30566
31394
  `,
30567
31395
  isInline: true,
30568
- styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row{position:relative;padding-inline-end:0}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row>.ul-chevron{position:absolute;inset-inline-end:12px;top:50%;margin-top:-10px;pointer-events:none}.ul-item--nav>.ul-row>.ul-content>ui-list-item.li-bordered .li-row{padding-inline-end:40px}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"],
31396
+ styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--unordered.ul-list--bulleted{list-style:disc;-webkit-padding-start:1.25rem;padding-inline-start:1.25rem}.ul-list--bulleted>.ul-item::marker{color:var(--text-secondary, #64748b)}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row{position:relative;padding-inline-end:0}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row>.ul-chevron{position:absolute;inset-inline-end:12px;top:50%;margin-top:-10px;pointer-events:none}.ul-item--nav>.ul-row>.ul-content>ui-list-item.li-bordered .li-row{padding-inline-end:40px}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"],
30569
31397
  dependencies: [{
30570
31398
  kind: "directive",
30571
31399
  type: NgTemplateOutlet,
@@ -30674,7 +31502,7 @@ i0.ɵɵngDeclareClassMetadata({
30674
31502
  <ng-container [ngTemplateOutlet]="rowsTpl" />
30675
31503
  </ol>
30676
31504
  } @else {
30677
- <ul class="ul-list ul-list--unordered" role="list" [class.ul-list--grid]="isGrid()"
31505
+ <ul class="ul-list ul-list--unordered" role="list" [class.ul-list--grid]="isGrid()" [class.ul-list--bulleted]="bulleted() && !isGrid()"
30678
31506
  [style.--ul-gap]="gapCss()" [style.--ul-min.px]="isGrid() ? gridMin() : null"
30679
31507
  [attr.aria-label]="ariaLabel() || null" [attr.aria-labelledby]="ariaLabelledby() || null"
30680
31508
  (keydown)="onKeydown($event)" (click)="onClick($event)" (focusout)="onFocusOut($event)"
@@ -30693,7 +31521,7 @@ i0.ɵɵngDeclareClassMetadata({
30693
31521
  <div class="ul-sr" role="status" aria-live="polite" aria-atomic="true">{{ announcement() }}</div>
30694
31522
  }
30695
31523
  `,
30696
- styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row{position:relative;padding-inline-end:0}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row>.ul-chevron{position:absolute;inset-inline-end:12px;top:50%;margin-top:-10px;pointer-events:none}.ul-item--nav>.ul-row>.ul-content>ui-list-item.li-bordered .li-row{padding-inline-end:40px}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"]
31524
+ styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--unordered.ul-list--bulleted{list-style:disc;-webkit-padding-start:1.25rem;padding-inline-start:1.25rem}.ul-list--bulleted>.ul-item::marker{color:var(--text-secondary, #64748b)}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row{position:relative;padding-inline-end:0}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row>.ul-chevron{position:absolute;inset-inline-end:12px;top:50%;margin-top:-10px;pointer-events:none}.ul-item--nav>.ul-row>.ul-content>ui-list-item.li-bordered .li-row{padding-inline-end:40px}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"]
30697
31525
  }]
30698
31526
  }],
30699
31527
  propDecorators: {
@@ -30713,6 +31541,14 @@ i0.ɵɵngDeclareClassMetadata({
30713
31541
  required: false
30714
31542
  }]
30715
31543
  }],
31544
+ bulleted: [{
31545
+ type: i0.Input,
31546
+ args: [{
31547
+ isSignal: true,
31548
+ alias: "bulleted",
31549
+ required: false
31550
+ }]
31551
+ }],
30716
31552
  layout: [{
30717
31553
  type: i0.Input,
30718
31554
  args: [{
@@ -30986,12 +31822,12 @@ var BarRowComponent = class BarRowComponent {
30986
31822
  ngImport: i0,
30987
31823
  template: `
30988
31824
  <div class="br">
30989
- <span class="br-label" [attr.id]="labelId">{{ label() }}</span>
31825
+ <span class="br-label" data-testid="bar-row-label" [attr.id]="labelId">{{ label() }}</span>
30990
31826
  <ui-progress-bar class="br-bar" [value]="barValue()" [max]="barMax()" [variant]="variant()"
30991
31827
  [ariaLabelledby]="label() ? labelId : ''" [valueText]="effectiveValueText()" />
30992
31828
  <span class="br-value">
30993
- <span class="br-count">{{ countText() }}</span>
30994
- @if (share()) { <span class="br-share">{{ share() }}</span> }
31829
+ <span class="br-count" data-testid="bar-row-count">{{ countText() }}</span>
31830
+ @if (share()) { <span class="br-share" data-testid="bar-row-share">{{ share() }}</span> }
30995
31831
  </span>
30996
31832
  </div>
30997
31833
  `,
@@ -31031,12 +31867,12 @@ i0.ɵɵngDeclareClassMetadata({
31031
31867
  changeDetection: ChangeDetectionStrategy.OnPush,
31032
31868
  template: `
31033
31869
  <div class="br">
31034
- <span class="br-label" [attr.id]="labelId">{{ label() }}</span>
31870
+ <span class="br-label" data-testid="bar-row-label" [attr.id]="labelId">{{ label() }}</span>
31035
31871
  <ui-progress-bar class="br-bar" [value]="barValue()" [max]="barMax()" [variant]="variant()"
31036
31872
  [ariaLabelledby]="label() ? labelId : ''" [valueText]="effectiveValueText()" />
31037
31873
  <span class="br-value">
31038
- <span class="br-count">{{ countText() }}</span>
31039
- @if (share()) { <span class="br-share">{{ share() }}</span> }
31874
+ <span class="br-count" data-testid="bar-row-count">{{ countText() }}</span>
31875
+ @if (share()) { <span class="br-share" data-testid="bar-row-share">{{ share() }}</span> }
31040
31876
  </span>
31041
31877
  </div>
31042
31878
  `,
@@ -32218,7 +33054,11 @@ var PanelInfoListComponent = class PanelInfoListComponent {
32218
33054
  kind: "component",
32219
33055
  type: BadgeComponent,
32220
33056
  selector: "ui-badge",
32221
- inputs: ["label", "variant"]
33057
+ inputs: [
33058
+ "label",
33059
+ "variant",
33060
+ "color"
33061
+ ]
32222
33062
  },
32223
33063
  {
32224
33064
  kind: "component",
@@ -34383,48 +35223,6 @@ i0.ɵɵngDeclareClassMetadata({
34383
35223
  }]
34384
35224
  }
34385
35225
  });
34386
- var HintComponent = class HintComponent {
34387
- static {
34388
- this.ɵfac = i0.ɵɵngDeclareFactory({
34389
- minVersion: "12.0.0",
34390
- version: "22.2.2",
34391
- ngImport: i0,
34392
- type: HintComponent,
34393
- deps: [],
34394
- target: i0.ɵɵFactoryTarget.Component
34395
- });
34396
- }
34397
- static {
34398
- this.ɵcmp = i0.ɵɵngDeclareComponent({
34399
- minVersion: "14.0.0",
34400
- version: "22.2.2",
34401
- type: HintComponent,
34402
- isStandalone: true,
34403
- selector: "ui-hint",
34404
- ngImport: i0,
34405
- template: `<p class="hint"><ng-content /></p>`,
34406
- isInline: true,
34407
- styles: [":host{display:block}.hint{font-size:.75rem;line-height:1.4;color:#64748b;margin:0}\n"],
34408
- changeDetection: i0.ChangeDetectionStrategy.OnPush
34409
- });
34410
- }
34411
- };
34412
- i0.ɵɵngDeclareClassMetadata({
34413
- minVersion: "12.0.0",
34414
- version: "22.2.2",
34415
- ngImport: i0,
34416
- type: HintComponent,
34417
- decorators: [{
34418
- type: Component,
34419
- args: [{
34420
- selector: "ui-hint",
34421
- standalone: true,
34422
- changeDetection: ChangeDetectionStrategy.OnPush,
34423
- template: `<p class="hint"><ng-content /></p>`,
34424
- styles: [":host{display:block}.hint{font-size:.75rem;line-height:1.4;color:#64748b;margin:0}\n"]
34425
- }]
34426
- }]
34427
- });
34428
35226
  var TimelineComponent = class TimelineComponent {
34429
35227
  constructor() {
34430
35228
  this.items = input([], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
@@ -34681,7 +35479,11 @@ var TimelineComponent = class TimelineComponent {
34681
35479
  kind: "component",
34682
35480
  type: BadgeComponent,
34683
35481
  selector: "ui-badge",
34684
- inputs: ["label", "variant"]
35482
+ inputs: [
35483
+ "label",
35484
+ "variant",
35485
+ "color"
35486
+ ]
34685
35487
  },
34686
35488
  {
34687
35489
  kind: "component",
@@ -35645,6 +36447,7 @@ var AddressInputComponent = class AddressInputComponent {
35645
36447
  "inputName",
35646
36448
  "placeholder",
35647
36449
  "prefix",
36450
+ "leadingIcon",
35648
36451
  "revealable",
35649
36452
  "passwordRequirements",
35650
36453
  "passwordRules",
@@ -35682,6 +36485,7 @@ var AddressInputComponent = class AddressInputComponent {
35682
36485
  inputs: [
35683
36486
  "label",
35684
36487
  "ariaLabel",
36488
+ "labelHidden",
35685
36489
  "inputName",
35686
36490
  "placeholder",
35687
36491
  "options",
@@ -36093,8 +36897,10 @@ var ImageComponent = class ImageComponent {
36093
36897
  this.placeholder = input(true, ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
36094
36898
  this.priority = input(false, ...ngDevMode ? [{ debugName: "priority" }] : /* istanbul ignore next */ []);
36095
36899
  this.retryKey = input(null, ...ngDevMode ? [{ debugName: "retryKey" }] : /* istanbul ignore next */ []);
36900
+ this.interactive = input(false, ...ngDevMode ? [{ debugName: "interactive" }] : /* istanbul ignore next */ []);
36096
36901
  this.loaded = output();
36097
36902
  this.failed = output();
36903
+ this.activate = output();
36098
36904
  this._failed = signal(false, ...ngDevMode ? [{ debugName: "_failed" }] : /* istanbul ignore next */ []);
36099
36905
  this._url = computed(() => this.src()?.trim() || null, ...ngDevMode ? [{ debugName: "_url" }] : /* istanbul ignore next */ []);
36100
36906
  this.radiusCss = computed(() => RADIUS_PX[this.radius()] ?? "0", ...ngDevMode ? [{ debugName: "radiusCss" }] : /* istanbul ignore next */ []);
@@ -36113,6 +36919,14 @@ var ImageComponent = class ImageComponent {
36113
36919
  this._failed.set(true);
36114
36920
  this.failed.emit();
36115
36921
  }
36922
+ onActivate() {
36923
+ if (this.interactive()) this.activate.emit();
36924
+ }
36925
+ onKey(event) {
36926
+ if (!this.interactive()) return;
36927
+ event.preventDefault();
36928
+ this.activate.emit();
36929
+ }
36116
36930
  static {
36117
36931
  this.ɵfac = i0.ɵɵngDeclareFactory({
36118
36932
  minVersion: "12.0.0",
@@ -36235,16 +37049,35 @@ var ImageComponent = class ImageComponent {
36235
37049
  isSignal: true,
36236
37050
  isRequired: false,
36237
37051
  transformFunction: null
37052
+ },
37053
+ interactive: {
37054
+ classPropertyName: "interactive",
37055
+ publicName: "interactive",
37056
+ isSignal: true,
37057
+ isRequired: false,
37058
+ transformFunction: null
36238
37059
  }
36239
37060
  },
36240
37061
  outputs: {
36241
37062
  loaded: "loaded",
36242
- failed: "failed"
37063
+ failed: "failed",
37064
+ activate: "activate"
37065
+ },
37066
+ host: {
37067
+ listeners: {
37068
+ "click": "onActivate()",
37069
+ "keydown.enter": "onKey($event)",
37070
+ "keydown.space": "onKey($event)"
37071
+ },
37072
+ properties: {
37073
+ "style.text-align": "align()",
37074
+ "class.im-block": "isBlock()",
37075
+ "class.im-interactive": "interactive()",
37076
+ "attr.role": "interactive() ? 'button' : null",
37077
+ "attr.tabindex": "interactive() ? 0 : null",
37078
+ "attr.aria-label": "interactive() ? (alt() || null) : null"
37079
+ }
36243
37080
  },
36244
- host: { properties: {
36245
- "style.text-align": "align()",
36246
- "class.im-block": "isBlock()"
36247
- } },
36248
37081
  ngImport: i0,
36249
37082
  template: `
36250
37083
  @if (_url() && !_failed()) {
@@ -36262,7 +37095,7 @@ var ImageComponent = class ImageComponent {
36262
37095
  }
36263
37096
  `,
36264
37097
  isInline: true,
36265
- styles: [":host{display:inline-block;max-width:100%;line-height:0}:host(.im-block){display:block}.im-img{display:inline-block;max-width:100%;height:auto;vertical-align:top}.im-bordered{border:1px solid #e2e8f0;box-sizing:border-box}.im-ph{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:48px;min-height:48px;background:#f1f5f9;color:#94a3b8;vertical-align:top}.im-ph svg{width:32px;height:32px;max-width:55%;max-height:55%}\n"],
37098
+ styles: [":host{display:inline-block;max-width:100%;line-height:0}:host(.im-block){display:block}:host(.im-interactive){cursor:pointer}:host(.im-interactive:focus-visible){outline:2px solid var(--ui-focus, #3b82f6);outline-offset:2px}.im-img{display:inline-block;max-width:100%;height:auto;vertical-align:top}.im-bordered{border:1px solid #e2e8f0;box-sizing:border-box}.im-ph{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:48px;min-height:48px;background:#f1f5f9;color:#94a3b8;vertical-align:top}.im-ph svg{width:32px;height:32px;max-width:55%;max-height:55%}\n"],
36266
37099
  changeDetection: i0.ChangeDetectionStrategy.OnPush
36267
37100
  });
36268
37101
  }
@@ -36280,7 +37113,14 @@ i0.ɵɵngDeclareClassMetadata({
36280
37113
  changeDetection: ChangeDetectionStrategy.OnPush,
36281
37114
  host: {
36282
37115
  "[style.text-align]": "align()",
36283
- "[class.im-block]": "isBlock()"
37116
+ "[class.im-block]": "isBlock()",
37117
+ "[class.im-interactive]": "interactive()",
37118
+ "[attr.role]": "interactive() ? 'button' : null",
37119
+ "[attr.tabindex]": "interactive() ? 0 : null",
37120
+ "[attr.aria-label]": "interactive() ? (alt() || null) : null",
37121
+ "(click)": "onActivate()",
37122
+ "(keydown.enter)": "onKey($event)",
37123
+ "(keydown.space)": "onKey($event)"
36284
37124
  },
36285
37125
  template: `
36286
37126
  @if (_url() && !_failed()) {
@@ -36297,7 +37137,7 @@ i0.ɵɵngDeclareClassMetadata({
36297
37137
  </span>
36298
37138
  }
36299
37139
  `,
36300
- styles: [":host{display:inline-block;max-width:100%;line-height:0}:host(.im-block){display:block}.im-img{display:inline-block;max-width:100%;height:auto;vertical-align:top}.im-bordered{border:1px solid #e2e8f0;box-sizing:border-box}.im-ph{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:48px;min-height:48px;background:#f1f5f9;color:#94a3b8;vertical-align:top}.im-ph svg{width:32px;height:32px;max-width:55%;max-height:55%}\n"]
37140
+ styles: [":host{display:inline-block;max-width:100%;line-height:0}:host(.im-block){display:block}:host(.im-interactive){cursor:pointer}:host(.im-interactive:focus-visible){outline:2px solid var(--ui-focus, #3b82f6);outline-offset:2px}.im-img{display:inline-block;max-width:100%;height:auto;vertical-align:top}.im-bordered{border:1px solid #e2e8f0;box-sizing:border-box}.im-ph{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:48px;min-height:48px;background:#f1f5f9;color:#94a3b8;vertical-align:top}.im-ph svg{width:32px;height:32px;max-width:55%;max-height:55%}\n"]
36301
37141
  }]
36302
37142
  }],
36303
37143
  ctorParameters: () => [],
@@ -36422,6 +37262,14 @@ i0.ɵɵngDeclareClassMetadata({
36422
37262
  required: false
36423
37263
  }]
36424
37264
  }],
37265
+ interactive: [{
37266
+ type: i0.Input,
37267
+ args: [{
37268
+ isSignal: true,
37269
+ alias: "interactive",
37270
+ required: false
37271
+ }]
37272
+ }],
36425
37273
  loaded: [{
36426
37274
  type: i0.Output,
36427
37275
  args: ["loaded"]
@@ -36429,6 +37277,10 @@ i0.ɵɵngDeclareClassMetadata({
36429
37277
  failed: [{
36430
37278
  type: i0.Output,
36431
37279
  args: ["failed"]
37280
+ }],
37281
+ activate: [{
37282
+ type: i0.Output,
37283
+ args: ["activate"]
36432
37284
  }]
36433
37285
  }
36434
37286
  });
@@ -36773,9 +37625,14 @@ var ImageGalleryComponent = class ImageGalleryComponent {
36773
37625
  "align",
36774
37626
  "placeholder",
36775
37627
  "priority",
36776
- "retryKey"
37628
+ "retryKey",
37629
+ "interactive"
36777
37630
  ],
36778
- outputs: ["loaded", "failed"]
37631
+ outputs: [
37632
+ "loaded",
37633
+ "failed",
37634
+ "activate"
37635
+ ]
36779
37636
  },
36780
37637
  {
36781
37638
  kind: "component",
@@ -36943,6 +37800,8 @@ var KpiCardComponent = class KpiCardComponent {
36943
37800
  this.highlight = input(false, ...ngDevMode ? [{ debugName: "highlight" }] : /* istanbul ignore next */ []);
36944
37801
  this.clickable = input(false, ...ngDevMode ? [{ debugName: "clickable" }] : /* istanbul ignore next */ []);
36945
37802
  this.valueColor = input("default", ...ngDevMode ? [{ debugName: "valueColor" }] : /* istanbul ignore next */ []);
37803
+ this.loading = input(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
37804
+ this.loadingLabel = input("Loading", ...ngDevMode ? [{ debugName: "loadingLabel" }] : /* istanbul ignore next */ []);
36946
37805
  this.background = input("", ...ngDevMode ? [{ debugName: "background" }] : /* istanbul ignore next */ []);
36947
37806
  this.progress = input(null, ...ngDevMode ? [{ debugName: "progress" }] : /* istanbul ignore next */ []);
36948
37807
  this.progressMax = input(100, ...ngDevMode ? [{ debugName: "progressMax" }] : /* istanbul ignore next */ []);
@@ -37036,6 +37895,20 @@ var KpiCardComponent = class KpiCardComponent {
37036
37895
  isRequired: false,
37037
37896
  transformFunction: null
37038
37897
  },
37898
+ loading: {
37899
+ classPropertyName: "loading",
37900
+ publicName: "loading",
37901
+ isSignal: true,
37902
+ isRequired: false,
37903
+ transformFunction: null
37904
+ },
37905
+ loadingLabel: {
37906
+ classPropertyName: "loadingLabel",
37907
+ publicName: "loadingLabel",
37908
+ isSignal: true,
37909
+ isRequired: false,
37910
+ transformFunction: null
37911
+ },
37039
37912
  background: {
37040
37913
  classPropertyName: "background",
37041
37914
  publicName: "background",
@@ -37100,6 +37973,7 @@ var KpiCardComponent = class KpiCardComponent {
37100
37973
  },
37101
37974
  properties: {
37102
37975
  "attr.role": "clickable() ? \"button\" : null",
37976
+ "attr.aria-busy": "loading() ? \"true\" : null",
37103
37977
  "attr.tabindex": "clickable() ? 0 : null"
37104
37978
  }
37105
37979
  },
@@ -37111,19 +37985,27 @@ var KpiCardComponent = class KpiCardComponent {
37111
37985
  }
37112
37986
  @if (hasProgress()) {
37113
37987
  <div class="kpi-top">
37114
- <span class="kpi-label">{{ label() }}</span>
37115
- <ui-progress-ring class="kpi-ring" [value]="progress()!" [max]="progressMax()" [size]="progressSize()" [strokeWidth]="progressStrokeWidth()"
37988
+ <span class="kpi-label" data-testid="kpi-label">{{ label() }}</span>
37989
+ <ui-progress-ring class="kpi-ring" [attr.aria-hidden]="loading() ? 'true' : null" [value]="progress()!" [max]="progressMax()" [size]="progressSize()" [strokeWidth]="progressStrokeWidth()"
37116
37990
  [variant]="progressVariant()" [ariaLabel]="progressAriaLabel() || (label() + ' progress')" [valueText]="progressValueText()" />
37117
37991
  </div>
37118
37992
  } @else {
37119
- <span class="kpi-label">{{ label() }}</span>
37993
+ <span class="kpi-label" data-testid="kpi-label">{{ label() }}</span>
37120
37994
  }
37121
- <span class="kpi-value"
37122
- [class.green-value]="highlight() || valueColor() === 'green'"
37123
- [class.blue-value]="valueColor() === 'blue'"
37124
- [class.red-value]="valueColor() === 'red'">{{ value() }}</span>
37125
- @if (subtitle()) {
37126
- <span class="kpi-subtitle">{{ subtitle() }}</span>
37995
+ @if (loading()) {
37996
+ <span class="kpi-value kpi-value--loading" aria-hidden="true" data-testid="kpi-value-placeholder"><span class="kpi-bar"></span></span>
37997
+ <span class="kpi-loading-text">{{ loadingLabel() }}</span>
37998
+ @if (subtitle()) {
37999
+ <span class="kpi-subtitle kpi-subtitle--loading" aria-hidden="true" data-testid="kpi-subtitle-placeholder">{{ subtitle() }}</span>
38000
+ }
38001
+ } @else {
38002
+ <span class="kpi-value" data-testid="kpi-value"
38003
+ [class.green-value]="highlight() || valueColor() === 'green'"
38004
+ [class.blue-value]="valueColor() === 'blue'"
38005
+ [class.red-value]="valueColor() === 'red'">{{ value() }}</span>
38006
+ @if (subtitle()) {
38007
+ <span class="kpi-subtitle">{{ subtitle() }}</span>
38008
+ }
37127
38009
  }
37128
38010
  <ng-content select="[kpi-footer]" />
37129
38011
  @if (clickable()) {
@@ -37132,7 +38014,7 @@ var KpiCardComponent = class KpiCardComponent {
37132
38014
  </div>
37133
38015
  `,
37134
38016
  isInline: true,
37135
- 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-card.ring-corner .kpi-top{display:contents}.kpi-card.ring-corner .kpi-ring{position:absolute;top:12px;right:12px}.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-value.red-value{color:#dc2626}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}\n"],
38017
+ 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-card.ring-corner .kpi-top{display:contents}.kpi-card.ring-corner .kpi-ring{position:absolute;top:12px;right:12px}.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-value.red-value{color:#dc2626}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}.kpi-value--loading{display:flex;align-items:center;height:1.65rem}.kpi-bar{display:block;width:60%;max-width:8rem;height:1.1rem;border-radius:6px;background:#e2e8f0;animation:kpi-pulse 1.4s ease-in-out infinite}.kpi-subtitle--loading{align-self:flex-start;max-width:100%;border-radius:4px;background:#e2e8f0;color:transparent;-webkit-user-select:none;user-select:none;animation:kpi-pulse 1.4s ease-in-out infinite}.kpi-loading-text{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes kpi-pulse{50%{opacity:.55}}@media(prefers-reduced-motion:reduce){.kpi-bar,.kpi-subtitle--loading{animation:none}}\n"],
37136
38018
  dependencies: [{
37137
38019
  kind: "component",
37138
38020
  type: ProgressRingComponent,
@@ -37168,6 +38050,7 @@ i0.ɵɵngDeclareClassMetadata({
37168
38050
  changeDetection: ChangeDetectionStrategy.OnPush,
37169
38051
  host: {
37170
38052
  "[attr.role]": "clickable() ? \"button\" : null",
38053
+ "[attr.aria-busy]": "loading() ? \"true\" : null",
37171
38054
  "[attr.tabindex]": "clickable() ? 0 : null",
37172
38055
  "(keydown.enter)": "onActivateKey($event)",
37173
38056
  "(keydown.space)": "onActivateKey($event)"
@@ -37179,19 +38062,27 @@ i0.ɵɵngDeclareClassMetadata({
37179
38062
  }
37180
38063
  @if (hasProgress()) {
37181
38064
  <div class="kpi-top">
37182
- <span class="kpi-label">{{ label() }}</span>
37183
- <ui-progress-ring class="kpi-ring" [value]="progress()!" [max]="progressMax()" [size]="progressSize()" [strokeWidth]="progressStrokeWidth()"
38065
+ <span class="kpi-label" data-testid="kpi-label">{{ label() }}</span>
38066
+ <ui-progress-ring class="kpi-ring" [attr.aria-hidden]="loading() ? 'true' : null" [value]="progress()!" [max]="progressMax()" [size]="progressSize()" [strokeWidth]="progressStrokeWidth()"
37184
38067
  [variant]="progressVariant()" [ariaLabel]="progressAriaLabel() || (label() + ' progress')" [valueText]="progressValueText()" />
37185
38068
  </div>
37186
38069
  } @else {
37187
- <span class="kpi-label">{{ label() }}</span>
38070
+ <span class="kpi-label" data-testid="kpi-label">{{ label() }}</span>
37188
38071
  }
37189
- <span class="kpi-value"
37190
- [class.green-value]="highlight() || valueColor() === 'green'"
37191
- [class.blue-value]="valueColor() === 'blue'"
37192
- [class.red-value]="valueColor() === 'red'">{{ value() }}</span>
37193
- @if (subtitle()) {
37194
- <span class="kpi-subtitle">{{ subtitle() }}</span>
38072
+ @if (loading()) {
38073
+ <span class="kpi-value kpi-value--loading" aria-hidden="true" data-testid="kpi-value-placeholder"><span class="kpi-bar"></span></span>
38074
+ <span class="kpi-loading-text">{{ loadingLabel() }}</span>
38075
+ @if (subtitle()) {
38076
+ <span class="kpi-subtitle kpi-subtitle--loading" aria-hidden="true" data-testid="kpi-subtitle-placeholder">{{ subtitle() }}</span>
38077
+ }
38078
+ } @else {
38079
+ <span class="kpi-value" data-testid="kpi-value"
38080
+ [class.green-value]="highlight() || valueColor() === 'green'"
38081
+ [class.blue-value]="valueColor() === 'blue'"
38082
+ [class.red-value]="valueColor() === 'red'">{{ value() }}</span>
38083
+ @if (subtitle()) {
38084
+ <span class="kpi-subtitle">{{ subtitle() }}</span>
38085
+ }
37195
38086
  }
37196
38087
  <ng-content select="[kpi-footer]" />
37197
38088
  @if (clickable()) {
@@ -37199,7 +38090,7 @@ i0.ɵɵngDeclareClassMetadata({
37199
38090
  }
37200
38091
  </div>
37201
38092
  `,
37202
- 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-card.ring-corner .kpi-top{display:contents}.kpi-card.ring-corner .kpi-ring{position:absolute;top:12px;right:12px}.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-value.red-value{color:#dc2626}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}\n"]
38093
+ 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-card.ring-corner .kpi-top{display:contents}.kpi-card.ring-corner .kpi-ring{position:absolute;top:12px;right:12px}.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-value.red-value{color:#dc2626}.kpi-subtitle{font-size:.75rem;color:#64748b;margin-top:2px}.kpi-value--loading{display:flex;align-items:center;height:1.65rem}.kpi-bar{display:block;width:60%;max-width:8rem;height:1.1rem;border-radius:6px;background:#e2e8f0;animation:kpi-pulse 1.4s ease-in-out infinite}.kpi-subtitle--loading{align-self:flex-start;max-width:100%;border-radius:4px;background:#e2e8f0;color:transparent;-webkit-user-select:none;user-select:none;animation:kpi-pulse 1.4s ease-in-out infinite}.kpi-loading-text{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes kpi-pulse{50%{opacity:.55}}@media(prefers-reduced-motion:reduce){.kpi-bar,.kpi-subtitle--loading{animation:none}}\n"]
37203
38094
  }]
37204
38095
  }],
37205
38096
  propDecorators: {
@@ -37267,6 +38158,22 @@ i0.ɵɵngDeclareClassMetadata({
37267
38158
  required: false
37268
38159
  }]
37269
38160
  }],
38161
+ loading: [{
38162
+ type: i0.Input,
38163
+ args: [{
38164
+ isSignal: true,
38165
+ alias: "loading",
38166
+ required: false
38167
+ }]
38168
+ }],
38169
+ loadingLabel: [{
38170
+ type: i0.Input,
38171
+ args: [{
38172
+ isSignal: true,
38173
+ alias: "loadingLabel",
38174
+ required: false
38175
+ }]
38176
+ }],
37270
38177
  background: [{
37271
38178
  type: i0.Input,
37272
38179
  args: [{
@@ -37578,7 +38485,10 @@ var DateRangePickerComponent = class DateRangePickerComponent {
37578
38485
  "ariaLabel",
37579
38486
  "name",
37580
38487
  "noWrap",
37581
- "orientation"
38488
+ "orientation",
38489
+ "controlsPanels",
38490
+ "showDescription",
38491
+ "headingLevel"
37582
38492
  ],
37583
38493
  outputs: ["tabChange"]
37584
38494
  },
@@ -39282,19 +40192,19 @@ i0.ɵɵngDeclareClassMetadata({
39282
40192
  }]
39283
40193
  }
39284
40194
  });
39285
- var RadioMatrixComponent = class RadioMatrixComponent {
40195
+ var SwatchPickerComponent = class SwatchPickerComponent {
39286
40196
  get _name() {
39287
40197
  return this.name() || this._generatedName;
39288
40198
  }
39289
40199
  constructor() {
40200
+ this._el = inject(ElementRef);
39290
40201
  this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
39291
- this.rowHeader = input("", ...ngDevMode ? [{ debugName: "rowHeader" }] : /* istanbul ignore next */ []);
39292
- this.rows = input([], ...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
39293
- this.columns = input([], ...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
40202
+ this.options = input([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
39294
40203
  this.required = input(false, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
39295
40204
  this.hint = input("", ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
39296
40205
  this.error = input("", ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
39297
40206
  this.showErrors = input(false, ...ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []);
40207
+ this.columns = input(0, ...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
39298
40208
  this.name = input("", ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
39299
40209
  this._disabledInput = input(false, {
39300
40210
  ...ngDevMode ? { debugName: "_disabledInput" } : /* istanbul ignore next */ {},
@@ -39302,14 +40212,15 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39302
40212
  });
39303
40213
  this._cvaDisabled = signal(false, ...ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []);
39304
40214
  this.disabled = computed(() => this._disabledInput() || this._cvaDisabled(), ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
39305
- this._generatedName = `rm-${Math.random().toString(36).slice(2, 8)}`;
40215
+ this._generatedName = `sp-${Math.random().toString(36).slice(2, 8)}`;
39306
40216
  this._descId = `${this._generatedName}-desc`;
39307
- this._value = signal({}, ...ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []);
40217
+ this._value = signal("", ...ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []);
39308
40218
  this._reveal = createFieldReveal(this.showErrors);
39309
40219
  this._issue = computed(() => this._check(this._value()), ...ngDevMode ? [{ debugName: "_issue" }] : /* istanbul ignore next */ []);
39310
40220
  this.invalid = computed(() => !!this.error() || !!this._issue(), ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
39311
40221
  this.errorMessage = computed(() => this._issue()?.message ?? "", ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
39312
40222
  this.invalidChange = output();
40223
+ this.valueChange = output();
39313
40224
  this._activeError = computed(() => this.error() || (this._reveal.revealed() ? this.errorMessage() : ""), ...ngDevMode ? [{ debugName: "_activeError" }] : /* istanbul ignore next */ []);
39314
40225
  this._onValidatorChange = () => {};
39315
40226
  this._onChange = (_) => {};
@@ -39322,13 +40233,14 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39322
40233
  this._onValidatorChange();
39323
40234
  }
39324
40235
  validate(control) {
39325
- return issueToErrors(this._check(this._toRecord(control.value)));
40236
+ const v = control.value;
40237
+ return issueToErrors(this._check(v == null ? "" : String(v)));
39326
40238
  }
39327
40239
  registerOnValidatorChange(fn) {
39328
40240
  this._onValidatorChange = fn;
39329
40241
  }
39330
40242
  writeValue(val) {
39331
- this._value.set(this._toRecord(val));
40243
+ this._value.set(val ?? "");
39332
40244
  }
39333
40245
  registerOnChange(fn) {
39334
40246
  this._onChange = fn;
@@ -39339,18 +40251,21 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39339
40251
  setDisabledState(d) {
39340
40252
  this._cvaDisabled.set(d);
39341
40253
  }
39342
- onSelect(row, column) {
39343
- const next = {
39344
- ...this._value(),
39345
- [row]: column
39346
- };
39347
- this._value.set(next);
39348
- this._onChange(next);
40254
+ onSelect(value) {
40255
+ if (this.disabled()) return;
40256
+ this._value.set(value);
40257
+ this._onChange(value);
40258
+ this.valueChange.emit(value);
39349
40259
  }
39350
- _rowInvalid(row) {
39351
- if (this.disabled() || row.disabled || !this._reveal.revealed()) return false;
39352
- const v = this._value()[row.value] ?? "";
39353
- return v ? !this.columns().some((c) => c.value === v) : this.required();
40260
+ onKeydown(e) {
40261
+ if (e.key !== "Home" && e.key !== "End" || this.disabled()) return;
40262
+ const opts = this.options();
40263
+ const enabled = opts.filter((o) => !o.disabled);
40264
+ if (!enabled.length) return;
40265
+ e.preventDefault();
40266
+ const target = e.key === "Home" ? enabled[0] : enabled[enabled.length - 1];
40267
+ this.onSelect(target.value);
40268
+ this._el.nativeElement.querySelectorAll("input[type=radio]")[opts.indexOf(target)]?.focus();
39354
40269
  }
39355
40270
  onFocusOut(event) {
39356
40271
  const next = event.relatedTarget;
@@ -39358,24 +40273,14 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39358
40273
  this._onTouched();
39359
40274
  this._reveal.touched.set(true);
39360
40275
  }
39361
- _toRecord(val) {
39362
- return val && typeof val === "object" ? { ...val } : {};
39363
- }
39364
40276
  _check(value) {
39365
40277
  if (this.disabled()) return null;
39366
- const cols = this.columns();
39367
- const rows = this.rows().filter((r) => !r.disabled);
39368
- if (cols.length > 0 && rows.some((r) => value[r.value] && !cols.some((c) => c.value === value[r.value]))) return {
40278
+ if (!value) return this.required() ? requiredIssue(this.label()) : null;
40279
+ const opts = this.options();
40280
+ if (opts.length > 0 && !opts.some((o) => o.value === value)) return {
39369
40281
  key: "option",
39370
40282
  message: "Select a valid option."
39371
40283
  };
39372
- if (this.required() && rows.some((r) => !value[r.value])) {
39373
- const label = this.label().trim();
39374
- return {
39375
- key: "required",
39376
- message: label ? `${label}: choose an option in every row.` : "Choose an option in every row."
39377
- };
39378
- }
39379
40284
  return null;
39380
40285
  }
39381
40286
  static {
@@ -39383,7 +40288,7 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39383
40288
  minVersion: "12.0.0",
39384
40289
  version: "22.2.2",
39385
40290
  ngImport: i0,
39386
- type: RadioMatrixComponent,
40291
+ type: SwatchPickerComponent,
39387
40292
  deps: [],
39388
40293
  target: i0.ɵɵFactoryTarget.Component
39389
40294
  });
@@ -39392,9 +40297,9 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39392
40297
  this.ɵcmp = i0.ɵɵngDeclareComponent({
39393
40298
  minVersion: "17.0.0",
39394
40299
  version: "22.2.2",
39395
- type: RadioMatrixComponent,
40300
+ type: SwatchPickerComponent,
39396
40301
  isStandalone: true,
39397
- selector: "ui-radio-matrix",
40302
+ selector: "ui-swatch-picker",
39398
40303
  inputs: {
39399
40304
  label: {
39400
40305
  classPropertyName: "label",
@@ -39403,23 +40308,853 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39403
40308
  isRequired: false,
39404
40309
  transformFunction: null
39405
40310
  },
39406
- rowHeader: {
39407
- classPropertyName: "rowHeader",
39408
- publicName: "rowHeader",
39409
- isSignal: true,
39410
- isRequired: false,
39411
- transformFunction: null
39412
- },
39413
- rows: {
39414
- classPropertyName: "rows",
39415
- publicName: "rows",
39416
- isSignal: true,
39417
- isRequired: false,
39418
- transformFunction: null
39419
- },
39420
- columns: {
39421
- classPropertyName: "columns",
39422
- publicName: "columns",
40311
+ options: {
40312
+ classPropertyName: "options",
40313
+ publicName: "options",
40314
+ isSignal: true,
40315
+ isRequired: false,
40316
+ transformFunction: null
40317
+ },
40318
+ required: {
40319
+ classPropertyName: "required",
40320
+ publicName: "required",
40321
+ isSignal: true,
40322
+ isRequired: false,
40323
+ transformFunction: null
40324
+ },
40325
+ hint: {
40326
+ classPropertyName: "hint",
40327
+ publicName: "hint",
40328
+ isSignal: true,
40329
+ isRequired: false,
40330
+ transformFunction: null
40331
+ },
40332
+ error: {
40333
+ classPropertyName: "error",
40334
+ publicName: "error",
40335
+ isSignal: true,
40336
+ isRequired: false,
40337
+ transformFunction: null
40338
+ },
40339
+ showErrors: {
40340
+ classPropertyName: "showErrors",
40341
+ publicName: "showErrors",
40342
+ isSignal: true,
40343
+ isRequired: false,
40344
+ transformFunction: null
40345
+ },
40346
+ columns: {
40347
+ classPropertyName: "columns",
40348
+ publicName: "columns",
40349
+ isSignal: true,
40350
+ isRequired: false,
40351
+ transformFunction: null
40352
+ },
40353
+ name: {
40354
+ classPropertyName: "name",
40355
+ publicName: "name",
40356
+ isSignal: true,
40357
+ isRequired: false,
40358
+ transformFunction: null
40359
+ },
40360
+ _disabledInput: {
40361
+ classPropertyName: "_disabledInput",
40362
+ publicName: "disabled",
40363
+ isSignal: true,
40364
+ isRequired: false,
40365
+ transformFunction: null
40366
+ }
40367
+ },
40368
+ outputs: {
40369
+ invalidChange: "invalidChange",
40370
+ valueChange: "valueChange"
40371
+ },
40372
+ providers: [
40373
+ {
40374
+ provide: NG_VALUE_ACCESSOR,
40375
+ useExisting: forwardRef(() => SwatchPickerComponent),
40376
+ multi: true
40377
+ },
40378
+ {
40379
+ provide: NG_VALIDATORS,
40380
+ useExisting: forwardRef(() => SwatchPickerComponent),
40381
+ multi: true
40382
+ },
40383
+ {
40384
+ provide: UiFieldValidity,
40385
+ useExisting: forwardRef(() => SwatchPickerComponent)
40386
+ }
40387
+ ],
40388
+ usesOnChanges: true,
40389
+ ngImport: i0,
40390
+ template: `
40391
+ <fieldset
40392
+ class="sp-field"
40393
+ role="radiogroup"
40394
+ [class.sp-error]="_activeError()"
40395
+ [class.sp-disabled]="disabled()"
40396
+ [disabled]="disabled()"
40397
+ [attr.aria-required]="required() ? 'true' : null"
40398
+ [attr.aria-invalid]="_activeError() ? 'true' : null"
40399
+ [attr.aria-describedby]="(_activeError() || hint()) ? _descId : null"
40400
+ (focusout)="onFocusOut($event)"
40401
+ (keydown)="onKeydown($event)">
40402
+ @if (label()) {
40403
+ <legend class="sp-label">
40404
+ {{ label() }}
40405
+ @if (required()) { <span class="sp-required" aria-hidden="true">*</span> }
40406
+ </legend>
40407
+ }
40408
+ <div class="sp-options" [class.sp-grid]="columns() > 0" [style.--sp-cols]="columns() > 0 ? columns() : null">
40409
+ @for (opt of options(); track opt.value) {
40410
+ <label class="sp-option" [class.sp-selected]="_value() === opt.value" [class.sp-option-disabled]="disabled() || !!opt.disabled" [attr.title]="opt.label">
40411
+ <input class="sp-input" type="radio"
40412
+ [name]="_name"
40413
+ [value]="opt.value"
40414
+ [checked]="_value() === opt.value"
40415
+ [disabled]="disabled() || !!opt.disabled"
40416
+ [attr.aria-label]="opt.label"
40417
+ [attr.data-testid]="opt.testId || null"
40418
+ (change)="onSelect(opt.value)" />
40419
+ <span class="sp-swatch" [style.background-color]="opt.color" aria-hidden="true">
40420
+ @if (_value() === opt.value) {
40421
+ <svg class="sp-check" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40422
+ <path d="M5 12.5l4.5 4.5L19 7.5" class="sp-check-outline" stroke-width="5"/>
40423
+ <path d="M5 12.5l4.5 4.5L19 7.5" class="sp-check-mark" stroke-width="3"/>
40424
+ </svg>
40425
+ }
40426
+ </span>
40427
+ </label>
40428
+ }
40429
+ </div>
40430
+ @if (_activeError()) {
40431
+ <p class="sp-desc sp-desc-error" [id]="_descId" role="alert">{{ _activeError() }}</p>
40432
+ } @else if (hint()) {
40433
+ <p class="sp-desc" [id]="_descId">{{ hint() }}</p>
40434
+ }
40435
+ </fieldset>
40436
+ `,
40437
+ isInline: true,
40438
+ styles: [":host{display:block}.sp-field{display:flex;flex-direction:column;gap:6px;border:0;margin:0;padding:0;min-width:0}.sp-label{padding:0;margin-bottom:6px;font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.sp-required{color:#dc2626;margin-left:2px}.sp-options{display:flex;flex-wrap:wrap;gap:8px;min-width:0}.sp-options.sp-grid{display:grid;grid-template-columns:repeat(var(--sp-cols),max-content)}.sp-option{position:relative;display:inline-flex;cursor:pointer}.sp-input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:inherit}.sp-swatch{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:50%;box-sizing:border-box;border:2px solid #fff;box-shadow:0 0 0 1px #94a3b8;transition:box-shadow .12s}.sp-option:hover .sp-swatch{box-shadow:0 0 0 2px #64748b}.sp-option.sp-selected .sp-swatch{box-shadow:0 0 0 3px #1e293b}.sp-input:focus-visible+.sp-swatch{outline:2px solid #3b82f6;outline-offset:3px}.sp-check-outline{stroke:#0f172abf}.sp-check-mark{stroke:#fff}.sp-option-disabled{cursor:not-allowed;opacity:.45}.sp-error .sp-option .sp-swatch{box-shadow:0 0 0 1px #dc2626}.sp-error .sp-option.sp-selected .sp-swatch{box-shadow:0 0 0 3px #dc2626}.sp-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b;overflow-wrap:anywhere}.sp-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.sp-options{gap:4px}.sp-option{min-width:44px;min-height:44px;align-items:center;justify-content:center}.sp-options.sp-grid{grid-template-columns:repeat(auto-fill,44px)}}\n"],
40439
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
40440
+ });
40441
+ }
40442
+ };
40443
+ i0.ɵɵngDeclareClassMetadata({
40444
+ minVersion: "12.0.0",
40445
+ version: "22.2.2",
40446
+ ngImport: i0,
40447
+ type: SwatchPickerComponent,
40448
+ decorators: [{
40449
+ type: Component,
40450
+ args: [{
40451
+ selector: "ui-swatch-picker",
40452
+ standalone: true,
40453
+ changeDetection: ChangeDetectionStrategy.OnPush,
40454
+ providers: [
40455
+ {
40456
+ provide: NG_VALUE_ACCESSOR,
40457
+ useExisting: forwardRef(() => SwatchPickerComponent),
40458
+ multi: true
40459
+ },
40460
+ {
40461
+ provide: NG_VALIDATORS,
40462
+ useExisting: forwardRef(() => SwatchPickerComponent),
40463
+ multi: true
40464
+ },
40465
+ {
40466
+ provide: UiFieldValidity,
40467
+ useExisting: forwardRef(() => SwatchPickerComponent)
40468
+ }
40469
+ ],
40470
+ template: `
40471
+ <fieldset
40472
+ class="sp-field"
40473
+ role="radiogroup"
40474
+ [class.sp-error]="_activeError()"
40475
+ [class.sp-disabled]="disabled()"
40476
+ [disabled]="disabled()"
40477
+ [attr.aria-required]="required() ? 'true' : null"
40478
+ [attr.aria-invalid]="_activeError() ? 'true' : null"
40479
+ [attr.aria-describedby]="(_activeError() || hint()) ? _descId : null"
40480
+ (focusout)="onFocusOut($event)"
40481
+ (keydown)="onKeydown($event)">
40482
+ @if (label()) {
40483
+ <legend class="sp-label">
40484
+ {{ label() }}
40485
+ @if (required()) { <span class="sp-required" aria-hidden="true">*</span> }
40486
+ </legend>
40487
+ }
40488
+ <div class="sp-options" [class.sp-grid]="columns() > 0" [style.--sp-cols]="columns() > 0 ? columns() : null">
40489
+ @for (opt of options(); track opt.value) {
40490
+ <label class="sp-option" [class.sp-selected]="_value() === opt.value" [class.sp-option-disabled]="disabled() || !!opt.disabled" [attr.title]="opt.label">
40491
+ <input class="sp-input" type="radio"
40492
+ [name]="_name"
40493
+ [value]="opt.value"
40494
+ [checked]="_value() === opt.value"
40495
+ [disabled]="disabled() || !!opt.disabled"
40496
+ [attr.aria-label]="opt.label"
40497
+ [attr.data-testid]="opt.testId || null"
40498
+ (change)="onSelect(opt.value)" />
40499
+ <span class="sp-swatch" [style.background-color]="opt.color" aria-hidden="true">
40500
+ @if (_value() === opt.value) {
40501
+ <svg class="sp-check" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40502
+ <path d="M5 12.5l4.5 4.5L19 7.5" class="sp-check-outline" stroke-width="5"/>
40503
+ <path d="M5 12.5l4.5 4.5L19 7.5" class="sp-check-mark" stroke-width="3"/>
40504
+ </svg>
40505
+ }
40506
+ </span>
40507
+ </label>
40508
+ }
40509
+ </div>
40510
+ @if (_activeError()) {
40511
+ <p class="sp-desc sp-desc-error" [id]="_descId" role="alert">{{ _activeError() }}</p>
40512
+ } @else if (hint()) {
40513
+ <p class="sp-desc" [id]="_descId">{{ hint() }}</p>
40514
+ }
40515
+ </fieldset>
40516
+ `,
40517
+ styles: [":host{display:block}.sp-field{display:flex;flex-direction:column;gap:6px;border:0;margin:0;padding:0;min-width:0}.sp-label{padding:0;margin-bottom:6px;font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.sp-required{color:#dc2626;margin-left:2px}.sp-options{display:flex;flex-wrap:wrap;gap:8px;min-width:0}.sp-options.sp-grid{display:grid;grid-template-columns:repeat(var(--sp-cols),max-content)}.sp-option{position:relative;display:inline-flex;cursor:pointer}.sp-input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:inherit}.sp-swatch{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:50%;box-sizing:border-box;border:2px solid #fff;box-shadow:0 0 0 1px #94a3b8;transition:box-shadow .12s}.sp-option:hover .sp-swatch{box-shadow:0 0 0 2px #64748b}.sp-option.sp-selected .sp-swatch{box-shadow:0 0 0 3px #1e293b}.sp-input:focus-visible+.sp-swatch{outline:2px solid #3b82f6;outline-offset:3px}.sp-check-outline{stroke:#0f172abf}.sp-check-mark{stroke:#fff}.sp-option-disabled{cursor:not-allowed;opacity:.45}.sp-error .sp-option .sp-swatch{box-shadow:0 0 0 1px #dc2626}.sp-error .sp-option.sp-selected .sp-swatch{box-shadow:0 0 0 3px #dc2626}.sp-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b;overflow-wrap:anywhere}.sp-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.sp-options{gap:4px}.sp-option{min-width:44px;min-height:44px;align-items:center;justify-content:center}.sp-options.sp-grid{grid-template-columns:repeat(auto-fill,44px)}}\n"]
40518
+ }]
40519
+ }],
40520
+ ctorParameters: () => [],
40521
+ propDecorators: {
40522
+ label: [{
40523
+ type: i0.Input,
40524
+ args: [{
40525
+ isSignal: true,
40526
+ alias: "label",
40527
+ required: false
40528
+ }]
40529
+ }],
40530
+ options: [{
40531
+ type: i0.Input,
40532
+ args: [{
40533
+ isSignal: true,
40534
+ alias: "options",
40535
+ required: false
40536
+ }]
40537
+ }],
40538
+ required: [{
40539
+ type: i0.Input,
40540
+ args: [{
40541
+ isSignal: true,
40542
+ alias: "required",
40543
+ required: false
40544
+ }]
40545
+ }],
40546
+ hint: [{
40547
+ type: i0.Input,
40548
+ args: [{
40549
+ isSignal: true,
40550
+ alias: "hint",
40551
+ required: false
40552
+ }]
40553
+ }],
40554
+ error: [{
40555
+ type: i0.Input,
40556
+ args: [{
40557
+ isSignal: true,
40558
+ alias: "error",
40559
+ required: false
40560
+ }]
40561
+ }],
40562
+ showErrors: [{
40563
+ type: i0.Input,
40564
+ args: [{
40565
+ isSignal: true,
40566
+ alias: "showErrors",
40567
+ required: false
40568
+ }]
40569
+ }],
40570
+ columns: [{
40571
+ type: i0.Input,
40572
+ args: [{
40573
+ isSignal: true,
40574
+ alias: "columns",
40575
+ required: false
40576
+ }]
40577
+ }],
40578
+ name: [{
40579
+ type: i0.Input,
40580
+ args: [{
40581
+ isSignal: true,
40582
+ alias: "name",
40583
+ required: false
40584
+ }]
40585
+ }],
40586
+ _disabledInput: [{
40587
+ type: i0.Input,
40588
+ args: [{
40589
+ isSignal: true,
40590
+ alias: "disabled",
40591
+ required: false
40592
+ }]
40593
+ }],
40594
+ invalidChange: [{
40595
+ type: i0.Output,
40596
+ args: ["invalidChange"]
40597
+ }],
40598
+ valueChange: [{
40599
+ type: i0.Output,
40600
+ args: ["valueChange"]
40601
+ }]
40602
+ }
40603
+ });
40604
+ var IconPickerComponent = class IconPickerComponent {
40605
+ _path(o) {
40606
+ return o.path || iconPath(o.iconKey || o.value) || "";
40607
+ }
40608
+ get _name() {
40609
+ return this.name() || this._generatedName;
40610
+ }
40611
+ constructor() {
40612
+ this._el = inject(ElementRef);
40613
+ this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
40614
+ this.options = input([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
40615
+ this.required = input(false, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
40616
+ this.hint = input("", ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
40617
+ this.error = input("", ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
40618
+ this.showErrors = input(false, ...ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []);
40619
+ this.columns = input(0, ...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
40620
+ this.name = input("", ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
40621
+ this._disabledInput = input(false, {
40622
+ ...ngDevMode ? { debugName: "_disabledInput" } : /* istanbul ignore next */ {},
40623
+ alias: "disabled"
40624
+ });
40625
+ this._cvaDisabled = signal(false, ...ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []);
40626
+ this.disabled = computed(() => this._disabledInput() || this._cvaDisabled(), ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
40627
+ this._generatedName = `ip-${Math.random().toString(36).slice(2, 8)}`;
40628
+ this._descId = `${this._generatedName}-desc`;
40629
+ this._value = signal("", ...ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []);
40630
+ this._reveal = createFieldReveal(this.showErrors);
40631
+ this._issue = computed(() => this._check(this._value()), ...ngDevMode ? [{ debugName: "_issue" }] : /* istanbul ignore next */ []);
40632
+ this.invalid = computed(() => !!this.error() || !!this._issue(), ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
40633
+ this.errorMessage = computed(() => this._issue()?.message ?? "", ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
40634
+ this.invalidChange = output();
40635
+ this.valueChange = output();
40636
+ this._activeError = computed(() => this.error() || (this._reveal.revealed() ? this.errorMessage() : ""), ...ngDevMode ? [{ debugName: "_activeError" }] : /* istanbul ignore next */ []);
40637
+ this._onValidatorChange = () => {};
40638
+ this._onChange = (_) => {};
40639
+ this._onTouched = () => {};
40640
+ effect(() => {
40641
+ this.invalidChange.emit(this.invalid());
40642
+ });
40643
+ }
40644
+ ngOnChanges() {
40645
+ this._onValidatorChange();
40646
+ }
40647
+ validate(control) {
40648
+ const v = control.value;
40649
+ return issueToErrors(this._check(v == null ? "" : String(v)));
40650
+ }
40651
+ registerOnValidatorChange(fn) {
40652
+ this._onValidatorChange = fn;
40653
+ }
40654
+ writeValue(val) {
40655
+ this._value.set(val ?? "");
40656
+ }
40657
+ registerOnChange(fn) {
40658
+ this._onChange = fn;
40659
+ }
40660
+ registerOnTouched(fn) {
40661
+ this._onTouched = fn;
40662
+ }
40663
+ setDisabledState(d) {
40664
+ this._cvaDisabled.set(d);
40665
+ }
40666
+ onSelect(value) {
40667
+ if (this.disabled()) return;
40668
+ this._value.set(value);
40669
+ this._onChange(value);
40670
+ this.valueChange.emit(value);
40671
+ }
40672
+ onKeydown(e) {
40673
+ if (e.key !== "Home" && e.key !== "End" || this.disabled()) return;
40674
+ const opts = this.options();
40675
+ const enabled = opts.filter((o) => !o.disabled);
40676
+ if (!enabled.length) return;
40677
+ e.preventDefault();
40678
+ const target = e.key === "Home" ? enabled[0] : enabled[enabled.length - 1];
40679
+ this.onSelect(target.value);
40680
+ this._el.nativeElement.querySelectorAll("input[type=radio]")[opts.indexOf(target)]?.focus();
40681
+ }
40682
+ onFocusOut(event) {
40683
+ const next = event.relatedTarget;
40684
+ if (next && event.currentTarget.contains(next)) return;
40685
+ this._onTouched();
40686
+ this._reveal.touched.set(true);
40687
+ }
40688
+ _check(value) {
40689
+ if (this.disabled()) return null;
40690
+ if (!value) return this.required() ? requiredIssue(this.label()) : null;
40691
+ const opts = this.options();
40692
+ if (opts.length > 0 && !opts.some((o) => o.value === value)) return {
40693
+ key: "option",
40694
+ message: "Select a valid option."
40695
+ };
40696
+ return null;
40697
+ }
40698
+ static {
40699
+ this.ɵfac = i0.ɵɵngDeclareFactory({
40700
+ minVersion: "12.0.0",
40701
+ version: "22.2.2",
40702
+ ngImport: i0,
40703
+ type: IconPickerComponent,
40704
+ deps: [],
40705
+ target: i0.ɵɵFactoryTarget.Component
40706
+ });
40707
+ }
40708
+ static {
40709
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
40710
+ minVersion: "17.0.0",
40711
+ version: "22.2.2",
40712
+ type: IconPickerComponent,
40713
+ isStandalone: true,
40714
+ selector: "ui-icon-picker",
40715
+ inputs: {
40716
+ label: {
40717
+ classPropertyName: "label",
40718
+ publicName: "label",
40719
+ isSignal: true,
40720
+ isRequired: false,
40721
+ transformFunction: null
40722
+ },
40723
+ options: {
40724
+ classPropertyName: "options",
40725
+ publicName: "options",
40726
+ isSignal: true,
40727
+ isRequired: false,
40728
+ transformFunction: null
40729
+ },
40730
+ required: {
40731
+ classPropertyName: "required",
40732
+ publicName: "required",
40733
+ isSignal: true,
40734
+ isRequired: false,
40735
+ transformFunction: null
40736
+ },
40737
+ hint: {
40738
+ classPropertyName: "hint",
40739
+ publicName: "hint",
40740
+ isSignal: true,
40741
+ isRequired: false,
40742
+ transformFunction: null
40743
+ },
40744
+ error: {
40745
+ classPropertyName: "error",
40746
+ publicName: "error",
40747
+ isSignal: true,
40748
+ isRequired: false,
40749
+ transformFunction: null
40750
+ },
40751
+ showErrors: {
40752
+ classPropertyName: "showErrors",
40753
+ publicName: "showErrors",
40754
+ isSignal: true,
40755
+ isRequired: false,
40756
+ transformFunction: null
40757
+ },
40758
+ columns: {
40759
+ classPropertyName: "columns",
40760
+ publicName: "columns",
40761
+ isSignal: true,
40762
+ isRequired: false,
40763
+ transformFunction: null
40764
+ },
40765
+ name: {
40766
+ classPropertyName: "name",
40767
+ publicName: "name",
40768
+ isSignal: true,
40769
+ isRequired: false,
40770
+ transformFunction: null
40771
+ },
40772
+ _disabledInput: {
40773
+ classPropertyName: "_disabledInput",
40774
+ publicName: "disabled",
40775
+ isSignal: true,
40776
+ isRequired: false,
40777
+ transformFunction: null
40778
+ }
40779
+ },
40780
+ outputs: {
40781
+ invalidChange: "invalidChange",
40782
+ valueChange: "valueChange"
40783
+ },
40784
+ providers: [
40785
+ {
40786
+ provide: NG_VALUE_ACCESSOR,
40787
+ useExisting: forwardRef(() => IconPickerComponent),
40788
+ multi: true
40789
+ },
40790
+ {
40791
+ provide: NG_VALIDATORS,
40792
+ useExisting: forwardRef(() => IconPickerComponent),
40793
+ multi: true
40794
+ },
40795
+ {
40796
+ provide: UiFieldValidity,
40797
+ useExisting: forwardRef(() => IconPickerComponent)
40798
+ }
40799
+ ],
40800
+ usesOnChanges: true,
40801
+ ngImport: i0,
40802
+ template: `
40803
+ <fieldset
40804
+ class="ip-field"
40805
+ role="radiogroup"
40806
+ [class.ip-error]="_activeError()"
40807
+ [class.ip-disabled]="disabled()"
40808
+ [disabled]="disabled()"
40809
+ [attr.aria-required]="required() ? 'true' : null"
40810
+ [attr.aria-invalid]="_activeError() ? 'true' : null"
40811
+ [attr.aria-describedby]="(_activeError() || hint()) ? _descId : null"
40812
+ (focusout)="onFocusOut($event)"
40813
+ (keydown)="onKeydown($event)">
40814
+ @if (label()) {
40815
+ <legend class="ip-label">
40816
+ {{ label() }}
40817
+ @if (required()) { <span class="ip-required" aria-hidden="true">*</span> }
40818
+ </legend>
40819
+ }
40820
+ <div class="ip-options" [class.ip-grid]="columns() > 0" [style.--ip-cols]="columns() > 0 ? columns() : null">
40821
+ @for (opt of options(); track opt.value) {
40822
+ <label class="ip-option" [class.ip-selected]="_value() === opt.value" [class.ip-option-disabled]="disabled() || !!opt.disabled" [attr.title]="opt.label">
40823
+ <input class="ip-input" type="radio"
40824
+ [name]="_name"
40825
+ [value]="opt.value"
40826
+ [checked]="_value() === opt.value"
40827
+ [disabled]="disabled() || !!opt.disabled"
40828
+ [attr.aria-label]="opt.label"
40829
+ [attr.data-testid]="opt.testId || null"
40830
+ (change)="onSelect(opt.value)" />
40831
+ <span class="ip-swatch" aria-hidden="true">
40832
+ <svg class="ip-glyph" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40833
+ <path [attr.d]="_path(opt)"/>
40834
+ </svg>
40835
+ @if (_value() === opt.value) {
40836
+ <svg class="ip-check" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40837
+ <path d="M5 12.5l4.5 4.5L19 7.5"/>
40838
+ </svg>
40839
+ }
40840
+ </span>
40841
+ </label>
40842
+ }
40843
+ </div>
40844
+ @if (_activeError()) {
40845
+ <p class="ip-desc ip-desc-error" [id]="_descId" role="alert">{{ _activeError() }}</p>
40846
+ } @else if (hint()) {
40847
+ <p class="ip-desc" [id]="_descId">{{ hint() }}</p>
40848
+ }
40849
+ </fieldset>
40850
+ `,
40851
+ isInline: true,
40852
+ styles: [":host{display:block}.ip-field{display:flex;flex-direction:column;gap:6px;border:0;margin:0;padding:0;min-width:0}.ip-label{padding:0;margin-bottom:6px;font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.ip-required{color:#dc2626;margin-left:2px}.ip-options{display:flex;flex-wrap:wrap;gap:8px;min-width:0}.ip-options.ip-grid{display:grid;grid-template-columns:repeat(var(--ip-cols),max-content)}.ip-option{position:relative;display:inline-flex;cursor:pointer}.ip-input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:inherit}.ip-swatch{display:inline-flex;align-items:center;justify-content:center;position:relative;width:36px;height:36px;border-radius:8px;box-sizing:border-box;background:#fff;color:#334155;border:1px solid #cbd5e1;box-shadow:0 0 0 0 transparent;transition:box-shadow .12s}.ip-option:hover .ip-swatch{border-color:#64748b}.ip-input:focus-visible+.ip-swatch{outline:2px solid #3b82f6;outline-offset:3px}.ip-option.ip-selected .ip-swatch{background:#1e293b;color:#fff;border-color:#1e293b}.ip-check{position:absolute;right:2px;bottom:2px;padding:1px;border-radius:50%;background:#fff;color:#1e293b;border:1px solid #1e293b;box-sizing:content-box}.ip-option-disabled{cursor:not-allowed;opacity:.45}.ip-error .ip-option .ip-swatch{border-color:#dc2626}.ip-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b;overflow-wrap:anywhere}.ip-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.ip-options{gap:4px}.ip-option{min-width:44px;min-height:44px;align-items:center;justify-content:center}.ip-options.ip-grid{grid-template-columns:repeat(auto-fill,44px)}}\n"],
40853
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
40854
+ });
40855
+ }
40856
+ };
40857
+ i0.ɵɵngDeclareClassMetadata({
40858
+ minVersion: "12.0.0",
40859
+ version: "22.2.2",
40860
+ ngImport: i0,
40861
+ type: IconPickerComponent,
40862
+ decorators: [{
40863
+ type: Component,
40864
+ args: [{
40865
+ selector: "ui-icon-picker",
40866
+ standalone: true,
40867
+ changeDetection: ChangeDetectionStrategy.OnPush,
40868
+ providers: [
40869
+ {
40870
+ provide: NG_VALUE_ACCESSOR,
40871
+ useExisting: forwardRef(() => IconPickerComponent),
40872
+ multi: true
40873
+ },
40874
+ {
40875
+ provide: NG_VALIDATORS,
40876
+ useExisting: forwardRef(() => IconPickerComponent),
40877
+ multi: true
40878
+ },
40879
+ {
40880
+ provide: UiFieldValidity,
40881
+ useExisting: forwardRef(() => IconPickerComponent)
40882
+ }
40883
+ ],
40884
+ template: `
40885
+ <fieldset
40886
+ class="ip-field"
40887
+ role="radiogroup"
40888
+ [class.ip-error]="_activeError()"
40889
+ [class.ip-disabled]="disabled()"
40890
+ [disabled]="disabled()"
40891
+ [attr.aria-required]="required() ? 'true' : null"
40892
+ [attr.aria-invalid]="_activeError() ? 'true' : null"
40893
+ [attr.aria-describedby]="(_activeError() || hint()) ? _descId : null"
40894
+ (focusout)="onFocusOut($event)"
40895
+ (keydown)="onKeydown($event)">
40896
+ @if (label()) {
40897
+ <legend class="ip-label">
40898
+ {{ label() }}
40899
+ @if (required()) { <span class="ip-required" aria-hidden="true">*</span> }
40900
+ </legend>
40901
+ }
40902
+ <div class="ip-options" [class.ip-grid]="columns() > 0" [style.--ip-cols]="columns() > 0 ? columns() : null">
40903
+ @for (opt of options(); track opt.value) {
40904
+ <label class="ip-option" [class.ip-selected]="_value() === opt.value" [class.ip-option-disabled]="disabled() || !!opt.disabled" [attr.title]="opt.label">
40905
+ <input class="ip-input" type="radio"
40906
+ [name]="_name"
40907
+ [value]="opt.value"
40908
+ [checked]="_value() === opt.value"
40909
+ [disabled]="disabled() || !!opt.disabled"
40910
+ [attr.aria-label]="opt.label"
40911
+ [attr.data-testid]="opt.testId || null"
40912
+ (change)="onSelect(opt.value)" />
40913
+ <span class="ip-swatch" aria-hidden="true">
40914
+ <svg class="ip-glyph" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40915
+ <path [attr.d]="_path(opt)"/>
40916
+ </svg>
40917
+ @if (_value() === opt.value) {
40918
+ <svg class="ip-check" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
40919
+ <path d="M5 12.5l4.5 4.5L19 7.5"/>
40920
+ </svg>
40921
+ }
40922
+ </span>
40923
+ </label>
40924
+ }
40925
+ </div>
40926
+ @if (_activeError()) {
40927
+ <p class="ip-desc ip-desc-error" [id]="_descId" role="alert">{{ _activeError() }}</p>
40928
+ } @else if (hint()) {
40929
+ <p class="ip-desc" [id]="_descId">{{ hint() }}</p>
40930
+ }
40931
+ </fieldset>
40932
+ `,
40933
+ styles: [":host{display:block}.ip-field{display:flex;flex-direction:column;gap:6px;border:0;margin:0;padding:0;min-width:0}.ip-label{padding:0;margin-bottom:6px;font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.ip-required{color:#dc2626;margin-left:2px}.ip-options{display:flex;flex-wrap:wrap;gap:8px;min-width:0}.ip-options.ip-grid{display:grid;grid-template-columns:repeat(var(--ip-cols),max-content)}.ip-option{position:relative;display:inline-flex;cursor:pointer}.ip-input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:inherit}.ip-swatch{display:inline-flex;align-items:center;justify-content:center;position:relative;width:36px;height:36px;border-radius:8px;box-sizing:border-box;background:#fff;color:#334155;border:1px solid #cbd5e1;box-shadow:0 0 0 0 transparent;transition:box-shadow .12s}.ip-option:hover .ip-swatch{border-color:#64748b}.ip-input:focus-visible+.ip-swatch{outline:2px solid #3b82f6;outline-offset:3px}.ip-option.ip-selected .ip-swatch{background:#1e293b;color:#fff;border-color:#1e293b}.ip-check{position:absolute;right:2px;bottom:2px;padding:1px;border-radius:50%;background:#fff;color:#1e293b;border:1px solid #1e293b;box-sizing:content-box}.ip-option-disabled{cursor:not-allowed;opacity:.45}.ip-error .ip-option .ip-swatch{border-color:#dc2626}.ip-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b;overflow-wrap:anywhere}.ip-desc-error{color:#dc2626}@media(pointer:coarse),(max-width:480px){.ip-options{gap:4px}.ip-option{min-width:44px;min-height:44px;align-items:center;justify-content:center}.ip-options.ip-grid{grid-template-columns:repeat(auto-fill,44px)}}\n"]
40934
+ }]
40935
+ }],
40936
+ ctorParameters: () => [],
40937
+ propDecorators: {
40938
+ label: [{
40939
+ type: i0.Input,
40940
+ args: [{
40941
+ isSignal: true,
40942
+ alias: "label",
40943
+ required: false
40944
+ }]
40945
+ }],
40946
+ options: [{
40947
+ type: i0.Input,
40948
+ args: [{
40949
+ isSignal: true,
40950
+ alias: "options",
40951
+ required: false
40952
+ }]
40953
+ }],
40954
+ required: [{
40955
+ type: i0.Input,
40956
+ args: [{
40957
+ isSignal: true,
40958
+ alias: "required",
40959
+ required: false
40960
+ }]
40961
+ }],
40962
+ hint: [{
40963
+ type: i0.Input,
40964
+ args: [{
40965
+ isSignal: true,
40966
+ alias: "hint",
40967
+ required: false
40968
+ }]
40969
+ }],
40970
+ error: [{
40971
+ type: i0.Input,
40972
+ args: [{
40973
+ isSignal: true,
40974
+ alias: "error",
40975
+ required: false
40976
+ }]
40977
+ }],
40978
+ showErrors: [{
40979
+ type: i0.Input,
40980
+ args: [{
40981
+ isSignal: true,
40982
+ alias: "showErrors",
40983
+ required: false
40984
+ }]
40985
+ }],
40986
+ columns: [{
40987
+ type: i0.Input,
40988
+ args: [{
40989
+ isSignal: true,
40990
+ alias: "columns",
40991
+ required: false
40992
+ }]
40993
+ }],
40994
+ name: [{
40995
+ type: i0.Input,
40996
+ args: [{
40997
+ isSignal: true,
40998
+ alias: "name",
40999
+ required: false
41000
+ }]
41001
+ }],
41002
+ _disabledInput: [{
41003
+ type: i0.Input,
41004
+ args: [{
41005
+ isSignal: true,
41006
+ alias: "disabled",
41007
+ required: false
41008
+ }]
41009
+ }],
41010
+ invalidChange: [{
41011
+ type: i0.Output,
41012
+ args: ["invalidChange"]
41013
+ }],
41014
+ valueChange: [{
41015
+ type: i0.Output,
41016
+ args: ["valueChange"]
41017
+ }]
41018
+ }
41019
+ });
41020
+ var RadioMatrixComponent = class RadioMatrixComponent {
41021
+ get _name() {
41022
+ return this.name() || this._generatedName;
41023
+ }
41024
+ constructor() {
41025
+ this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
41026
+ this.rowHeader = input("", ...ngDevMode ? [{ debugName: "rowHeader" }] : /* istanbul ignore next */ []);
41027
+ this.rows = input([], ...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
41028
+ this.columns = input([], ...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
41029
+ this.required = input(false, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
41030
+ this.hint = input("", ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
41031
+ this.error = input("", ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
41032
+ this.showErrors = input(false, ...ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []);
41033
+ this.name = input("", ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
41034
+ this._disabledInput = input(false, {
41035
+ ...ngDevMode ? { debugName: "_disabledInput" } : /* istanbul ignore next */ {},
41036
+ alias: "disabled"
41037
+ });
41038
+ this._cvaDisabled = signal(false, ...ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []);
41039
+ this.disabled = computed(() => this._disabledInput() || this._cvaDisabled(), ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
41040
+ this._generatedName = `rm-${Math.random().toString(36).slice(2, 8)}`;
41041
+ this._descId = `${this._generatedName}-desc`;
41042
+ this._value = signal({}, ...ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []);
41043
+ this._reveal = createFieldReveal(this.showErrors);
41044
+ this._issue = computed(() => this._check(this._value()), ...ngDevMode ? [{ debugName: "_issue" }] : /* istanbul ignore next */ []);
41045
+ this.invalid = computed(() => !!this.error() || !!this._issue(), ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
41046
+ this.errorMessage = computed(() => this._issue()?.message ?? "", ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
41047
+ this.invalidChange = output();
41048
+ this._activeError = computed(() => this.error() || (this._reveal.revealed() ? this.errorMessage() : ""), ...ngDevMode ? [{ debugName: "_activeError" }] : /* istanbul ignore next */ []);
41049
+ this._onValidatorChange = () => {};
41050
+ this._onChange = (_) => {};
41051
+ this._onTouched = () => {};
41052
+ effect(() => {
41053
+ this.invalidChange.emit(this.invalid());
41054
+ });
41055
+ }
41056
+ ngOnChanges() {
41057
+ this._onValidatorChange();
41058
+ }
41059
+ validate(control) {
41060
+ return issueToErrors(this._check(this._toRecord(control.value)));
41061
+ }
41062
+ registerOnValidatorChange(fn) {
41063
+ this._onValidatorChange = fn;
41064
+ }
41065
+ writeValue(val) {
41066
+ this._value.set(this._toRecord(val));
41067
+ }
41068
+ registerOnChange(fn) {
41069
+ this._onChange = fn;
41070
+ }
41071
+ registerOnTouched(fn) {
41072
+ this._onTouched = fn;
41073
+ }
41074
+ setDisabledState(d) {
41075
+ this._cvaDisabled.set(d);
41076
+ }
41077
+ onSelect(row, column) {
41078
+ const next = {
41079
+ ...this._value(),
41080
+ [row]: column
41081
+ };
41082
+ this._value.set(next);
41083
+ this._onChange(next);
41084
+ }
41085
+ _rowInvalid(row) {
41086
+ if (this.disabled() || row.disabled || !this._reveal.revealed()) return false;
41087
+ const v = this._value()[row.value] ?? "";
41088
+ return v ? !this.columns().some((c) => c.value === v) : this.required();
41089
+ }
41090
+ onFocusOut(event) {
41091
+ const next = event.relatedTarget;
41092
+ if (next && event.currentTarget.contains(next)) return;
41093
+ this._onTouched();
41094
+ this._reveal.touched.set(true);
41095
+ }
41096
+ _toRecord(val) {
41097
+ return val && typeof val === "object" ? { ...val } : {};
41098
+ }
41099
+ _check(value) {
41100
+ if (this.disabled()) return null;
41101
+ const cols = this.columns();
41102
+ const rows = this.rows().filter((r) => !r.disabled);
41103
+ if (cols.length > 0 && rows.some((r) => value[r.value] && !cols.some((c) => c.value === value[r.value]))) return {
41104
+ key: "option",
41105
+ message: "Select a valid option."
41106
+ };
41107
+ if (this.required() && rows.some((r) => !value[r.value])) {
41108
+ const label = this.label().trim();
41109
+ return {
41110
+ key: "required",
41111
+ message: label ? `${label}: choose an option in every row.` : "Choose an option in every row."
41112
+ };
41113
+ }
41114
+ return null;
41115
+ }
41116
+ static {
41117
+ this.ɵfac = i0.ɵɵngDeclareFactory({
41118
+ minVersion: "12.0.0",
41119
+ version: "22.2.2",
41120
+ ngImport: i0,
41121
+ type: RadioMatrixComponent,
41122
+ deps: [],
41123
+ target: i0.ɵɵFactoryTarget.Component
41124
+ });
41125
+ }
41126
+ static {
41127
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
41128
+ minVersion: "17.0.0",
41129
+ version: "22.2.2",
41130
+ type: RadioMatrixComponent,
41131
+ isStandalone: true,
41132
+ selector: "ui-radio-matrix",
41133
+ inputs: {
41134
+ label: {
41135
+ classPropertyName: "label",
41136
+ publicName: "label",
41137
+ isSignal: true,
41138
+ isRequired: false,
41139
+ transformFunction: null
41140
+ },
41141
+ rowHeader: {
41142
+ classPropertyName: "rowHeader",
41143
+ publicName: "rowHeader",
41144
+ isSignal: true,
41145
+ isRequired: false,
41146
+ transformFunction: null
41147
+ },
41148
+ rows: {
41149
+ classPropertyName: "rows",
41150
+ publicName: "rows",
41151
+ isSignal: true,
41152
+ isRequired: false,
41153
+ transformFunction: null
41154
+ },
41155
+ columns: {
41156
+ classPropertyName: "columns",
41157
+ publicName: "columns",
39423
41158
  isSignal: true,
39424
41159
  isRequired: false,
39425
41160
  transformFunction: null
@@ -39550,6 +41285,7 @@ var RadioMatrixComponent = class RadioMatrixComponent {
39550
41285
  inputs: [
39551
41286
  "label",
39552
41287
  "description",
41288
+ "icon",
39553
41289
  "ariaLabel",
39554
41290
  "testId",
39555
41291
  "value",
@@ -45068,7 +46804,11 @@ var CalendarComponent = class CalendarComponent {
45068
46804
  kind: "component",
45069
46805
  type: BadgeComponent,
45070
46806
  selector: "ui-badge",
45071
- inputs: ["label", "variant"]
46807
+ inputs: [
46808
+ "label",
46809
+ "variant",
46810
+ "color"
46811
+ ]
45072
46812
  },
45073
46813
  {
45074
46814
  kind: "component",
@@ -45100,7 +46840,10 @@ var CalendarComponent = class CalendarComponent {
45100
46840
  "ariaLabel",
45101
46841
  "name",
45102
46842
  "noWrap",
45103
- "orientation"
46843
+ "orientation",
46844
+ "controlsPanels",
46845
+ "showDescription",
46846
+ "headingLevel"
45104
46847
  ],
45105
46848
  outputs: ["tabChange"]
45106
46849
  },
@@ -49281,7 +51024,11 @@ var SetupWizardComponent = class SetupWizardComponent {
49281
51024
  kind: "component",
49282
51025
  type: BadgeComponent,
49283
51026
  selector: "ui-badge",
49284
- inputs: ["label", "variant"]
51027
+ inputs: [
51028
+ "label",
51029
+ "variant",
51030
+ "color"
51031
+ ]
49285
51032
  },
49286
51033
  {
49287
51034
  kind: "component",
@@ -49341,6 +51088,7 @@ var SetupWizardComponent = class SetupWizardComponent {
49341
51088
  "background",
49342
51089
  "headerBackground",
49343
51090
  "footerBackground",
51091
+ "footerAlign",
49344
51092
  "textColor",
49345
51093
  "showHeader",
49346
51094
  "collapsible",
@@ -49406,7 +51154,10 @@ var SetupWizardComponent = class SetupWizardComponent {
49406
51154
  "ariaLabel",
49407
51155
  "name",
49408
51156
  "noWrap",
49409
- "orientation"
51157
+ "orientation",
51158
+ "controlsPanels",
51159
+ "showDescription",
51160
+ "headingLevel"
49410
51161
  ],
49411
51162
  outputs: ["tabChange"]
49412
51163
  },
@@ -49493,6 +51244,7 @@ var SetupWizardComponent = class SetupWizardComponent {
49493
51244
  "inputName",
49494
51245
  "placeholder",
49495
51246
  "prefix",
51247
+ "leadingIcon",
49496
51248
  "revealable",
49497
51249
  "passwordRequirements",
49498
51250
  "passwordRules",
@@ -51606,7 +53358,10 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
51606
53358
  "ariaLabel",
51607
53359
  "name",
51608
53360
  "noWrap",
51609
- "orientation"
53361
+ "orientation",
53362
+ "controlsPanels",
53363
+ "showDescription",
53364
+ "headingLevel"
51610
53365
  ],
51611
53366
  outputs: ["tabChange"]
51612
53367
  },
@@ -51652,6 +53407,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
51652
53407
  inputs: [
51653
53408
  "label",
51654
53409
  "ariaLabel",
53410
+ "labelHidden",
51655
53411
  "inputName",
51656
53412
  "placeholder",
51657
53413
  "options",
@@ -51710,6 +53466,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
51710
53466
  "inputName",
51711
53467
  "placeholder",
51712
53468
  "prefix",
53469
+ "leadingIcon",
51713
53470
  "revealable",
51714
53471
  "passwordRequirements",
51715
53472
  "passwordRules",
@@ -53384,7 +55141,11 @@ var ReminderAlertsComponent = class ReminderAlertsComponent {
53384
55141
  kind: "component",
53385
55142
  type: BadgeComponent,
53386
55143
  selector: "ui-badge",
53387
- inputs: ["label", "variant"]
55144
+ inputs: [
55145
+ "label",
55146
+ "variant",
55147
+ "color"
55148
+ ]
53388
55149
  },
53389
55150
  {
53390
55151
  kind: "component",
@@ -55075,7 +56836,11 @@ var ConversationsComponent = class ConversationsComponent {
55075
56836
  kind: "component",
55076
56837
  type: BadgeComponent,
55077
56838
  selector: "ui-badge",
55078
- inputs: ["label", "variant"]
56839
+ inputs: [
56840
+ "label",
56841
+ "variant",
56842
+ "color"
56843
+ ]
55079
56844
  },
55080
56845
  {
55081
56846
  kind: "component",
@@ -55165,6 +56930,7 @@ var ConversationsComponent = class ConversationsComponent {
55165
56930
  inputs: [
55166
56931
  "items",
55167
56932
  "ordered",
56933
+ "bulleted",
55168
56934
  "layout",
55169
56935
  "gridMin",
55170
56936
  "gap",
@@ -58136,6 +59902,8 @@ var PaymentSidePanelComponent = class PaymentSidePanelComponent {
58136
59902
  "highlight",
58137
59903
  "clickable",
58138
59904
  "valueColor",
59905
+ "loading",
59906
+ "loadingLabel",
58139
59907
  "background",
58140
59908
  "progress",
58141
59909
  "progressMax",
@@ -58159,6 +59927,7 @@ var PaymentSidePanelComponent = class PaymentSidePanelComponent {
58159
59927
  inputs: [
58160
59928
  "label",
58161
59929
  "ariaLabel",
59930
+ "labelHidden",
58162
59931
  "inputName",
58163
59932
  "placeholder",
58164
59933
  "options",
@@ -58205,6 +59974,7 @@ var PaymentSidePanelComponent = class PaymentSidePanelComponent {
58205
59974
  "inputName",
58206
59975
  "placeholder",
58207
59976
  "prefix",
59977
+ "leadingIcon",
58208
59978
  "revealable",
58209
59979
  "passwordRequirements",
58210
59980
  "passwordRules",
@@ -58704,6 +60474,6 @@ i0.ɵɵngDeclareClassMetadata({
58704
60474
  }]
58705
60475
  }
58706
60476
  });
58707
- export { ALLOCATION_CUSTOM, ASCII_SPECIAL_PASSWORD_RULES, ActionBarComponent, AddressInputComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BankAccountFormComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, COMMON_DETAIL_GROUP_STYLES, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, ConversationRichBodyComponent, ConversationsComponent, DEFAULT_ALLOCATION_MODES, DEFAULT_BANK_ACCOUNT_TYPE_OPTIONS, DEFAULT_BANK_HOLDER_TYPE_OPTIONS, DEFAULT_BANK_MANDATE_TEXT, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DEFAULT_PAYMENT_METHODS, DETAIL_CARD_HEADER_BG, DETAIL_GROUP_HEADER_BG, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FillViewportDirective, FixedFooterComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, ImportSourceGridComponent, KeypadComponent, KpiCardComponent, LAYOUT_GAP_PX, LISTED_SPECIAL_PASSWORD_RULES, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, MAX_PAYMENT_AMOUNT, MIN_PAYMENT_AMOUNT, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, OfflineBannerComponent, OptionCardComponent, PASSWORD_MAX_LENGTH, PAYMENT_METHOD, PAYMENT_METHOD_PLUGIN, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PaymentCustomMethodComponent, PaymentMethodPlugin, PaymentSidePanelComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, ReminderAlertsComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShareMenuComponent, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, SnackbarComponent, SnackbarService, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextTemplatePickerComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_LOCATIONS, US_STATES, US_STATE_OPTIONS, US_ZIP_PATTERN, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildPreviewDocument, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, callHost, conversationDateLabel, conversationHtmlToText, conversationInitial, conversationMessageStatusLabel, conversationMessageStatusMark, createFieldReveal, createPasswordPolicyValidator, decodeFilterValues, digitsOnly, downloadBlob, emailShareUrl, emptyAddress, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, facebookShareUrl, fileMatchesAccept, fileNameFromContentDisposition, formatAddress, formatAddressValue, formatAddressValueOneLine, formatCategoryLabel, formatConversationPhone, formatConversationTime, formatCurrency, formatDuration, formatFileSize, formatIsoDate, formatIsoDateTime, formatMessageTime, formatPhone, formatPhoneDisplay, formatShortDate, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, getInitials, gmailShareUrl, groupMessagesByDay, hostErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isEmptyAddress, isValidAmount, isValidEmailAddress, isValidZip, isWebUrl, isoKey, issueToErrors, last4Error, linkedInShareUrl, maxLengthIssue, mergeDescribedBy, normalizeAddress, normalizeHexColor, outlookShareUrl, parseAddressOneLine, parseAddressValue, parseBizHours, parseIso, parseTime, passwordMeetsRules, periodGroup, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, serializedTextLength, setupIntegrations, splitIntro, terminalTimeoutText, terminalVerdict, todayInTimezone, truncateConversationText, xShareUrl };
60477
+ export { ALLOCATION_CUSTOM, ASCII_SPECIAL_PASSWORD_RULES, ActionBarComponent, AddressInputComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BankAccountFormComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, COMMON_DETAIL_GROUP_STYLES, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, ConversationRichBodyComponent, ConversationsComponent, DEFAULT_ALLOCATION_MODES, DEFAULT_BANK_ACCOUNT_TYPE_OPTIONS, DEFAULT_BANK_HOLDER_TYPE_OPTIONS, DEFAULT_BANK_MANDATE_TEXT, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DEFAULT_PAYMENT_METHODS, DETAIL_CARD_HEADER_BG, DETAIL_GROUP_HEADER_BG, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FillViewportDirective, FixedFooterComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, ICON_NAMES, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, IconPickerComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, ImportSourceGridComponent, KeypadComponent, KpiCardComponent, LAYOUT_GAP_PX, LISTED_SPECIAL_PASSWORD_RULES, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, MAX_PAYMENT_AMOUNT, MIN_PAYMENT_AMOUNT, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, OfflineBannerComponent, OptionCardComponent, PASSWORD_MAX_LENGTH, PAYMENT_METHOD, PAYMENT_METHOD_PLUGIN, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PaymentCustomMethodComponent, PaymentMethodPlugin, PaymentSidePanelComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabPanelDirective, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, ReminderAlertsComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShareMenuComponent, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, SnackbarComponent, SnackbarService, StackComponent, StarComponent, StepperComponent, SwatchPickerComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextTemplatePickerComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_LOCATIONS, US_STATES, US_STATE_OPTIONS, US_ZIP_PATTERN, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildPreviewDocument, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, callHost, conversationDateLabel, conversationHtmlToText, conversationInitial, conversationMessageStatusLabel, conversationMessageStatusMark, createFieldReveal, createPasswordPolicyValidator, decodeFilterValues, digitsOnly, downloadBlob, emailShareUrl, emptyAddress, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, facebookShareUrl, fileMatchesAccept, fileNameFromContentDisposition, formatAddress, formatAddressValue, formatAddressValueOneLine, formatCategoryLabel, formatConversationPhone, formatConversationTime, formatCurrency, formatDuration, formatFileSize, formatIsoDate, formatIsoDateTime, formatMessageTime, formatPhone, formatPhoneDisplay, formatShortDate, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, getInitials, gmailShareUrl, groupMessagesByDay, hostErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isEmptyAddress, isValidAmount, isValidEmailAddress, isValidZip, isWebUrl, isoKey, issueToErrors, last4Error, linkedInShareUrl, maxLengthIssue, mergeDescribedBy, normalizeAddress, normalizeHexColor, outlookShareUrl, parseAddressOneLine, parseAddressValue, parseBizHours, parseIso, parseTime, passwordMeetsRules, periodGroup, pillTabDescriptionId, pillTabId, pillTabPanelId, pillTabTitleId, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, serializedTextLength, setupIntegrations, splitIntro, terminalTimeoutText, terminalVerdict, todayInTimezone, truncateConversationText, xShareUrl };
58708
60478
 
58709
60479
  //# sourceMappingURL=forgeroute-ui.mjs.map