@akcelik/strct 4.19.0 → 4.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, DOCUMENT, signal, computed, Injectable, input, isDevMode, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, NgZone, booleanAttribute, afterNextRender, Directive, model, output, contentChildren, HostListener, effect, ApplicationRef, EnvironmentInjector, createComponent, PLATFORM_ID, forwardRef, DestroyRef, TemplateRef, contentChild, viewChild, InjectionToken, untracked, ViewContainerRef, Injector, viewChildren, Renderer2, Pipe, afterRenderEffect } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
- import { NgTemplateOutlet, DOCUMENT as DOCUMENT$1, isPlatformBrowser } from '@angular/common';
4
+ import { DOCUMENT as DOCUMENT$1, NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
5
5
  import { RouterLink, RouterLinkActive } from '@angular/router';
6
6
  import * as i1 from '@angular/forms';
7
7
  import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
@@ -1033,21 +1033,66 @@ class StrctShellService {
1033
1033
  * </strct-shell>
1034
1034
  */
1035
1035
  class StrctShell {
1036
+ /**
1037
+ * Id of the main region. Given one, the shell renders "Skip to main content"
1038
+ * as its first focusable element — invisible until focused. Null (the
1039
+ * default) renders nothing, so existing shells are unchanged.
1040
+ */
1041
+ skipLinkTarget = input(null, /* @ts-ignore */
1042
+ ...(ngDevMode ? [{ debugName: "skipLinkTarget" }] : /* istanbul ignore next */ []));
1043
+ /** The link's text (localisable). */
1044
+ skipLinkLabel = input('Skip to main content', /* @ts-ignore */
1045
+ ...(ngDevMode ? [{ debugName: "skipLinkLabel" }] : /* istanbul ignore next */ []));
1046
+ doc = inject(DOCUMENT$1);
1047
+ /**
1048
+ * Moves focus rather than only the scroll position: an href alone scrolls
1049
+ * without focusing, so the next Tab would resume from the link.
1050
+ */
1051
+ skipToMain(event) {
1052
+ const id = this.skipLinkTarget();
1053
+ const target = id ? this.doc.getElementById(id) : null;
1054
+ if (!target)
1055
+ return;
1056
+ event.preventDefault();
1057
+ if (!target.hasAttribute('tabindex'))
1058
+ target.setAttribute('tabindex', '-1');
1059
+ target.focus();
1060
+ // Optional: not every environment implements it (jsdom does not).
1061
+ target.scrollIntoView?.({ block: 'start' });
1062
+ }
1036
1063
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
1037
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.4", type: StrctShell, isStandalone: true, selector: "strct-shell", host: { classAttribute: "strct-shell" }, providers: [StrctShellService], ngImport: i0, template: `
1064
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctShell, isStandalone: true, selector: "strct-shell", inputs: { skipLinkTarget: { classPropertyName: "skipLinkTarget", publicName: "skipLinkTarget", isSignal: true, isRequired: false, transformFunction: null }, skipLinkLabel: { classPropertyName: "skipLinkLabel", publicName: "skipLinkLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "strct-shell" }, providers: [StrctShellService], ngImport: i0, template: `
1065
+ @if (skipLinkTarget()) {
1066
+ <!-- The first focusable element on the page, invisible until focused. -->
1067
+ <a
1068
+ class="strct-shell__skip"
1069
+ [attr.href]="'#' + skipLinkTarget()"
1070
+ (click)="skipToMain($event)"
1071
+ >{{ skipLinkLabel() }}</a
1072
+ >
1073
+ }
1038
1074
  <ng-content select="strct-header" />
1039
1075
  <div class="strct-shell__main"><ng-content /></div>
1040
1076
  <ng-content select="strct-footer" />
1041
- `, isInline: true, styles: [".strct-shell{display:grid;grid-template-rows:auto 1fr auto;height:100vh;overflow:hidden;background:var(--bg-2)}.strct-shell__main{display:flex;min-height:0;overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1077
+ `, isInline: true, styles: [".strct-shell{display:grid;grid-template-rows:auto 1fr auto;height:100vh;overflow:hidden;background:var(--bg-2)}.strct-shell__main{display:flex;min-height:0;overflow:hidden}.strct-shell__skip{position:absolute;inset-inline-start:0;top:0;z-index:1;transform:translateY(-120%);padding:var(--space-2) var(--space-3);border-radius:0 0 var(--radius-md) 0;background:var(--acc);color:var(--inv);font-size:var(--text-sm);text-decoration:none}.strct-shell__skip:focus-visible{transform:none;outline:2px solid var(--acc50);outline-offset:2px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1042
1078
  }
1043
1079
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctShell, decorators: [{
1044
1080
  type: Component,
1045
1081
  args: [{ selector: 'strct-shell', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [StrctShellService], template: `
1082
+ @if (skipLinkTarget()) {
1083
+ <!-- The first focusable element on the page, invisible until focused. -->
1084
+ <a
1085
+ class="strct-shell__skip"
1086
+ [attr.href]="'#' + skipLinkTarget()"
1087
+ (click)="skipToMain($event)"
1088
+ >{{ skipLinkLabel() }}</a
1089
+ >
1090
+ }
1046
1091
  <ng-content select="strct-header" />
1047
1092
  <div class="strct-shell__main"><ng-content /></div>
1048
1093
  <ng-content select="strct-footer" />
1049
- `, host: { class: 'strct-shell' }, styles: [".strct-shell{display:grid;grid-template-rows:auto 1fr auto;height:100vh;overflow:hidden;background:var(--bg-2)}.strct-shell__main{display:flex;min-height:0;overflow:hidden}\n"] }]
1050
- }] });
1094
+ `, host: { class: 'strct-shell' }, styles: [".strct-shell{display:grid;grid-template-rows:auto 1fr auto;height:100vh;overflow:hidden;background:var(--bg-2)}.strct-shell__main{display:flex;min-height:0;overflow:hidden}.strct-shell__skip{position:absolute;inset-inline-start:0;top:0;z-index:1;transform:translateY(-120%);padding:var(--space-2) var(--space-3);border-radius:0 0 var(--radius-md) 0;background:var(--acc);color:var(--inv);font-size:var(--text-sm);text-decoration:none}.strct-shell__skip:focus-visible{transform:none;outline:2px solid var(--acc50);outline-offset:2px}\n"] }]
1095
+ }], propDecorators: { skipLinkTarget: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLinkTarget", required: false }] }], skipLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLinkLabel", required: false }] }] } });
1051
1096
  /** Top application bar. Holds brand on the left and actions on the right. */
1052
1097
  class StrctHeader {
1053
1098
  /** Accessible label of the mobile drawer toggle. */
@@ -2790,13 +2835,20 @@ class StrctAccordionPanel {
2790
2835
  /** Whether the panel is open (two-way). */
2791
2836
  expanded = model(false, /* @ts-ignore */
2792
2837
  ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
2838
+ /**
2839
+ * `quiet` is a fold in running text — no border or background, a `--text-sm`
2840
+ * summary in `--t2` with a chevron, the body indented. It reads like a raw
2841
+ * `<details>` while keeping the button + region semantics.
2842
+ */
2843
+ appearance = input('boxed', /* @ts-ignore */
2844
+ ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
2793
2845
  bodyId = `strct-acc-${++accordionCounter}`;
2794
2846
  headId = `${this.bodyId}-head`;
2795
2847
  toggle() {
2796
2848
  this.expanded.update((v) => !v);
2797
2849
  }
2798
2850
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctAccordionPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
2799
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctAccordionPanel, isStandalone: true, selector: "strct-accordion-panel", inputs: { heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { classAttribute: "strct-acc" }, ngImport: i0, template: `
2851
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctAccordionPanel, isStandalone: true, selector: "strct-accordion-panel", inputs: { heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange" }, host: { properties: { "class.strct-acc--quiet": "appearance() === 'quiet'" }, classAttribute: "strct-acc" }, ngImport: i0, template: `
2800
2852
  <button
2801
2853
  type="button"
2802
2854
  class="strct-acc__head"
@@ -2815,7 +2867,7 @@ class StrctAccordionPanel {
2815
2867
  <ng-content />
2816
2868
  </div>
2817
2869
  }
2818
- `, isInline: true, styles: [".strct-acc{display:block}.strct-acc+.strct-acc{border-top:1px solid var(--b2)}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:start}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}[dir=rtl] .strct-acc__chevron:not(.strct-acc__chevron--open){transform:rotate(180deg)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px;padding-inline-start:32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\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 });
2870
+ `, isInline: true, styles: [".strct-acc{display:block}.strct-acc+.strct-acc{border-top:1px solid var(--b2)}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:start}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}[dir=rtl] .strct-acc__chevron:not(.strct-acc__chevron--open){transform:rotate(180deg)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px;padding-inline-start:32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}.strct-acc--quiet+.strct-acc--quiet{border-top:0}.strct-acc--quiet .strct-acc__head{width:auto;padding:2px 0;gap:6px;font-size:var(--text-sm);font-weight:400;color:var(--t2)}.strct-acc--quiet .strct-acc__head:hover{background:none;color:var(--t1);text-decoration:underline}.strct-acc--quiet .strct-acc__head:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-acc--quiet .strct-acc__title{flex:none}.strct-acc--quiet .strct-acc__body{padding:4px 0 8px;padding-inline-start:var(--space-3);border-top:0;font-size:var(--text-sm)}\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 });
2819
2871
  }
2820
2872
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctAccordionPanel, decorators: [{
2821
2873
  type: Component,
@@ -2838,8 +2890,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
2838
2890
  <ng-content />
2839
2891
  </div>
2840
2892
  }
2841
- `, host: { class: 'strct-acc' }, styles: [".strct-acc{display:block}.strct-acc+.strct-acc{border-top:1px solid var(--b2)}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:start}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}[dir=rtl] .strct-acc__chevron:not(.strct-acc__chevron--open){transform:rotate(180deg)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px;padding-inline-start:32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}\n"] }]
2842
- }], propDecorators: { heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }] } });
2893
+ `, host: {
2894
+ class: 'strct-acc',
2895
+ '[class.strct-acc--quiet]': "appearance() === 'quiet'",
2896
+ }, styles: [".strct-acc{display:block}.strct-acc+.strct-acc{border-top:1px solid var(--b2)}.strct-acc__head{display:flex;align-items:center;gap:9px;width:100%;padding:11px 14px;border:0;background:transparent;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t1);text-align:start}.strct-acc__head:hover{background:var(--bg-3)}.strct-acc__chevron{display:inline-flex;color:var(--t3);transition:transform .16s ease}.strct-acc__chevron--open{transform:rotate(90deg);color:var(--acc)}[dir=rtl] .strct-acc__chevron:not(.strct-acc__chevron--open){transform:rotate(180deg)}.strct-acc__title{flex:1}.strct-acc__body{padding:4px 14px 14px;padding-inline-start:32px;color:var(--t2);font-size:13px;border-top:1px solid var(--b1)}.strct-acc--quiet+.strct-acc--quiet{border-top:0}.strct-acc--quiet .strct-acc__head{width:auto;padding:2px 0;gap:6px;font-size:var(--text-sm);font-weight:400;color:var(--t2)}.strct-acc--quiet .strct-acc__head:hover{background:none;color:var(--t1);text-decoration:underline}.strct-acc--quiet .strct-acc__head:focus-visible{outline:2px solid var(--acc50);outline-offset:2px;border-radius:var(--radius-sm)}.strct-acc--quiet .strct-acc__title{flex:none}.strct-acc--quiet .strct-acc__body{padding:4px 0 8px;padding-inline-start:var(--space-3);border-top:0;font-size:var(--text-sm)}\n"] }]
2897
+ }], propDecorators: { heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }] } });
2843
2898
 
2844
2899
  let tabsCounter = 0;
2845
2900
  /** A single tab. Place inside `<strct-tabs>`; `label` names its button. */
@@ -20698,6 +20753,22 @@ class StrctSplitter {
20698
20753
  ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
20699
20754
  max = input(85, /* @ts-ignore */
20700
20755
  ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
20756
+ /**
20757
+ * What `split`, `minSize` and `maxSize` are measured in. A sidebar is 280px,
20758
+ * not 22%, so `px` sizes the start pane in pixels and drags it in pixels.
20759
+ */
20760
+ unit = input('percent', /* @ts-ignore */
20761
+ ...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ []));
20762
+ /** Bounds in `unit` for the start pane; they win over `min` / `max`. */
20763
+ minSize = input(null, /* @ts-ignore */
20764
+ ...(ngDevMode ? [{ debugName: "minSize" }] : /* istanbul ignore next */ []));
20765
+ maxSize = input(null, /* @ts-ignore */
20766
+ ...(ngDevMode ? [{ debugName: "maxSize" }] : /* istanbul ignore next */ []));
20767
+ /** The start pane can be collapsed to nothing (Enter on the gutter). */
20768
+ collapsible = input(false, { ...(ngDevMode ? { debugName: "collapsible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
20769
+ /** Whether it is collapsed (two-way). */
20770
+ collapsed = model(false, /* @ts-ignore */
20771
+ ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
20701
20772
  /** Stack panes vertically (gutter drags up/down). */
20702
20773
  vertical = input(false, { ...(ngDevMode ? { debugName: "vertical" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
20703
20774
  /** Accessible name of the separator (localizable). */
@@ -20706,8 +20777,20 @@ class StrctSplitter {
20706
20777
  /** Keyboard nudge step in percent. */
20707
20778
  step = input(3, /* @ts-ignore */
20708
20779
  ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
20709
- clamped = computed(() => Math.min(this.max(), Math.max(this.min(), this.split())), /* @ts-ignore */
20780
+ /** The effective bounds, in whichever unit the splitter is measured in. */
20781
+ lowerBound = computed(() => this.minSize() ?? (this.unit() === 'px' ? 0 : this.min()), /* @ts-ignore */
20782
+ ...(ngDevMode ? [{ debugName: "lowerBound" }] : /* istanbul ignore next */ []));
20783
+ upperBound = computed(() => this.maxSize() ?? (this.unit() === 'px' ? Number.POSITIVE_INFINITY : this.max()), /* @ts-ignore */
20784
+ ...(ngDevMode ? [{ debugName: "upperBound" }] : /* istanbul ignore next */ []));
20785
+ clamped = computed(() => Math.min(this.upperBound(), Math.max(this.lowerBound(), this.split())), /* @ts-ignore */
20710
20786
  ...(ngDevMode ? [{ debugName: "clamped" }] : /* istanbul ignore next */ []));
20787
+ /** The start pane's flex-basis: its size, or nothing while collapsed. */
20788
+ startBasis = computed(() => {
20789
+ if (this.collapsed())
20790
+ return '0px';
20791
+ return this.unit() === 'px' ? `${this.clamped()}px` : `${this.clamped()}%`;
20792
+ }, /* @ts-ignore */
20793
+ ...(ngDevMode ? [{ debugName: "startBasis" }] : /* istanbul ignore next */ []));
20711
20794
  dragging = signal(false, /* @ts-ignore */
20712
20795
  ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
20713
20796
  moveHandler = (e) => this.onDragMove(e);
@@ -20733,7 +20816,11 @@ class StrctSplitter {
20733
20816
  : (event.clientX - rect.left) / rect.width;
20734
20817
  if (!this.vertical() && this.isRtl())
20735
20818
  ratio = 1 - ratio;
20736
- this.split.set(Math.min(this.max(), Math.max(this.min(), Math.round(ratio * 100))));
20819
+ const span = this.vertical() ? rect.height : rect.width;
20820
+ const next = this.unit() === 'px' ? Math.round(ratio * span) : Math.round(ratio * 100);
20821
+ if (this.collapsed())
20822
+ this.collapsed.set(false);
20823
+ this.split.set(Math.min(this.upperBound(), Math.max(this.lowerBound(), next)));
20737
20824
  }
20738
20825
  onDragEnd() {
20739
20826
  this.dragging.set(false);
@@ -20754,23 +20841,36 @@ class StrctSplitter {
20754
20841
  // RTL: the start pane extends to the left, so Left grows and Right shrinks.
20755
20842
  if (!this.vertical() && this.isRtl())
20756
20843
  [dec, inc] = [inc, dec];
20844
+ // Enter collapses a collapsible pane, and restores it.
20845
+ if (this.collapsible() && (event.key === 'Enter' || event.key === ' ')) {
20846
+ event.preventDefault();
20847
+ this.collapsed.update((v) => !v);
20848
+ return;
20849
+ }
20850
+ const step = this.unit() === 'px' ? this.step() * 8 : this.step();
20757
20851
  let next = null;
20758
20852
  if (event.key === dec)
20759
- next = this.clamped() - this.step();
20853
+ next = this.clamped() - step;
20760
20854
  else if (event.key === inc)
20761
- next = this.clamped() + this.step();
20855
+ next = this.clamped() + step;
20762
20856
  else if (event.key === 'Home')
20763
- next = this.min();
20857
+ next = this.lowerBound();
20764
20858
  else if (event.key === 'End')
20765
- next = this.max();
20859
+ next = Number.isFinite(this.upperBound()) ? this.upperBound() : this.clamped() + step * 4;
20766
20860
  if (next == null)
20767
20861
  return;
20768
20862
  event.preventDefault();
20769
- this.split.set(Math.min(this.max(), Math.max(this.min(), next)));
20863
+ if (this.collapsed())
20864
+ this.collapsed.set(false);
20865
+ this.split.set(Math.min(this.upperBound(), Math.max(this.lowerBound(), next)));
20770
20866
  }
20771
20867
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctSplitter, deps: [], target: i0.ɵɵFactoryTarget.Component });
20772
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctSplitter, isStandalone: true, selector: "strct-splitter", inputs: { split: { classPropertyName: "split", publicName: "split", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, gutterLabel: { classPropertyName: "gutterLabel", publicName: "gutterLabel", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { split: "splitChange" }, host: { properties: { "class.strct-split--vertical": "vertical()", "class.strct-split--dragging": "dragging()" }, classAttribute: "strct-split" }, ngImport: i0, template: `
20773
- <div class="strct-split__pane" [style.flex-basis.%]="clamped()">
20868
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctSplitter, isStandalone: true, selector: "strct-splitter", inputs: { split: { classPropertyName: "split", publicName: "split", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, minSize: { classPropertyName: "minSize", publicName: "minSize", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, gutterLabel: { classPropertyName: "gutterLabel", publicName: "gutterLabel", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { split: "splitChange", collapsed: "collapsedChange" }, host: { properties: { "class.strct-split--vertical": "vertical()", "class.strct-split--dragging": "dragging()" }, classAttribute: "strct-split" }, ngImport: i0, template: `
20869
+ <div
20870
+ class="strct-split__pane"
20871
+ [class.strct-split__pane--collapsed]="collapsed()"
20872
+ [style.flex-basis]="startBasis()"
20873
+ >
20774
20874
  <ng-content select="[strctPaneStart]" />
20775
20875
  </div>
20776
20876
  <div
@@ -20779,9 +20879,10 @@ class StrctSplitter {
20779
20879
  tabindex="0"
20780
20880
  [attr.aria-label]="gutterLabel()"
20781
20881
  [attr.aria-orientation]="vertical() ? 'horizontal' : 'vertical'"
20782
- [attr.aria-valuenow]="clamped()"
20783
- [attr.aria-valuemin]="min()"
20784
- [attr.aria-valuemax]="max()"
20882
+ [attr.aria-valuenow]="collapsed() ? 0 : clamped()"
20883
+ [attr.aria-valuemin]="lowerBound()"
20884
+ [attr.aria-valuemax]="upperBound()"
20885
+ [attr.aria-expanded]="collapsible() ? !collapsed() : null"
20785
20886
  (pointerdown)="onDragStart($event)"
20786
20887
  (keydown)="onKeydown($event)"
20787
20888
  >
@@ -20790,12 +20891,16 @@ class StrctSplitter {
20790
20891
  <div class="strct-split__pane strct-split__pane--end">
20791
20892
  <ng-content select="[strctPaneEnd]" />
20792
20893
  </div>
20793
- `, isInline: true, styles: [".strct-split{display:flex;width:100%;min-height:0}.strct-split--vertical{flex-direction:column}.strct-split__pane{flex-grow:0;flex-shrink:0;overflow:auto;min-width:0;min-height:0}.strct-split__pane--end{flex:1 1 0}.strct-split__gutter{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:7px;cursor:col-resize;background:transparent;touch-action:none}.strct-split--vertical>.strct-split__gutter{width:auto;height:7px;cursor:row-resize}.strct-split__gutter:hover,.strct-split--dragging>.strct-split__gutter{background:var(--acc18)}.strct-split__gutter:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-split__grip{width:1.5px;height:26px;border-radius:1px;background:var(--b2)}.strct-split--vertical .strct-split__grip{width:26px;height:1.5px}.strct-split--dragging{-webkit-user-select:none;user-select:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20894
+ `, isInline: true, styles: [".strct-split{display:flex;width:100%;min-height:0}.strct-split--vertical{flex-direction:column}.strct-split__pane--collapsed{overflow:hidden}.strct-split__pane{flex-grow:0;flex-shrink:0;overflow:auto;min-width:0;min-height:0}.strct-split__pane--end{flex:1 1 0}.strct-split__gutter{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:7px;cursor:col-resize;background:transparent;touch-action:none}.strct-split--vertical>.strct-split__gutter{width:auto;height:7px;cursor:row-resize}.strct-split__gutter:hover,.strct-split--dragging>.strct-split__gutter{background:var(--acc18)}.strct-split__gutter:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-split__grip{width:1.5px;height:26px;border-radius:1px;background:var(--b2)}.strct-split--vertical .strct-split__grip{width:26px;height:1.5px}.strct-split--dragging{-webkit-user-select:none;user-select:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20794
20895
  }
20795
20896
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctSplitter, decorators: [{
20796
20897
  type: Component,
20797
20898
  args: [{ selector: 'strct-splitter', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
20798
- <div class="strct-split__pane" [style.flex-basis.%]="clamped()">
20899
+ <div
20900
+ class="strct-split__pane"
20901
+ [class.strct-split__pane--collapsed]="collapsed()"
20902
+ [style.flex-basis]="startBasis()"
20903
+ >
20799
20904
  <ng-content select="[strctPaneStart]" />
20800
20905
  </div>
20801
20906
  <div
@@ -20804,9 +20909,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
20804
20909
  tabindex="0"
20805
20910
  [attr.aria-label]="gutterLabel()"
20806
20911
  [attr.aria-orientation]="vertical() ? 'horizontal' : 'vertical'"
20807
- [attr.aria-valuenow]="clamped()"
20808
- [attr.aria-valuemin]="min()"
20809
- [attr.aria-valuemax]="max()"
20912
+ [attr.aria-valuenow]="collapsed() ? 0 : clamped()"
20913
+ [attr.aria-valuemin]="lowerBound()"
20914
+ [attr.aria-valuemax]="upperBound()"
20915
+ [attr.aria-expanded]="collapsible() ? !collapsed() : null"
20810
20916
  (pointerdown)="onDragStart($event)"
20811
20917
  (keydown)="onKeydown($event)"
20812
20918
  >
@@ -20819,8 +20925,143 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
20819
20925
  class: 'strct-split',
20820
20926
  '[class.strct-split--vertical]': 'vertical()',
20821
20927
  '[class.strct-split--dragging]': 'dragging()',
20822
- }, styles: [".strct-split{display:flex;width:100%;min-height:0}.strct-split--vertical{flex-direction:column}.strct-split__pane{flex-grow:0;flex-shrink:0;overflow:auto;min-width:0;min-height:0}.strct-split__pane--end{flex:1 1 0}.strct-split__gutter{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:7px;cursor:col-resize;background:transparent;touch-action:none}.strct-split--vertical>.strct-split__gutter{width:auto;height:7px;cursor:row-resize}.strct-split__gutter:hover,.strct-split--dragging>.strct-split__gutter{background:var(--acc18)}.strct-split__gutter:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-split__grip{width:1.5px;height:26px;border-radius:1px;background:var(--b2)}.strct-split--vertical .strct-split__grip{width:26px;height:1.5px}.strct-split--dragging{-webkit-user-select:none;user-select:none}\n"] }]
20823
- }], ctorParameters: () => [], propDecorators: { split: [{ type: i0.Input, args: [{ isSignal: true, alias: "split", required: false }] }, { type: i0.Output, args: ["splitChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], vertical: [{ type: i0.Input, args: [{ isSignal: true, alias: "vertical", required: false }] }], gutterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterLabel", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }] } });
20928
+ }, styles: [".strct-split{display:flex;width:100%;min-height:0}.strct-split--vertical{flex-direction:column}.strct-split__pane--collapsed{overflow:hidden}.strct-split__pane{flex-grow:0;flex-shrink:0;overflow:auto;min-width:0;min-height:0}.strct-split__pane--end{flex:1 1 0}.strct-split__gutter{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:7px;cursor:col-resize;background:transparent;touch-action:none}.strct-split--vertical>.strct-split__gutter{width:auto;height:7px;cursor:row-resize}.strct-split__gutter:hover,.strct-split--dragging>.strct-split__gutter{background:var(--acc18)}.strct-split__gutter:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-split__grip{width:1.5px;height:26px;border-radius:1px;background:var(--b2)}.strct-split--vertical .strct-split__grip{width:26px;height:1.5px}.strct-split--dragging{-webkit-user-select:none;user-select:none}\n"] }]
20929
+ }], ctorParameters: () => [], propDecorators: { split: [{ type: i0.Input, args: [{ isSignal: true, alias: "split", required: false }] }, { type: i0.Output, args: ["splitChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], minSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSize", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }, { type: i0.Output, args: ["collapsedChange"] }], vertical: [{ type: i0.Input, args: [{ isSignal: true, alias: "vertical", required: false }] }], gutterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterLabel", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }] } });
20930
+
20931
+ /**
20932
+ * The splitter's gutter, for layouts the splitter does not own — a shell grid,
20933
+ * a docked panel. It draws the library's grip and brings the separator
20934
+ * semantics with it: `role="separator"`, a tab stop, arrows that step, Home and
20935
+ * End for the bounds, and Enter to collapse when `collapsible`.
20936
+ *
20937
+ * <div [strctResizeHandle]="'y'" [(size)]="panelHeight" [min]="120" [max]="600"
20938
+ * aria-label="Resize the task panel"></div>
20939
+ *
20940
+ * The consumer owns the size — the handle only reports it, so the value can be
20941
+ * persisted, clamped or animated as the layout needs.
20942
+ */
20943
+ class StrctResizeHandle {
20944
+ /** Which axis the handle resizes along: `'x'` (default) or `'y'`. */
20945
+ axis = input('x', { ...(ngDevMode ? { debugName: "axis" } : /* istanbul ignore next */ {}), alias: 'strctResizeHandle' });
20946
+ /** The size being dragged, in px (two-way). */
20947
+ size = model(240, /* @ts-ignore */
20948
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
20949
+ /** Bounds, in px. */
20950
+ min = input(0, /* @ts-ignore */
20951
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
20952
+ max = input(Number.POSITIVE_INFINITY, /* @ts-ignore */
20953
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
20954
+ /** Arrow-key step in px; Shift multiplies it by four. */
20955
+ step = input(16, /* @ts-ignore */
20956
+ ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
20957
+ /** Enter collapses the pane the handle sizes. */
20958
+ collapsible = input(false, { ...(ngDevMode ? { debugName: "collapsible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
20959
+ /** Whether it is collapsed (two-way). */
20960
+ collapsed = model(false, /* @ts-ignore */
20961
+ ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
20962
+ /**
20963
+ * Which side of the handle the sized pane is on. `'before'` (default) grows
20964
+ * the pane as the pointer moves toward the inline/block end.
20965
+ */
20966
+ side = input('before', /* @ts-ignore */
20967
+ ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
20968
+ el = inject(ElementRef);
20969
+ dragging = signal(false, /* @ts-ignore */
20970
+ ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
20971
+ origin = 0;
20972
+ originSize = 0;
20973
+ rtl = computed(() => getComputedStyle(this.el.nativeElement).direction === 'rtl', /* @ts-ignore */
20974
+ ...(ngDevMode ? [{ debugName: "rtl" }] : /* istanbul ignore next */ []));
20975
+ move = (e) => this.onMove(e);
20976
+ up = () => this.onUp();
20977
+ constructor() {
20978
+ inject(DestroyRef).onDestroy(() => this.detach());
20979
+ }
20980
+ onDown(event) {
20981
+ event.preventDefault();
20982
+ this.el.nativeElement.setPointerCapture?.(event.pointerId);
20983
+ this.origin = this.axis() === 'y' ? event.clientY : event.clientX;
20984
+ this.originSize = this.size();
20985
+ this.dragging.set(true);
20986
+ document.addEventListener('pointermove', this.move);
20987
+ document.addEventListener('pointerup', this.up);
20988
+ document.addEventListener('pointercancel', this.up);
20989
+ }
20990
+ onMove(event) {
20991
+ let delta = (this.axis() === 'y' ? event.clientY : event.clientX) - this.origin;
20992
+ // Pointer coordinates are physical; the pane is logical.
20993
+ if (this.axis() === 'x' && this.rtl())
20994
+ delta = -delta;
20995
+ if (this.side() === 'after')
20996
+ delta = -delta;
20997
+ if (this.collapsed())
20998
+ this.collapsed.set(false);
20999
+ this.commit(this.originSize + delta);
21000
+ }
21001
+ onUp() {
21002
+ this.dragging.set(false);
21003
+ this.detach();
21004
+ }
21005
+ detach() {
21006
+ document.removeEventListener('pointermove', this.move);
21007
+ document.removeEventListener('pointerup', this.up);
21008
+ document.removeEventListener('pointercancel', this.up);
21009
+ }
21010
+ onKeydown(event) {
21011
+ if (this.collapsible() && (event.key === 'Enter' || event.key === ' ')) {
21012
+ event.preventDefault();
21013
+ this.collapsed.update((v) => !v);
21014
+ return;
21015
+ }
21016
+ let dec = this.axis() === 'y' ? 'ArrowUp' : 'ArrowLeft';
21017
+ let inc = this.axis() === 'y' ? 'ArrowDown' : 'ArrowRight';
21018
+ if (this.axis() === 'x' && this.rtl())
21019
+ [dec, inc] = [inc, dec];
21020
+ if (this.side() === 'after')
21021
+ [dec, inc] = [inc, dec];
21022
+ const step = this.step() * (event.shiftKey ? 4 : 1);
21023
+ let next = null;
21024
+ if (event.key === dec)
21025
+ next = this.size() - step;
21026
+ else if (event.key === inc)
21027
+ next = this.size() + step;
21028
+ else if (event.key === 'Home')
21029
+ next = this.min();
21030
+ else if (event.key === 'End')
21031
+ next = Number.isFinite(this.max()) ? this.max() : this.size() + step * 4;
21032
+ if (next == null)
21033
+ return;
21034
+ event.preventDefault();
21035
+ if (this.collapsed())
21036
+ this.collapsed.set(false);
21037
+ this.commit(next);
21038
+ }
21039
+ commit(value) {
21040
+ this.size.set(Math.round(Math.min(this.max(), Math.max(this.min(), value))));
21041
+ }
21042
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctResizeHandle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
21043
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: StrctResizeHandle, isStandalone: true, selector: "[strctResizeHandle]", inputs: { axis: { classPropertyName: "axis", publicName: "strctResizeHandle", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { size: "sizeChange", collapsed: "collapsedChange" }, host: { attributes: { "role": "separator", "tabindex": "0" }, listeners: { "pointerdown": "onDown($event)", "keydown": "onKeydown($event)" }, properties: { "class.strct-resize--y": "axis() === 'y'", "class.strct-resize--dragging": "dragging()", "attr.aria-orientation": "axis() === 'y' ? 'horizontal' : 'vertical'", "attr.aria-valuenow": "size()", "attr.aria-valuemin": "min()", "attr.aria-valuemax": "max()", "attr.aria-expanded": "collapsible() ? !collapsed() : null" }, classAttribute: "strct-resize" }, ngImport: i0 });
21044
+ }
21045
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctResizeHandle, decorators: [{
21046
+ type: Directive,
21047
+ args: [{
21048
+ selector: '[strctResizeHandle]',
21049
+ host: {
21050
+ class: 'strct-resize',
21051
+ role: 'separator',
21052
+ tabindex: '0',
21053
+ '[class.strct-resize--y]': "axis() === 'y'",
21054
+ '[class.strct-resize--dragging]': 'dragging()',
21055
+ '[attr.aria-orientation]': "axis() === 'y' ? 'horizontal' : 'vertical'",
21056
+ '[attr.aria-valuenow]': 'size()',
21057
+ '[attr.aria-valuemin]': 'min()',
21058
+ '[attr.aria-valuemax]': 'max()',
21059
+ '[attr.aria-expanded]': 'collapsible() ? !collapsed() : null',
21060
+ '(pointerdown)': 'onDown($event)',
21061
+ '(keydown)': 'onKeydown($event)',
21062
+ },
21063
+ }]
21064
+ }], ctorParameters: () => [], propDecorators: { axis: [{ type: i0.Input, args: [{ isSignal: true, alias: "strctResizeHandle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }, { type: i0.Output, args: ["sizeChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }, { type: i0.Output, args: ["collapsedChange"] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }] } });
20824
21065
 
20825
21066
  /**
20826
21067
  * Dual-list transfer (picklist) — "assign hosts to the cluster": all items on
@@ -22216,6 +22457,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
22216
22457
  args: ['document:keydown.escape', ['$event']]
22217
22458
  }] } });
22218
22459
 
22460
+ /**
22461
+ * Connects several `[strctReorder]` lists, so a card can move between the
22462
+ * columns of a board — by its handle, or with Alt+ArrowLeft / Alt+ArrowRight.
22463
+ * Moves within one list stay on that list's `reordered`; moves across lists
22464
+ * come out here.
22465
+ */
22466
+ class StrctReorderGroup {
22467
+ /** A card moved from one list to another. */
22468
+ moved = output();
22469
+ /** Every list in this group, in DOM order. */
22470
+ lists = signal([], /* @ts-ignore */
22471
+ ...(ngDevMode ? [{ debugName: "lists" }] : /* istanbul ignore next */ []));
22472
+ /** Where the current drag started, so a drop elsewhere knows its origin. */
22473
+ source = signal(null, /* @ts-ignore */
22474
+ ...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
22475
+ register(list) {
22476
+ this.lists.update((ls) => [...ls, list]);
22477
+ }
22478
+ unregister(list) {
22479
+ this.lists.update((ls) => ls.filter((l) => l !== list));
22480
+ }
22481
+ /** The list next to `list` in the given direction, or null at the ends. */
22482
+ neighbour(list, dir) {
22483
+ const ordered = this.ordered();
22484
+ const i = ordered.indexOf(list);
22485
+ return ordered[i + dir] ?? null;
22486
+ }
22487
+ /** DOM order, not registration order — columns read left to right. */
22488
+ ordered() {
22489
+ return [...this.lists()].sort((a, b) => a.element().compareDocumentPosition(b.element()) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
22490
+ }
22491
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorderGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
22492
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctReorderGroup, isStandalone: true, selector: "[strctReorderGroup]", outputs: { moved: "moved" }, ngImport: i0 });
22493
+ }
22494
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorderGroup, decorators: [{
22495
+ type: Directive,
22496
+ args: [{ selector: '[strctReorderGroup]' }]
22497
+ }], propDecorators: { moved: [{ type: i0.Output, args: ["moved"] }] } });
22219
22498
  let reorderCounter = 0;
22220
22499
  /**
22221
22500
  * List drag-reorder primitive — the consumer owns the array:
@@ -22238,6 +22517,8 @@ let reorderCounter = 0;
22238
22517
  */
22239
22518
  class StrctReorder {
22240
22519
  host = inject(ElementRef);
22520
+ /** The group this list belongs to, when it is one of several. */
22521
+ group = inject(StrctReorderGroup, { optional: true });
22241
22522
  renderer = inject(Renderer2);
22242
22523
  doc = inject(DOCUMENT);
22243
22524
  announcer = inject(StrctAnnouncer);
@@ -22257,6 +22538,12 @@ class StrctReorder {
22257
22538
  */
22258
22539
  announcement = input((label, position, total) => `Moved ${label} to position ${position} of ${total}`, /* @ts-ignore */
22259
22540
  ...(ngDevMode ? [{ debugName: "announcement" }] : /* istanbul ignore next */ []));
22541
+ /** This list's name inside a `[strctReorderGroup]`. */
22542
+ listId = input('', /* @ts-ignore */
22543
+ ...(ngDevMode ? [{ debugName: "listId" }] : /* istanbul ignore next */ []));
22544
+ /** What a move between lists says (localizable). */
22545
+ moveAnnouncement = input((label, list, position, total) => `Moved ${label} to ${list}, position ${position} of ${total}`, /* @ts-ignore */
22546
+ ...(ngDevMode ? [{ debugName: "moveAnnouncement" }] : /* istanbul ignore next */ []));
22260
22547
  dragIndex = signal(null, /* @ts-ignore */
22261
22548
  ...(ngDevMode ? [{ debugName: "dragIndex" }] : /* istanbul ignore next */ []));
22262
22549
  overIndex = signal(null, /* @ts-ignore */
@@ -22264,7 +22551,31 @@ class StrctReorder {
22264
22551
  /** Id of the sr-only instructions element the items point to. */
22265
22552
  instructionsId = `strct-reorder-hint-${++reorderCounter}`;
22266
22553
  hint = null;
22554
+ /** The container element — the group orders its lists by DOM position. */
22555
+ element() {
22556
+ return this.host.nativeElement;
22557
+ }
22558
+ /** Move an item into this list at `index`, and say so. */
22559
+ acceptFrom(from, fromIndex, index) {
22560
+ const item = from.items()[fromIndex];
22561
+ if (!item)
22562
+ return;
22563
+ const label = item.textContent?.trim() ?? '';
22564
+ const toIndex = Math.max(0, Math.min(index, this.items().length));
22565
+ from.dragIndex.set(null);
22566
+ this.overIndex.set(null);
22567
+ this.group?.source.set(null);
22568
+ this.group?.moved.emit({
22569
+ item,
22570
+ fromList: from.listId(),
22571
+ toList: this.listId(),
22572
+ fromIndex,
22573
+ toIndex,
22574
+ });
22575
+ this.announcer.announce(this.moveAnnouncement()(label, this.listId(), toIndex + 1, this.items().length + 1));
22576
+ }
22267
22577
  constructor() {
22578
+ this.group?.register(this);
22268
22579
  // Keep the sr-only instructions element in sync with the input.
22269
22580
  effect(() => {
22270
22581
  const text = this.instructions();
@@ -22297,18 +22608,24 @@ class StrctReorder {
22297
22608
  onContainerDragOver(event) {
22298
22609
  // Only the container's own empty space (below the last item); drags over
22299
22610
  // items are handled by the items themselves.
22300
- if (this.dragIndex() == null)
22611
+ if (this.dragIndex() == null && !this.group?.source())
22301
22612
  return;
22302
22613
  if (event.target.closest('[strctReorderItem]'))
22303
22614
  return;
22304
22615
  event.preventDefault();
22305
22616
  }
22306
22617
  onContainerDrop(event) {
22618
+ if (event.target.closest('[strctReorderItem]'))
22619
+ return;
22620
+ const source = this.group?.source();
22621
+ if (source && source.list !== this) {
22622
+ event.preventDefault();
22623
+ this.acceptFrom(source.list, source.index, this.items().length);
22624
+ return;
22625
+ }
22307
22626
  const from = this.dragIndex();
22308
22627
  if (from == null)
22309
22628
  return; // an item already consumed this drop
22310
- if (event.target.closest('[strctReorderItem]'))
22311
- return;
22312
22629
  event.preventDefault();
22313
22630
  // Drop into empty space moves the item to the end.
22314
22631
  this.commit(from, this.items().length - 1);
@@ -22322,18 +22639,19 @@ class StrctReorder {
22322
22639
  this.overIndex.set(null);
22323
22640
  }
22324
22641
  ngOnDestroy() {
22642
+ this.group?.unregister(this);
22325
22643
  if (this.hint) {
22326
22644
  this.renderer.removeChild(this.doc.body, this.hint);
22327
22645
  this.hint = null;
22328
22646
  }
22329
22647
  }
22330
22648
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorder, deps: [], target: i0.ɵɵFactoryTarget.Directive });
22331
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: StrctReorder, isStandalone: true, selector: "[strctReorder]", inputs: { reorderDisabled: { classPropertyName: "reorderDisabled", publicName: "reorderDisabled", isSignal: true, isRequired: false, transformFunction: null }, instructions: { classPropertyName: "instructions", publicName: "instructions", isSignal: true, isRequired: false, transformFunction: null }, announcement: { classPropertyName: "announcement", publicName: "announcement", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { reordered: "reordered" }, host: { listeners: { "dragover": "onContainerDragOver($event)", "drop": "onContainerDrop($event)", "dragleave": "onDragLeave($event)" } }, ngImport: i0 });
22649
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: StrctReorder, isStandalone: true, selector: "[strctReorder]", inputs: { reorderDisabled: { classPropertyName: "reorderDisabled", publicName: "reorderDisabled", isSignal: true, isRequired: false, transformFunction: null }, instructions: { classPropertyName: "instructions", publicName: "instructions", isSignal: true, isRequired: false, transformFunction: null }, announcement: { classPropertyName: "announcement", publicName: "announcement", isSignal: true, isRequired: false, transformFunction: null }, listId: { classPropertyName: "listId", publicName: "listId", isSignal: true, isRequired: false, transformFunction: null }, moveAnnouncement: { classPropertyName: "moveAnnouncement", publicName: "moveAnnouncement", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { reordered: "reordered" }, host: { listeners: { "dragover": "onContainerDragOver($event)", "drop": "onContainerDrop($event)", "dragleave": "onDragLeave($event)" } }, ngImport: i0 });
22332
22650
  }
22333
22651
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorder, decorators: [{
22334
22652
  type: Directive,
22335
22653
  args: [{ selector: '[strctReorder]' }]
22336
- }], ctorParameters: () => [], propDecorators: { reordered: [{ type: i0.Output, args: ["reordered"] }], reorderDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderDisabled", required: false }] }], instructions: [{ type: i0.Input, args: [{ isSignal: true, alias: "instructions", required: false }] }], announcement: [{ type: i0.Input, args: [{ isSignal: true, alias: "announcement", required: false }] }], onContainerDragOver: [{
22654
+ }], ctorParameters: () => [], propDecorators: { reordered: [{ type: i0.Output, args: ["reordered"] }], reorderDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderDisabled", required: false }] }], instructions: [{ type: i0.Input, args: [{ isSignal: true, alias: "instructions", required: false }] }], announcement: [{ type: i0.Input, args: [{ isSignal: true, alias: "announcement", required: false }] }], listId: [{ type: i0.Input, args: [{ isSignal: true, alias: "listId", required: false }] }], moveAnnouncement: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveAnnouncement", required: false }] }], onContainerDragOver: [{
22337
22655
  type: HostListener,
22338
22656
  args: ['dragover', ['$event']]
22339
22657
  }], onContainerDrop: [{
@@ -22343,6 +22661,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
22343
22661
  type: HostListener,
22344
22662
  args: ['dragleave', ['$event']]
22345
22663
  }] } });
22664
+ /**
22665
+ * The only place a drag may start from, when an item has one. Content that is
22666
+ * itself draggable — text selection, a chart brush — must not start a move.
22667
+ */
22668
+ class StrctReorderHandle {
22669
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorderHandle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
22670
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctReorderHandle, isStandalone: true, selector: "[strctReorderHandle]", host: { classAttribute: "strct-reorder__handle" }, ngImport: i0 });
22671
+ }
22672
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorderHandle, decorators: [{
22673
+ type: Directive,
22674
+ args: [{ selector: '[strctReorderHandle]', host: { class: 'strct-reorder__handle' } }]
22675
+ }] });
22346
22676
  /** One draggable row inside a `[strctReorder]` container. */
22347
22677
  class StrctReorderItem {
22348
22678
  list = inject(StrctReorder);
@@ -22352,6 +22682,12 @@ class StrctReorderItem {
22352
22682
  hostTabindex() {
22353
22683
  return this.hadOwnTabindex ? null : 0;
22354
22684
  }
22685
+ /** The keys that apply: the sideways pair only when there is somewhere to go. */
22686
+ shortcuts() {
22687
+ return this.list.group
22688
+ ? 'Alt+ArrowUp Alt+ArrowDown Alt+ArrowLeft Alt+ArrowRight'
22689
+ : 'Alt+ArrowUp Alt+ArrowDown';
22690
+ }
22355
22691
  isDragging() {
22356
22692
  return this.list.dragIndex() === this.index();
22357
22693
  }
@@ -22361,22 +22697,38 @@ class StrctReorderItem {
22361
22697
  index() {
22362
22698
  return this.list.indexOf(this.el.nativeElement);
22363
22699
  }
22700
+ /** Where the last pointerdown landed — a drag may only start on a handle. */
22701
+ fromHandle = false;
22702
+ onPointerDown(event) {
22703
+ this.fromHandle = !!event.target.closest('[strctReorderHandle]');
22704
+ }
22364
22705
  onDragStart(event) {
22365
22706
  if (this.list.reorderDisabled())
22366
22707
  return;
22708
+ // With a handle present, only the handle starts a move.
22709
+ if (this.el.nativeElement.querySelector('[strctReorderHandle]') && !this.fromHandle) {
22710
+ event.preventDefault();
22711
+ return;
22712
+ }
22367
22713
  this.list.dragIndex.set(this.index());
22714
+ this.list.group?.source.set({ list: this.list, index: this.index() });
22368
22715
  event.dataTransfer?.setData('text/plain', String(this.index()));
22369
22716
  if (event.dataTransfer)
22370
22717
  event.dataTransfer.effectAllowed = 'move';
22371
22718
  }
22372
22719
  onDragOver(event) {
22373
- if (this.list.dragIndex() == null)
22720
+ if (this.list.dragIndex() == null && !this.list.group?.source())
22374
22721
  return;
22375
22722
  event.preventDefault();
22376
22723
  this.list.overIndex.set(this.index());
22377
22724
  }
22378
22725
  onDrop(event) {
22379
22726
  event.preventDefault();
22727
+ const source = this.list.group?.source();
22728
+ if (source && source.list !== this.list) {
22729
+ this.list.acceptFrom(source.list, source.index, this.index());
22730
+ return;
22731
+ }
22380
22732
  const from = this.list.dragIndex();
22381
22733
  if (from == null)
22382
22734
  return;
@@ -22385,10 +22737,23 @@ class StrctReorderItem {
22385
22737
  onDragEnd() {
22386
22738
  this.list.dragIndex.set(null);
22387
22739
  this.list.overIndex.set(null);
22740
+ this.list.group?.source.set(null);
22388
22741
  }
22389
22742
  onKeydown(event) {
22390
22743
  if (this.list.reorderDisabled() || !event.altKey)
22391
22744
  return;
22745
+ const group = this.list.group;
22746
+ // Alt+Left / Alt+Right move to the neighbouring list at the same index.
22747
+ if (group && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
22748
+ const target = group.neighbour(this.list, event.key === 'ArrowLeft' ? -1 : 1);
22749
+ if (!target)
22750
+ return;
22751
+ event.preventDefault();
22752
+ const index = this.index();
22753
+ target.acceptFrom(this.list, index, index);
22754
+ setTimeout(() => target.items()[Math.min(index, target.items().length - 1)]?.focus());
22755
+ return;
22756
+ }
22392
22757
  if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown')
22393
22758
  return;
22394
22759
  event.preventDefault();
@@ -22401,7 +22766,7 @@ class StrctReorderItem {
22401
22766
  setTimeout(() => this.list.items()[to]?.focus());
22402
22767
  }
22403
22768
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorderItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
22404
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctReorderItem, isStandalone: true, selector: "[strctReorderItem]", host: { listeners: { "dragstart": "onDragStart($event)", "dragover": "onDragOver($event)", "drop": "onDrop($event)", "dragend": "onDragEnd()", "keydown": "onKeydown($event)" }, properties: { "attr.draggable": "!list.reorderDisabled()", "attr.tabindex": "hostTabindex()", "class.strct-reorder--dragging": "isDragging()", "class.strct-reorder--over": "isOver()", "attr.aria-roledescription": "'sortable'", "attr.aria-keyshortcuts": "'Alt+ArrowUp Alt+ArrowDown'", "attr.aria-posinset": "index() + 1", "attr.aria-setsize": "list.items().length", "attr.aria-describedby": "list.instructions() ? list.instructionsId : null" } }, ngImport: i0 });
22769
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctReorderItem, isStandalone: true, selector: "[strctReorderItem]", host: { listeners: { "pointerdown": "onPointerDown($event)", "dragstart": "onDragStart($event)", "dragover": "onDragOver($event)", "drop": "onDrop($event)", "dragend": "onDragEnd()", "keydown": "onKeydown($event)" }, properties: { "attr.draggable": "!list.reorderDisabled()", "attr.tabindex": "hostTabindex()", "class.strct-reorder--dragging": "isDragging()", "class.strct-reorder--over": "isOver()", "attr.aria-roledescription": "'sortable'", "attr.aria-keyshortcuts": "shortcuts()", "attr.aria-posinset": "index() + 1", "attr.aria-setsize": "list.items().length", "attr.aria-describedby": "list.instructions() ? list.instructionsId : null" } }, ngImport: i0 });
22405
22770
  }
22406
22771
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctReorderItem, decorators: [{
22407
22772
  type: Directive,
@@ -22413,13 +22778,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
22413
22778
  '[class.strct-reorder--dragging]': 'isDragging()',
22414
22779
  '[class.strct-reorder--over]': 'isOver()',
22415
22780
  '[attr.aria-roledescription]': "'sortable'",
22416
- '[attr.aria-keyshortcuts]': "'Alt+ArrowUp Alt+ArrowDown'",
22781
+ '[attr.aria-keyshortcuts]': 'shortcuts()',
22417
22782
  '[attr.aria-posinset]': 'index() + 1',
22418
22783
  '[attr.aria-setsize]': 'list.items().length',
22419
22784
  '[attr.aria-describedby]': 'list.instructions() ? list.instructionsId : null',
22420
22785
  },
22421
22786
  }]
22422
- }], propDecorators: { onDragStart: [{
22787
+ }], propDecorators: { onPointerDown: [{
22788
+ type: HostListener,
22789
+ args: ['pointerdown', ['$event']]
22790
+ }], onDragStart: [{
22423
22791
  type: HostListener,
22424
22792
  args: ['dragstart', ['$event']]
22425
22793
  }], onDragOver: [{
@@ -22793,6 +23161,106 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
22793
23161
  }, styles: [".strct-steps{display:block;min-width:0}.strct-steps__list{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;align-items:center;gap:6px 4px}.strct-steps--vertical .strct-steps__list{flex-direction:column;align-items:stretch;flex-wrap:nowrap}.strct-steps__step{position:relative;display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1px solid var(--b2);border-radius:999px;font-size:var(--text-sm);color:var(--t2);background:var(--bg-1);min-width:0}.strct-steps--dense .strct-steps__step{padding:2px 8px}.strct-steps__list>.strct-steps__step+.strct-steps__step:before{content:\"\";position:absolute;inset-inline-start:-5px;width:5px;height:1px;background:var(--b2)}.strct-steps--vertical .strct-steps__list>.strct-steps__step+.strct-steps__step:before{inset-inline-start:14px;top:-7px;width:1px;height:7px}.strct-steps__marker:empty{display:none}.strct-steps__marker{display:inline-flex;align-items:center;justify-content:center;flex:none;width:18px;height:18px;border-radius:50%;font-size:11px;font-weight:600;background:var(--bg-3);color:var(--t2)}.strct-steps__text{display:flex;flex-direction:column;min-width:0}.strct-steps__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-steps__desc{font-size:var(--text-sm);color:var(--t3);white-space:normal}.strct-steps__action{margin-inline-start:auto;padding-inline-start:8px;flex:none}.strct-steps__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-steps__step[data-state=done]{border-color:var(--success);color:var(--success)}.strct-steps__step[data-state=done] .strct-steps__marker{background:var(--success);color:var(--inv)}.strct-steps__step[data-state=active]{border-color:var(--acc);color:var(--acc);background:var(--acc-s)}.strct-steps__step[data-state=active] .strct-steps__marker{background:var(--acc);color:var(--inv)}.strct-steps__step[data-state=failed]{border-color:var(--critical);color:var(--critical)}.strct-steps__step[data-state=failed] .strct-steps__marker{background:var(--critical);color:var(--inv)}.strct-steps__step[data-state=blocked]{border-color:var(--warning);color:var(--warning)}.strct-steps__step[data-state=blocked] .strct-steps__marker{background:var(--warning);color:var(--inv)}.strct-steps__step[data-state=skipped]{color:var(--t3);border-style:dashed}.strct-steps__step[data-state=skipped] .strct-steps__label{text-decoration:line-through}.strct-steps__step[data-state=pending]{color:var(--t3);border-color:var(--t4)}.strct-steps__step[data-state=active]:after{content:\"\";position:absolute;inset:-1px;border-radius:inherit;border:1px solid var(--acc);animation:strct-steps-pulse 1.4s ease-out infinite;pointer-events:none}@keyframes strct-steps-pulse{0%{opacity:.9;transform:scale(1)}to{opacity:0;transform:scale(1.06)}}@media(prefers-reduced-motion:reduce){.strct-steps__step[data-state=active]:after{animation:none;opacity:.5;transform:none}}.strct-steps--dots .strct-steps__step{padding:0;border:0;background:none;gap:4px}.strct-steps--dots .strct-steps__label{display:none}.strct-steps--dots .strct-steps__marker{display:inline-flex;width:9px;height:9px;font-size:0}.strct-steps--dots .strct-steps__step[data-state=pending] .strct-steps__marker{background:var(--bg-3);box-shadow:inset 0 0 0 1px var(--b3)}.strct-steps--dots .strct-steps__list>.strct-steps__step+.strct-steps__step:before{inset-inline-start:-4px;width:4px}.strct-steps--cards .strct-steps__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(var(--strct-steps-card-min, 220px),100%),1fr));gap:var(--space-3)}.strct-steps--cards .strct-steps__step{align-items:flex-start;border-radius:var(--radius-lg);padding:var(--space-3);background:var(--bg-1)}.strct-steps--cards .strct-steps__label{font-weight:600;white-space:normal}.strct-steps--cards .strct-steps__list>.strct-steps__step+.strct-steps__step:before{content:none}\n"] }]
22794
23162
  }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], numbered: [{ type: i0.Input, args: [{ isSignal: true, alias: "numbered", required: false }] }], dense: [{ type: i0.Input, args: [{ isSignal: true, alias: "dense", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], actionTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctStepAction), { ...{ read: TemplateRef }, isSignal: true }] }] } });
22795
23163
 
23164
+ const STATE_ICON = {
23165
+ empty: 'monitor',
23166
+ off: 'stopped',
23167
+ error: 'warning',
23168
+ };
23169
+ /**
23170
+ * A live picture — a console thumbnail, a camera — sits in a fixed-ratio frame,
23171
+ * and when there is no picture yet, or none at all, the frame says why **in its
23172
+ * own small space**: an empty state is too large for a 240px card.
23173
+ *
23174
+ * <strct-media-frame ratio="4 / 3"><img [src]="thumb" alt="" /></strct-media-frame>
23175
+ * <strct-media-frame state="off" message="The VM is off" />
23176
+ */
23177
+ class StrctMediaFrame {
23178
+ /** The frame's aspect ratio, as a CSS `aspect-ratio` value. */
23179
+ ratio = input('4 / 3', /* @ts-ignore */
23180
+ ...(ngDevMode ? [{ debugName: "ratio" }] : /* istanbul ignore next */ []));
23181
+ /** What the frame shows: the projected picture, or why there is none. */
23182
+ state = input('content', /* @ts-ignore */
23183
+ ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
23184
+ /** The placeholder's line ("The VM is off"). */
23185
+ message = input('', /* @ts-ignore */
23186
+ ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
23187
+ /** Overrides the icon derived from `state`. */
23188
+ icon = input('', /* @ts-ignore */
23189
+ ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
23190
+ /** The whole frame becomes one tab stop that emits `activated`. */
23191
+ interactive = input(false, { ...(ngDevMode ? { debugName: "interactive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
23192
+ /** The accessible name of that control; falls back to `message`. */
23193
+ activateLabel = input('', /* @ts-ignore */
23194
+ ...(ngDevMode ? [{ debugName: "activateLabel" }] : /* istanbul ignore next */ []));
23195
+ /** The frame was activated. */
23196
+ activated = output();
23197
+ iconName = computed(() => {
23198
+ const explicit = this.icon();
23199
+ if (explicit)
23200
+ return explicit;
23201
+ const state = this.state();
23202
+ return state === 'content' || state === 'loading' ? '' : STATE_ICON[state];
23203
+ }, /* @ts-ignore */
23204
+ ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
23205
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMediaFrame, deps: [], target: i0.ɵɵFactoryTarget.Component });
23206
+ 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: `
23207
+ @if (state() === 'content') {
23208
+ <ng-content />
23209
+ } @else {
23210
+ <span class="strct-mf__placeholder">
23211
+ @if (state() === 'loading') {
23212
+ <strct-spinner size="sm" />
23213
+ } @else if (iconName()) {
23214
+ <strct-icon [name]="iconName()" [size]="20" />
23215
+ }
23216
+ @if (message()) {
23217
+ <span class="strct-mf__msg">{{ message() }}</span>
23218
+ }
23219
+ </span>
23220
+ }
23221
+ @if (interactive()) {
23222
+ <button
23223
+ type="button"
23224
+ class="strct-mf__hit"
23225
+ [attr.aria-label]="activateLabel() || message() || null"
23226
+ (click)="activated.emit()"
23227
+ ></button>
23228
+ }
23229
+ `, 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 });
23230
+ }
23231
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMediaFrame, decorators: [{
23232
+ type: Component,
23233
+ args: [{ selector: 'strct-media-frame', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon, StrctSpinner], template: `
23234
+ @if (state() === 'content') {
23235
+ <ng-content />
23236
+ } @else {
23237
+ <span class="strct-mf__placeholder">
23238
+ @if (state() === 'loading') {
23239
+ <strct-spinner size="sm" />
23240
+ } @else if (iconName()) {
23241
+ <strct-icon [name]="iconName()" [size]="20" />
23242
+ }
23243
+ @if (message()) {
23244
+ <span class="strct-mf__msg">{{ message() }}</span>
23245
+ }
23246
+ </span>
23247
+ }
23248
+ @if (interactive()) {
23249
+ <button
23250
+ type="button"
23251
+ class="strct-mf__hit"
23252
+ [attr.aria-label]="activateLabel() || message() || null"
23253
+ (click)="activated.emit()"
23254
+ ></button>
23255
+ }
23256
+ `, host: {
23257
+ class: 'strct-mf',
23258
+ '[style.aspect-ratio]': 'ratio()',
23259
+ '[attr.data-state]': 'state()',
23260
+ '[class.strct-mf--interactive]': 'interactive()',
23261
+ }, 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"] }]
23262
+ }], 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"] }] } });
23263
+
22796
23264
  /**
22797
23265
  * A value change, as one phrase: "v10.27 → v10.28". The old value is muted, the
22798
23266
  * arrow is the library's, the new one is emphasised — and assistive tech hears
@@ -24709,5 +25177,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
24709
25177
  * Generated bundle index. Do not edit.
24710
25178
  */
24711
25179
 
24712
- 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, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCardHeaderActions, StrctCardHeaderMeta, StrctCardHeaderNote, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChange, StrctChart, 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, 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, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctModalContent, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPageHeaderTitleMeta, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProgress, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderItem, 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, StrctWizard, StrctWizardAside, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctValidationIcon, strctValidationTone, unlockBodyScroll };
25180
+ 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, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCardHeaderActions, StrctCardHeaderMeta, StrctCardHeaderNote, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChange, StrctChart, 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, 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, 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, StrctWizard, StrctWizardAside, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctValidationIcon, strctValidationTone, unlockBodyScroll };
24713
25181
  //# sourceMappingURL=akcelik-strct.mjs.map