@forgeroute/ui 0.4.21 → 0.4.22

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.
@@ -1494,9 +1494,33 @@ var AvatarComponent = class AvatarComponent {
1494
1494
  this.initials = input.required(...ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []);
1495
1495
  this.name = input("", ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
1496
1496
  this.size = input(32, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
1497
+ this.imageUrl = input(void 0, ...ngDevMode ? [{ debugName: "imageUrl" }] : /* istanbul ignore next */ []);
1498
+ this.editable = input(false, ...ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []);
1499
+ this.editLabel = input("Change photo", ...ngDevMode ? [{ debugName: "editLabel" }] : /* istanbul ignore next */ []);
1500
+ this.busy = input(false, ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
1501
+ this.editClick = output();
1502
+ this.imageError = output();
1503
+ this.failedUrl = signal(null, ...ngDevMode ? [{ debugName: "failedUrl" }] : /* istanbul ignore next */ []);
1504
+ this.showImage = computed(() => {
1505
+ const url = this.imageUrl();
1506
+ return !!url && this.failedUrl() !== url;
1507
+ }, ...ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []);
1508
+ this.badgeSize = computed(() => Math.max(18, Math.round(this.size() * .3)), ...ngDevMode ? [{ debugName: "badgeSize" }] : /* istanbul ignore next */ []);
1497
1509
  this.bg = computed(() => BG_PALETTE[colorIndex(this.initials())], ...ngDevMode ? [{ debugName: "bg" }] : /* istanbul ignore next */ []);
1498
1510
  this.color = computed(() => COLOR_PALETTE[colorIndex(this.initials())], ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
1499
1511
  }
1512
+ onImageError() {
1513
+ this.failedUrl.set(this.imageUrl() ?? null);
1514
+ this.imageError.emit();
1515
+ }
1516
+ onEdit() {
1517
+ if (this.busy()) return;
1518
+ this.editClick.emit();
1519
+ }
1520
+ onKey(event) {
1521
+ event.preventDefault();
1522
+ this.onEdit();
1523
+ }
1500
1524
  static {
1501
1525
  this.ɵfac = i0.ɵɵngDeclareFactory({
1502
1526
  minVersion: "12.0.0",
@@ -1509,7 +1533,7 @@ var AvatarComponent = class AvatarComponent {
1509
1533
  }
1510
1534
  static {
1511
1535
  this.ɵcmp = i0.ɵɵngDeclareComponent({
1512
- minVersion: "17.1.0",
1536
+ minVersion: "17.0.0",
1513
1537
  version: "22.2.2",
1514
1538
  type: AvatarComponent,
1515
1539
  isStandalone: true,
@@ -1535,24 +1559,91 @@ var AvatarComponent = class AvatarComponent {
1535
1559
  isSignal: true,
1536
1560
  isRequired: false,
1537
1561
  transformFunction: null
1562
+ },
1563
+ imageUrl: {
1564
+ classPropertyName: "imageUrl",
1565
+ publicName: "imageUrl",
1566
+ isSignal: true,
1567
+ isRequired: false,
1568
+ transformFunction: null
1569
+ },
1570
+ editable: {
1571
+ classPropertyName: "editable",
1572
+ publicName: "editable",
1573
+ isSignal: true,
1574
+ isRequired: false,
1575
+ transformFunction: null
1576
+ },
1577
+ editLabel: {
1578
+ classPropertyName: "editLabel",
1579
+ publicName: "editLabel",
1580
+ isSignal: true,
1581
+ isRequired: false,
1582
+ transformFunction: null
1583
+ },
1584
+ busy: {
1585
+ classPropertyName: "busy",
1586
+ publicName: "busy",
1587
+ isSignal: true,
1588
+ isRequired: false,
1589
+ transformFunction: null
1538
1590
  }
1539
1591
  },
1592
+ outputs: {
1593
+ editClick: "editClick",
1594
+ imageError: "imageError"
1595
+ },
1540
1596
  ngImport: i0,
1541
1597
  template: `
1542
- <span
1543
- class="avatar"
1544
- role="img"
1545
- [style.width.px]="size()"
1546
- [style.height.px]="size()"
1547
- [style.font-size.px]="size() * 0.38"
1548
- [style.background]="bg()"
1549
- [style.color]="color()"
1550
- [attr.aria-label]="name() || initials()">
1551
- {{ initials() }}
1552
- </span>
1598
+ @if (editable()) {
1599
+ <span class="av-edit" role="button" [attr.tabindex]="busy() ? -1 : 0" [attr.aria-label]="editLabel()" [attr.title]="editLabel()"
1600
+ [attr.aria-busy]="busy() ? 'true' : null" [attr.aria-disabled]="busy() ? 'true' : null" [class.av-busy]="busy()"
1601
+ [style.width.px]="size()" [style.height.px]="size()"
1602
+ (click)="onEdit()" (keydown.enter)="onKey($event)" (keydown.space)="onKey($event)">
1603
+ <ng-container [ngTemplateOutlet]="face" />
1604
+ <span class="av-badge" aria-hidden="true" [style.width.px]="badgeSize()" [style.height.px]="badgeSize()">
1605
+ @if (busy()) {
1606
+ <span class="av-spinner" [style.width.px]="badgeSize() * 0.6" [style.height.px]="badgeSize() * 0.6"></span>
1607
+ } @else {
1608
+ <svg [attr.width]="badgeSize() * 0.6" [attr.height]="badgeSize() * 0.6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
1609
+ }
1610
+ </span>
1611
+ </span>
1612
+ } @else {
1613
+ <ng-container [ngTemplateOutlet]="face" />
1614
+ }
1615
+ <ng-template #face>
1616
+ @if (showImage()) {
1617
+ <img class="avatar avatar-img" [src]="imageUrl()" [attr.alt]="editable() ? '' : (name() || initials())"
1618
+ [style.width.px]="size()" [style.height.px]="size()" (error)="onImageError()" />
1619
+ } @else {
1620
+ <span
1621
+ class="avatar"
1622
+ [attr.role]="editable() ? null : 'img'"
1623
+ [attr.aria-hidden]="editable() ? 'true' : null"
1624
+ [style.width.px]="size()"
1625
+ [style.height.px]="size()"
1626
+ [style.font-size.px]="size() * 0.38"
1627
+ [style.background]="bg()"
1628
+ [style.color]="color()"
1629
+ [attr.aria-label]="editable() ? null : (name() || initials())">
1630
+ {{ initials() }}
1631
+ </span>
1632
+ }
1633
+ </ng-template>
1553
1634
  `,
1554
1635
  isInline: true,
1555
- styles: [":host{display:inline-flex;flex-shrink:0}.avatar{border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;text-transform:uppercase;letter-spacing:.02em;-webkit-user-select:none;user-select:none;flex-shrink:0}\n"],
1636
+ styles: [":host{display:inline-flex;flex-shrink:0}.avatar{border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;text-transform:uppercase;letter-spacing:.02em;-webkit-user-select:none;user-select:none;flex-shrink:0}.avatar-img{display:block;object-fit:cover}.av-edit{position:relative;display:inline-flex;flex-shrink:0;border-radius:50%;cursor:pointer}.av-edit:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.av-edit.av-busy{cursor:progress}.av-edit.av-busy .avatar{opacity:.55}.av-badge{position:absolute;right:-2px;bottom:-2px;box-sizing:border-box;border-radius:50%;display:flex;align-items:center;justify-content:center;background:#fff;color:#475569;border:1px solid #cbd5e1;box-shadow:0 1px 2px #0f172a1f}@media(hover:hover){.av-edit:hover:not(.av-busy) .av-badge{color:#0f172a;border-color:#94a3b8}}.av-spinner{display:block;box-sizing:border-box;border:2px solid rgba(100,116,139,.3);border-top-color:currentColor;border-radius:50%;animation:av-spin .6s linear infinite}@keyframes av-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.av-spinner{animation-duration:2s}}@media(pointer:coarse){.av-edit:after{content:\"\";position:absolute;inset:-6px}}\n"],
1637
+ dependencies: [{
1638
+ kind: "directive",
1639
+ type: NgTemplateOutlet,
1640
+ selector: "[ngTemplateOutlet]",
1641
+ inputs: [
1642
+ "ngTemplateOutletContext",
1643
+ "ngTemplateOutlet",
1644
+ "ngTemplateOutletInjector"
1645
+ ]
1646
+ }],
1556
1647
  changeDetection: i0.ChangeDetectionStrategy.OnPush
1557
1648
  });
1558
1649
  }
@@ -1567,21 +1658,47 @@ i0.ɵɵngDeclareClassMetadata({
1567
1658
  args: [{
1568
1659
  selector: "ui-avatar",
1569
1660
  standalone: true,
1661
+ imports: [NgTemplateOutlet],
1570
1662
  changeDetection: ChangeDetectionStrategy.OnPush,
1571
1663
  template: `
1572
- <span
1573
- class="avatar"
1574
- role="img"
1575
- [style.width.px]="size()"
1576
- [style.height.px]="size()"
1577
- [style.font-size.px]="size() * 0.38"
1578
- [style.background]="bg()"
1579
- [style.color]="color()"
1580
- [attr.aria-label]="name() || initials()">
1581
- {{ initials() }}
1582
- </span>
1664
+ @if (editable()) {
1665
+ <span class="av-edit" role="button" [attr.tabindex]="busy() ? -1 : 0" [attr.aria-label]="editLabel()" [attr.title]="editLabel()"
1666
+ [attr.aria-busy]="busy() ? 'true' : null" [attr.aria-disabled]="busy() ? 'true' : null" [class.av-busy]="busy()"
1667
+ [style.width.px]="size()" [style.height.px]="size()"
1668
+ (click)="onEdit()" (keydown.enter)="onKey($event)" (keydown.space)="onKey($event)">
1669
+ <ng-container [ngTemplateOutlet]="face" />
1670
+ <span class="av-badge" aria-hidden="true" [style.width.px]="badgeSize()" [style.height.px]="badgeSize()">
1671
+ @if (busy()) {
1672
+ <span class="av-spinner" [style.width.px]="badgeSize() * 0.6" [style.height.px]="badgeSize() * 0.6"></span>
1673
+ } @else {
1674
+ <svg [attr.width]="badgeSize() * 0.6" [attr.height]="badgeSize() * 0.6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
1675
+ }
1676
+ </span>
1677
+ </span>
1678
+ } @else {
1679
+ <ng-container [ngTemplateOutlet]="face" />
1680
+ }
1681
+ <ng-template #face>
1682
+ @if (showImage()) {
1683
+ <img class="avatar avatar-img" [src]="imageUrl()" [attr.alt]="editable() ? '' : (name() || initials())"
1684
+ [style.width.px]="size()" [style.height.px]="size()" (error)="onImageError()" />
1685
+ } @else {
1686
+ <span
1687
+ class="avatar"
1688
+ [attr.role]="editable() ? null : 'img'"
1689
+ [attr.aria-hidden]="editable() ? 'true' : null"
1690
+ [style.width.px]="size()"
1691
+ [style.height.px]="size()"
1692
+ [style.font-size.px]="size() * 0.38"
1693
+ [style.background]="bg()"
1694
+ [style.color]="color()"
1695
+ [attr.aria-label]="editable() ? null : (name() || initials())">
1696
+ {{ initials() }}
1697
+ </span>
1698
+ }
1699
+ </ng-template>
1583
1700
  `,
1584
- styles: [":host{display:inline-flex;flex-shrink:0}.avatar{border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;text-transform:uppercase;letter-spacing:.02em;-webkit-user-select:none;user-select:none;flex-shrink:0}\n"]
1701
+ styles: [":host{display:inline-flex;flex-shrink:0}.avatar{border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;text-transform:uppercase;letter-spacing:.02em;-webkit-user-select:none;user-select:none;flex-shrink:0}.avatar-img{display:block;object-fit:cover}.av-edit{position:relative;display:inline-flex;flex-shrink:0;border-radius:50%;cursor:pointer}.av-edit:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.av-edit.av-busy{cursor:progress}.av-edit.av-busy .avatar{opacity:.55}.av-badge{position:absolute;right:-2px;bottom:-2px;box-sizing:border-box;border-radius:50%;display:flex;align-items:center;justify-content:center;background:#fff;color:#475569;border:1px solid #cbd5e1;box-shadow:0 1px 2px #0f172a1f}@media(hover:hover){.av-edit:hover:not(.av-busy) .av-badge{color:#0f172a;border-color:#94a3b8}}.av-spinner{display:block;box-sizing:border-box;border:2px solid rgba(100,116,139,.3);border-top-color:currentColor;border-radius:50%;animation:av-spin .6s linear infinite}@keyframes av-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.av-spinner{animation-duration:2s}}@media(pointer:coarse){.av-edit:after{content:\"\";position:absolute;inset:-6px}}\n"]
1585
1702
  }]
1586
1703
  }],
1587
1704
  propDecorators: {
@@ -1608,6 +1725,46 @@ i0.ɵɵngDeclareClassMetadata({
1608
1725
  alias: "size",
1609
1726
  required: false
1610
1727
  }]
1728
+ }],
1729
+ imageUrl: [{
1730
+ type: i0.Input,
1731
+ args: [{
1732
+ isSignal: true,
1733
+ alias: "imageUrl",
1734
+ required: false
1735
+ }]
1736
+ }],
1737
+ editable: [{
1738
+ type: i0.Input,
1739
+ args: [{
1740
+ isSignal: true,
1741
+ alias: "editable",
1742
+ required: false
1743
+ }]
1744
+ }],
1745
+ editLabel: [{
1746
+ type: i0.Input,
1747
+ args: [{
1748
+ isSignal: true,
1749
+ alias: "editLabel",
1750
+ required: false
1751
+ }]
1752
+ }],
1753
+ busy: [{
1754
+ type: i0.Input,
1755
+ args: [{
1756
+ isSignal: true,
1757
+ alias: "busy",
1758
+ required: false
1759
+ }]
1760
+ }],
1761
+ editClick: [{
1762
+ type: i0.Output,
1763
+ args: ["editClick"]
1764
+ }],
1765
+ imageError: [{
1766
+ type: i0.Output,
1767
+ args: ["imageError"]
1611
1768
  }]
1612
1769
  }
1613
1770
  });
@@ -9256,6 +9413,15 @@ var EmptyStateComponent = class EmptyStateComponent {
9256
9413
  @case ('shield') {
9257
9414
  <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
9258
9415
  }
9416
+ @case ('pipeline') {
9417
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 4h18l-7 8.5V19l-4 2v-8.5z"/></svg>
9418
+ }
9419
+ @case ('property') {
9420
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16"/><path d="M16 11h2a2 2 0 0 1 2 2v8"/><path d="M2 21h20"/><path d="M8 7h4M8 11h4M8 15h4"/></svg>
9421
+ }
9422
+ @case ('clipboard') {
9423
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="4" width="14" height="18" rx="2"/><path d="M9 2h6v4H9z"/><path d="m8.5 12 1.5 1.5 2.5-3"/><path d="M14.5 12.5H16M8.5 18H16"/></svg>
9424
+ }
9259
9425
  @default {
9260
9426
  <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
9261
9427
  }
@@ -9330,6 +9496,15 @@ i0.ɵɵngDeclareClassMetadata({
9330
9496
  @case ('shield') {
9331
9497
  <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
9332
9498
  }
9499
+ @case ('pipeline') {
9500
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 4h18l-7 8.5V19l-4 2v-8.5z"/></svg>
9501
+ }
9502
+ @case ('property') {
9503
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16"/><path d="M16 11h2a2 2 0 0 1 2 2v8"/><path d="M2 21h20"/><path d="M8 7h4M8 11h4M8 15h4"/></svg>
9504
+ }
9505
+ @case ('clipboard') {
9506
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="4" width="14" height="18" rx="2"/><path d="M9 2h6v4H9z"/><path d="m8.5 12 1.5 1.5 2.5-3"/><path d="M14.5 12.5H16M8.5 18H16"/></svg>
9507
+ }
9333
9508
  @default {
9334
9509
  <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
9335
9510
  }
@@ -11943,8 +12118,13 @@ var DataTableComponent = class DataTableComponent {
11943
12118
  inputs: [
11944
12119
  "initials",
11945
12120
  "name",
11946
- "size"
11947
- ]
12121
+ "size",
12122
+ "imageUrl",
12123
+ "editable",
12124
+ "editLabel",
12125
+ "busy"
12126
+ ],
12127
+ outputs: ["editClick", "imageError"]
11948
12128
  },
11949
12129
  {
11950
12130
  kind: "component",
@@ -25351,12 +25531,20 @@ function getErrorMessage(error, fallbackContext, action) {
25351
25531
  if (typeof error === "string") return error;
25352
25532
  return `${failed} Please try again.`;
25353
25533
  }
25534
+ const NOTES_MAX_LENGTH = 1e4;
25354
25535
  const NOTES_PAGE_SIZE = 5;
25355
25536
  var NotesComponent = class NotesComponent {
25356
25537
  initials(name) {
25357
25538
  const parts = (name || "You").trim().split(/\s+/).filter(Boolean);
25358
25539
  return ((parts[0]?.[0] ?? "") + (parts.length > 1 ? parts[parts.length - 1][0] : "")).toUpperCase();
25359
25540
  }
25541
+ tooLong(text) {
25542
+ return text.trim().length > NOTES_MAX_LENGTH;
25543
+ }
25544
+ validBody(text) {
25545
+ const n = text.trim().length;
25546
+ return n > 0 && n <= 1e4;
25547
+ }
25360
25548
  get listUrl() {
25361
25549
  return `${this.apiBase}/notes/${this.resourceType()}/${this.resourceId()}`;
25362
25550
  }
@@ -25370,6 +25558,7 @@ var NotesComponent = class NotesComponent {
25370
25558
  this.destroyRef = inject(DestroyRef);
25371
25559
  this.apiBase = inject(FORGEROUTE_CONFIG, { optional: true })?.baseUrl ?? "/api";
25372
25560
  this.pageSize = NOTES_PAGE_SIZE;
25561
+ this.maxLength = NOTES_MAX_LENGTH;
25373
25562
  this.notes = signal([], ...ngDevMode ? [{ debugName: "notes" }] : /* istanbul ignore next */ []);
25374
25563
  this.loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
25375
25564
  this.saving = signal(false, ...ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []);
@@ -25403,7 +25592,7 @@ var NotesComponent = class NotesComponent {
25403
25592
  });
25404
25593
  }
25405
25594
  addNote() {
25406
- if (this.readOnly() || !this.newBody.trim() || this.saving()) return;
25595
+ if (this.readOnly() || !this.validBody(this.newBody) || this.saving()) return;
25407
25596
  this.saving.set(true);
25408
25597
  this.http.post(this.listUrl, { body: this.newBody.trim() }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
25409
25598
  next: () => {
@@ -25427,7 +25616,7 @@ var NotesComponent = class NotesComponent {
25427
25616
  this.editBody = "";
25428
25617
  }
25429
25618
  saveEdit(noteId) {
25430
- if (this.readOnly() || !this.editBody.trim() || this.saving()) return;
25619
+ if (this.readOnly() || !this.validBody(this.editBody) || this.saving()) return;
25431
25620
  this.saving.set(true);
25432
25621
  this.http.put(`${this.apiBase}/notes/${noteId}`, { body: this.editBody.trim() }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
25433
25622
  next: (updated) => {
@@ -25507,10 +25696,10 @@ var NotesComponent = class NotesComponent {
25507
25696
  template: `
25508
25697
  @if (!readOnly()) {
25509
25698
  <div class="note-add">
25510
- <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [disabled]="saving()" [(ngModel)]="newBody"
25699
+ <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
25511
25700
  (keydown.meta.enter)="addNote()" (keydown.control.enter)="addNote()" />
25512
25701
  <div class="note-add-footer">
25513
- <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!newBody.trim()" (click)="addNote()">Add Note</ui-button>
25702
+ <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!validBody(newBody)" (click)="addNote()">Add Note</ui-button>
25514
25703
  </div>
25515
25704
  </div>
25516
25705
  }
@@ -25534,20 +25723,16 @@ var NotesComponent = class NotesComponent {
25534
25723
  }
25535
25724
  @if (!readOnly() && editingId() !== note.id) {
25536
25725
  <div class="note-actions">
25537
- <ui-button variant="icon" size="xs" ariaLabel="Edit note" uiTooltip="Edit note" (click)="startEdit(note)">
25538
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
25539
- </ui-button>
25540
- <ui-button variant="icon-danger" size="xs" ariaLabel="Delete note" uiTooltip="Delete note" (click)="confirmDelete(note.id)">
25541
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>
25542
- </ui-button>
25726
+ <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
25727
+ <ui-icon name="delete" variant="danger" [size]="14" tooltip="Delete note" (iconClick)="confirmDelete(note.id)" />
25543
25728
  </div>
25544
25729
  }
25545
25730
  </div>
25546
25731
  @if (editingId() === note.id) {
25547
- <ui-textarea-input ariaLabel="Edit note" [rows]="3" [disabled]="saving()" [(ngModel)]="editBody" />
25732
+ <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
25548
25733
  <div class="note-item-footer">
25549
25734
  <ui-button variant="secondary" size="sm" (click)="cancelEdit()">Cancel</ui-button>
25550
- <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!editBody.trim()" (click)="saveEdit(note.id)">Save</ui-button>
25735
+ <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!validBody(editBody)" (click)="saveEdit(note.id)">Save</ui-button>
25551
25736
  </div>
25552
25737
  } @else {
25553
25738
  <p class="note-body">{{ note.body }}</p>
@@ -25577,6 +25762,12 @@ var NotesComponent = class NotesComponent {
25577
25762
  type: i1.NgControlStatus,
25578
25763
  selector: "[formControlName],[ngModel],[formControl]"
25579
25764
  },
25765
+ {
25766
+ kind: "directive",
25767
+ type: i1.MaxLengthValidator,
25768
+ selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",
25769
+ inputs: ["maxlength"]
25770
+ },
25580
25771
  {
25581
25772
  kind: "directive",
25582
25773
  type: i1.NgModel,
@@ -25682,10 +25873,20 @@ var NotesComponent = class NotesComponent {
25682
25873
  outputs: ["invalidChange"]
25683
25874
  },
25684
25875
  {
25685
- kind: "directive",
25686
- type: TooltipDirective,
25687
- selector: "[uiTooltip]",
25688
- inputs: ["uiTooltip", "tooltipPosition"]
25876
+ kind: "component",
25877
+ type: IconComponent,
25878
+ selector: "ui-icon",
25879
+ inputs: [
25880
+ "name",
25881
+ "tooltip",
25882
+ "ariaLabel",
25883
+ "size",
25884
+ "variant",
25885
+ "disabled",
25886
+ "loading",
25887
+ "interactive"
25888
+ ],
25889
+ outputs: ["iconClick"]
25689
25890
  },
25690
25891
  {
25691
25892
  kind: "component",
@@ -25694,8 +25895,13 @@ var NotesComponent = class NotesComponent {
25694
25895
  inputs: [
25695
25896
  "initials",
25696
25897
  "name",
25697
- "size"
25698
- ]
25898
+ "size",
25899
+ "imageUrl",
25900
+ "editable",
25901
+ "editLabel",
25902
+ "busy"
25903
+ ],
25904
+ outputs: ["editClick", "imageError"]
25699
25905
  },
25700
25906
  {
25701
25907
  kind: "pipe",
@@ -25726,16 +25932,16 @@ i0.ɵɵngDeclareClassMetadata({
25726
25932
  EmptyStateComponent,
25727
25933
  PaginationComponent,
25728
25934
  TextareaInputComponent,
25729
- TooltipDirective,
25935
+ IconComponent,
25730
25936
  AvatarComponent
25731
25937
  ],
25732
25938
  template: `
25733
25939
  @if (!readOnly()) {
25734
25940
  <div class="note-add">
25735
- <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [disabled]="saving()" [(ngModel)]="newBody"
25941
+ <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
25736
25942
  (keydown.meta.enter)="addNote()" (keydown.control.enter)="addNote()" />
25737
25943
  <div class="note-add-footer">
25738
- <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!newBody.trim()" (click)="addNote()">Add Note</ui-button>
25944
+ <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!validBody(newBody)" (click)="addNote()">Add Note</ui-button>
25739
25945
  </div>
25740
25946
  </div>
25741
25947
  }
@@ -25759,20 +25965,16 @@ i0.ɵɵngDeclareClassMetadata({
25759
25965
  }
25760
25966
  @if (!readOnly() && editingId() !== note.id) {
25761
25967
  <div class="note-actions">
25762
- <ui-button variant="icon" size="xs" ariaLabel="Edit note" uiTooltip="Edit note" (click)="startEdit(note)">
25763
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
25764
- </ui-button>
25765
- <ui-button variant="icon-danger" size="xs" ariaLabel="Delete note" uiTooltip="Delete note" (click)="confirmDelete(note.id)">
25766
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>
25767
- </ui-button>
25968
+ <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
25969
+ <ui-icon name="delete" variant="danger" [size]="14" tooltip="Delete note" (iconClick)="confirmDelete(note.id)" />
25768
25970
  </div>
25769
25971
  }
25770
25972
  </div>
25771
25973
  @if (editingId() === note.id) {
25772
- <ui-textarea-input ariaLabel="Edit note" [rows]="3" [disabled]="saving()" [(ngModel)]="editBody" />
25974
+ <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
25773
25975
  <div class="note-item-footer">
25774
25976
  <ui-button variant="secondary" size="sm" (click)="cancelEdit()">Cancel</ui-button>
25775
- <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!editBody.trim()" (click)="saveEdit(note.id)">Save</ui-button>
25977
+ <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!validBody(editBody)" (click)="saveEdit(note.id)">Save</ui-button>
25776
25978
  </div>
25777
25979
  } @else {
25778
25980
  <p class="note-body">{{ note.body }}</p>
@@ -25849,11 +26051,11 @@ const LAYOUT_GAP_PX = {
25849
26051
  lg: 24,
25850
26052
  xl: 32
25851
26053
  };
25852
- const CSS_LENGTH = /^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|vh|vw|ch)|(?:calc|var)\([^;{}]*\))$/i;
26054
+ const CSS_LENGTH$1 = /^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|vh|vw|ch)|(?:calc|var)\([^;{}]*\))$/i;
25853
26055
  function resolveLayoutGap(gap, fallback) {
25854
26056
  const v = (gap ?? "").trim();
25855
26057
  if (Object.prototype.hasOwnProperty.call(LAYOUT_GAP_PX, v)) return `${LAYOUT_GAP_PX[v]}px`;
25856
- if (v && CSS_LENGTH.test(v)) return v;
26058
+ if (v && CSS_LENGTH$1.test(v)) return v;
25857
26059
  return `${LAYOUT_GAP_PX[fallback]}px`;
25858
26060
  }
25859
26061
  function reorderItems(items, order) {
@@ -27847,6 +28049,7 @@ var PanelInfoListComponent = class PanelInfoListComponent {
27847
28049
  this.sections = input([], ...ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []);
27848
28050
  this.showEmptyState = input(false, ...ngDevMode ? [{ debugName: "showEmptyState" }] : /* istanbul ignore next */ []);
27849
28051
  this.labelColon = input(false, ...ngDevMode ? [{ debugName: "labelColon" }] : /* istanbul ignore next */ []);
28052
+ this.fill = input(false, ...ngDevMode ? [{ debugName: "fill" }] : /* istanbul ignore next */ []);
27850
28053
  this.displaySections = computed(() => this.showEmptyState() ? this.sections() : this.sections().filter((s) => s.items.some((i) => !i.hidden)), ...ngDevMode ? [{ debugName: "displaySections" }] : /* istanbul ignore next */ []);
27851
28054
  }
27852
28055
  hrefOf(item) {
@@ -27912,8 +28115,16 @@ var PanelInfoListComponent = class PanelInfoListComponent {
27912
28115
  isSignal: true,
27913
28116
  isRequired: false,
27914
28117
  transformFunction: null
28118
+ },
28119
+ fill: {
28120
+ classPropertyName: "fill",
28121
+ publicName: "fill",
28122
+ isSignal: true,
28123
+ isRequired: false,
28124
+ transformFunction: null
27915
28125
  }
27916
28126
  },
28127
+ host: { properties: { "class.pil-fill": "fill()" } },
27917
28128
  ngImport: i0,
27918
28129
  template: `
27919
28130
  @for (section of displaySections(); track section.title ?? $index) {
@@ -27981,7 +28192,7 @@ var PanelInfoListComponent = class PanelInfoListComponent {
27981
28192
  }
27982
28193
  `,
27983
28194
  isInline: true,
27984
- styles: [":host{display:flex;flex-direction:column;gap:12px}.pil-section{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.pil-section-label{display:flex;justify-content:space-between;align-items:center;font-size:.6875rem;font-weight:700;letter-spacing:.07em;color:#94a3b8;text-transform:uppercase;padding:8px 14px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.pil-header-link{font-size:.75rem;font-weight:500;color:#2563eb;text-decoration:none;text-transform:none;letter-spacing:0}.pil-header-link:hover{text-decoration:underline}.pil-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:9px 14px;border-bottom:1px solid #f1f5f9}.pil-row:last-child{border-bottom:none}.pil-row--inline{justify-content:flex-start}.pil-row--inline .pil-value{text-align:left;justify-content:flex-start;flex-wrap:wrap;min-width:0;overflow-wrap:anywhere;word-break:break-word}.pil-label{font-size:.8125rem;color:#64748b;flex-shrink:0}.pil-value{font-size:.875rem;font-weight:500;color:#1e293b;text-align:right;display:flex;align-items:center;justify-content:flex-end}.pil-multiline{white-space:pre-line;overflow-wrap:anywhere;word-break:break-word}.pil-strong .pil-label,.pil-strong .pil-value,.pil-strong .pil-muted{font-weight:700;color:#0f172a}.pil-badges{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}.pil-edit-btn{margin-left:4px;flex-shrink:0}ui-empty-state{padding:12px 0}.pil-muted{color:#1e293b;font-weight:400}.pil-danger{color:#ef4444;font-weight:600}.pil-link{font-size:.875rem;font-weight:500;color:#2563eb;text-decoration:none}.pil-link:hover{text-decoration:underline}.pil-link--href{overflow-wrap:anywhere;word-break:break-word}.pil-link:focus-visible,.pil-header-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:2px}.pil-link-icon{display:inline-flex;align-items:center;gap:5px;font-size:.875rem;font-weight:500;color:#1e293b;text-decoration:none}.pil-link-icon svg{color:#94a3b8;flex-shrink:0}.pil-grid-2{display:grid;grid-template-columns:1fr 1fr}.pil-grid-cell{display:flex;flex-direction:column;gap:3px;padding:10px 14px;border-right:1px solid #f1f5f9}.pil-grid-cell:last-child{border-right:none}.pil-value--block{text-align:left;justify-content:flex-start}\n"],
28195
+ styles: [":host{display:flex;flex-direction:column;gap:12px}:host(.pil-fill){flex:1;min-height:0}:host(.pil-fill) .pil-section{flex:1}.pil-section{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.pil-section-label{display:flex;justify-content:space-between;align-items:center;font-size:.6875rem;font-weight:700;letter-spacing:.07em;color:#94a3b8;text-transform:uppercase;padding:8px 14px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.pil-header-link{font-size:.75rem;font-weight:500;color:#2563eb;text-decoration:none;text-transform:none;letter-spacing:0}.pil-header-link:hover{text-decoration:underline}.pil-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:9px 14px;border-bottom:1px solid #f1f5f9}.pil-row:last-child{border-bottom:none}.pil-row--inline{justify-content:flex-start}.pil-row--inline .pil-value{text-align:left;justify-content:flex-start;flex-wrap:wrap;min-width:0;overflow-wrap:anywhere;word-break:break-word}.pil-label{font-size:.8125rem;color:#64748b;flex-shrink:0}.pil-value{font-size:.875rem;font-weight:500;color:#1e293b;text-align:right;display:flex;align-items:center;justify-content:flex-end}.pil-multiline{white-space:pre-line;overflow-wrap:anywhere;word-break:break-word}.pil-strong .pil-label,.pil-strong .pil-value,.pil-strong .pil-muted{font-weight:700;color:#0f172a}.pil-badges{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}.pil-edit-btn{margin-left:4px;flex-shrink:0}ui-empty-state{padding:12px 0}.pil-muted{color:#1e293b;font-weight:400}.pil-danger{color:#ef4444;font-weight:600}.pil-link{font-size:.875rem;font-weight:500;color:#2563eb;text-decoration:none}.pil-link:hover{text-decoration:underline}.pil-link--href{overflow-wrap:anywhere;word-break:break-word}.pil-link:focus-visible,.pil-header-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:2px}.pil-link-icon{display:inline-flex;align-items:center;gap:5px;font-size:.875rem;font-weight:500;color:#1e293b;text-decoration:none}.pil-link-icon svg{color:#94a3b8;flex-shrink:0}.pil-grid-2{display:grid;grid-template-columns:1fr 1fr}.pil-grid-cell{display:flex;flex-direction:column;gap:3px;padding:10px 14px;border-right:1px solid #f1f5f9}.pil-grid-cell:last-child{border-right:none}.pil-value--block{text-align:left;justify-content:flex-start}\n"],
27985
28196
  dependencies: [
27986
28197
  {
27987
28198
  kind: "component",
@@ -28056,6 +28267,7 @@ i0.ɵɵngDeclareClassMetadata({
28056
28267
  EmptyStateComponent,
28057
28268
  IconComponent
28058
28269
  ],
28270
+ host: { "[class.pil-fill]": "fill()" },
28059
28271
  template: `
28060
28272
  @for (section of displaySections(); track section.title ?? $index) {
28061
28273
  <div class="pil-section">
@@ -28121,7 +28333,7 @@ i0.ɵɵngDeclareClassMetadata({
28121
28333
  </div>
28122
28334
  }
28123
28335
  `,
28124
- styles: [":host{display:flex;flex-direction:column;gap:12px}.pil-section{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.pil-section-label{display:flex;justify-content:space-between;align-items:center;font-size:.6875rem;font-weight:700;letter-spacing:.07em;color:#94a3b8;text-transform:uppercase;padding:8px 14px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.pil-header-link{font-size:.75rem;font-weight:500;color:#2563eb;text-decoration:none;text-transform:none;letter-spacing:0}.pil-header-link:hover{text-decoration:underline}.pil-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:9px 14px;border-bottom:1px solid #f1f5f9}.pil-row:last-child{border-bottom:none}.pil-row--inline{justify-content:flex-start}.pil-row--inline .pil-value{text-align:left;justify-content:flex-start;flex-wrap:wrap;min-width:0;overflow-wrap:anywhere;word-break:break-word}.pil-label{font-size:.8125rem;color:#64748b;flex-shrink:0}.pil-value{font-size:.875rem;font-weight:500;color:#1e293b;text-align:right;display:flex;align-items:center;justify-content:flex-end}.pil-multiline{white-space:pre-line;overflow-wrap:anywhere;word-break:break-word}.pil-strong .pil-label,.pil-strong .pil-value,.pil-strong .pil-muted{font-weight:700;color:#0f172a}.pil-badges{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}.pil-edit-btn{margin-left:4px;flex-shrink:0}ui-empty-state{padding:12px 0}.pil-muted{color:#1e293b;font-weight:400}.pil-danger{color:#ef4444;font-weight:600}.pil-link{font-size:.875rem;font-weight:500;color:#2563eb;text-decoration:none}.pil-link:hover{text-decoration:underline}.pil-link--href{overflow-wrap:anywhere;word-break:break-word}.pil-link:focus-visible,.pil-header-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:2px}.pil-link-icon{display:inline-flex;align-items:center;gap:5px;font-size:.875rem;font-weight:500;color:#1e293b;text-decoration:none}.pil-link-icon svg{color:#94a3b8;flex-shrink:0}.pil-grid-2{display:grid;grid-template-columns:1fr 1fr}.pil-grid-cell{display:flex;flex-direction:column;gap:3px;padding:10px 14px;border-right:1px solid #f1f5f9}.pil-grid-cell:last-child{border-right:none}.pil-value--block{text-align:left;justify-content:flex-start}\n"]
28336
+ styles: [":host{display:flex;flex-direction:column;gap:12px}:host(.pil-fill){flex:1;min-height:0}:host(.pil-fill) .pil-section{flex:1}.pil-section{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.pil-section-label{display:flex;justify-content:space-between;align-items:center;font-size:.6875rem;font-weight:700;letter-spacing:.07em;color:#94a3b8;text-transform:uppercase;padding:8px 14px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.pil-header-link{font-size:.75rem;font-weight:500;color:#2563eb;text-decoration:none;text-transform:none;letter-spacing:0}.pil-header-link:hover{text-decoration:underline}.pil-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:9px 14px;border-bottom:1px solid #f1f5f9}.pil-row:last-child{border-bottom:none}.pil-row--inline{justify-content:flex-start}.pil-row--inline .pil-value{text-align:left;justify-content:flex-start;flex-wrap:wrap;min-width:0;overflow-wrap:anywhere;word-break:break-word}.pil-label{font-size:.8125rem;color:#64748b;flex-shrink:0}.pil-value{font-size:.875rem;font-weight:500;color:#1e293b;text-align:right;display:flex;align-items:center;justify-content:flex-end}.pil-multiline{white-space:pre-line;overflow-wrap:anywhere;word-break:break-word}.pil-strong .pil-label,.pil-strong .pil-value,.pil-strong .pil-muted{font-weight:700;color:#0f172a}.pil-badges{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}.pil-edit-btn{margin-left:4px;flex-shrink:0}ui-empty-state{padding:12px 0}.pil-muted{color:#1e293b;font-weight:400}.pil-danger{color:#ef4444;font-weight:600}.pil-link{font-size:.875rem;font-weight:500;color:#2563eb;text-decoration:none}.pil-link:hover{text-decoration:underline}.pil-link--href{overflow-wrap:anywhere;word-break:break-word}.pil-link:focus-visible,.pil-header-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:2px}.pil-link-icon{display:inline-flex;align-items:center;gap:5px;font-size:.875rem;font-weight:500;color:#1e293b;text-decoration:none}.pil-link-icon svg{color:#94a3b8;flex-shrink:0}.pil-grid-2{display:grid;grid-template-columns:1fr 1fr}.pil-grid-cell{display:flex;flex-direction:column;gap:3px;padding:10px 14px;border-right:1px solid #f1f5f9}.pil-grid-cell:last-child{border-right:none}.pil-value--block{text-align:left;justify-content:flex-start}\n"]
28125
28337
  }]
28126
28338
  }],
28127
28339
  propDecorators: {
@@ -28148,6 +28360,14 @@ i0.ɵɵngDeclareClassMetadata({
28148
28360
  alias: "labelColon",
28149
28361
  required: false
28150
28362
  }]
28363
+ }],
28364
+ fill: [{
28365
+ type: i0.Input,
28366
+ args: [{
28367
+ isSignal: true,
28368
+ alias: "fill",
28369
+ required: false
28370
+ }]
28151
28371
  }]
28152
28372
  }
28153
28373
  });
@@ -29327,6 +29547,98 @@ var TimelineComponent = class TimelineComponent {
29327
29547
  this.emptyMessage = input("", ...ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []);
29328
29548
  this.maxHeight = input("", ...ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []);
29329
29549
  this.timePosition = input("below", ...ngDevMode ? [{ debugName: "timePosition" }] : /* istanbul ignore next */ []);
29550
+ this.groupByDay = input(false, ...ngDevMode ? [{ debugName: "groupByDay" }] : /* istanbul ignore next */ []);
29551
+ this.timeZone = input("", ...ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []);
29552
+ this.now = input(null, ...ngDevMode ? [{ debugName: "now" }] : /* istanbul ignore next */ []);
29553
+ this.dayHeadingLevel = input(3, ...ngDevMode ? [{ debugName: "dayHeadingLevel" }] : /* istanbul ignore next */ []);
29554
+ this.headingLevel = computed(() => {
29555
+ const n = this.dayHeadingLevel();
29556
+ return Number.isInteger(n) && n >= 1 && n <= 6 ? n : 3;
29557
+ }, ...ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []);
29558
+ this.groups = computed(() => {
29559
+ if (!this.groupByDay()) return [];
29560
+ const zone = this.timeZone() || void 0;
29561
+ let fmt;
29562
+ try {
29563
+ fmt = new Intl.DateTimeFormat("en-US", {
29564
+ timeZone: zone,
29565
+ year: "numeric",
29566
+ month: "2-digit",
29567
+ day: "2-digit"
29568
+ });
29569
+ } catch {
29570
+ fmt = new Intl.DateTimeFormat("en-US", {
29571
+ year: "numeric",
29572
+ month: "2-digit",
29573
+ day: "2-digit"
29574
+ });
29575
+ }
29576
+ const parts = (d) => {
29577
+ const p = fmt.formatToParts(d);
29578
+ const get = (t) => Number(p.find((x) => x.type === t)?.value);
29579
+ return {
29580
+ y: get("year"),
29581
+ m: get("month"),
29582
+ d: get("day")
29583
+ };
29584
+ };
29585
+ const keyOf = (v) => `${v.y}-${String(v.m).padStart(2, "0")}-${String(v.d).padStart(2, "0")}`;
29586
+ const nowRaw = this.now();
29587
+ let nowDate = nowRaw == null ? /* @__PURE__ */ new Date() : new Date(nowRaw);
29588
+ if (isNaN(nowDate.getTime())) nowDate = /* @__PURE__ */ new Date();
29589
+ const t = parts(nowDate);
29590
+ const todayKey = keyOf(t);
29591
+ const yd = new Date(Date.UTC(t.y, t.m - 1, t.d - 1));
29592
+ const yesterdayKey = keyOf({
29593
+ y: yd.getUTCFullYear(),
29594
+ m: yd.getUTCMonth() + 1,
29595
+ d: yd.getUTCDate()
29596
+ });
29597
+ const labelFmt = (withYear, tz) => new Intl.DateTimeFormat("en-US", {
29598
+ timeZone: tz,
29599
+ month: "short",
29600
+ day: "numeric",
29601
+ ...withYear ? { year: "numeric" } : {}
29602
+ });
29603
+ const label = (v) => keyOf(v) === todayKey ? "Today" : keyOf(v) === yesterdayKey ? "Yesterday" : labelFmt(v.y !== t.y, "UTC").format(new Date(Date.UTC(v.y, v.m - 1, v.d)));
29604
+ const dayOf = (iso) => {
29605
+ const m = iso ? /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?)?$/.exec(iso) : null;
29606
+ if (!m) return null;
29607
+ const y = Number(m[1]), mo = Number(m[2]), d = Number(m[3]);
29608
+ const probe = new Date(Date.UTC(y, mo - 1, d));
29609
+ if (probe.getUTCFullYear() !== y || probe.getUTCMonth() !== mo - 1 || probe.getUTCDate() !== d) return null;
29610
+ if (m[4] !== void 0 && (Number(m[4]) > 23 || Number(m[5]) > 59 || m[6] !== void 0 && Number(m[6]) > 59)) return null;
29611
+ if (m[7] === void 0) return {
29612
+ y,
29613
+ m: mo,
29614
+ d
29615
+ };
29616
+ const inst = new Date(iso.replace(/([+-]\d{2})(\d{2})$/, "$1:$2"));
29617
+ return isNaN(inst.getTime()) ? null : parts(inst);
29618
+ };
29619
+ const groups = [];
29620
+ for (const item of this.items()) {
29621
+ const v = dayOf(item.dateTime);
29622
+ const last = groups[groups.length - 1];
29623
+ if (!v) {
29624
+ if (last) last.items.push(item);
29625
+ else groups.push({
29626
+ key: "",
29627
+ label: "",
29628
+ items: [item]
29629
+ });
29630
+ continue;
29631
+ }
29632
+ const key = keyOf(v);
29633
+ if (last && last.key === key) last.items.push(item);
29634
+ else groups.push({
29635
+ key,
29636
+ label: label(v),
29637
+ items: [item]
29638
+ });
29639
+ }
29640
+ return groups;
29641
+ }, ...ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []);
29330
29642
  }
29331
29643
  dotColor(item) {
29332
29644
  return item.dotVariant ? BADGE_VARIANT_STYLES[item.dotVariant]?.color ?? null : null;
@@ -29383,6 +29695,34 @@ var TimelineComponent = class TimelineComponent {
29383
29695
  isSignal: true,
29384
29696
  isRequired: false,
29385
29697
  transformFunction: null
29698
+ },
29699
+ groupByDay: {
29700
+ classPropertyName: "groupByDay",
29701
+ publicName: "groupByDay",
29702
+ isSignal: true,
29703
+ isRequired: false,
29704
+ transformFunction: null
29705
+ },
29706
+ timeZone: {
29707
+ classPropertyName: "timeZone",
29708
+ publicName: "timeZone",
29709
+ isSignal: true,
29710
+ isRequired: false,
29711
+ transformFunction: null
29712
+ },
29713
+ now: {
29714
+ classPropertyName: "now",
29715
+ publicName: "now",
29716
+ isSignal: true,
29717
+ isRequired: false,
29718
+ transformFunction: null
29719
+ },
29720
+ dayHeadingLevel: {
29721
+ classPropertyName: "dayHeadingLevel",
29722
+ publicName: "dayHeadingLevel",
29723
+ isSignal: true,
29724
+ isRequired: false,
29725
+ transformFunction: null
29386
29726
  }
29387
29727
  },
29388
29728
  ngImport: i0,
@@ -29399,29 +29739,47 @@ var TimelineComponent = class TimelineComponent {
29399
29739
  <ui-hint class="tl-empty">{{ emptyMessage() }}</ui-hint>
29400
29740
  }
29401
29741
  <ng-template #listTpl>
29402
- <ol class="tl" [attr.aria-label]="ariaLabel() || null">
29403
- @for (item of items(); track item.id ?? $index) {
29404
- <li [attr.data-testid]="item.testId || null" class="tl-item" [class]="'tl-item tl-item--' + (item.tone ?? 'default')" [class.tl-item--icon]="!!item.icon" [style.--tl-color]="dotColor(item)">
29405
- <span class="tl-marker" aria-hidden="true">
29406
- @if (item.icon) { <ui-icon [name]="item.icon" [interactive]="false" [size]="12" /> }
29407
- </span>
29408
- <div class="tl-content">
29409
- <div class="tl-head">
29410
- <span class="tl-title">{{ item.title }}</span>
29411
- @if (item.badge) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: item.badge }" /> }
29412
- @for (b of item.badges ?? []; track $index) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: b }" /> }
29413
- @if (timePosition() === 'end' && (item.time || item.dateTime)) {
29414
- <time class="tl-time tl-time--end" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29742
+ @if (groupByDay()) {
29743
+ <ol class="tl tl-grouped" [attr.aria-label]="ariaLabel() || null">
29744
+ @for (g of groups(); track $index) {
29745
+ <li class="tl-day-group" [attr.data-day]="g.key || null">
29746
+ @if (g.label) { <div class="tl-day" role="heading" [attr.aria-level]="headingLevel()">{{ g.label }}</div> }
29747
+ <ol class="tl-sub">
29748
+ @for (item of g.items; track item.id ?? $index) {
29749
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29415
29750
  }
29416
- </div>
29417
- @if (item.description) { <p class="tl-description">{{ item.description }}</p> }
29418
- @if (timePosition() !== 'end' && (item.time || item.dateTime)) {
29419
- <time class="tl-time" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29420
- }
29421
- </div>
29422
- </li>
29423
- }
29424
- </ol>
29751
+ </ol>
29752
+ </li>
29753
+ }
29754
+ </ol>
29755
+ } @else {
29756
+ <ol class="tl" [attr.aria-label]="ariaLabel() || null">
29757
+ @for (item of items(); track item.id ?? $index) {
29758
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29759
+ }
29760
+ </ol>
29761
+ }
29762
+ </ng-template>
29763
+ <ng-template #itemTpl let-item>
29764
+ <li [attr.data-testid]="item.testId || null" class="tl-item" [class]="'tl-item tl-item--' + (item.tone ?? 'default')" [class.tl-item--icon]="!!item.icon" [style.--tl-color]="dotColor(item)">
29765
+ <span class="tl-marker" aria-hidden="true">
29766
+ @if (item.icon) { <ui-icon [name]="item.icon" [interactive]="false" [size]="12" /> }
29767
+ </span>
29768
+ <div class="tl-content">
29769
+ <div class="tl-head">
29770
+ <span class="tl-title">{{ item.title }}</span>
29771
+ @if (item.badge) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: item.badge }" /> }
29772
+ @for (b of item.badges ?? []; track $index) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: b }" /> }
29773
+ @if (timePosition() === 'end' && (item.time || item.dateTime)) {
29774
+ <time class="tl-time tl-time--end" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29775
+ }
29776
+ </div>
29777
+ @if (item.description) { <p class="tl-description">{{ item.description }}</p> }
29778
+ @if (timePosition() !== 'end' && (item.time || item.dateTime)) {
29779
+ <time class="tl-time" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29780
+ }
29781
+ </div>
29782
+ </li>
29425
29783
  </ng-template>
29426
29784
  <ng-template #badgeTpl let-b>
29427
29785
  @if (b.tooltip) {
@@ -29432,7 +29790,7 @@ var TimelineComponent = class TimelineComponent {
29432
29790
  </ng-template>
29433
29791
  `,
29434
29792
  isInline: true,
29435
- styles: [":host{display:block}.tl{list-style:none;margin:0;padding:0}.tl-item{position:relative;display:flex;gap:12px;padding-bottom:16px;--tl-color: #475569}.tl-item:last-child{padding-bottom:0}.tl-item:before{content:\"\";position:absolute;left:7px;top:18px;bottom:-2px;width:2px;background:#e2e8f0}.tl-item:last-child:before{display:none}.tl-item--success{--tl-color: #15803d}.tl-item--warning{--tl-color: #b45309}.tl-item--danger{--tl-color: #b91c1c}.tl-marker{flex-shrink:0;box-sizing:border-box;width:16px;height:16px;margin-top:2px;border-radius:50%;background:var(--tl-color);border:3px solid #fff;box-shadow:0 0 0 1px var(--tl-color);display:inline-flex;align-items:center;justify-content:center;position:relative;z-index:1}.tl-item--icon .tl-marker{border:none;box-shadow:none;color:#fff}.tl-content{flex:1;min-width:0;overflow-wrap:anywhere;word-break:break-word}.tl-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px}.tl-badge-tip{display:inline-flex;border-radius:999px}.tl-badge-tip:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.tl-time--end{display:inline;margin:0 0 0 auto;padding-left:8px;white-space:nowrap}.tl-scroll{overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding-right:8px}.tl-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:4px}.tl-title{font-size:.875rem;font-weight:600;color:#1e293b;line-height:1.4}.tl-description{margin:2px 0 0;font-size:.8125rem;line-height:1.5;color:#475569}.tl-time{display:block;margin-top:2px;font-size:.75rem;color:#64748b}\n"],
29793
+ styles: [":host{display:block}.tl,.tl-sub{list-style:none;margin:0;padding:0}.tl-day-group+.tl-day-group{margin-top:16px}.tl-day{margin:0 0 10px;font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;color:#64748b}.tl-item{position:relative;display:flex;gap:12px;padding-bottom:16px;--tl-color: #475569}.tl-item:last-child{padding-bottom:0}.tl-item:before{content:\"\";position:absolute;left:7px;top:18px;bottom:-2px;width:2px;background:#e2e8f0}.tl-item:last-child:before{display:none}.tl-item--success{--tl-color: #15803d}.tl-item--warning{--tl-color: #b45309}.tl-item--danger{--tl-color: #b91c1c}.tl-marker{flex-shrink:0;box-sizing:border-box;width:16px;height:16px;margin-top:2px;border-radius:50%;background:var(--tl-color);border:3px solid #fff;box-shadow:0 0 0 1px var(--tl-color);display:inline-flex;align-items:center;justify-content:center;position:relative;z-index:1}.tl-item--icon .tl-marker{border:none;box-shadow:none;color:#fff}.tl-content{flex:1;min-width:0;overflow-wrap:anywhere;word-break:break-word}.tl-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px}.tl-badge-tip{display:inline-flex;border-radius:999px}.tl-badge-tip:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.tl-time--end{display:inline;margin:0 0 0 auto;padding-left:8px;white-space:nowrap}.tl-scroll{overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding-right:8px}.tl-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:4px}.tl-title{font-size:.875rem;font-weight:600;color:#1e293b;line-height:1.4}.tl-description{margin:2px 0 0;font-size:.8125rem;line-height:1.5;color:#475569}.tl-time{display:block;margin-top:2px;font-size:.75rem;color:#64748b}\n"],
29436
29794
  dependencies: [
29437
29795
  {
29438
29796
  kind: "component",
@@ -29513,29 +29871,47 @@ i0.ɵɵngDeclareClassMetadata({
29513
29871
  <ui-hint class="tl-empty">{{ emptyMessage() }}</ui-hint>
29514
29872
  }
29515
29873
  <ng-template #listTpl>
29516
- <ol class="tl" [attr.aria-label]="ariaLabel() || null">
29517
- @for (item of items(); track item.id ?? $index) {
29518
- <li [attr.data-testid]="item.testId || null" class="tl-item" [class]="'tl-item tl-item--' + (item.tone ?? 'default')" [class.tl-item--icon]="!!item.icon" [style.--tl-color]="dotColor(item)">
29519
- <span class="tl-marker" aria-hidden="true">
29520
- @if (item.icon) { <ui-icon [name]="item.icon" [interactive]="false" [size]="12" /> }
29521
- </span>
29522
- <div class="tl-content">
29523
- <div class="tl-head">
29524
- <span class="tl-title">{{ item.title }}</span>
29525
- @if (item.badge) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: item.badge }" /> }
29526
- @for (b of item.badges ?? []; track $index) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: b }" /> }
29527
- @if (timePosition() === 'end' && (item.time || item.dateTime)) {
29528
- <time class="tl-time tl-time--end" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29874
+ @if (groupByDay()) {
29875
+ <ol class="tl tl-grouped" [attr.aria-label]="ariaLabel() || null">
29876
+ @for (g of groups(); track $index) {
29877
+ <li class="tl-day-group" [attr.data-day]="g.key || null">
29878
+ @if (g.label) { <div class="tl-day" role="heading" [attr.aria-level]="headingLevel()">{{ g.label }}</div> }
29879
+ <ol class="tl-sub">
29880
+ @for (item of g.items; track item.id ?? $index) {
29881
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29529
29882
  }
29530
- </div>
29531
- @if (item.description) { <p class="tl-description">{{ item.description }}</p> }
29532
- @if (timePosition() !== 'end' && (item.time || item.dateTime)) {
29533
- <time class="tl-time" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29534
- }
29535
- </div>
29536
- </li>
29537
- }
29538
- </ol>
29883
+ </ol>
29884
+ </li>
29885
+ }
29886
+ </ol>
29887
+ } @else {
29888
+ <ol class="tl" [attr.aria-label]="ariaLabel() || null">
29889
+ @for (item of items(); track item.id ?? $index) {
29890
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29891
+ }
29892
+ </ol>
29893
+ }
29894
+ </ng-template>
29895
+ <ng-template #itemTpl let-item>
29896
+ <li [attr.data-testid]="item.testId || null" class="tl-item" [class]="'tl-item tl-item--' + (item.tone ?? 'default')" [class.tl-item--icon]="!!item.icon" [style.--tl-color]="dotColor(item)">
29897
+ <span class="tl-marker" aria-hidden="true">
29898
+ @if (item.icon) { <ui-icon [name]="item.icon" [interactive]="false" [size]="12" /> }
29899
+ </span>
29900
+ <div class="tl-content">
29901
+ <div class="tl-head">
29902
+ <span class="tl-title">{{ item.title }}</span>
29903
+ @if (item.badge) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: item.badge }" /> }
29904
+ @for (b of item.badges ?? []; track $index) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: b }" /> }
29905
+ @if (timePosition() === 'end' && (item.time || item.dateTime)) {
29906
+ <time class="tl-time tl-time--end" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29907
+ }
29908
+ </div>
29909
+ @if (item.description) { <p class="tl-description">{{ item.description }}</p> }
29910
+ @if (timePosition() !== 'end' && (item.time || item.dateTime)) {
29911
+ <time class="tl-time" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29912
+ }
29913
+ </div>
29914
+ </li>
29539
29915
  </ng-template>
29540
29916
  <ng-template #badgeTpl let-b>
29541
29917
  @if (b.tooltip) {
@@ -29545,7 +29921,7 @@ i0.ɵɵngDeclareClassMetadata({
29545
29921
  }
29546
29922
  </ng-template>
29547
29923
  `,
29548
- styles: [":host{display:block}.tl{list-style:none;margin:0;padding:0}.tl-item{position:relative;display:flex;gap:12px;padding-bottom:16px;--tl-color: #475569}.tl-item:last-child{padding-bottom:0}.tl-item:before{content:\"\";position:absolute;left:7px;top:18px;bottom:-2px;width:2px;background:#e2e8f0}.tl-item:last-child:before{display:none}.tl-item--success{--tl-color: #15803d}.tl-item--warning{--tl-color: #b45309}.tl-item--danger{--tl-color: #b91c1c}.tl-marker{flex-shrink:0;box-sizing:border-box;width:16px;height:16px;margin-top:2px;border-radius:50%;background:var(--tl-color);border:3px solid #fff;box-shadow:0 0 0 1px var(--tl-color);display:inline-flex;align-items:center;justify-content:center;position:relative;z-index:1}.tl-item--icon .tl-marker{border:none;box-shadow:none;color:#fff}.tl-content{flex:1;min-width:0;overflow-wrap:anywhere;word-break:break-word}.tl-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px}.tl-badge-tip{display:inline-flex;border-radius:999px}.tl-badge-tip:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.tl-time--end{display:inline;margin:0 0 0 auto;padding-left:8px;white-space:nowrap}.tl-scroll{overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding-right:8px}.tl-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:4px}.tl-title{font-size:.875rem;font-weight:600;color:#1e293b;line-height:1.4}.tl-description{margin:2px 0 0;font-size:.8125rem;line-height:1.5;color:#475569}.tl-time{display:block;margin-top:2px;font-size:.75rem;color:#64748b}\n"]
29924
+ styles: [":host{display:block}.tl,.tl-sub{list-style:none;margin:0;padding:0}.tl-day-group+.tl-day-group{margin-top:16px}.tl-day{margin:0 0 10px;font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;color:#64748b}.tl-item{position:relative;display:flex;gap:12px;padding-bottom:16px;--tl-color: #475569}.tl-item:last-child{padding-bottom:0}.tl-item:before{content:\"\";position:absolute;left:7px;top:18px;bottom:-2px;width:2px;background:#e2e8f0}.tl-item:last-child:before{display:none}.tl-item--success{--tl-color: #15803d}.tl-item--warning{--tl-color: #b45309}.tl-item--danger{--tl-color: #b91c1c}.tl-marker{flex-shrink:0;box-sizing:border-box;width:16px;height:16px;margin-top:2px;border-radius:50%;background:var(--tl-color);border:3px solid #fff;box-shadow:0 0 0 1px var(--tl-color);display:inline-flex;align-items:center;justify-content:center;position:relative;z-index:1}.tl-item--icon .tl-marker{border:none;box-shadow:none;color:#fff}.tl-content{flex:1;min-width:0;overflow-wrap:anywhere;word-break:break-word}.tl-head{display:flex;align-items:center;flex-wrap:wrap;gap:4px 8px}.tl-badge-tip{display:inline-flex;border-radius:999px}.tl-badge-tip:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.tl-time--end{display:inline;margin:0 0 0 auto;padding-left:8px;white-space:nowrap}.tl-scroll{overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding-right:8px}.tl-scroll:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:4px}.tl-title{font-size:.875rem;font-weight:600;color:#1e293b;line-height:1.4}.tl-description{margin:2px 0 0;font-size:.8125rem;line-height:1.5;color:#475569}.tl-time{display:block;margin-top:2px;font-size:.75rem;color:#64748b}\n"]
29549
29925
  }]
29550
29926
  }],
29551
29927
  propDecorators: {
@@ -29588,6 +29964,38 @@ i0.ɵɵngDeclareClassMetadata({
29588
29964
  alias: "timePosition",
29589
29965
  required: false
29590
29966
  }]
29967
+ }],
29968
+ groupByDay: [{
29969
+ type: i0.Input,
29970
+ args: [{
29971
+ isSignal: true,
29972
+ alias: "groupByDay",
29973
+ required: false
29974
+ }]
29975
+ }],
29976
+ timeZone: [{
29977
+ type: i0.Input,
29978
+ args: [{
29979
+ isSignal: true,
29980
+ alias: "timeZone",
29981
+ required: false
29982
+ }]
29983
+ }],
29984
+ now: [{
29985
+ type: i0.Input,
29986
+ args: [{
29987
+ isSignal: true,
29988
+ alias: "now",
29989
+ required: false
29990
+ }]
29991
+ }],
29992
+ dayHeadingLevel: [{
29993
+ type: i0.Input,
29994
+ args: [{
29995
+ isSignal: true,
29996
+ alias: "dayHeadingLevel",
29997
+ required: false
29998
+ }]
29591
29999
  }]
29592
30000
  }
29593
30001
  });
@@ -34909,6 +35317,10 @@ i0.ɵɵngDeclareClassMetadata({
34909
35317
  });
34910
35318
  var BoardCardDirective = class BoardCardDirective {
34911
35319
  constructor() {
35320
+ this.typeFrom = input("", {
35321
+ ...ngDevMode ? { debugName: "typeFrom" } : /* istanbul ignore next */ {},
35322
+ alias: "uiBoardCard"
35323
+ });
34912
35324
  this.template = inject(TemplateRef);
34913
35325
  }
34914
35326
  static ngTemplateContextGuard(_dir, _ctx) {
@@ -34926,11 +35338,18 @@ var BoardCardDirective = class BoardCardDirective {
34926
35338
  }
34927
35339
  static {
34928
35340
  this.ɵdir = i0.ɵɵngDeclareDirective({
34929
- minVersion: "14.0.0",
35341
+ minVersion: "17.1.0",
34930
35342
  version: "22.2.2",
34931
35343
  type: BoardCardDirective,
34932
35344
  isStandalone: true,
34933
35345
  selector: "ng-template[uiBoardCard]",
35346
+ inputs: { typeFrom: {
35347
+ classPropertyName: "typeFrom",
35348
+ publicName: "uiBoardCard",
35349
+ isSignal: true,
35350
+ isRequired: false,
35351
+ transformFunction: null
35352
+ } },
34934
35353
  ngImport: i0
34935
35354
  });
34936
35355
  }
@@ -34946,8 +35365,17 @@ i0.ɵɵngDeclareClassMetadata({
34946
35365
  selector: "ng-template[uiBoardCard]",
34947
35366
  standalone: true
34948
35367
  }]
34949
- }]
35368
+ }],
35369
+ propDecorators: { typeFrom: [{
35370
+ type: i0.Input,
35371
+ args: [{
35372
+ isSignal: true,
35373
+ alias: "uiBoardCard",
35374
+ required: false
35375
+ }]
35376
+ }] }
34950
35377
  });
35378
+ let nextBoardId = 0;
34951
35379
  const DOT_COLORS = {
34952
35380
  blue: "#3b82f6",
34953
35381
  cyan: "#06b6d4",
@@ -34961,6 +35389,25 @@ const DOT_COLORS = {
34961
35389
  gray: "#6b7280"
34962
35390
  };
34963
35391
  var BoardComponent = class BoardComponent {
35392
+ limitOf(col) {
35393
+ const size = this.pageSize() > 0 ? Math.floor(this.pageSize()) : 0;
35394
+ if (!size) return col.items.length;
35395
+ let limit = this.drawn()[col.key] ?? size;
35396
+ const moved = this.movedTo();
35397
+ if (moved?.to === col.key) limit = Math.max(limit, col.items.findIndex((i) => this.itemKey()(i) === moved.key) + 1);
35398
+ return limit;
35399
+ }
35400
+ showMore(key) {
35401
+ const size = Math.floor(this.pageSize());
35402
+ const col = this.cols().find((c) => c.key === key);
35403
+ if (!col || size < 1) return;
35404
+ const limit = Math.min(col.items.length, this.limitOf(col) + size);
35405
+ this.drawn.update((d) => ({
35406
+ ...d,
35407
+ [key]: limit
35408
+ }));
35409
+ this.announcement.set(`Showing ${limit} of ${col.items.length} ${this.itemNounPlural()} in ${col.label}`);
35410
+ }
34964
35411
  constructor() {
34965
35412
  this.columns = input.required(...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
34966
35413
  this.itemKey = input.required(...ngDevMode ? [{ debugName: "itemKey" }] : /* istanbul ignore next */ []);
@@ -34977,12 +35424,29 @@ var BoardComponent = class BoardComponent {
34977
35424
  this.itemNoun = input("item", ...ngDevMode ? [{ debugName: "itemNoun" }] : /* istanbul ignore next */ []);
34978
35425
  this.itemNounPlural = input("items", ...ngDevMode ? [{ debugName: "itemNounPlural" }] : /* istanbul ignore next */ []);
34979
35426
  this.retryLabel = input("Retry", ...ngDevMode ? [{ debugName: "retryLabel" }] : /* istanbul ignore next */ []);
35427
+ this.pageSize = input(50, ...ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []);
34980
35428
  this.cardClick = output();
34981
35429
  this.cardAction = output();
34982
35430
  this.itemMove = output();
34983
35431
  this.retry = output();
34984
35432
  this.card = contentChild(BoardCardDirective, ...ngDevMode ? [{ debugName: "card" }] : /* istanbul ignore next */ []);
34985
35433
  this.cols = linkedSignal(() => this.columns(), ...ngDevMode ? [{ debugName: "cols" }] : /* istanbul ignore next */ []);
35434
+ this.drawn = signal({}, ...ngDevMode ? [{ debugName: "drawn" }] : /* istanbul ignore next */ []);
35435
+ this.movedTo = signal(null, ...ngDevMode ? [{ debugName: "movedTo" }] : /* istanbul ignore next */ []);
35436
+ this.shownCols = computed(() => {
35437
+ const size = this.pageSize() > 0 ? Math.floor(this.pageSize()) : 0;
35438
+ return this.cols().map((col) => {
35439
+ const limit = this.limitOf(col);
35440
+ const hidden = Math.max(0, col.items.length - limit);
35441
+ return {
35442
+ col,
35443
+ shown: hidden ? col.items.slice(0, limit) : col.items,
35444
+ hidden,
35445
+ next: Math.min(size, hidden)
35446
+ };
35447
+ });
35448
+ }, ...ngDevMode ? [{ debugName: "shownCols" }] : /* istanbul ignore next */ []);
35449
+ this.hintId = `ub-hint-${nextBoardId++}`;
34986
35450
  this.overKey = signal(null, ...ngDevMode ? [{ debugName: "overKey" }] : /* istanbul ignore next */ []);
34987
35451
  this.draggingKey = signal(null, ...ngDevMode ? [{ debugName: "draggingKey" }] : /* istanbul ignore next */ []);
34988
35452
  this.announcement = signal("", ...ngDevMode ? [{ debugName: "announcement" }] : /* istanbul ignore next */ []);
@@ -34990,7 +35454,12 @@ var BoardComponent = class BoardComponent {
34990
35454
  this.drag = null;
34991
35455
  this.skeletonColumns = computed(() => Array.from({ length: Math.max(this.columns().length, 4) }, (_, i) => i), ...ngDevMode ? [{ debugName: "skeletonColumns" }] : /* istanbul ignore next */ []);
34992
35456
  this.canDrag = computed(() => !this.readOnly() && !this.moveDisabled(), ...ngDevMode ? [{ debugName: "canDrag" }] : /* istanbul ignore next */ []);
34993
- this.canMoveAny = this.canDrag;
35457
+ effect(() => {
35458
+ if (this.loading()) {
35459
+ this.drawn.set({});
35460
+ this.movedTo.set(null);
35461
+ }
35462
+ });
34994
35463
  }
34995
35464
  dot(color) {
34996
35465
  return color && DOT_COLORS[color] || color || "#3b82f6";
@@ -35076,11 +35545,18 @@ var BoardComponent = class BoardComponent {
35076
35545
  };
35077
35546
  return c;
35078
35547
  }));
35548
+ this.movedTo.set({
35549
+ key,
35550
+ to
35551
+ });
35079
35552
  this.itemMove.emit({
35080
35553
  item,
35081
35554
  from,
35082
35555
  to,
35083
- revert: () => this.cols.set(before)
35556
+ revert: () => {
35557
+ this.cols.set(before);
35558
+ this.movedTo.set(null);
35559
+ }
35084
35560
  });
35085
35561
  }
35086
35562
  static {
@@ -35205,6 +35681,13 @@ var BoardComponent = class BoardComponent {
35205
35681
  isSignal: true,
35206
35682
  isRequired: false,
35207
35683
  transformFunction: null
35684
+ },
35685
+ pageSize: {
35686
+ classPropertyName: "pageSize",
35687
+ publicName: "pageSize",
35688
+ isSignal: true,
35689
+ isRequired: false,
35690
+ transformFunction: null
35208
35691
  }
35209
35692
  },
35210
35693
  outputs: {
@@ -35249,8 +35732,9 @@ var BoardComponent = class BoardComponent {
35249
35732
  } @else if (cols().length === 0) {
35250
35733
  <div class="ub-message" role="status"><p>{{ emptyMessage() }}</p></div>
35251
35734
  } @else {
35252
- <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()">
35253
- @for (col of cols(); track col.key) {
35735
+ <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()" [attr.aria-describedby]="canDrag() ? hintId : null">
35736
+ @for (view of shownCols(); track view.col.key) {
35737
+ @let col = view.col;
35254
35738
  <div class="ub-col"
35255
35739
  [class.ub-col--over]="overKey() === col.key"
35256
35740
  [class.ub-col--success]="col.tone === 'success'"
@@ -35266,19 +35750,20 @@ var BoardComponent = class BoardComponent {
35266
35750
  <span class="ub-col__count" aria-hidden="true">{{ col.items.length }}</span>
35267
35751
  </div>
35268
35752
  @if (col.summary) {
35269
- <div class="ub-col__summary" [attr.aria-label]="col.summaryLabel || col.summary">{{ col.summary }}</div>
35753
+ <div class="ub-col__summary"><span aria-hidden="true">{{ col.summary }}</span><span class="ub-sr-only">{{ col.summaryLabel || col.summary }}</span></div>
35270
35754
  }
35271
35755
  </div>
35272
- <div class="ub-col__cards" role="list">
35273
- @for (item of col.items; track itemKey()(item)) {
35756
+ <div class="ub-col__cards" [attr.role]="col.items.length ? 'list' : null">
35757
+ @for (item of view.shown; track itemKey()(item)) {
35758
+ @let key = itemKey()(item);
35274
35759
  <div class="ub-card"
35275
35760
  [class.ub-card--success]="col.tone === 'success'"
35276
- [class.ub-card--dragging]="draggingKey() === itemKey()(item)"
35761
+ [class.ub-card--dragging]="draggingKey() === key"
35277
35762
  role="listitem"
35278
35763
  tabindex="0"
35279
- [attr.data-board-key]="itemKey()(item)"
35764
+ [attr.data-board-key]="key"
35280
35765
  [attr.aria-label]="itemLabel()(item)"
35281
- [attr.aria-keyshortcuts]="canMoveAny() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35766
+ [attr.aria-keyshortcuts]="canDrag() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35282
35767
  [attr.draggable]="canDrag() ? 'true' : null"
35283
35768
  (dragstart)="onDragStart($event, item, col)"
35284
35769
  (dragend)="onDragEnd()"
@@ -35289,6 +35774,11 @@ var BoardComponent = class BoardComponent {
35289
35774
  }
35290
35775
  </div>
35291
35776
  }
35777
+ @if (view.hidden > 0) {
35778
+ <div class="ub-col__more" role="listitem">
35779
+ <button type="button" class="ub-more-btn" [attr.aria-label]="'Show ' + view.next + ' more (' + view.hidden + ' not shown), ' + col.label" (click)="showMore(col.key)">Show {{ view.next }} more ({{ view.hidden }} not shown)</button>
35780
+ </div>
35781
+ }
35292
35782
  @if (col.items.length === 0) {
35293
35783
  <div class="ub-col__empty" role="status">{{ col.emptyText || emptyColumnText() }}</div>
35294
35784
  }
@@ -35296,12 +35786,15 @@ var BoardComponent = class BoardComponent {
35296
35786
  </div>
35297
35787
  }
35298
35788
  </div>
35789
+ @if (canDrag()) {
35790
+ <p class="ub-sr-only" [id]="hintId">Drag a card to another column to move it, or focus a card and press Shift with the Left or Right Arrow key.</p>
35791
+ }
35299
35792
  <div class="ub-sr-only" role="status" aria-live="polite">{{ announcement() }}</div>
35300
35793
  }
35301
35794
  </div>
35302
35795
  `,
35303
35796
  isInline: true,
35304
- styles: ["ui-board{display:flex;flex-direction:column;flex:1;min-height:0}.ub-wrap{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}.ub-board{display:flex;gap:12px;padding:0 0 16px;overflow-x:auto;overflow-y:hidden;height:100%;align-items:flex-start}.ub-board::-webkit-scrollbar{height:6px}.ub-board::-webkit-scrollbar-track{background:#f1f5f9;border-radius:3px}.ub-board::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.ub-col{flex:0 0 280px;min-width:280px;max-width:280px;display:flex;flex-direction:column;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;max-height:calc(100vh - 200px);transition:border-color .15s,background .15s}.ub-col--over{border-color:#3b82f6;background:#eff6ff}.ub-col--success{background:#f0fdf4;border-color:#bbf7d0}.ub-col--success.ub-col--over{border-color:#22c55e;background:#dcfce7}.ub-col__header{padding:12px 14px 10px;border-bottom:1px solid #e2e8f0;flex-shrink:0}.ub-col__title{display:flex;align-items:center;gap:7px;margin-bottom:2px}.ub-col__dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}.ub-col__label{font-size:12px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:.04em;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-col__count{font-size:11px;font-weight:600;color:#fff;background:#94a3b8;border-radius:10px;padding:1px 7px;flex-shrink:0}.ub-col__summary{font-size:11px;color:#64748b;font-weight:500;margin-top:2px}.ub-col__cards{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:60px}.ub-col__cards::-webkit-scrollbar{width:4px}.ub-col__cards::-webkit-scrollbar-track{background:transparent}.ub-col__cards::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}.ub-col__empty{text-align:center;padding:24px 12px;color:#94a3b8;font-size:12px;border:1.5px dashed #e2e8f0;border-radius:8px;margin:4px 0}.ub-card{position:relative;background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;padding:11px 12px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:box-shadow .12s,border-color .12s,opacity .12s,transform .12s}.ub-card[draggable=true]{cursor:grab}.ub-card[draggable=true]:active{cursor:grabbing}.ub-card:hover{border-color:#94a3b8;box-shadow:0 2px 8px #00000012}.ub-card:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ub-card--dragging{opacity:.4;transform:scale(.98);box-shadow:none}.ub-card--success{border-left:3px solid #22c55e}.ub-card__top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px}.ub-card__title{font-size:13px;font-weight:600;color:#1e293b;line-height:1.35;flex:1;min-width:0;word-break:break-word}.ub-card:hover .ub-card__title{color:#2563eb}.ub-card__top-right{flex-shrink:0;margin-top:-2px}.ub-card__status-row{margin-bottom:5px}.ub-card__contact{font-size:12px;color:#475569;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__property{font-size:11px;color:#94a3b8;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__next-step{display:flex;align-items:flex-start;gap:4px;font-size:11px;color:#64748b;margin-bottom:6px;line-height:1.4}.ub-card__next-step svg{flex-shrink:0;margin-top:1px;color:#94a3b8}.ub-card__footer{display:flex;align-items:center;justify-content:space-between;margin-top:6px;padding-top:6px;border-top:1px solid #f1f5f9}.ub-card__value{font-size:12px;font-weight:700;color:#0f172a}.ub-card__activity{font-size:11px;color:#94a3b8}.ub-card__activity--stale{color:#d97706;font-weight:600}.ub-skeleton{display:flex;gap:12px;padding-bottom:16px}.ub-col-skeleton{flex:0 0 280px;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:10px}.ub-col-skeleton__header,.ub-col-skeleton__card{background:linear-gradient(90deg,#e2e8f0 25%,#f1f5f9,#e2e8f0 75%);background-size:200% 100%;animation:ub-shimmer 1.4s infinite}.ub-col-skeleton__header{height:32px;border-radius:6px}.ub-col-skeleton__card{height:90px;border-radius:8px}@keyframes ub-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.ub-col-skeleton__header,.ub-col-skeleton__card{animation:none}}.ub-message{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px;color:#64748b;font-size:14px;text-align:center}.ub-message p{margin:0}.ub-sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@media(max-width:640px){.ub-board{flex-direction:column;overflow-x:hidden;overflow-y:auto;height:auto;align-items:stretch}.ub-col{flex:none;min-width:0;max-width:100%;width:100%;max-height:none}.ub-skeleton{flex-direction:column}.ub-col-skeleton{flex:none;width:100%}}\n"],
35797
+ styles: ["ui-board{display:flex;flex-direction:column;flex:1;min-height:0}.ub-wrap{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}.ub-board{display:flex;gap:12px;padding:0 0 16px;overflow-x:auto;overflow-y:hidden;height:100%;align-items:stretch}.ub-board::-webkit-scrollbar{height:6px}.ub-board::-webkit-scrollbar-track{background:#f1f5f9;border-radius:3px}.ub-board::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.ub-col{flex:0 0 280px;min-width:280px;max-width:280px;display:flex;flex-direction:column;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;min-height:0;transition:border-color .15s,background .15s}.ub-col--over{border-color:#3b82f6;background:#eff6ff}.ub-col--success{background:#f0fdf4;border-color:#bbf7d0}.ub-col--success.ub-col--over{border-color:#22c55e;background:#dcfce7}.ub-col__header{padding:12px 14px 10px;border-bottom:1px solid #e2e8f0;flex-shrink:0}.ub-col__title{display:flex;align-items:center;gap:7px;margin-bottom:2px}.ub-col__dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}.ub-col__label{font-size:12px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:.04em;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-col__count{font-size:11px;font-weight:600;color:#fff;background:#64748b;border-radius:10px;padding:1px 7px;flex-shrink:0}.ub-col__summary{font-size:11px;color:#64748b;font-weight:500;margin-top:2px}.ub-col__cards{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:60px}.ub-col__cards::-webkit-scrollbar{width:4px}.ub-col__cards::-webkit-scrollbar-track{background:transparent}.ub-col__cards::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}.ub-col__more{flex-shrink:0}.ub-more-btn{width:100%;padding:8px 10px;font:inherit;font-size:12px;font-weight:600;color:#475569;background:#fff;border:1.5px dashed #cbd5e1;border-radius:8px;cursor:pointer}.ub-more-btn:hover{background:#f1f5f9;border-color:#94a3b8}.ub-more-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ub-col__empty{text-align:center;padding:24px 12px;color:#64748b;font-size:12px;border:1.5px dashed #e2e8f0;border-radius:8px;margin:4px 0}.ub-card{position:relative;background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;padding:11px 12px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:box-shadow .12s,border-color .12s,opacity .12s,transform .12s}.ub-card[draggable=true]{cursor:grab}.ub-card[draggable=true]:active{cursor:grabbing}.ub-card:hover{border-color:#94a3b8;box-shadow:0 2px 8px #00000012}.ub-card:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ub-card--dragging{opacity:.4;transform:scale(.98);box-shadow:none}.ub-card--success{border-left:3px solid #22c55e}.ub-card__top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px}.ub-card__title{font-size:13px;font-weight:600;color:#1e293b;line-height:1.35;flex:1;min-width:0;word-break:break-word}.ub-card:hover .ub-card__title{color:#2563eb}.ub-card__top-right{flex-shrink:0;margin-top:-2px}.ub-card__status-row{margin-bottom:5px}.ub-card__contact{font-size:12px;color:#475569;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__property{font-size:11px;color:#64748b;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__next-step{display:flex;align-items:flex-start;gap:4px;font-size:11px;color:#64748b;margin-bottom:6px;line-height:1.4}.ub-card__next-step svg{flex-shrink:0;margin-top:1px;color:#94a3b8}.ub-card__footer{display:flex;align-items:center;justify-content:space-between;margin-top:6px;padding-top:6px;border-top:1px solid #f1f5f9}.ub-card__value{font-size:12px;font-weight:700;color:#0f172a}.ub-card__activity{font-size:11px;color:#64748b}.ub-card__activity--stale{color:#b45309;font-weight:600}.ub-skeleton{display:flex;gap:12px;padding-bottom:16px}.ub-col-skeleton{flex:0 0 280px;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:10px}.ub-col-skeleton__header,.ub-col-skeleton__card{background:linear-gradient(90deg,#e2e8f0 25%,#f1f5f9,#e2e8f0 75%);background-size:200% 100%;animation:ub-shimmer 1.4s infinite}.ub-col-skeleton__header{height:32px;border-radius:6px}.ub-col-skeleton__card{height:90px;border-radius:8px}@keyframes ub-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.ub-col-skeleton__header,.ub-col-skeleton__card{animation:none}.ub-card,.ub-col{transition:none}.ub-card--dragging{transform:none}}@media(pointer:coarse){.ub-more-btn{min-height:44px}}.ub-message{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px;color:#64748b;font-size:14px;text-align:center}.ub-message p{margin:0}.ub-sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@media(max-width:640px){.ub-board{flex-direction:column;overflow-x:hidden;overflow-y:auto;height:auto;align-items:stretch}.ub-col{flex:none;min-width:0;max-width:100%;width:100%;max-height:none}.ub-skeleton{flex-direction:column}.ub-col-skeleton{flex:none;width:100%}}\n"],
35305
35798
  dependencies: [
35306
35799
  {
35307
35800
  kind: "directive",
@@ -35401,8 +35894,9 @@ i0.ɵɵngDeclareClassMetadata({
35401
35894
  } @else if (cols().length === 0) {
35402
35895
  <div class="ub-message" role="status"><p>{{ emptyMessage() }}</p></div>
35403
35896
  } @else {
35404
- <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()">
35405
- @for (col of cols(); track col.key) {
35897
+ <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()" [attr.aria-describedby]="canDrag() ? hintId : null">
35898
+ @for (view of shownCols(); track view.col.key) {
35899
+ @let col = view.col;
35406
35900
  <div class="ub-col"
35407
35901
  [class.ub-col--over]="overKey() === col.key"
35408
35902
  [class.ub-col--success]="col.tone === 'success'"
@@ -35418,19 +35912,20 @@ i0.ɵɵngDeclareClassMetadata({
35418
35912
  <span class="ub-col__count" aria-hidden="true">{{ col.items.length }}</span>
35419
35913
  </div>
35420
35914
  @if (col.summary) {
35421
- <div class="ub-col__summary" [attr.aria-label]="col.summaryLabel || col.summary">{{ col.summary }}</div>
35915
+ <div class="ub-col__summary"><span aria-hidden="true">{{ col.summary }}</span><span class="ub-sr-only">{{ col.summaryLabel || col.summary }}</span></div>
35422
35916
  }
35423
35917
  </div>
35424
- <div class="ub-col__cards" role="list">
35425
- @for (item of col.items; track itemKey()(item)) {
35918
+ <div class="ub-col__cards" [attr.role]="col.items.length ? 'list' : null">
35919
+ @for (item of view.shown; track itemKey()(item)) {
35920
+ @let key = itemKey()(item);
35426
35921
  <div class="ub-card"
35427
35922
  [class.ub-card--success]="col.tone === 'success'"
35428
- [class.ub-card--dragging]="draggingKey() === itemKey()(item)"
35923
+ [class.ub-card--dragging]="draggingKey() === key"
35429
35924
  role="listitem"
35430
35925
  tabindex="0"
35431
- [attr.data-board-key]="itemKey()(item)"
35926
+ [attr.data-board-key]="key"
35432
35927
  [attr.aria-label]="itemLabel()(item)"
35433
- [attr.aria-keyshortcuts]="canMoveAny() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35928
+ [attr.aria-keyshortcuts]="canDrag() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35434
35929
  [attr.draggable]="canDrag() ? 'true' : null"
35435
35930
  (dragstart)="onDragStart($event, item, col)"
35436
35931
  (dragend)="onDragEnd()"
@@ -35441,6 +35936,11 @@ i0.ɵɵngDeclareClassMetadata({
35441
35936
  }
35442
35937
  </div>
35443
35938
  }
35939
+ @if (view.hidden > 0) {
35940
+ <div class="ub-col__more" role="listitem">
35941
+ <button type="button" class="ub-more-btn" [attr.aria-label]="'Show ' + view.next + ' more (' + view.hidden + ' not shown), ' + col.label" (click)="showMore(col.key)">Show {{ view.next }} more ({{ view.hidden }} not shown)</button>
35942
+ </div>
35943
+ }
35444
35944
  @if (col.items.length === 0) {
35445
35945
  <div class="ub-col__empty" role="status">{{ col.emptyText || emptyColumnText() }}</div>
35446
35946
  }
@@ -35448,13 +35948,17 @@ i0.ɵɵngDeclareClassMetadata({
35448
35948
  </div>
35449
35949
  }
35450
35950
  </div>
35951
+ @if (canDrag()) {
35952
+ <p class="ub-sr-only" [id]="hintId">Drag a card to another column to move it, or focus a card and press Shift with the Left or Right Arrow key.</p>
35953
+ }
35451
35954
  <div class="ub-sr-only" role="status" aria-live="polite">{{ announcement() }}</div>
35452
35955
  }
35453
35956
  </div>
35454
35957
  `,
35455
- styles: ["ui-board{display:flex;flex-direction:column;flex:1;min-height:0}.ub-wrap{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}.ub-board{display:flex;gap:12px;padding:0 0 16px;overflow-x:auto;overflow-y:hidden;height:100%;align-items:flex-start}.ub-board::-webkit-scrollbar{height:6px}.ub-board::-webkit-scrollbar-track{background:#f1f5f9;border-radius:3px}.ub-board::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.ub-col{flex:0 0 280px;min-width:280px;max-width:280px;display:flex;flex-direction:column;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;max-height:calc(100vh - 200px);transition:border-color .15s,background .15s}.ub-col--over{border-color:#3b82f6;background:#eff6ff}.ub-col--success{background:#f0fdf4;border-color:#bbf7d0}.ub-col--success.ub-col--over{border-color:#22c55e;background:#dcfce7}.ub-col__header{padding:12px 14px 10px;border-bottom:1px solid #e2e8f0;flex-shrink:0}.ub-col__title{display:flex;align-items:center;gap:7px;margin-bottom:2px}.ub-col__dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}.ub-col__label{font-size:12px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:.04em;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-col__count{font-size:11px;font-weight:600;color:#fff;background:#94a3b8;border-radius:10px;padding:1px 7px;flex-shrink:0}.ub-col__summary{font-size:11px;color:#64748b;font-weight:500;margin-top:2px}.ub-col__cards{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:60px}.ub-col__cards::-webkit-scrollbar{width:4px}.ub-col__cards::-webkit-scrollbar-track{background:transparent}.ub-col__cards::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}.ub-col__empty{text-align:center;padding:24px 12px;color:#94a3b8;font-size:12px;border:1.5px dashed #e2e8f0;border-radius:8px;margin:4px 0}.ub-card{position:relative;background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;padding:11px 12px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:box-shadow .12s,border-color .12s,opacity .12s,transform .12s}.ub-card[draggable=true]{cursor:grab}.ub-card[draggable=true]:active{cursor:grabbing}.ub-card:hover{border-color:#94a3b8;box-shadow:0 2px 8px #00000012}.ub-card:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ub-card--dragging{opacity:.4;transform:scale(.98);box-shadow:none}.ub-card--success{border-left:3px solid #22c55e}.ub-card__top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px}.ub-card__title{font-size:13px;font-weight:600;color:#1e293b;line-height:1.35;flex:1;min-width:0;word-break:break-word}.ub-card:hover .ub-card__title{color:#2563eb}.ub-card__top-right{flex-shrink:0;margin-top:-2px}.ub-card__status-row{margin-bottom:5px}.ub-card__contact{font-size:12px;color:#475569;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__property{font-size:11px;color:#94a3b8;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__next-step{display:flex;align-items:flex-start;gap:4px;font-size:11px;color:#64748b;margin-bottom:6px;line-height:1.4}.ub-card__next-step svg{flex-shrink:0;margin-top:1px;color:#94a3b8}.ub-card__footer{display:flex;align-items:center;justify-content:space-between;margin-top:6px;padding-top:6px;border-top:1px solid #f1f5f9}.ub-card__value{font-size:12px;font-weight:700;color:#0f172a}.ub-card__activity{font-size:11px;color:#94a3b8}.ub-card__activity--stale{color:#d97706;font-weight:600}.ub-skeleton{display:flex;gap:12px;padding-bottom:16px}.ub-col-skeleton{flex:0 0 280px;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:10px}.ub-col-skeleton__header,.ub-col-skeleton__card{background:linear-gradient(90deg,#e2e8f0 25%,#f1f5f9,#e2e8f0 75%);background-size:200% 100%;animation:ub-shimmer 1.4s infinite}.ub-col-skeleton__header{height:32px;border-radius:6px}.ub-col-skeleton__card{height:90px;border-radius:8px}@keyframes ub-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.ub-col-skeleton__header,.ub-col-skeleton__card{animation:none}}.ub-message{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px;color:#64748b;font-size:14px;text-align:center}.ub-message p{margin:0}.ub-sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@media(max-width:640px){.ub-board{flex-direction:column;overflow-x:hidden;overflow-y:auto;height:auto;align-items:stretch}.ub-col{flex:none;min-width:0;max-width:100%;width:100%;max-height:none}.ub-skeleton{flex-direction:column}.ub-col-skeleton{flex:none;width:100%}}\n"]
35958
+ styles: ["ui-board{display:flex;flex-direction:column;flex:1;min-height:0}.ub-wrap{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}.ub-board{display:flex;gap:12px;padding:0 0 16px;overflow-x:auto;overflow-y:hidden;height:100%;align-items:stretch}.ub-board::-webkit-scrollbar{height:6px}.ub-board::-webkit-scrollbar-track{background:#f1f5f9;border-radius:3px}.ub-board::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}.ub-col{flex:0 0 280px;min-width:280px;max-width:280px;display:flex;flex-direction:column;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;min-height:0;transition:border-color .15s,background .15s}.ub-col--over{border-color:#3b82f6;background:#eff6ff}.ub-col--success{background:#f0fdf4;border-color:#bbf7d0}.ub-col--success.ub-col--over{border-color:#22c55e;background:#dcfce7}.ub-col__header{padding:12px 14px 10px;border-bottom:1px solid #e2e8f0;flex-shrink:0}.ub-col__title{display:flex;align-items:center;gap:7px;margin-bottom:2px}.ub-col__dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}.ub-col__label{font-size:12px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:.04em;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-col__count{font-size:11px;font-weight:600;color:#fff;background:#64748b;border-radius:10px;padding:1px 7px;flex-shrink:0}.ub-col__summary{font-size:11px;color:#64748b;font-weight:500;margin-top:2px}.ub-col__cards{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:60px}.ub-col__cards::-webkit-scrollbar{width:4px}.ub-col__cards::-webkit-scrollbar-track{background:transparent}.ub-col__cards::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}.ub-col__more{flex-shrink:0}.ub-more-btn{width:100%;padding:8px 10px;font:inherit;font-size:12px;font-weight:600;color:#475569;background:#fff;border:1.5px dashed #cbd5e1;border-radius:8px;cursor:pointer}.ub-more-btn:hover{background:#f1f5f9;border-color:#94a3b8}.ub-more-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ub-col__empty{text-align:center;padding:24px 12px;color:#64748b;font-size:12px;border:1.5px dashed #e2e8f0;border-radius:8px;margin:4px 0}.ub-card{position:relative;background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;padding:11px 12px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:box-shadow .12s,border-color .12s,opacity .12s,transform .12s}.ub-card[draggable=true]{cursor:grab}.ub-card[draggable=true]:active{cursor:grabbing}.ub-card:hover{border-color:#94a3b8;box-shadow:0 2px 8px #00000012}.ub-card:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.ub-card--dragging{opacity:.4;transform:scale(.98);box-shadow:none}.ub-card--success{border-left:3px solid #22c55e}.ub-card__top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px}.ub-card__title{font-size:13px;font-weight:600;color:#1e293b;line-height:1.35;flex:1;min-width:0;word-break:break-word}.ub-card:hover .ub-card__title{color:#2563eb}.ub-card__top-right{flex-shrink:0;margin-top:-2px}.ub-card__status-row{margin-bottom:5px}.ub-card__contact{font-size:12px;color:#475569;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__property{font-size:11px;color:#64748b;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ub-card__next-step{display:flex;align-items:flex-start;gap:4px;font-size:11px;color:#64748b;margin-bottom:6px;line-height:1.4}.ub-card__next-step svg{flex-shrink:0;margin-top:1px;color:#94a3b8}.ub-card__footer{display:flex;align-items:center;justify-content:space-between;margin-top:6px;padding-top:6px;border-top:1px solid #f1f5f9}.ub-card__value{font-size:12px;font-weight:700;color:#0f172a}.ub-card__activity{font-size:11px;color:#64748b}.ub-card__activity--stale{color:#b45309;font-weight:600}.ub-skeleton{display:flex;gap:12px;padding-bottom:16px}.ub-col-skeleton{flex:0 0 280px;background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:10px;padding:12px;display:flex;flex-direction:column;gap:10px}.ub-col-skeleton__header,.ub-col-skeleton__card{background:linear-gradient(90deg,#e2e8f0 25%,#f1f5f9,#e2e8f0 75%);background-size:200% 100%;animation:ub-shimmer 1.4s infinite}.ub-col-skeleton__header{height:32px;border-radius:6px}.ub-col-skeleton__card{height:90px;border-radius:8px}@keyframes ub-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.ub-col-skeleton__header,.ub-col-skeleton__card{animation:none}.ub-card,.ub-col{transition:none}.ub-card--dragging{transform:none}}@media(pointer:coarse){.ub-more-btn{min-height:44px}}.ub-message{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px;color:#64748b;font-size:14px;text-align:center}.ub-message p{margin:0}.ub-sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@media(max-width:640px){.ub-board{flex-direction:column;overflow-x:hidden;overflow-y:auto;height:auto;align-items:stretch}.ub-col{flex:none;min-width:0;max-width:100%;width:100%;max-height:none}.ub-skeleton{flex-direction:column}.ub-col-skeleton{flex:none;width:100%}}\n"]
35456
35959
  }]
35457
35960
  }],
35961
+ ctorParameters: () => [],
35458
35962
  propDecorators: {
35459
35963
  columns: [{
35460
35964
  type: i0.Input,
@@ -35576,6 +36080,14 @@ i0.ɵɵngDeclareClassMetadata({
35576
36080
  required: false
35577
36081
  }]
35578
36082
  }],
36083
+ pageSize: [{
36084
+ type: i0.Input,
36085
+ args: [{
36086
+ isSignal: true,
36087
+ alias: "pageSize",
36088
+ required: false
36089
+ }]
36090
+ }],
35579
36091
  cardClick: [{
35580
36092
  type: i0.Output,
35581
36093
  args: ["cardClick"]
@@ -36990,6 +37502,208 @@ i0.ɵɵngDeclareClassMetadata({
36990
37502
  }]
36991
37503
  }
36992
37504
  });
37505
+ const CSS_LENGTH = /^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|vh|vw|ch)|(?:calc|var)\([^;{}]*\))$/i;
37506
+ function px(v, fallback) {
37507
+ if (v === null || v === void 0 || v === "") return fallback;
37508
+ const n = Number(v);
37509
+ return Number.isFinite(n) && n >= 0 ? n : fallback;
37510
+ }
37511
+ var SidebarLayoutComponent = class SidebarLayoutComponent {
37512
+ constructor() {
37513
+ this.sideWidth = input("320px", ...ngDevMode ? [{ debugName: "sideWidth" }] : /* istanbul ignore next */ []);
37514
+ this.sidePosition = input("end", ...ngDevMode ? [{ debugName: "sidePosition" }] : /* istanbul ignore next */ []);
37515
+ this.gap = input("md", ...ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []);
37516
+ this.stickySide = input(true, ...ngDevMode ? [{ debugName: "stickySide" }] : /* istanbul ignore next */ []);
37517
+ this.stickyTop = input(16, ...ngDevMode ? [{ debugName: "stickyTop" }] : /* istanbul ignore next */ []);
37518
+ this.stickyOffset = input(32, ...ngDevMode ? [{ debugName: "stickyOffset" }] : /* istanbul ignore next */ []);
37519
+ this.collapseAt = input("md", ...ngDevMode ? [{ debugName: "collapseAt" }] : /* istanbul ignore next */ []);
37520
+ this.sideFirstWhenCollapsed = input(true, ...ngDevMode ? [{ debugName: "sideFirstWhenCollapsed" }] : /* istanbul ignore next */ []);
37521
+ this.position = computed(() => this.sidePosition() === "start" ? "start" : "end", ...ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []);
37522
+ this.sideCss = computed(() => {
37523
+ const v = String(this.sideWidth() ?? "").trim();
37524
+ return v && CSS_LENGTH.test(v) ? v : "320px";
37525
+ }, ...ngDevMode ? [{ debugName: "sideCss" }] : /* istanbul ignore next */ []);
37526
+ this.gapCss = computed(() => resolveLayoutGap(this.gap(), "md"), ...ngDevMode ? [{ debugName: "gapCss" }] : /* istanbul ignore next */ []);
37527
+ this.topCss = computed(() => `${px(this.stickyTop(), 16)}px`, ...ngDevMode ? [{ debugName: "topCss" }] : /* istanbul ignore next */ []);
37528
+ this.offCss = computed(() => `${px(this.stickyOffset(), 32)}px`, ...ngDevMode ? [{ debugName: "offCss" }] : /* istanbul ignore next */ []);
37529
+ this.rootClass = computed(() => {
37530
+ const c = this.collapseAt();
37531
+ const collapse = c === "never" ? "" : c === "sm" || c === "lg" ? `sl-c-${c}` : "sl-c-md";
37532
+ return [
37533
+ this.position() === "start" ? "sl-start" : "",
37534
+ this.stickySide() ? "sl-sticky" : "",
37535
+ collapse,
37536
+ collapse && this.sideFirstWhenCollapsed() ? "sl-first" : ""
37537
+ ].filter(Boolean).join(" ");
37538
+ }, ...ngDevMode ? [{ debugName: "rootClass" }] : /* istanbul ignore next */ []);
37539
+ }
37540
+ static {
37541
+ this.ɵfac = i0.ɵɵngDeclareFactory({
37542
+ minVersion: "12.0.0",
37543
+ version: "22.2.2",
37544
+ ngImport: i0,
37545
+ type: SidebarLayoutComponent,
37546
+ deps: [],
37547
+ target: i0.ɵɵFactoryTarget.Component
37548
+ });
37549
+ }
37550
+ static {
37551
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
37552
+ minVersion: "17.1.0",
37553
+ version: "22.2.2",
37554
+ type: SidebarLayoutComponent,
37555
+ isStandalone: true,
37556
+ selector: "ui-sidebar-layout",
37557
+ inputs: {
37558
+ sideWidth: {
37559
+ classPropertyName: "sideWidth",
37560
+ publicName: "sideWidth",
37561
+ isSignal: true,
37562
+ isRequired: false,
37563
+ transformFunction: null
37564
+ },
37565
+ sidePosition: {
37566
+ classPropertyName: "sidePosition",
37567
+ publicName: "sidePosition",
37568
+ isSignal: true,
37569
+ isRequired: false,
37570
+ transformFunction: null
37571
+ },
37572
+ gap: {
37573
+ classPropertyName: "gap",
37574
+ publicName: "gap",
37575
+ isSignal: true,
37576
+ isRequired: false,
37577
+ transformFunction: null
37578
+ },
37579
+ stickySide: {
37580
+ classPropertyName: "stickySide",
37581
+ publicName: "stickySide",
37582
+ isSignal: true,
37583
+ isRequired: false,
37584
+ transformFunction: null
37585
+ },
37586
+ stickyTop: {
37587
+ classPropertyName: "stickyTop",
37588
+ publicName: "stickyTop",
37589
+ isSignal: true,
37590
+ isRequired: false,
37591
+ transformFunction: null
37592
+ },
37593
+ stickyOffset: {
37594
+ classPropertyName: "stickyOffset",
37595
+ publicName: "stickyOffset",
37596
+ isSignal: true,
37597
+ isRequired: false,
37598
+ transformFunction: null
37599
+ },
37600
+ collapseAt: {
37601
+ classPropertyName: "collapseAt",
37602
+ publicName: "collapseAt",
37603
+ isSignal: true,
37604
+ isRequired: false,
37605
+ transformFunction: null
37606
+ },
37607
+ sideFirstWhenCollapsed: {
37608
+ classPropertyName: "sideFirstWhenCollapsed",
37609
+ publicName: "sideFirstWhenCollapsed",
37610
+ isSignal: true,
37611
+ isRequired: false,
37612
+ transformFunction: null
37613
+ }
37614
+ },
37615
+ host: { properties: { "attr.data-side-position": "position()" } },
37616
+ ngImport: i0,
37617
+ template: `<div class="sl" [class]="rootClass()" [style.--sl-side-w]="sideCss()" [style.--sl-gap]="gapCss()" [style.--sl-top]="topCss()" [style.--sl-off]="offCss()" [style.row-gap]="gapCss()"><div class="sl-main"><ng-content select="[layout-main]" /></div><div class="sl-side"><ng-content select="[layout-side]" /></div></div>`,
37618
+ isInline: true,
37619
+ styles: [":host{display:block}.sl{display:grid;grid-template-columns:minmax(0,1fr) auto}.sl-main{grid-column:1;grid-row:1;min-width:0}.sl-side{grid-column:2;grid-row:1;box-sizing:border-box;width:var(--sl-side-w, 320px);max-width:100%;min-width:0;margin-inline-start:var(--sl-gap, 16px)}.sl-side:empty{display:none}.sl.sl-start{grid-template-columns:auto minmax(0,1fr)}.sl.sl-start .sl-main{grid-column:2}.sl.sl-start .sl-side{grid-column:1;margin-inline-start:0;margin-inline-end:var(--sl-gap, 16px)}.sl.sl-sticky .sl-side{position:-webkit-sticky;position:sticky;top:var(--sl-top, 16px);align-self:start;max-height:calc(100vh - (var(--sl-top, 16px) + var(--sl-off, 32px)));max-height:calc(100dvh - (var(--sl-top, 16px) + var(--sl-off, 32px)));overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}@media(max-width:640px){.sl.sl-c-sm{grid-template-columns:minmax(0,1fr)}.sl.sl-c-sm .sl-main{grid-column:1;grid-row:auto}.sl.sl-c-sm .sl-side{grid-column:1;grid-row:auto;width:auto;margin-inline-start:0;margin-inline-end:0;position:static;top:auto;align-self:auto;max-height:none;overflow-y:visible}.sl.sl-c-sm.sl-first .sl-side{order:-1}}@media(max-width:900px){.sl.sl-c-md{grid-template-columns:minmax(0,1fr)}.sl.sl-c-md .sl-main{grid-column:1;grid-row:auto}.sl.sl-c-md .sl-side{grid-column:1;grid-row:auto;width:auto;margin-inline-start:0;margin-inline-end:0;position:static;top:auto;align-self:auto;max-height:none;overflow-y:visible}.sl.sl-c-md.sl-first .sl-side{order:-1}}@media(max-width:1200px){.sl.sl-c-lg{grid-template-columns:minmax(0,1fr)}.sl.sl-c-lg .sl-main{grid-column:1;grid-row:auto}.sl.sl-c-lg .sl-side{grid-column:1;grid-row:auto;width:auto;margin-inline-start:0;margin-inline-end:0;position:static;top:auto;align-self:auto;max-height:none;overflow-y:visible}.sl.sl-c-lg.sl-first .sl-side{order:-1}}\n"],
37620
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
37621
+ });
37622
+ }
37623
+ };
37624
+ i0.ɵɵngDeclareClassMetadata({
37625
+ minVersion: "12.0.0",
37626
+ version: "22.2.2",
37627
+ ngImport: i0,
37628
+ type: SidebarLayoutComponent,
37629
+ decorators: [{
37630
+ type: Component,
37631
+ args: [{
37632
+ selector: "ui-sidebar-layout",
37633
+ standalone: true,
37634
+ changeDetection: ChangeDetectionStrategy.OnPush,
37635
+ host: { "[attr.data-side-position]": "position()" },
37636
+ template: `<div class="sl" [class]="rootClass()" [style.--sl-side-w]="sideCss()" [style.--sl-gap]="gapCss()" [style.--sl-top]="topCss()" [style.--sl-off]="offCss()" [style.row-gap]="gapCss()"><div class="sl-main"><ng-content select="[layout-main]" /></div><div class="sl-side"><ng-content select="[layout-side]" /></div></div>`,
37637
+ styles: [":host{display:block}.sl{display:grid;grid-template-columns:minmax(0,1fr) auto}.sl-main{grid-column:1;grid-row:1;min-width:0}.sl-side{grid-column:2;grid-row:1;box-sizing:border-box;width:var(--sl-side-w, 320px);max-width:100%;min-width:0;margin-inline-start:var(--sl-gap, 16px)}.sl-side:empty{display:none}.sl.sl-start{grid-template-columns:auto minmax(0,1fr)}.sl.sl-start .sl-main{grid-column:2}.sl.sl-start .sl-side{grid-column:1;margin-inline-start:0;margin-inline-end:var(--sl-gap, 16px)}.sl.sl-sticky .sl-side{position:-webkit-sticky;position:sticky;top:var(--sl-top, 16px);align-self:start;max-height:calc(100vh - (var(--sl-top, 16px) + var(--sl-off, 32px)));max-height:calc(100dvh - (var(--sl-top, 16px) + var(--sl-off, 32px)));overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}@media(max-width:640px){.sl.sl-c-sm{grid-template-columns:minmax(0,1fr)}.sl.sl-c-sm .sl-main{grid-column:1;grid-row:auto}.sl.sl-c-sm .sl-side{grid-column:1;grid-row:auto;width:auto;margin-inline-start:0;margin-inline-end:0;position:static;top:auto;align-self:auto;max-height:none;overflow-y:visible}.sl.sl-c-sm.sl-first .sl-side{order:-1}}@media(max-width:900px){.sl.sl-c-md{grid-template-columns:minmax(0,1fr)}.sl.sl-c-md .sl-main{grid-column:1;grid-row:auto}.sl.sl-c-md .sl-side{grid-column:1;grid-row:auto;width:auto;margin-inline-start:0;margin-inline-end:0;position:static;top:auto;align-self:auto;max-height:none;overflow-y:visible}.sl.sl-c-md.sl-first .sl-side{order:-1}}@media(max-width:1200px){.sl.sl-c-lg{grid-template-columns:minmax(0,1fr)}.sl.sl-c-lg .sl-main{grid-column:1;grid-row:auto}.sl.sl-c-lg .sl-side{grid-column:1;grid-row:auto;width:auto;margin-inline-start:0;margin-inline-end:0;position:static;top:auto;align-self:auto;max-height:none;overflow-y:visible}.sl.sl-c-lg.sl-first .sl-side{order:-1}}\n"]
37638
+ }]
37639
+ }],
37640
+ propDecorators: {
37641
+ sideWidth: [{
37642
+ type: i0.Input,
37643
+ args: [{
37644
+ isSignal: true,
37645
+ alias: "sideWidth",
37646
+ required: false
37647
+ }]
37648
+ }],
37649
+ sidePosition: [{
37650
+ type: i0.Input,
37651
+ args: [{
37652
+ isSignal: true,
37653
+ alias: "sidePosition",
37654
+ required: false
37655
+ }]
37656
+ }],
37657
+ gap: [{
37658
+ type: i0.Input,
37659
+ args: [{
37660
+ isSignal: true,
37661
+ alias: "gap",
37662
+ required: false
37663
+ }]
37664
+ }],
37665
+ stickySide: [{
37666
+ type: i0.Input,
37667
+ args: [{
37668
+ isSignal: true,
37669
+ alias: "stickySide",
37670
+ required: false
37671
+ }]
37672
+ }],
37673
+ stickyTop: [{
37674
+ type: i0.Input,
37675
+ args: [{
37676
+ isSignal: true,
37677
+ alias: "stickyTop",
37678
+ required: false
37679
+ }]
37680
+ }],
37681
+ stickyOffset: [{
37682
+ type: i0.Input,
37683
+ args: [{
37684
+ isSignal: true,
37685
+ alias: "stickyOffset",
37686
+ required: false
37687
+ }]
37688
+ }],
37689
+ collapseAt: [{
37690
+ type: i0.Input,
37691
+ args: [{
37692
+ isSignal: true,
37693
+ alias: "collapseAt",
37694
+ required: false
37695
+ }]
37696
+ }],
37697
+ sideFirstWhenCollapsed: [{
37698
+ type: i0.Input,
37699
+ args: [{
37700
+ isSignal: true,
37701
+ alias: "sideFirstWhenCollapsed",
37702
+ required: false
37703
+ }]
37704
+ }]
37705
+ }
37706
+ });
36993
37707
  const JUSTIFY = {
36994
37708
  start: "flex-start",
36995
37709
  center: "center",
@@ -39428,6 +40142,6 @@ i0.ɵɵngDeclareClassMetadata({
39428
40142
  }]
39429
40143
  }
39430
40144
  });
39431
- export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, ModalComponent, MoreMenuComponent, MultiSelectComponent, NotesComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SearchInputComponent, SectionHeaderComponent, SelectComponent, ShowComponent, SidePanelComponent, SignaturePadComponent, SkeletonComponent, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, buildDefaultSchedule, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, encodeFilterValue, encodeFilterValues, errorContextInterceptor, fileMatchesAccept, formatAddress, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, isoKey, issueToErrors, maxLengthIssue, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours };
40145
+ export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SearchInputComponent, SectionHeaderComponent, SelectComponent, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, buildDefaultSchedule, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, encodeFilterValue, encodeFilterValues, errorContextInterceptor, fileMatchesAccept, formatAddress, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, isoKey, issueToErrors, maxLengthIssue, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours };
39432
40146
 
39433
40147
  //# sourceMappingURL=forgeroute-ui.mjs.map