@nucleus-suite-pe/core 2.2.0 → 2.3.0

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, inject, Injector, signal, computed, Injectable, effect, DestroyRef, ElementRef, input, Directive, model, untracked, ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, TemplateRef, viewChild, output, afterNextRender, contentChildren } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, inject, Injector, signal, computed, Injectable, effect, Pipe, DestroyRef, ElementRef, input, Directive, model, untracked, ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, TemplateRef, viewChild, output, afterNextRender, contentChildren } from '@angular/core';
3
3
  import { HttpContextToken, HttpClient, HttpContext, HttpErrorResponse } from '@angular/common/http';
4
4
  import { firstValueFrom, from, switchMap, catchError, throwError } from 'rxjs';
5
5
  import { Router, RouterLink, NavigationEnd } from '@angular/router';
@@ -499,8 +499,12 @@ class SessionService {
499
499
  if (!me)
500
500
  return [];
501
501
  return [
502
- ...me.ownedCompanies.map((company) => toOption(company, 'owner')),
503
- ...me.sharedCompanies.map((company) => toOption(company, 'collaborator')),
502
+ ...me.ownedCompanies
503
+ .filter((company) => company.isActive)
504
+ .map((company) => toOption(company, 'owner')),
505
+ ...me.sharedCompanies
506
+ .filter((company) => company.isActive)
507
+ .map((company) => toOption(company, 'collaborator')),
504
508
  ];
505
509
  }, ...(ngDevMode ? [{ debugName: "companyOptions" }] : /* istanbul ignore next */ []));
506
510
  companyId = computed(() => {
@@ -840,7 +844,7 @@ function isoDay(value) {
840
844
  const date = String(parsed.getDate()).padStart(2, '0');
841
845
  return `${year}-${month}-${date}`;
842
846
  }
843
- function toNumber(value) {
847
+ function toNumber$1(value) {
844
848
  const parsed = typeof value === 'number' ? value : Number(value);
845
849
  return Number.isFinite(parsed) ? parsed : 0;
846
850
  }
@@ -867,6 +871,82 @@ function endOfDayUtc(value) {
867
871
  return `${isoDay(nucleusParseDate(value))}T23:59:59.999Z`;
868
872
  }
869
873
 
874
+ const COMPACT_LOCALES = { es: 'es-PE', en: 'en-US' };
875
+ const BYTE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
876
+ function trim(value) {
877
+ return value.endsWith('.0') ? value.slice(0, -2) : value;
878
+ }
879
+ function compactNumber(value) {
880
+ if (!Number.isFinite(value))
881
+ return '—';
882
+ const abs = Math.abs(value);
883
+ const locale = COMPACT_LOCALES[nucleusLang()] ?? 'en-US';
884
+ let digits = 0;
885
+ if (abs >= 1000) {
886
+ const unit = 1000 ** Math.floor(Math.log10(abs) / 3);
887
+ digits = Math.abs(value / unit) < 10 ? 1 : 0;
888
+ }
889
+ const text = new Intl.NumberFormat(locale, {
890
+ notation: 'compact',
891
+ compactDisplay: 'short',
892
+ maximumFractionDigits: digits,
893
+ }).format(value);
894
+ return text.replace(/(\d)\s?k$/, '$1 K');
895
+ }
896
+ function compactBytes(value) {
897
+ if (!Number.isFinite(value) || value <= 0)
898
+ return '0 B';
899
+ const index = Math.min(Math.floor(Math.log(value) / Math.log(1024)), BYTE_UNITS.length - 1);
900
+ const scaled = value / 1024 ** index;
901
+ const digits = index === 0 ? 0 : scaled < 10 ? 1 : 0;
902
+ return `${trim(scaled.toFixed(digits))} ${BYTE_UNITS[index]}`;
903
+ }
904
+ function compactMegabytes(value) {
905
+ return compactBytes(value * 1024 * 1024);
906
+ }
907
+ function toNumber(value) {
908
+ if (value === null || value === undefined || value === '')
909
+ return null;
910
+ const parsed = typeof value === 'number' ? value : Number(value);
911
+ return Number.isFinite(parsed) ? parsed : null;
912
+ }
913
+ class NucleusCompact {
914
+ transform(value, fallback = '—') {
915
+ const parsed = toNumber(value);
916
+ return parsed === null ? fallback : compactNumber(parsed);
917
+ }
918
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCompact, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
919
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.22", ngImport: i0, type: NucleusCompact, isStandalone: true, name: "nucleusCompact" });
920
+ }
921
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCompact, decorators: [{
922
+ type: Pipe,
923
+ args: [{ name: 'nucleusCompact' }]
924
+ }] });
925
+ class NucleusBytes {
926
+ transform(value, fallback = '—') {
927
+ const parsed = toNumber(value);
928
+ return parsed === null ? fallback : compactBytes(parsed);
929
+ }
930
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusBytes, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
931
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.22", ngImport: i0, type: NucleusBytes, isStandalone: true, name: "nucleusBytes" });
932
+ }
933
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusBytes, decorators: [{
934
+ type: Pipe,
935
+ args: [{ name: 'nucleusBytes' }]
936
+ }] });
937
+ class NucleusMegabytes {
938
+ transform(value, fallback = '—') {
939
+ const parsed = toNumber(value);
940
+ return parsed === null ? fallback : compactMegabytes(parsed);
941
+ }
942
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusMegabytes, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
943
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.22", ngImport: i0, type: NucleusMegabytes, isStandalone: true, name: "nucleusMegabytes" });
944
+ }
945
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusMegabytes, decorators: [{
946
+ type: Pipe,
947
+ args: [{ name: 'nucleusMegabytes' }]
948
+ }] });
949
+
870
950
  const FIELD_TARGETS = [
871
951
  'input:not([type="hidden"]):not([disabled])',
872
952
  'textarea:not([disabled])',
@@ -1498,12 +1578,12 @@ const FRAMES = [
1498
1578
  starfield: true,
1499
1579
  accent: 'violet',
1500
1580
  tokens: {
1501
- bg: '#16132b',
1502
- raised: '#241f42',
1581
+ bg: '#1f1646',
1582
+ raised: '#2c2160',
1503
1583
  ink: '#ece9fb',
1504
- muted: '#9d95c6',
1505
- line: '#302a54',
1506
- glow: '#8c7ff0',
1584
+ muted: '#9690af',
1585
+ line: '#403863',
1586
+ glow: '#a78bfa',
1507
1587
  },
1508
1588
  },
1509
1589
  {
@@ -1512,12 +1592,12 @@ const FRAMES = [
1512
1592
  starfield: false,
1513
1593
  accent: 'blue',
1514
1594
  tokens: {
1515
- bg: '#131f33',
1516
- raised: '#1e2e48',
1517
- ink: '#e3ecfa',
1518
- muted: '#94a9c9',
1519
- line: '#2b3d5d',
1520
- glow: '#6ea8f0',
1595
+ bg: '#12244a',
1596
+ raised: '#1b3263',
1597
+ ink: '#e6edf9',
1598
+ muted: '#95a1b7',
1599
+ line: '#344466',
1600
+ glow: '#60a5fa',
1521
1601
  },
1522
1602
  },
1523
1603
  {
@@ -1526,12 +1606,12 @@ const FRAMES = [
1526
1606
  starfield: false,
1527
1607
  accent: 'cyan',
1528
1608
  tokens: {
1529
- bg: '#0d2a30',
1530
- raised: '#153c45',
1531
- ink: '#e0f2f4',
1532
- muted: '#8cb3b9',
1533
- line: '#1d4e58',
1534
- glow: '#4cc5e8',
1609
+ bg: '#0b3a44',
1610
+ raised: '#124d59',
1611
+ ink: '#e3f3f6',
1612
+ muted: '#a2bcc1',
1613
+ line: '#2e5860',
1614
+ glow: '#22d3ee',
1535
1615
  },
1536
1616
  },
1537
1617
  {
@@ -1540,26 +1620,26 @@ const FRAMES = [
1540
1620
  starfield: false,
1541
1621
  accent: 'green',
1542
1622
  tokens: {
1543
- bg: '#122419',
1544
- raised: '#1d3526',
1545
- ink: '#e2f1e7',
1546
- muted: '#93b8a1',
1547
- line: '#28462f',
1548
- glow: '#5cc47f',
1623
+ bg: '#0f3d2b',
1624
+ raised: '#18523b',
1625
+ ink: '#e6f2eb',
1626
+ muted: '#aabfb5',
1627
+ line: '#315a4a',
1628
+ glow: '#4ade80',
1549
1629
  },
1550
1630
  },
1551
1631
  {
1552
1632
  id: 'plum',
1553
1633
  scheme: 'dark',
1554
1634
  starfield: false,
1555
- accent: 'rose',
1635
+ accent: 'plum',
1556
1636
  tokens: {
1557
- bg: '#241330',
1558
- raised: '#341e43',
1559
- ink: '#f3e8f7',
1560
- muted: '#b596c3',
1561
- line: '#452851',
1562
- glow: '#cf7fdb',
1637
+ bg: '#3a1a4f',
1638
+ raised: '#4d2666',
1639
+ ink: '#f3e8fa',
1640
+ muted: '#b09ebc',
1641
+ line: '#583b6a',
1642
+ glow: '#c084fc',
1563
1643
  },
1564
1644
  },
1565
1645
  {
@@ -1568,12 +1648,12 @@ const FRAMES = [
1568
1648
  starfield: false,
1569
1649
  accent: 'red',
1570
1650
  tokens: {
1571
- bg: '#2a1113',
1572
- raised: '#3d1b1f',
1573
- ink: '#f8e6e7',
1574
- muted: '#c9979c',
1575
- line: '#4d2429',
1576
- glow: '#f0797b',
1651
+ bg: '#4a1519',
1652
+ raised: '#611f24',
1653
+ ink: '#fbe9e9',
1654
+ muted: '#b8989a',
1655
+ line: '#66373a',
1656
+ glow: '#f87171',
1577
1657
  },
1578
1658
  },
1579
1659
  {
@@ -1582,12 +1662,12 @@ const FRAMES = [
1582
1662
  starfield: false,
1583
1663
  accent: 'amber',
1584
1664
  tokens: {
1585
- bg: '#2b2415',
1586
- raised: '#3d3320',
1587
- ink: '#f6efdd',
1588
- muted: '#c2b18b',
1589
- line: '#4b3f28',
1590
- glow: '#e0a33a',
1665
+ bg: '#3d2d12',
1666
+ raised: '#52401c',
1667
+ ink: '#f7efdd',
1668
+ muted: '#bbb19c',
1669
+ line: '#5b4c32',
1670
+ glow: '#fbbf24',
1591
1671
  },
1592
1672
  },
1593
1673
  {
@@ -1596,12 +1676,12 @@ const FRAMES = [
1596
1676
  starfield: false,
1597
1677
  accent: 'blue',
1598
1678
  tokens: {
1599
- bg: '#232b36',
1600
- raised: '#313c4b',
1601
- ink: '#e6ecf4',
1602
- muted: '#9fb0c4',
1603
- line: '#3d4a5b',
1604
- glow: '#6fb2ea',
1679
+ bg: '#27313f',
1680
+ raised: '#354254',
1681
+ ink: '#e8edf3',
1682
+ muted: '#aab1b9',
1683
+ line: '#464f5c',
1684
+ glow: '#60a5fa',
1605
1685
  },
1606
1686
  },
1607
1687
  {
@@ -1612,10 +1692,10 @@ const FRAMES = [
1612
1692
  tokens: {
1613
1693
  bg: '#101318',
1614
1694
  raised: '#1b2129',
1615
- ink: '#edf0f4',
1616
- muted: '#97a1ae',
1617
- line: '#262d37',
1618
- glow: '#7fb3d9',
1695
+ ink: '#e9edf2',
1696
+ muted: '#85898e',
1697
+ line: '#33363b',
1698
+ glow: '#94a3b8',
1619
1699
  },
1620
1700
  },
1621
1701
  {
@@ -1626,10 +1706,10 @@ const FRAMES = [
1626
1706
  tokens: {
1627
1707
  bg: '#17171a',
1628
1708
  raised: '#232327',
1629
- ink: '#eeeef0',
1630
- muted: '#9c9ca4',
1631
- line: '#2f2f35',
1632
- glow: '#b9b9c2',
1709
+ ink: '#ededf0',
1710
+ muted: '#8b8b8e',
1711
+ line: '#39393c',
1712
+ glow: '#a1a1aa',
1633
1713
  },
1634
1714
  },
1635
1715
  {
@@ -1641,9 +1721,23 @@ const FRAMES = [
1641
1721
  bg: '#ffffff',
1642
1722
  raised: '#f1f0f5',
1643
1723
  ink: '#16151d',
1644
- muted: '#5e5c6b',
1645
- line: '#e3e2ea',
1646
- glow: '#5b4fd6',
1724
+ muted: '#6a696e',
1725
+ line: '#dadadb',
1726
+ glow: '#7c3aed',
1727
+ },
1728
+ },
1729
+ {
1730
+ id: 'mist',
1731
+ scheme: 'light',
1732
+ starfield: false,
1733
+ accent: 'blue',
1734
+ tokens: {
1735
+ bg: '#eef1f6',
1736
+ raised: '#e2e7ef',
1737
+ ink: '#141a24',
1738
+ muted: '#5e636b',
1739
+ line: '#cbcfd4',
1740
+ glow: '#2563eb',
1647
1741
  },
1648
1742
  },
1649
1743
  {
@@ -1655,23 +1749,51 @@ const FRAMES = [
1655
1749
  bg: '#f1cba0',
1656
1750
  raised: '#f6dfc4',
1657
1751
  ink: '#3b2f24',
1658
- muted: '#5f4e3d',
1659
- line: '#ccb383',
1752
+ muted: '#675442',
1753
+ line: '#d4b28c',
1660
1754
  glow: '#7a4a0a',
1661
1755
  },
1662
1756
  },
1663
1757
  {
1664
- id: 'mist',
1758
+ id: 'sage',
1759
+ scheme: 'light',
1760
+ starfield: false,
1761
+ accent: 'green',
1762
+ tokens: {
1763
+ bg: '#d3e4d6',
1764
+ raised: '#e3efe5',
1765
+ ink: '#1c2b20',
1766
+ muted: '#536257',
1767
+ line: '#b6c6b9',
1768
+ glow: '#15803d',
1769
+ },
1770
+ },
1771
+ {
1772
+ id: 'sky',
1665
1773
  scheme: 'light',
1666
1774
  starfield: false,
1667
1775
  accent: 'blue',
1668
1776
  tokens: {
1669
- bg: '#eef1f6',
1670
- raised: '#e2e7ef',
1671
- ink: '#141a24',
1672
- muted: '#576274',
1673
- line: '#d3dae5',
1674
- glow: '#1160b8',
1777
+ bg: '#cfe0f5',
1778
+ raised: '#e0ebf9',
1779
+ ink: '#14213a',
1780
+ muted: '#505e76',
1781
+ line: '#b1c1d7',
1782
+ glow: '#2563eb',
1783
+ },
1784
+ },
1785
+ {
1786
+ id: 'lavender',
1787
+ scheme: 'light',
1788
+ starfield: false,
1789
+ accent: 'violet',
1790
+ tokens: {
1791
+ bg: '#ddd6f3',
1792
+ raised: '#eae5f8',
1793
+ ink: '#221a3d',
1794
+ muted: '#5e5677',
1795
+ line: '#bfb8d6',
1796
+ glow: '#7c3aed',
1675
1797
  },
1676
1798
  },
1677
1799
  ];
@@ -1704,7 +1826,7 @@ const CANVASES = [
1704
1826
  tokens: {
1705
1827
  bg: '#d9dce3',
1706
1828
  surface: '#eef0f4',
1707
- surfaceAlt: '#c8ccd6',
1829
+ surfaceAlt: '#dfe3ea',
1708
1830
  text: '#16151d',
1709
1831
  textMuted: '#545a66',
1710
1832
  border: '#c0c6d1',
@@ -1770,15 +1892,20 @@ const CANVASES = [
1770
1892
  },
1771
1893
  ];
1772
1894
  const ACCENTS = [
1773
- { id: 'violet', light: '#5b4fd6', dark: '#9b8ef5' },
1774
- { id: 'blue', light: '#1160b8', dark: '#6fb2f2' },
1775
- { id: 'cyan', light: '#0d6f87', dark: '#4cc5e8' },
1776
- { id: 'green', light: '#157a3c', dark: '#5bd98a' },
1777
- { id: 'lime', light: '#4d7c0f', dark: '#a3d94b' },
1778
- { id: 'amber', light: '#8a5a00', dark: '#e0a33a' },
1779
- { id: 'orange', light: '#b2430c', dark: '#f2934f' },
1780
- { id: 'rose', light: '#b21b5c', dark: '#f07aab' },
1781
- { id: 'red', light: '#b02121', dark: '#f0797b' },
1895
+ { id: 'violet', light: '#7c3aed', dark: '#a78bfa' },
1896
+ { id: 'blue', light: '#2563eb', dark: '#60a5fa' },
1897
+ { id: 'cyan', light: '#0e7490', dark: '#22d3ee' },
1898
+ { id: 'green', light: '#15803d', dark: '#4ade80' },
1899
+ { id: 'lime', light: '#4d7c0f', dark: '#a3e635' },
1900
+ { id: 'amber', light: '#b45309', dark: '#fbbf24' },
1901
+ { id: 'orange', light: '#c2410c', dark: '#fb923c' },
1902
+ { id: 'rose', light: '#e11d48', dark: '#fb7185' },
1903
+ { id: 'red', light: '#dc2626', dark: '#f87171' },
1904
+ { id: 'indigo', light: '#4f46e5', dark: '#818cf8' },
1905
+ { id: 'teal', light: '#0f766e', dark: '#2dd4bf' },
1906
+ { id: 'plum', light: '#9333ea', dark: '#c084fc' },
1907
+ { id: 'slate', light: '#64748b', dark: '#94a3b8' },
1908
+ { id: 'graphite', light: '#71717a', dark: '#a1a1aa' },
1782
1909
  ];
1783
1910
  const DENSITIES = [
1784
1911
  { id: 'comfortable', scale: 1 },
@@ -1839,10 +1966,10 @@ function resolveAccent(frame, preference) {
1839
1966
  return accentById(preference === 'auto' ? frame.accent : preference);
1840
1967
  }
1841
1968
  function accentOn(accent, canvas) {
1842
- return canvas === 'light' ? accent.light : accent.dark;
1969
+ return isDarkCanvas(canvas) ? accent.dark : accent.light;
1843
1970
  }
1844
1971
  function isDarkCanvas(canvas) {
1845
- return canvas !== 'light';
1972
+ return canvas === 'dim' || canvas === 'dark';
1846
1973
  }
1847
1974
  function auditAppearance() {
1848
1975
  const issues = [];
@@ -1889,9 +2016,12 @@ const FRAMES_ES = {
1889
2016
  slate: 'Pizarra',
1890
2017
  ink: 'Tinta',
1891
2018
  graphite: 'Grafito',
1892
- studio: 'Estudio',
1893
2019
  paper: 'Papel',
1894
2020
  mist: 'Bruma',
2021
+ studio: 'Estudio',
2022
+ sage: 'Salvia',
2023
+ sky: 'Cielo',
2024
+ lavender: 'Lavanda',
1895
2025
  };
1896
2026
  const FRAMES_EN = {
1897
2027
  nucleus: 'Nucleus',
@@ -1904,9 +2034,12 @@ const FRAMES_EN = {
1904
2034
  slate: 'Slate',
1905
2035
  ink: 'Ink',
1906
2036
  graphite: 'Graphite',
1907
- studio: 'Studio',
1908
2037
  paper: 'Paper',
1909
2038
  mist: 'Mist',
2039
+ studio: 'Studio',
2040
+ sage: 'Sage',
2041
+ sky: 'Sky',
2042
+ lavender: 'Lavender',
1910
2043
  };
1911
2044
  const ACCENTS_ES = {
1912
2045
  auto: 'Del marco',
@@ -1919,6 +2052,11 @@ const ACCENTS_ES = {
1919
2052
  orange: 'Naranja',
1920
2053
  rose: 'Rosa',
1921
2054
  red: 'Rojo',
2055
+ slate: 'Pizarra',
2056
+ graphite: 'Grafito',
2057
+ indigo: 'Índigo',
2058
+ teal: 'Verde azulado',
2059
+ plum: 'Ciruela',
1922
2060
  };
1923
2061
  const ACCENTS_EN = {
1924
2062
  auto: 'From the frame',
@@ -1931,6 +2069,11 @@ const ACCENTS_EN = {
1931
2069
  orange: 'Orange',
1932
2070
  rose: 'Rose',
1933
2071
  red: 'Red',
2072
+ slate: 'Slate',
2073
+ graphite: 'Graphite',
2074
+ indigo: 'Indigo',
2075
+ teal: 'Teal',
2076
+ plum: 'Plum',
1934
2077
  };
1935
2078
  const THEME_COPY = {
1936
2079
  es: {
@@ -2083,6 +2226,9 @@ class ThemeService {
2083
2226
  root.style.setProperty(`--ns-frame-${kebab(name)}`, value);
2084
2227
  }
2085
2228
  root.style.setProperty('--ns-frame-on-glow', readableOn(frame.tokens.glow));
2229
+ const navActive = readableOn(frame.tokens.bg);
2230
+ root.style.setProperty('--ns-nav-active-bg', navActive);
2231
+ root.style.setProperty('--ns-nav-active-ink', readableOn(navActive));
2086
2232
  for (const [name, value] of Object.entries(canvas.tokens)) {
2087
2233
  root.style.setProperty(`--ac-${kebab(name)}`, value);
2088
2234
  }
@@ -2359,7 +2505,7 @@ class NucleusCard {
2359
2505
  <div class="actions">
2360
2506
  <ng-content select="[nucleusCardActions]" />
2361
2507
  </div>
2362
- `, isInline: true, styles: [":host{display:block;padding:22px 24px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}:host([data-size=\"sm\"]){max-width:34rem}:host([data-size=\"md\"]){max-width:48rem}:host([data-size=\"lg\"]){max-width:64rem}.head{margin-bottom:18px}h2{margin:0;font-size:16px;font-weight:600}.subtitle{margin:4px 0 0;color:var(--ac-text-muted);font-size:13px}.body{display:contents}.skeleton-rows{display:grid}.skeleton-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 0;border-bottom:1px solid color-mix(in srgb,var(--ac-border) 60%,transparent)}.skeleton-row:last-child{border-bottom:0}.actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.actions:empty{display:none}\n"], dependencies: [{ kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2508
+ `, isInline: true, styles: [":host{display:block;padding:22px 24px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}:host([data-size=\"sm\"]){max-width:34rem}:host([data-size=\"md\"]){max-width:48rem}:host([data-size=\"lg\"]){max-width:64rem}.head{margin-bottom:18px}h2{margin:0;font-size:16px;font-weight:var(--ns-weight-heading)}.subtitle{margin:4px 0 0;color:var(--ac-text-muted);font-size:13px}.body{display:contents}.skeleton-rows{display:grid}.skeleton-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 0;border-bottom:1px solid color-mix(in srgb,var(--ac-border) 60%,transparent)}.skeleton-row:last-child{border-bottom:0}.actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.actions:empty{display:none}\n"], dependencies: [{ kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2363
2509
  }
2364
2510
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusCard, decorators: [{
2365
2511
  type: Component,
@@ -2393,7 +2539,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
2393
2539
  <div class="actions">
2394
2540
  <ng-content select="[nucleusCardActions]" />
2395
2541
  </div>
2396
- `, styles: [":host{display:block;padding:22px 24px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}:host([data-size=\"sm\"]){max-width:34rem}:host([data-size=\"md\"]){max-width:48rem}:host([data-size=\"lg\"]){max-width:64rem}.head{margin-bottom:18px}h2{margin:0;font-size:16px;font-weight:600}.subtitle{margin:4px 0 0;color:var(--ac-text-muted);font-size:13px}.body{display:contents}.skeleton-rows{display:grid}.skeleton-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 0;border-bottom:1px solid color-mix(in srgb,var(--ac-border) 60%,transparent)}.skeleton-row:last-child{border-bottom:0}.actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.actions:empty{display:none}\n"] }]
2542
+ `, styles: [":host{display:block;padding:22px 24px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}:host([data-size=\"sm\"]){max-width:34rem}:host([data-size=\"md\"]){max-width:48rem}:host([data-size=\"lg\"]){max-width:64rem}.head{margin-bottom:18px}h2{margin:0;font-size:16px;font-weight:var(--ns-weight-heading)}.subtitle{margin:4px 0 0;color:var(--ac-text-muted);font-size:13px}.body{display:contents}.skeleton-rows{display:grid}.skeleton-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 0;border-bottom:1px solid color-mix(in srgb,var(--ac-border) 60%,transparent)}.skeleton-row:last-child{border-bottom:0}.actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.actions:empty{display:none}\n"] }]
2397
2543
  }], propDecorators: { heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], skeletonRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRows", required: false }] }] } });
2398
2544
 
2399
2545
  class NucleusMetrics {
@@ -2413,10 +2559,17 @@ class NucleusMetric {
2413
2559
  hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
2414
2560
  link = input('', ...(ngDevMode ? [{ debugName: "link" }] : /* istanbul ignore next */ []));
2415
2561
  tone = input('plain', ...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
2562
+ progress = input(null, ...(ngDevMode ? [{ debugName: "progress" }] : /* istanbul ignore next */ []));
2563
+ bar = computed(() => {
2564
+ const value = this.progress();
2565
+ if (value === null || !Number.isFinite(value))
2566
+ return null;
2567
+ return Math.min(Math.max(value, 0), 100);
2568
+ }, ...(ngDevMode ? [{ debugName: "bar" }] : /* istanbul ignore next */ []));
2416
2569
  loading = input(null, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
2417
2570
  busy = computed(() => this.loading() ?? this.group?.loading() ?? false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
2418
2571
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusMetric, deps: [], target: i0.ɵɵFactoryTarget.Component });
2419
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusMetric, isStandalone: true, selector: "nucleus-metric", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-tone": "tone() === 'accent' ? 'accent' : null" } }, ngImport: i0, template: `
2572
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusMetric, isStandalone: true, selector: "nucleus-metric", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, progress: { classPropertyName: "progress", publicName: "progress", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-tone": "tone() === 'accent' ? 'accent' : null" } }, ngImport: i0, template: `
2420
2573
  @if (link().length) {
2421
2574
  <a class="tile" [routerLink]="link()">
2422
2575
  <ng-container [ngTemplateOutlet]="body" />
@@ -2437,12 +2590,15 @@ class NucleusMetric {
2437
2590
  }
2438
2591
  } @else {
2439
2592
  <strong class="value">{{ value() }}</strong>
2593
+ @if (bar() !== null) {
2594
+ <span class="track"><span class="fill" [style.width.%]="bar()"></span></span>
2595
+ }
2440
2596
  @if (hint().length) {
2441
2597
  <small class="hint">{{ hint() }}</small>
2442
2598
  }
2443
2599
  }
2444
2600
  </ng-template>
2445
- `, isInline: true, styles: [":host{display:block}.tile{display:grid;align-content:start;gap:5px;height:100%;padding:18px 20px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);color:inherit;text-decoration:none;transition:border-color .14s ease}a.tile:hover{border-color:var(--ac-accent)}:host([data-tone=\"accent\"]) .tile{border-color:var(--ac-accent)}.label{color:var(--ac-text-muted);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.value{font-size:26px;font-variant-numeric:tabular-nums;line-height:1}.hint{color:var(--ac-text-muted);font-size:12px}.value-skeleton{margin:1px 0 2px}.hint-skeleton{margin:3px 0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2601
+ `, isInline: true, styles: [":host{display:block}.track{overflow:hidden;height:4px;margin-top:3px;border-radius:999px;background:color-mix(in srgb,var(--ac-text) 12%,transparent)}.fill{display:block;height:4px;border-radius:999px;background:var(--ac-accent)}.tile{display:grid;align-content:start;gap:5px;height:100%;padding:18px 20px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);color:inherit;text-decoration:none;transition:border-color .14s ease}a.tile:hover{border-color:var(--ac-accent)}:host([data-tone=\"accent\"]) .tile{border-color:var(--ac-accent)}.label{color:var(--ac-text-muted);font-size:11px;font-weight:var(--ns-weight-heading);letter-spacing:.04em;text-transform:uppercase}.value{font-size:26px;font-variant-numeric:tabular-nums;line-height:1}.hint{color:var(--ac-text-muted);font-size:12px}.value-skeleton{margin:1px 0 2px}.hint-skeleton{margin:3px 0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2446
2602
  }
2447
2603
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusMetric, decorators: [{
2448
2604
  type: Component,
@@ -2467,13 +2623,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
2467
2623
  }
2468
2624
  } @else {
2469
2625
  <strong class="value">{{ value() }}</strong>
2626
+ @if (bar() !== null) {
2627
+ <span class="track"><span class="fill" [style.width.%]="bar()"></span></span>
2628
+ }
2470
2629
  @if (hint().length) {
2471
2630
  <small class="hint">{{ hint() }}</small>
2472
2631
  }
2473
2632
  }
2474
2633
  </ng-template>
2475
- `, styles: [":host{display:block}.tile{display:grid;align-content:start;gap:5px;height:100%;padding:18px 20px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);color:inherit;text-decoration:none;transition:border-color .14s ease}a.tile:hover{border-color:var(--ac-accent)}:host([data-tone=\"accent\"]) .tile{border-color:var(--ac-accent)}.label{color:var(--ac-text-muted);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.value{font-size:26px;font-variant-numeric:tabular-nums;line-height:1}.hint{color:var(--ac-text-muted);font-size:12px}.value-skeleton{margin:1px 0 2px}.hint-skeleton{margin:3px 0}\n"] }]
2476
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], link: [{ type: i0.Input, args: [{ isSignal: true, alias: "link", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
2634
+ `, styles: [":host{display:block}.track{overflow:hidden;height:4px;margin-top:3px;border-radius:999px;background:color-mix(in srgb,var(--ac-text) 12%,transparent)}.fill{display:block;height:4px;border-radius:999px;background:var(--ac-accent)}.tile{display:grid;align-content:start;gap:5px;height:100%;padding:18px 20px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);color:inherit;text-decoration:none;transition:border-color .14s ease}a.tile:hover{border-color:var(--ac-accent)}:host([data-tone=\"accent\"]) .tile{border-color:var(--ac-accent)}.label{color:var(--ac-text-muted);font-size:11px;font-weight:var(--ns-weight-heading);letter-spacing:.04em;text-transform:uppercase}.value{font-size:26px;font-variant-numeric:tabular-nums;line-height:1}.hint{color:var(--ac-text-muted);font-size:12px}.value-skeleton{margin:1px 0 2px}.hint-skeleton{margin:3px 0}\n"] }]
2635
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], link: [{ type: i0.Input, args: [{ isSignal: true, alias: "link", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
2477
2636
 
2478
2637
  class NucleusTabs {
2479
2638
  tabs = input.required(...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
@@ -2500,7 +2659,7 @@ class NucleusTabs {
2500
2659
  </button>
2501
2660
  }
2502
2661
  </div>
2503
- `, isInline: true, styles: [":host{display:block;margin-bottom:12px}.bar{display:flex;overflow-x:auto;justify-content:flex-start;gap:4px;border-bottom:1px solid var(--ac-border);scrollbar-width:none}.bar::-webkit-scrollbar{display:none}.tab{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;background:transparent;color:var(--ac-text-muted);font:inherit;font-size:13px;font-weight:500;white-space:nowrap;cursor:pointer;transition:color .12s ease,border-color .12s ease}.tab:hover{color:var(--ac-text)}.tab.is-active{border-bottom-color:var(--ac-accent);color:var(--ac-text)}.tab i{font-size:13px}.badge{padding:1px 7px;border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 12%,transparent);font-size:11px}.tab.is-active .badge{background:color-mix(in srgb,var(--ac-accent) 26%,transparent)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2662
+ `, isInline: true, styles: [":host{display:block;margin-bottom:12px}.bar{display:flex;overflow-x:auto;justify-content:flex-start;gap:4px;padding:5px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1);scrollbar-width:none}.bar::-webkit-scrollbar{display:none}.tab{display:inline-flex;flex:none;align-items:center;gap:8px;padding:8px 14px;border:0;border-radius:8px;background:transparent;color:var(--ac-text-muted);font:inherit;font-size:13px;font-weight:var(--ns-weight-emphasis);white-space:nowrap;cursor:pointer;transition:background .12s ease,color .12s ease}.tab:hover{background:var(--ac-surface-alt);color:var(--ac-text)}.tab:focus-visible{outline:2px solid var(--ac-accent);outline-offset:1px}.tab.is-active{background:var(--ac-text);color:var(--ac-surface)}.tab i{font-size:13px}.badge{padding:1px 7px;border-radius:var(--ac-radius-pill);background:color-mix(in srgb,currentColor 14%,transparent);font-size:11px;font-variant-numeric:tabular-nums}.tab.is-active .badge{background:color-mix(in srgb,currentColor 22%,transparent)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2504
2663
  }
2505
2664
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusTabs, decorators: [{
2506
2665
  type: Component,
@@ -2525,7 +2684,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
2525
2684
  </button>
2526
2685
  }
2527
2686
  </div>
2528
- `, styles: [":host{display:block;margin-bottom:12px}.bar{display:flex;overflow-x:auto;justify-content:flex-start;gap:4px;border-bottom:1px solid var(--ac-border);scrollbar-width:none}.bar::-webkit-scrollbar{display:none}.tab{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;background:transparent;color:var(--ac-text-muted);font:inherit;font-size:13px;font-weight:500;white-space:nowrap;cursor:pointer;transition:color .12s ease,border-color .12s ease}.tab:hover{color:var(--ac-text)}.tab.is-active{border-bottom-color:var(--ac-accent);color:var(--ac-text)}.tab i{font-size:13px}.badge{padding:1px 7px;border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 12%,transparent);font-size:11px}.tab.is-active .badge{background:color-mix(in srgb,var(--ac-accent) 26%,transparent)}\n"] }]
2687
+ `, styles: [":host{display:block;margin-bottom:12px}.bar{display:flex;overflow-x:auto;justify-content:flex-start;gap:4px;padding:5px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1);scrollbar-width:none}.bar::-webkit-scrollbar{display:none}.tab{display:inline-flex;flex:none;align-items:center;gap:8px;padding:8px 14px;border:0;border-radius:8px;background:transparent;color:var(--ac-text-muted);font:inherit;font-size:13px;font-weight:var(--ns-weight-emphasis);white-space:nowrap;cursor:pointer;transition:background .12s ease,color .12s ease}.tab:hover{background:var(--ac-surface-alt);color:var(--ac-text)}.tab:focus-visible{outline:2px solid var(--ac-accent);outline-offset:1px}.tab.is-active{background:var(--ac-text);color:var(--ac-surface)}.tab i{font-size:13px}.badge{padding:1px 7px;border-radius:var(--ac-radius-pill);background:color-mix(in srgb,currentColor 14%,transparent);font-size:11px;font-variant-numeric:tabular-nums}.tab.is-active .badge{background:color-mix(in srgb,currentColor 22%,transparent)}\n"] }]
2529
2688
  }], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: true }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: true }] }, { type: i0.Output, args: ["activeChange"] }] } });
2530
2689
 
2531
2690
  class NucleusPage {
@@ -3249,7 +3408,7 @@ class NucleusList {
3249
3408
  this.toggle.emit({ key: column.key, row, value: !this.isChecked(column, row) });
3250
3409
  }
3251
3410
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusList, deps: [], target: i0.ɵɵFactoryTarget.Component });
3252
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusList, isStandalone: true, selector: "nucleus-list", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, skeletonRows: { classPropertyName: "skeletonRows", publicName: "skeletonRows", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, reorderGroup: { classPropertyName: "reorderGroup", publicName: "reorderGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action", reorder: "reorder", dragStart: "dragStart", toggle: "toggle" }, queries: [{ propertyName: "cells", predicate: NucleusCell, isSignal: true }], ngImport: i0, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <div class=\"bar\">\n @if (searchable()) {\n <label class=\"search\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n type=\"search\"\n [value]=\"term()\"\n [placeholder]=\"copy().search\"\n [attr.aria-label]=\"copy().search\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <span class=\"bar-spacer\"></span>\n\n @if (canChooseView()) {\n <span class=\"views\">\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'grid'\"\n [attr.aria-pressed]=\"view() === 'grid'\"\n [attr.aria-label]=\"copy().viewGrid\"\n [pTooltip]=\"copy().viewGrid\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('grid')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'rows'\"\n [attr.aria-pressed]=\"view() === 'rows'\"\n [attr.aria-label]=\"copy().viewRows\"\n [pTooltip]=\"copy().viewRows\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('rows')\"\n >\n <i class=\"pi pi-list\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n\n @if (compact()) {\n @if (showNoResults()) {\n <div class=\"placeholder\">{{ copy().noResults }}</div>\n }\n\n <div\n class=\"cards\"\n [class.is-rows]=\"view() === 'rows'\"\n cdkDropList\n cdkDropListOrientation=\"mixed\"\n [cdkDropListDisabled]=\"dragLocked()\"\n [cdkDropListSortPredicate]=\"sortAllowed\"\n (cdkDropListDropped)=\"onCardDrop($event)\"\n >\n @if (loading()) {\n @for (item of placeholders(); track $index) {\n <div class=\"card\">\n <div class=\"card-top\">\n <p-skeleton height=\"15px\" width=\"52%\" />\n </div>\n <div class=\"card-foot\">\n <p-skeleton height=\"12px\" width=\"30%\" />\n <p-skeleton height=\"12px\" width=\"30%\" />\n </div>\n </div>\n }\n } @else {\n @for (row of pagedRows(); track $index) {\n <article class=\"card\" [class]=\"rowClass()(row)\" cdkDrag\n [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragLocked()\"\n (cdkDragStarted)=\"dragStart.emit(row)\">\n <div class=\"card-top\">\n @if (reorderable()) {\n <button\n type=\"button\"\n class=\"grip\"\n cdkDragHandle\n [disabled]=\"dragLocked()\"\n [attr.aria-label]=\"copy().reorderHandle\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (identityColumn(); as column) {\n <span class=\"card-name\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n\n @if (statusColumn(); as column) {\n <span class=\"card-status\">\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n </div>\n\n @if (attributeColumns().length || visibleActions(row).length) {\n <div class=\"card-foot\">\n <div class=\"card-fields\">\n @for (column of attributeColumns(); track column.key) {\n <div class=\"field\">\n <span class=\"field-label\">{{ column.header }}</span>\n <span class=\"field-value\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (linkOf(column, row); as target) {\n <nucleus-link\n [route]=\"target.route\"\n [queryParams]=\"target.queryParams ?? null\"\n [hint]=\"column.header\"\n >\n {{ text(column, row) }}\n </nucleus-link>\n } @else if (column.kind === 'switch') {\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"column.header\"\n [disabled]=\"isLocked(column, row)\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </span>\n </div>\n }\n </div>\n\n @if (visibleActions(row).length) {\n <div class=\"card-actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </div>\n }\n </div>\n }\n </article>\n }\n }\n </div>\n\n @if (paginate()) {\n <div class=\"foot\">\n <p-paginator\n styleClass=\"ns-cards-paginator\"\n [first]=\"page()\"\n [rows]=\"rowsPerPage()\"\n [totalRecords]=\"filtered().length\"\n [rowsPerPageOptions]=\"pageSizes()\"\n (onPageChange)=\"onPage($event)\"\n />\n </div>\n }\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n (onRowReorder)=\"onRowReorder($event)\"\n >\n <ng-template #header>\n <tr>\n @if (reorderable()) {\n <th class=\"grip-head\"></th>\n }\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row let-rowIndex=\"rowIndex\">\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @if (reorderable()) {\n <td class=\"grip-cell\"></td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr\n [class]=\"rowClass()(row)\"\n [pReorderableRow]=\"rowIndex\"\n [pReorderableRowDisabled]=\"dragLocked()\"\n >\n @if (reorderable()) {\n <td class=\"grip-cell\">\n <span class=\"grip\" pReorderableRowHandle [attr.aria-label]=\"copy().reorderHandle\">\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </span>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:600}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.cards{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.card{padding:13px 14px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.card-name{display:flex;min-width:0;flex:1;align-items:center;gap:10px;font-size:15px;font-weight:600;line-height:1.3}.card-status{flex:none}.card-foot{display:flex;align-items:flex-end;gap:12px;margin-top:11px;padding-top:11px;border-top:1px solid var(--ac-border)}.card-fields{display:flex;min-width:0;flex:1;flex-wrap:wrap;gap:10px 20px}.card-actions{display:flex;flex:none;align-items:center;gap:2px}.field{display:flex;min-width:0;flex-direction:column;gap:2px}.field-label{color:var(--ac-text-muted);font-size:10px;font-weight:600;letter-spacing:.07em;text-transform:uppercase}.field-value{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}::ng-deep .ns-cards-paginator{background:transparent}.grip{display:inline-grid;width:26px;height:26px;flex:none;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ac-text-muted);cursor:grab;place-items:center;touch-action:none}.grip:hover{background:color-mix(in srgb,var(--ac-text) 8%,transparent);color:var(--ac-text)}.grip:active{cursor:grabbing}.grip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.grip .pi{font-size:13px}.grip-head,.grip-cell{width:38px;padding-right:0!important}.cdk-drag-preview{border:1px solid var(--ac-accent);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-2);opacity:.96}.cdk-drag-placeholder{border:1px dashed var(--ac-border);background:color-mix(in srgb,var(--ac-text) 4%,transparent);opacity:.6}.cdk-drag-placeholder *{visibility:hidden}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .18s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .22s cubic-bezier(0,0,.2,1)}.bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:7px 10px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.bar-spacer{flex:1}.search{display:flex;min-width:0;max-width:340px;flex:1 1 220px;align-items:center;gap:8px;padding:5px 10px;border:1px solid var(--ac-border);border-radius:6px;background:color-mix(in srgb,var(--ac-text) 4%,transparent);color:var(--ac-text-muted)}.search:focus-within{border-color:var(--ac-accent);color:var(--ac-text)}.search .pi{font-size:13px}.search input{min-width:0;flex:1;padding:0;border:0;background:transparent;color:var(--ac-text);font:inherit;font-size:13px;outline:none}.search input::-webkit-search-cancel-button{filter:grayscale(1) opacity(.6)}.views{display:inline-flex;flex:none;padding:2px;border:1px solid var(--ac-border);border-radius:7px}.view{display:grid;width:30px;height:28px;padding:0;border:0;border-radius:5px;background:transparent;color:var(--ac-text-muted);cursor:pointer;place-items:center}.view:hover{color:var(--ac-text)}.view.is-on{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-accent)}.view:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.view .pi{font-size:14px}.foot{margin-top:12px;padding:4px 6px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}@media(min-width:721px){.cards.is-rows{gap:8px;grid-template-columns:minmax(0,1fr)}.cards.is-rows .card{display:grid;align-items:center;gap:18px;grid-template-columns:minmax(0,2fr) minmax(0,3fr);padding:9px 14px}.cards.is-rows .card-top{min-width:0;align-items:center;gap:12px}.cards.is-rows .card-foot{margin-top:0;padding-top:0;border-top:0;gap:14px}.cards.is-rows .card-fields{display:grid;min-width:0;flex:1;gap:14px;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column}.cards.is-rows .field-label,.cards.is-rows .field-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NucleusLink, selector: "nucleus-link", inputs: ["route", "queryParams", "href", "hint", "muted"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i2$3.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i4.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i4.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3411
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusList, isStandalone: true, selector: "nucleus-list", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, skeletonRows: { classPropertyName: "skeletonRows", publicName: "skeletonRows", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null }, cards: { classPropertyName: "cards", publicName: "cards", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, reorderGroup: { classPropertyName: "reorderGroup", publicName: "reorderGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action", reorder: "reorder", dragStart: "dragStart", toggle: "toggle" }, queries: [{ propertyName: "cells", predicate: NucleusCell, isSignal: true }], ngImport: i0, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <div class=\"bar\">\n @if (searchable()) {\n <label class=\"search\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n type=\"search\"\n [value]=\"term()\"\n [placeholder]=\"copy().search\"\n [attr.aria-label]=\"copy().search\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <span class=\"bar-spacer\"></span>\n\n @if (canChooseView()) {\n <span class=\"views\">\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'grid'\"\n [attr.aria-pressed]=\"view() === 'grid'\"\n [attr.aria-label]=\"copy().viewGrid\"\n [pTooltip]=\"copy().viewGrid\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('grid')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'rows'\"\n [attr.aria-pressed]=\"view() === 'rows'\"\n [attr.aria-label]=\"copy().viewRows\"\n [pTooltip]=\"copy().viewRows\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('rows')\"\n >\n <i class=\"pi pi-list\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n\n @if (compact()) {\n @if (showNoResults()) {\n <div class=\"placeholder\">{{ copy().noResults }}</div>\n }\n\n <div\n class=\"cards\"\n [class.is-rows]=\"view() === 'rows'\"\n cdkDropList\n cdkDropListOrientation=\"mixed\"\n [cdkDropListDisabled]=\"dragLocked()\"\n [cdkDropListSortPredicate]=\"sortAllowed\"\n (cdkDropListDropped)=\"onCardDrop($event)\"\n >\n @if (loading()) {\n @for (item of placeholders(); track $index) {\n <div class=\"card\">\n <div class=\"card-top\">\n <p-skeleton height=\"15px\" width=\"52%\" />\n </div>\n <div class=\"card-foot\">\n <p-skeleton height=\"12px\" width=\"30%\" />\n <p-skeleton height=\"12px\" width=\"30%\" />\n </div>\n </div>\n }\n } @else {\n @for (row of pagedRows(); track $index) {\n <article class=\"card\" [class]=\"rowClass()(row)\" cdkDrag\n [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragLocked()\"\n (cdkDragStarted)=\"dragStart.emit(row)\">\n <div class=\"card-top\">\n @if (reorderable()) {\n <button\n type=\"button\"\n class=\"grip\"\n cdkDragHandle\n [disabled]=\"dragLocked()\"\n [attr.aria-label]=\"copy().reorderHandle\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (identityColumn(); as column) {\n <span class=\"card-name\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n\n @if (statusColumn(); as column) {\n <span class=\"card-status\">\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n </div>\n\n @if (attributeColumns().length || visibleActions(row).length) {\n <div class=\"card-foot\">\n <div class=\"card-fields\">\n @for (column of attributeColumns(); track column.key) {\n <div class=\"field\">\n <span class=\"field-label\">{{ column.header }}</span>\n <span class=\"field-value\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (linkOf(column, row); as target) {\n <nucleus-link\n [route]=\"target.route\"\n [queryParams]=\"target.queryParams ?? null\"\n [hint]=\"column.header\"\n >\n {{ text(column, row) }}\n </nucleus-link>\n } @else if (column.kind === 'switch') {\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"column.header\"\n [disabled]=\"isLocked(column, row)\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else {\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n }\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </span>\n </div>\n }\n </div>\n\n @if (visibleActions(row).length) {\n <div class=\"card-actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </div>\n }\n </div>\n }\n </article>\n }\n }\n </div>\n\n @if (paginate()) {\n <div class=\"foot\">\n <p-paginator\n styleClass=\"ns-cards-paginator\"\n [first]=\"page()\"\n [rows]=\"rowsPerPage()\"\n [totalRecords]=\"filtered().length\"\n [rowsPerPageOptions]=\"pageSizes()\"\n (onPageChange)=\"onPage($event)\"\n />\n </div>\n }\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n (onRowReorder)=\"onRowReorder($event)\"\n >\n <ng-template #header>\n <tr>\n @if (reorderable()) {\n <th class=\"grip-head\"></th>\n }\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row let-rowIndex=\"rowIndex\">\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @if (reorderable()) {\n <td class=\"grip-cell\"></td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr\n [class]=\"rowClass()(row)\"\n [pReorderableRow]=\"rowIndex\"\n [pReorderableRowDisabled]=\"dragLocked()\"\n >\n @if (reorderable()) {\n <td class=\"grip-cell\">\n <span class=\"grip\" pReorderableRowHandle [attr.aria-label]=\"copy().reorderHandle\">\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </span>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:var(--ns-weight-emphasis)}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.cards{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.card{padding:13px 14px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.card-name{display:flex;min-width:0;flex:1;align-items:center;gap:10px;font-size:15px;font-weight:var(--ns-weight-emphasis);line-height:1.3}.card-status{flex:none}.card-foot{display:flex;align-items:flex-end;gap:12px;margin-top:11px;padding-top:11px;border-top:1px solid var(--ac-border)}.card-fields{display:flex;min-width:0;flex:1;flex-wrap:wrap;gap:10px 20px}.card-actions{display:flex;flex:none;align-items:center;gap:2px}.field{display:flex;min-width:0;flex-direction:column;gap:2px}.field-label{color:var(--ac-text-muted);font-size:10px;font-weight:var(--ns-weight-heading);letter-spacing:.07em;text-transform:uppercase}.field-value{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:var(--ns-weight-emphasis);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}::ng-deep .ns-cards-paginator{background:transparent}.grip{display:inline-grid;width:26px;height:26px;flex:none;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ac-text-muted);cursor:grab;place-items:center;touch-action:none}.grip:hover{background:color-mix(in srgb,var(--ac-text) 8%,transparent);color:var(--ac-text)}.grip:active{cursor:grabbing}.grip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.grip .pi{font-size:13px}.grip-head,.grip-cell{width:38px;padding-right:0!important}.cdk-drag-preview{border:1px solid var(--ac-accent);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-2);opacity:.96}.cdk-drag-placeholder{border:1px dashed var(--ac-border);background:color-mix(in srgb,var(--ac-text) 4%,transparent);opacity:.6}.cdk-drag-placeholder *{visibility:hidden}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .18s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .22s cubic-bezier(0,0,.2,1)}.bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:7px 10px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.bar-spacer{flex:1}.search{display:flex;min-width:0;max-width:340px;flex:1 1 220px;align-items:center;gap:8px;padding:5px 10px;border:1px solid var(--ac-border);border-radius:6px;background:color-mix(in srgb,var(--ac-text) 4%,transparent);color:var(--ac-text-muted)}.search:focus-within{border-color:var(--ac-accent);color:var(--ac-text)}.search .pi{font-size:13px}.search input{min-width:0;flex:1;padding:0;border:0;background:transparent;color:var(--ac-text);font:inherit;font-size:13px;outline:none}.search input::-webkit-search-cancel-button{filter:grayscale(1) opacity(.6)}.views{display:inline-flex;flex:none;padding:2px;border:1px solid var(--ac-border);border-radius:7px}.view{display:grid;width:30px;height:28px;padding:0;border:0;border-radius:5px;background:transparent;color:var(--ac-text-muted);cursor:pointer;place-items:center}.view:hover{color:var(--ac-text)}.view.is-on{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-accent)}.view:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.view .pi{font-size:14px}.foot{margin-top:12px;padding:4px 6px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}@media(min-width:721px){.cards.is-rows{gap:8px;grid-template-columns:minmax(0,1fr)}.cards.is-rows .card{display:grid;align-items:center;gap:18px;grid-template-columns:minmax(0,2fr) minmax(0,3fr);padding:9px 14px}.cards.is-rows .card-top{min-width:0;align-items:center;gap:12px}.cards.is-rows .card-foot{margin-top:0;padding-top:0;border-top:0;gap:14px}.cards.is-rows .card-fields{display:grid;min-width:0;flex:1;gap:14px;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column}.cards.is-rows .field-label,.cards.is-rows .field-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NucleusLink, selector: "nucleus-link", inputs: ["route", "queryParams", "href", "hint", "muted"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i2$3.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i4.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i4.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3253
3412
  }
3254
3413
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusList, decorators: [{
3255
3414
  type: Component,
@@ -3265,7 +3424,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
3265
3424
  TableModule,
3266
3425
  TagModule,
3267
3426
  TooltipModule,
3268
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <div class=\"bar\">\n @if (searchable()) {\n <label class=\"search\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n type=\"search\"\n [value]=\"term()\"\n [placeholder]=\"copy().search\"\n [attr.aria-label]=\"copy().search\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <span class=\"bar-spacer\"></span>\n\n @if (canChooseView()) {\n <span class=\"views\">\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'grid'\"\n [attr.aria-pressed]=\"view() === 'grid'\"\n [attr.aria-label]=\"copy().viewGrid\"\n [pTooltip]=\"copy().viewGrid\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('grid')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'rows'\"\n [attr.aria-pressed]=\"view() === 'rows'\"\n [attr.aria-label]=\"copy().viewRows\"\n [pTooltip]=\"copy().viewRows\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('rows')\"\n >\n <i class=\"pi pi-list\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n\n @if (compact()) {\n @if (showNoResults()) {\n <div class=\"placeholder\">{{ copy().noResults }}</div>\n }\n\n <div\n class=\"cards\"\n [class.is-rows]=\"view() === 'rows'\"\n cdkDropList\n cdkDropListOrientation=\"mixed\"\n [cdkDropListDisabled]=\"dragLocked()\"\n [cdkDropListSortPredicate]=\"sortAllowed\"\n (cdkDropListDropped)=\"onCardDrop($event)\"\n >\n @if (loading()) {\n @for (item of placeholders(); track $index) {\n <div class=\"card\">\n <div class=\"card-top\">\n <p-skeleton height=\"15px\" width=\"52%\" />\n </div>\n <div class=\"card-foot\">\n <p-skeleton height=\"12px\" width=\"30%\" />\n <p-skeleton height=\"12px\" width=\"30%\" />\n </div>\n </div>\n }\n } @else {\n @for (row of pagedRows(); track $index) {\n <article class=\"card\" [class]=\"rowClass()(row)\" cdkDrag\n [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragLocked()\"\n (cdkDragStarted)=\"dragStart.emit(row)\">\n <div class=\"card-top\">\n @if (reorderable()) {\n <button\n type=\"button\"\n class=\"grip\"\n cdkDragHandle\n [disabled]=\"dragLocked()\"\n [attr.aria-label]=\"copy().reorderHandle\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (identityColumn(); as column) {\n <span class=\"card-name\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n\n @if (statusColumn(); as column) {\n <span class=\"card-status\">\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n </div>\n\n @if (attributeColumns().length || visibleActions(row).length) {\n <div class=\"card-foot\">\n <div class=\"card-fields\">\n @for (column of attributeColumns(); track column.key) {\n <div class=\"field\">\n <span class=\"field-label\">{{ column.header }}</span>\n <span class=\"field-value\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (linkOf(column, row); as target) {\n <nucleus-link\n [route]=\"target.route\"\n [queryParams]=\"target.queryParams ?? null\"\n [hint]=\"column.header\"\n >\n {{ text(column, row) }}\n </nucleus-link>\n } @else if (column.kind === 'switch') {\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"column.header\"\n [disabled]=\"isLocked(column, row)\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </span>\n </div>\n }\n </div>\n\n @if (visibleActions(row).length) {\n <div class=\"card-actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </div>\n }\n </div>\n }\n </article>\n }\n }\n </div>\n\n @if (paginate()) {\n <div class=\"foot\">\n <p-paginator\n styleClass=\"ns-cards-paginator\"\n [first]=\"page()\"\n [rows]=\"rowsPerPage()\"\n [totalRecords]=\"filtered().length\"\n [rowsPerPageOptions]=\"pageSizes()\"\n (onPageChange)=\"onPage($event)\"\n />\n </div>\n }\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n (onRowReorder)=\"onRowReorder($event)\"\n >\n <ng-template #header>\n <tr>\n @if (reorderable()) {\n <th class=\"grip-head\"></th>\n }\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row let-rowIndex=\"rowIndex\">\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @if (reorderable()) {\n <td class=\"grip-cell\"></td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr\n [class]=\"rowClass()(row)\"\n [pReorderableRow]=\"rowIndex\"\n [pReorderableRowDisabled]=\"dragLocked()\"\n >\n @if (reorderable()) {\n <td class=\"grip-cell\">\n <span class=\"grip\" pReorderableRowHandle [attr.aria-label]=\"copy().reorderHandle\">\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </span>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:600}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.cards{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.card{padding:13px 14px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.card-name{display:flex;min-width:0;flex:1;align-items:center;gap:10px;font-size:15px;font-weight:600;line-height:1.3}.card-status{flex:none}.card-foot{display:flex;align-items:flex-end;gap:12px;margin-top:11px;padding-top:11px;border-top:1px solid var(--ac-border)}.card-fields{display:flex;min-width:0;flex:1;flex-wrap:wrap;gap:10px 20px}.card-actions{display:flex;flex:none;align-items:center;gap:2px}.field{display:flex;min-width:0;flex-direction:column;gap:2px}.field-label{color:var(--ac-text-muted);font-size:10px;font-weight:600;letter-spacing:.07em;text-transform:uppercase}.field-value{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}::ng-deep .ns-cards-paginator{background:transparent}.grip{display:inline-grid;width:26px;height:26px;flex:none;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ac-text-muted);cursor:grab;place-items:center;touch-action:none}.grip:hover{background:color-mix(in srgb,var(--ac-text) 8%,transparent);color:var(--ac-text)}.grip:active{cursor:grabbing}.grip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.grip .pi{font-size:13px}.grip-head,.grip-cell{width:38px;padding-right:0!important}.cdk-drag-preview{border:1px solid var(--ac-accent);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-2);opacity:.96}.cdk-drag-placeholder{border:1px dashed var(--ac-border);background:color-mix(in srgb,var(--ac-text) 4%,transparent);opacity:.6}.cdk-drag-placeholder *{visibility:hidden}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .18s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .22s cubic-bezier(0,0,.2,1)}.bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:7px 10px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.bar-spacer{flex:1}.search{display:flex;min-width:0;max-width:340px;flex:1 1 220px;align-items:center;gap:8px;padding:5px 10px;border:1px solid var(--ac-border);border-radius:6px;background:color-mix(in srgb,var(--ac-text) 4%,transparent);color:var(--ac-text-muted)}.search:focus-within{border-color:var(--ac-accent);color:var(--ac-text)}.search .pi{font-size:13px}.search input{min-width:0;flex:1;padding:0;border:0;background:transparent;color:var(--ac-text);font:inherit;font-size:13px;outline:none}.search input::-webkit-search-cancel-button{filter:grayscale(1) opacity(.6)}.views{display:inline-flex;flex:none;padding:2px;border:1px solid var(--ac-border);border-radius:7px}.view{display:grid;width:30px;height:28px;padding:0;border:0;border-radius:5px;background:transparent;color:var(--ac-text-muted);cursor:pointer;place-items:center}.view:hover{color:var(--ac-text)}.view.is-on{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-accent)}.view:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.view .pi{font-size:14px}.foot{margin-top:12px;padding:4px 6px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}@media(min-width:721px){.cards.is-rows{gap:8px;grid-template-columns:minmax(0,1fr)}.cards.is-rows .card{display:grid;align-items:center;gap:18px;grid-template-columns:minmax(0,2fr) minmax(0,3fr);padding:9px 14px}.cards.is-rows .card-top{min-width:0;align-items:center;gap:12px}.cards.is-rows .card-foot{margin-top:0;padding-top:0;border-top:0;gap:14px}.cards.is-rows .card-fields{display:grid;min-width:0;flex:1;gap:14px;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column}.cards.is-rows .field-label,.cards.is-rows .field-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"] }]
3427
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <ng-content select=\"[nucleusListTitle]\" />\n <div class=\"head-actions\">\n <ng-content select=\"[nucleusListActions]\" />\n </div>\n</div>\n\n@if (showEmpty()) {\n <div class=\"placeholder\">{{ empty() }}</div>\n} @else {\n <div class=\"bar\">\n @if (searchable()) {\n <label class=\"search\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n type=\"search\"\n [value]=\"term()\"\n [placeholder]=\"copy().search\"\n [attr.aria-label]=\"copy().search\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <span class=\"bar-spacer\"></span>\n\n @if (canChooseView()) {\n <span class=\"views\">\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'grid'\"\n [attr.aria-pressed]=\"view() === 'grid'\"\n [attr.aria-label]=\"copy().viewGrid\"\n [pTooltip]=\"copy().viewGrid\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('grid')\"\n >\n <i class=\"pi pi-th-large\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"view\"\n [class.is-on]=\"view() === 'rows'\"\n [attr.aria-pressed]=\"view() === 'rows'\"\n [attr.aria-label]=\"copy().viewRows\"\n [pTooltip]=\"copy().viewRows\"\n tooltipPosition=\"bottom\"\n (click)=\"chooseView('rows')\"\n >\n <i class=\"pi pi-list\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n\n @if (compact()) {\n @if (showNoResults()) {\n <div class=\"placeholder\">{{ copy().noResults }}</div>\n }\n\n <div\n class=\"cards\"\n [class.is-rows]=\"view() === 'rows'\"\n cdkDropList\n cdkDropListOrientation=\"mixed\"\n [cdkDropListDisabled]=\"dragLocked()\"\n [cdkDropListSortPredicate]=\"sortAllowed\"\n (cdkDropListDropped)=\"onCardDrop($event)\"\n >\n @if (loading()) {\n @for (item of placeholders(); track $index) {\n <div class=\"card\">\n <div class=\"card-top\">\n <p-skeleton height=\"15px\" width=\"52%\" />\n </div>\n <div class=\"card-foot\">\n <p-skeleton height=\"12px\" width=\"30%\" />\n <p-skeleton height=\"12px\" width=\"30%\" />\n </div>\n </div>\n }\n } @else {\n @for (row of pagedRows(); track $index) {\n <article class=\"card\" [class]=\"rowClass()(row)\" cdkDrag\n [cdkDragData]=\"row\"\n [cdkDragDisabled]=\"dragLocked()\"\n (cdkDragStarted)=\"dragStart.emit(row)\">\n <div class=\"card-top\">\n @if (reorderable()) {\n <button\n type=\"button\"\n class=\"grip\"\n cdkDragHandle\n [disabled]=\"dragLocked()\"\n [attr.aria-label]=\"copy().reorderHandle\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (identityColumn(); as column) {\n <span class=\"card-name\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n\n @if (statusColumn(); as column) {\n <span class=\"card-status\">\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else {\n {{ text(column, row) }}\n }\n </span>\n }\n </div>\n\n @if (attributeColumns().length || visibleActions(row).length) {\n <div class=\"card-foot\">\n <div class=\"card-fields\">\n @for (column of attributeColumns(); track column.key) {\n <div class=\"field\">\n <span class=\"field-label\">{{ column.header }}</span>\n <span class=\"field-value\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (linkOf(column, row); as target) {\n <nucleus-link\n [route]=\"target.route\"\n [queryParams]=\"target.queryParams ?? null\"\n [hint]=\"column.header\"\n >\n {{ text(column, row) }}\n </nucleus-link>\n } @else if (column.kind === 'switch') {\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"column.header\"\n [disabled]=\"isLocked(column, row)\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n } @else {\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n }\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </span>\n </div>\n }\n </div>\n\n @if (visibleActions(row).length) {\n <div class=\"card-actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </div>\n }\n </div>\n }\n </article>\n }\n }\n </div>\n\n @if (paginate()) {\n <div class=\"foot\">\n <p-paginator\n styleClass=\"ns-cards-paginator\"\n [first]=\"page()\"\n [rows]=\"rowsPerPage()\"\n [totalRecords]=\"filtered().length\"\n [rowsPerPageOptions]=\"pageSizes()\"\n (onPageChange)=\"onPage($event)\"\n />\n </div>\n }\n} @else {\n <p-table\n [value]=\"data()\"\n styleClass=\"ns-table\"\n [tableStyle]=\"tableStyle()\"\n [paginator]=\"paginate()\"\n [rows]=\"pageSize()\"\n [rowsPerPageOptions]=\"pageSizes()\"\n [alwaysShowPaginator]=\"true\"\n (onRowReorder)=\"onRowReorder($event)\"\n >\n <ng-template #header>\n <tr>\n @if (reorderable()) {\n <th class=\"grip-head\"></th>\n }\n @for (column of columns(); track column.key) {\n <th [class]=\"'align-' + (column.align ?? 'left')\" [style.width]=\"column.width\">\n {{ column.header }}\n </th>\n }\n @if (actions().length) {\n <th class=\"align-right\"></th>\n }\n </tr>\n </ng-template>\n\n <ng-template #body let-row let-rowIndex=\"rowIndex\">\n @if (loading()) {\n <tr class=\"is-skeleton\">\n @if (reorderable()) {\n <td class=\"grip-cell\"></td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\">\n <p-skeleton height=\"13px\" [width]=\"skeletonWidth(column)\" />\n </td>\n }\n @if (actions().length) {\n <td class=\"align-right actions\">\n <p-skeleton shape=\"circle\" size=\"26px\" />\n </td>\n }\n </tr>\n } @else {\n <tr\n [class]=\"rowClass()(row)\"\n [pReorderableRow]=\"rowIndex\"\n [pReorderableRowDisabled]=\"dragLocked()\"\n >\n @if (reorderable()) {\n <td class=\"grip-cell\">\n <span class=\"grip\" pReorderableRowHandle [attr.aria-label]=\"copy().reorderHandle\">\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </span>\n </td>\n }\n @for (column of columns(); track column.key) {\n <td [class]=\"'align-' + (column.align ?? 'left')\" [class.strong]=\"column.strong\">\n @if (cellTemplate(column.key); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"\n />\n } @else if (column.kind === 'switch') {\n <span class=\"switch-cell\">\n <button\n type=\"button\"\n class=\"ns-switch\"\n role=\"switch\"\n [class.is-on]=\"isChecked(column, row)\"\n [attr.aria-checked]=\"isChecked(column, row)\"\n [attr.aria-label]=\"text(column, row)\"\n [disabled]=\"isLocked(column, row)\"\n [pTooltip]=\"hintOf(column, row)\"\n tooltipPosition=\"top\"\n (click)=\"flip(column, row)\"\n >\n <span class=\"knob\"></span>\n </button>\n <span class=\"switch-label\">{{ text(column, row) }}</span>\n </span>\n } @else {\n {{ text(column, row) }}\n @if (tagOf(column, row); as tag) {\n <p-tag [value]=\"tag.label\" [severity]=\"tag.severity ?? 'secondary'\" />\n }\n }\n </td>\n }\n\n @if (actions().length) {\n <td class=\"align-right actions\">\n @for (entry of visibleActions(row); track entry.id) {\n <p-button\n [icon]=\"entry.icon\"\n [severity]=\"entry.tone === 'danger' ? 'danger' : 'secondary'\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [pTooltip]=\"entry.label\"\n tooltipPosition=\"left\"\n [ariaLabel]=\"entry.label\"\n [disabled]=\"isActionLocked(entry, row)\"\n (onClick)=\"run(entry, row)\"\n />\n }\n </td>\n }\n </tr>\n }\n </ng-template>\n </p-table>\n}\n}\n", styles: [":host{display:block}.head{display:flex;align-items:center;justify-content:space-between;gap:12px}.head:has(>*:not(.head-actions)),.head:has(.head-actions>*){min-height:34px;margin-bottom:12px}.head-actions{display:flex;gap:8px}.placeholder{padding:26px;border:1px dashed var(--ac-border);border-radius:10px;color:var(--ac-text-muted);font-size:14px}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.strong{font-weight:var(--ns-weight-emphasis)}.actions{white-space:nowrap}.switch-cell{display:inline-flex;align-items:center;gap:10px}.switch-label{color:var(--ac-text-muted);font-size:12px}.ns-switch{position:relative;width:38px;height:22px;flex:none;padding:0;border:1px solid var(--ac-border);border-radius:var(--ac-radius-pill);background:color-mix(in srgb,var(--ac-text) 10%,transparent);cursor:pointer;transition:background .14s ease,border-color .14s ease}.ns-switch .knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--ac-text);transition:transform .14s ease}.ns-switch.is-on{border-color:var(--ac-accent);background:var(--ac-accent)}.ns-switch.is-on .knob{background:var(--ac-on-accent);transform:translate(16px)}.ns-switch:disabled{cursor:not-allowed;opacity:.45}.ns-switch:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.cards{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}.card{padding:13px 14px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.card-name{display:flex;min-width:0;flex:1;align-items:center;gap:10px;font-size:15px;font-weight:var(--ns-weight-emphasis);line-height:1.3}.card-status{flex:none}.card-foot{display:flex;align-items:flex-end;gap:12px;margin-top:11px;padding-top:11px;border-top:1px solid var(--ac-border)}.card-fields{display:flex;min-width:0;flex:1;flex-wrap:wrap;gap:10px 20px}.card-actions{display:flex;flex:none;align-items:center;gap:2px}.field{display:flex;min-width:0;flex-direction:column;gap:2px}.field-label{color:var(--ac-text-muted);font-size:10px;font-weight:var(--ns-weight-heading);letter-spacing:.07em;text-transform:uppercase}.field-value{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:var(--ns-weight-emphasis);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}::ng-deep .ns-cards-paginator{background:transparent}.grip{display:inline-grid;width:26px;height:26px;flex:none;padding:0;border:0;border-radius:4px;background:transparent;color:var(--ac-text-muted);cursor:grab;place-items:center;touch-action:none}.grip:hover{background:color-mix(in srgb,var(--ac-text) 8%,transparent);color:var(--ac-text)}.grip:active{cursor:grabbing}.grip:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.grip .pi{font-size:13px}.grip-head,.grip-cell{width:38px;padding-right:0!important}.cdk-drag-preview{border:1px solid var(--ac-accent);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-2);opacity:.96}.cdk-drag-placeholder{border:1px dashed var(--ac-border);background:color-mix(in srgb,var(--ac-text) 4%,transparent);opacity:.6}.cdk-drag-placeholder *{visibility:hidden}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .18s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .22s cubic-bezier(0,0,.2,1)}.bar{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:7px 10px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.bar-spacer{flex:1}.search{display:flex;min-width:0;max-width:340px;flex:1 1 220px;align-items:center;gap:8px;padding:5px 10px;border:1px solid var(--ac-border);border-radius:6px;background:color-mix(in srgb,var(--ac-text) 4%,transparent);color:var(--ac-text-muted)}.search:focus-within{border-color:var(--ac-accent);color:var(--ac-text)}.search .pi{font-size:13px}.search input{min-width:0;flex:1;padding:0;border:0;background:transparent;color:var(--ac-text);font:inherit;font-size:13px;outline:none}.search input::-webkit-search-cancel-button{filter:grayscale(1) opacity(.6)}.views{display:inline-flex;flex:none;padding:2px;border:1px solid var(--ac-border);border-radius:7px}.view{display:grid;width:30px;height:28px;padding:0;border:0;border-radius:5px;background:transparent;color:var(--ac-text-muted);cursor:pointer;place-items:center}.view:hover{color:var(--ac-text)}.view.is-on{background:color-mix(in srgb,var(--ac-accent) 18%,transparent);color:var(--ac-accent)}.view:focus-visible{outline:2px solid var(--ac-accent);outline-offset:2px}.view .pi{font-size:14px}.foot{margin-top:12px;padding:4px 6px;border:1px solid var(--ac-border);border-radius:10px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}@media(min-width:721px){.cards.is-rows{gap:8px;grid-template-columns:minmax(0,1fr)}.cards.is-rows .card{display:grid;align-items:center;gap:18px;grid-template-columns:minmax(0,2fr) minmax(0,3fr);padding:9px 14px}.cards.is-rows .card-top{min-width:0;align-items:center;gap:12px}.cards.is-rows .card-foot{margin-top:0;padding-top:0;border-top:0;gap:14px}.cards.is-rows .card-fields{display:grid;min-width:0;flex:1;gap:14px;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column}.cards.is-rows .field-label,.cards.is-rows .field-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}\n"] }]
3269
3428
  }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], empty: [{ type: i0.Input, args: [{ isSignal: true, alias: "empty", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], skeletonRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRows", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizes", required: false }] }], cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], reorderGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderGroup", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], reorder: [{ type: i0.Output, args: ["reorder"] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }], toggle: [{ type: i0.Output, args: ["toggle"] }], cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NucleusCell), { isSignal: true }] }] } });
3270
3429
 
3271
3430
  function toggleCollapsed(collapsed, id) {
@@ -3403,11 +3562,11 @@ class NucleusAppearance {
3403
3562
  this.theme.setDensity(id);
3404
3563
  }
3405
3564
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusAppearance, deps: [], target: i0.ɵɵFactoryTarget.Component });
3406
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusAppearance, isStandalone: true, selector: "nucleus-appearance", ngImport: i0, template: "@let t = copy();\n@let current = appearance();\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.frameTitle }}</h3>\n <p class=\"group-hint\">{{ t.frameHint }}</p>\n\n <div class=\"frames\" role=\"radiogroup\" [attr.aria-label]=\"t.frameTitle\">\n @for (frame of frames(); track frame.id) {\n <button\n type=\"button\"\n class=\"frame\"\n role=\"radio\"\n [class.is-active]=\"frame.id === current.frame\"\n [attr.aria-checked]=\"frame.id === current.frame\"\n [attr.aria-label]=\"frame.label\"\n [style.--f-bg]=\"frame.tokens.bg\"\n [style.--f-raised]=\"frame.tokens.raised\"\n [style.--f-ink]=\"frame.tokens.ink\"\n [style.--f-muted]=\"frame.tokens.muted\"\n [style.--f-line]=\"frame.tokens.line\"\n [style.--f-glow]=\"frame.tokens.glow\"\n (click)=\"pickFrame(frame.id)\"\n >\n <span class=\"frame-chip\" aria-hidden=\"true\">\n <span class=\"frame-bar\">\n <span class=\"frame-dot\"></span>\n </span>\n <span class=\"frame-lower\">\n <span class=\"frame-rail\">\n <span class=\"frame-pin\"></span>\n <span class=\"frame-row is-on\"></span>\n <span class=\"frame-row\"></span>\n <span class=\"frame-row\"></span>\n </span>\n <span class=\"frame-canvas\"></span>\n </span>\n </span>\n <span class=\"frame-name\">{{ frame.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.canvasTitle }}</h3>\n <p class=\"group-hint\">{{ t.canvasHint }}</p>\n\n <div class=\"canvases\" role=\"radiogroup\" [attr.aria-label]=\"t.canvasTitle\">\n @for (canvas of canvases(); track canvas.id) {\n <button\n type=\"button\"\n class=\"canvas\"\n role=\"radio\"\n [class.is-active]=\"canvas.id === current.canvas\"\n [attr.aria-checked]=\"canvas.id === current.canvas\"\n (click)=\"pickCanvas(canvas.id)\"\n >\n <span\n class=\"canvas-chip\"\n aria-hidden=\"true\"\n [style.background]=\"canvas.bg\"\n [style.color]=\"canvas.text\"\n >\n @if (canvas.icon) {\n <i [class]=\"canvas.icon\"></i>\n } @else {\n <span class=\"canvas-sheet\" [style.background]=\"canvas.surface\"></span>\n }\n </span>\n <span class=\"canvas-name\">{{ canvas.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.accentTitle }}</h3>\n <p class=\"group-hint\">{{ t.accentHint }}</p>\n\n <div class=\"accents\" role=\"radiogroup\" [attr.aria-label]=\"t.accentTitle\">\n @for (accent of accents(); track accent.id) {\n <button\n type=\"button\"\n class=\"accent\"\n role=\"radio\"\n [class.is-auto]=\"accent.id === 'auto'\"\n [class.is-active]=\"accent.id === current.accent\"\n [attr.aria-checked]=\"accent.id === current.accent\"\n [attr.aria-label]=\"accent.label\"\n [title]=\"accent.label\"\n [style.background]=\"accent.color\"\n [style.color]=\"accent.ink\"\n (click)=\"pickAccent(accent.id)\"\n >\n @if (accent.id === current.accent) {\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n } @else if (accent.id === 'auto') {\n <i class=\"pi pi-sparkles\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.densityTitle }}</h3>\n <p class=\"group-hint\">{{ t.densityHint }}</p>\n\n <div class=\"densities\" role=\"radiogroup\" [attr.aria-label]=\"t.densityTitle\">\n @for (density of densities(); track density.id) {\n <button\n type=\"button\"\n class=\"density\"\n role=\"radio\"\n [class.is-active]=\"density.id === current.density\"\n [attr.aria-checked]=\"density.id === current.density\"\n (click)=\"pickDensity(density.id)\"\n >\n <span class=\"density-chip\" aria-hidden=\"true\" [style.gap.px]=\"density.gap\">\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n </span>\n <span class=\"density-name\">{{ density.label }}</span>\n </button>\n }\n </div>\n</section>\n", styles: [":host{display:flex;flex-direction:column;gap:26px}.group{display:flex;flex-direction:column;gap:2px}.group-title{margin:0;font-size:13px;font-weight:600;letter-spacing:.02em}.group-hint{margin:0 0 12px;color:var(--ac-text-muted);font-size:12px;font-weight:300;line-height:1.45}.frames{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}.frame{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.frame:hover{color:var(--ac-text)}.frame.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.frame-chip{display:flex;overflow:hidden;flex-direction:column;height:52px;border:1px solid var(--f-line);border-radius:6px;background:var(--f-bg)}.frame-bar{display:flex;flex:none;align-items:center;height:12px;padding-left:5px;border-bottom:1px solid var(--f-line)}.frame-dot{width:5px;height:5px;border-radius:50%;background:var(--f-glow)}.frame-lower{display:flex;flex:1;min-height:0}.frame-rail{display:flex;flex:none;flex-direction:column;gap:3px;width:22px;padding:4px 3px;border-right:1px solid var(--f-line)}.frame-pin{height:7px;border-left:2px solid var(--f-glow);border-radius:2px;background:var(--f-raised)}.frame-row{height:3px;border-radius:2px;background:var(--f-muted);opacity:.55}.frame-row.is-on{background:var(--f-glow);opacity:1}.frame-canvas{flex:1;background:var(--ac-bg)}.frame-name{overflow:hidden;font-size:11px;font-weight:500;text-align:center;text-overflow:ellipsis;white-space:nowrap}.canvases{display:grid;grid-template-columns:repeat(auto-fit,minmax(70px,1fr));gap:8px}.canvas{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.canvas:hover{color:var(--ac-text)}.canvas.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.canvas-chip{display:flex;align-items:center;justify-content:center;height:40px;border:1px solid var(--ac-border);border-radius:6px}.canvas-chip i{font-size:15px}.canvas-sheet{width:60%;height:58%;border-radius:3px;box-shadow:0 1px 4px #00000038}.canvas-name{font-size:11px;font-weight:500;text-align:center}.accents{display:flex;flex-wrap:wrap;gap:9px}.accent{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:2px solid transparent;border-radius:50%;cursor:pointer;transition:transform .12s ease}.accent:hover{transform:scale(1.12)}.accent.is-auto{border-style:dashed;border-color:var(--ac-border)}.accent.is-active{border-style:solid;border-color:var(--ac-text);box-shadow:0 0 0 2px var(--ac-surface) inset}.accent i{font-size:11px}.densities{display:flex;gap:10px}.density{display:flex;flex:1;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.density:hover{color:var(--ac-text)}.density.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.density-chip{display:flex;flex-direction:column;justify-content:center;height:42px;padding:0 10px;border:1px solid var(--ac-border);border-radius:6px;background:var(--ac-surface)}.density-row{height:3px;border-radius:2px;background:var(--ac-text-muted);opacity:.5}.density-name{font-size:11px;font-weight:500;text-align:center}@media(prefers-reduced-motion:reduce){.accent{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3565
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusAppearance, isStandalone: true, selector: "nucleus-appearance", ngImport: i0, template: "@let t = copy();\n@let current = appearance();\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.frameTitle }}</h3>\n <p class=\"group-hint\">{{ t.frameHint }}</p>\n\n <div class=\"frames\" role=\"radiogroup\" [attr.aria-label]=\"t.frameTitle\">\n @for (frame of frames(); track frame.id) {\n <button\n type=\"button\"\n class=\"frame\"\n role=\"radio\"\n [class.is-active]=\"frame.id === current.frame\"\n [attr.aria-checked]=\"frame.id === current.frame\"\n [attr.aria-label]=\"frame.label\"\n [style.--f-bg]=\"frame.tokens.bg\"\n [style.--f-raised]=\"frame.tokens.raised\"\n [style.--f-ink]=\"frame.tokens.ink\"\n [style.--f-muted]=\"frame.tokens.muted\"\n [style.--f-line]=\"frame.tokens.line\"\n [style.--f-glow]=\"frame.tokens.glow\"\n (click)=\"pickFrame(frame.id)\"\n >\n <span class=\"frame-chip\" aria-hidden=\"true\">\n <span class=\"frame-bar\">\n <span class=\"frame-dot\"></span>\n </span>\n <span class=\"frame-lower\">\n <span class=\"frame-rail\">\n <span class=\"frame-pin\"></span>\n <span class=\"frame-row is-on\"></span>\n <span class=\"frame-row\"></span>\n <span class=\"frame-row\"></span>\n </span>\n <span class=\"frame-canvas\"></span>\n </span>\n </span>\n <span class=\"frame-name\">{{ frame.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.canvasTitle }}</h3>\n <p class=\"group-hint\">{{ t.canvasHint }}</p>\n\n <div class=\"canvases\" role=\"radiogroup\" [attr.aria-label]=\"t.canvasTitle\">\n @for (canvas of canvases(); track canvas.id) {\n <button\n type=\"button\"\n class=\"canvas\"\n role=\"radio\"\n [class.is-active]=\"canvas.id === current.canvas\"\n [attr.aria-checked]=\"canvas.id === current.canvas\"\n (click)=\"pickCanvas(canvas.id)\"\n >\n <span\n class=\"canvas-chip\"\n aria-hidden=\"true\"\n [style.background]=\"canvas.bg\"\n [style.color]=\"canvas.text\"\n >\n @if (canvas.icon) {\n <i [class]=\"canvas.icon\"></i>\n } @else {\n <span class=\"canvas-sheet\" [style.background]=\"canvas.surface\"></span>\n }\n </span>\n <span class=\"canvas-name\">{{ canvas.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.accentTitle }}</h3>\n <p class=\"group-hint\">{{ t.accentHint }}</p>\n\n <div class=\"accents\" role=\"radiogroup\" [attr.aria-label]=\"t.accentTitle\">\n @for (accent of accents(); track accent.id) {\n <button\n type=\"button\"\n class=\"accent\"\n role=\"radio\"\n [class.is-auto]=\"accent.id === 'auto'\"\n [class.is-active]=\"accent.id === current.accent\"\n [attr.aria-checked]=\"accent.id === current.accent\"\n [attr.aria-label]=\"accent.label\"\n [title]=\"accent.label\"\n [style.background]=\"accent.color\"\n [style.color]=\"accent.ink\"\n (click)=\"pickAccent(accent.id)\"\n >\n @if (accent.id === current.accent) {\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n } @else if (accent.id === 'auto') {\n <i class=\"pi pi-sparkles\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.densityTitle }}</h3>\n <p class=\"group-hint\">{{ t.densityHint }}</p>\n\n <div class=\"densities\" role=\"radiogroup\" [attr.aria-label]=\"t.densityTitle\">\n @for (density of densities(); track density.id) {\n <button\n type=\"button\"\n class=\"density\"\n role=\"radio\"\n [class.is-active]=\"density.id === current.density\"\n [attr.aria-checked]=\"density.id === current.density\"\n (click)=\"pickDensity(density.id)\"\n >\n <span class=\"density-chip\" aria-hidden=\"true\" [style.gap.px]=\"density.gap\">\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n </span>\n <span class=\"density-name\">{{ density.label }}</span>\n </button>\n }\n </div>\n</section>\n", styles: [":host{display:flex;flex-direction:column;gap:26px}.group{display:flex;flex-direction:column;gap:2px}.group-title{margin:0;font-size:13px;font-weight:var(--ns-weight-heading);letter-spacing:.02em}.group-hint{margin:0 0 12px;color:var(--ac-text-muted);font-size:12px;font-weight:300;line-height:1.45}.frames{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}.frame{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.frame:hover{color:var(--ac-text)}.frame.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.frame-chip{display:flex;overflow:hidden;flex-direction:column;height:52px;border:1px solid var(--f-line);border-radius:6px;background:var(--f-bg)}.frame-bar{display:flex;flex:none;align-items:center;height:12px;padding-left:5px;border-bottom:1px solid var(--f-line)}.frame-dot{width:5px;height:5px;border-radius:50%;background:var(--f-glow)}.frame-lower{display:flex;flex:1;min-height:0}.frame-rail{display:flex;flex:none;flex-direction:column;gap:3px;width:22px;padding:4px 3px;border-right:1px solid var(--f-line)}.frame-pin{height:7px;border-left:2px solid var(--f-glow);border-radius:2px;background:var(--f-raised)}.frame-row{height:3px;border-radius:2px;background:var(--f-muted);opacity:.55}.frame-row.is-on{background:var(--f-glow);opacity:1}.frame-canvas{flex:1;background:var(--ac-bg)}.frame-name{overflow:hidden;font-size:11px;font-weight:var(--ns-weight-emphasis);text-align:center;text-overflow:ellipsis;white-space:nowrap}.canvases{display:grid;grid-template-columns:repeat(auto-fit,minmax(70px,1fr));gap:8px}.canvas{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.canvas:hover{color:var(--ac-text)}.canvas.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.canvas-chip{display:flex;align-items:center;justify-content:center;height:40px;border:1px solid var(--ac-border);border-radius:6px}.canvas-chip i{font-size:15px}.canvas-sheet{width:60%;height:58%;border-radius:3px;box-shadow:0 1px 4px #00000038}.canvas-name{font-size:11px;font-weight:var(--ns-weight-emphasis);text-align:center}.accents{display:flex;flex-wrap:wrap;gap:9px}.accent{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:2px solid transparent;border-radius:50%;cursor:pointer;transition:transform .12s ease}.accent:hover{transform:scale(1.12)}.accent.is-auto{border-style:dashed;border-color:var(--ac-border)}.accent.is-active{border-style:solid;border-color:var(--ac-text);box-shadow:0 0 0 2px var(--ac-surface) inset}.accent i{font-size:11px}.densities{display:flex;gap:10px}.density{display:flex;flex:1;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.density:hover{color:var(--ac-text)}.density.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.density-chip{display:flex;flex-direction:column;justify-content:center;height:42px;padding:0 10px;border:1px solid var(--ac-border);border-radius:6px;background:var(--ac-surface)}.density-row{height:3px;border-radius:2px;background:var(--ac-text-muted);opacity:.5}.density-name{font-size:11px;font-weight:var(--ns-weight-emphasis);text-align:center}@media(prefers-reduced-motion:reduce){.accent{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3407
3566
  }
3408
3567
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusAppearance, decorators: [{
3409
3568
  type: Component,
3410
- args: [{ selector: 'nucleus-appearance', changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let current = appearance();\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.frameTitle }}</h3>\n <p class=\"group-hint\">{{ t.frameHint }}</p>\n\n <div class=\"frames\" role=\"radiogroup\" [attr.aria-label]=\"t.frameTitle\">\n @for (frame of frames(); track frame.id) {\n <button\n type=\"button\"\n class=\"frame\"\n role=\"radio\"\n [class.is-active]=\"frame.id === current.frame\"\n [attr.aria-checked]=\"frame.id === current.frame\"\n [attr.aria-label]=\"frame.label\"\n [style.--f-bg]=\"frame.tokens.bg\"\n [style.--f-raised]=\"frame.tokens.raised\"\n [style.--f-ink]=\"frame.tokens.ink\"\n [style.--f-muted]=\"frame.tokens.muted\"\n [style.--f-line]=\"frame.tokens.line\"\n [style.--f-glow]=\"frame.tokens.glow\"\n (click)=\"pickFrame(frame.id)\"\n >\n <span class=\"frame-chip\" aria-hidden=\"true\">\n <span class=\"frame-bar\">\n <span class=\"frame-dot\"></span>\n </span>\n <span class=\"frame-lower\">\n <span class=\"frame-rail\">\n <span class=\"frame-pin\"></span>\n <span class=\"frame-row is-on\"></span>\n <span class=\"frame-row\"></span>\n <span class=\"frame-row\"></span>\n </span>\n <span class=\"frame-canvas\"></span>\n </span>\n </span>\n <span class=\"frame-name\">{{ frame.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.canvasTitle }}</h3>\n <p class=\"group-hint\">{{ t.canvasHint }}</p>\n\n <div class=\"canvases\" role=\"radiogroup\" [attr.aria-label]=\"t.canvasTitle\">\n @for (canvas of canvases(); track canvas.id) {\n <button\n type=\"button\"\n class=\"canvas\"\n role=\"radio\"\n [class.is-active]=\"canvas.id === current.canvas\"\n [attr.aria-checked]=\"canvas.id === current.canvas\"\n (click)=\"pickCanvas(canvas.id)\"\n >\n <span\n class=\"canvas-chip\"\n aria-hidden=\"true\"\n [style.background]=\"canvas.bg\"\n [style.color]=\"canvas.text\"\n >\n @if (canvas.icon) {\n <i [class]=\"canvas.icon\"></i>\n } @else {\n <span class=\"canvas-sheet\" [style.background]=\"canvas.surface\"></span>\n }\n </span>\n <span class=\"canvas-name\">{{ canvas.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.accentTitle }}</h3>\n <p class=\"group-hint\">{{ t.accentHint }}</p>\n\n <div class=\"accents\" role=\"radiogroup\" [attr.aria-label]=\"t.accentTitle\">\n @for (accent of accents(); track accent.id) {\n <button\n type=\"button\"\n class=\"accent\"\n role=\"radio\"\n [class.is-auto]=\"accent.id === 'auto'\"\n [class.is-active]=\"accent.id === current.accent\"\n [attr.aria-checked]=\"accent.id === current.accent\"\n [attr.aria-label]=\"accent.label\"\n [title]=\"accent.label\"\n [style.background]=\"accent.color\"\n [style.color]=\"accent.ink\"\n (click)=\"pickAccent(accent.id)\"\n >\n @if (accent.id === current.accent) {\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n } @else if (accent.id === 'auto') {\n <i class=\"pi pi-sparkles\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.densityTitle }}</h3>\n <p class=\"group-hint\">{{ t.densityHint }}</p>\n\n <div class=\"densities\" role=\"radiogroup\" [attr.aria-label]=\"t.densityTitle\">\n @for (density of densities(); track density.id) {\n <button\n type=\"button\"\n class=\"density\"\n role=\"radio\"\n [class.is-active]=\"density.id === current.density\"\n [attr.aria-checked]=\"density.id === current.density\"\n (click)=\"pickDensity(density.id)\"\n >\n <span class=\"density-chip\" aria-hidden=\"true\" [style.gap.px]=\"density.gap\">\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n </span>\n <span class=\"density-name\">{{ density.label }}</span>\n </button>\n }\n </div>\n</section>\n", styles: [":host{display:flex;flex-direction:column;gap:26px}.group{display:flex;flex-direction:column;gap:2px}.group-title{margin:0;font-size:13px;font-weight:600;letter-spacing:.02em}.group-hint{margin:0 0 12px;color:var(--ac-text-muted);font-size:12px;font-weight:300;line-height:1.45}.frames{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}.frame{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.frame:hover{color:var(--ac-text)}.frame.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.frame-chip{display:flex;overflow:hidden;flex-direction:column;height:52px;border:1px solid var(--f-line);border-radius:6px;background:var(--f-bg)}.frame-bar{display:flex;flex:none;align-items:center;height:12px;padding-left:5px;border-bottom:1px solid var(--f-line)}.frame-dot{width:5px;height:5px;border-radius:50%;background:var(--f-glow)}.frame-lower{display:flex;flex:1;min-height:0}.frame-rail{display:flex;flex:none;flex-direction:column;gap:3px;width:22px;padding:4px 3px;border-right:1px solid var(--f-line)}.frame-pin{height:7px;border-left:2px solid var(--f-glow);border-radius:2px;background:var(--f-raised)}.frame-row{height:3px;border-radius:2px;background:var(--f-muted);opacity:.55}.frame-row.is-on{background:var(--f-glow);opacity:1}.frame-canvas{flex:1;background:var(--ac-bg)}.frame-name{overflow:hidden;font-size:11px;font-weight:500;text-align:center;text-overflow:ellipsis;white-space:nowrap}.canvases{display:grid;grid-template-columns:repeat(auto-fit,minmax(70px,1fr));gap:8px}.canvas{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.canvas:hover{color:var(--ac-text)}.canvas.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.canvas-chip{display:flex;align-items:center;justify-content:center;height:40px;border:1px solid var(--ac-border);border-radius:6px}.canvas-chip i{font-size:15px}.canvas-sheet{width:60%;height:58%;border-radius:3px;box-shadow:0 1px 4px #00000038}.canvas-name{font-size:11px;font-weight:500;text-align:center}.accents{display:flex;flex-wrap:wrap;gap:9px}.accent{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:2px solid transparent;border-radius:50%;cursor:pointer;transition:transform .12s ease}.accent:hover{transform:scale(1.12)}.accent.is-auto{border-style:dashed;border-color:var(--ac-border)}.accent.is-active{border-style:solid;border-color:var(--ac-text);box-shadow:0 0 0 2px var(--ac-surface) inset}.accent i{font-size:11px}.densities{display:flex;gap:10px}.density{display:flex;flex:1;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.density:hover{color:var(--ac-text)}.density.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.density-chip{display:flex;flex-direction:column;justify-content:center;height:42px;padding:0 10px;border:1px solid var(--ac-border);border-radius:6px;background:var(--ac-surface)}.density-row{height:3px;border-radius:2px;background:var(--ac-text-muted);opacity:.5}.density-name{font-size:11px;font-weight:500;text-align:center}@media(prefers-reduced-motion:reduce){.accent{transition:none}}\n"] }]
3569
+ args: [{ selector: 'nucleus-appearance', changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let current = appearance();\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.frameTitle }}</h3>\n <p class=\"group-hint\">{{ t.frameHint }}</p>\n\n <div class=\"frames\" role=\"radiogroup\" [attr.aria-label]=\"t.frameTitle\">\n @for (frame of frames(); track frame.id) {\n <button\n type=\"button\"\n class=\"frame\"\n role=\"radio\"\n [class.is-active]=\"frame.id === current.frame\"\n [attr.aria-checked]=\"frame.id === current.frame\"\n [attr.aria-label]=\"frame.label\"\n [style.--f-bg]=\"frame.tokens.bg\"\n [style.--f-raised]=\"frame.tokens.raised\"\n [style.--f-ink]=\"frame.tokens.ink\"\n [style.--f-muted]=\"frame.tokens.muted\"\n [style.--f-line]=\"frame.tokens.line\"\n [style.--f-glow]=\"frame.tokens.glow\"\n (click)=\"pickFrame(frame.id)\"\n >\n <span class=\"frame-chip\" aria-hidden=\"true\">\n <span class=\"frame-bar\">\n <span class=\"frame-dot\"></span>\n </span>\n <span class=\"frame-lower\">\n <span class=\"frame-rail\">\n <span class=\"frame-pin\"></span>\n <span class=\"frame-row is-on\"></span>\n <span class=\"frame-row\"></span>\n <span class=\"frame-row\"></span>\n </span>\n <span class=\"frame-canvas\"></span>\n </span>\n </span>\n <span class=\"frame-name\">{{ frame.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.canvasTitle }}</h3>\n <p class=\"group-hint\">{{ t.canvasHint }}</p>\n\n <div class=\"canvases\" role=\"radiogroup\" [attr.aria-label]=\"t.canvasTitle\">\n @for (canvas of canvases(); track canvas.id) {\n <button\n type=\"button\"\n class=\"canvas\"\n role=\"radio\"\n [class.is-active]=\"canvas.id === current.canvas\"\n [attr.aria-checked]=\"canvas.id === current.canvas\"\n (click)=\"pickCanvas(canvas.id)\"\n >\n <span\n class=\"canvas-chip\"\n aria-hidden=\"true\"\n [style.background]=\"canvas.bg\"\n [style.color]=\"canvas.text\"\n >\n @if (canvas.icon) {\n <i [class]=\"canvas.icon\"></i>\n } @else {\n <span class=\"canvas-sheet\" [style.background]=\"canvas.surface\"></span>\n }\n </span>\n <span class=\"canvas-name\">{{ canvas.label }}</span>\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.accentTitle }}</h3>\n <p class=\"group-hint\">{{ t.accentHint }}</p>\n\n <div class=\"accents\" role=\"radiogroup\" [attr.aria-label]=\"t.accentTitle\">\n @for (accent of accents(); track accent.id) {\n <button\n type=\"button\"\n class=\"accent\"\n role=\"radio\"\n [class.is-auto]=\"accent.id === 'auto'\"\n [class.is-active]=\"accent.id === current.accent\"\n [attr.aria-checked]=\"accent.id === current.accent\"\n [attr.aria-label]=\"accent.label\"\n [title]=\"accent.label\"\n [style.background]=\"accent.color\"\n [style.color]=\"accent.ink\"\n (click)=\"pickAccent(accent.id)\"\n >\n @if (accent.id === current.accent) {\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n } @else if (accent.id === 'auto') {\n <i class=\"pi pi-sparkles\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n</section>\n\n<section class=\"group\">\n <h3 class=\"group-title\">{{ t.densityTitle }}</h3>\n <p class=\"group-hint\">{{ t.densityHint }}</p>\n\n <div class=\"densities\" role=\"radiogroup\" [attr.aria-label]=\"t.densityTitle\">\n @for (density of densities(); track density.id) {\n <button\n type=\"button\"\n class=\"density\"\n role=\"radio\"\n [class.is-active]=\"density.id === current.density\"\n [attr.aria-checked]=\"density.id === current.density\"\n (click)=\"pickDensity(density.id)\"\n >\n <span class=\"density-chip\" aria-hidden=\"true\" [style.gap.px]=\"density.gap\">\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n <span class=\"density-row\"></span>\n </span>\n <span class=\"density-name\">{{ density.label }}</span>\n </button>\n }\n </div>\n</section>\n", styles: [":host{display:flex;flex-direction:column;gap:26px}.group{display:flex;flex-direction:column;gap:2px}.group-title{margin:0;font-size:13px;font-weight:var(--ns-weight-heading);letter-spacing:.02em}.group-hint{margin:0 0 12px;color:var(--ac-text-muted);font-size:12px;font-weight:300;line-height:1.45}.frames{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px}.frame{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.frame:hover{color:var(--ac-text)}.frame.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.frame-chip{display:flex;overflow:hidden;flex-direction:column;height:52px;border:1px solid var(--f-line);border-radius:6px;background:var(--f-bg)}.frame-bar{display:flex;flex:none;align-items:center;height:12px;padding-left:5px;border-bottom:1px solid var(--f-line)}.frame-dot{width:5px;height:5px;border-radius:50%;background:var(--f-glow)}.frame-lower{display:flex;flex:1;min-height:0}.frame-rail{display:flex;flex:none;flex-direction:column;gap:3px;width:22px;padding:4px 3px;border-right:1px solid var(--f-line)}.frame-pin{height:7px;border-left:2px solid var(--f-glow);border-radius:2px;background:var(--f-raised)}.frame-row{height:3px;border-radius:2px;background:var(--f-muted);opacity:.55}.frame-row.is-on{background:var(--f-glow);opacity:1}.frame-canvas{flex:1;background:var(--ac-bg)}.frame-name{overflow:hidden;font-size:11px;font-weight:var(--ns-weight-emphasis);text-align:center;text-overflow:ellipsis;white-space:nowrap}.canvases{display:grid;grid-template-columns:repeat(auto-fit,minmax(70px,1fr));gap:8px}.canvas{display:flex;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.canvas:hover{color:var(--ac-text)}.canvas.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.canvas-chip{display:flex;align-items:center;justify-content:center;height:40px;border:1px solid var(--ac-border);border-radius:6px}.canvas-chip i{font-size:15px}.canvas-sheet{width:60%;height:58%;border-radius:3px;box-shadow:0 1px 4px #00000038}.canvas-name{font-size:11px;font-weight:var(--ns-weight-emphasis);text-align:center}.accents{display:flex;flex-wrap:wrap;gap:9px}.accent{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:2px solid transparent;border-radius:50%;cursor:pointer;transition:transform .12s ease}.accent:hover{transform:scale(1.12)}.accent.is-auto{border-style:dashed;border-color:var(--ac-border)}.accent.is-active{border-style:solid;border-color:var(--ac-text);box-shadow:0 0 0 2px var(--ac-surface) inset}.accent i{font-size:11px}.densities{display:flex;gap:10px}.density{display:flex;flex:1;flex-direction:column;gap:6px;padding:4px;border:2px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text-muted);cursor:pointer}.density:hover{color:var(--ac-text)}.density.is-active{border-color:var(--ac-accent);color:var(--ac-text)}.density-chip{display:flex;flex-direction:column;justify-content:center;height:42px;padding:0 10px;border:1px solid var(--ac-border);border-radius:6px;background:var(--ac-surface)}.density-row{height:3px;border-radius:2px;background:var(--ac-text-muted);opacity:.5}.density-name{font-size:11px;font-weight:var(--ns-weight-emphasis);text-align:center}@media(prefers-reduced-motion:reduce){.accent{transition:none}}\n"] }]
3411
3570
  }] });
3412
3571
 
3413
3572
  class NucleusMenu {
@@ -3419,9 +3578,14 @@ class NucleusMenu {
3419
3578
  emptyText = input('', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
3420
3579
  keyboardHint = input('', ...(ngDevMode ? [{ debugName: "keyboardHint" }] : /* istanbul ignore next */ []));
3421
3580
  width = input(320, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
3581
+ layout = input('list', ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
3582
+ columns = input(3, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
3422
3583
  select = output();
3423
3584
  dismiss = output();
3424
3585
  term = signal('', ...(ngDevMode ? [{ debugName: "term" }] : /* istanbul ignore next */ []));
3586
+ grid = computed(() => this.layout() === 'grid', ...(ngDevMode ? [{ debugName: "grid" }] : /* istanbul ignore next */ []));
3587
+ keyed = signal(false, ...(ngDevMode ? [{ debugName: "keyed" }] : /* istanbul ignore next */ []));
3588
+ pointed = computed(() => this.searchable() || this.keyed(), ...(ngDevMode ? [{ debugName: "pointed" }] : /* istanbul ignore next */ []));
3425
3589
  searchBox = viewChild('searchBox', ...(ngDevMode ? [{ debugName: "searchBox" }] : /* istanbul ignore next */ []));
3426
3590
  root = viewChild.required('root');
3427
3591
  visible = computed(() => {
@@ -3448,7 +3612,7 @@ class NucleusMenu {
3448
3612
  queueMicrotask(() => this.focusEntry());
3449
3613
  }
3450
3614
  isActive(row) {
3451
- return row.id === this.activeId();
3615
+ return this.pointed() && row.id === this.activeId();
3452
3616
  }
3453
3617
  onTerm(value) {
3454
3618
  this.term.set(value);
@@ -3464,12 +3628,15 @@ class NucleusMenu {
3464
3628
  this.dismiss.emit();
3465
3629
  return;
3466
3630
  }
3467
- if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
3631
+ const move = this.moveOf(event.key);
3632
+ if (move) {
3468
3633
  event.preventDefault();
3469
- this.step(event.key === 'ArrowDown' ? 1 : -1);
3634
+ if (this.pointed())
3635
+ this.step(move);
3636
+ this.keyed.set(true);
3470
3637
  return;
3471
3638
  }
3472
- if (event.key === 'Enter') {
3639
+ if (event.key === 'Enter' && this.pointed()) {
3473
3640
  const row = this.reachable().find((item) => item.id === this.activeId());
3474
3641
  if (!row)
3475
3642
  return;
@@ -3477,15 +3644,41 @@ class NucleusMenu {
3477
3644
  this.choose(row);
3478
3645
  }
3479
3646
  }
3480
- step(delta) {
3647
+ moveOf(key) {
3648
+ const grid = this.grid();
3649
+ const jump = grid ? this.columns() : 1;
3650
+ if (key === 'ArrowDown')
3651
+ return { delta: jump, wrap: !grid };
3652
+ if (key === 'ArrowUp')
3653
+ return { delta: -jump, wrap: !grid };
3654
+ if (!grid || this.term())
3655
+ return null;
3656
+ if (key === 'ArrowRight')
3657
+ return { delta: 1, wrap: true };
3658
+ if (key === 'ArrowLeft')
3659
+ return { delta: -1, wrap: true };
3660
+ return null;
3661
+ }
3662
+ step(move) {
3481
3663
  const rows = this.reachable();
3482
3664
  if (!rows.length)
3483
3665
  return;
3484
3666
  const index = rows.findIndex((row) => row.id === this.activeId());
3485
- const next = (index + delta + rows.length) % rows.length;
3667
+ const next = this.landing(index, move, rows.length);
3486
3668
  this.activeId.set(rows[next].id);
3487
3669
  this.scrollIntoView(rows[next].id);
3488
3670
  }
3671
+ landing(index, move, size) {
3672
+ const target = index + move.delta;
3673
+ if (move.wrap)
3674
+ return (target + size) % size;
3675
+ if (target < 0)
3676
+ return Math.max(index, 0);
3677
+ if (target < size)
3678
+ return target;
3679
+ const lastRowStart = size - 1 - ((size - 1) % move.delta);
3680
+ return index < lastRowStart ? size - 1 : index;
3681
+ }
3489
3682
  scrollIntoView(id) {
3490
3683
  const target = this.root().nativeElement.querySelector(`[data-row="${id}"]`);
3491
3684
  target?.scrollIntoView({ block: 'nearest' });
@@ -3499,15 +3692,16 @@ class NucleusMenu {
3499
3692
  this.root().nativeElement.focus();
3500
3693
  }
3501
3694
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
3502
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusMenu, isStandalone: true, selector: "nucleus-menu", inputs: { sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, keyboardHint: { classPropertyName: "keyboardHint", publicName: "keyboardHint", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select", dismiss: "dismiss" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "style.width.px": "width()" } }, viewQueries: [{ propertyName: "searchBox", first: true, predicate: ["searchBox"], descendants: true, isSignal: true }, { propertyName: "root", first: true, predicate: ["root"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"menu\" #root tabindex=\"-1\">\n @if (heading()) {\n <div class=\"menu-head\">\n <h4>{{ heading() }}</h4>\n @if (badge(); as count) {\n <span class=\"menu-badge\">{{ count }}</span>\n }\n </div>\n }\n\n @if (showSearch()) {\n <div class=\"menu-search\">\n <label class=\"menu-field\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n #searchBox\n type=\"text\"\n autocomplete=\"off\"\n [attr.aria-label]=\"searchPlaceholder()\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"term()\"\n (input)=\"onTerm($any($event.target).value)\"\n />\n </label>\n </div>\n }\n\n <div class=\"menu-body\" role=\"listbox\" [attr.aria-label]=\"heading()\">\n @if (isEmpty()) {\n <p class=\"menu-empty\">{{ emptyText() }}</p>\n }\n\n @for (section of visible(); track section.id) {\n @if (section.rows.length) {\n @if (section.label) {\n <p class=\"menu-section\">{{ section.label }}</p>\n }\n\n @for (row of section.rows; track row.id) {\n <button\n type=\"button\"\n class=\"menu-row\"\n role=\"option\"\n [attr.data-row]=\"row.id\"\n [class.is-current]=\"row.current\"\n [class.is-locked]=\"row.disabled\"\n [class.is-active]=\"isActive(row)\"\n [attr.aria-selected]=\"isActive(row)\"\n [disabled]=\"row.disabled || row.current\"\n (click)=\"choose(row)\"\n >\n @if (row.tile; as tile) {\n <span\n class=\"menu-tile\"\n [class.is-ghost]=\"tile.ghost\"\n [style.background]=\"tile.ghost ? null : tile.color\"\n [style.color]=\"tile.ghost ? null : tile.ink\"\n aria-hidden=\"true\"\n >\n @if (tile.icon) {\n <i [class]=\"tile.icon\"></i>\n } @else {\n {{ tile.label }}\n }\n </span>\n }\n\n <span class=\"menu-text\">\n <span class=\"menu-name\">{{ row.name }}</span>\n @if (row.meta) {\n <span class=\"menu-meta\">{{ row.meta }}</span>\n }\n </span>\n\n <span class=\"menu-end\">\n @if (row.tag) {\n <span class=\"menu-tag\" [class.is-current]=\"row.current\">{{ row.tag }}</span>\n } @else if (!row.disabled && !row.current) {\n <i class=\"pi pi-chevron-right menu-chevron\" aria-hidden=\"true\"></i>\n }\n </span>\n </button>\n }\n }\n }\n </div>\n\n @if (showSearch() && keyboardHint()) {\n <p class=\"menu-foot\">{{ keyboardHint() }}</p>\n }\n</div>\n", styles: [":host{display:block}.menu{display:flex;flex-direction:column;min-width:0}.menu:focus-visible{outline:none}.menu-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 15px 10px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.menu-head h4{margin:0;overflow:hidden;color:var(--ns-header-ink);font-size:11px;font-weight:600;letter-spacing:.08em;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.menu-badge{flex:none;padding:1px 8px;border-radius:var(--ac-radius-pill);background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:10px;font-variant-numeric:tabular-nums}.menu-search{padding:9px 10px;border-bottom:1px solid var(--ac-border)}.menu-field{position:relative;display:block}.menu-field i{position:absolute;top:50%;left:11px;color:var(--ac-text-muted);font-size:12px;pointer-events:none;transform:translateY(-50%)}.menu-field input{width:100%;box-sizing:border-box;padding:7px 10px 7px 31px;border:1px solid var(--ac-border);border-radius:7px;background:var(--ac-bg);color:var(--ac-text);font:inherit;font-size:13px}.menu-field input::placeholder{color:var(--ac-text-muted)}.menu-field input:focus-visible{border-color:var(--ac-accent);outline:2px solid color-mix(in srgb,var(--ac-accent) 45%,transparent);outline-offset:1px}.menu-body{display:flex;max-height:348px;flex-direction:column;gap:1px;padding:6px;overflow-y:auto}.menu-section{margin:0;padding:11px 9px 5px;color:var(--ac-text-muted);font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.menu-empty{margin:0;padding:26px 14px;color:var(--ac-text-muted);font-size:12px;text-align:center}.menu-row{display:flex;width:100%;align-items:center;gap:11px;padding:9px 10px;border:0;border-radius:8px;background:transparent;color:var(--ac-text);font:inherit;text-align:left;cursor:pointer}.menu-row:hover:not(:disabled),.menu-row.is-active:not(:disabled){background:var(--ns-accent-wash);box-shadow:inset 2px 0 0 var(--ac-accent)}.menu-row:focus-visible{outline:none}.menu-row.is-current{background:var(--ac-surface-alt);box-shadow:none;cursor:default}.menu-row.is-locked{cursor:default;opacity:.55}.menu-tile{display:inline-flex;width:34px;height:34px;flex:none;align-items:center;justify-content:center;border-radius:9px;font-size:11.5px;font-weight:600;letter-spacing:.02em}.menu-tile i{font-size:14px}.menu-tile.is-ghost{background:var(--ac-surface-alt);color:var(--ac-text-muted)}.menu-row:hover:not(:disabled) .menu-tile.is-ghost,.menu-row.is-active:not(:disabled) .menu-tile.is-ghost{color:var(--ac-accent)}.menu-text{display:flex;min-width:0;flex-direction:column;gap:1px}.menu-name{overflow:hidden;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.menu-meta{overflow:hidden;color:var(--ac-text-muted);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.menu-end{display:flex;flex:none;align-items:center;margin-left:auto}.menu-chevron{color:var(--ac-accent);font-size:11px;opacity:0}.menu-row:hover:not(:disabled) .menu-chevron,.menu-row.is-active:not(:disabled) .menu-chevron{opacity:1}.menu-tag{padding:2px 7px;border-radius:4px;background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:9.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}.menu-tag.is-current{background:color-mix(in srgb,var(--ac-accent) 16%,transparent);color:var(--ac-accent)}.menu-foot{margin:0;padding:8px 14px;border-top:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:10.5px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3695
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusMenu, isStandalone: true, selector: "nucleus-menu", inputs: { sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, keyboardHint: { classPropertyName: "keyboardHint", publicName: "keyboardHint", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select", dismiss: "dismiss" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "style.width.px": "width()", "style.--menu-columns": "columns()" } }, viewQueries: [{ propertyName: "searchBox", first: true, predicate: ["searchBox"], descendants: true, isSignal: true }, { propertyName: "root", first: true, predicate: ["root"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"menu\" #root tabindex=\"-1\" [class.is-grid]=\"grid()\">\n @if (heading() && !grid()) {\n <div class=\"menu-head\">\n <h4>{{ heading() }}</h4>\n @if (badge(); as count) {\n <span class=\"menu-badge\">{{ count }}</span>\n }\n </div>\n }\n\n @if (showSearch()) {\n <div class=\"menu-search\">\n <label class=\"menu-field\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n #searchBox\n type=\"text\"\n autocomplete=\"off\"\n [attr.aria-label]=\"searchPlaceholder()\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"term()\"\n (input)=\"onTerm($any($event.target).value)\"\n />\n </label>\n </div>\n }\n\n <div class=\"menu-body\" role=\"listbox\" [attr.aria-label]=\"heading()\">\n @if (isEmpty()) {\n <p class=\"menu-empty\">{{ emptyText() }}</p>\n }\n\n @for (section of visible(); track section.id) {\n @if (section.rows.length) {\n @if (section.label) {\n <p class=\"menu-section\">\n {{ section.label }}\n @if (grid()) {\n <span class=\"menu-count\">{{ section.rows.length }}</span>\n }\n </p>\n }\n\n <div class=\"menu-group\" role=\"group\" [attr.aria-label]=\"section.label\">\n @for (row of section.rows; track row.id) {\n <button\n type=\"button\"\n class=\"menu-row\"\n role=\"option\"\n [attr.data-row]=\"row.id\"\n [attr.title]=\"grid() && row.disabled ? row.tag : null\"\n [class.is-current]=\"row.current\"\n [class.is-locked]=\"row.disabled\"\n [class.is-active]=\"isActive(row)\"\n [attr.aria-selected]=\"isActive(row)\"\n [disabled]=\"row.disabled || row.current\"\n (click)=\"choose(row)\"\n >\n @if (row.tile; as tile) {\n <span\n class=\"menu-tile\"\n [class.is-ghost]=\"tile.ghost\"\n [class.is-outline]=\"grid() && row.disabled\"\n [style.background]=\"tile.ghost || (grid() && row.disabled) ? null : tile.color\"\n [style.color]=\"tile.ghost || (grid() && row.disabled) ? null : tile.ink\"\n aria-hidden=\"true\"\n >\n @if (tile.icon) {\n <i [class]=\"tile.icon\"></i>\n } @else {\n {{ tile.label }}\n }\n </span>\n }\n\n <span class=\"menu-text\">\n <span class=\"menu-name\">{{ row.name }}</span>\n @if (grid() && row.current && row.tag) {\n <span class=\"menu-meta\">{{ row.tag }}</span>\n } @else if (!grid() && row.meta) {\n <span class=\"menu-meta\">{{ row.meta }}</span>\n }\n </span>\n\n @if (grid() && row.current) {\n <span class=\"menu-end\">\n <span class=\"menu-dot\" aria-hidden=\"true\"></span>\n </span>\n } @else if (!grid()) {\n <span class=\"menu-end\">\n @if (row.tag) {\n <span class=\"menu-tag\" [class.is-current]=\"row.current\">{{ row.tag }}</span>\n } @else if (!row.disabled && !row.current) {\n <i class=\"pi pi-chevron-right menu-chevron\" aria-hidden=\"true\"></i>\n }\n </span>\n }\n </button>\n }\n </div>\n }\n }\n </div>\n\n @if (showSearch() && keyboardHint()) {\n <p class=\"menu-foot\">{{ keyboardHint() }}</p>\n }\n</div>\n", styles: [":host{display:block;max-width:calc(100vw - 24px)}.menu{display:flex;flex-direction:column;min-width:0}.menu:focus-visible{outline:none}.menu-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 15px 10px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.menu-head h4{margin:0;overflow:hidden;color:var(--ns-header-ink);font-size:11px;font-weight:var(--ns-weight-heading);letter-spacing:.08em;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.menu-badge{flex:none;padding:1px 8px;border-radius:var(--ac-radius-pill);background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:10px;font-variant-numeric:tabular-nums}.menu-search{padding:9px 10px;border-bottom:1px solid var(--ac-border)}.menu-field{position:relative;display:block}.menu-field i{position:absolute;top:50%;left:11px;color:var(--ac-text-muted);font-size:12px;pointer-events:none;transform:translateY(-50%)}.menu-field input{width:100%;box-sizing:border-box;padding:7px 10px 7px 31px;border:1px solid var(--ac-border);border-radius:7px;background:var(--ac-bg);color:var(--ac-text);font:inherit;font-size:13px}.menu-field input::placeholder{color:var(--ac-text-muted)}.menu-field input:focus-visible{border-color:var(--ac-accent);outline:2px solid color-mix(in srgb,var(--ac-accent) 45%,transparent);outline-offset:1px}.menu-body{display:flex;max-height:348px;flex-direction:column;gap:1px;padding:6px;overflow-y:auto}.menu-section{margin:0;padding:11px 9px 5px;color:var(--ac-text-muted);font-size:10px;font-weight:var(--ns-weight-heading);letter-spacing:.08em;text-transform:uppercase}.menu-count:before{margin:0 5px;content:\"\\b7\"}.menu-group{display:flex;flex-direction:column;gap:1px}.menu-empty{margin:0;padding:26px 14px;color:var(--ac-text-muted);font-size:12px;text-align:center}.menu-row{display:flex;width:100%;align-items:center;gap:11px;padding:9px 10px;border:1px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text);font:inherit;text-align:left;cursor:pointer}.menu-row:hover:not(:disabled),.menu-row.is-active:not(:disabled){border-color:color-mix(in srgb,var(--ac-accent) 38%,transparent);background:var(--ns-accent-wash)}.menu-row:focus-visible{outline:none}.menu-row.is-current{background:var(--ac-surface-alt);cursor:default}.menu-row.is-locked{cursor:default;opacity:.55}.menu-tile{display:inline-flex;width:34px;height:34px;flex:none;align-items:center;justify-content:center;border-radius:9px;font-size:11.5px;font-weight:var(--ns-weight-heading);letter-spacing:.02em}.menu-tile i{font-size:14px}.menu-tile.is-ghost{background:var(--ac-surface-alt);color:var(--ac-text-muted)}.menu-row:hover:not(:disabled) .menu-tile.is-ghost,.menu-row.is-active:not(:disabled) .menu-tile.is-ghost{color:var(--ac-accent)}.menu-text{display:flex;min-width:0;flex-direction:column;gap:1px}.menu-name{overflow:hidden;font-size:13px;font-weight:var(--ns-weight-emphasis);text-overflow:ellipsis;white-space:nowrap}.menu-meta{overflow:hidden;color:var(--ac-text-muted);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.menu-end{display:flex;flex:none;align-items:center;margin-left:auto}.menu-chevron{color:var(--ac-accent);font-size:11px;opacity:0}.menu-row:hover:not(:disabled) .menu-chevron,.menu-row.is-active:not(:disabled) .menu-chevron{opacity:1}.menu-tag{padding:2px 7px;border-radius:4px;background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:9.5px;font-weight:var(--ns-weight-heading);letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}.menu-tag.is-current{background:color-mix(in srgb,var(--ac-accent) 16%,transparent);color:var(--ac-accent)}.menu-foot{margin:0;padding:8px 14px;border-top:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:10.5px}.menu-dot{width:8px;height:8px;border-radius:var(--ac-radius-pill);background:var(--ns-success)}.menu.is-grid .menu-search{padding:10px 10px 0;border-bottom:0}.menu.is-grid .menu-body{max-height:min(540px,calc(100dvh - 190px));gap:2px;padding:10px}.menu.is-grid .menu-section{padding:12px 6px 6px}.menu.is-grid .menu-group{display:grid;grid-template-columns:repeat(var(--menu-columns, 3),minmax(0,1fr));gap:4px}.menu.is-grid .menu-row{flex-direction:column;gap:7px;padding:11px 6px 9px;text-align:center}.menu.is-grid .menu-row.is-locked{opacity:1}.menu.is-grid .menu-tile{width:40px;height:40px;border-radius:11px;font-size:12px}.menu.is-grid .menu-tile i{font-size:16px}.menu.is-grid .menu-tile.is-outline{border:1px dashed color-mix(in srgb,var(--ac-text-muted) 55%,transparent);background:transparent;color:var(--ac-text-muted)}.menu.is-grid .menu-text{width:100%;align-items:center}.menu.is-grid .menu-name{display:-webkit-box;max-width:100%;font-size:12px;line-height:1.25;white-space:normal;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.menu.is-grid .menu-row.is-locked .menu-name{color:var(--ac-text-muted);font-weight:var(--ns-weight-text)}.menu.is-grid .menu-row.is-current{grid-column:1 / -1;flex-direction:row;gap:12px;padding:10px 12px;background:var(--ac-text);color:var(--ac-surface);text-align:left}.menu.is-grid .menu-row.is-current .menu-tile{width:36px;height:36px;border-radius:10px}.menu.is-grid .menu-row.is-current .menu-text{width:auto;align-items:flex-start}.menu.is-grid .menu-row.is-current .menu-name{display:block;font-size:13px;white-space:nowrap}.menu.is-grid .menu-row.is-current .menu-meta{color:color-mix(in srgb,currentColor 64%,transparent)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3503
3696
  }
3504
3697
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusMenu, decorators: [{
3505
3698
  type: Component,
3506
3699
  args: [{ selector: 'nucleus-menu', host: {
3507
3700
  '[style.width.px]': 'width()',
3701
+ '[style.--menu-columns]': 'columns()',
3508
3702
  '(keydown)': 'onKeydown($event)',
3509
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"menu\" #root tabindex=\"-1\">\n @if (heading()) {\n <div class=\"menu-head\">\n <h4>{{ heading() }}</h4>\n @if (badge(); as count) {\n <span class=\"menu-badge\">{{ count }}</span>\n }\n </div>\n }\n\n @if (showSearch()) {\n <div class=\"menu-search\">\n <label class=\"menu-field\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n #searchBox\n type=\"text\"\n autocomplete=\"off\"\n [attr.aria-label]=\"searchPlaceholder()\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"term()\"\n (input)=\"onTerm($any($event.target).value)\"\n />\n </label>\n </div>\n }\n\n <div class=\"menu-body\" role=\"listbox\" [attr.aria-label]=\"heading()\">\n @if (isEmpty()) {\n <p class=\"menu-empty\">{{ emptyText() }}</p>\n }\n\n @for (section of visible(); track section.id) {\n @if (section.rows.length) {\n @if (section.label) {\n <p class=\"menu-section\">{{ section.label }}</p>\n }\n\n @for (row of section.rows; track row.id) {\n <button\n type=\"button\"\n class=\"menu-row\"\n role=\"option\"\n [attr.data-row]=\"row.id\"\n [class.is-current]=\"row.current\"\n [class.is-locked]=\"row.disabled\"\n [class.is-active]=\"isActive(row)\"\n [attr.aria-selected]=\"isActive(row)\"\n [disabled]=\"row.disabled || row.current\"\n (click)=\"choose(row)\"\n >\n @if (row.tile; as tile) {\n <span\n class=\"menu-tile\"\n [class.is-ghost]=\"tile.ghost\"\n [style.background]=\"tile.ghost ? null : tile.color\"\n [style.color]=\"tile.ghost ? null : tile.ink\"\n aria-hidden=\"true\"\n >\n @if (tile.icon) {\n <i [class]=\"tile.icon\"></i>\n } @else {\n {{ tile.label }}\n }\n </span>\n }\n\n <span class=\"menu-text\">\n <span class=\"menu-name\">{{ row.name }}</span>\n @if (row.meta) {\n <span class=\"menu-meta\">{{ row.meta }}</span>\n }\n </span>\n\n <span class=\"menu-end\">\n @if (row.tag) {\n <span class=\"menu-tag\" [class.is-current]=\"row.current\">{{ row.tag }}</span>\n } @else if (!row.disabled && !row.current) {\n <i class=\"pi pi-chevron-right menu-chevron\" aria-hidden=\"true\"></i>\n }\n </span>\n </button>\n }\n }\n }\n </div>\n\n @if (showSearch() && keyboardHint()) {\n <p class=\"menu-foot\">{{ keyboardHint() }}</p>\n }\n</div>\n", styles: [":host{display:block}.menu{display:flex;flex-direction:column;min-width:0}.menu:focus-visible{outline:none}.menu-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 15px 10px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.menu-head h4{margin:0;overflow:hidden;color:var(--ns-header-ink);font-size:11px;font-weight:600;letter-spacing:.08em;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.menu-badge{flex:none;padding:1px 8px;border-radius:var(--ac-radius-pill);background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:10px;font-variant-numeric:tabular-nums}.menu-search{padding:9px 10px;border-bottom:1px solid var(--ac-border)}.menu-field{position:relative;display:block}.menu-field i{position:absolute;top:50%;left:11px;color:var(--ac-text-muted);font-size:12px;pointer-events:none;transform:translateY(-50%)}.menu-field input{width:100%;box-sizing:border-box;padding:7px 10px 7px 31px;border:1px solid var(--ac-border);border-radius:7px;background:var(--ac-bg);color:var(--ac-text);font:inherit;font-size:13px}.menu-field input::placeholder{color:var(--ac-text-muted)}.menu-field input:focus-visible{border-color:var(--ac-accent);outline:2px solid color-mix(in srgb,var(--ac-accent) 45%,transparent);outline-offset:1px}.menu-body{display:flex;max-height:348px;flex-direction:column;gap:1px;padding:6px;overflow-y:auto}.menu-section{margin:0;padding:11px 9px 5px;color:var(--ac-text-muted);font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.menu-empty{margin:0;padding:26px 14px;color:var(--ac-text-muted);font-size:12px;text-align:center}.menu-row{display:flex;width:100%;align-items:center;gap:11px;padding:9px 10px;border:0;border-radius:8px;background:transparent;color:var(--ac-text);font:inherit;text-align:left;cursor:pointer}.menu-row:hover:not(:disabled),.menu-row.is-active:not(:disabled){background:var(--ns-accent-wash);box-shadow:inset 2px 0 0 var(--ac-accent)}.menu-row:focus-visible{outline:none}.menu-row.is-current{background:var(--ac-surface-alt);box-shadow:none;cursor:default}.menu-row.is-locked{cursor:default;opacity:.55}.menu-tile{display:inline-flex;width:34px;height:34px;flex:none;align-items:center;justify-content:center;border-radius:9px;font-size:11.5px;font-weight:600;letter-spacing:.02em}.menu-tile i{font-size:14px}.menu-tile.is-ghost{background:var(--ac-surface-alt);color:var(--ac-text-muted)}.menu-row:hover:not(:disabled) .menu-tile.is-ghost,.menu-row.is-active:not(:disabled) .menu-tile.is-ghost{color:var(--ac-accent)}.menu-text{display:flex;min-width:0;flex-direction:column;gap:1px}.menu-name{overflow:hidden;font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.menu-meta{overflow:hidden;color:var(--ac-text-muted);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.menu-end{display:flex;flex:none;align-items:center;margin-left:auto}.menu-chevron{color:var(--ac-accent);font-size:11px;opacity:0}.menu-row:hover:not(:disabled) .menu-chevron,.menu-row.is-active:not(:disabled) .menu-chevron{opacity:1}.menu-tag{padding:2px 7px;border-radius:4px;background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:9.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}.menu-tag.is-current{background:color-mix(in srgb,var(--ac-accent) 16%,transparent);color:var(--ac-accent)}.menu-foot{margin:0;padding:8px 14px;border-top:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:10.5px}\n"] }]
3510
- }], ctorParameters: () => [], propDecorators: { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], keyboardHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardHint", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], searchBox: [{ type: i0.ViewChild, args: ['searchBox', { isSignal: true }] }], root: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }] } });
3703
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"menu\" #root tabindex=\"-1\" [class.is-grid]=\"grid()\">\n @if (heading() && !grid()) {\n <div class=\"menu-head\">\n <h4>{{ heading() }}</h4>\n @if (badge(); as count) {\n <span class=\"menu-badge\">{{ count }}</span>\n }\n </div>\n }\n\n @if (showSearch()) {\n <div class=\"menu-search\">\n <label class=\"menu-field\">\n <i class=\"pi pi-search\" aria-hidden=\"true\"></i>\n <input\n #searchBox\n type=\"text\"\n autocomplete=\"off\"\n [attr.aria-label]=\"searchPlaceholder()\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"term()\"\n (input)=\"onTerm($any($event.target).value)\"\n />\n </label>\n </div>\n }\n\n <div class=\"menu-body\" role=\"listbox\" [attr.aria-label]=\"heading()\">\n @if (isEmpty()) {\n <p class=\"menu-empty\">{{ emptyText() }}</p>\n }\n\n @for (section of visible(); track section.id) {\n @if (section.rows.length) {\n @if (section.label) {\n <p class=\"menu-section\">\n {{ section.label }}\n @if (grid()) {\n <span class=\"menu-count\">{{ section.rows.length }}</span>\n }\n </p>\n }\n\n <div class=\"menu-group\" role=\"group\" [attr.aria-label]=\"section.label\">\n @for (row of section.rows; track row.id) {\n <button\n type=\"button\"\n class=\"menu-row\"\n role=\"option\"\n [attr.data-row]=\"row.id\"\n [attr.title]=\"grid() && row.disabled ? row.tag : null\"\n [class.is-current]=\"row.current\"\n [class.is-locked]=\"row.disabled\"\n [class.is-active]=\"isActive(row)\"\n [attr.aria-selected]=\"isActive(row)\"\n [disabled]=\"row.disabled || row.current\"\n (click)=\"choose(row)\"\n >\n @if (row.tile; as tile) {\n <span\n class=\"menu-tile\"\n [class.is-ghost]=\"tile.ghost\"\n [class.is-outline]=\"grid() && row.disabled\"\n [style.background]=\"tile.ghost || (grid() && row.disabled) ? null : tile.color\"\n [style.color]=\"tile.ghost || (grid() && row.disabled) ? null : tile.ink\"\n aria-hidden=\"true\"\n >\n @if (tile.icon) {\n <i [class]=\"tile.icon\"></i>\n } @else {\n {{ tile.label }}\n }\n </span>\n }\n\n <span class=\"menu-text\">\n <span class=\"menu-name\">{{ row.name }}</span>\n @if (grid() && row.current && row.tag) {\n <span class=\"menu-meta\">{{ row.tag }}</span>\n } @else if (!grid() && row.meta) {\n <span class=\"menu-meta\">{{ row.meta }}</span>\n }\n </span>\n\n @if (grid() && row.current) {\n <span class=\"menu-end\">\n <span class=\"menu-dot\" aria-hidden=\"true\"></span>\n </span>\n } @else if (!grid()) {\n <span class=\"menu-end\">\n @if (row.tag) {\n <span class=\"menu-tag\" [class.is-current]=\"row.current\">{{ row.tag }}</span>\n } @else if (!row.disabled && !row.current) {\n <i class=\"pi pi-chevron-right menu-chevron\" aria-hidden=\"true\"></i>\n }\n </span>\n }\n </button>\n }\n </div>\n }\n }\n </div>\n\n @if (showSearch() && keyboardHint()) {\n <p class=\"menu-foot\">{{ keyboardHint() }}</p>\n }\n</div>\n", styles: [":host{display:block;max-width:calc(100vw - 24px)}.menu{display:flex;flex-direction:column;min-width:0}.menu:focus-visible{outline:none}.menu-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 15px 10px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.menu-head h4{margin:0;overflow:hidden;color:var(--ns-header-ink);font-size:11px;font-weight:var(--ns-weight-heading);letter-spacing:.08em;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}.menu-badge{flex:none;padding:1px 8px;border-radius:var(--ac-radius-pill);background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:10px;font-variant-numeric:tabular-nums}.menu-search{padding:9px 10px;border-bottom:1px solid var(--ac-border)}.menu-field{position:relative;display:block}.menu-field i{position:absolute;top:50%;left:11px;color:var(--ac-text-muted);font-size:12px;pointer-events:none;transform:translateY(-50%)}.menu-field input{width:100%;box-sizing:border-box;padding:7px 10px 7px 31px;border:1px solid var(--ac-border);border-radius:7px;background:var(--ac-bg);color:var(--ac-text);font:inherit;font-size:13px}.menu-field input::placeholder{color:var(--ac-text-muted)}.menu-field input:focus-visible{border-color:var(--ac-accent);outline:2px solid color-mix(in srgb,var(--ac-accent) 45%,transparent);outline-offset:1px}.menu-body{display:flex;max-height:348px;flex-direction:column;gap:1px;padding:6px;overflow-y:auto}.menu-section{margin:0;padding:11px 9px 5px;color:var(--ac-text-muted);font-size:10px;font-weight:var(--ns-weight-heading);letter-spacing:.08em;text-transform:uppercase}.menu-count:before{margin:0 5px;content:\"\\b7\"}.menu-group{display:flex;flex-direction:column;gap:1px}.menu-empty{margin:0;padding:26px 14px;color:var(--ac-text-muted);font-size:12px;text-align:center}.menu-row{display:flex;width:100%;align-items:center;gap:11px;padding:9px 10px;border:1px solid transparent;border-radius:10px;background:transparent;color:var(--ac-text);font:inherit;text-align:left;cursor:pointer}.menu-row:hover:not(:disabled),.menu-row.is-active:not(:disabled){border-color:color-mix(in srgb,var(--ac-accent) 38%,transparent);background:var(--ns-accent-wash)}.menu-row:focus-visible{outline:none}.menu-row.is-current{background:var(--ac-surface-alt);cursor:default}.menu-row.is-locked{cursor:default;opacity:.55}.menu-tile{display:inline-flex;width:34px;height:34px;flex:none;align-items:center;justify-content:center;border-radius:9px;font-size:11.5px;font-weight:var(--ns-weight-heading);letter-spacing:.02em}.menu-tile i{font-size:14px}.menu-tile.is-ghost{background:var(--ac-surface-alt);color:var(--ac-text-muted)}.menu-row:hover:not(:disabled) .menu-tile.is-ghost,.menu-row.is-active:not(:disabled) .menu-tile.is-ghost{color:var(--ac-accent)}.menu-text{display:flex;min-width:0;flex-direction:column;gap:1px}.menu-name{overflow:hidden;font-size:13px;font-weight:var(--ns-weight-emphasis);text-overflow:ellipsis;white-space:nowrap}.menu-meta{overflow:hidden;color:var(--ac-text-muted);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.menu-end{display:flex;flex:none;align-items:center;margin-left:auto}.menu-chevron{color:var(--ac-accent);font-size:11px;opacity:0}.menu-row:hover:not(:disabled) .menu-chevron,.menu-row.is-active:not(:disabled) .menu-chevron{opacity:1}.menu-tag{padding:2px 7px;border-radius:4px;background:var(--ac-surface-alt);color:var(--ac-text-muted);font-size:9.5px;font-weight:var(--ns-weight-heading);letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}.menu-tag.is-current{background:color-mix(in srgb,var(--ac-accent) 16%,transparent);color:var(--ac-accent)}.menu-foot{margin:0;padding:8px 14px;border-top:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:10.5px}.menu-dot{width:8px;height:8px;border-radius:var(--ac-radius-pill);background:var(--ns-success)}.menu.is-grid .menu-search{padding:10px 10px 0;border-bottom:0}.menu.is-grid .menu-body{max-height:min(540px,calc(100dvh - 190px));gap:2px;padding:10px}.menu.is-grid .menu-section{padding:12px 6px 6px}.menu.is-grid .menu-group{display:grid;grid-template-columns:repeat(var(--menu-columns, 3),minmax(0,1fr));gap:4px}.menu.is-grid .menu-row{flex-direction:column;gap:7px;padding:11px 6px 9px;text-align:center}.menu.is-grid .menu-row.is-locked{opacity:1}.menu.is-grid .menu-tile{width:40px;height:40px;border-radius:11px;font-size:12px}.menu.is-grid .menu-tile i{font-size:16px}.menu.is-grid .menu-tile.is-outline{border:1px dashed color-mix(in srgb,var(--ac-text-muted) 55%,transparent);background:transparent;color:var(--ac-text-muted)}.menu.is-grid .menu-text{width:100%;align-items:center}.menu.is-grid .menu-name{display:-webkit-box;max-width:100%;font-size:12px;line-height:1.25;white-space:normal;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.menu.is-grid .menu-row.is-locked .menu-name{color:var(--ac-text-muted);font-weight:var(--ns-weight-text)}.menu.is-grid .menu-row.is-current{grid-column:1 / -1;flex-direction:row;gap:12px;padding:10px 12px;background:var(--ac-text);color:var(--ac-surface);text-align:left}.menu.is-grid .menu-row.is-current .menu-tile{width:36px;height:36px;border-radius:10px}.menu.is-grid .menu-row.is-current .menu-text{width:auto;align-items:flex-start}.menu.is-grid .menu-row.is-current .menu-name{display:block;font-size:13px;white-space:nowrap}.menu.is-grid .menu-row.is-current .menu-meta{color:color-mix(in srgb,currentColor 64%,transparent)}\n"] }]
3704
+ }], ctorParameters: () => [], propDecorators: { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], keyboardHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardHint", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], searchBox: [{ type: i0.ViewChild, args: ['searchBox', { isSignal: true }] }], root: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }] } });
3511
3705
 
3512
3706
  const STORAGE_KEY = 'nucleus_recent_apps';
3513
3707
  const KEEP = 8;
@@ -3656,11 +3850,10 @@ const SHELL_COPY = {
3656
3850
  appsSwitch: 'Cambiar de aplicación',
3657
3851
  appsSearch: 'Buscar aplicación',
3658
3852
  appsNoMatch: 'Ninguna aplicación coincide con lo que escribiste.',
3659
- appsRecent: 'Recientes',
3660
- appsAll: 'Todas',
3661
3853
  appsAvailable: 'Disponibles',
3662
- appsHere: 'Aquí',
3663
- keyboardHint: '↑ ↓ moverse · ↵ abrir · esc cerrar',
3854
+ appsUpcoming: 'En preparación',
3855
+ appsHere: 'Estás aquí',
3856
+ keyboardHint: '← ↑ ↓ → moverse · ↵ abrir · esc cerrar',
3664
3857
  accountSwitchHint: 'Entrar con otro correo',
3665
3858
  signOutHint: 'Salir de la suite',
3666
3859
  settingsTitle: 'Ajustes',
@@ -3693,11 +3886,10 @@ const SHELL_COPY = {
3693
3886
  appsSwitch: 'Switch application',
3694
3887
  appsSearch: 'Search applications',
3695
3888
  appsNoMatch: 'No application matches what you typed.',
3696
- appsRecent: 'Recent',
3697
- appsAll: 'All',
3698
3889
  appsAvailable: 'Available',
3699
- appsHere: 'Here',
3700
- keyboardHint: '↑ ↓ move · ↵ open · esc close',
3890
+ appsUpcoming: 'Coming soon',
3891
+ appsHere: 'You are here',
3892
+ keyboardHint: '← ↑ ↓ → move · ↵ open · esc close',
3701
3893
  accountSwitchHint: 'Sign in with another address',
3702
3894
  signOutHint: 'Leave the suite',
3703
3895
  settingsTitle: 'Settings',
@@ -3726,7 +3918,7 @@ const SHELL_COPY = {
3726
3918
  };
3727
3919
 
3728
3920
  const LAUNCHER_RICH_THRESHOLD = 6;
3729
- const RECENT_LIMIT = 3;
3921
+ const SUITE_PREFIX = 'Nucleus ';
3730
3922
  const FALLBACK_APP_COLOR = '#64748b';
3731
3923
  const HOME_MENU_ID = 'nucleus-home';
3732
3924
  class NucleusShell {
@@ -3818,41 +4010,30 @@ class NucleusShell {
3818
4010
  words = computed(() => commonCopyOf(this.lang()), ...(ngDevMode ? [{ debugName: "words" }] : /* istanbul ignore next */ []));
3819
4011
  hasSiteContext = computed(() => this.session.scope() === 'site', ...(ngDevMode ? [{ debugName: "hasSiteContext" }] : /* istanbul ignore next */ []));
3820
4012
  launcherRich = computed(() => this.launcherApps().length > LAUNCHER_RICH_THRESHOLD, ...(ngDevMode ? [{ debugName: "launcherRich" }] : /* istanbul ignore next */ []));
3821
- launcherCount = computed(() => {
3822
- const total = this.launcherApps().length + (this.session.currentApp() ? 1 : 0);
3823
- return total > LAUNCHER_RICH_THRESHOLD ? String(total) : null;
3824
- }, ...(ngDevMode ? [{ debugName: "launcherCount" }] : /* istanbul ignore next */ []));
3825
4013
  launcherSections = computed(() => {
3826
4014
  const t = this.copy();
3827
4015
  const apps = this.launcherApps();
3828
4016
  const current = this.session.currentApp();
4017
+ const open = apps.filter((app) => this.canOpen(app));
4018
+ const pending = apps.filter((app) => !this.canOpen(app));
3829
4019
  const sections = [];
3830
4020
  if (current) {
3831
4021
  sections.push({ id: 'current', label: null, rows: [this.appRow(current, true)] });
3832
4022
  }
3833
- if (!apps.length)
3834
- return sections;
3835
- if (this.launcherRich()) {
3836
- const recent = this.recents.pick(apps, RECENT_LIMIT);
3837
- if (recent.length) {
3838
- sections.push({
3839
- id: 'recent',
3840
- label: t.appsRecent,
3841
- rows: recent.map((app) => this.appRow(app, false)),
3842
- });
3843
- }
4023
+ if (open.length) {
3844
4024
  sections.push({
3845
- id: 'all',
3846
- label: t.appsAll,
3847
- rows: apps.map((app) => this.appRow(app, false)),
4025
+ id: 'available',
4026
+ label: t.appsAvailable,
4027
+ rows: open.map((app) => this.appRow(app, false)),
4028
+ });
4029
+ }
4030
+ if (pending.length) {
4031
+ sections.push({
4032
+ id: 'upcoming',
4033
+ label: t.appsUpcoming,
4034
+ rows: pending.map((app) => this.appRow(app, false)),
3848
4035
  });
3849
- return sections;
3850
4036
  }
3851
- sections.push({
3852
- id: 'all',
3853
- label: current ? t.appsAvailable : null,
3854
- rows: apps.map((app) => this.appRow(app, false)),
3855
- });
3856
4037
  return sections;
3857
4038
  }, ...(ngDevMode ? [{ debugName: "launcherSections" }] : /* istanbul ignore next */ []));
3858
4039
  accountSections = computed(() => {
@@ -4019,11 +4200,12 @@ class NucleusShell {
4019
4200
  }
4020
4201
  appRow(app, current) {
4021
4202
  const hint = current ? this.copy().appsHere : this.launchHint(app);
4203
+ const name = shortAppName(app.name);
4022
4204
  return {
4023
4205
  id: app.id,
4024
- name: app.name,
4206
+ name,
4025
4207
  meta: app.description,
4026
- tile: menuTile(initialsOf(app.name), app.icon, app.color ?? FALLBACK_APP_COLOR),
4208
+ tile: menuTile(initialsOf(name), app.icon, app.color ?? FALLBACK_APP_COLOR),
4027
4209
  tag: hint || null,
4028
4210
  current,
4029
4211
  disabled: !current && !this.canOpen(app),
@@ -4097,7 +4279,7 @@ class NucleusShell {
4097
4279
  }
4098
4280
  }
4099
4281
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
4100
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusShell, isStandalone: true, selector: "nucleus-shell", inputs: { brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, activeNavId: { classPropertyName: "activeNavId", publicName: "activeNavId", isSignal: true, isRequired: false, transformFunction: null }, selectedMenuId: { classPropertyName: "selectedMenuId", publicName: "selectedMenuId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navSelect: "navSelect", menuSelect: "menuSelect" }, host: { properties: { "style.--ns-topbar-h": "topbarHeight()" } }, ngImport: i0, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n [heading]=\"t.appsSwitch\"\n [badge]=\"launcherCount()\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"336\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:500;letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:600;letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:500;text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-frame-raised);box-shadow:inset 2px 0 0 var(--ns-frame-glow);color:var(--ns-frame-ink)}.nav-item.is-active i{color:var(--ns-frame-glow)}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:600}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{gap:10px;min-height:42px;padding:7px 12px}.page-head-main{gap:8px}.page-head h1{overflow:hidden;min-width:0;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.page-head-actions{flex-wrap:wrap;justify-content:flex-end;gap:6px}.page-head-actions ::ng-deep .p-button{padding-block:6px;padding-inline:11px;font-size:13px;white-space:nowrap}.page-head-actions ::ng-deep .p-button-icon{font-size:13px}}.who{display:flex;align-items:center;gap:12px;padding:15px 15px 13px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:600}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:var(--ac-text-muted);font-size:11.5px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:9px 15px;border-bottom:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:11.5px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:600}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:5px;height:5px;flex:none;border-radius:50%;background:var(--ac-accent)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:600}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:600}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:600}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;margin-bottom:10px;padding:9px 12px;border-left:2px solid var(--ns-frame-glow);border-radius:0 7px 7px 0;background:var(--ns-frame-raised);box-shadow:-2px 0 12px -3px color-mix(in srgb,var(--ns-frame-glow) 65%,transparent)}.role-badge>i{flex:none;color:var(--ns-frame-glow);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1$3.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: BreadcrumbModule }, { kind: "component", type: i2$4.Breadcrumb, selector: "p-breadcrumb", inputs: ["model", "style", "styleClass", "home", "homeAriaLabel"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ConfirmDialogModule }, { kind: "component", type: i4$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: ToastModule }, { kind: "component", type: i5$2.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6$2.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusAppearance, selector: "nucleus-appearance" }, { kind: "component", type: NucleusLordicon, selector: "nucleus-lordicon", inputs: ["src", "trigger", "state", "size", "tone"] }, { kind: "component", type: NucleusMenu, selector: "nucleus-menu", inputs: ["sections", "heading", "badge", "searchable", "searchPlaceholder", "emptyText", "keyboardHint", "width"], outputs: ["select", "dismiss"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4282
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: NucleusShell, isStandalone: true, selector: "nucleus-shell", inputs: { brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, activeNavId: { classPropertyName: "activeNavId", publicName: "activeNavId", isSignal: true, isRequired: false, transformFunction: null }, selectedMenuId: { classPropertyName: "selectedMenuId", publicName: "selectedMenuId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navSelect: "navSelect", menuSelect: "menuSelect" }, host: { properties: { "style.--ns-topbar-h": "topbarHeight()" } }, ngImport: i0, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n layout=\"grid\"\n [heading]=\"t.appsSwitch\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"384\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:var(--ns-weight-emphasis);letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:var(--ns-weight-emphasis);letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:var(--ns-weight-text);text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-nav-active-bg, var(--ns-frame-raised));color:var(--ns-nav-active-ink, var(--ns-frame-ink));font-weight:var(--ns-weight-emphasis)}.nav-item.is-active i{color:inherit}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:var(--ns-weight-heading)}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:var(--ns-weight-emphasis);letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{gap:10px;min-height:42px;padding:7px 12px}.page-head-main{gap:8px}.page-head h1{overflow:hidden;min-width:0;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.page-head-actions{flex-wrap:wrap;justify-content:flex-end;gap:6px}.page-head-actions ::ng-deep .p-button{padding-block:6px;padding-inline:11px;font-size:13px;white-space:nowrap}.page-head-actions ::ng-deep .p-button-icon{font-size:13px}}.who{display:flex;align-items:center;gap:12px;margin:6px 6px 0;padding:12px;border-radius:10px;background:var(--ac-text);color:var(--ac-surface)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:var(--ns-weight-emphasis)}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:var(--ns-weight-emphasis);text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:color-mix(in srgb,currentColor 64%,transparent);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:11px 17px 5px;color:var(--ac-text-muted);font-size:12px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:var(--ns-weight-emphasis)}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:7px;height:7px;flex:none;border-radius:50%;background:var(--ns-success)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:var(--ns-weight-emphasis)}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:var(--ns-weight-heading)}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:var(--ns-weight-emphasis)}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;padding:4px 12px 2px}.role-badge>i{flex:none;color:var(--ns-frame-muted);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:var(--ns-weight-emphasis);text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i1$3.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: BreadcrumbModule }, { kind: "component", type: i2$4.Breadcrumb, selector: "p-breadcrumb", inputs: ["model", "style", "styleClass", "home", "homeAriaLabel"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ConfirmDialogModule }, { kind: "component", type: i4$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: ToastModule }, { kind: "component", type: i5$2.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6$2.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i6$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NucleusAppearance, selector: "nucleus-appearance" }, { kind: "component", type: NucleusLordicon, selector: "nucleus-lordicon", inputs: ["src", "trigger", "state", "size", "tone"] }, { kind: "component", type: NucleusMenu, selector: "nucleus-menu", inputs: ["sections", "heading", "badge", "searchable", "searchPlaceholder", "emptyText", "keyboardHint", "width", "layout", "columns"], outputs: ["select", "dismiss"] }, { kind: "component", type: NucleusMark, selector: "nucleus-mark", inputs: ["accent", "size"] }, { kind: "component", type: NucleusStarfield, selector: "nucleus-starfield" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4101
4283
  }
4102
4284
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: NucleusShell, decorators: [{
4103
4285
  type: Component,
@@ -4120,8 +4302,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
4120
4302
  NucleusMenu,
4121
4303
  NucleusMark,
4122
4304
  NucleusStarfield,
4123
- ], host: { '[style.--ns-topbar-h]': 'topbarHeight()' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n [heading]=\"t.appsSwitch\"\n [badge]=\"launcherCount()\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"336\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:500;letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:600;letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:500;text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-frame-raised);box-shadow:inset 2px 0 0 var(--ns-frame-glow);color:var(--ns-frame-ink)}.nav-item.is-active i{color:var(--ns-frame-glow)}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:600}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:500;letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{gap:10px;min-height:42px;padding:7px 12px}.page-head-main{gap:8px}.page-head h1{overflow:hidden;min-width:0;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.page-head-actions{flex-wrap:wrap;justify-content:flex-end;gap:6px}.page-head-actions ::ng-deep .p-button{padding-block:6px;padding-inline:11px;font-size:13px;white-space:nowrap}.page-head-actions ::ng-deep .p-button-icon{font-size:13px}}.who{display:flex;align-items:center;gap:12px;padding:15px 15px 13px;border-bottom:1px solid var(--ac-border);background:var(--ns-header-bg)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:600}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:var(--ac-text-muted);font-size:11.5px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:9px 15px;border-bottom:1px solid var(--ac-border);color:var(--ac-text-muted);font-size:11.5px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:600}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:5px;height:5px;flex:none;border-radius:50%;background:var(--ac-accent)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:600}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:600}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:600}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;margin-bottom:10px;padding:9px 12px;border-left:2px solid var(--ns-frame-glow);border-radius:0 7px 7px 0;background:var(--ns-frame-raised);box-shadow:-2px 0 12px -3px color-mix(in srgb,var(--ns-frame-glow) 65%,transparent)}.role-badge>i{flex:none;color:var(--ns-frame-glow);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"] }]
4305
+ ], host: { '[style.--ns-topbar-h]': 'topbarHeight()' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let t = copy();\n@let me = identity();\n\n@if (starfield()) {\n <nucleus-starfield />\n}\n\n<header class=\"topbar ns-frame\">\n <div class=\"side\">\n <p-button\n icon=\"pi pi-bars\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.navToggle\"\n [pTooltip]=\"t.navToggle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"toggleSidebar()\"\n />\n\n <div class=\"brand\">\n <nucleus-mark [size]=\"20\" />\n <div class=\"brand-name\">\n <span class=\"brand-primary\">NUCLEUS</span>\n <span class=\"brand-secondary\">{{ brand() }}</span>\n </div>\n </div>\n\n </div>\n\n @if (hasSiteContext()) {\n <div class=\"context ns-context\">\n <p-select\n styleClass=\"context-select\"\n [options]=\"companyChoices()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"companyChoice()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [placeholder]=\"t.companyPlaceholder\"\n [disabled]=\"switching()\"\n [filter]=\"companyChoices().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.companyLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n <ng-template #item let-option>\n <span class=\"company-option\">\n <span class=\"company-name\">{{ option.name }}</span>\n <p-tag [value]=\"option.tag\" severity=\"secondary\" />\n </span>\n </ng-template>\n </p-select>\n\n <p-select\n styleClass=\"context-select\"\n [options]=\"siteOptions()\"\n optionValue=\"id\"\n optionLabel=\"name\"\n [ngModel]=\"siteChoice()\"\n (ngModelChange)=\"onSiteChange($event)\"\n [placeholder]=\"sitePlaceholder()\"\n [disabled]=\"switching() || sitesLoading() || !siteOptions().length\"\n [filter]=\"siteOptions().length > 8\"\n filterBy=\"name\"\n [filterPlaceholder]=\"words().search\"\n [autofocusFilter]=\"true\"\n [resetFilterOnHide]=\"true\"\n [ariaLabel]=\"t.siteLabel\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n }\n\n <div class=\"side is-end\">\n <div class=\"lang-switch\" role=\"group\" aria-label=\"Idioma / Language\">\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'es'\"\n [attr.aria-pressed]=\"lang() === 'es'\"\n (click)=\"setLang('es')\"\n >\n ES\n </button>\n <button\n type=\"button\"\n class=\"lang-pill\"\n [class.is-active]=\"lang() === 'en'\"\n [attr.aria-pressed]=\"lang() === 'en'\"\n (click)=\"setLang('en')\"\n >\n EN\n </button>\n </div>\n\n <p-button\n icon=\"pi pi-th-large\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.appsLauncher\"\n [pTooltip]=\"t.appsLauncher\"\n tooltipPosition=\"bottom\"\n (onClick)=\"launcher.toggle($event)\"\n />\n\n <p-popover #launcher styleClass=\"ns-flush-popover\">\n @if (!hasCompany()) {\n <div class=\"launcher-notice\">\n <i class=\"pi pi-building\" aria-hidden=\"true\"></i>\n <div>\n <p class=\"launcher-notice-title\">{{ t.noCompanyTitle }}</p>\n <p class=\"launcher-notice-body\">{{ t.noCompanyHint }}</p>\n </div>\n </div>\n }\n\n <nucleus-menu\n layout=\"grid\"\n [heading]=\"t.appsSwitch\"\n [sections]=\"launcherSections()\"\n [searchable]=\"launcherRich()\"\n [searchPlaceholder]=\"t.appsSearch\"\n [emptyText]=\"launcherRich() ? t.appsNoMatch : t.appsEmpty\"\n [keyboardHint]=\"t.keyboardHint\"\n [width]=\"384\"\n (select)=\"onLauncherSelect($event); launcher.hide()\"\n (dismiss)=\"launcher.hide()\"\n />\n </p-popover>\n\n <p-button\n icon=\"pi pi-cog\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n [ariaLabel]=\"t.settingsTitle\"\n [pTooltip]=\"t.settingsTitle\"\n tooltipPosition=\"bottom\"\n (onClick)=\"settingsOpen.set(true)\"\n />\n\n @if (me) {\n <p-button\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n [rounded]=\"true\"\n styleClass=\"avatar-trigger\"\n [ariaLabel]=\"me.name\"\n [pTooltip]=\"me.name\"\n tooltipPosition=\"bottom\"\n (onClick)=\"account.toggle($event)\"\n >\n <p-avatar\n [image]=\"me.photoUrl ?? undefined\"\n [label]=\"me.photoUrl ? undefined : initials()\"\n shape=\"circle\"\n size=\"normal\"\n />\n </p-button>\n }\n </div>\n</header>\n\n<p-popover #account styleClass=\"ns-flush-popover\">\n @if (me) {\n <div class=\"who\">\n @if (me.photoUrl) {\n <img class=\"who-photo\" [src]=\"me.photoUrl\" alt=\"\" width=\"42\" height=\"42\" />\n } @else {\n <span class=\"who-photo who-initials\">{{ initials() }}</span>\n }\n <span class=\"who-text\">\n <span class=\"who-name\">{{ me.name }}</span>\n <span class=\"who-mail\">{{ me.email }}</span>\n </span>\n </div>\n\n <p class=\"who-role\">\n <span class=\"who-dot\" aria-hidden=\"true\"></span>\n @if (roleName(); as role) {\n <b>{{ role }}</b>\n <span class=\"who-sep\">\u00B7</span>\n }\n <span class=\"who-context\">{{ accountContext() }}</span>\n </p>\n\n <nucleus-menu\n [sections]=\"accountSections()\"\n [width]=\"304\"\n (select)=\"onAccountSelect($event); account.hide()\"\n (dismiss)=\"account.hide()\"\n />\n }\n</p-popover>\n\n<div class=\"body\">\n @if (narrow() && sidebarOpen()) {\n <button\n type=\"button\"\n class=\"sidebar-scrim\"\n [attr.aria-label]=\"t.navToggle\"\n (click)=\"toggleSidebar()\"\n ></button>\n }\n\n <aside class=\"sidebar ns-frame\" [class.is-collapsed]=\"!sidebarOpen()\">\n @if (roleName(); as role) {\n <div class=\"role-badge\" [pTooltip]=\"sidebarOpen() ? '' : role\" tooltipPosition=\"right\">\n <i class=\"pi pi-key\" aria-hidden=\"true\"></i>\n <span class=\"nav-label role-text\">\n <span class=\"role-name\">{{ role }}</span>\n <span class=\"role-caption\">{{ t.roleCaption }}</span>\n </span>\n </div>\n }\n\n @if (navItems().length) {\n <nav>\n @for (item of navItems(); track item.id) {\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"activeNavId() === item.id\"\n [attr.aria-current]=\"activeNavId() === item.id ? 'page' : null\"\n [pTooltip]=\"sidebarOpen() ? '' : item.label\"\n tooltipPosition=\"right\"\n (click)=\"selectNav(item.id)\"\n >\n <i [class]=\"item.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ item.label }}</span>\n </button>\n }\n </nav>\n }\n\n <nav class=\"access-menu\">\n @if (menuLoading()) {\n <div class=\"nav-skeleton\" role=\"status\" [attr.aria-label]=\"t.accessLoading\">\n @for (width of menuPlaceholders; track $index) {\n <div class=\"nav-skeleton-item\">\n <p-skeleton shape=\"circle\" size=\"15px\" />\n <p-skeleton height=\"9px\" [width]=\"width\" />\n </div>\n }\n </div>\n } @else if (menuError()) {\n <p class=\"access-state is-error\">{{ menuError() }}</p>\n } @else if (!menu().length) {\n <p class=\"access-state\">{{ t.accessEmpty }}</p>\n } @else {\n @for (node of menu(); track node.id) {\n @let group = isGroup(node);\n @let open = isExpanded(node);\n\n <button\n type=\"button\"\n class=\"nav-item\"\n [class.is-active]=\"!group && isSelected(node)\"\n [class.is-inert]=\"!group && !node.route\"\n [attr.aria-expanded]=\"group ? open : null\"\n [disabled]=\"!group && !node.route\"\n [pTooltip]=\"sidebarOpen() ? '' : node.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(node)\"\n >\n <i [class]=\"node.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ node.label }}</span>\n @if (group && sidebarOpen()) {\n <i\n class=\"pi nav-caret\"\n [class.pi-chevron-down]=\"open\"\n [class.pi-chevron-right]=\"!open\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n\n @if (open) {\n @for (child of node.children; track child.id) {\n <button\n type=\"button\"\n class=\"nav-item is-child\"\n [class.is-active]=\"isSelected(child)\"\n [pTooltip]=\"sidebarOpen() ? '' : child.label\"\n tooltipPosition=\"right\"\n (click)=\"selectMenu(child)\"\n >\n <i [class]=\"child.icon ?? 'pi pi-circle'\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ child.label }}</span>\n </button>\n }\n }\n }\n }\n </nav>\n </aside>\n\n <main class=\"content\">\n <div class=\"measure\">\n <ng-content select=\"[nucleusTop]\" />\n\n @if (crumbs().length || title() || pageActions()) {\n <header class=\"page-head\">\n <div class=\"page-head-main\">\n @if (crumbs().length) {\n <p-breadcrumb [model]=\"crumbs()\" [home]=\"home()\" styleClass=\"ns-crumbs\" />\n }\n\n @if (title()) {\n <h1>{{ title() }}</h1>\n }\n </div>\n\n @if (pageActions(); as actions) {\n <div class=\"page-head-actions\">\n <ng-container [ngTemplateOutlet]=\"actions\" />\n </div>\n }\n </header>\n }\n\n <ng-content />\n </div>\n </main>\n</div>\n\n<p-drawer\n [visible]=\"settingsOpen()\"\n (visibleChange)=\"settingsOpen.set($event)\"\n position=\"right\"\n [header]=\"t.settingsTitle\"\n [modal]=\"false\"\n [blockScroll]=\"false\"\n styleClass=\"ns-settings-drawer\"\n [style]=\"{ width: '380px' }\"\n>\n <nucleus-appearance />\n</p-drawer>\n\n<p-toast position=\"bottom-right\" styleClass=\"ns-toast\">\n <ng-template #message let-message>\n <nucleus-lordicon\n [src]=\"message.severity === 'success' ? icons.check : icons.warning\"\n [tone]=\"message.severity === 'success' ? 'accent' : 'danger'\"\n [size]=\"34\"\n trigger=\"in\"\n />\n <div class=\"toast-text\">\n <p class=\"toast-summary\">{{ message.summary }}</p>\n @if (message.detail) {\n <p class=\"toast-detail\">{{ message.detail }}</p>\n }\n </div>\n </ng-template>\n</p-toast>\n\n<p-confirmdialog [style]=\"{ width: '420px' }\">\n <ng-template #headless let-message let-onAccept=\"onAccept\" let-onReject=\"onReject\">\n <div class=\"confirm\">\n <nucleus-lordicon\n [src]=\"message.icon\"\n [tone]=\"message.acceptButtonStyleClass ? 'danger' : 'accent'\"\n [size]=\"64\"\n trigger=\"loop\"\n />\n <h2>{{ message.header }}</h2>\n <p>{{ message.message }}</p>\n <div class=\"confirm-actions\">\n <p-button\n [label]=\"message.rejectLabel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onReject()\"\n />\n <p-button\n [label]=\"message.acceptLabel\"\n [severity]=\"message.acceptButtonStyleClass ? 'danger' : 'primary'\"\n (onClick)=\"onAccept()\"\n />\n </div>\n </div>\n </ng-template>\n</p-confirmdialog>\n", styles: [":host{display:flex;flex-direction:column;min-height:100dvh;background:var(--ac-bg);color:var(--ac-text)}.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:flex-start;gap:16px;height:56px;padding:0 12px 0 8px;border-bottom:1px solid var(--ns-frame-line)}.side{display:flex;min-width:0;align-items:center;gap:4px}.side.is-end{margin-left:auto}.brand{display:flex;align-items:center;gap:9px;margin-left:4px}.brand-name{display:flex;align-items:baseline;gap:7px}.brand-primary{font-size:13px;font-weight:700;letter-spacing:.15em}.brand-secondary{font-size:9px;font-weight:var(--ns-weight-emphasis);letter-spacing:.22em;color:var(--ns-frame-muted)}.lang-switch{display:flex;align-items:center;gap:2px;margin-right:6px;border:1px solid var(--ns-frame-line);border-radius:999px;padding:2px}.lang-pill{font-size:10px;font-weight:var(--ns-weight-emphasis);letter-spacing:.08em;padding:4px 10px;border:none;border-radius:999px;background:transparent;color:var(--ns-frame-muted);cursor:pointer}.lang-pill:hover{color:var(--ns-frame-ink)}.lang-pill.is-active{background:var(--ns-frame-glow);color:var(--ns-frame-on-glow)}.body{display:flex;flex:1;min-height:0}.sidebar{flex:none;width:max-content;min-width:224px;max-width:340px;padding:12px 10px;border-right:1px solid var(--ns-frame-line);transition:width .18s ease}.sidebar.is-collapsed{width:60px;min-width:0}.sidebar nav{display:flex;flex-direction:column;gap:3px}.nav-item{display:flex;align-items:center;gap:12px;width:100%;padding:var(--ns-nav-y, 9px) 12px;border:none;border-radius:6px;background:transparent;color:var(--ns-frame-muted);font-size:13px;font-weight:var(--ns-weight-text);text-align:left;white-space:nowrap;cursor:pointer}.nav-item i{flex:none;font-size:15px}.nav-item:hover{background:var(--ns-frame-raised);color:var(--ns-frame-ink)}.nav-item.is-active{background:var(--ns-nav-active-bg, var(--ns-frame-raised));color:var(--ns-nav-active-ink, var(--ns-frame-ink));font-weight:var(--ns-weight-emphasis)}.nav-item.is-active i{color:inherit}.nav-caret{margin-left:auto;font-size:11px!important;opacity:.7}.nav-item.is-inert{opacity:.45;cursor:default}.nav-item.is-inert:hover{background:transparent;color:var(--ns-frame-muted)}.nav-label{overflow:hidden;text-overflow:ellipsis}.sidebar.is-collapsed .nav-label{display:none}.sidebar.is-collapsed .nav-item{justify-content:center;padding-inline:0}.content{flex:1;min-width:0;padding:28px 28px 64px;display:flex;flex-direction:column;gap:14px}.page-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:46px;padding:7px 16px;border:1px solid var(--ac-border);border-radius:12px;background:var(--ac-surface);box-shadow:var(--ns-shadow-1)}.page-head-main{display:flex;min-width:0;flex:1;align-items:center;gap:14px}.page-head-actions{display:flex;flex:none;align-items:center;gap:8px}.page-head h1{margin:0;font-size:19px;font-weight:var(--ns-weight-heading)}.measure{display:flex;width:100%;max-width:var(--ac-content-max, 1440px);flex-direction:column;gap:14px;margin-inline:0}h1{margin:0;font-size:26px;line-height:1.2;font-weight:var(--ns-weight-emphasis);letter-spacing:-.02em}.access-menu{display:flex;flex-direction:column;gap:.15rem;margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--ns-frame-line)}.access-caption{margin:0 0 .4rem;padding:0 .75rem;color:var(--ns-frame-muted);font-size:.68rem;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.access-state{margin:0;padding:.35rem .75rem;color:var(--ns-frame-muted);font-size:.78rem}.access-state.is-error{color:var(--p-red-400, #f87171)}.nav-item.is-child{padding-left:2.1rem;font-size:.86rem}@media(max-width:720px){.sidebar{max-width:none;position:fixed;top:var(--ns-topbar-h, 56px);bottom:0;left:0;z-index:30;width:268px;max-width:82vw;overflow-y:auto;box-shadow:0 18px 44px #00000073;transform:translate(-100%);transition:transform .18s ease}.sidebar.is-collapsed{width:268px;max-width:82vw;transform:translate(-100%)}.sidebar:not(.is-collapsed){transform:translate(0)}.sidebar.is-collapsed .nav-label{display:inline}.sidebar.is-collapsed .role-text{display:flex}.sidebar.is-collapsed .nav-item,.sidebar.is-collapsed .role-badge{justify-content:flex-start;padding-inline:12px}.brand-secondary{display:none}.topbar{height:auto;min-height:56px;flex-wrap:wrap;padding-bottom:8px;row-gap:8px}.context{order:3;width:100%;margin-left:0}.context-select{min-width:0;max-width:none;flex:1 1 0}.content{padding:20px 16px 48px}h1{font-size:22px}.page-head{gap:10px;min-height:42px;padding:7px 12px}.page-head-main{gap:8px}.page-head h1{overflow:hidden;min-width:0;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.page-head-actions{flex-wrap:wrap;justify-content:flex-end;gap:6px}.page-head-actions ::ng-deep .p-button{padding-block:6px;padding-inline:11px;font-size:13px;white-space:nowrap}.page-head-actions ::ng-deep .p-button-icon{font-size:13px}}.who{display:flex;align-items:center;gap:12px;margin:6px 6px 0;padding:12px;border-radius:10px;background:var(--ac-text);color:var(--ac-surface)}.who-photo{width:42px;height:42px;flex:none;border-radius:999px;object-fit:cover}.who-initials{display:inline-flex;align-items:center;justify-content:center;background:var(--ac-accent);color:var(--ac-on-accent);font-size:15px;font-weight:var(--ns-weight-emphasis)}.who-text{display:flex;min-width:0;flex-direction:column}.who-name{overflow:hidden;font-size:14px;font-weight:var(--ns-weight-emphasis);text-overflow:ellipsis;white-space:nowrap}.who-mail{overflow:hidden;color:color-mix(in srgb,currentColor 64%,transparent);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.who-role{display:flex;align-items:center;gap:7px;margin:0;overflow:hidden;padding:11px 17px 5px;color:var(--ac-text-muted);font-size:12px;white-space:nowrap}.who-role b{flex:none;color:var(--ac-text);font-size:12px;font-weight:var(--ns-weight-emphasis)}.who-sep{flex:none}.who-context{overflow:hidden;text-overflow:ellipsis}.who-dot{width:7px;height:7px;flex:none;border-radius:50%;background:var(--ns-success)}.company-option{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.company-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.launcher-notice{display:flex;gap:10px;margin:12px 12px 0;padding:12px;border:1px solid color-mix(in srgb,var(--ac-accent) 40%,transparent);border-radius:8px;background:color-mix(in srgb,var(--ac-accent) 10%,transparent)}.launcher-notice i{margin-top:2px;color:var(--ac-accent);font-size:15px}.launcher-notice-title{margin:0 0 4px;font-size:13px;font-weight:var(--ns-weight-emphasis)}.launcher-notice-body{margin:0;color:var(--ac-text-muted);font-size:12px;line-height:1.45}.confirm{display:flex;flex-direction:column;align-items:center;gap:6px;padding:26px 24px 20px;border:1px solid var(--ac-border);border-radius:14px;background:var(--ac-surface);text-align:center}.confirm h2{margin:8px 0 0;font-size:17px;font-weight:var(--ns-weight-heading)}.confirm p{margin:0;max-width:34ch;color:var(--ac-text-muted);font-size:13px;line-height:1.5}.confirm-actions{display:flex;justify-content:center;gap:8px;margin-top:18px}.toast-text{flex:1;margin-left:12px}.toast-summary{margin:0;font-size:13px;font-weight:var(--ns-weight-emphasis)}.toast-detail{margin:2px 0 0;color:var(--ac-text-muted);font-size:12px}.context{display:flex;min-width:0;align-items:center;gap:8px;margin-left:14px}.context-select{min-width:150px;max-width:210px}.role-badge{display:flex;align-items:center;gap:12px;padding:4px 12px 2px}.role-badge>i{flex:none;color:var(--ns-frame-muted);font-size:14px}.role-text{display:flex;min-width:0;flex-direction:column;gap:1px}.role-name{overflow:hidden;color:var(--ns-frame-ink);font-size:13px;font-weight:var(--ns-weight-emphasis);text-overflow:ellipsis;white-space:nowrap}.role-caption{color:var(--ns-frame-muted);font-size:10px;letter-spacing:.06em;text-transform:uppercase}.sidebar.is-collapsed .role-badge{justify-content:center;padding-inline:0}.sidebar-scrim{position:fixed;top:var(--ns-topbar-h, 56px);right:0;bottom:0;left:0;z-index:29;padding:0;border:0;background:#00000073;cursor:pointer}.nav-skeleton{display:flex;flex-direction:column;gap:3px}.nav-skeleton-item{display:flex;align-items:center;gap:12px;padding:11px 12px}.sidebar.is-collapsed .nav-skeleton-item .p-skeleton:last-child{display:none}\n"] }]
4124
4306
  }], ctorParameters: () => [], propDecorators: { brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], activeNavId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeNavId", required: false }] }], selectedMenuId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMenuId", required: false }] }], navSelect: [{ type: i0.Output, args: ["navSelect"] }], menuSelect: [{ type: i0.Output, args: ["menuSelect"] }] } });
4307
+ function shortAppName(name) {
4308
+ if (!name.startsWith(SUITE_PREFIX))
4309
+ return name;
4310
+ return name.slice(SUITE_PREFIX.length).trim() || name;
4311
+ }
4125
4312
  function initialsOf(source) {
4126
4313
  const parts = source.trim().split(/\s+/).filter(Boolean);
4127
4314
  if (!parts.length)
@@ -4153,5 +4340,5 @@ function homeNode(route, label) {
4153
4340
  * Generated bundle index. Do not edit.
4154
4341
  */
4155
4342
 
4156
- export { ACCENTS, CANVASES, COMMON_COPY, CONTROL_CONTRAST, DEFAULT_APPEARANCE, DENSITIES, EMPTY_GEO_VALUE, FIELD_TARGETS, FRAMES, GEO_COPY, LEGACY_THEMES, NO_PERMISSIONS, NUCLEUS_ACCENTS, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_HOME, NUCLEUS_ICONS, NUCLEUS_ICON_CATALOG, NUCLEUS_LANGS, NUCLEUS_LOGOUT_PARAM, NUCLEUS_NARROW_QUERY, NUCLEUS_SKIP_AUTH, NucleusAppearance, NucleusAuth, NucleusCache, NucleusCard, NucleusCell, NucleusColorPicker, NucleusEnterAdvance, NucleusFeedback, NucleusForm, NucleusGeo, NucleusGeoSelect, NucleusIconPicker, NucleusLanguage, NucleusLink, NucleusList, NucleusLordicon, NucleusMark, NucleusMenu, NucleusMetric, NucleusMetrics, NucleusPage, NucleusPageActions, NucleusPreset, NucleusRecentApps, NucleusSessionAuth, NucleusShell, NucleusShortcut, NucleusShortcuts, NucleusStarfield, NucleusTabs, NucleusViewport, SHELL_COPY, SessionService, TEXT_CONTRAST, THEME_COPY, ThemeService, UserSyncService, accentById, accentLabelOf, accentOn, ariaKeysOf, auditAppearance, canvasById, clock, comboOf, commonCopyOf, consumeNucleusLogout, contrastIssue, contrastRatio, day, densityById, endOfDayUtc, fieldsIn, findMenuByRoute, flagOf, foldText, frameById, geoCopyOf, hasChildren, hasModifier, iconClassOf, iconNameOf, integer, isAccentPreference, isApplePlatform, isBeforeToday, isCanvasPreference, isDarkCanvas, isDensityId, isFieldSearchable, isFrameId, isHomeRoute, isNucleusConfigured, isOnOrBeforeToday, isReachable, isToday, isTypingTarget, isUnderRoute, isoDay, levelLabel, loadLordicon, loadNucleusConfig, matchMenuByRoute, matchesRow, meetsContrast, menuGlyph, menuTile, minutesAsClock, mixHex, money, moveTo, normalizeHomeRoute, normalizeKeys, nucleusAccessGuard, nucleusAuthInterceptor, nucleusErrorMessage, nucleusLang, nucleusLogoutUrl, nucleusParseDate, ownsUrl, percent, permissionsOf, provideNucleus, provideNucleusFeedback, provideNucleusHome, provideNucleusTheme, qty, readableOn, relativeLuminance, resolveAccent, resolveFieldSize, routePath, searchIcons, selectableRows, shiftDay, shortcutHint, signedMoney, stamp, startOfDayUtc, themeCopyOf, toNumber, toggleCollapsed, visibleTreeRows };
4343
+ export { ACCENTS, CANVASES, COMMON_COPY, CONTROL_CONTRAST, DEFAULT_APPEARANCE, DENSITIES, EMPTY_GEO_VALUE, FIELD_TARGETS, FRAMES, GEO_COPY, LEGACY_THEMES, NO_PERMISSIONS, NUCLEUS_ACCENTS, NUCLEUS_CONFIG, NUCLEUS_DARK_SELECTOR, NUCLEUS_FORCE_BEARER, NUCLEUS_HOME, NUCLEUS_ICONS, NUCLEUS_ICON_CATALOG, NUCLEUS_LANGS, NUCLEUS_LOGOUT_PARAM, NUCLEUS_NARROW_QUERY, NUCLEUS_SKIP_AUTH, NucleusAppearance, NucleusAuth, NucleusBytes, NucleusCache, NucleusCard, NucleusCell, NucleusColorPicker, NucleusCompact, NucleusEnterAdvance, NucleusFeedback, NucleusForm, NucleusGeo, NucleusGeoSelect, NucleusIconPicker, NucleusLanguage, NucleusLink, NucleusList, NucleusLordicon, NucleusMark, NucleusMegabytes, NucleusMenu, NucleusMetric, NucleusMetrics, NucleusPage, NucleusPageActions, NucleusPreset, NucleusRecentApps, NucleusSessionAuth, NucleusShell, NucleusShortcut, NucleusShortcuts, NucleusStarfield, NucleusTabs, NucleusViewport, SHELL_COPY, SessionService, TEXT_CONTRAST, THEME_COPY, ThemeService, UserSyncService, accentById, accentLabelOf, accentOn, ariaKeysOf, auditAppearance, canvasById, clock, comboOf, commonCopyOf, compactBytes, compactMegabytes, compactNumber, consumeNucleusLogout, contrastIssue, contrastRatio, day, densityById, endOfDayUtc, fieldsIn, findMenuByRoute, flagOf, foldText, frameById, geoCopyOf, hasChildren, hasModifier, iconClassOf, iconNameOf, integer, isAccentPreference, isApplePlatform, isBeforeToday, isCanvasPreference, isDarkCanvas, isDensityId, isFieldSearchable, isFrameId, isHomeRoute, isNucleusConfigured, isOnOrBeforeToday, isReachable, isToday, isTypingTarget, isUnderRoute, isoDay, levelLabel, loadLordicon, loadNucleusConfig, matchMenuByRoute, matchesRow, meetsContrast, menuGlyph, menuTile, minutesAsClock, mixHex, money, moveTo, normalizeHomeRoute, normalizeKeys, nucleusAccessGuard, nucleusAuthInterceptor, nucleusErrorMessage, nucleusLang, nucleusLogoutUrl, nucleusParseDate, ownsUrl, percent, permissionsOf, provideNucleus, provideNucleusFeedback, provideNucleusHome, provideNucleusTheme, qty, readableOn, relativeLuminance, resolveAccent, resolveFieldSize, routePath, searchIcons, selectableRows, shiftDay, shortcutHint, signedMoney, stamp, startOfDayUtc, themeCopyOf, toNumber$1 as toNumber, toggleCollapsed, visibleTreeRows };
4157
4344
  //# sourceMappingURL=nucleus-suite-pe-core.mjs.map