@forgeroute/ui 0.4.21 → 0.4.23

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.
@@ -371,7 +371,7 @@ var SearchInputComponent = class SearchInputComponent {
371
371
  </div>
372
372
  `,
373
373
  isInline: true,
374
- styles: [":host{display:block;flex:0 1 325px;min-width:0}.search-bar{position:relative;display:flex;align-items:center;width:100%}.search-icon{position:absolute;left:10px;color:#94a3b8;pointer-events:none}.search-input{width:100%;padding:9px 10px 9px 34px;border:1px solid #e2e8f0;border-radius:8px;font-size:.875rem;background:#fff;color:#1e293b;outline:none;min-width:0;font-family:inherit;transition:border-color .15s,box-shadow .15s}.search-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.search-input::placeholder{color:#94a3b8}.search-input-loading{padding-right:34px}.search-input-loading::-webkit-search-cancel-button{display:none}.search-spinner{position:absolute;right:10px;top:50%;margin-top:-8px;width:16px;height:16px;pointer-events:none}.search-spinner-ring{display:block;width:16px;height:16px;box-sizing:border-box;border:2px solid #e2e8f0;border-top-color:#64748b;border-radius:50%;animation:search-spin .6s linear infinite}.search-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}@keyframes search-spin{to{transform:rotate(360deg)}}@media(pointer:coarse),(max-width:480px){.search-input{min-height:44px}}@media(max-width:1024px){:host{flex:0 1 280px}}@media(max-width:768px){:host{flex:0 1 240px}}@media(max-width:640px){:host{flex:1 1 auto}.search-input{font-size:16px}}\n"],
374
+ styles: [":host{display:block;flex:0 1 var(--ui-search-width, 325px);min-width:0}.search-bar{position:relative;display:flex;align-items:center;width:100%}.search-icon{position:absolute;left:10px;color:#94a3b8;pointer-events:none}.search-input{width:100%;padding:9px 10px 9px 34px;border:1px solid #e2e8f0;border-radius:8px;font-size:.875rem;background:#fff;color:#1e293b;outline:none;min-width:0;font-family:inherit;transition:border-color .15s,box-shadow .15s}.search-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.search-input::placeholder{color:#94a3b8}.search-input-loading{padding-right:34px}.search-input-loading::-webkit-search-cancel-button{display:none}.search-spinner{position:absolute;right:10px;top:50%;margin-top:-8px;width:16px;height:16px;pointer-events:none}.search-spinner-ring{display:block;width:16px;height:16px;box-sizing:border-box;border:2px solid #e2e8f0;border-top-color:#64748b;border-radius:50%;animation:search-spin .6s linear infinite}.search-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}@keyframes search-spin{to{transform:rotate(360deg)}}@media(pointer:coarse),(max-width:480px){.search-input{min-height:44px}}@media(max-width:1024px){:host{flex:0 1 280px}}@media(max-width:768px){:host{flex:0 1 240px}}@media(max-width:640px){:host{flex:1 1 auto}.search-input{font-size:16px}}\n"],
375
375
  changeDetection: i0.ChangeDetectionStrategy.OnPush
376
376
  });
377
377
  }
@@ -424,7 +424,7 @@ i0.ɵɵngDeclareClassMetadata({
424
424
  }
425
425
  </div>
426
426
  `,
427
- styles: [":host{display:block;flex:0 1 325px;min-width:0}.search-bar{position:relative;display:flex;align-items:center;width:100%}.search-icon{position:absolute;left:10px;color:#94a3b8;pointer-events:none}.search-input{width:100%;padding:9px 10px 9px 34px;border:1px solid #e2e8f0;border-radius:8px;font-size:.875rem;background:#fff;color:#1e293b;outline:none;min-width:0;font-family:inherit;transition:border-color .15s,box-shadow .15s}.search-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.search-input::placeholder{color:#94a3b8}.search-input-loading{padding-right:34px}.search-input-loading::-webkit-search-cancel-button{display:none}.search-spinner{position:absolute;right:10px;top:50%;margin-top:-8px;width:16px;height:16px;pointer-events:none}.search-spinner-ring{display:block;width:16px;height:16px;box-sizing:border-box;border:2px solid #e2e8f0;border-top-color:#64748b;border-radius:50%;animation:search-spin .6s linear infinite}.search-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}@keyframes search-spin{to{transform:rotate(360deg)}}@media(pointer:coarse),(max-width:480px){.search-input{min-height:44px}}@media(max-width:1024px){:host{flex:0 1 280px}}@media(max-width:768px){:host{flex:0 1 240px}}@media(max-width:640px){:host{flex:1 1 auto}.search-input{font-size:16px}}\n"]
427
+ styles: [":host{display:block;flex:0 1 var(--ui-search-width, 325px);min-width:0}.search-bar{position:relative;display:flex;align-items:center;width:100%}.search-icon{position:absolute;left:10px;color:#94a3b8;pointer-events:none}.search-input{width:100%;padding:9px 10px 9px 34px;border:1px solid #e2e8f0;border-radius:8px;font-size:.875rem;background:#fff;color:#1e293b;outline:none;min-width:0;font-family:inherit;transition:border-color .15s,box-shadow .15s}.search-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.search-input::placeholder{color:#94a3b8}.search-input-loading{padding-right:34px}.search-input-loading::-webkit-search-cancel-button{display:none}.search-spinner{position:absolute;right:10px;top:50%;margin-top:-8px;width:16px;height:16px;pointer-events:none}.search-spinner-ring{display:block;width:16px;height:16px;box-sizing:border-box;border:2px solid #e2e8f0;border-top-color:#64748b;border-radius:50%;animation:search-spin .6s linear infinite}.search-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}@keyframes search-spin{to{transform:rotate(360deg)}}@media(pointer:coarse),(max-width:480px){.search-input{min-height:44px}}@media(max-width:1024px){:host{flex:0 1 280px}}@media(max-width:768px){:host{flex:0 1 240px}}@media(max-width:640px){:host{flex:1 1 auto}.search-input{font-size:16px}}\n"]
428
428
  }]
429
429
  }],
430
430
  ctorParameters: () => [],
@@ -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
  });
@@ -4340,6 +4497,7 @@ const EXTRA_ICONS = {
4340
4497
  "refund": "M3 10h10a8 8 0 0 1 8 8v2 M3 10l6 6 M3 10l6-6",
4341
4498
  "link": "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71 M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71",
4342
4499
  "chart": "M18 20V10 M12 20V4 M6 20v-6",
4500
+ "clipboard": "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2 M9 2h6a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z",
4343
4501
  "save": "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z M17 21v-8H7v8 M7 3v5h8",
4344
4502
  "bank": "M3 21h18 M3 10h18 M5 6l7-3 7 3 M4 10v11 M20 10v11 M8 14v3 M12 14v3 M16 14v3"
4345
4503
  };
@@ -5605,7 +5763,7 @@ var TableToolbarComponent = class TableToolbarComponent {
5605
5763
  this.saveNameModalOpen = signal(false, ...ngDevMode ? [{ debugName: "saveNameModalOpen" }] : /* istanbul ignore next */ []);
5606
5764
  this._saveViewName = "";
5607
5765
  this._pendingCols = signal([], ...ngDevMode ? [{ debugName: "_pendingCols" }] : /* istanbul ignore next */ []);
5608
- this._allowedButtons = computed(() => this.readOnly() ? this.tableButtons().filter((b) => b.type === "export") : this.tableButtons(), ...ngDevMode ? [{ debugName: "_allowedButtons" }] : /* istanbul ignore next */ []);
5766
+ this._allowedButtons = computed(() => this.readOnly() ? this.tableButtons().filter((b) => b.type === "export" || b.allowReadOnly && b.type !== "import") : this.tableButtons(), ...ngDevMode ? [{ debugName: "_allowedButtons" }] : /* istanbul ignore next */ []);
5609
5767
  this.standaloneButtons = computed(() => this._allowedButtons().filter((b) => (b.variant === "primary" || b.variant === "secondary") && !b.hidden).sort((a, b) => {
5610
5768
  if (a.variant === b.variant) return 0;
5611
5769
  return a.variant === "primary" ? -1 : 1;
@@ -9256,6 +9414,15 @@ var EmptyStateComponent = class EmptyStateComponent {
9256
9414
  @case ('shield') {
9257
9415
  <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
9416
  }
9417
+ @case ('pipeline') {
9418
+ <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>
9419
+ }
9420
+ @case ('property') {
9421
+ <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>
9422
+ }
9423
+ @case ('clipboard') {
9424
+ <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>
9425
+ }
9259
9426
  @default {
9260
9427
  <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
9428
  }
@@ -9330,6 +9497,15 @@ i0.ɵɵngDeclareClassMetadata({
9330
9497
  @case ('shield') {
9331
9498
  <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
9499
  }
9500
+ @case ('pipeline') {
9501
+ <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>
9502
+ }
9503
+ @case ('property') {
9504
+ <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>
9505
+ }
9506
+ @case ('clipboard') {
9507
+ <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>
9508
+ }
9333
9509
  @default {
9334
9510
  <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
9511
  }
@@ -10176,7 +10352,7 @@ var DataTableComponent = class DataTableComponent {
10176
10352
  }, ...ngDevMode ? [{ debugName: "_exportParams" }] : /* istanbul ignore next */ []);
10177
10353
  this._effectiveButtons = computed(() => {
10178
10354
  const canEdit = this._canEdit();
10179
- const buttons = canEdit ? this.tableButtons() : [];
10355
+ const buttons = canEdit ? this.tableButtons() : this.tableButtons().filter((b) => b.allowReadOnly);
10180
10356
  const cfg = this.importExportConfig();
10181
10357
  if (!cfg) return buttons;
10182
10358
  return [
@@ -11943,8 +12119,13 @@ var DataTableComponent = class DataTableComponent {
11943
12119
  inputs: [
11944
12120
  "initials",
11945
12121
  "name",
11946
- "size"
11947
- ]
12122
+ "size",
12123
+ "imageUrl",
12124
+ "editable",
12125
+ "editLabel",
12126
+ "busy"
12127
+ ],
12128
+ outputs: ["editClick", "imageError"]
11948
12129
  },
11949
12130
  {
11950
12131
  kind: "component",
@@ -25351,12 +25532,20 @@ function getErrorMessage(error, fallbackContext, action) {
25351
25532
  if (typeof error === "string") return error;
25352
25533
  return `${failed} Please try again.`;
25353
25534
  }
25535
+ const NOTES_MAX_LENGTH = 1e4;
25354
25536
  const NOTES_PAGE_SIZE = 5;
25355
25537
  var NotesComponent = class NotesComponent {
25356
25538
  initials(name) {
25357
25539
  const parts = (name || "You").trim().split(/\s+/).filter(Boolean);
25358
25540
  return ((parts[0]?.[0] ?? "") + (parts.length > 1 ? parts[parts.length - 1][0] : "")).toUpperCase();
25359
25541
  }
25542
+ tooLong(text) {
25543
+ return text.trim().length > NOTES_MAX_LENGTH;
25544
+ }
25545
+ validBody(text) {
25546
+ const n = text.trim().length;
25547
+ return n > 0 && n <= 1e4;
25548
+ }
25360
25549
  get listUrl() {
25361
25550
  return `${this.apiBase}/notes/${this.resourceType()}/${this.resourceId()}`;
25362
25551
  }
@@ -25370,6 +25559,7 @@ var NotesComponent = class NotesComponent {
25370
25559
  this.destroyRef = inject(DestroyRef);
25371
25560
  this.apiBase = inject(FORGEROUTE_CONFIG, { optional: true })?.baseUrl ?? "/api";
25372
25561
  this.pageSize = NOTES_PAGE_SIZE;
25562
+ this.maxLength = NOTES_MAX_LENGTH;
25373
25563
  this.notes = signal([], ...ngDevMode ? [{ debugName: "notes" }] : /* istanbul ignore next */ []);
25374
25564
  this.loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
25375
25565
  this.saving = signal(false, ...ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []);
@@ -25403,7 +25593,7 @@ var NotesComponent = class NotesComponent {
25403
25593
  });
25404
25594
  }
25405
25595
  addNote() {
25406
- if (this.readOnly() || !this.newBody.trim() || this.saving()) return;
25596
+ if (this.readOnly() || !this.validBody(this.newBody) || this.saving()) return;
25407
25597
  this.saving.set(true);
25408
25598
  this.http.post(this.listUrl, { body: this.newBody.trim() }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
25409
25599
  next: () => {
@@ -25427,7 +25617,7 @@ var NotesComponent = class NotesComponent {
25427
25617
  this.editBody = "";
25428
25618
  }
25429
25619
  saveEdit(noteId) {
25430
- if (this.readOnly() || !this.editBody.trim() || this.saving()) return;
25620
+ if (this.readOnly() || !this.validBody(this.editBody) || this.saving()) return;
25431
25621
  this.saving.set(true);
25432
25622
  this.http.put(`${this.apiBase}/notes/${noteId}`, { body: this.editBody.trim() }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
25433
25623
  next: (updated) => {
@@ -25507,10 +25697,10 @@ var NotesComponent = class NotesComponent {
25507
25697
  template: `
25508
25698
  @if (!readOnly()) {
25509
25699
  <div class="note-add">
25510
- <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [disabled]="saving()" [(ngModel)]="newBody"
25700
+ <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
25511
25701
  (keydown.meta.enter)="addNote()" (keydown.control.enter)="addNote()" />
25512
25702
  <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>
25703
+ <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!validBody(newBody)" (click)="addNote()">Add Note</ui-button>
25514
25704
  </div>
25515
25705
  </div>
25516
25706
  }
@@ -25534,20 +25724,16 @@ var NotesComponent = class NotesComponent {
25534
25724
  }
25535
25725
  @if (!readOnly() && editingId() !== note.id) {
25536
25726
  <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>
25727
+ <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
25728
+ <ui-icon name="delete" variant="danger" [size]="14" tooltip="Delete note" (iconClick)="confirmDelete(note.id)" />
25543
25729
  </div>
25544
25730
  }
25545
25731
  </div>
25546
25732
  @if (editingId() === note.id) {
25547
- <ui-textarea-input ariaLabel="Edit note" [rows]="3" [disabled]="saving()" [(ngModel)]="editBody" />
25733
+ <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
25548
25734
  <div class="note-item-footer">
25549
25735
  <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>
25736
+ <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!validBody(editBody)" (click)="saveEdit(note.id)">Save</ui-button>
25551
25737
  </div>
25552
25738
  } @else {
25553
25739
  <p class="note-body">{{ note.body }}</p>
@@ -25577,6 +25763,12 @@ var NotesComponent = class NotesComponent {
25577
25763
  type: i1.NgControlStatus,
25578
25764
  selector: "[formControlName],[ngModel],[formControl]"
25579
25765
  },
25766
+ {
25767
+ kind: "directive",
25768
+ type: i1.MaxLengthValidator,
25769
+ selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",
25770
+ inputs: ["maxlength"]
25771
+ },
25580
25772
  {
25581
25773
  kind: "directive",
25582
25774
  type: i1.NgModel,
@@ -25682,10 +25874,20 @@ var NotesComponent = class NotesComponent {
25682
25874
  outputs: ["invalidChange"]
25683
25875
  },
25684
25876
  {
25685
- kind: "directive",
25686
- type: TooltipDirective,
25687
- selector: "[uiTooltip]",
25688
- inputs: ["uiTooltip", "tooltipPosition"]
25877
+ kind: "component",
25878
+ type: IconComponent,
25879
+ selector: "ui-icon",
25880
+ inputs: [
25881
+ "name",
25882
+ "tooltip",
25883
+ "ariaLabel",
25884
+ "size",
25885
+ "variant",
25886
+ "disabled",
25887
+ "loading",
25888
+ "interactive"
25889
+ ],
25890
+ outputs: ["iconClick"]
25689
25891
  },
25690
25892
  {
25691
25893
  kind: "component",
@@ -25694,8 +25896,13 @@ var NotesComponent = class NotesComponent {
25694
25896
  inputs: [
25695
25897
  "initials",
25696
25898
  "name",
25697
- "size"
25698
- ]
25899
+ "size",
25900
+ "imageUrl",
25901
+ "editable",
25902
+ "editLabel",
25903
+ "busy"
25904
+ ],
25905
+ outputs: ["editClick", "imageError"]
25699
25906
  },
25700
25907
  {
25701
25908
  kind: "pipe",
@@ -25726,16 +25933,16 @@ i0.ɵɵngDeclareClassMetadata({
25726
25933
  EmptyStateComponent,
25727
25934
  PaginationComponent,
25728
25935
  TextareaInputComponent,
25729
- TooltipDirective,
25936
+ IconComponent,
25730
25937
  AvatarComponent
25731
25938
  ],
25732
25939
  template: `
25733
25940
  @if (!readOnly()) {
25734
25941
  <div class="note-add">
25735
- <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [disabled]="saving()" [(ngModel)]="newBody"
25942
+ <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
25736
25943
  (keydown.meta.enter)="addNote()" (keydown.control.enter)="addNote()" />
25737
25944
  <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>
25945
+ <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!validBody(newBody)" (click)="addNote()">Add Note</ui-button>
25739
25946
  </div>
25740
25947
  </div>
25741
25948
  }
@@ -25759,20 +25966,16 @@ i0.ɵɵngDeclareClassMetadata({
25759
25966
  }
25760
25967
  @if (!readOnly() && editingId() !== note.id) {
25761
25968
  <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>
25969
+ <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
25970
+ <ui-icon name="delete" variant="danger" [size]="14" tooltip="Delete note" (iconClick)="confirmDelete(note.id)" />
25768
25971
  </div>
25769
25972
  }
25770
25973
  </div>
25771
25974
  @if (editingId() === note.id) {
25772
- <ui-textarea-input ariaLabel="Edit note" [rows]="3" [disabled]="saving()" [(ngModel)]="editBody" />
25975
+ <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
25773
25976
  <div class="note-item-footer">
25774
25977
  <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>
25978
+ <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!validBody(editBody)" (click)="saveEdit(note.id)">Save</ui-button>
25776
25979
  </div>
25777
25980
  } @else {
25778
25981
  <p class="note-body">{{ note.body }}</p>
@@ -25849,11 +26052,11 @@ const LAYOUT_GAP_PX = {
25849
26052
  lg: 24,
25850
26053
  xl: 32
25851
26054
  };
25852
- const CSS_LENGTH = /^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|vh|vw|ch)|(?:calc|var)\([^;{}]*\))$/i;
26055
+ const CSS_LENGTH$1 = /^(?:0|-?(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|vh|vw|ch)|(?:calc|var)\([^;{}]*\))$/i;
25853
26056
  function resolveLayoutGap(gap, fallback) {
25854
26057
  const v = (gap ?? "").trim();
25855
26058
  if (Object.prototype.hasOwnProperty.call(LAYOUT_GAP_PX, v)) return `${LAYOUT_GAP_PX[v]}px`;
25856
- if (v && CSS_LENGTH.test(v)) return v;
26059
+ if (v && CSS_LENGTH$1.test(v)) return v;
25857
26060
  return `${LAYOUT_GAP_PX[fallback]}px`;
25858
26061
  }
25859
26062
  function reorderItems(items, order) {
@@ -27847,6 +28050,7 @@ var PanelInfoListComponent = class PanelInfoListComponent {
27847
28050
  this.sections = input([], ...ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []);
27848
28051
  this.showEmptyState = input(false, ...ngDevMode ? [{ debugName: "showEmptyState" }] : /* istanbul ignore next */ []);
27849
28052
  this.labelColon = input(false, ...ngDevMode ? [{ debugName: "labelColon" }] : /* istanbul ignore next */ []);
28053
+ this.fill = input(false, ...ngDevMode ? [{ debugName: "fill" }] : /* istanbul ignore next */ []);
27850
28054
  this.displaySections = computed(() => this.showEmptyState() ? this.sections() : this.sections().filter((s) => s.items.some((i) => !i.hidden)), ...ngDevMode ? [{ debugName: "displaySections" }] : /* istanbul ignore next */ []);
27851
28055
  }
27852
28056
  hrefOf(item) {
@@ -27912,8 +28116,16 @@ var PanelInfoListComponent = class PanelInfoListComponent {
27912
28116
  isSignal: true,
27913
28117
  isRequired: false,
27914
28118
  transformFunction: null
28119
+ },
28120
+ fill: {
28121
+ classPropertyName: "fill",
28122
+ publicName: "fill",
28123
+ isSignal: true,
28124
+ isRequired: false,
28125
+ transformFunction: null
27915
28126
  }
27916
28127
  },
28128
+ host: { properties: { "class.pil-fill": "fill()" } },
27917
28129
  ngImport: i0,
27918
28130
  template: `
27919
28131
  @for (section of displaySections(); track section.title ?? $index) {
@@ -27981,7 +28193,7 @@ var PanelInfoListComponent = class PanelInfoListComponent {
27981
28193
  }
27982
28194
  `,
27983
28195
  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"],
28196
+ 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
28197
  dependencies: [
27986
28198
  {
27987
28199
  kind: "component",
@@ -28056,6 +28268,7 @@ i0.ɵɵngDeclareClassMetadata({
28056
28268
  EmptyStateComponent,
28057
28269
  IconComponent
28058
28270
  ],
28271
+ host: { "[class.pil-fill]": "fill()" },
28059
28272
  template: `
28060
28273
  @for (section of displaySections(); track section.title ?? $index) {
28061
28274
  <div class="pil-section">
@@ -28121,7 +28334,7 @@ i0.ɵɵngDeclareClassMetadata({
28121
28334
  </div>
28122
28335
  }
28123
28336
  `,
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"]
28337
+ 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
28338
  }]
28126
28339
  }],
28127
28340
  propDecorators: {
@@ -28148,6 +28361,14 @@ i0.ɵɵngDeclareClassMetadata({
28148
28361
  alias: "labelColon",
28149
28362
  required: false
28150
28363
  }]
28364
+ }],
28365
+ fill: [{
28366
+ type: i0.Input,
28367
+ args: [{
28368
+ isSignal: true,
28369
+ alias: "fill",
28370
+ required: false
28371
+ }]
28151
28372
  }]
28152
28373
  }
28153
28374
  });
@@ -29327,6 +29548,98 @@ var TimelineComponent = class TimelineComponent {
29327
29548
  this.emptyMessage = input("", ...ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []);
29328
29549
  this.maxHeight = input("", ...ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []);
29329
29550
  this.timePosition = input("below", ...ngDevMode ? [{ debugName: "timePosition" }] : /* istanbul ignore next */ []);
29551
+ this.groupByDay = input(false, ...ngDevMode ? [{ debugName: "groupByDay" }] : /* istanbul ignore next */ []);
29552
+ this.timeZone = input("", ...ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []);
29553
+ this.now = input(null, ...ngDevMode ? [{ debugName: "now" }] : /* istanbul ignore next */ []);
29554
+ this.dayHeadingLevel = input(3, ...ngDevMode ? [{ debugName: "dayHeadingLevel" }] : /* istanbul ignore next */ []);
29555
+ this.headingLevel = computed(() => {
29556
+ const n = this.dayHeadingLevel();
29557
+ return Number.isInteger(n) && n >= 1 && n <= 6 ? n : 3;
29558
+ }, ...ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []);
29559
+ this.groups = computed(() => {
29560
+ if (!this.groupByDay()) return [];
29561
+ const zone = this.timeZone() || void 0;
29562
+ let fmt;
29563
+ try {
29564
+ fmt = new Intl.DateTimeFormat("en-US", {
29565
+ timeZone: zone,
29566
+ year: "numeric",
29567
+ month: "2-digit",
29568
+ day: "2-digit"
29569
+ });
29570
+ } catch {
29571
+ fmt = new Intl.DateTimeFormat("en-US", {
29572
+ year: "numeric",
29573
+ month: "2-digit",
29574
+ day: "2-digit"
29575
+ });
29576
+ }
29577
+ const parts = (d) => {
29578
+ const p = fmt.formatToParts(d);
29579
+ const get = (t) => Number(p.find((x) => x.type === t)?.value);
29580
+ return {
29581
+ y: get("year"),
29582
+ m: get("month"),
29583
+ d: get("day")
29584
+ };
29585
+ };
29586
+ const keyOf = (v) => `${v.y}-${String(v.m).padStart(2, "0")}-${String(v.d).padStart(2, "0")}`;
29587
+ const nowRaw = this.now();
29588
+ let nowDate = nowRaw == null ? /* @__PURE__ */ new Date() : new Date(nowRaw);
29589
+ if (isNaN(nowDate.getTime())) nowDate = /* @__PURE__ */ new Date();
29590
+ const t = parts(nowDate);
29591
+ const todayKey = keyOf(t);
29592
+ const yd = new Date(Date.UTC(t.y, t.m - 1, t.d - 1));
29593
+ const yesterdayKey = keyOf({
29594
+ y: yd.getUTCFullYear(),
29595
+ m: yd.getUTCMonth() + 1,
29596
+ d: yd.getUTCDate()
29597
+ });
29598
+ const labelFmt = (withYear, tz) => new Intl.DateTimeFormat("en-US", {
29599
+ timeZone: tz,
29600
+ month: "short",
29601
+ day: "numeric",
29602
+ ...withYear ? { year: "numeric" } : {}
29603
+ });
29604
+ 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)));
29605
+ const dayOf = (iso) => {
29606
+ 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;
29607
+ if (!m) return null;
29608
+ const y = Number(m[1]), mo = Number(m[2]), d = Number(m[3]);
29609
+ const probe = new Date(Date.UTC(y, mo - 1, d));
29610
+ if (probe.getUTCFullYear() !== y || probe.getUTCMonth() !== mo - 1 || probe.getUTCDate() !== d) return null;
29611
+ if (m[4] !== void 0 && (Number(m[4]) > 23 || Number(m[5]) > 59 || m[6] !== void 0 && Number(m[6]) > 59)) return null;
29612
+ if (m[7] === void 0) return {
29613
+ y,
29614
+ m: mo,
29615
+ d
29616
+ };
29617
+ const inst = new Date(iso.replace(/([+-]\d{2})(\d{2})$/, "$1:$2"));
29618
+ return isNaN(inst.getTime()) ? null : parts(inst);
29619
+ };
29620
+ const groups = [];
29621
+ for (const item of this.items()) {
29622
+ const v = dayOf(item.dateTime);
29623
+ const last = groups[groups.length - 1];
29624
+ if (!v) {
29625
+ if (last) last.items.push(item);
29626
+ else groups.push({
29627
+ key: "",
29628
+ label: "",
29629
+ items: [item]
29630
+ });
29631
+ continue;
29632
+ }
29633
+ const key = keyOf(v);
29634
+ if (last && last.key === key) last.items.push(item);
29635
+ else groups.push({
29636
+ key,
29637
+ label: label(v),
29638
+ items: [item]
29639
+ });
29640
+ }
29641
+ return groups;
29642
+ }, ...ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []);
29330
29643
  }
29331
29644
  dotColor(item) {
29332
29645
  return item.dotVariant ? BADGE_VARIANT_STYLES[item.dotVariant]?.color ?? null : null;
@@ -29383,6 +29696,34 @@ var TimelineComponent = class TimelineComponent {
29383
29696
  isSignal: true,
29384
29697
  isRequired: false,
29385
29698
  transformFunction: null
29699
+ },
29700
+ groupByDay: {
29701
+ classPropertyName: "groupByDay",
29702
+ publicName: "groupByDay",
29703
+ isSignal: true,
29704
+ isRequired: false,
29705
+ transformFunction: null
29706
+ },
29707
+ timeZone: {
29708
+ classPropertyName: "timeZone",
29709
+ publicName: "timeZone",
29710
+ isSignal: true,
29711
+ isRequired: false,
29712
+ transformFunction: null
29713
+ },
29714
+ now: {
29715
+ classPropertyName: "now",
29716
+ publicName: "now",
29717
+ isSignal: true,
29718
+ isRequired: false,
29719
+ transformFunction: null
29720
+ },
29721
+ dayHeadingLevel: {
29722
+ classPropertyName: "dayHeadingLevel",
29723
+ publicName: "dayHeadingLevel",
29724
+ isSignal: true,
29725
+ isRequired: false,
29726
+ transformFunction: null
29386
29727
  }
29387
29728
  },
29388
29729
  ngImport: i0,
@@ -29399,29 +29740,47 @@ var TimelineComponent = class TimelineComponent {
29399
29740
  <ui-hint class="tl-empty">{{ emptyMessage() }}</ui-hint>
29400
29741
  }
29401
29742
  <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>
29743
+ @if (groupByDay()) {
29744
+ <ol class="tl tl-grouped" [attr.aria-label]="ariaLabel() || null">
29745
+ @for (g of groups(); track $index) {
29746
+ <li class="tl-day-group" [attr.data-day]="g.key || null">
29747
+ @if (g.label) { <div class="tl-day" role="heading" [attr.aria-level]="headingLevel()">{{ g.label }}</div> }
29748
+ <ol class="tl-sub">
29749
+ @for (item of g.items; track item.id ?? $index) {
29750
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29415
29751
  }
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>
29752
+ </ol>
29753
+ </li>
29754
+ }
29755
+ </ol>
29756
+ } @else {
29757
+ <ol class="tl" [attr.aria-label]="ariaLabel() || null">
29758
+ @for (item of items(); track item.id ?? $index) {
29759
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29760
+ }
29761
+ </ol>
29762
+ }
29763
+ </ng-template>
29764
+ <ng-template #itemTpl let-item>
29765
+ <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)">
29766
+ <span class="tl-marker" aria-hidden="true">
29767
+ @if (item.icon) { <ui-icon [name]="item.icon" [interactive]="false" [size]="12" /> }
29768
+ </span>
29769
+ <div class="tl-content">
29770
+ <div class="tl-head">
29771
+ <span class="tl-title">{{ item.title }}</span>
29772
+ @if (item.badge) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: item.badge }" /> }
29773
+ @for (b of item.badges ?? []; track $index) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: b }" /> }
29774
+ @if (timePosition() === 'end' && (item.time || item.dateTime)) {
29775
+ <time class="tl-time tl-time--end" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29776
+ }
29777
+ </div>
29778
+ @if (item.description) { <p class="tl-description">{{ item.description }}</p> }
29779
+ @if (timePosition() !== 'end' && (item.time || item.dateTime)) {
29780
+ <time class="tl-time" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29781
+ }
29782
+ </div>
29783
+ </li>
29425
29784
  </ng-template>
29426
29785
  <ng-template #badgeTpl let-b>
29427
29786
  @if (b.tooltip) {
@@ -29432,7 +29791,7 @@ var TimelineComponent = class TimelineComponent {
29432
29791
  </ng-template>
29433
29792
  `,
29434
29793
  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"],
29794
+ 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
29795
  dependencies: [
29437
29796
  {
29438
29797
  kind: "component",
@@ -29513,29 +29872,47 @@ i0.ɵɵngDeclareClassMetadata({
29513
29872
  <ui-hint class="tl-empty">{{ emptyMessage() }}</ui-hint>
29514
29873
  }
29515
29874
  <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>
29875
+ @if (groupByDay()) {
29876
+ <ol class="tl tl-grouped" [attr.aria-label]="ariaLabel() || null">
29877
+ @for (g of groups(); track $index) {
29878
+ <li class="tl-day-group" [attr.data-day]="g.key || null">
29879
+ @if (g.label) { <div class="tl-day" role="heading" [attr.aria-level]="headingLevel()">{{ g.label }}</div> }
29880
+ <ol class="tl-sub">
29881
+ @for (item of g.items; track item.id ?? $index) {
29882
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29529
29883
  }
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>
29884
+ </ol>
29885
+ </li>
29886
+ }
29887
+ </ol>
29888
+ } @else {
29889
+ <ol class="tl" [attr.aria-label]="ariaLabel() || null">
29890
+ @for (item of items(); track item.id ?? $index) {
29891
+ <ng-container [ngTemplateOutlet]="itemTpl" [ngTemplateOutletContext]="{ $implicit: item }" />
29892
+ }
29893
+ </ol>
29894
+ }
29895
+ </ng-template>
29896
+ <ng-template #itemTpl let-item>
29897
+ <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)">
29898
+ <span class="tl-marker" aria-hidden="true">
29899
+ @if (item.icon) { <ui-icon [name]="item.icon" [interactive]="false" [size]="12" /> }
29900
+ </span>
29901
+ <div class="tl-content">
29902
+ <div class="tl-head">
29903
+ <span class="tl-title">{{ item.title }}</span>
29904
+ @if (item.badge) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: item.badge }" /> }
29905
+ @for (b of item.badges ?? []; track $index) { <ng-container [ngTemplateOutlet]="badgeTpl" [ngTemplateOutletContext]="{ $implicit: b }" /> }
29906
+ @if (timePosition() === 'end' && (item.time || item.dateTime)) {
29907
+ <time class="tl-time tl-time--end" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29908
+ }
29909
+ </div>
29910
+ @if (item.description) { <p class="tl-description">{{ item.description }}</p> }
29911
+ @if (timePosition() !== 'end' && (item.time || item.dateTime)) {
29912
+ <time class="tl-time" [attr.datetime]="item.dateTime || null">{{ item.time || item.dateTime }}</time>
29913
+ }
29914
+ </div>
29915
+ </li>
29539
29916
  </ng-template>
29540
29917
  <ng-template #badgeTpl let-b>
29541
29918
  @if (b.tooltip) {
@@ -29545,7 +29922,7 @@ i0.ɵɵngDeclareClassMetadata({
29545
29922
  }
29546
29923
  </ng-template>
29547
29924
  `,
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"]
29925
+ 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
29926
  }]
29550
29927
  }],
29551
29928
  propDecorators: {
@@ -29588,6 +29965,38 @@ i0.ɵɵngDeclareClassMetadata({
29588
29965
  alias: "timePosition",
29589
29966
  required: false
29590
29967
  }]
29968
+ }],
29969
+ groupByDay: [{
29970
+ type: i0.Input,
29971
+ args: [{
29972
+ isSignal: true,
29973
+ alias: "groupByDay",
29974
+ required: false
29975
+ }]
29976
+ }],
29977
+ timeZone: [{
29978
+ type: i0.Input,
29979
+ args: [{
29980
+ isSignal: true,
29981
+ alias: "timeZone",
29982
+ required: false
29983
+ }]
29984
+ }],
29985
+ now: [{
29986
+ type: i0.Input,
29987
+ args: [{
29988
+ isSignal: true,
29989
+ alias: "now",
29990
+ required: false
29991
+ }]
29992
+ }],
29993
+ dayHeadingLevel: [{
29994
+ type: i0.Input,
29995
+ args: [{
29996
+ isSignal: true,
29997
+ alias: "dayHeadingLevel",
29998
+ required: false
29999
+ }]
29591
30000
  }]
29592
30001
  }
29593
30002
  });
@@ -34909,6 +35318,10 @@ i0.ɵɵngDeclareClassMetadata({
34909
35318
  });
34910
35319
  var BoardCardDirective = class BoardCardDirective {
34911
35320
  constructor() {
35321
+ this.typeFrom = input("", {
35322
+ ...ngDevMode ? { debugName: "typeFrom" } : /* istanbul ignore next */ {},
35323
+ alias: "uiBoardCard"
35324
+ });
34912
35325
  this.template = inject(TemplateRef);
34913
35326
  }
34914
35327
  static ngTemplateContextGuard(_dir, _ctx) {
@@ -34926,11 +35339,18 @@ var BoardCardDirective = class BoardCardDirective {
34926
35339
  }
34927
35340
  static {
34928
35341
  this.ɵdir = i0.ɵɵngDeclareDirective({
34929
- minVersion: "14.0.0",
35342
+ minVersion: "17.1.0",
34930
35343
  version: "22.2.2",
34931
35344
  type: BoardCardDirective,
34932
35345
  isStandalone: true,
34933
35346
  selector: "ng-template[uiBoardCard]",
35347
+ inputs: { typeFrom: {
35348
+ classPropertyName: "typeFrom",
35349
+ publicName: "uiBoardCard",
35350
+ isSignal: true,
35351
+ isRequired: false,
35352
+ transformFunction: null
35353
+ } },
34934
35354
  ngImport: i0
34935
35355
  });
34936
35356
  }
@@ -34946,8 +35366,19 @@ i0.ɵɵngDeclareClassMetadata({
34946
35366
  selector: "ng-template[uiBoardCard]",
34947
35367
  standalone: true
34948
35368
  }]
34949
- }]
35369
+ }],
35370
+ propDecorators: { typeFrom: [{
35371
+ type: i0.Input,
35372
+ args: [{
35373
+ isSignal: true,
35374
+ alias: "uiBoardCard",
35375
+ required: false
35376
+ }]
35377
+ }] }
34950
35378
  });
35379
+ const MOVE_PREFIX = "ub-move:";
35380
+ const MOVE_ICON = "M4 12h12m0 0l-4-4m4 4l-4 4M20 5v14";
35381
+ let nextBoardId = 0;
34951
35382
  const DOT_COLORS = {
34952
35383
  blue: "#3b82f6",
34953
35384
  cyan: "#06b6d4",
@@ -34961,11 +35392,31 @@ const DOT_COLORS = {
34961
35392
  gray: "#6b7280"
34962
35393
  };
34963
35394
  var BoardComponent = class BoardComponent {
35395
+ limitOf(col) {
35396
+ const size = this.pageSize() > 0 ? Math.floor(this.pageSize()) : 0;
35397
+ if (!size) return col.items.length;
35398
+ let limit = this.drawn()[col.key] ?? size;
35399
+ const moved = this.movedTo();
35400
+ if (moved?.to === col.key) limit = Math.max(limit, col.items.findIndex((i) => this.itemKey()(i) === moved.key) + 1);
35401
+ return limit;
35402
+ }
35403
+ showMore(key) {
35404
+ const size = Math.floor(this.pageSize());
35405
+ const col = this.cols().find((c) => c.key === key);
35406
+ if (!col || size < 1) return;
35407
+ const limit = Math.min(col.items.length, this.limitOf(col) + size);
35408
+ this.drawn.update((d) => ({
35409
+ ...d,
35410
+ [key]: limit
35411
+ }));
35412
+ this.announcement.set(`Showing ${limit} of ${col.items.length} ${this.itemNounPlural()} in ${col.label}`);
35413
+ }
34964
35414
  constructor() {
34965
35415
  this.columns = input.required(...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
34966
35416
  this.itemKey = input.required(...ngDevMode ? [{ debugName: "itemKey" }] : /* istanbul ignore next */ []);
34967
35417
  this.itemLabel = input.required(...ngDevMode ? [{ debugName: "itemLabel" }] : /* istanbul ignore next */ []);
34968
35418
  this.cardActions = input([], ...ngDevMode ? [{ debugName: "cardActions" }] : /* istanbul ignore next */ []);
35419
+ this.moveMenu = input(true, ...ngDevMode ? [{ debugName: "moveMenu" }] : /* istanbul ignore next */ []);
34969
35420
  this.loading = input(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
34970
35421
  this.error = input(null, ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
34971
35422
  this.readOnly = input(false, ...ngDevMode ? [{ debugName: "readOnly" }] : /* istanbul ignore next */ []);
@@ -34977,12 +35428,29 @@ var BoardComponent = class BoardComponent {
34977
35428
  this.itemNoun = input("item", ...ngDevMode ? [{ debugName: "itemNoun" }] : /* istanbul ignore next */ []);
34978
35429
  this.itemNounPlural = input("items", ...ngDevMode ? [{ debugName: "itemNounPlural" }] : /* istanbul ignore next */ []);
34979
35430
  this.retryLabel = input("Retry", ...ngDevMode ? [{ debugName: "retryLabel" }] : /* istanbul ignore next */ []);
35431
+ this.pageSize = input(50, ...ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []);
34980
35432
  this.cardClick = output();
34981
35433
  this.cardAction = output();
34982
35434
  this.itemMove = output();
34983
35435
  this.retry = output();
34984
35436
  this.card = contentChild(BoardCardDirective, ...ngDevMode ? [{ debugName: "card" }] : /* istanbul ignore next */ []);
34985
35437
  this.cols = linkedSignal(() => this.columns(), ...ngDevMode ? [{ debugName: "cols" }] : /* istanbul ignore next */ []);
35438
+ this.drawn = signal({}, ...ngDevMode ? [{ debugName: "drawn" }] : /* istanbul ignore next */ []);
35439
+ this.movedTo = signal(null, ...ngDevMode ? [{ debugName: "movedTo" }] : /* istanbul ignore next */ []);
35440
+ this.shownCols = computed(() => {
35441
+ const size = this.pageSize() > 0 ? Math.floor(this.pageSize()) : 0;
35442
+ return this.cols().map((col) => {
35443
+ const limit = this.limitOf(col);
35444
+ const hidden = Math.max(0, col.items.length - limit);
35445
+ return {
35446
+ col,
35447
+ shown: hidden ? col.items.slice(0, limit) : col.items,
35448
+ hidden,
35449
+ next: Math.min(size, hidden)
35450
+ };
35451
+ });
35452
+ }, ...ngDevMode ? [{ debugName: "shownCols" }] : /* istanbul ignore next */ []);
35453
+ this.hintId = `ub-hint-${nextBoardId++}`;
34986
35454
  this.overKey = signal(null, ...ngDevMode ? [{ debugName: "overKey" }] : /* istanbul ignore next */ []);
34987
35455
  this.draggingKey = signal(null, ...ngDevMode ? [{ debugName: "draggingKey" }] : /* istanbul ignore next */ []);
34988
35456
  this.announcement = signal("", ...ngDevMode ? [{ debugName: "announcement" }] : /* istanbul ignore next */ []);
@@ -34990,7 +35458,33 @@ var BoardComponent = class BoardComponent {
34990
35458
  this.drag = null;
34991
35459
  this.skeletonColumns = computed(() => Array.from({ length: Math.max(this.columns().length, 4) }, (_, i) => i), ...ngDevMode ? [{ debugName: "skeletonColumns" }] : /* istanbul ignore next */ []);
34992
35460
  this.canDrag = computed(() => !this.readOnly() && !this.moveDisabled(), ...ngDevMode ? [{ debugName: "canDrag" }] : /* istanbul ignore next */ []);
34993
- this.canMoveAny = this.canDrag;
35461
+ this.menuActions = computed(() => {
35462
+ const out = /* @__PURE__ */ new Map();
35463
+ const own = this.cardActions();
35464
+ if (!this.moveMenu() || !this.canDrag()) return out;
35465
+ const cols = this.cols();
35466
+ const shared = /* @__PURE__ */ new Map();
35467
+ for (const from of cols) for (const item of from.items) {
35468
+ let list = this.canMove() ? void 0 : shared.get(from.key);
35469
+ if (!list) {
35470
+ const moves = cols.filter((to) => this.accepts(item, from.key, to)).map((to) => ({
35471
+ type: MOVE_PREFIX + to.key,
35472
+ label: `Move to ${to.label}`,
35473
+ icon: MOVE_ICON
35474
+ }));
35475
+ list = moves.length ? [...own, ...moves] : own;
35476
+ if (!this.canMove()) shared.set(from.key, list);
35477
+ }
35478
+ out.set(this.itemKey()(item), list);
35479
+ }
35480
+ return out;
35481
+ }, ...ngDevMode ? [{ debugName: "menuActions" }] : /* istanbul ignore next */ []);
35482
+ effect(() => {
35483
+ if (this.loading()) {
35484
+ this.drawn.set({});
35485
+ this.movedTo.set(null);
35486
+ }
35487
+ });
34994
35488
  }
34995
35489
  dot(color) {
34996
35490
  return color && DOT_COLORS[color] || color || "#3b82f6";
@@ -35049,13 +35543,32 @@ var BoardComponent = class BoardComponent {
35049
35543
  for (let i = cols.findIndex((c) => c.key === col.key) + step; i >= 0 && i < cols.length; i += step) if (this.accepts(item, col.key, cols[i])) {
35050
35544
  this.move(item, col.key, cols[i].key);
35051
35545
  this.announcement.set(`${this.itemLabel()(item)} moved to ${cols[i].label}`);
35052
- const key = this.itemKey()(item);
35053
- setTimeout(() => {
35054
- const cards = this.host.nativeElement.querySelectorAll(".ub-card");
35055
- Array.from(cards).find((c) => c.dataset["boardKey"] === key)?.focus();
35546
+ this.focusCard(item);
35547
+ return;
35548
+ }
35549
+ }
35550
+ onMenuAction(type, item) {
35551
+ if (!type.startsWith(MOVE_PREFIX)) {
35552
+ this.cardAction.emit({
35553
+ type,
35554
+ item
35056
35555
  });
35057
35556
  return;
35058
35557
  }
35558
+ const key = this.itemKey()(item);
35559
+ const from = this.cols().find((c) => c.items.some((i) => this.itemKey()(i) === key));
35560
+ const to = this.cols().find((c) => c.key === type.slice(8));
35561
+ if (!from || !to || !this.accepts(item, from.key, to)) return;
35562
+ this.move(item, from.key, to.key);
35563
+ this.announcement.set(`${this.itemLabel()(item)} moved to ${to.label}`);
35564
+ this.focusCard(item);
35565
+ }
35566
+ focusCard(item) {
35567
+ const key = this.itemKey()(item);
35568
+ setTimeout(() => {
35569
+ const cards = this.host.nativeElement.querySelectorAll(".ub-card");
35570
+ Array.from(cards).find((c) => c.dataset["boardKey"] === key)?.focus();
35571
+ });
35059
35572
  }
35060
35573
  accepts(item, from, to) {
35061
35574
  if (from === to.key || to.dropDisabled || this.moveDisabled() || this.readOnly()) return false;
@@ -35076,11 +35589,18 @@ var BoardComponent = class BoardComponent {
35076
35589
  };
35077
35590
  return c;
35078
35591
  }));
35592
+ this.movedTo.set({
35593
+ key,
35594
+ to
35595
+ });
35079
35596
  this.itemMove.emit({
35080
35597
  item,
35081
35598
  from,
35082
35599
  to,
35083
- revert: () => this.cols.set(before)
35600
+ revert: () => {
35601
+ this.cols.set(before);
35602
+ this.movedTo.set(null);
35603
+ }
35084
35604
  });
35085
35605
  }
35086
35606
  static {
@@ -35129,6 +35649,13 @@ var BoardComponent = class BoardComponent {
35129
35649
  isRequired: false,
35130
35650
  transformFunction: null
35131
35651
  },
35652
+ moveMenu: {
35653
+ classPropertyName: "moveMenu",
35654
+ publicName: "moveMenu",
35655
+ isSignal: true,
35656
+ isRequired: false,
35657
+ transformFunction: null
35658
+ },
35132
35659
  loading: {
35133
35660
  classPropertyName: "loading",
35134
35661
  publicName: "loading",
@@ -35205,6 +35732,13 @@ var BoardComponent = class BoardComponent {
35205
35732
  isSignal: true,
35206
35733
  isRequired: false,
35207
35734
  transformFunction: null
35735
+ },
35736
+ pageSize: {
35737
+ classPropertyName: "pageSize",
35738
+ publicName: "pageSize",
35739
+ isSignal: true,
35740
+ isRequired: false,
35741
+ transformFunction: null
35208
35742
  }
35209
35743
  },
35210
35744
  outputs: {
@@ -35224,10 +35758,11 @@ var BoardComponent = class BoardComponent {
35224
35758
  template: `
35225
35759
  <!-- The card's "⋮" menu. Place it in the card's top row: <ng-container [ngTemplateOutlet]="menu" [ngTemplateOutletContext]="{ $implicit: item }" /> -->
35226
35760
  <ng-template #menuTpl let-item>
35227
- @if (cardActions().length) {
35761
+ @let actions = menuActions().get(itemKey()(item)) ?? cardActions();
35762
+ @if (actions.length) {
35228
35763
  <div class="ub-card__top-right" (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
35229
- <ui-more-menu [actions]="cardActions()" [ariaLabel]="'Actions for ' + itemLabel()(item)"
35230
- (actionClick)="cardAction.emit({ type: $event, item })" />
35764
+ <ui-more-menu [actions]="actions" [ariaLabel]="'Actions for ' + itemLabel()(item)"
35765
+ (actionClick)="onMenuAction($event, item)" />
35231
35766
  </div>
35232
35767
  }
35233
35768
  </ng-template>
@@ -35249,8 +35784,9 @@ var BoardComponent = class BoardComponent {
35249
35784
  } @else if (cols().length === 0) {
35250
35785
  <div class="ub-message" role="status"><p>{{ emptyMessage() }}</p></div>
35251
35786
  } @else {
35252
- <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()">
35253
- @for (col of cols(); track col.key) {
35787
+ <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()" [attr.aria-describedby]="canDrag() ? hintId : null">
35788
+ @for (view of shownCols(); track view.col.key) {
35789
+ @let col = view.col;
35254
35790
  <div class="ub-col"
35255
35791
  [class.ub-col--over]="overKey() === col.key"
35256
35792
  [class.ub-col--success]="col.tone === 'success'"
@@ -35266,19 +35802,20 @@ var BoardComponent = class BoardComponent {
35266
35802
  <span class="ub-col__count" aria-hidden="true">{{ col.items.length }}</span>
35267
35803
  </div>
35268
35804
  @if (col.summary) {
35269
- <div class="ub-col__summary" [attr.aria-label]="col.summaryLabel || col.summary">{{ col.summary }}</div>
35805
+ <div class="ub-col__summary"><span aria-hidden="true">{{ col.summary }}</span><span class="ub-sr-only">{{ col.summaryLabel || col.summary }}</span></div>
35270
35806
  }
35271
35807
  </div>
35272
- <div class="ub-col__cards" role="list">
35273
- @for (item of col.items; track itemKey()(item)) {
35808
+ <div class="ub-col__cards" [attr.role]="col.items.length ? 'list' : null">
35809
+ @for (item of view.shown; track itemKey()(item)) {
35810
+ @let key = itemKey()(item);
35274
35811
  <div class="ub-card"
35275
35812
  [class.ub-card--success]="col.tone === 'success'"
35276
- [class.ub-card--dragging]="draggingKey() === itemKey()(item)"
35813
+ [class.ub-card--dragging]="draggingKey() === key"
35277
35814
  role="listitem"
35278
35815
  tabindex="0"
35279
- [attr.data-board-key]="itemKey()(item)"
35816
+ [attr.data-board-key]="key"
35280
35817
  [attr.aria-label]="itemLabel()(item)"
35281
- [attr.aria-keyshortcuts]="canMoveAny() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35818
+ [attr.aria-keyshortcuts]="canDrag() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35282
35819
  [attr.draggable]="canDrag() ? 'true' : null"
35283
35820
  (dragstart)="onDragStart($event, item, col)"
35284
35821
  (dragend)="onDragEnd()"
@@ -35289,6 +35826,11 @@ var BoardComponent = class BoardComponent {
35289
35826
  }
35290
35827
  </div>
35291
35828
  }
35829
+ @if (view.hidden > 0) {
35830
+ <div class="ub-col__more" role="listitem">
35831
+ <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>
35832
+ </div>
35833
+ }
35292
35834
  @if (col.items.length === 0) {
35293
35835
  <div class="ub-col__empty" role="status">{{ col.emptyText || emptyColumnText() }}</div>
35294
35836
  }
@@ -35296,12 +35838,15 @@ var BoardComponent = class BoardComponent {
35296
35838
  </div>
35297
35839
  }
35298
35840
  </div>
35841
+ @if (canDrag()) {
35842
+ <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>
35843
+ }
35299
35844
  <div class="ub-sr-only" role="status" aria-live="polite">{{ announcement() }}</div>
35300
35845
  }
35301
35846
  </div>
35302
35847
  `,
35303
35848
  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"],
35849
+ 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
35850
  dependencies: [
35306
35851
  {
35307
35852
  kind: "directive",
@@ -35376,10 +35921,11 @@ i0.ɵɵngDeclareClassMetadata({
35376
35921
  template: `
35377
35922
  <!-- The card's "⋮" menu. Place it in the card's top row: <ng-container [ngTemplateOutlet]="menu" [ngTemplateOutletContext]="{ $implicit: item }" /> -->
35378
35923
  <ng-template #menuTpl let-item>
35379
- @if (cardActions().length) {
35924
+ @let actions = menuActions().get(itemKey()(item)) ?? cardActions();
35925
+ @if (actions.length) {
35380
35926
  <div class="ub-card__top-right" (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
35381
- <ui-more-menu [actions]="cardActions()" [ariaLabel]="'Actions for ' + itemLabel()(item)"
35382
- (actionClick)="cardAction.emit({ type: $event, item })" />
35927
+ <ui-more-menu [actions]="actions" [ariaLabel]="'Actions for ' + itemLabel()(item)"
35928
+ (actionClick)="onMenuAction($event, item)" />
35383
35929
  </div>
35384
35930
  }
35385
35931
  </ng-template>
@@ -35401,8 +35947,9 @@ i0.ɵɵngDeclareClassMetadata({
35401
35947
  } @else if (cols().length === 0) {
35402
35948
  <div class="ub-message" role="status"><p>{{ emptyMessage() }}</p></div>
35403
35949
  } @else {
35404
- <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()">
35405
- @for (col of cols(); track col.key) {
35950
+ <div class="ub-board" role="region" [attr.aria-label]="ariaLabel()" [attr.aria-describedby]="canDrag() ? hintId : null">
35951
+ @for (view of shownCols(); track view.col.key) {
35952
+ @let col = view.col;
35406
35953
  <div class="ub-col"
35407
35954
  [class.ub-col--over]="overKey() === col.key"
35408
35955
  [class.ub-col--success]="col.tone === 'success'"
@@ -35418,19 +35965,20 @@ i0.ɵɵngDeclareClassMetadata({
35418
35965
  <span class="ub-col__count" aria-hidden="true">{{ col.items.length }}</span>
35419
35966
  </div>
35420
35967
  @if (col.summary) {
35421
- <div class="ub-col__summary" [attr.aria-label]="col.summaryLabel || col.summary">{{ col.summary }}</div>
35968
+ <div class="ub-col__summary"><span aria-hidden="true">{{ col.summary }}</span><span class="ub-sr-only">{{ col.summaryLabel || col.summary }}</span></div>
35422
35969
  }
35423
35970
  </div>
35424
- <div class="ub-col__cards" role="list">
35425
- @for (item of col.items; track itemKey()(item)) {
35971
+ <div class="ub-col__cards" [attr.role]="col.items.length ? 'list' : null">
35972
+ @for (item of view.shown; track itemKey()(item)) {
35973
+ @let key = itemKey()(item);
35426
35974
  <div class="ub-card"
35427
35975
  [class.ub-card--success]="col.tone === 'success'"
35428
- [class.ub-card--dragging]="draggingKey() === itemKey()(item)"
35976
+ [class.ub-card--dragging]="draggingKey() === key"
35429
35977
  role="listitem"
35430
35978
  tabindex="0"
35431
- [attr.data-board-key]="itemKey()(item)"
35979
+ [attr.data-board-key]="key"
35432
35980
  [attr.aria-label]="itemLabel()(item)"
35433
- [attr.aria-keyshortcuts]="canMoveAny() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35981
+ [attr.aria-keyshortcuts]="canDrag() ? 'Shift+ArrowLeft Shift+ArrowRight' : null"
35434
35982
  [attr.draggable]="canDrag() ? 'true' : null"
35435
35983
  (dragstart)="onDragStart($event, item, col)"
35436
35984
  (dragend)="onDragEnd()"
@@ -35441,6 +35989,11 @@ i0.ɵɵngDeclareClassMetadata({
35441
35989
  }
35442
35990
  </div>
35443
35991
  }
35992
+ @if (view.hidden > 0) {
35993
+ <div class="ub-col__more" role="listitem">
35994
+ <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>
35995
+ </div>
35996
+ }
35444
35997
  @if (col.items.length === 0) {
35445
35998
  <div class="ub-col__empty" role="status">{{ col.emptyText || emptyColumnText() }}</div>
35446
35999
  }
@@ -35448,13 +36001,17 @@ i0.ɵɵngDeclareClassMetadata({
35448
36001
  </div>
35449
36002
  }
35450
36003
  </div>
36004
+ @if (canDrag()) {
36005
+ <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>
36006
+ }
35451
36007
  <div class="ub-sr-only" role="status" aria-live="polite">{{ announcement() }}</div>
35452
36008
  }
35453
36009
  </div>
35454
36010
  `,
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"]
36011
+ 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
36012
  }]
35457
36013
  }],
36014
+ ctorParameters: () => [],
35458
36015
  propDecorators: {
35459
36016
  columns: [{
35460
36017
  type: i0.Input,
@@ -35488,6 +36045,14 @@ i0.ɵɵngDeclareClassMetadata({
35488
36045
  required: false
35489
36046
  }]
35490
36047
  }],
36048
+ moveMenu: [{
36049
+ type: i0.Input,
36050
+ args: [{
36051
+ isSignal: true,
36052
+ alias: "moveMenu",
36053
+ required: false
36054
+ }]
36055
+ }],
35491
36056
  loading: [{
35492
36057
  type: i0.Input,
35493
36058
  args: [{
@@ -35576,6 +36141,14 @@ i0.ɵɵngDeclareClassMetadata({
35576
36141
  required: false
35577
36142
  }]
35578
36143
  }],
36144
+ pageSize: [{
36145
+ type: i0.Input,
36146
+ args: [{
36147
+ isSignal: true,
36148
+ alias: "pageSize",
36149
+ required: false
36150
+ }]
36151
+ }],
35579
36152
  cardClick: [{
35580
36153
  type: i0.Output,
35581
36154
  args: ["cardClick"]
@@ -36990,6 +37563,291 @@ i0.ɵɵngDeclareClassMetadata({
36990
37563
  }]
36991
37564
  }
36992
37565
  });
37566
+ const CSS_LENGTH = /^(?:0|(?:\d+\.?\d*|\.\d+)(?:px|rem|em|%|vh|vw|ch)|(?:calc|var)\([^;{}]*\))$/i;
37567
+ const BREAKPOINT_PX = {
37568
+ sm: 640,
37569
+ md: 900,
37570
+ lg: 1200
37571
+ };
37572
+ function lengthOr(v, fallback) {
37573
+ const t = String(v ?? "").trim();
37574
+ if (!t || !CSS_LENGTH.test(t)) return fallback;
37575
+ return t === "0" ? "0px" : t;
37576
+ }
37577
+ function px(v, fallback) {
37578
+ if (v === null || v === void 0 || v === "") return fallback;
37579
+ const n = Number(v);
37580
+ return Number.isFinite(n) && n >= 0 ? n : fallback;
37581
+ }
37582
+ var SidebarLayoutComponent = class SidebarLayoutComponent {
37583
+ constructor() {
37584
+ this.sideWidth = input("320px", ...ngDevMode ? [{ debugName: "sideWidth" }] : /* istanbul ignore next */ []);
37585
+ this.sidePosition = input("end", ...ngDevMode ? [{ debugName: "sidePosition" }] : /* istanbul ignore next */ []);
37586
+ this.gap = input("md", ...ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []);
37587
+ this.stickySide = input(true, ...ngDevMode ? [{ debugName: "stickySide" }] : /* istanbul ignore next */ []);
37588
+ this.stickyTop = input(16, ...ngDevMode ? [{ debugName: "stickyTop" }] : /* istanbul ignore next */ []);
37589
+ this.stickyOffset = input(32, ...ngDevMode ? [{ debugName: "stickyOffset" }] : /* istanbul ignore next */ []);
37590
+ this.collapseAt = input("md", ...ngDevMode ? [{ debugName: "collapseAt" }] : /* istanbul ignore next */ []);
37591
+ this.sideFirstWhenCollapsed = input(true, ...ngDevMode ? [{ debugName: "sideFirstWhenCollapsed" }] : /* istanbul ignore next */ []);
37592
+ this.sideFirstInDom = input(false, ...ngDevMode ? [{ debugName: "sideFirstInDom" }] : /* istanbul ignore next */ []);
37593
+ this.sideBleed = input("4px", ...ngDevMode ? [{ debugName: "sideBleed" }] : /* istanbul ignore next */ []);
37594
+ this.collapsed = signal(false, ...ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []);
37595
+ this.position = computed(() => this.sidePosition() === "start" ? "start" : "end", ...ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []);
37596
+ this.collapseKey = computed(() => {
37597
+ const c = this.collapseAt();
37598
+ return c === "never" || c === "sm" || c === "lg" ? c : "md";
37599
+ }, ...ngDevMode ? [{ debugName: "collapseKey" }] : /* istanbul ignore next */ []);
37600
+ this.domSideFirst = computed(() => this.sideFirstInDom() && this.sideFirstWhenCollapsed() && this.collapsed(), ...ngDevMode ? [{ debugName: "domSideFirst" }] : /* istanbul ignore next */ []);
37601
+ this.domOrder = computed(() => this.domSideFirst() ? "side-first" : "main-first", ...ngDevMode ? [{ debugName: "domOrder" }] : /* istanbul ignore next */ []);
37602
+ this.sideCss = computed(() => lengthOr(this.sideWidth(), "320px"), ...ngDevMode ? [{ debugName: "sideCss" }] : /* istanbul ignore next */ []);
37603
+ this.bleedCss = computed(() => lengthOr(this.sideBleed(), "4px"), ...ngDevMode ? [{ debugName: "bleedCss" }] : /* istanbul ignore next */ []);
37604
+ this.gapCss = computed(() => {
37605
+ const g = resolveLayoutGap(this.gap(), "md");
37606
+ if (g.startsWith("-")) return "16px";
37607
+ return g === "0" ? "0px" : g;
37608
+ }, ...ngDevMode ? [{ debugName: "gapCss" }] : /* istanbul ignore next */ []);
37609
+ this.topCss = computed(() => `${px(this.stickyTop(), 16)}px`, ...ngDevMode ? [{ debugName: "topCss" }] : /* istanbul ignore next */ []);
37610
+ this.offCss = computed(() => `${px(this.stickyOffset(), 32)}px`, ...ngDevMode ? [{ debugName: "offCss" }] : /* istanbul ignore next */ []);
37611
+ this.rootClass = computed(() => {
37612
+ const key = this.collapseKey();
37613
+ const collapse = key === "never" ? "" : `sl-c-${key}`;
37614
+ const domFirst = this.domSideFirst();
37615
+ return [
37616
+ this.position() === "start" ? "sl-start" : "",
37617
+ this.stickySide() ? "sl-sticky" : "",
37618
+ collapse,
37619
+ collapse && this.sideFirstWhenCollapsed() && !domFirst ? "sl-first" : "",
37620
+ domFirst ? "sl-dom-first" : ""
37621
+ ].filter(Boolean).join(" ");
37622
+ }, ...ngDevMode ? [{ debugName: "rootClass" }] : /* istanbul ignore next */ []);
37623
+ effect((onCleanup) => {
37624
+ const key = this.collapseKey();
37625
+ if (!this.sideFirstInDom() || key === "never" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
37626
+ this.collapsed.set(false);
37627
+ return;
37628
+ }
37629
+ const mql = window.matchMedia(`(max-width: ${BREAKPOINT_PX[key]}px)`);
37630
+ this.collapsed.set(mql.matches);
37631
+ const onChange = (e) => this.collapsed.set(e.matches);
37632
+ if (typeof mql.addEventListener === "function") {
37633
+ mql.addEventListener("change", onChange);
37634
+ onCleanup(() => mql.removeEventListener("change", onChange));
37635
+ } else {
37636
+ const legacy = mql;
37637
+ legacy.addListener(onChange);
37638
+ onCleanup(() => legacy.removeListener(onChange));
37639
+ }
37640
+ });
37641
+ }
37642
+ static {
37643
+ this.ɵfac = i0.ɵɵngDeclareFactory({
37644
+ minVersion: "12.0.0",
37645
+ version: "22.2.2",
37646
+ ngImport: i0,
37647
+ type: SidebarLayoutComponent,
37648
+ deps: [],
37649
+ target: i0.ɵɵFactoryTarget.Component
37650
+ });
37651
+ }
37652
+ static {
37653
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
37654
+ minVersion: "17.0.0",
37655
+ version: "22.2.2",
37656
+ type: SidebarLayoutComponent,
37657
+ isStandalone: true,
37658
+ selector: "ui-sidebar-layout",
37659
+ inputs: {
37660
+ sideWidth: {
37661
+ classPropertyName: "sideWidth",
37662
+ publicName: "sideWidth",
37663
+ isSignal: true,
37664
+ isRequired: false,
37665
+ transformFunction: null
37666
+ },
37667
+ sidePosition: {
37668
+ classPropertyName: "sidePosition",
37669
+ publicName: "sidePosition",
37670
+ isSignal: true,
37671
+ isRequired: false,
37672
+ transformFunction: null
37673
+ },
37674
+ gap: {
37675
+ classPropertyName: "gap",
37676
+ publicName: "gap",
37677
+ isSignal: true,
37678
+ isRequired: false,
37679
+ transformFunction: null
37680
+ },
37681
+ stickySide: {
37682
+ classPropertyName: "stickySide",
37683
+ publicName: "stickySide",
37684
+ isSignal: true,
37685
+ isRequired: false,
37686
+ transformFunction: null
37687
+ },
37688
+ stickyTop: {
37689
+ classPropertyName: "stickyTop",
37690
+ publicName: "stickyTop",
37691
+ isSignal: true,
37692
+ isRequired: false,
37693
+ transformFunction: null
37694
+ },
37695
+ stickyOffset: {
37696
+ classPropertyName: "stickyOffset",
37697
+ publicName: "stickyOffset",
37698
+ isSignal: true,
37699
+ isRequired: false,
37700
+ transformFunction: null
37701
+ },
37702
+ collapseAt: {
37703
+ classPropertyName: "collapseAt",
37704
+ publicName: "collapseAt",
37705
+ isSignal: true,
37706
+ isRequired: false,
37707
+ transformFunction: null
37708
+ },
37709
+ sideFirstWhenCollapsed: {
37710
+ classPropertyName: "sideFirstWhenCollapsed",
37711
+ publicName: "sideFirstWhenCollapsed",
37712
+ isSignal: true,
37713
+ isRequired: false,
37714
+ transformFunction: null
37715
+ },
37716
+ sideFirstInDom: {
37717
+ classPropertyName: "sideFirstInDom",
37718
+ publicName: "sideFirstInDom",
37719
+ isSignal: true,
37720
+ isRequired: false,
37721
+ transformFunction: null
37722
+ },
37723
+ sideBleed: {
37724
+ classPropertyName: "sideBleed",
37725
+ publicName: "sideBleed",
37726
+ isSignal: true,
37727
+ isRequired: false,
37728
+ transformFunction: null
37729
+ }
37730
+ },
37731
+ host: { properties: { "attr.data-side-position": "position()" } },
37732
+ ngImport: i0,
37733
+ template: `<div class="sl" [class]="rootClass()" [attr.data-dom-order]="domOrder()" [style.--sl-side-w]="sideCss()" [style.--sl-gap]="gapCss()" [style.--sl-top]="topCss()" [style.--sl-off]="offCss()" [style.--sl-bleed]="bleedCss()" [style.row-gap]="gapCss()">@if (domSideFirst()) {<ng-container [ngTemplateOutlet]="sideTpl" /><ng-container [ngTemplateOutlet]="mainTpl" />} @else {<ng-container [ngTemplateOutlet]="mainTpl" /><ng-container [ngTemplateOutlet]="sideTpl" />}</div><ng-template #mainTpl><div class="sl-main"><ng-content select="[layout-main]" /></div></ng-template><ng-template #sideTpl><div class="sl-side"><ng-content select="[layout-side]" /></div></ng-template>`,
37734
+ isInline: true,
37735
+ styles: [":host{display:block}.sl{display:grid;grid-template-columns:minmax(0,1fr) auto;--sl-mis: var(--sl-gap, 16px);--sl-mie: 0px}.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);min-width:0;margin-inline-start:var(--sl-mis);margin-inline-end:var(--sl-mie)}.sl-side:empty{display:none}.sl.sl-start{grid-template-columns:auto minmax(0,1fr);--sl-mis: 0px;--sl-mie: var(--sl-gap, 16px)}.sl.sl-start .sl-main{grid-column:2}.sl.sl-start .sl-side{grid-column:1}.sl.sl-sticky{--sl-bin: min(var(--sl-bleed, 4px), var(--sl-gap, 16px));--sl-mis: calc(var(--sl-gap, 16px) - var(--sl-bin));--sl-mie: calc(-1 * var(--sl-bleed, 4px));--sl-pis: var(--sl-bin);--sl-pie: var(--sl-bleed, 4px)}.sl.sl-sticky.sl-start{--sl-mis: calc(-1 * var(--sl-bleed, 4px));--sl-mie: calc(var(--sl-gap, 16px) - var(--sl-bin));--sl-pis: var(--sl-bleed, 4px);--sl-pie: var(--sl-bin)}.sl.sl-sticky .sl-side{position:-webkit-sticky;position:sticky;top:calc(var(--sl-top, 16px) - var(--sl-bleed, 4px));align-self:start;width:calc(var(--sl-side-w, 320px) + var(--sl-bleed, 4px) + var(--sl-bin));padding-block:var(--sl-bleed, 4px);padding-inline-start:var(--sl-pis);padding-inline-end:var(--sl-pie);margin-block-start:calc(-1 * var(--sl-bleed, 4px));margin-block-end:calc(-1 * var(--sl-bleed, 4px));max-height:calc(100vh - (var(--sl-top, 16px) + var(--sl-off, 32px)) + 2 * var(--sl-bleed, 4px));max-height:calc(100dvh - (var(--sl-top, 16px) + var(--sl-off, 32px)) + 2 * var(--sl-bleed, 4px));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;padding:0;margin-inline-start:0;margin-inline-end:0;margin-block-start:0;margin-block-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;padding:0;margin-inline-start:0;margin-inline-end:0;margin-block-start:0;margin-block-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;padding:0;margin-inline-start:0;margin-inline-end:0;margin-block-start:0;margin-block-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"],
37736
+ dependencies: [{
37737
+ kind: "directive",
37738
+ type: NgTemplateOutlet,
37739
+ selector: "[ngTemplateOutlet]",
37740
+ inputs: [
37741
+ "ngTemplateOutletContext",
37742
+ "ngTemplateOutlet",
37743
+ "ngTemplateOutletInjector"
37744
+ ]
37745
+ }],
37746
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
37747
+ });
37748
+ }
37749
+ };
37750
+ i0.ɵɵngDeclareClassMetadata({
37751
+ minVersion: "12.0.0",
37752
+ version: "22.2.2",
37753
+ ngImport: i0,
37754
+ type: SidebarLayoutComponent,
37755
+ decorators: [{
37756
+ type: Component,
37757
+ args: [{
37758
+ selector: "ui-sidebar-layout",
37759
+ standalone: true,
37760
+ changeDetection: ChangeDetectionStrategy.OnPush,
37761
+ imports: [NgTemplateOutlet],
37762
+ host: { "[attr.data-side-position]": "position()" },
37763
+ template: `<div class="sl" [class]="rootClass()" [attr.data-dom-order]="domOrder()" [style.--sl-side-w]="sideCss()" [style.--sl-gap]="gapCss()" [style.--sl-top]="topCss()" [style.--sl-off]="offCss()" [style.--sl-bleed]="bleedCss()" [style.row-gap]="gapCss()">@if (domSideFirst()) {<ng-container [ngTemplateOutlet]="sideTpl" /><ng-container [ngTemplateOutlet]="mainTpl" />} @else {<ng-container [ngTemplateOutlet]="mainTpl" /><ng-container [ngTemplateOutlet]="sideTpl" />}</div><ng-template #mainTpl><div class="sl-main"><ng-content select="[layout-main]" /></div></ng-template><ng-template #sideTpl><div class="sl-side"><ng-content select="[layout-side]" /></div></ng-template>`,
37764
+ styles: [":host{display:block}.sl{display:grid;grid-template-columns:minmax(0,1fr) auto;--sl-mis: var(--sl-gap, 16px);--sl-mie: 0px}.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);min-width:0;margin-inline-start:var(--sl-mis);margin-inline-end:var(--sl-mie)}.sl-side:empty{display:none}.sl.sl-start{grid-template-columns:auto minmax(0,1fr);--sl-mis: 0px;--sl-mie: var(--sl-gap, 16px)}.sl.sl-start .sl-main{grid-column:2}.sl.sl-start .sl-side{grid-column:1}.sl.sl-sticky{--sl-bin: min(var(--sl-bleed, 4px), var(--sl-gap, 16px));--sl-mis: calc(var(--sl-gap, 16px) - var(--sl-bin));--sl-mie: calc(-1 * var(--sl-bleed, 4px));--sl-pis: var(--sl-bin);--sl-pie: var(--sl-bleed, 4px)}.sl.sl-sticky.sl-start{--sl-mis: calc(-1 * var(--sl-bleed, 4px));--sl-mie: calc(var(--sl-gap, 16px) - var(--sl-bin));--sl-pis: var(--sl-bleed, 4px);--sl-pie: var(--sl-bin)}.sl.sl-sticky .sl-side{position:-webkit-sticky;position:sticky;top:calc(var(--sl-top, 16px) - var(--sl-bleed, 4px));align-self:start;width:calc(var(--sl-side-w, 320px) + var(--sl-bleed, 4px) + var(--sl-bin));padding-block:var(--sl-bleed, 4px);padding-inline-start:var(--sl-pis);padding-inline-end:var(--sl-pie);margin-block-start:calc(-1 * var(--sl-bleed, 4px));margin-block-end:calc(-1 * var(--sl-bleed, 4px));max-height:calc(100vh - (var(--sl-top, 16px) + var(--sl-off, 32px)) + 2 * var(--sl-bleed, 4px));max-height:calc(100dvh - (var(--sl-top, 16px) + var(--sl-off, 32px)) + 2 * var(--sl-bleed, 4px));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;padding:0;margin-inline-start:0;margin-inline-end:0;margin-block-start:0;margin-block-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;padding:0;margin-inline-start:0;margin-inline-end:0;margin-block-start:0;margin-block-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;padding:0;margin-inline-start:0;margin-inline-end:0;margin-block-start:0;margin-block-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"]
37765
+ }]
37766
+ }],
37767
+ ctorParameters: () => [],
37768
+ propDecorators: {
37769
+ sideWidth: [{
37770
+ type: i0.Input,
37771
+ args: [{
37772
+ isSignal: true,
37773
+ alias: "sideWidth",
37774
+ required: false
37775
+ }]
37776
+ }],
37777
+ sidePosition: [{
37778
+ type: i0.Input,
37779
+ args: [{
37780
+ isSignal: true,
37781
+ alias: "sidePosition",
37782
+ required: false
37783
+ }]
37784
+ }],
37785
+ gap: [{
37786
+ type: i0.Input,
37787
+ args: [{
37788
+ isSignal: true,
37789
+ alias: "gap",
37790
+ required: false
37791
+ }]
37792
+ }],
37793
+ stickySide: [{
37794
+ type: i0.Input,
37795
+ args: [{
37796
+ isSignal: true,
37797
+ alias: "stickySide",
37798
+ required: false
37799
+ }]
37800
+ }],
37801
+ stickyTop: [{
37802
+ type: i0.Input,
37803
+ args: [{
37804
+ isSignal: true,
37805
+ alias: "stickyTop",
37806
+ required: false
37807
+ }]
37808
+ }],
37809
+ stickyOffset: [{
37810
+ type: i0.Input,
37811
+ args: [{
37812
+ isSignal: true,
37813
+ alias: "stickyOffset",
37814
+ required: false
37815
+ }]
37816
+ }],
37817
+ collapseAt: [{
37818
+ type: i0.Input,
37819
+ args: [{
37820
+ isSignal: true,
37821
+ alias: "collapseAt",
37822
+ required: false
37823
+ }]
37824
+ }],
37825
+ sideFirstWhenCollapsed: [{
37826
+ type: i0.Input,
37827
+ args: [{
37828
+ isSignal: true,
37829
+ alias: "sideFirstWhenCollapsed",
37830
+ required: false
37831
+ }]
37832
+ }],
37833
+ sideFirstInDom: [{
37834
+ type: i0.Input,
37835
+ args: [{
37836
+ isSignal: true,
37837
+ alias: "sideFirstInDom",
37838
+ required: false
37839
+ }]
37840
+ }],
37841
+ sideBleed: [{
37842
+ type: i0.Input,
37843
+ args: [{
37844
+ isSignal: true,
37845
+ alias: "sideBleed",
37846
+ required: false
37847
+ }]
37848
+ }]
37849
+ }
37850
+ });
36993
37851
  const JUSTIFY = {
36994
37852
  start: "flex-start",
36995
37853
  center: "center",
@@ -39428,6 +40286,6 @@ i0.ɵɵngDeclareClassMetadata({
39428
40286
  }]
39429
40287
  }
39430
40288
  });
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 };
40289
+ 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
40290
 
39433
40291
  //# sourceMappingURL=forgeroute-ui.mjs.map