@akcelik/strct 5.4.0 → 5.6.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.
@@ -812,12 +812,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
812
812
  class StrctThemeSwitcher {
813
813
  theme = inject(StrctThemeService);
814
814
  /** Labels for the Light / Dark mode buttons (localizable). */
815
+ /**
816
+ * Where the switcher sits. `header` (the default) reads on `--hdr`;
817
+ * `surface` is a raised one — a user menu, a settings popover — where the
818
+ * header's foreground would be invisible.
819
+ */
820
+ tone = input('header', /* @ts-ignore */
821
+ ...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
815
822
  lightLabel = input('Light', /* @ts-ignore */
816
823
  ...(ngDevMode ? [{ debugName: "lightLabel" }] : /* istanbul ignore next */ []));
817
824
  darkLabel = input('Dark', /* @ts-ignore */
818
825
  ...(ngDevMode ? [{ debugName: "darkLabel" }] : /* istanbul ignore next */ []));
819
826
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctThemeSwitcher, deps: [], target: i0.ɵɵFactoryTarget.Component });
820
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctThemeSwitcher, isStandalone: true, selector: "strct-theme-switcher", inputs: { lightLabel: { classPropertyName: "lightLabel", publicName: "lightLabel", isSignal: true, isRequired: false, transformFunction: null }, darkLabel: { classPropertyName: "darkLabel", publicName: "darkLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-ts" }, ngImport: i0, template: `
827
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctThemeSwitcher, isStandalone: true, selector: "strct-theme-switcher", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, lightLabel: { classPropertyName: "lightLabel", publicName: "lightLabel", isSignal: true, isRequired: false, transformFunction: null }, darkLabel: { classPropertyName: "darkLabel", publicName: "darkLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-ts--surface": "tone() === 'surface'" }, classAttribute: "strct-ts" }, ngImport: i0, template: `
821
828
  <div class="strct-ts__pal">
822
829
  @for (p of theme.palettes; track p.id) {
823
830
  <button
@@ -857,7 +864,7 @@ class StrctThemeSwitcher {
857
864
  <strct-icon name="moon" [size]="16" [strokeWidth]="1.5" />
858
865
  </button>
859
866
  </div>
860
- `, isInline: true, styles: [".strct-ts{display:inline-flex;align-items:center;gap:14px}.strct-ts__pal{display:inline-flex;gap:7px}.strct-ts__dot{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;padding:0;cursor:pointer;background:transparent;border:1.5px solid color-mix(in srgb,var(--hdr-fg) 40%,transparent);transition:transform .15s ease,border-color .15s ease}.strct-ts__dot:hover{transform:scale(1.12)}.strct-ts__inner{width:11px;height:11px;border-radius:50%;display:block}.strct-ts__dot--on{border-color:var(--hdr-fg);box-shadow:0 0 0 2px color-mix(in srgb,var(--hdr-fg) 28%,transparent)}.strct-ts__pill{display:inline-flex;padding:2px;gap:2px;border-radius:7px;background:color-mix(in srgb,var(--hdr-fg) 12%,transparent)}.strct-ts__pbtn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:color-mix(in srgb,var(--hdr-fg) 65%,transparent);transition:background .14s ease,color .14s ease}.strct-ts__pbtn--on{background:color-mix(in srgb,var(--hdr-fg) 20%,transparent);color:var(--hdr-fg)}.strct-ts__dot:focus-visible,.strct-ts__pbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
867
+ `, isInline: true, styles: [".strct-ts--surface{--strct-ts-fg: var(--t1)}.strct-ts{display:inline-flex;align-items:center;gap:14px}.strct-ts__pal{display:inline-flex;gap:7px}.strct-ts__dot{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;padding:0;cursor:pointer;background:transparent;border:1.5px solid color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 40%,transparent);transition:transform .15s ease,border-color .15s ease}.strct-ts__dot:hover{transform:scale(1.12)}.strct-ts__inner{width:11px;height:11px;border-radius:50%;display:block}.strct-ts__dot--on{border-color:var(--strct-ts-fg, var(--hdr-fg));box-shadow:0 0 0 2px color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 28%,transparent)}.strct-ts__pill{display:inline-flex;padding:2px;gap:2px;border-radius:7px;background:color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 12%,transparent)}.strct-ts__pbtn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 65%,transparent);transition:background .14s ease,color .14s ease}.strct-ts__pbtn--on{background:color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 20%,transparent);color:var(--strct-ts-fg, var(--hdr-fg))}.strct-ts__dot:focus-visible,.strct-ts__pbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
861
868
  }
862
869
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctThemeSwitcher, decorators: [{
863
870
  type: Component,
@@ -901,8 +908,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
901
908
  <strct-icon name="moon" [size]="16" [strokeWidth]="1.5" />
902
909
  </button>
903
910
  </div>
904
- `, host: { class: 'strct-ts' }, styles: [".strct-ts{display:inline-flex;align-items:center;gap:14px}.strct-ts__pal{display:inline-flex;gap:7px}.strct-ts__dot{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;padding:0;cursor:pointer;background:transparent;border:1.5px solid color-mix(in srgb,var(--hdr-fg) 40%,transparent);transition:transform .15s ease,border-color .15s ease}.strct-ts__dot:hover{transform:scale(1.12)}.strct-ts__inner{width:11px;height:11px;border-radius:50%;display:block}.strct-ts__dot--on{border-color:var(--hdr-fg);box-shadow:0 0 0 2px color-mix(in srgb,var(--hdr-fg) 28%,transparent)}.strct-ts__pill{display:inline-flex;padding:2px;gap:2px;border-radius:7px;background:color-mix(in srgb,var(--hdr-fg) 12%,transparent)}.strct-ts__pbtn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:color-mix(in srgb,var(--hdr-fg) 65%,transparent);transition:background .14s ease,color .14s ease}.strct-ts__pbtn--on{background:color-mix(in srgb,var(--hdr-fg) 20%,transparent);color:var(--hdr-fg)}.strct-ts__dot:focus-visible,.strct-ts__pbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
905
- }], propDecorators: { lightLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lightLabel", required: false }] }], darkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "darkLabel", required: false }] }] } });
911
+ `, host: {
912
+ class: 'strct-ts',
913
+ '[class.strct-ts--surface]': "tone() === 'surface'",
914
+ }, styles: [".strct-ts--surface{--strct-ts-fg: var(--t1)}.strct-ts{display:inline-flex;align-items:center;gap:14px}.strct-ts__pal{display:inline-flex;gap:7px}.strct-ts__dot{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;padding:0;cursor:pointer;background:transparent;border:1.5px solid color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 40%,transparent);transition:transform .15s ease,border-color .15s ease}.strct-ts__dot:hover{transform:scale(1.12)}.strct-ts__inner{width:11px;height:11px;border-radius:50%;display:block}.strct-ts__dot--on{border-color:var(--strct-ts-fg, var(--hdr-fg));box-shadow:0 0 0 2px color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 28%,transparent)}.strct-ts__pill{display:inline-flex;padding:2px;gap:2px;border-radius:7px;background:color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 12%,transparent)}.strct-ts__pbtn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 65%,transparent);transition:background .14s ease,color .14s ease}.strct-ts__pbtn--on{background:color-mix(in srgb,var(--strct-ts-fg, var(--hdr-fg)) 20%,transparent);color:var(--strct-ts-fg, var(--hdr-fg))}.strct-ts__dot:focus-visible,.strct-ts__pbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
915
+ }], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], lightLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lightLabel", required: false }] }], darkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "darkLabel", required: false }] }] } });
906
916
 
907
917
  /**
908
918
  * Positions an overlay panel with `position: fixed` relative to an anchor
@@ -1112,7 +1122,7 @@ class StrctHeader {
1112
1122
  <strct-icon name="menu" [size]="18" />
1113
1123
  </button>
1114
1124
  <ng-content />
1115
- `, isInline: true, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:var(--hdr-fg)}.strct-header__drawer-toggle{display:none;align-items:center;justify-content:center;padding:4px;border:0;border-radius:5px;background:transparent;color:color-mix(in srgb,var(--hdr-fg) 85%,transparent);cursor:pointer}.strct-header__drawer-toggle:hover{background:#ffffff1f;color:var(--hdr-fg)}@media(max-width:768px){.strct-header__drawer-toggle{display:inline-flex}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1125
+ `, isInline: true, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:var(--hdr-fg)}.strct-header .strct-btn--flat{color:color-mix(in srgb,var(--hdr-fg) 72%,transparent)}.strct-header .strct-btn--flat:hover:not(:disabled){background:color-mix(in srgb,var(--hdr-fg) 12%,transparent);color:var(--hdr-fg)}.strct-header .strct-btn--flat:focus-visible{outline-color:color-mix(in srgb,var(--hdr-fg) 60%,transparent)}.strct-header__drawer-toggle{display:none;align-items:center;justify-content:center;padding:4px;border:0;border-radius:5px;background:transparent;color:color-mix(in srgb,var(--hdr-fg) 85%,transparent);cursor:pointer}.strct-header__drawer-toggle:hover{background:#ffffff1f;color:var(--hdr-fg)}@media(max-width:768px){.strct-header__drawer-toggle{display:inline-flex}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1116
1126
  }
1117
1127
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctHeader, decorators: [{
1118
1128
  type: Component,
@@ -1128,7 +1138,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
1128
1138
  <strct-icon name="menu" [size]="18" />
1129
1139
  </button>
1130
1140
  <ng-content />
1131
- `, host: { class: 'strct-header' }, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:var(--hdr-fg)}.strct-header__drawer-toggle{display:none;align-items:center;justify-content:center;padding:4px;border:0;border-radius:5px;background:transparent;color:color-mix(in srgb,var(--hdr-fg) 85%,transparent);cursor:pointer}.strct-header__drawer-toggle:hover{background:#ffffff1f;color:var(--hdr-fg)}@media(max-width:768px){.strct-header__drawer-toggle{display:inline-flex}}\n"] }]
1141
+ `, host: { class: 'strct-header' }, styles: [".strct-header{display:flex;align-items:center;gap:14px;height:56px;padding:0 18px;background:var(--hdr);border-bottom:1px solid var(--b2);color:var(--hdr-fg)}.strct-header .strct-btn--flat{color:color-mix(in srgb,var(--hdr-fg) 72%,transparent)}.strct-header .strct-btn--flat:hover:not(:disabled){background:color-mix(in srgb,var(--hdr-fg) 12%,transparent);color:var(--hdr-fg)}.strct-header .strct-btn--flat:focus-visible{outline-color:color-mix(in srgb,var(--hdr-fg) 60%,transparent)}.strct-header__drawer-toggle{display:none;align-items:center;justify-content:center;padding:4px;border:0;border-radius:5px;background:transparent;color:color-mix(in srgb,var(--hdr-fg) 85%,transparent);cursor:pointer}.strct-header__drawer-toggle:hover{background:#ffffff1f;color:var(--hdr-fg)}@media(max-width:768px){.strct-header__drawer-toggle{display:inline-flex}}\n"] }]
1132
1142
  }], propDecorators: { drawerToggleAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawerToggleAriaLabel", required: false }] }] } });
1133
1143
  /** Bottom status bar. */
1134
1144
  class StrctFooter {
@@ -1569,18 +1579,21 @@ class StrctLogin {
1569
1579
  }
1570
1580
  }
1571
1581
  <div class="strct-login__aside-inner">
1572
- @if (brandIcon() || brandName()) {
1573
- <div class="strct-login__brand">
1574
- @if (brandIcon()) {
1575
- <span class="strct-login__mark">
1576
- <strct-icon [name]="brandIcon()" [size]="18" [strokeWidth]="1.5" />
1577
- </span>
1578
- }
1579
- @if (brandName()) {
1580
- <span class="strct-login__brandname">{{ brandName() }}</span>
1581
- }
1582
- </div>
1583
- }
1582
+ <div class="strct-login__brand">
1583
+ @if (brandIcon()) {
1584
+ <span class="strct-login__mark">
1585
+ <strct-icon [name]="brandIcon()" [size]="18" [strokeWidth]="1.5" />
1586
+ </span>
1587
+ }
1588
+ @if (brandName()) {
1589
+ <span class="strct-login__brandname">{{ brandName() }}</span>
1590
+ }
1591
+ <!-- What this install is: "APPLIANCE", "EVALUATION". It belongs
1592
+ on the brand's line, not in the tagline under it. -->
1593
+ <span class="strct-login__brandmeta">
1594
+ <ng-content select="[strctLoginBrandMeta]" />
1595
+ </span>
1596
+ </div>
1584
1597
  <div class="strct-login__asidebody">
1585
1598
  @if (tagline()) {
1586
1599
  <div class="strct-login__kicker">{{ tagline() }}</div>
@@ -1595,7 +1608,7 @@ class StrctLogin {
1595
1608
  } @else {
1596
1609
  <div class="strct-login__inner" [style.max-width.px]="maxWidth()"><ng-content /></div>
1597
1610
  }
1598
- `, isInline: true, styles: [".strct-login{display:flex;align-items:center;justify-content:center;width:100%;min-height:100%;padding:32px}.strct-login__inner{width:100%}.strct-login__card{display:grid;grid-template-columns:1.05fr 1fr;width:100%;overflow:hidden}.strct-login__main{padding:40px 38px;display:flex;flex-direction:column;justify-content:center}.strct-login__aside{position:relative;overflow:hidden;min-height:420px;color:var(--t1);border-inline-end:1px solid var(--b2)}.strct-login__aside:before,.strct-login__aside:after{display:none}.strct-login__aside-inner{position:relative;z-index:var(--z-base);height:100%;display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-5);padding:34px 36px}.strct-login__glow,.strct-login__matrix,.strct-login__net{position:absolute;inset:-36px;pointer-events:none}.strct-login__glow{filter:blur(46px)}.strct-login__glow--a{background:radial-gradient(360px 300px at 12% 8%,var(--acc30),transparent 70%)}.strct-login__glow--b{background:radial-gradient(320px 300px at 92% 96%,var(--acc18),transparent 70%)}.strct-login__matrix{background-image:radial-gradient(var(--acc30) 1px,transparent 1.4px);background-size:22px 22px;opacity:.4;-webkit-mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%);mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%)}.strct-login__net{width:calc(100% + 72px);height:calc(100% + 72px)}.strct-login__link{fill:none;stroke:var(--acc30);stroke-width:1}.strct-login__node{fill:var(--acc);opacity:.55}@media(prefers-reduced-motion:no-preference){.strct-login__node{animation:strct-login-pulse 4.5s ease-in-out infinite}.strct-login__node--p2{animation-delay:1.4s}.strct-login__node--p3{animation-delay:2.8s}}@keyframes strct-login-pulse{0%,to{opacity:.35}50%{opacity:.85}}.strct-login__brand{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:10px}.strct-login__mark{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:9px;background:var(--acc-m);border:1px solid var(--acc30);color:var(--acc)}.strct-login__brandname{font-size:13px;font-weight:700;letter-spacing:2px;color:var(--t1)}.strct-login__asidebody{position:relative}.strct-login__kicker{font-size:11.5px;font-weight:700;letter-spacing:1.6px;text-transform:uppercase;margin-block-end:10px;color:var(--acc)}.strct-login__status:empty{display:none}.strct-login__status{position:relative}@media(max-width:720px){.strct-login__card{grid-template-columns:1fr}.strct-login__aside{min-height:220px}.strct-login__main{padding:30px 26px}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1611
+ `, isInline: true, styles: [".strct-login{display:flex;align-items:center;justify-content:center;width:100%;min-height:100%;padding:32px}.strct-login__inner{width:100%}.strct-login__card{display:grid;grid-template-columns:1.05fr 1fr;width:100%;overflow:hidden}.strct-login__main{padding:40px 38px;display:flex;flex-direction:column;justify-content:center}.strct-login__aside{position:relative;overflow:hidden;min-height:420px;color:var(--t1);border-inline-end:1px solid var(--b2)}.strct-login__aside:before,.strct-login__aside:after{display:none}.strct-login__aside-inner{position:relative;z-index:var(--z-base);height:100%;display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-5);padding:34px 36px}.strct-login__glow,.strct-login__matrix,.strct-login__net{position:absolute;inset:-36px;pointer-events:none}.strct-login__glow{filter:blur(46px)}.strct-login__glow--a{background:radial-gradient(360px 300px at 12% 8%,var(--acc30),transparent 70%)}.strct-login__glow--b{background:radial-gradient(320px 300px at 92% 96%,var(--acc18),transparent 70%)}.strct-login__matrix{background-image:radial-gradient(var(--acc30) 1px,transparent 1.4px);background-size:22px 22px;opacity:.4;-webkit-mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%);mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%)}.strct-login__net{width:calc(100% + 72px);height:calc(100% + 72px)}.strct-login__link{fill:none;stroke:var(--acc30);stroke-width:1}.strct-login__node{fill:var(--acc);opacity:.55}@media(prefers-reduced-motion:no-preference){.strct-login__node{animation:strct-login-pulse 4.5s ease-in-out infinite}.strct-login__node--p2{animation-delay:1.4s}.strct-login__node--p3{animation-delay:2.8s}}@keyframes strct-login-pulse{0%,to{opacity:.35}50%{opacity:.85}}.strct-login__brand:not(:has(*)){display:none}.strct-login__brandmeta:empty{display:none}.strct-login__brandmeta{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-login__brand{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:10px}.strct-login__mark{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:9px;background:var(--acc-m);border:1px solid var(--acc30);color:var(--acc)}.strct-login__brandname{font-size:13px;font-weight:700;letter-spacing:2px;color:var(--t1)}.strct-login__asidebody{position:relative}.strct-login__kicker{font-size:11.5px;font-weight:700;letter-spacing:1.6px;text-transform:uppercase;margin-block-end:10px;color:var(--acc)}.strct-login__status:empty{display:none}.strct-login__status{position:relative}@media(max-width:720px){.strct-login__card{grid-template-columns:1fr}.strct-login__aside{min-height:220px}.strct-login__main{padding:30px 26px}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1599
1612
  }
1600
1613
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctLogin, decorators: [{
1601
1614
  type: Component,
@@ -1627,18 +1640,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
1627
1640
  }
1628
1641
  }
1629
1642
  <div class="strct-login__aside-inner">
1630
- @if (brandIcon() || brandName()) {
1631
- <div class="strct-login__brand">
1632
- @if (brandIcon()) {
1633
- <span class="strct-login__mark">
1634
- <strct-icon [name]="brandIcon()" [size]="18" [strokeWidth]="1.5" />
1635
- </span>
1636
- }
1637
- @if (brandName()) {
1638
- <span class="strct-login__brandname">{{ brandName() }}</span>
1639
- }
1640
- </div>
1641
- }
1643
+ <div class="strct-login__brand">
1644
+ @if (brandIcon()) {
1645
+ <span class="strct-login__mark">
1646
+ <strct-icon [name]="brandIcon()" [size]="18" [strokeWidth]="1.5" />
1647
+ </span>
1648
+ }
1649
+ @if (brandName()) {
1650
+ <span class="strct-login__brandname">{{ brandName() }}</span>
1651
+ }
1652
+ <!-- What this install is: "APPLIANCE", "EVALUATION". It belongs
1653
+ on the brand's line, not in the tagline under it. -->
1654
+ <span class="strct-login__brandmeta">
1655
+ <ng-content select="[strctLoginBrandMeta]" />
1656
+ </span>
1657
+ </div>
1642
1658
  <div class="strct-login__asidebody">
1643
1659
  @if (tagline()) {
1644
1660
  <div class="strct-login__kicker">{{ tagline() }}</div>
@@ -1653,7 +1669,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
1653
1669
  } @else {
1654
1670
  <div class="strct-login__inner" [style.max-width.px]="maxWidth()"><ng-content /></div>
1655
1671
  }
1656
- `, host: { class: 'strct-login' }, styles: [".strct-login{display:flex;align-items:center;justify-content:center;width:100%;min-height:100%;padding:32px}.strct-login__inner{width:100%}.strct-login__card{display:grid;grid-template-columns:1.05fr 1fr;width:100%;overflow:hidden}.strct-login__main{padding:40px 38px;display:flex;flex-direction:column;justify-content:center}.strct-login__aside{position:relative;overflow:hidden;min-height:420px;color:var(--t1);border-inline-end:1px solid var(--b2)}.strct-login__aside:before,.strct-login__aside:after{display:none}.strct-login__aside-inner{position:relative;z-index:var(--z-base);height:100%;display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-5);padding:34px 36px}.strct-login__glow,.strct-login__matrix,.strct-login__net{position:absolute;inset:-36px;pointer-events:none}.strct-login__glow{filter:blur(46px)}.strct-login__glow--a{background:radial-gradient(360px 300px at 12% 8%,var(--acc30),transparent 70%)}.strct-login__glow--b{background:radial-gradient(320px 300px at 92% 96%,var(--acc18),transparent 70%)}.strct-login__matrix{background-image:radial-gradient(var(--acc30) 1px,transparent 1.4px);background-size:22px 22px;opacity:.4;-webkit-mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%);mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%)}.strct-login__net{width:calc(100% + 72px);height:calc(100% + 72px)}.strct-login__link{fill:none;stroke:var(--acc30);stroke-width:1}.strct-login__node{fill:var(--acc);opacity:.55}@media(prefers-reduced-motion:no-preference){.strct-login__node{animation:strct-login-pulse 4.5s ease-in-out infinite}.strct-login__node--p2{animation-delay:1.4s}.strct-login__node--p3{animation-delay:2.8s}}@keyframes strct-login-pulse{0%,to{opacity:.35}50%{opacity:.85}}.strct-login__brand{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:10px}.strct-login__mark{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:9px;background:var(--acc-m);border:1px solid var(--acc30);color:var(--acc)}.strct-login__brandname{font-size:13px;font-weight:700;letter-spacing:2px;color:var(--t1)}.strct-login__asidebody{position:relative}.strct-login__kicker{font-size:11.5px;font-weight:700;letter-spacing:1.6px;text-transform:uppercase;margin-block-end:10px;color:var(--acc)}.strct-login__status:empty{display:none}.strct-login__status{position:relative}@media(max-width:720px){.strct-login__card{grid-template-columns:1fr}.strct-login__aside{min-height:220px}.strct-login__main{padding:30px 26px}}\n"] }]
1672
+ `, host: { class: 'strct-login' }, styles: [".strct-login{display:flex;align-items:center;justify-content:center;width:100%;min-height:100%;padding:32px}.strct-login__inner{width:100%}.strct-login__card{display:grid;grid-template-columns:1.05fr 1fr;width:100%;overflow:hidden}.strct-login__main{padding:40px 38px;display:flex;flex-direction:column;justify-content:center}.strct-login__aside{position:relative;overflow:hidden;min-height:420px;color:var(--t1);border-inline-end:1px solid var(--b2)}.strct-login__aside:before,.strct-login__aside:after{display:none}.strct-login__aside-inner{position:relative;z-index:var(--z-base);height:100%;display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-5);padding:34px 36px}.strct-login__glow,.strct-login__matrix,.strct-login__net{position:absolute;inset:-36px;pointer-events:none}.strct-login__glow{filter:blur(46px)}.strct-login__glow--a{background:radial-gradient(360px 300px at 12% 8%,var(--acc30),transparent 70%)}.strct-login__glow--b{background:radial-gradient(320px 300px at 92% 96%,var(--acc18),transparent 70%)}.strct-login__matrix{background-image:radial-gradient(var(--acc30) 1px,transparent 1.4px);background-size:22px 22px;opacity:.4;-webkit-mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%);mask-image:linear-gradient(155deg,rgba(0,0,0,.9),transparent 72%)}.strct-login__net{width:calc(100% + 72px);height:calc(100% + 72px)}.strct-login__link{fill:none;stroke:var(--acc30);stroke-width:1}.strct-login__node{fill:var(--acc);opacity:.55}@media(prefers-reduced-motion:no-preference){.strct-login__node{animation:strct-login-pulse 4.5s ease-in-out infinite}.strct-login__node--p2{animation-delay:1.4s}.strct-login__node--p3{animation-delay:2.8s}}@keyframes strct-login-pulse{0%,to{opacity:.35}50%{opacity:.85}}.strct-login__brand:not(:has(*)){display:none}.strct-login__brandmeta:empty{display:none}.strct-login__brandmeta{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-login__brand{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:10px}.strct-login__mark{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:9px;background:var(--acc-m);border:1px solid var(--acc30);color:var(--acc)}.strct-login__brandname{font-size:13px;font-weight:700;letter-spacing:2px;color:var(--t1)}.strct-login__asidebody{position:relative}.strct-login__kicker{font-size:11.5px;font-weight:700;letter-spacing:1.6px;text-transform:uppercase;margin-block-end:10px;color:var(--acc)}.strct-login__status:empty{display:none}.strct-login__status{position:relative}@media(max-width:720px){.strct-login__card{grid-template-columns:1fr}.strct-login__aside{min-height:220px}.strct-login__main{padding:30px 26px}}\n"] }]
1657
1673
  }], propDecorators: { maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], split: [{ type: i0.Input, args: [{ isSignal: true, alias: "split", required: false }] }], art: [{ type: i0.Input, args: [{ isSignal: true, alias: "art", required: false }] }], brandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIcon", required: false }] }], brandName: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandName", required: false }] }], tagline: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagline", required: false }] }] } });
1658
1674
 
1659
1675
  /** Marks the breadcrumb row projected above the title. */
@@ -2539,6 +2555,25 @@ class StrctProgress {
2539
2555
  /** A quiet line under the bar — "219 GB free across 2 nodes". */
2540
2556
  caption = input('', /* @ts-ignore */
2541
2557
  ...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
2558
+ /**
2559
+ * The caption's tone. A critical capacity line's note — "2 GB left after the
2560
+ * tightest node" — is the warning; `--t3` says it is an aside.
2561
+ */
2562
+ captionStatus = input(null, /* @ts-ignore */
2563
+ ...(ngDevMode ? [{ debugName: "captionStatus" }] : /* istanbul ignore next */ []));
2564
+ /**
2565
+ * The bar's accessible name, when the visible `label` is not it: a column of
2566
+ * per-cluster memory bars would otherwise all be named "Memory". Defaults to
2567
+ * `label`.
2568
+ */
2569
+ ariaLabel = input('', /* @ts-ignore */
2570
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2571
+ /**
2572
+ * Where `showValue` puts the number: on its own row above the track, or
2573
+ * beside it — which is what a bar inside a table cell wants.
2574
+ */
2575
+ valuePosition = input('top', /* @ts-ignore */
2576
+ ...(ngDevMode ? [{ debugName: "valuePosition" }] : /* istanbul ignore next */ []));
2542
2577
  /** Running, but with no percentage to report. */
2543
2578
  indeterminate = input(false, { ...(ngDevMode ? { debugName: "indeterminate" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2544
2579
  /** Stack several fills (used now + what would arrive); clamped to 100 total. */
@@ -2594,13 +2629,13 @@ class StrctProgress {
2594
2629
  }, /* @ts-ignore */
2595
2630
  ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
2596
2631
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
2597
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctProgress, isStandalone: true, selector: "strct-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, visibleLabel: { classPropertyName: "visibleLabel", publicName: "visibleLabel", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, valueText: { classPropertyName: "valueText", publicName: "valueText", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-progress--neutral": "resolvedStatus() === 'neutral'", "class.strct-progress--success": "resolvedStatus() === 'success'", "class.strct-progress--warning": "resolvedStatus() === 'warning'", "class.strct-progress--critical": "resolvedStatus() === 'critical'" }, classAttribute: "strct-progress" }, ngImport: i0, template: `
2598
- @if (visibleLabel() || showValue()) {
2632
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctProgress, isStandalone: true, selector: "strct-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, visibleLabel: { classPropertyName: "visibleLabel", publicName: "visibleLabel", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, valueText: { classPropertyName: "valueText", publicName: "valueText", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, captionStatus: { classPropertyName: "captionStatus", publicName: "captionStatus", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, valuePosition: { classPropertyName: "valuePosition", publicName: "valuePosition", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, thresholds: { classPropertyName: "thresholds", publicName: "thresholds", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-progress--neutral": "resolvedStatus() === 'neutral'", "class.strct-progress--success": "resolvedStatus() === 'success'", "class.strct-progress--warning": "resolvedStatus() === 'warning'", "class.strct-progress--critical": "resolvedStatus() === 'critical'", "class.strct-progress--endvalue": "showValue() && valuePosition() === 'end'" }, classAttribute: "strct-progress" }, ngImport: i0, template: `
2633
+ @if (visibleLabel() || (showValue() && valuePosition() === 'top')) {
2599
2634
  <div class="strct-progress__row">
2600
2635
  @if (visibleLabel()) {
2601
2636
  <span class="strct-progress__label">{{ label() }}</span>
2602
2637
  }
2603
- @if (showValue()) {
2638
+ @if (showValue() && valuePosition() === 'top') {
2604
2639
  <span class="strct-progress__value">{{ valueText() || clamped() + '%' }}</span>
2605
2640
  }
2606
2641
  </div>
@@ -2608,7 +2643,7 @@ class StrctProgress {
2608
2643
  <div
2609
2644
  class="strct-progress__track"
2610
2645
  role="progressbar"
2611
- [attr.aria-label]="label() || 'Progress'"
2646
+ [attr.aria-label]="ariaLabel() || label() || 'Progress'"
2612
2647
  [attr.aria-valuenow]="indeterminate() ? null : clamped()"
2613
2648
  [attr.aria-valuetext]="valueDescription()"
2614
2649
  [attr.aria-valuemin]="indeterminate() ? null : 0"
@@ -2627,20 +2662,28 @@ class StrctProgress {
2627
2662
  <div class="strct-progress__fill" [style.width.%]="clamped()"></div>
2628
2663
  }
2629
2664
  </div>
2665
+ @if (showValue() && valuePosition() === 'end') {
2666
+ <!-- A bar in a cell wants its number beside the track, not above it. -->
2667
+ <span class="strct-progress__value strct-progress__value--end">{{
2668
+ valueText() || clamped() + '%'
2669
+ }}</span>
2670
+ }
2630
2671
  @if (caption()) {
2631
- <p class="strct-progress__caption">{{ caption() }}</p>
2672
+ <p class="strct-progress__caption strct-progress__caption--{{ captionStatus() ?? 'none' }}">
2673
+ {{ caption() }}
2674
+ </p>
2632
2675
  }
2633
- `, isInline: true, styles: [".strct-progress{display:block}.strct-progress__row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-2);margin-block-end:4px;font-size:var(--text-sm)}.strct-progress__label{color:var(--t2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-progress__value{color:var(--t1);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-progress__caption{margin:4px 0 0;font-size:var(--text-sm);line-height:1.5;color:var(--t3)}.strct-progress__track{position:relative;display:flex;height:6px;border-radius:var(--radius-sm);background:var(--strct-progress-track, color-mix(in srgb, var(--t1) 12%, transparent));box-shadow:inset 0 0 0 1px var(--b2);overflow:hidden}.strct-progress__fill{height:100%;border-radius:var(--radius-sm);background:var(--acc);transition:width .3s ease}.strct-progress--neutral .strct-progress__fill{background:var(--t3)}.strct-progress--success .strct-progress__fill{background:var(--success)}.strct-progress--warning .strct-progress__fill{background:var(--warning)}.strct-progress--critical .strct-progress__fill{background:var(--critical)}.strct-progress .strct-progress__fill--neutral{background:var(--t3)}.strct-progress .strct-progress__fill--accent{background:var(--acc)}.strct-progress .strct-progress__fill--success{background:var(--success)}.strct-progress .strct-progress__fill--warning{background:var(--warning)}.strct-progress .strct-progress__fill--critical{background:var(--critical)}.strct-progress__track .strct-progress__fill+.strct-progress__fill{border-start-start-radius:0;border-end-start-radius:0}.strct-progress .strct-progress__fill--indeterminate{width:35%;animation:strct-progress-sweep 1.1s ease-in-out infinite}@keyframes strct-progress-sweep{0%{transform:translate(-120%)}to{transform:translate(340%)}}@media(prefers-reduced-motion:reduce){.strct-progress .strct-progress__fill--indeterminate{width:100%;animation:none;background:repeating-linear-gradient(135deg,var(--acc) 0 6px,color-mix(in srgb,var(--acc) 45%,transparent) 6px 12px)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2676
+ `, isInline: true, styles: [".strct-progress{display:block}.strct-progress__row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-2);margin-block-end:4px;font-size:var(--text-sm)}.strct-progress__label{color:var(--t2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-progress__value{color:var(--t1);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-progress__caption{margin:4px 0 0;font-size:var(--text-sm);line-height:1.5;color:var(--t3)}.strct-progress__caption--accent{color:var(--acc)}.strct-progress__caption--success{color:var(--success)}.strct-progress__caption--warning{color:var(--warning)}.strct-progress__caption--critical{color:var(--critical)}.strct-progress--endvalue{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.strct-progress--endvalue .strct-progress__track{flex:1;min-width:0}.strct-progress__value--end{flex:none;font-size:var(--text-sm);color:var(--t2);font-variant-numeric:tabular-nums}.strct-progress--endvalue .strct-progress__caption,.strct-progress--endvalue .strct-progress__row{flex-basis:100%}.strct-progress__track{position:relative;display:flex;height:6px;border-radius:var(--radius-sm);background:var(--strct-progress-track, color-mix(in srgb, var(--t1) 12%, transparent));box-shadow:inset 0 0 0 1px var(--b2);overflow:hidden}.strct-progress__fill{height:100%;border-radius:var(--radius-sm);background:var(--acc);transition:width .3s ease}.strct-progress--neutral .strct-progress__fill{background:var(--t3)}.strct-progress--success .strct-progress__fill{background:var(--success)}.strct-progress--warning .strct-progress__fill{background:var(--warning)}.strct-progress--critical .strct-progress__fill{background:var(--critical)}.strct-progress .strct-progress__fill--neutral{background:var(--t3)}.strct-progress .strct-progress__fill--accent{background:var(--acc)}.strct-progress .strct-progress__fill--success{background:var(--success)}.strct-progress .strct-progress__fill--warning{background:var(--warning)}.strct-progress .strct-progress__fill--critical{background:var(--critical)}.strct-progress__track .strct-progress__fill+.strct-progress__fill{border-start-start-radius:0;border-end-start-radius:0}.strct-progress .strct-progress__fill--indeterminate{width:35%;animation:strct-progress-sweep 1.1s ease-in-out infinite}@keyframes strct-progress-sweep{0%{transform:translate(-120%)}to{transform:translate(340%)}}@media(prefers-reduced-motion:reduce){.strct-progress .strct-progress__fill--indeterminate{width:100%;animation:none;background:repeating-linear-gradient(135deg,var(--acc) 0 6px,color-mix(in srgb,var(--acc) 45%,transparent) 6px 12px)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2634
2677
  }
2635
2678
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctProgress, decorators: [{
2636
2679
  type: Component,
2637
2680
  args: [{ selector: 'strct-progress', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
2638
- @if (visibleLabel() || showValue()) {
2681
+ @if (visibleLabel() || (showValue() && valuePosition() === 'top')) {
2639
2682
  <div class="strct-progress__row">
2640
2683
  @if (visibleLabel()) {
2641
2684
  <span class="strct-progress__label">{{ label() }}</span>
2642
2685
  }
2643
- @if (showValue()) {
2686
+ @if (showValue() && valuePosition() === 'top') {
2644
2687
  <span class="strct-progress__value">{{ valueText() || clamped() + '%' }}</span>
2645
2688
  }
2646
2689
  </div>
@@ -2648,7 +2691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
2648
2691
  <div
2649
2692
  class="strct-progress__track"
2650
2693
  role="progressbar"
2651
- [attr.aria-label]="label() || 'Progress'"
2694
+ [attr.aria-label]="ariaLabel() || label() || 'Progress'"
2652
2695
  [attr.aria-valuenow]="indeterminate() ? null : clamped()"
2653
2696
  [attr.aria-valuetext]="valueDescription()"
2654
2697
  [attr.aria-valuemin]="indeterminate() ? null : 0"
@@ -2667,8 +2710,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
2667
2710
  <div class="strct-progress__fill" [style.width.%]="clamped()"></div>
2668
2711
  }
2669
2712
  </div>
2713
+ @if (showValue() && valuePosition() === 'end') {
2714
+ <!-- A bar in a cell wants its number beside the track, not above it. -->
2715
+ <span class="strct-progress__value strct-progress__value--end">{{
2716
+ valueText() || clamped() + '%'
2717
+ }}</span>
2718
+ }
2670
2719
  @if (caption()) {
2671
- <p class="strct-progress__caption">{{ caption() }}</p>
2720
+ <p class="strct-progress__caption strct-progress__caption--{{ captionStatus() ?? 'none' }}">
2721
+ {{ caption() }}
2722
+ </p>
2672
2723
  }
2673
2724
  `, host: {
2674
2725
  class: 'strct-progress',
@@ -2676,8 +2727,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
2676
2727
  '[class.strct-progress--success]': "resolvedStatus() === 'success'",
2677
2728
  '[class.strct-progress--warning]': "resolvedStatus() === 'warning'",
2678
2729
  '[class.strct-progress--critical]': "resolvedStatus() === 'critical'",
2679
- }, styles: [".strct-progress{display:block}.strct-progress__row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-2);margin-block-end:4px;font-size:var(--text-sm)}.strct-progress__label{color:var(--t2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-progress__value{color:var(--t1);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-progress__caption{margin:4px 0 0;font-size:var(--text-sm);line-height:1.5;color:var(--t3)}.strct-progress__track{position:relative;display:flex;height:6px;border-radius:var(--radius-sm);background:var(--strct-progress-track, color-mix(in srgb, var(--t1) 12%, transparent));box-shadow:inset 0 0 0 1px var(--b2);overflow:hidden}.strct-progress__fill{height:100%;border-radius:var(--radius-sm);background:var(--acc);transition:width .3s ease}.strct-progress--neutral .strct-progress__fill{background:var(--t3)}.strct-progress--success .strct-progress__fill{background:var(--success)}.strct-progress--warning .strct-progress__fill{background:var(--warning)}.strct-progress--critical .strct-progress__fill{background:var(--critical)}.strct-progress .strct-progress__fill--neutral{background:var(--t3)}.strct-progress .strct-progress__fill--accent{background:var(--acc)}.strct-progress .strct-progress__fill--success{background:var(--success)}.strct-progress .strct-progress__fill--warning{background:var(--warning)}.strct-progress .strct-progress__fill--critical{background:var(--critical)}.strct-progress__track .strct-progress__fill+.strct-progress__fill{border-start-start-radius:0;border-end-start-radius:0}.strct-progress .strct-progress__fill--indeterminate{width:35%;animation:strct-progress-sweep 1.1s ease-in-out infinite}@keyframes strct-progress-sweep{0%{transform:translate(-120%)}to{transform:translate(340%)}}@media(prefers-reduced-motion:reduce){.strct-progress .strct-progress__fill--indeterminate{width:100%;animation:none;background:repeating-linear-gradient(135deg,var(--acc) 0 6px,color-mix(in srgb,var(--acc) 45%,transparent) 6px 12px)}}\n"] }]
2680
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], visibleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleLabel", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], valueText: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueText", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }] } });
2730
+ '[class.strct-progress--endvalue]': "showValue() && valuePosition() === 'end'",
2731
+ }, styles: [".strct-progress{display:block}.strct-progress__row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-2);margin-block-end:4px;font-size:var(--text-sm)}.strct-progress__label{color:var(--t2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-progress__value{color:var(--t1);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-progress__caption{margin:4px 0 0;font-size:var(--text-sm);line-height:1.5;color:var(--t3)}.strct-progress__caption--accent{color:var(--acc)}.strct-progress__caption--success{color:var(--success)}.strct-progress__caption--warning{color:var(--warning)}.strct-progress__caption--critical{color:var(--critical)}.strct-progress--endvalue{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.strct-progress--endvalue .strct-progress__track{flex:1;min-width:0}.strct-progress__value--end{flex:none;font-size:var(--text-sm);color:var(--t2);font-variant-numeric:tabular-nums}.strct-progress--endvalue .strct-progress__caption,.strct-progress--endvalue .strct-progress__row{flex-basis:100%}.strct-progress__track{position:relative;display:flex;height:6px;border-radius:var(--radius-sm);background:var(--strct-progress-track, color-mix(in srgb, var(--t1) 12%, transparent));box-shadow:inset 0 0 0 1px var(--b2);overflow:hidden}.strct-progress__fill{height:100%;border-radius:var(--radius-sm);background:var(--acc);transition:width .3s ease}.strct-progress--neutral .strct-progress__fill{background:var(--t3)}.strct-progress--success .strct-progress__fill{background:var(--success)}.strct-progress--warning .strct-progress__fill{background:var(--warning)}.strct-progress--critical .strct-progress__fill{background:var(--critical)}.strct-progress .strct-progress__fill--neutral{background:var(--t3)}.strct-progress .strct-progress__fill--accent{background:var(--acc)}.strct-progress .strct-progress__fill--success{background:var(--success)}.strct-progress .strct-progress__fill--warning{background:var(--warning)}.strct-progress .strct-progress__fill--critical{background:var(--critical)}.strct-progress__track .strct-progress__fill+.strct-progress__fill{border-start-start-radius:0;border-end-start-radius:0}.strct-progress .strct-progress__fill--indeterminate{width:35%;animation:strct-progress-sweep 1.1s ease-in-out infinite}@keyframes strct-progress-sweep{0%{transform:translate(-120%)}to{transform:translate(340%)}}@media(prefers-reduced-motion:reduce){.strct-progress .strct-progress__fill--indeterminate{width:100%;animation:none;background:repeating-linear-gradient(135deg,var(--acc) 0 6px,color-mix(in srgb,var(--acc) 45%,transparent) 6px 12px)}}\n"] }]
2732
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], visibleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleLabel", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], valueText: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueText", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], captionStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionStatus", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], valuePosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "valuePosition", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }] } });
2681
2733
 
2682
2734
  /** Indeterminate loading ring. `<strct-spinner size="sm" />`. */
2683
2735
  class StrctSpinner {
@@ -5445,6 +5497,13 @@ class StrctDropdown {
5445
5497
  /** Accessible name of the popover dialog (localizable). */
5446
5498
  popoverLabel = input('Filters', /* @ts-ignore */
5447
5499
  ...(ngDevMode ? [{ debugName: "popoverLabel" }] : /* istanbul ignore next */ []));
5500
+ /**
5501
+ * Only with `popover`: the panel's rows are controls in their own right — a
5502
+ * theme switcher, a filter — so they keep a real tab stop instead of the
5503
+ * `tabindex="-1"` a menu's items carry. Without it nothing inside a popover
5504
+ * can be reached from the keyboard at all.
5505
+ */
5506
+ focusable = input(false, { ...(ngDevMode ? { debugName: "focusable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5448
5507
  open = signal(false, /* @ts-ignore */
5449
5508
  ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
5450
5509
  constructor() {
@@ -5590,7 +5649,7 @@ class StrctDropdown {
5590
5649
  this.close(true);
5591
5650
  }
5592
5651
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
5593
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDropdown, isStandalone: true, selector: "strct-dropdown", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, popover: { classPropertyName: "popover", publicName: "popover", isSignal: true, isRequired: false, transformFunction: null }, popoverLabel: { classPropertyName: "popoverLabel", publicName: "popoverLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape()" }, classAttribute: "strct-dd" }, ngImport: i0, template: `
5652
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDropdown, isStandalone: true, selector: "strct-dropdown", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, popover: { classPropertyName: "popover", publicName: "popover", isSignal: true, isRequired: false, transformFunction: null }, popoverLabel: { classPropertyName: "popoverLabel", publicName: "popoverLabel", isSignal: true, isRequired: false, transformFunction: null }, focusable: { classPropertyName: "focusable", publicName: "focusable", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape()" }, classAttribute: "strct-dd" }, ngImport: i0, template: `
5594
5653
  <!--
5595
5654
  The wrapper is intentionally inert: the projected trigger should be a
5596
5655
  real button (nesting interactives fails axe). Its native click —
@@ -5653,7 +5712,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
5653
5712
  </div>
5654
5713
  }
5655
5714
  `, host: { class: 'strct-dd' }, styles: [".strct-dd{position:relative;display:inline-block}.strct-dd__trigger{display:inline-flex}.strct-dd__menu{position:absolute;top:calc(100% + 4px);left:0;z-index:var(--z-dropdown);min-width:170px;max-width:calc(100vw - 24px);padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-dd-in .1s ease}.strct-dd__menu--end{left:auto;right:0}.strct-dd__menu--popover{min-width:240px;padding:12px 14px}@keyframes strct-dd-in{0%{opacity:0;transform:translateY(-4px)}}\n"] }]
5656
- }], ctorParameters: () => [], propDecorators: { align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], popover: [{ type: i0.Input, args: [{ isSignal: true, alias: "popover", required: false }] }], popoverLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverLabel", required: false }] }], onDocClick: [{
5715
+ }], ctorParameters: () => [], propDecorators: { align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], popover: [{ type: i0.Input, args: [{ isSignal: true, alias: "popover", required: false }] }], popoverLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverLabel", required: false }] }], focusable: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusable", required: false }] }], onDocClick: [{
5657
5716
  type: HostListener,
5658
5717
  args: ['document:click', ['$event']]
5659
5718
  }], onEscape: [{
@@ -5736,6 +5795,19 @@ class StrctDropdownItem {
5736
5795
  hint = input(null, /* @ts-ignore */
5737
5796
  ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
5738
5797
  hintId = `strct-dd-item-${++dropdownItemCounter}-hint`;
5798
+ /** The panel this row belongs to, when it is inside one. */
5799
+ panel = inject(StrctDropdown, { optional: true });
5800
+ /**
5801
+ * A menu's rows are roved with the arrow keys, so they stay out of the tab
5802
+ * order. A `popover [focusable]` is a panel of real controls, and its rows
5803
+ * keep a tab stop of their own.
5804
+ */
5805
+ tabindex = computed(() => {
5806
+ if (this.disabled() && !this.hint())
5807
+ return null;
5808
+ return this.panel?.popover() && this.panel.focusable() ? 0 : -1;
5809
+ }, /* @ts-ignore */
5810
+ ...(ngDevMode ? [{ debugName: "tabindex" }] : /* istanbul ignore next */ []));
5739
5811
  constructor() {
5740
5812
  // Without pointer-events:none (see the hinted style), a disabled item
5741
5813
  // would pass clicks to the consumer's (click). Capture-phase at the target
@@ -5750,7 +5822,7 @@ class StrctDropdownItem {
5750
5822
  }, { capture: true });
5751
5823
  }
5752
5824
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDropdownItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
5753
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDropdownItem, isStandalone: true, selector: "strct-dropdown-item", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, critical: { classPropertyName: "critical", publicName: "critical", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "selected() === null ? 'menuitem' : 'menuitemradio'", "attr.aria-checked": "selected()", "attr.tabindex": "disabled() && !hint() ? null : -1", "attr.title": "hint() || null", "attr.aria-describedby": "hint() ? hintId : null", "class.strct-dd__item--hinted": "!!hint()", "class.strct-dd__item--critical": "critical()", "class.strct-dd__item--selected": "selected() === true", "attr.aria-disabled": "disabled() || null" }, classAttribute: "strct-dd__item" }, ngImport: i0, template: `@if (selected() !== null) {
5825
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDropdownItem, isStandalone: true, selector: "strct-dropdown-item", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, critical: { classPropertyName: "critical", publicName: "critical", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "selected() === null ? 'menuitem' : 'menuitemradio'", "attr.aria-checked": "selected()", "attr.tabindex": "tabindex()", "attr.title": "hint() || null", "attr.aria-describedby": "hint() ? hintId : null", "class.strct-dd__item--hinted": "!!hint()", "class.strct-dd__item--critical": "critical()", "class.strct-dd__item--selected": "selected() === true", "attr.aria-disabled": "disabled() || null" }, classAttribute: "strct-dd__item" }, ngImport: i0, template: `@if (selected() !== null) {
5754
5826
  <span class="strct-dd__check" aria-hidden="true">
5755
5827
  @if (selected()) {
5756
5828
  <strct-icon strictName="check" [size]="12" [strokeWidth]="1.8" />
@@ -5789,7 +5861,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
5789
5861
  '[attr.role]': "selected() === null ? 'menuitem' : 'menuitemradio'",
5790
5862
  '[attr.aria-checked]': 'selected()',
5791
5863
  // A disabled item is skipped — unless it has a hint to be read.
5792
- '[attr.tabindex]': 'disabled() && !hint() ? null : -1',
5864
+ '[attr.tabindex]': 'tabindex()',
5793
5865
  '[attr.title]': 'hint() || null',
5794
5866
  '[attr.aria-describedby]': 'hint() ? hintId : null',
5795
5867
  '[class.strct-dd__item--hinted]': '!!hint()',
@@ -9892,6 +9964,11 @@ class StrctInputOtp {
9892
9964
  */
9893
9965
  groupSize = input(0, /* @ts-ignore */
9894
9966
  ...(ngDevMode ? [{ debugName: "groupSize" }] : /* istanbul ignore next */ []));
9967
+ /**
9968
+ * Spread the boxes across the full width, so the code lines up with a
9969
+ * full-width button under it rather than huddling at the start of the row.
9970
+ */
9971
+ fill = input(false, { ...(ngDevMode ? { debugName: "fill" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
9895
9972
  slots = signal([], /* @ts-ignore */
9896
9973
  ...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
9897
9974
  isDisabled = signal(false, /* @ts-ignore */
@@ -9976,10 +10053,10 @@ class StrctInputOtp {
9976
10053
  this.isDisabled.set(isDisabled);
9977
10054
  }
9978
10055
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctInputOtp, deps: [], target: i0.ɵɵFactoryTarget.Component });
9979
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctInputOtp, isStandalone: true, selector: "strct-input-otp", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, masked: { classPropertyName: "masked", publicName: "masked", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, groupSize: { classPropertyName: "groupSize", publicName: "groupSize", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
10056
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctInputOtp, isStandalone: true, selector: "strct-input-otp", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, masked: { classPropertyName: "masked", publicName: "masked", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, groupSize: { classPropertyName: "groupSize", publicName: "groupSize", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
9980
10057
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctInputOtp), multi: true },
9981
10058
  ], ngImport: i0, template: `
9982
- <div class="strct-otp">
10059
+ <div class="strct-otp" [class.strct-otp--fill]="fill()">
9983
10060
  @for (i of indices(); track i) {
9984
10061
  @if (groupSize() > 0 && i > 0 && i % groupSize() === 0) {
9985
10062
  <span class="strct-otp__sep" aria-hidden="true">–</span>
@@ -9999,14 +10076,14 @@ class StrctInputOtp {
9999
10076
  />
10000
10077
  }
10001
10078
  </div>
10002
- `, isInline: true, styles: [".strct-otp{display:inline-flex;align-items:center;gap:8px}.strct-otp__sep{margin-inline:3px;color:var(--t3);font-size:16px;-webkit-user-select:none;user-select:none}.strct-otp__box{width:40px;height:46px;text-align:center;font-family:var(--mono);font-size:18px;color:var(--t1);background:var(--bg-2);border:1px solid var(--b2);border-radius:8px;transition:border-color .14s ease,box-shadow .14s ease,background .14s ease}.strct-otp__box:focus{outline:none;border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-otp__box:disabled{opacity:.5}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10079
+ `, isInline: true, styles: [".strct-otp{display:inline-flex;align-items:center;gap:8px}.strct-otp--fill{display:flex;width:100%}.strct-otp--fill .strct-otp__box{flex:1;min-width:0}.strct-otp__sep{margin-inline:3px;color:var(--t3);font-size:16px;-webkit-user-select:none;user-select:none}.strct-otp__box{width:40px;height:46px;text-align:center;font-family:var(--mono);font-size:18px;color:var(--t1);background:var(--bg-2);border:1px solid var(--b2);border-radius:8px;transition:border-color .14s ease,box-shadow .14s ease,background .14s ease}.strct-otp__box:focus{outline:none;border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-otp__box:disabled{opacity:.5}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10003
10080
  }
10004
10081
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctInputOtp, decorators: [{
10005
10082
  type: Component,
10006
10083
  args: [{ selector: 'strct-input-otp', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
10007
10084
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StrctInputOtp), multi: true },
10008
10085
  ], template: `
10009
- <div class="strct-otp">
10086
+ <div class="strct-otp" [class.strct-otp--fill]="fill()">
10010
10087
  @for (i of indices(); track i) {
10011
10088
  @if (groupSize() > 0 && i > 0 && i % groupSize() === 0) {
10012
10089
  <span class="strct-otp__sep" aria-hidden="true">–</span>
@@ -10026,8 +10103,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
10026
10103
  />
10027
10104
  }
10028
10105
  </div>
10029
- `, styles: [".strct-otp{display:inline-flex;align-items:center;gap:8px}.strct-otp__sep{margin-inline:3px;color:var(--t3);font-size:16px;-webkit-user-select:none;user-select:none}.strct-otp__box{width:40px;height:46px;text-align:center;font-family:var(--mono);font-size:18px;color:var(--t1);background:var(--bg-2);border:1px solid var(--b2);border-radius:8px;transition:border-color .14s ease,box-shadow .14s ease,background .14s ease}.strct-otp__box:focus{outline:none;border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-otp__box:disabled{opacity:.5}\n"] }]
10030
- }], ctorParameters: () => [], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], masked: [{ type: i0.Input, args: [{ isSignal: true, alias: "masked", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], groupSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupSize", required: false }] }] } });
10106
+ `, styles: [".strct-otp{display:inline-flex;align-items:center;gap:8px}.strct-otp--fill{display:flex;width:100%}.strct-otp--fill .strct-otp__box{flex:1;min-width:0}.strct-otp__sep{margin-inline:3px;color:var(--t3);font-size:16px;-webkit-user-select:none;user-select:none}.strct-otp__box{width:40px;height:46px;text-align:center;font-family:var(--mono);font-size:18px;color:var(--t1);background:var(--bg-2);border:1px solid var(--b2);border-radius:8px;transition:border-color .14s ease,box-shadow .14s ease,background .14s ease}.strct-otp__box:focus{outline:none;border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-otp__box:disabled{opacity:.5}\n"] }]
10107
+ }], ctorParameters: () => [], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], masked: [{ type: i0.Input, args: [{ isSignal: true, alias: "masked", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], groupSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupSize", required: false }] }], fill: [{ type: i0.Input, args: [{ isSignal: true, alias: "fill", required: false }] }] } });
10031
10108
 
10032
10109
  const COLOR$3 = {
10033
10110
  accent: 'var(--acc)',
@@ -19633,16 +19710,33 @@ class StrctHero {
19633
19710
  /** Tighter padding for secondary placements. */
19634
19711
  dense = input(false, { ...(ngDevMode ? { debugName: "dense" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
19635
19712
  /**
19636
- * Opt into a polite live region (role="status") for banners whose content
19637
- * updates after load; static banners should leave this off. Critical heroes
19638
- * are always role="alert" regardless.
19713
+ * How the banner announces itself. `true` opts a non-critical hero into a
19714
+ * polite live region (`role="status"`), for content that updates after load.
19715
+ * `'polite'` and `'assertive'` say it outright, whatever the status — a page
19716
+ * that renders its verdict on navigation wants `'polite'`, so a critical
19717
+ * hero does not interrupt on every load.
19639
19718
  */
19640
- live = input(false, { ...(ngDevMode ? { debugName: "live" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
19719
+ live = input(false, { ...(ngDevMode ? { debugName: "live" } : /* istanbul ignore next */ {}), transform: (v) => v === 'assertive' || v === 'polite' ? v : booleanAttribute(v) });
19720
+ /**
19721
+ * A critical hero interrupts by default, because it usually appears in
19722
+ * answer to something the user did. A page that renders a verdict on
19723
+ * navigation would interrupt on every load instead, so `live="polite"` makes
19724
+ * it a `status`; `live="assertive"` asks for `alert` whatever the status.
19725
+ */
19726
+ liveRole = computed(() => {
19727
+ const live = this.live();
19728
+ if (live === 'polite')
19729
+ return 'status';
19730
+ if (live === 'assertive')
19731
+ return 'alert';
19732
+ return this.status() === 'critical' ? 'alert' : live ? 'status' : null;
19733
+ }, /* @ts-ignore */
19734
+ ...(ngDevMode ? [{ debugName: "liveRole" }] : /* istanbul ignore next */ []));
19641
19735
  headingId = `strct-hero-${++heroCounter}`;
19642
19736
  resolvedIcon = computed(() => this.icon() || DEFAULT_ICON[this.status()], /* @ts-ignore */
19643
19737
  ...(ngDevMode ? [{ debugName: "resolvedIcon" }] : /* istanbul ignore next */ []));
19644
19738
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctHero, deps: [], target: i0.ɵɵFactoryTarget.Component });
19645
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctHero, isStandalone: true, selector: "strct-hero", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-hero--accent": "status() === 'accent'", "class.strct-hero--success": "status() === 'success'", "class.strct-hero--warning": "status() === 'warning'", "class.strct-hero--critical": "status() === 'critical'", "class.strct-hero--dense": "dense()", "attr.role": "status() === 'critical' ? 'alert' : live() ? 'status' : null", "attr.aria-labelledby": "headingId" }, classAttribute: "strct-hero" }, ngImport: i0, template: `
19739
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctHero, isStandalone: true, selector: "strct-hero", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, live: { classPropertyName: "live", publicName: "live", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-hero--accent": "status() === 'accent'", "class.strct-hero--success": "status() === 'success'", "class.strct-hero--warning": "status() === 'warning'", "class.strct-hero--critical": "status() === 'critical'", "class.strct-hero--dense": "dense()", "attr.role": "liveRole()", "attr.aria-labelledby": "headingId" }, classAttribute: "strct-hero" }, ngImport: i0, template: `
19646
19740
  <span class="strct-hero__chip" aria-hidden="true">
19647
19741
  <strct-icon [name]="resolvedIcon()" [size]="dense() ? 16 : 18" />
19648
19742
  </span>
@@ -19681,7 +19775,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
19681
19775
  '[class.strct-hero--warning]': "status() === 'warning'",
19682
19776
  '[class.strct-hero--critical]': "status() === 'critical'",
19683
19777
  '[class.strct-hero--dense]': 'dense()',
19684
- '[attr.role]': "status() === 'critical' ? 'alert' : live() ? 'status' : null",
19778
+ '[attr.role]': 'liveRole()',
19685
19779
  '[attr.aria-labelledby]': 'headingId',
19686
19780
  }, styles: [".strct-hero{display:flex;align-items:flex-start;flex-wrap:wrap;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-radius:var(--radius-lg);background:var(--bg-1);border:1px solid var(--b2);border-inline-start:3px solid var(--b3)}.strct-hero--dense{padding:var(--space-3) var(--space-4);gap:var(--space-2)}.strct-hero__chip{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;flex-shrink:0;background:var(--bg-a);color:var(--t2)}.strct-hero--dense .strct-hero__chip{width:28px;height:28px}.strct-hero__text{flex:1 1 280px;min-width:0;display:flex;flex-direction:column;gap:3px}.strct-hero__heading{margin:0;font-size:var(--text-xl);font-weight:650;letter-spacing:-.01em;color:var(--t1);line-height:var(--leading-tight)}.strct-hero--dense .strct-hero__heading{font-size:var(--text-lg)}.strct-hero__desc{font-size:var(--text-md);color:var(--t2);line-height:var(--leading-normal)}.strct-hero__desc:empty{display:none}.strct-hero__aside{display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-2);margin-inline-start:auto}.strct-hero__meta,.strct-hero__actions{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2);justify-content:flex-end}.strct-hero__meta:empty,.strct-hero__actions:empty{display:none}.strct-hero__aside:not(:has(*:not(:empty))){display:none}.strct-hero--accent{border-inline-start-color:var(--acc)}.strct-hero--accent .strct-hero__chip{background:var(--acc);color:var(--inv)}.strct-hero--success{border-inline-start-color:var(--success)}.strct-hero--success .strct-hero__chip{background:var(--success);color:var(--inv)}.strct-hero--warning{border-inline-start-color:var(--warning)}.strct-hero--warning .strct-hero__chip{background:var(--warning);color:var(--inv)}.strct-hero--critical{border-inline-start-color:var(--critical)}.strct-hero--critical .strct-hero__chip{background:var(--critical);color:var(--inv)}@media(max-width:560px){.strct-hero__aside{margin-inline-start:0;align-items:stretch;width:100%}.strct-hero__meta,.strct-hero__actions{justify-content:flex-start}}\n"] }]
19687
19781
  }], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], dense: [{ type: i0.Input, args: [{ isSignal: true, alias: "dense", required: false }] }], live: [{ type: i0.Input, args: [{ isSignal: true, alias: "live", required: false }] }] } });
@@ -20289,6 +20383,13 @@ class StrctEmptyState {
20289
20383
  ...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
20290
20384
  title = input.required(/* @ts-ignore */
20291
20385
  ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
20386
+ /**
20387
+ * Which heading element the title is. `null` renders a `<p>` — what a
20388
+ * loading state inside a card wants, since it should not add a heading to
20389
+ * the page outline.
20390
+ */
20391
+ titleLevel = input(3, /* @ts-ignore */
20392
+ ...(ngDevMode ? [{ debugName: "titleLevel" }] : /* istanbul ignore next */ []));
20292
20393
  /**
20293
20394
  * `sm` is the inline row a 240px frame wants: a 16px icon with the title and
20294
20395
  * description on one line. A page-sized empty state stays `md`.
@@ -20302,7 +20403,7 @@ class StrctEmptyState {
20302
20403
  toneClass = computed(() => this.tone() || VARIANTS[this.variant()].tone, /* @ts-ignore */
20303
20404
  ...(ngDevMode ? [{ debugName: "toneClass" }] : /* istanbul ignore next */ []));
20304
20405
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctEmptyState, deps: [], target: i0.ɵɵFactoryTarget.Component });
20305
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctEmptyState, isStandalone: true, selector: "strct-empty-state", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-empty--sm": "size() === 'sm'", "attr.aria-busy": "variant() === 'loading' ? 'true' : null" }, classAttribute: "strct-empty" }, ngImport: i0, template: `
20406
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctEmptyState, isStandalone: true, selector: "strct-empty-state", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, titleLevel: { classPropertyName: "titleLevel", publicName: "titleLevel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-empty--sm": "size() === 'sm'", "attr.aria-busy": "variant() === 'loading' ? 'true' : null" }, classAttribute: "strct-empty" }, ngImport: i0, template: `
20306
20407
  <span class="strct-empty__icon strct-empty__icon--{{ toneClass() }}">
20307
20408
  @if (variant() === 'loading') {
20308
20409
  <strct-spinner [size]="size() === 'sm' ? 'sm' : 'md'" [label]="title()" />
@@ -20314,12 +20415,33 @@ class StrctEmptyState {
20314
20415
  />
20315
20416
  }
20316
20417
  </span>
20317
- <h3 class="strct-empty__title">{{ title() }}</h3>
20418
+ <!-- A zero state on a page is a heading; a loading state inside a card is
20419
+ not, and an outline that gains an h3 while data loads is noise. -->
20420
+ @switch (titleLevel()) {
20421
+ @case (2) {
20422
+ <h2 class="strct-empty__title">{{ title() }}</h2>
20423
+ }
20424
+ @case (3) {
20425
+ <h3 class="strct-empty__title">{{ title() }}</h3>
20426
+ }
20427
+ @case (4) {
20428
+ <h4 class="strct-empty__title">{{ title() }}</h4>
20429
+ }
20430
+ @case (5) {
20431
+ <h5 class="strct-empty__title">{{ title() }}</h5>
20432
+ }
20433
+ @case (6) {
20434
+ <h6 class="strct-empty__title">{{ title() }}</h6>
20435
+ }
20436
+ @default {
20437
+ <p class="strct-empty__title">{{ title() }}</p>
20438
+ }
20439
+ }
20318
20440
  @if (description()) {
20319
20441
  <p class="strct-empty__desc">{{ description() }}</p>
20320
20442
  }
20321
20443
  <div class="strct-empty__actions"><ng-content /></div>
20322
- `, isInline: true, styles: [".strct-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;padding:40px 24px}.strct-empty__icon{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:14px;margin-bottom:2px}.strct-empty__icon--neutral{background:var(--bg-3);color:var(--t2)}.strct-empty__icon--warning{background:var(--warning-bg);color:var(--warning)}.strct-empty__icon--critical{background:var(--critical-bg);color:var(--critical)}.strct-empty__icon--accent{background:var(--acc-m);color:var(--acc)}.strct-empty__title{margin:0;font-size:15px;font-weight:600;color:var(--t1)}.strct-empty__desc{margin:0;max-width:360px;font-size:13px;line-height:1.5;color:var(--t3)}.strct-empty--sm{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px var(--space-2);text-align:start;padding:var(--space-3)}.strct-empty--sm .strct-empty__icon{width:16px;height:16px;border-radius:0;margin-bottom:0;background:none;grid-row:1}.strct-empty--sm .strct-empty__title{font-size:13px;grid-row:1}.strct-empty--sm .strct-empty__desc,.strct-empty--sm .strct-empty__actions{grid-column:2}.strct-empty--sm .strct-empty__desc{font-size:var(--text-sm);max-width:none}.strct-empty--sm .strct-empty__actions:empty{display:none}.strct-empty__actions{display:flex;align-items:center;gap:8px;margin-top:6px}.strct-empty__actions:empty{display:none}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20444
+ `, isInline: true, styles: [".strct-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;padding:40px 24px}.strct-empty__icon{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:14px;margin-bottom:2px}.strct-empty__icon--neutral{background:var(--bg-3);color:var(--t2)}.strct-empty__icon--warning{background:var(--warning-bg);color:var(--warning)}.strct-empty__icon--critical{background:var(--critical-bg);color:var(--critical)}.strct-empty__icon--accent{background:var(--acc-m);color:var(--acc)}.strct-empty__title{margin:0;font:inherit;font-size:15px;font-weight:600;color:var(--t1)}.strct-empty__desc{margin:0;max-width:360px;font-size:13px;line-height:1.5;color:var(--t3)}.strct-empty--sm{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px var(--space-2);text-align:start;padding:var(--space-3)}.strct-empty--sm .strct-empty__icon{width:16px;height:16px;border-radius:0;margin-bottom:0;background:none;grid-row:1}.strct-empty--sm .strct-empty__title{font-size:13px;grid-row:1}.strct-empty--sm .strct-empty__desc,.strct-empty--sm .strct-empty__actions{grid-column:2}.strct-empty--sm .strct-empty__desc{font-size:var(--text-sm);max-width:none}.strct-empty--sm .strct-empty__actions:empty{display:none}.strct-empty__actions{display:flex;align-items:center;gap:8px;margin-top:6px}.strct-empty__actions:empty{display:none}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20323
20445
  }
20324
20446
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctEmptyState, decorators: [{
20325
20447
  type: Component,
@@ -20335,7 +20457,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
20335
20457
  />
20336
20458
  }
20337
20459
  </span>
20338
- <h3 class="strct-empty__title">{{ title() }}</h3>
20460
+ <!-- A zero state on a page is a heading; a loading state inside a card is
20461
+ not, and an outline that gains an h3 while data loads is noise. -->
20462
+ @switch (titleLevel()) {
20463
+ @case (2) {
20464
+ <h2 class="strct-empty__title">{{ title() }}</h2>
20465
+ }
20466
+ @case (3) {
20467
+ <h3 class="strct-empty__title">{{ title() }}</h3>
20468
+ }
20469
+ @case (4) {
20470
+ <h4 class="strct-empty__title">{{ title() }}</h4>
20471
+ }
20472
+ @case (5) {
20473
+ <h5 class="strct-empty__title">{{ title() }}</h5>
20474
+ }
20475
+ @case (6) {
20476
+ <h6 class="strct-empty__title">{{ title() }}</h6>
20477
+ }
20478
+ @default {
20479
+ <p class="strct-empty__title">{{ title() }}</p>
20480
+ }
20481
+ }
20339
20482
  @if (description()) {
20340
20483
  <p class="strct-empty__desc">{{ description() }}</p>
20341
20484
  }
@@ -20344,8 +20487,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
20344
20487
  class: 'strct-empty',
20345
20488
  '[class.strct-empty--sm]': "size() === 'sm'",
20346
20489
  '[attr.aria-busy]': "variant() === 'loading' ? 'true' : null",
20347
- }, styles: [".strct-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;padding:40px 24px}.strct-empty__icon{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:14px;margin-bottom:2px}.strct-empty__icon--neutral{background:var(--bg-3);color:var(--t2)}.strct-empty__icon--warning{background:var(--warning-bg);color:var(--warning)}.strct-empty__icon--critical{background:var(--critical-bg);color:var(--critical)}.strct-empty__icon--accent{background:var(--acc-m);color:var(--acc)}.strct-empty__title{margin:0;font-size:15px;font-weight:600;color:var(--t1)}.strct-empty__desc{margin:0;max-width:360px;font-size:13px;line-height:1.5;color:var(--t3)}.strct-empty--sm{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px var(--space-2);text-align:start;padding:var(--space-3)}.strct-empty--sm .strct-empty__icon{width:16px;height:16px;border-radius:0;margin-bottom:0;background:none;grid-row:1}.strct-empty--sm .strct-empty__title{font-size:13px;grid-row:1}.strct-empty--sm .strct-empty__desc,.strct-empty--sm .strct-empty__actions{grid-column:2}.strct-empty--sm .strct-empty__desc{font-size:var(--text-sm);max-width:none}.strct-empty--sm .strct-empty__actions:empty{display:none}.strct-empty__actions{display:flex;align-items:center;gap:8px;margin-top:6px}.strct-empty__actions:empty{display:none}\n"] }]
20348
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }] } });
20490
+ }, styles: [".strct-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;padding:40px 24px}.strct-empty__icon{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;border-radius:14px;margin-bottom:2px}.strct-empty__icon--neutral{background:var(--bg-3);color:var(--t2)}.strct-empty__icon--warning{background:var(--warning-bg);color:var(--warning)}.strct-empty__icon--critical{background:var(--critical-bg);color:var(--critical)}.strct-empty__icon--accent{background:var(--acc-m);color:var(--acc)}.strct-empty__title{margin:0;font:inherit;font-size:15px;font-weight:600;color:var(--t1)}.strct-empty__desc{margin:0;max-width:360px;font-size:13px;line-height:1.5;color:var(--t3)}.strct-empty--sm{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:2px var(--space-2);text-align:start;padding:var(--space-3)}.strct-empty--sm .strct-empty__icon{width:16px;height:16px;border-radius:0;margin-bottom:0;background:none;grid-row:1}.strct-empty--sm .strct-empty__title{font-size:13px;grid-row:1}.strct-empty--sm .strct-empty__desc,.strct-empty--sm .strct-empty__actions{grid-column:2}.strct-empty--sm .strct-empty__desc{font-size:var(--text-sm);max-width:none}.strct-empty--sm .strct-empty__actions:empty{display:none}.strct-empty__actions{display:flex;align-items:center;gap:8px;margin-top:6px}.strct-empty__actions:empty{display:none}\n"] }]
20491
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], titleLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleLevel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }] } });
20349
20492
 
20350
20493
  /**
20351
20494
  * Unit formatting for infrastructure consoles — bytes, rates, durations and
@@ -20703,7 +20846,7 @@ class StrctTimeRangePicker {
20703
20846
  </div>
20704
20847
  </div>
20705
20848
  </strct-dropdown>
20706
- `, isInline: true, styles: [".strct-tr{display:inline-block}.strct-tr__trigger .strct-tr__label{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-tr__panel{display:flex;gap:16px}.strct-tr__group{display:flex;flex-direction:column;gap:2px;min-width:150px}.strct-tr__head{font-size:10.5px;font-weight:600;letter-spacing:.7px;text-transform:uppercase;color:var(--t3);margin-bottom:5px}.strct-tr__preset{text-align:start;padding:6px 9px;border:0;border-radius:var(--radius-sm);background:transparent;font-family:var(--font);font-size:12.5px;color:var(--t1);cursor:pointer}.strct-tr__preset:hover{background:var(--bg-3)}.strct-tr__preset--active{background:var(--acc18);color:var(--acc);font-weight:600}.strct-tr__preset:focus-visible,.strct-tr__input:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-tr__field{display:flex;flex-direction:column;gap:3px;font-size:11.5px;color:var(--t2);margin-bottom:7px}.strct-tr__input{padding:5px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:var(--bg-2);color:var(--t1);font-family:var(--font);font-size:12px}.strct-tr__error{font-size:11.5px;color:var(--critical);margin-bottom:6px}.strct-tr__apply{align-self:flex-start}\n"], dependencies: [{ kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }, { kind: "component", type: StrctDropdown, selector: "strct-dropdown", inputs: ["align", "popover", "popoverLabel"] }, { kind: "directive", type: StrctDropdownTrigger, selector: "[strctDropdownTrigger]" }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20849
+ `, isInline: true, styles: [".strct-tr{display:inline-block}.strct-tr__trigger .strct-tr__label{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-tr__panel{display:flex;gap:16px}.strct-tr__group{display:flex;flex-direction:column;gap:2px;min-width:150px}.strct-tr__head{font-size:10.5px;font-weight:600;letter-spacing:.7px;text-transform:uppercase;color:var(--t3);margin-bottom:5px}.strct-tr__preset{text-align:start;padding:6px 9px;border:0;border-radius:var(--radius-sm);background:transparent;font-family:var(--font);font-size:12.5px;color:var(--t1);cursor:pointer}.strct-tr__preset:hover{background:var(--bg-3)}.strct-tr__preset--active{background:var(--acc18);color:var(--acc);font-weight:600}.strct-tr__preset:focus-visible,.strct-tr__input:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-tr__field{display:flex;flex-direction:column;gap:3px;font-size:11.5px;color:var(--t2);margin-bottom:7px}.strct-tr__input{padding:5px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:var(--bg-2);color:var(--t1);font-family:var(--font);font-size:12px}.strct-tr__error{font-size:11.5px;color:var(--critical);margin-bottom:6px}.strct-tr__apply{align-self:flex-start}\n"], dependencies: [{ kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }, { kind: "component", type: StrctDropdown, selector: "strct-dropdown", inputs: ["align", "popover", "popoverLabel", "focusable"] }, { kind: "directive", type: StrctDropdownTrigger, selector: "[strctDropdownTrigger]" }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20707
20850
  }
20708
20851
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctTimeRangePicker, decorators: [{
20709
20852
  type: Component,
@@ -22225,7 +22368,7 @@ class StrctSplitButton {
22225
22368
  }
22226
22369
  </strct-dropdown>
22227
22370
  </div>
22228
- `, isInline: true, styles: [".strct-sbt{display:inline-flex;align-items:stretch}.strct-sbt .strct-dd{display:inline-flex;align-self:stretch}.strct-sbt .strct-dd__trigger{display:inline-flex;align-items:stretch}.strct-sbt__chev{align-self:stretch;height:100%}.strct-sbt__main,.strct-sbt__chev{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--acc);background:transparent;color:var(--acc);font-family:var(--font);font-size:13px;font-weight:600;line-height:1;cursor:pointer;padding:var(--space-2) var(--space-4)}.strct-sbt__main{border-start-start-radius:var(--radius-md);border-end-start-radius:var(--radius-md);border-inline-end:0}.strct-sbt__chev{padding:var(--space-2);border-start-end-radius:var(--radius-md);border-end-end-radius:var(--radius-md);border-inline-start:1px solid var(--acc50)}.strct-sbt--solid .strct-sbt__main,.strct-sbt--solid .strct-sbt__chev{background:var(--acc);color:var(--inv)}.strct-sbt--solid .strct-sbt__chev{border-inline-start-color:color-mix(in srgb,var(--inv) 30%,var(--acc))}.strct-sbt__main:hover:not(:disabled),.strct-sbt__chev:hover:not(:disabled){background:var(--acc18)}.strct-sbt--solid .strct-sbt__main:hover:not(:disabled),.strct-sbt--solid .strct-sbt__chev:hover:not(:disabled){filter:brightness(1.08);background:var(--acc)}.strct-sbt__main:disabled,.strct-sbt__chev:disabled{opacity:.5;cursor:default}.strct-sbt__main:focus-visible,.strct-sbt__chev:focus-visible{outline:2px solid var(--acc50);outline-offset:1px;position:relative;z-index:var(--z-base)}\n"], dependencies: [{ kind: "component", type: StrctDropdown, selector: "strct-dropdown", inputs: ["align", "popover", "popoverLabel"] }, { kind: "component", type: StrctDropdownDivider, selector: "strct-dropdown-divider" }, { kind: "component", type: StrctDropdownItem, selector: "strct-dropdown-item", inputs: ["selected", "critical", "disabled", "hint"] }, { kind: "directive", type: StrctDropdownTrigger, selector: "[strctDropdownTrigger]" }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
22371
+ `, isInline: true, styles: [".strct-sbt{display:inline-flex;align-items:stretch}.strct-sbt .strct-dd{display:inline-flex;align-self:stretch}.strct-sbt .strct-dd__trigger{display:inline-flex;align-items:stretch}.strct-sbt__chev{align-self:stretch;height:100%}.strct-sbt__main,.strct-sbt__chev{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--acc);background:transparent;color:var(--acc);font-family:var(--font);font-size:13px;font-weight:600;line-height:1;cursor:pointer;padding:var(--space-2) var(--space-4)}.strct-sbt__main{border-start-start-radius:var(--radius-md);border-end-start-radius:var(--radius-md);border-inline-end:0}.strct-sbt__chev{padding:var(--space-2);border-start-end-radius:var(--radius-md);border-end-end-radius:var(--radius-md);border-inline-start:1px solid var(--acc50)}.strct-sbt--solid .strct-sbt__main,.strct-sbt--solid .strct-sbt__chev{background:var(--acc);color:var(--inv)}.strct-sbt--solid .strct-sbt__chev{border-inline-start-color:color-mix(in srgb,var(--inv) 30%,var(--acc))}.strct-sbt__main:hover:not(:disabled),.strct-sbt__chev:hover:not(:disabled){background:var(--acc18)}.strct-sbt--solid .strct-sbt__main:hover:not(:disabled),.strct-sbt--solid .strct-sbt__chev:hover:not(:disabled){filter:brightness(1.08);background:var(--acc)}.strct-sbt__main:disabled,.strct-sbt__chev:disabled{opacity:.5;cursor:default}.strct-sbt__main:focus-visible,.strct-sbt__chev:focus-visible{outline:2px solid var(--acc50);outline-offset:1px;position:relative;z-index:var(--z-base)}\n"], dependencies: [{ kind: "component", type: StrctDropdown, selector: "strct-dropdown", inputs: ["align", "popover", "popoverLabel", "focusable"] }, { kind: "component", type: StrctDropdownDivider, selector: "strct-dropdown-divider" }, { kind: "component", type: StrctDropdownItem, selector: "strct-dropdown-item", inputs: ["selected", "critical", "disabled", "hint"] }, { kind: "directive", type: StrctDropdownTrigger, selector: "[strctDropdownTrigger]" }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
22229
22372
  }
22230
22373
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctSplitButton, decorators: [{
22231
22374
  type: Component,
@@ -24050,6 +24193,13 @@ class StrctMediaFrame {
24050
24193
  /** The frame's aspect ratio, as a CSS `aspect-ratio` value. */
24051
24194
  ratio = input('4 / 3', /* @ts-ignore */
24052
24195
  ...(ngDevMode ? [{ debugName: "ratio" }] : /* istanbul ignore next */ []));
24196
+ /**
24197
+ * How the media fills the frame. `cover` crops to fill, as today; `contain`
24198
+ * shows all of it — what a console thumbnail needs, since the corner it
24199
+ * would crop is where the error is.
24200
+ */
24201
+ fit = input('cover', /* @ts-ignore */
24202
+ ...(ngDevMode ? [{ debugName: "fit" }] : /* istanbul ignore next */ []));
24053
24203
  /** What the frame shows: the projected picture, or why there is none. */
24054
24204
  state = input('content', /* @ts-ignore */
24055
24205
  ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
@@ -24075,7 +24225,7 @@ class StrctMediaFrame {
24075
24225
  }, /* @ts-ignore */
24076
24226
  ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
24077
24227
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMediaFrame, deps: [], target: i0.ɵɵFactoryTarget.Component });
24078
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctMediaFrame, isStandalone: true, selector: "strct-media-frame", inputs: { ratio: { classPropertyName: "ratio", publicName: "ratio", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, activateLabel: { classPropertyName: "activateLabel", publicName: "activateLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "activated" }, host: { properties: { "style.aspect-ratio": "ratio()", "attr.data-state": "state()", "class.strct-mf--interactive": "interactive()" }, classAttribute: "strct-mf" }, ngImport: i0, template: `
24228
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctMediaFrame, isStandalone: true, selector: "strct-media-frame", inputs: { ratio: { classPropertyName: "ratio", publicName: "ratio", isSignal: true, isRequired: false, transformFunction: null }, fit: { classPropertyName: "fit", publicName: "fit", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, activateLabel: { classPropertyName: "activateLabel", publicName: "activateLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "activated" }, host: { properties: { "style.aspect-ratio": "ratio()", "attr.data-state": "state()", "class.strct-mf--interactive": "interactive()", "class.strct-mf--contain": "fit() === 'contain'" }, classAttribute: "strct-mf" }, ngImport: i0, template: `
24079
24229
  @if (state() === 'content') {
24080
24230
  <ng-content />
24081
24231
  } @else {
@@ -24098,7 +24248,7 @@ class StrctMediaFrame {
24098
24248
  (click)="activated.emit()"
24099
24249
  ></button>
24100
24250
  }
24101
- `, isInline: true, styles: [".strct-mf{position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden;border:1px solid var(--b2);border-radius:var(--radius-md);background:var(--bg-3);min-width:0}.strct-mf>img,.strct-mf>video,.strct-mf>canvas{width:100%;height:100%;object-fit:cover;display:block}.strct-mf[data-state=off]{background:#000}.strct-mf__placeholder{display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--space-2);color:var(--t3);text-align:center}.strct-mf[data-state=off] .strct-mf__placeholder{color:#fff9}.strct-mf[data-state=error] .strct-mf__placeholder{color:var(--critical)}.strct-mf__msg{font-size:var(--text-sm);line-height:1.35}.strct-mf__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;cursor:pointer}.strct-mf__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mf--interactive:hover{border-color:var(--b3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24251
+ `, isInline: true, styles: [".strct-mf{position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden;border:1px solid var(--b2);border-radius:var(--radius-md);background:var(--bg-3);min-width:0}.strct-mf>img,.strct-mf>video,.strct-mf>canvas{width:100%;height:100%;object-fit:cover;display:block}.strct-mf--contain>img,.strct-mf--contain>video,.strct-mf--contain>canvas{object-fit:contain}.strct-mf[data-state=off]{background:#000}.strct-mf__placeholder{display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--space-2);color:var(--t3);text-align:center}.strct-mf[data-state=off] .strct-mf__placeholder{color:#fff9}.strct-mf[data-state=error] .strct-mf__placeholder{color:var(--critical)}.strct-mf__msg{font-size:var(--text-sm);line-height:1.35}.strct-mf__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;cursor:pointer}.strct-mf__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mf--interactive:hover{border-color:var(--b3)}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24102
24252
  }
24103
24253
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMediaFrame, decorators: [{
24104
24254
  type: Component,
@@ -24130,15 +24280,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24130
24280
  '[style.aspect-ratio]': 'ratio()',
24131
24281
  '[attr.data-state]': 'state()',
24132
24282
  '[class.strct-mf--interactive]': 'interactive()',
24133
- }, styles: [".strct-mf{position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden;border:1px solid var(--b2);border-radius:var(--radius-md);background:var(--bg-3);min-width:0}.strct-mf>img,.strct-mf>video,.strct-mf>canvas{width:100%;height:100%;object-fit:cover;display:block}.strct-mf[data-state=off]{background:#000}.strct-mf__placeholder{display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--space-2);color:var(--t3);text-align:center}.strct-mf[data-state=off] .strct-mf__placeholder{color:#fff9}.strct-mf[data-state=error] .strct-mf__placeholder{color:var(--critical)}.strct-mf__msg{font-size:var(--text-sm);line-height:1.35}.strct-mf__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;cursor:pointer}.strct-mf__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mf--interactive:hover{border-color:var(--b3)}\n"] }]
24134
- }], propDecorators: { ratio: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratio", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], activateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "activateLabel", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
24283
+ '[class.strct-mf--contain]': "fit() === 'contain'",
24284
+ }, styles: [".strct-mf{position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden;border:1px solid var(--b2);border-radius:var(--radius-md);background:var(--bg-3);min-width:0}.strct-mf>img,.strct-mf>video,.strct-mf>canvas{width:100%;height:100%;object-fit:cover;display:block}.strct-mf--contain>img,.strct-mf--contain>video,.strct-mf--contain>canvas{object-fit:contain}.strct-mf[data-state=off]{background:#000}.strct-mf__placeholder{display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--space-2);color:var(--t3);text-align:center}.strct-mf[data-state=off] .strct-mf__placeholder{color:#fff9}.strct-mf[data-state=error] .strct-mf__placeholder{color:var(--critical)}.strct-mf__msg{font-size:var(--text-sm);line-height:1.35}.strct-mf__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;cursor:pointer}.strct-mf__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mf--interactive:hover{border-color:var(--b3)}\n"] }]
24285
+ }], propDecorators: { ratio: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratio", required: false }] }], fit: [{ type: i0.Input, args: [{ isSignal: true, alias: "fit", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], activateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "activateLabel", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
24135
24286
 
24287
+ /** The title bar's height — what must stay on screen for the window to be
24288
+ * draggable back from an edge. */
24289
+ const TITLE_H = 36;
24136
24290
  const WINDOW_LABELS = {
24137
24291
  minimize: 'Minimize',
24138
24292
  maximize: 'Maximize',
24139
24293
  restore: 'Restore',
24140
24294
  close: 'Close',
24141
24295
  dock: 'Minimized windows',
24296
+ minimizeHint: '',
24297
+ maximizeHint: '',
24298
+ restoreHint: '',
24299
+ closeHint: '',
24142
24300
  };
24143
24301
  let windowCounter = 0;
24144
24302
  /**
@@ -24217,8 +24375,20 @@ class StrctWindow {
24217
24375
  /** The accessible name of each resize grip. */
24218
24376
  resizeLabel = input((corner) => `Resize (${corner})`, /* @ts-ignore */
24219
24377
  ...(ngDevMode ? [{ debugName: "resizeLabel" }] : /* istanbul ignore next */ []));
24378
+ /** A leading icon in the title bar, as `strct-page-header [icon]` has. */
24379
+ icon = input('', /* @ts-ignore */
24380
+ ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
24381
+ /**
24382
+ * What a double-click on the title bar does. A console whose content has a
24383
+ * real full screen of its own wants `none` and its own answer to
24384
+ * `(titleDblclick)`.
24385
+ */
24386
+ titleDblclick = input('maximize', /* @ts-ignore */
24387
+ ...(ngDevMode ? [{ debugName: "titleDblclick" }] : /* istanbul ignore next */ []));
24220
24388
  /** The window was closed. */
24221
24389
  closed = output();
24390
+ /** The title bar was double-clicked, whatever `titleDblclick` then did. */
24391
+ titleDblclicked = output();
24222
24392
  CORNERS = ['nw', 'ne', 'sw', 'se'];
24223
24393
  titleId = `strct-window-${++windowCounter}`;
24224
24394
  L = computed(() => ({
@@ -24333,6 +24503,14 @@ class StrctWindow {
24333
24503
  this.doc.removeEventListener('pointercancel', this.onUp);
24334
24504
  }
24335
24505
  /** Alt+arrows move the window; Escape minimises it. */
24506
+ toggleMaximized() {
24507
+ this.maximized.set(!this.maximized());
24508
+ }
24509
+ onTitleDblclick() {
24510
+ this.titleDblclicked.emit();
24511
+ if (this.titleDblclick() === 'maximize')
24512
+ this.toggleMaximized();
24513
+ }
24336
24514
  onTitleKeydown(event) {
24337
24515
  if (!event.altKey)
24338
24516
  return;
@@ -24405,14 +24583,33 @@ class StrctWindow {
24405
24583
  height,
24406
24584
  };
24407
24585
  }
24586
+ /**
24587
+ * A window dragged off the screen cannot be dragged back: the title bar is
24588
+ * the only handle it has. Keep enough of that bar on screen to grab — the
24589
+ * window may hang off any edge, but never past its own title.
24590
+ */
24591
+ clamp(next) {
24592
+ const view = this.doc.defaultView;
24593
+ if (!view)
24594
+ return next;
24595
+ const KEEP = 48; // enough of the bar to put a pointer on
24596
+ const maxX = view.innerWidth - KEEP;
24597
+ const maxY = view.innerHeight - TITLE_H;
24598
+ return {
24599
+ ...next,
24600
+ x: Math.min(Math.max(next.x, KEEP - next.width), maxX),
24601
+ y: Math.min(Math.max(next.y, 0), Math.max(0, maxY)),
24602
+ };
24603
+ }
24408
24604
  setRect(next) {
24605
+ const clamped = this.clamp(next);
24409
24606
  if (this.bounds())
24410
- this.bounds.set(next);
24607
+ this.bounds.set(clamped);
24411
24608
  else
24412
- this.fallback.set(next);
24609
+ this.fallback.set(clamped);
24413
24610
  }
24414
24611
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctWindow, deps: [], target: i0.ɵɵFactoryTarget.Component });
24415
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctWindow, isStandalone: true, selector: "strct-window", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, minimized: { classPropertyName: "minimized", publicName: "minimized", isSignal: true, isRequired: false, transformFunction: null }, maximized: { classPropertyName: "maximized", publicName: "maximized", isSignal: true, isRequired: false, transformFunction: null }, bounds: { classPropertyName: "bounds", publicName: "bounds", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutside: { classPropertyName: "closeOnOutside", publicName: "closeOnOutside", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, resizeLabel: { classPropertyName: "resizeLabel", publicName: "resizeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", minimized: "minimizedChange", maximized: "maximizedChange", bounds: "boundsChange", closed: "closed" }, host: { classAttribute: "strct-window" }, ngImport: i0, template: `
24612
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctWindow, isStandalone: true, selector: "strct-window", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, minimized: { classPropertyName: "minimized", publicName: "minimized", isSignal: true, isRequired: false, transformFunction: null }, maximized: { classPropertyName: "maximized", publicName: "maximized", isSignal: true, isRequired: false, transformFunction: null }, bounds: { classPropertyName: "bounds", publicName: "bounds", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutside: { classPropertyName: "closeOnOutside", publicName: "closeOnOutside", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, resizeLabel: { classPropertyName: "resizeLabel", publicName: "resizeLabel", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, titleDblclick: { classPropertyName: "titleDblclick", publicName: "titleDblclick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", minimized: "minimizedChange", maximized: "maximizedChange", bounds: "boundsChange", closed: "closed", titleDblclicked: "titleDblclicked" }, host: { classAttribute: "strct-window" }, ngImport: i0, template: `
24416
24613
  @if (open() && !minimized()) {
24417
24614
  <div
24418
24615
  class="strct-window__frame"
@@ -24437,8 +24634,11 @@ class StrctWindow {
24437
24634
  [attr.aria-label]="heading()"
24438
24635
  (pointerdown)="onDragStart($event)"
24439
24636
  (keydown)="onTitleKeydown($event)"
24440
- (dblclick)="maximized.set(!maximized())"
24637
+ (dblclick)="onTitleDblclick()"
24441
24638
  >
24639
+ @if (icon()) {
24640
+ <strct-icon class="strct-window__icon" [name]="icon()" [size]="14" />
24641
+ }
24442
24642
  <span class="strct-window__heading" [id]="titleId">{{ heading() }}</span>
24443
24643
  <span class="strct-window__meta"><ng-content select="[strctWindowTitleMeta]" /></span>
24444
24644
  <span class="strct-window__actions"><ng-content select="[strctWindowActions]" /></span>
@@ -24447,6 +24647,7 @@ class StrctWindow {
24447
24647
  type="button"
24448
24648
  class="strct-window__btn"
24449
24649
  [attr.aria-label]="L().minimize"
24650
+ [attr.title]="L().minimizeHint || null"
24450
24651
  (click)="minimize()"
24451
24652
  >
24452
24653
  <strct-icon strictName="minus" [size]="14" />
@@ -24455,7 +24656,8 @@ class StrctWindow {
24455
24656
  type="button"
24456
24657
  class="strct-window__btn"
24457
24658
  [attr.aria-label]="maximized() ? L().restore : L().maximize"
24458
- (click)="maximized.set(!maximized())"
24659
+ [attr.title]="(maximized() ? L().restoreHint : L().maximizeHint) || null"
24660
+ (click)="toggleMaximized()"
24459
24661
  >
24460
24662
  <strct-icon
24461
24663
  [strictName]="maximized() ? 'exitFullscreen' : 'fullscreen'"
@@ -24466,6 +24668,7 @@ class StrctWindow {
24466
24668
  type="button"
24467
24669
  class="strct-window__btn strct-window__btn--close"
24468
24670
  [attr.aria-label]="L().close"
24671
+ [attr.title]="L().closeHint || null"
24469
24672
  (click)="close()"
24470
24673
  >
24471
24674
  <strct-icon strictName="close" [size]="14" />
@@ -24490,7 +24693,7 @@ class StrctWindow {
24490
24693
  }
24491
24694
  </div>
24492
24695
  }
24493
- `, isInline: true, styles: [".strct-window{display:contents}.strct-window__frame{position:fixed;display:flex;flex-direction:column;min-width:0;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);color:var(--t1);box-shadow:var(--shadow-overlay, 0 12px 40px rgba(0, 0, 0, .32));overflow:hidden}.strct-window__frame--max{inset:var(--space-3);width:auto;height:auto}.strct-window__title{display:flex;align-items:center;gap:var(--space-2);padding:6px 6px 6px var(--space-3);border-block-end:1px solid var(--b1);background:var(--bg-2);cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-window__title:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__heading{font-size:var(--text-sm);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-window__meta,.strct-window__actions{display:inline-flex;align-items:center;gap:6px}.strct-window__actions{margin-inline-start:auto}.strct-window__controls{display:inline-flex;align-items:center;gap:2px;flex:none}.strct-window__btn{display:inline-flex;padding:4px;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--t2);cursor:pointer}.strct-window__btn:hover{background:var(--bg-3);color:var(--t1)}.strct-window__btn--close:hover{background:var(--critical-bg);color:var(--critical)}.strct-window__body{flex:1;min-height:0;overflow:auto}.strct-window__status:empty{display:none}.strct-window__status{border-block-start:1px solid var(--b1);padding:4px var(--space-3);font-size:var(--text-sm);color:var(--t3);background:var(--bg-2)}.strct-window__rz{position:absolute;width:14px;height:14px;padding:0;border:0;background:transparent}.strct-window__rz:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__rz--nw{inset-block-start:0;inset-inline-start:0;cursor:nwse-resize}.strct-window__rz--ne{inset-block-start:0;inset-inline-end:0;cursor:nesw-resize}.strct-window__rz--sw{inset-block-end:0;inset-inline-start:0;cursor:nesw-resize}.strct-window__rz--se{inset-block-end:0;inset-inline-end:0;cursor:nwse-resize}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24696
+ `, isInline: true, styles: [".strct-window{display:contents}.strct-window__frame{position:fixed;display:flex;flex-direction:column;min-width:0;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);color:var(--t1);box-shadow:var(--shadow-overlay, 0 12px 40px rgba(0, 0, 0, .32));overflow:hidden}.strct-window__frame--max{inset:var(--space-3);width:auto;height:auto}.strct-window__icon{flex:none;color:var(--t3)}.strct-window__title{display:flex;align-items:center;gap:var(--space-2);padding:6px 6px 6px var(--space-3);border-block-end:1px solid var(--b1);background:var(--bg-2);cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-window__title:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__heading{font-size:var(--text-sm);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-window__meta,.strct-window__actions{display:inline-flex;align-items:center;gap:6px}.strct-window__actions{margin-inline-start:auto}.strct-window__controls{display:inline-flex;align-items:center;gap:2px;flex:none}.strct-window__btn{display:inline-flex;padding:4px;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--t2);cursor:pointer}.strct-window__btn:hover{background:var(--bg-3);color:var(--t1)}.strct-window__btn--close:hover{background:var(--critical-bg);color:var(--critical)}.strct-window__body{flex:1;min-height:0;overflow:auto}.strct-window__status:empty{display:none}.strct-window__status{border-block-start:1px solid var(--b1);padding:4px var(--space-3);font-size:var(--text-sm);color:var(--t3);background:var(--bg-2)}.strct-window__rz{position:absolute;width:14px;height:14px;padding:0;border:0;background:transparent}.strct-window__rz:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__rz--nw{inset-block-start:0;inset-inline-start:0;cursor:nwse-resize}.strct-window__rz--ne{inset-block-start:0;inset-inline-end:0;cursor:nesw-resize}.strct-window__rz--sw{inset-block-end:0;inset-inline-start:0;cursor:nesw-resize}.strct-window__rz--se{inset-block-end:0;inset-inline-end:0;cursor:nwse-resize}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24494
24697
  }
24495
24698
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctWindow, decorators: [{
24496
24699
  type: Component,
@@ -24519,8 +24722,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24519
24722
  [attr.aria-label]="heading()"
24520
24723
  (pointerdown)="onDragStart($event)"
24521
24724
  (keydown)="onTitleKeydown($event)"
24522
- (dblclick)="maximized.set(!maximized())"
24725
+ (dblclick)="onTitleDblclick()"
24523
24726
  >
24727
+ @if (icon()) {
24728
+ <strct-icon class="strct-window__icon" [name]="icon()" [size]="14" />
24729
+ }
24524
24730
  <span class="strct-window__heading" [id]="titleId">{{ heading() }}</span>
24525
24731
  <span class="strct-window__meta"><ng-content select="[strctWindowTitleMeta]" /></span>
24526
24732
  <span class="strct-window__actions"><ng-content select="[strctWindowActions]" /></span>
@@ -24529,6 +24735,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24529
24735
  type="button"
24530
24736
  class="strct-window__btn"
24531
24737
  [attr.aria-label]="L().minimize"
24738
+ [attr.title]="L().minimizeHint || null"
24532
24739
  (click)="minimize()"
24533
24740
  >
24534
24741
  <strct-icon strictName="minus" [size]="14" />
@@ -24537,7 +24744,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24537
24744
  type="button"
24538
24745
  class="strct-window__btn"
24539
24746
  [attr.aria-label]="maximized() ? L().restore : L().maximize"
24540
- (click)="maximized.set(!maximized())"
24747
+ [attr.title]="(maximized() ? L().restoreHint : L().maximizeHint) || null"
24748
+ (click)="toggleMaximized()"
24541
24749
  >
24542
24750
  <strct-icon
24543
24751
  [strictName]="maximized() ? 'exitFullscreen' : 'fullscreen'"
@@ -24548,6 +24756,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24548
24756
  type="button"
24549
24757
  class="strct-window__btn strct-window__btn--close"
24550
24758
  [attr.aria-label]="L().close"
24759
+ [attr.title]="L().closeHint || null"
24551
24760
  (click)="close()"
24552
24761
  >
24553
24762
  <strct-icon strictName="close" [size]="14" />
@@ -24572,11 +24781,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24572
24781
  }
24573
24782
  </div>
24574
24783
  }
24575
- `, host: { class: 'strct-window' }, styles: [".strct-window{display:contents}.strct-window__frame{position:fixed;display:flex;flex-direction:column;min-width:0;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);color:var(--t1);box-shadow:var(--shadow-overlay, 0 12px 40px rgba(0, 0, 0, .32));overflow:hidden}.strct-window__frame--max{inset:var(--space-3);width:auto;height:auto}.strct-window__title{display:flex;align-items:center;gap:var(--space-2);padding:6px 6px 6px var(--space-3);border-block-end:1px solid var(--b1);background:var(--bg-2);cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-window__title:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__heading{font-size:var(--text-sm);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-window__meta,.strct-window__actions{display:inline-flex;align-items:center;gap:6px}.strct-window__actions{margin-inline-start:auto}.strct-window__controls{display:inline-flex;align-items:center;gap:2px;flex:none}.strct-window__btn{display:inline-flex;padding:4px;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--t2);cursor:pointer}.strct-window__btn:hover{background:var(--bg-3);color:var(--t1)}.strct-window__btn--close:hover{background:var(--critical-bg);color:var(--critical)}.strct-window__body{flex:1;min-height:0;overflow:auto}.strct-window__status:empty{display:none}.strct-window__status{border-block-start:1px solid var(--b1);padding:4px var(--space-3);font-size:var(--text-sm);color:var(--t3);background:var(--bg-2)}.strct-window__rz{position:absolute;width:14px;height:14px;padding:0;border:0;background:transparent}.strct-window__rz:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__rz--nw{inset-block-start:0;inset-inline-start:0;cursor:nwse-resize}.strct-window__rz--ne{inset-block-start:0;inset-inline-end:0;cursor:nesw-resize}.strct-window__rz--sw{inset-block-end:0;inset-inline-start:0;cursor:nesw-resize}.strct-window__rz--se{inset-block-end:0;inset-inline-end:0;cursor:nwse-resize}\n"] }]
24576
- }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], minimized: [{ type: i0.Input, args: [{ isSignal: true, alias: "minimized", required: false }] }, { type: i0.Output, args: ["minimizedChange"] }], maximized: [{ type: i0.Input, args: [{ isSignal: true, alias: "maximized", required: false }] }, { type: i0.Output, args: ["maximizedChange"] }], bounds: [{ type: i0.Input, args: [{ isSignal: true, alias: "bounds", required: false }] }, { type: i0.Output, args: ["boundsChange"] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], minHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHeight", required: false }] }], palette: [{ type: i0.Input, args: [{ isSignal: true, alias: "palette", required: false }] }], closeOnOutside: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutside", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], resizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeLabel", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
24784
+ `, host: { class: 'strct-window' }, styles: [".strct-window{display:contents}.strct-window__frame{position:fixed;display:flex;flex-direction:column;min-width:0;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);color:var(--t1);box-shadow:var(--shadow-overlay, 0 12px 40px rgba(0, 0, 0, .32));overflow:hidden}.strct-window__frame--max{inset:var(--space-3);width:auto;height:auto}.strct-window__icon{flex:none;color:var(--t3)}.strct-window__title{display:flex;align-items:center;gap:var(--space-2);padding:6px 6px 6px var(--space-3);border-block-end:1px solid var(--b1);background:var(--bg-2);cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-window__title:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__heading{font-size:var(--text-sm);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-window__meta,.strct-window__actions{display:inline-flex;align-items:center;gap:6px}.strct-window__actions{margin-inline-start:auto}.strct-window__controls{display:inline-flex;align-items:center;gap:2px;flex:none}.strct-window__btn{display:inline-flex;padding:4px;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--t2);cursor:pointer}.strct-window__btn:hover{background:var(--bg-3);color:var(--t1)}.strct-window__btn--close:hover{background:var(--critical-bg);color:var(--critical)}.strct-window__body{flex:1;min-height:0;overflow:auto}.strct-window__status:empty{display:none}.strct-window__status{border-block-start:1px solid var(--b1);padding:4px var(--space-3);font-size:var(--text-sm);color:var(--t3);background:var(--bg-2)}.strct-window__rz{position:absolute;width:14px;height:14px;padding:0;border:0;background:transparent}.strct-window__rz:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-window__rz--nw{inset-block-start:0;inset-inline-start:0;cursor:nwse-resize}.strct-window__rz--ne{inset-block-start:0;inset-inline-end:0;cursor:nesw-resize}.strct-window__rz--sw{inset-block-end:0;inset-inline-start:0;cursor:nesw-resize}.strct-window__rz--se{inset-block-end:0;inset-inline-end:0;cursor:nwse-resize}\n"] }]
24785
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], minimized: [{ type: i0.Input, args: [{ isSignal: true, alias: "minimized", required: false }] }, { type: i0.Output, args: ["minimizedChange"] }], maximized: [{ type: i0.Input, args: [{ isSignal: true, alias: "maximized", required: false }] }, { type: i0.Output, args: ["maximizedChange"] }], bounds: [{ type: i0.Input, args: [{ isSignal: true, alias: "bounds", required: false }] }, { type: i0.Output, args: ["boundsChange"] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], minHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHeight", required: false }] }], palette: [{ type: i0.Input, args: [{ isSignal: true, alias: "palette", required: false }] }], closeOnOutside: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutside", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], resizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeLabel", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], titleDblclick: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleDblclick", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], titleDblclicked: [{ type: i0.Output, args: ["titleDblclicked"] }] } });
24786
+ /**
24787
+ * What a dock chip shows, when the window's heading is not enough — a status
24788
+ * dot, an icon, a count. The window is the context:
24789
+ *
24790
+ * <ng-template strctWindowDockItem let-w>
24791
+ * <strct-status-dot [status]="tone(w)" size="sm" /> {{ w.heading() }}
24792
+ * </ng-template>
24793
+ */
24794
+ class StrctWindowDockItem {
24795
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctWindowDockItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
24796
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctWindowDockItem, isStandalone: true, selector: "ng-template[strctWindowDockItem]", ngImport: i0 });
24797
+ }
24798
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctWindowDockItem, decorators: [{
24799
+ type: Directive,
24800
+ args: [{ selector: 'ng-template[strctWindowDockItem]' }]
24801
+ }] });
24577
24802
  /**
24578
24803
  * Where minimised windows wait. Put it in a toolbar or a status bar; each entry
24579
- * restores its window, and its × closes it.
24804
+ * restores its window — or asks the consumer to, through `(restoreRequest)` —
24805
+ * and its × closes it.
24580
24806
  */
24581
24807
  class StrctWindowDock {
24582
24808
  service = inject(StrctWindowService);
@@ -24586,12 +24812,39 @@ class StrctWindowDock {
24586
24812
  /** The name of each chip's close button. */
24587
24813
  closeLabel = input((heading) => `Close ${heading}`, /* @ts-ignore */
24588
24814
  ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
24815
+ /** What each chip shows, when a heading is not enough. */
24816
+ itemTpl = contentChild(StrctWindowDockItem, { ...(ngDevMode ? { debugName: "itemTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
24817
+ /**
24818
+ * Who restores a window when its chip is pressed. `dock` does it itself, as
24819
+ * before; `request` only emits `(restoreRequest)`, so an app that allows one
24820
+ * open window at a time can close the other first — the dock's own restore
24821
+ * would walk past that rule.
24822
+ */
24823
+ restoreMode = input('dock', /* @ts-ignore */
24824
+ ...(ngDevMode ? [{ debugName: "restoreMode" }] : /* istanbul ignore next */ []));
24825
+ /** A chip was pressed. Always emitted; with `restoreMode="request"` it is
24826
+ * the only thing that happens. */
24827
+ restoreRequest = output();
24828
+ onRestore(w) {
24829
+ this.restoreRequest.emit(w);
24830
+ if (this.restoreMode() === 'dock')
24831
+ w.restore();
24832
+ }
24589
24833
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctWindowDock, deps: [], target: i0.ɵɵFactoryTarget.Component });
24590
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctWindowDock, isStandalone: true, selector: "strct-window-dock", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "attr.aria-label": "label()" }, classAttribute: "strct-windock" }, ngImport: i0, template: `
24834
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctWindowDock, isStandalone: true, selector: "strct-window-dock", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, restoreMode: { classPropertyName: "restoreMode", publicName: "restoreMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { restoreRequest: "restoreRequest" }, host: { attributes: { "role": "group" }, properties: { "attr.aria-label": "label()" }, classAttribute: "strct-windock" }, queries: [{ propertyName: "itemTpl", first: true, predicate: StrctWindowDockItem, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: `
24591
24835
  @for (w of service.minimized(); track w) {
24592
24836
  <span class="strct-windock__chip">
24593
- <button type="button" class="strct-windock__open" (click)="w.restore()">
24594
- {{ w.heading() }}
24837
+ <button type="button" class="strct-windock__open" (click)="onRestore(w)">
24838
+ @if (itemTpl(); as tpl) {
24839
+ <!-- A chip can say more than a heading: a status dot, an icon, a
24840
+ count. The window is the template's context. -->
24841
+ <ng-container
24842
+ [ngTemplateOutlet]="tpl"
24843
+ [ngTemplateOutletContext]="{ $implicit: w, window: w }"
24844
+ />
24845
+ } @else {
24846
+ {{ w.heading() }}
24847
+ }
24595
24848
  </button>
24596
24849
  <button
24597
24850
  type="button"
@@ -24603,15 +24856,24 @@ class StrctWindowDock {
24603
24856
  </button>
24604
24857
  </span>
24605
24858
  }
24606
- `, isInline: true, styles: [".strct-windock{display:inline-flex;align-items:center;gap:6px}.strct-windock__chip{display:inline-flex;align-items:center;gap:2px;padding-inline:8px 4px;border:1px solid var(--b2);border-radius:var(--radius-full, 999px);background:var(--bg-1);font-size:12px}.strct-windock__open,.strct-windock__close{border:0;background:none;color:inherit;font:inherit;cursor:pointer;padding:3px 2px;border-radius:var(--radius-sm)}.strct-windock__open:hover{color:var(--acc)}.strct-windock__close{display:inline-flex;color:var(--t3)}.strct-windock__close:hover{color:var(--critical)}.strct-windock__open:focus-visible,.strct-windock__close:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24859
+ `, isInline: true, styles: [".strct-windock{display:inline-flex;align-items:center;gap:6px}.strct-windock__chip{display:inline-flex;align-items:center;gap:2px;padding-inline:8px 4px;border:1px solid var(--b2);border-radius:var(--radius-full, 999px);background:var(--bg-1);font-size:12px}.strct-windock__open,.strct-windock__close{border:0;background:none;color:inherit;font:inherit;cursor:pointer;padding:3px 2px;border-radius:var(--radius-sm)}.strct-windock__open:hover{color:var(--acc)}.strct-windock__close{display:inline-flex;color:var(--t3)}.strct-windock__close:hover{color:var(--critical)}.strct-windock__open:focus-visible,.strct-windock__close:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24607
24860
  }
24608
24861
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctWindowDock, decorators: [{
24609
24862
  type: Component,
24610
- args: [{ selector: 'strct-window-dock', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
24863
+ args: [{ selector: 'strct-window-dock', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon, NgTemplateOutlet], template: `
24611
24864
  @for (w of service.minimized(); track w) {
24612
24865
  <span class="strct-windock__chip">
24613
- <button type="button" class="strct-windock__open" (click)="w.restore()">
24614
- {{ w.heading() }}
24866
+ <button type="button" class="strct-windock__open" (click)="onRestore(w)">
24867
+ @if (itemTpl(); as tpl) {
24868
+ <!-- A chip can say more than a heading: a status dot, an icon, a
24869
+ count. The window is the template's context. -->
24870
+ <ng-container
24871
+ [ngTemplateOutlet]="tpl"
24872
+ [ngTemplateOutletContext]="{ $implicit: w, window: w }"
24873
+ />
24874
+ } @else {
24875
+ {{ w.heading() }}
24876
+ }
24615
24877
  </button>
24616
24878
  <button
24617
24879
  type="button"
@@ -24628,7 +24890,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24628
24890
  role: 'group',
24629
24891
  '[attr.aria-label]': 'label()',
24630
24892
  }, styles: [".strct-windock{display:inline-flex;align-items:center;gap:6px}.strct-windock__chip{display:inline-flex;align-items:center;gap:2px;padding-inline:8px 4px;border:1px solid var(--b2);border-radius:var(--radius-full, 999px);background:var(--bg-1);font-size:12px}.strct-windock__open,.strct-windock__close{border:0;background:none;color:inherit;font:inherit;cursor:pointer;padding:3px 2px;border-radius:var(--radius-sm)}.strct-windock__open:hover{color:var(--acc)}.strct-windock__close{display:inline-flex;color:var(--t3)}.strct-windock__close:hover{color:var(--critical)}.strct-windock__open:focus-visible,.strct-windock__close:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
24631
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }] } });
24893
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctWindowDockItem), { ...{ read: TemplateRef }, isSignal: true }] }], restoreMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreMode", required: false }] }], restoreRequest: [{ type: i0.Output, args: ["restoreRequest"] }] } });
24632
24894
 
24633
24895
  /** A card the message carries — an action to approve, a result to read. */
24634
24896
  class StrctChatAttachment {
@@ -24859,6 +25121,11 @@ class StrctChatComposer {
24859
25121
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
24860
25122
  /** Disabled while the assistant is busy, say. */
24861
25123
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
25124
+ /**
25125
+ * Only the send button is disabled: the reader may draft their next question
25126
+ * while a reply is still streaming. `disabled` stops the typing as well.
25127
+ */
25128
+ sendDisabled = input(false, { ...(ngDevMode ? { debugName: "sendDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
24862
25129
  /** How tall the box grows before it scrolls. */
24863
25130
  maxRows = input(8, /* @ts-ignore */
24864
25131
  ...(ngDevMode ? [{ debugName: "maxRows" }] : /* istanbul ignore next */ []));
@@ -24891,7 +25158,7 @@ class StrctChatComposer {
24891
25158
  }
24892
25159
  submit() {
24893
25160
  const text = this.value().trim();
24894
- if (!text || this.disabled())
25161
+ if (!text || this.disabled() || this.sendDisabled())
24895
25162
  return;
24896
25163
  this.send.emit(text);
24897
25164
  this.value.set('');
@@ -24903,7 +25170,7 @@ class StrctChatComposer {
24903
25170
  }
24904
25171
  }
24905
25172
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatComposer, deps: [], target: i0.ɵɵFactoryTarget.Component });
24906
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctChatComposer, isStandalone: true, selector: "strct-chat-composer", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, sendLabel: { classPropertyName: "sendLabel", publicName: "sendLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", send: "send" }, host: { classAttribute: "strct-composer" }, ngImport: i0, template: `
25173
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctChatComposer, isStandalone: true, selector: "strct-chat-composer", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, sendDisabled: { classPropertyName: "sendDisabled", publicName: "sendDisabled", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, sendLabel: { classPropertyName: "sendLabel", publicName: "sendLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", send: "send" }, host: { classAttribute: "strct-composer" }, ngImport: i0, template: `
24907
25174
  <label class="strct-composer__label" [attr.for]="inputId">{{ label() }}</label>
24908
25175
  <div class="strct-composer__box">
24909
25176
  <textarea
@@ -24923,7 +25190,7 @@ class StrctChatComposer {
24923
25190
  type="button"
24924
25191
  class="strct-composer__send"
24925
25192
  [attr.aria-label]="sendLabel()"
24926
- [disabled]="disabled() || !value().trim()"
25193
+ [disabled]="disabled() || sendDisabled() || !value().trim()"
24927
25194
  (click)="submit()"
24928
25195
  >
24929
25196
  <strct-icon strictName="arrowUp" [size]="15" [strokeWidth]="1.8" />
@@ -24953,14 +25220,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24953
25220
  type="button"
24954
25221
  class="strct-composer__send"
24955
25222
  [attr.aria-label]="sendLabel()"
24956
- [disabled]="disabled() || !value().trim()"
25223
+ [disabled]="disabled() || sendDisabled() || !value().trim()"
24957
25224
  (click)="submit()"
24958
25225
  >
24959
25226
  <strct-icon strictName="arrowUp" [size]="15" [strokeWidth]="1.8" />
24960
25227
  </button>
24961
25228
  </div>
24962
25229
  `, host: { class: 'strct-composer' }, styles: [".strct-composer{display:block}.strct-composer__label{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-composer__box{display:flex;align-items:flex-end;gap:4px;padding:4px 4px 4px var(--space-3);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);transition:border-color .14s ease,box-shadow .14s ease}.strct-composer__box:focus-within{border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-composer__input{flex:1;min-width:0;border:0;background:none;resize:none;padding:6px 0;font-family:var(--font);font-size:13px;line-height:20px;color:var(--t1);overflow-y:auto}.strct-composer__input:focus{outline:none}.strct-composer__input::placeholder{color:var(--t3)}.strct-composer__send{display:inline-flex;align-items:center;justify-content:center;flex:none;width:28px;height:28px;border:0;border-radius:var(--radius-md);background:var(--acc);color:var(--inv);cursor:pointer}.strct-composer__send:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.strct-composer__send:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}\n"] }]
24963
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], sendLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sendLabel", required: false }] }], send: [{ type: i0.Output, args: ["send"] }] } });
25230
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], sendDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sendDisabled", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], sendLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sendLabel", required: false }] }], send: [{ type: i0.Output, args: ["send"] }] } });
24964
25231
  let composerCounter = 0;
24965
25232
 
24966
25233
  /**
@@ -25531,6 +25798,13 @@ class StrctPopover {
25531
25798
  /** Accessible name of the popover dialog (localizable). */
25532
25799
  ariaLabel = input('Details', /* @ts-ignore */
25533
25800
  ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
25801
+ /**
25802
+ * How wide the panel may get (px). The default suits a sentence; an alarm
25803
+ * list or a drift table wants 340–360. `--strct-popover-max-w` is the same
25804
+ * knob in CSS, for a panel the consumer does not own.
25805
+ */
25806
+ maxWidth = input(null, /* @ts-ignore */
25807
+ ...(ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []));
25534
25808
  /**
25535
25809
  * Modal-ish usage: move focus into the panel on open, trap Tab inside and
25536
25810
  * hand focus back to the trigger on close. Off by default — a plain popover
@@ -25587,7 +25861,7 @@ class StrctPopover {
25587
25861
  this.close(true);
25588
25862
  }
25589
25863
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctPopover, deps: [], target: i0.ɵɵFactoryTarget.Component });
25590
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctPopover, isStandalone: true, selector: "strct-popover", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, trap: { classPropertyName: "trap", publicName: "trap", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape($event)" }, classAttribute: "strct-popover" }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
25864
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctPopover, isStandalone: true, selector: "strct-popover", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, trap: { classPropertyName: "trap", publicName: "trap", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { listeners: { "document:click": "onDocClick($event)", "document:keydown.escape": "onEscape($event)" }, classAttribute: "strct-popover" }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
25591
25865
  <!--
25592
25866
  Same contract as the signpost: the wrapper stays inert and the real
25593
25867
  trigger button carries aria-haspopup/aria-expanded (wired by the
@@ -25603,6 +25877,7 @@ class StrctPopover {
25603
25877
  role="dialog"
25604
25878
  tabindex="-1"
25605
25879
  [attr.aria-label]="ariaLabel()"
25880
+ [style.--strct-popover-max-w.px]="maxWidth()"
25606
25881
  [strctOverlay]="trigger"
25607
25882
  [strctOverlayPlacement]="placement()"
25608
25883
  (keydown.tab)="onTab($event)"
@@ -25611,7 +25886,7 @@ class StrctPopover {
25611
25886
  <ng-content />
25612
25887
  </div>
25613
25888
  }
25614
- `, isInline: true, styles: [".strct-popover{position:relative;display:inline-block}.strct-popover__trigger{display:inline-flex}.strct-popover__panel{z-index:var(--z-popover);width:max-content;max-width:320px;padding:var(--space-3);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-lg);box-shadow:var(--shadow-floating);animation:strct-popover-in .11s ease}@keyframes strct-popover-in{0%{opacity:0;transform:scale(.97)}}@media(prefers-reduced-motion:reduce){.strct-popover__panel{animation:none}}\n"], dependencies: [{ kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
25889
+ `, isInline: true, styles: [".strct-popover{position:relative;display:inline-block}.strct-popover__trigger{display:inline-flex}.strct-popover__panel{z-index:var(--z-popover);width:max-content;max-width:var(--strct-popover-max-w, 320px);padding:var(--space-3);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-lg);box-shadow:var(--shadow-floating);animation:strct-popover-in .11s ease}@keyframes strct-popover-in{0%{opacity:0;transform:scale(.97)}}@media(prefers-reduced-motion:reduce){.strct-popover__panel{animation:none}}\n"], dependencies: [{ kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
25615
25890
  }
25616
25891
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctPopover, decorators: [{
25617
25892
  type: Component,
@@ -25631,6 +25906,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
25631
25906
  role="dialog"
25632
25907
  tabindex="-1"
25633
25908
  [attr.aria-label]="ariaLabel()"
25909
+ [style.--strct-popover-max-w.px]="maxWidth()"
25634
25910
  [strctOverlay]="trigger"
25635
25911
  [strctOverlayPlacement]="placement()"
25636
25912
  (keydown.tab)="onTab($event)"
@@ -25639,8 +25915,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
25639
25915
  <ng-content />
25640
25916
  </div>
25641
25917
  }
25642
- `, host: { class: 'strct-popover' }, styles: [".strct-popover{position:relative;display:inline-block}.strct-popover__trigger{display:inline-flex}.strct-popover__panel{z-index:var(--z-popover);width:max-content;max-width:320px;padding:var(--space-3);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-lg);box-shadow:var(--shadow-floating);animation:strct-popover-in .11s ease}@keyframes strct-popover-in{0%{opacity:0;transform:scale(.97)}}@media(prefers-reduced-motion:reduce){.strct-popover__panel{animation:none}}\n"] }]
25643
- }], ctorParameters: () => [], propDecorators: { panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], trap: [{ type: i0.Input, args: [{ isSignal: true, alias: "trap", required: false }] }], onDocClick: [{
25918
+ `, host: { class: 'strct-popover' }, styles: [".strct-popover{position:relative;display:inline-block}.strct-popover__trigger{display:inline-flex}.strct-popover__panel{z-index:var(--z-popover);width:max-content;max-width:var(--strct-popover-max-w, 320px);padding:var(--space-3);font-size:13px;color:var(--t1);background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-lg);box-shadow:var(--shadow-floating);animation:strct-popover-in .11s ease}@keyframes strct-popover-in{0%{opacity:0;transform:scale(.97)}}@media(prefers-reduced-motion:reduce){.strct-popover__panel{animation:none}}\n"] }]
25919
+ }], ctorParameters: () => [], propDecorators: { panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], trap: [{ type: i0.Input, args: [{ isSignal: true, alias: "trap", required: false }] }], onDocClick: [{
25644
25920
  type: HostListener,
25645
25921
  args: ['document:click', ['$event']]
25646
25922
  }], onEscape: [{
@@ -26381,6 +26657,14 @@ class StrctToolbar {
26381
26657
  const idx = items.indexOf(active);
26382
26658
  if (idx < 0)
26383
26659
  return; // focus is not on a toolbar control
26660
+ // A control that has opened something owns its own arrow keys: a select's
26661
+ // listbox, a menu, a tree inside a popover. The bar's roving must not take
26662
+ // them, or the list cannot be walked from the keyboard at all.
26663
+ if (active?.getAttribute('aria-expanded') === 'true')
26664
+ return;
26665
+ const target = event.target;
26666
+ if (target?.closest('[role=listbox], [role=menu], [role=dialog], [role=tree], [role=grid]'))
26667
+ return;
26384
26668
  const vertical = this.orientation() === 'vertical';
26385
26669
  const prevKey = vertical ? 'ArrowUp' : 'ArrowLeft';
26386
26670
  const nextKey = vertical ? 'ArrowDown' : 'ArrowRight';
@@ -27370,5 +27654,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
27370
27654
  * Generated bundle index. Do not edit.
27371
27655
  */
27372
27656
 
27373
- export { FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_NOTIFICATION_HISTORY_LIMIT, STRCT_PALETTES, STRCT_RAW_ICONS, STRCT_TIME_RANGE_PRESETS, STRCT_WIZARD_DEFAULTS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAlertActions, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCardHeaderActions, StrctCardHeaderLeading, StrctCardHeaderMeta, StrctCardHeaderNote, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChange, StrctChart, StrctChatAttachment, StrctChatComposer, StrctChatMessage, StrctChatThread, StrctCheckbox, StrctChips, StrctCode, StrctCodeInline, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctControlDescription, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatagridActionBarCaption, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctDropdownItemAction, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFieldGroup, StrctFieldHint, StrctFieldPrefix, StrctFieldSuffix, StrctFieldValue, StrctFile, StrctFilterBar, StrctFlow, StrctFlowNodeTemplate, StrctFooter, StrctGauge, StrctHeader, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLegend, StrctList, StrctListItem, StrctListItemDescription, StrctListItemLeading, StrctListItemMeta, StrctListItemTrailing, StrctLiveIndicator, StrctLogViewer, StrctLogin, StrctMediaFrame, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctModalContent, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPageHeaderTitleMeta, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProgress, StrctQr, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderGroup, StrctReorderHandle, StrctReorderItem, StrctResizeHandle, StrctRowDetailDef, StrctSearchbox, StrctSectionHeader, StrctSectionHeaderActions, StrctSectionHeaderMeta, StrctSectionMenu, StrctSegmented, StrctSelect, StrctShell, StrctShellService, StrctSiPipe, StrctSignpost, StrctSignpostTrigger, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctSplitButton, StrctSplitter, StrctStack, StrctStackItem, StrctStatusDot, StrctStep, StrctStepAction, StrctSteps, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctTagLeading, StrctThemeService, StrctThemeSwitcher, StrctTimeRangePicker, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctToolbar, StrctToolbarCaption, StrctToolbarSpacer, StrctTooltip, StrctTour, StrctTransfer, StrctTree, StrctTreeNode, StrctTreeSelect, StrctVerticalNav, StrctWatermark, StrctWindow, StrctWindowDock, StrctWindowService, StrctWizard, StrctWizardAside, __qrInternals, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctCheckHostDisplay, strctCheckHostInputs, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctQrMatrix, strctValidationIcon, strctValidationTone, unlockBodyScroll };
27657
+ export { FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_NOTIFICATION_HISTORY_LIMIT, STRCT_PALETTES, STRCT_RAW_ICONS, STRCT_TIME_RANGE_PRESETS, STRCT_WIZARD_DEFAULTS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAlertActions, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCardHeaderActions, StrctCardHeaderLeading, StrctCardHeaderMeta, StrctCardHeaderNote, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChange, StrctChart, StrctChatAttachment, StrctChatComposer, StrctChatMessage, StrctChatThread, StrctCheckbox, StrctChips, StrctCode, StrctCodeInline, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctControlDescription, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatagridActionBarCaption, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctDropdownItemAction, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFieldGroup, StrctFieldHint, StrctFieldPrefix, StrctFieldSuffix, StrctFieldValue, StrctFile, StrctFilterBar, StrctFlow, StrctFlowNodeTemplate, StrctFooter, StrctGauge, StrctHeader, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLegend, StrctList, StrctListItem, StrctListItemDescription, StrctListItemLeading, StrctListItemMeta, StrctListItemTrailing, StrctLiveIndicator, StrctLogViewer, StrctLogin, StrctMediaFrame, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctModalContent, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPageHeaderTitleMeta, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProgress, StrctQr, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderGroup, StrctReorderHandle, StrctReorderItem, StrctResizeHandle, StrctRowDetailDef, StrctSearchbox, StrctSectionHeader, StrctSectionHeaderActions, StrctSectionHeaderMeta, StrctSectionMenu, StrctSegmented, StrctSelect, StrctShell, StrctShellService, StrctSiPipe, StrctSignpost, StrctSignpostTrigger, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctSplitButton, StrctSplitter, StrctStack, StrctStackItem, StrctStatusDot, StrctStep, StrctStepAction, StrctSteps, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctTagLeading, StrctThemeService, StrctThemeSwitcher, StrctTimeRangePicker, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctToolbar, StrctToolbarCaption, StrctToolbarSpacer, StrctTooltip, StrctTour, StrctTransfer, StrctTree, StrctTreeNode, StrctTreeSelect, StrctVerticalNav, StrctWatermark, StrctWindow, StrctWindowDock, StrctWindowDockItem, StrctWindowService, StrctWizard, StrctWizardAside, __qrInternals, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctCheckHostDisplay, strctCheckHostInputs, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctQrMatrix, strctValidationIcon, strctValidationTone, unlockBodyScroll };
27374
27658
  //# sourceMappingURL=akcelik-strct.mjs.map