@akcelik/strct 5.9.0 → 5.11.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.
@@ -1890,6 +1890,16 @@ class StrctListItem {
1890
1890
  * row at once; this is the per-row form.
1891
1891
  */
1892
1892
  wrap = input(false, { ...(ngDevMode ? { debugName: "wrap" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1893
+ /**
1894
+ * The row cannot be activated — a conversation that cannot be switched away
1895
+ * from while a reply arrives. It keeps its tab stop and says
1896
+ * `aria-disabled`, so the reason can be read; a keyboard or touch user
1897
+ * never sees a `title`.
1898
+ */
1899
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1900
+ /** Why it cannot be activated, read as the row's description. */
1901
+ disabledReason = input('', /* @ts-ignore */
1902
+ ...(ngDevMode ? [{ debugName: "disabledReason" }] : /* istanbul ignore next */ []));
1893
1903
  /** Marks the current row (`aria-current`). */
1894
1904
  selected = input(false, { ...(ngDevMode ? { debugName: "selected" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1895
1905
  /** Optional leading rail, as `strct-card [status]`. */
@@ -1898,16 +1908,19 @@ class StrctListItem {
1898
1908
  /** Emitted when an `interactive` row is activated. */
1899
1909
  activated = output();
1900
1910
  onActivate() {
1901
- if (this.interactive())
1911
+ if (this.interactive() && !this.disabled())
1902
1912
  this.activated.emit();
1903
1913
  }
1904
1914
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctListItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
1905
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctListItem, isStandalone: true, selector: "strct-list-item", inputs: { interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, wrap: { classPropertyName: "wrap", publicName: "wrap", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "activated" }, host: { attributes: { "role": "listitem" }, properties: { "class.strct-li--interactive": "interactive()", "class.strct-li--wrap": "wrap()", "class.strct-li--selected": "selected()", "class.strct-li--status": "status()", "attr.data-status": "status()" }, classAttribute: "strct-li" }, ngImport: i0, template: `
1915
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctListItem, isStandalone: true, selector: "strct-list-item", inputs: { interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, wrap: { classPropertyName: "wrap", publicName: "wrap", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledReason: { classPropertyName: "disabledReason", publicName: "disabledReason", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "activated" }, host: { attributes: { "role": "listitem" }, properties: { "class.strct-li--interactive": "interactive()", "class.strct-li--wrap": "wrap()", "class.strct-li--disabled": "disabled()", "class.strct-li--selected": "selected()", "class.strct-li--status": "status()", "attr.data-status": "status()" }, classAttribute: "strct-li" }, ngImport: i0, template: `
1906
1916
  <div
1907
1917
  class="strct-li__main"
1908
1918
  [attr.role]="interactive() ? 'button' : null"
1909
1919
  [attr.tabindex]="interactive() ? 0 : null"
1910
1920
  [attr.aria-current]="selected() ? 'true' : null"
1921
+ [attr.aria-disabled]="disabled() ? 'true' : null"
1922
+ [attr.title]="disabledReason() || null"
1923
+ [attr.aria-description]="disabled() ? disabledReason() || null : null"
1911
1924
  (click)="onActivate()"
1912
1925
  (keydown.enter)="onActivate()"
1913
1926
  (keydown.space)="$event.preventDefault(); onActivate()"
@@ -1920,7 +1933,7 @@ class StrctListItem {
1920
1933
  <span class="strct-li__meta"><ng-content select="[strctListItemMeta]" /></span>
1921
1934
  </div>
1922
1935
  <span class="strct-li__trailing"><ng-content select="[strctListItemTrailing]" /></span>
1923
- `, isInline: true, styles: [".strct-li{display:flex;align-items:center;gap:var(--space-2);padding-inline:var(--space-3);position:relative}.strct-list--flush .strct-li{padding-inline:0}.strct-list--dividers .strct-li+.strct-li{border-block-start:1px solid var(--b1)}.strct-li__main{display:flex;align-items:center;gap:var(--space-2);flex:1;min-width:0;min-height:44px;padding-block:6px;text-align:start;border-radius:var(--radius-sm)}.strct-list--dense .strct-li__main{min-height:32px;padding-block:2px}.strct-li--interactive .strct-li__main{cursor:pointer}.strct-li--interactive:hover{background:var(--bg-2)}.strct-li--selected{background:var(--acc-s)}.strct-li__main:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-li--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:2px;background:var(--t3)}.strct-li[data-status=accent]:before{background:var(--acc)}.strct-li[data-status=success]:before{background:var(--success)}.strct-li[data-status=warning]:before{background:var(--warning)}.strct-li[data-status=critical]:before{background:var(--critical)}.strct-li--wrap .strct-li__main,.strct-list--wrap .strct-li__main{align-items:flex-start}.strct-li--wrap .strct-li__leading,.strct-list--wrap .strct-li__leading{min-height:calc(var(--text-md) * 1.45)}.strct-li--wrap .strct-li__title,.strct-li--wrap .strct-li__desc,.strct-list--wrap .strct-li__title,.strct-list--wrap .strct-li__desc{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.strct-li--wrap .strct-li__meta,.strct-list--wrap .strct-li__meta{align-self:flex-start;min-height:calc(var(--text-md) * 1.45)}.strct-li__leading:empty,.strct-li__meta:empty,.strct-li__desc:empty,.strct-li__trailing:empty{display:none}.strct-li__leading{display:inline-flex;align-items:center;flex:none}.strct-li__text{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.strct-li__title{font-size:var(--text-md);color:var(--t1);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__desc{font-size:var(--text-sm);color:var(--t3);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__meta{display:inline-flex;align-items:center;flex:none;font-size:var(--text-sm);color:var(--t3);white-space:nowrap}.strct-li__trailing{display:inline-flex;align-items:center;gap:var(--space-2);flex:none}@container (max-width: 360px){.strct-li__main{flex-wrap:wrap}.strct-li__meta{flex-basis:100%;padding-inline-start:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1936
+ `, isInline: true, styles: [".strct-li{display:flex;align-items:center;gap:var(--space-2);padding-inline:var(--space-3);position:relative}.strct-list--flush .strct-li{padding-inline:0}.strct-list--dividers .strct-li+.strct-li{border-block-start:1px solid var(--b1)}.strct-li__main{display:flex;align-items:center;gap:var(--space-2);flex:1;min-width:0;min-height:44px;padding-block:6px;text-align:start;border-radius:var(--radius-sm)}.strct-list--dense .strct-li__main{min-height:32px;padding-block:2px}.strct-li--interactive .strct-li__main{cursor:pointer}.strct-li--disabled .strct-li__main{cursor:not-allowed;opacity:.6}.strct-li--disabled.strct-li--interactive:hover{background:none}.strct-li--interactive:hover{background:var(--bg-2)}.strct-li--selected{background:var(--acc-s)}.strct-li__main:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-li--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:2px;background:var(--t3)}.strct-li[data-status=accent]:before{background:var(--acc)}.strct-li[data-status=success]:before{background:var(--success)}.strct-li[data-status=warning]:before{background:var(--warning)}.strct-li[data-status=critical]:before{background:var(--critical)}.strct-li--wrap .strct-li__main,.strct-list--wrap .strct-li__main{align-items:flex-start}.strct-li--wrap .strct-li__leading,.strct-list--wrap .strct-li__leading{min-height:calc(var(--text-md) * 1.45)}.strct-li--wrap .strct-li__title,.strct-li--wrap .strct-li__desc,.strct-list--wrap .strct-li__title,.strct-list--wrap .strct-li__desc{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.strct-li--wrap .strct-li__meta,.strct-list--wrap .strct-li__meta{align-self:flex-start;min-height:calc(var(--text-md) * 1.45)}.strct-li__leading:empty,.strct-li__meta:empty,.strct-li__desc:empty,.strct-li__trailing:empty{display:none}.strct-li__leading{display:inline-flex;align-items:center;flex:none}.strct-li__text{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.strct-li__title{font-size:var(--text-md);color:var(--t1);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__desc{font-size:var(--text-sm);color:var(--t3);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__meta{display:inline-flex;align-items:center;flex:none;font-size:var(--text-sm);color:var(--t3);white-space:nowrap}.strct-li__trailing{display:inline-flex;align-items:center;gap:var(--space-2);flex:none}@container (max-width: 360px){.strct-li__main{flex-wrap:wrap}.strct-li__meta{flex-basis:100%;padding-inline-start:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1924
1937
  }
1925
1938
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctListItem, decorators: [{
1926
1939
  type: Component,
@@ -1930,6 +1943,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
1930
1943
  [attr.role]="interactive() ? 'button' : null"
1931
1944
  [attr.tabindex]="interactive() ? 0 : null"
1932
1945
  [attr.aria-current]="selected() ? 'true' : null"
1946
+ [attr.aria-disabled]="disabled() ? 'true' : null"
1947
+ [attr.title]="disabledReason() || null"
1948
+ [attr.aria-description]="disabled() ? disabledReason() || null : null"
1933
1949
  (click)="onActivate()"
1934
1950
  (keydown.enter)="onActivate()"
1935
1951
  (keydown.space)="$event.preventDefault(); onActivate()"
@@ -1947,11 +1963,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
1947
1963
  role: 'listitem',
1948
1964
  '[class.strct-li--interactive]': 'interactive()',
1949
1965
  '[class.strct-li--wrap]': 'wrap()',
1966
+ '[class.strct-li--disabled]': 'disabled()',
1950
1967
  '[class.strct-li--selected]': 'selected()',
1951
1968
  '[class.strct-li--status]': 'status()',
1952
1969
  '[attr.data-status]': 'status()',
1953
- }, styles: [".strct-li{display:flex;align-items:center;gap:var(--space-2);padding-inline:var(--space-3);position:relative}.strct-list--flush .strct-li{padding-inline:0}.strct-list--dividers .strct-li+.strct-li{border-block-start:1px solid var(--b1)}.strct-li__main{display:flex;align-items:center;gap:var(--space-2);flex:1;min-width:0;min-height:44px;padding-block:6px;text-align:start;border-radius:var(--radius-sm)}.strct-list--dense .strct-li__main{min-height:32px;padding-block:2px}.strct-li--interactive .strct-li__main{cursor:pointer}.strct-li--interactive:hover{background:var(--bg-2)}.strct-li--selected{background:var(--acc-s)}.strct-li__main:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-li--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:2px;background:var(--t3)}.strct-li[data-status=accent]:before{background:var(--acc)}.strct-li[data-status=success]:before{background:var(--success)}.strct-li[data-status=warning]:before{background:var(--warning)}.strct-li[data-status=critical]:before{background:var(--critical)}.strct-li--wrap .strct-li__main,.strct-list--wrap .strct-li__main{align-items:flex-start}.strct-li--wrap .strct-li__leading,.strct-list--wrap .strct-li__leading{min-height:calc(var(--text-md) * 1.45)}.strct-li--wrap .strct-li__title,.strct-li--wrap .strct-li__desc,.strct-list--wrap .strct-li__title,.strct-list--wrap .strct-li__desc{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.strct-li--wrap .strct-li__meta,.strct-list--wrap .strct-li__meta{align-self:flex-start;min-height:calc(var(--text-md) * 1.45)}.strct-li__leading:empty,.strct-li__meta:empty,.strct-li__desc:empty,.strct-li__trailing:empty{display:none}.strct-li__leading{display:inline-flex;align-items:center;flex:none}.strct-li__text{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.strct-li__title{font-size:var(--text-md);color:var(--t1);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__desc{font-size:var(--text-sm);color:var(--t3);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__meta{display:inline-flex;align-items:center;flex:none;font-size:var(--text-sm);color:var(--t3);white-space:nowrap}.strct-li__trailing{display:inline-flex;align-items:center;gap:var(--space-2);flex:none}@container (max-width: 360px){.strct-li__main{flex-wrap:wrap}.strct-li__meta{flex-basis:100%;padding-inline-start:0}}\n"] }]
1954
- }], propDecorators: { interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], wrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrap", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
1970
+ }, styles: [".strct-li{display:flex;align-items:center;gap:var(--space-2);padding-inline:var(--space-3);position:relative}.strct-list--flush .strct-li{padding-inline:0}.strct-list--dividers .strct-li+.strct-li{border-block-start:1px solid var(--b1)}.strct-li__main{display:flex;align-items:center;gap:var(--space-2);flex:1;min-width:0;min-height:44px;padding-block:6px;text-align:start;border-radius:var(--radius-sm)}.strct-list--dense .strct-li__main{min-height:32px;padding-block:2px}.strct-li--interactive .strct-li__main{cursor:pointer}.strct-li--disabled .strct-li__main{cursor:not-allowed;opacity:.6}.strct-li--disabled.strct-li--interactive:hover{background:none}.strct-li--interactive:hover{background:var(--bg-2)}.strct-li--selected{background:var(--acc-s)}.strct-li__main:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-li--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:2px;background:var(--t3)}.strct-li[data-status=accent]:before{background:var(--acc)}.strct-li[data-status=success]:before{background:var(--success)}.strct-li[data-status=warning]:before{background:var(--warning)}.strct-li[data-status=critical]:before{background:var(--critical)}.strct-li--wrap .strct-li__main,.strct-list--wrap .strct-li__main{align-items:flex-start}.strct-li--wrap .strct-li__leading,.strct-list--wrap .strct-li__leading{min-height:calc(var(--text-md) * 1.45)}.strct-li--wrap .strct-li__title,.strct-li--wrap .strct-li__desc,.strct-list--wrap .strct-li__title,.strct-list--wrap .strct-li__desc{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.strct-li--wrap .strct-li__meta,.strct-list--wrap .strct-li__meta{align-self:flex-start;min-height:calc(var(--text-md) * 1.45)}.strct-li__leading:empty,.strct-li__meta:empty,.strct-li__desc:empty,.strct-li__trailing:empty{display:none}.strct-li__leading{display:inline-flex;align-items:center;flex:none}.strct-li__text{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}.strct-li__title{font-size:var(--text-md);color:var(--t1);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__desc{font-size:var(--text-sm);color:var(--t3);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.strct-li__meta{display:inline-flex;align-items:center;flex:none;font-size:var(--text-sm);color:var(--t3);white-space:nowrap}.strct-li__trailing{display:inline-flex;align-items:center;gap:var(--space-2);flex:none}@container (max-width: 360px){.strct-li__main{flex-wrap:wrap}.strct-li__meta{flex-basis:100%;padding-inline-start:0}}\n"] }]
1971
+ }], propDecorators: { interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], wrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrap", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], disabledReason: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledReason", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
1955
1972
  /**
1956
1973
  * A short list of things with a status — alarms, findings, clusters in a
1957
1974
  * summary. A table needs a header row and columns, a timeline implies time
@@ -2379,6 +2396,16 @@ class StrctTag {
2379
2396
  */
2380
2397
  activateLabel = input('', /* @ts-ignore */
2381
2398
  ...(ngDevMode ? [{ debugName: "activateLabel" }] : /* istanbul ignore next */ []));
2399
+ /**
2400
+ * The tag's body is a link to this address — an object chip in a reply opens
2401
+ * the object's page. A link is what a middle click, a Ctrl/Cmd-click and
2402
+ * "copy link address" need; `interactive` cannot give them.
2403
+ */
2404
+ href = input(null, /* @ts-ignore */
2405
+ ...(ngDevMode ? [{ debugName: "href" }] : /* istanbul ignore next */ []));
2406
+ /** `_blank` adds the `rel` a new tab needs. */
2407
+ target = input('', /* @ts-ignore */
2408
+ ...(ngDevMode ? [{ debugName: "target" }] : /* istanbul ignore next */ []));
2382
2409
  /**
2383
2410
  * The body becomes a control: pointer, hover, focus ring, and `activated` on
2384
2411
  * click / Enter / Space. The × stays a separate tab stop, so "open it" and
@@ -2399,21 +2426,38 @@ class StrctTag {
2399
2426
  this.activated.emit();
2400
2427
  }
2401
2428
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctTag, deps: [], target: i0.ɵɵFactoryTarget.Component });
2402
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctTag, isStandalone: true, selector: "strct-tag", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, activateLabel: { classPropertyName: "activateLabel", publicName: "activateLabel", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, mono: { classPropertyName: "mono", publicName: "mono", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed", activated: "activated" }, host: { properties: { "class.strct-tag--interactive": "interactive() && !disabled()", "class.strct-tag--pill": "shape() === 'pill'", "class.strct-tag--mono": "mono()", "class.strct-tag--accent": "status() === 'accent'", "class.strct-tag--success": "status() === 'success'", "class.strct-tag--warning": "status() === 'warning'", "class.strct-tag--critical": "status() === 'critical'" }, classAttribute: "strct-tag" }, ngImport: i0, template: `
2403
- <span
2404
- class="strct-tag__text"
2405
- [attr.role]="interactive() ? 'button' : null"
2406
- [attr.tabindex]="interactive() && !disabled() ? 0 : null"
2407
- [attr.aria-label]="interactive() && activateLabel() ? activateLabel() : null"
2408
- (click)="onActivate()"
2409
- (keydown.enter)="onActivate()"
2410
- (keydown.space)="$event.preventDefault(); onActivate()"
2411
- >
2412
- <!-- Declared before the catch-all so the selector wins; it renders first
2429
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctTag, isStandalone: true, selector: "strct-tag", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, activateLabel: { classPropertyName: "activateLabel", publicName: "activateLabel", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, mono: { classPropertyName: "mono", publicName: "mono", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed", activated: "activated" }, host: { properties: { "class.strct-tag--interactive": "interactive() && !disabled()", "class.strct-tag--pill": "shape() === 'pill'", "class.strct-tag--mono": "mono()", "class.strct-tag--accent": "status() === 'accent'", "class.strct-tag--success": "status() === 'success'", "class.strct-tag--warning": "status() === 'warning'", "class.strct-tag--critical": "status() === 'critical'" }, classAttribute: "strct-tag" }, ngImport: i0, template: `
2430
+ <!-- With an href the body is a real link: Ctrl/Cmd-click opens a tab, the
2431
+ address shows on hover and it can be copied as a link — none of which
2432
+ a role="button" can do. The same text, the same focus ring. -->
2433
+ @if (href() && !disabled()) {
2434
+ <a
2435
+ class="strct-tag__text strct-tag__text--link"
2436
+ [attr.href]="href()"
2437
+ [attr.target]="target() || null"
2438
+ [attr.rel]="target() === '_blank' ? 'noopener noreferrer' : null"
2439
+ [attr.aria-label]="activateLabel() || null"
2440
+ (click)="onActivate()"
2441
+ >
2442
+ <ng-content select="[strctTagLeading]" />
2443
+ <ng-content />
2444
+ </a>
2445
+ } @else {
2446
+ <span
2447
+ class="strct-tag__text"
2448
+ [attr.role]="interactive() ? 'button' : null"
2449
+ [attr.tabindex]="interactive() && !disabled() ? 0 : null"
2450
+ [attr.aria-label]="interactive() && activateLabel() ? activateLabel() : null"
2451
+ (click)="onActivate()"
2452
+ (keydown.enter)="onActivate()"
2453
+ (keydown.space)="$event.preventDefault(); onActivate()"
2454
+ >
2455
+ <!-- Declared before the catch-all so the selector wins; it renders first
2413
2456
  either way. -->
2414
- <ng-content select="[strctTagLeading]" />
2415
- <ng-content />
2416
- </span>
2457
+ <ng-content select="[strctTagLeading]" />
2458
+ <ng-content />
2459
+ </span>
2460
+ }
2417
2461
  @if (removable() && !disabled()) {
2418
2462
  <button
2419
2463
  type="button"
@@ -2424,25 +2468,42 @@ class StrctTag {
2424
2468
  <strct-icon name="close" [size]="11" [strokeWidth]="1.6" />
2425
2469
  </button>
2426
2470
  }
2427
- `, isInline: true, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding-block:3px;padding-inline:9px 4px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-inline-end:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--success);border-color:var(--success);background:transparent}.strct-tag--warning{color:var(--warning);border-color:var(--warning);background:transparent}.strct-tag--critical{color:var(--critical);border-color:var(--critical);background:transparent}.strct-tag__text{display:inline-flex;align-items:center;gap:5px}.strct-tag--interactive .strct-tag__text{cursor:pointer;border-radius:3px}.strct-tag--interactive:hover{border-color:var(--b3);background:var(--bg-2)}.strct-tag--interactive.strct-tag--accent:hover{border-color:var(--acc)}.strct-tag__text:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-tag--pill{border-radius:var(--radius-full, 999px);padding-inline:10px 5px}.strct-tag--pill:not(:has(.strct-tag__remove)){padding-inline-end:10px}.strct-tag--pill .strct-tag__remove{border-radius:999px}.strct-tag--mono{font-family:var(--mono)}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover,.strct-tag__remove:focus-visible{opacity:1;background:var(--dn)}\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 });
2471
+ `, isInline: true, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding-block:3px;padding-inline:9px 4px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-inline-end:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--success);border-color:var(--success);background:transparent}.strct-tag--warning{color:var(--warning);border-color:var(--warning);background:transparent}.strct-tag--critical{color:var(--critical);border-color:var(--critical);background:transparent}.strct-tag__text{display:inline-flex;align-items:center;gap:5px}.strct-tag__text--link{color:inherit;text-decoration:none;cursor:pointer}.strct-tag__text--link:hover{text-decoration:underline}.strct-tag--interactive .strct-tag__text{cursor:pointer;border-radius:3px}.strct-tag--interactive:hover{border-color:var(--b3);background:var(--bg-2)}.strct-tag--interactive.strct-tag--accent:hover{border-color:var(--acc)}.strct-tag__text:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-tag--pill{border-radius:var(--radius-full, 999px);padding-inline:10px 5px}.strct-tag--pill:not(:has(.strct-tag__remove)){padding-inline-end:10px}.strct-tag--pill .strct-tag__remove{border-radius:999px}.strct-tag--mono{font-family:var(--mono)}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover,.strct-tag__remove:focus-visible{opacity:1;background:var(--dn)}\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 });
2428
2472
  }
2429
2473
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctTag, decorators: [{
2430
2474
  type: Component,
2431
2475
  args: [{ selector: 'strct-tag', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [StrctIcon], template: `
2432
- <span
2433
- class="strct-tag__text"
2434
- [attr.role]="interactive() ? 'button' : null"
2435
- [attr.tabindex]="interactive() && !disabled() ? 0 : null"
2436
- [attr.aria-label]="interactive() && activateLabel() ? activateLabel() : null"
2437
- (click)="onActivate()"
2438
- (keydown.enter)="onActivate()"
2439
- (keydown.space)="$event.preventDefault(); onActivate()"
2440
- >
2441
- <!-- Declared before the catch-all so the selector wins; it renders first
2476
+ <!-- With an href the body is a real link: Ctrl/Cmd-click opens a tab, the
2477
+ address shows on hover and it can be copied as a link — none of which
2478
+ a role="button" can do. The same text, the same focus ring. -->
2479
+ @if (href() && !disabled()) {
2480
+ <a
2481
+ class="strct-tag__text strct-tag__text--link"
2482
+ [attr.href]="href()"
2483
+ [attr.target]="target() || null"
2484
+ [attr.rel]="target() === '_blank' ? 'noopener noreferrer' : null"
2485
+ [attr.aria-label]="activateLabel() || null"
2486
+ (click)="onActivate()"
2487
+ >
2488
+ <ng-content select="[strctTagLeading]" />
2489
+ <ng-content />
2490
+ </a>
2491
+ } @else {
2492
+ <span
2493
+ class="strct-tag__text"
2494
+ [attr.role]="interactive() ? 'button' : null"
2495
+ [attr.tabindex]="interactive() && !disabled() ? 0 : null"
2496
+ [attr.aria-label]="interactive() && activateLabel() ? activateLabel() : null"
2497
+ (click)="onActivate()"
2498
+ (keydown.enter)="onActivate()"
2499
+ (keydown.space)="$event.preventDefault(); onActivate()"
2500
+ >
2501
+ <!-- Declared before the catch-all so the selector wins; it renders first
2442
2502
  either way. -->
2443
- <ng-content select="[strctTagLeading]" />
2444
- <ng-content />
2445
- </span>
2503
+ <ng-content select="[strctTagLeading]" />
2504
+ <ng-content />
2505
+ </span>
2506
+ }
2446
2507
  @if (removable() && !disabled()) {
2447
2508
  <button
2448
2509
  type="button"
@@ -2462,8 +2523,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
2462
2523
  '[class.strct-tag--success]': "status() === 'success'",
2463
2524
  '[class.strct-tag--warning]': "status() === 'warning'",
2464
2525
  '[class.strct-tag--critical]': "status() === 'critical'",
2465
- }, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding-block:3px;padding-inline:9px 4px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-inline-end:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--success);border-color:var(--success);background:transparent}.strct-tag--warning{color:var(--warning);border-color:var(--warning);background:transparent}.strct-tag--critical{color:var(--critical);border-color:var(--critical);background:transparent}.strct-tag__text{display:inline-flex;align-items:center;gap:5px}.strct-tag--interactive .strct-tag__text{cursor:pointer;border-radius:3px}.strct-tag--interactive:hover{border-color:var(--b3);background:var(--bg-2)}.strct-tag--interactive.strct-tag--accent:hover{border-color:var(--acc)}.strct-tag__text:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-tag--pill{border-radius:var(--radius-full, 999px);padding-inline:10px 5px}.strct-tag--pill:not(:has(.strct-tag__remove)){padding-inline-end:10px}.strct-tag--pill .strct-tag__remove{border-radius:999px}.strct-tag--mono{font-family:var(--mono)}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover,.strct-tag__remove:focus-visible{opacity:1;background:var(--dn)}\n"] }]
2466
- }], ctorParameters: () => [], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], activateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "activateLabel", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], mono: [{ type: i0.Input, args: [{ isSignal: true, alias: "mono", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
2526
+ }, styles: [".strct-tag{display:inline-flex;align-items:center;gap:5px;padding-block:3px;padding-inline:9px 4px;border-radius:4px;font-size:12px;font-weight:500;color:var(--t1);background:var(--bg-3);border:1px solid var(--b2)}.strct-tag:not(:has(.strct-tag__remove)){padding-inline-end:9px}.strct-tag--accent{color:var(--acc);border-color:var(--acc30);background:var(--acc-s)}.strct-tag--success{color:var(--success);border-color:var(--success);background:transparent}.strct-tag--warning{color:var(--warning);border-color:var(--warning);background:transparent}.strct-tag--critical{color:var(--critical);border-color:var(--critical);background:transparent}.strct-tag__text{display:inline-flex;align-items:center;gap:5px}.strct-tag__text--link{color:inherit;text-decoration:none;cursor:pointer}.strct-tag__text--link:hover{text-decoration:underline}.strct-tag--interactive .strct-tag__text{cursor:pointer;border-radius:3px}.strct-tag--interactive:hover{border-color:var(--b3);background:var(--bg-2)}.strct-tag--interactive.strct-tag--accent:hover{border-color:var(--acc)}.strct-tag__text:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-tag--pill{border-radius:var(--radius-full, 999px);padding-inline:10px 5px}.strct-tag--pill:not(:has(.strct-tag__remove)){padding-inline-end:10px}.strct-tag--pill .strct-tag__remove{border-radius:999px}.strct-tag--mono{font-family:var(--mono)}.strct-tag__remove{display:inline-flex;padding:2px;border:0;border-radius:3px;background:transparent;color:currentColor;opacity:.65;cursor:pointer}.strct-tag__remove:hover,.strct-tag__remove:focus-visible{opacity:1;background:var(--dn)}\n"] }]
2527
+ }], ctorParameters: () => [], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], activateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "activateLabel", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], mono: [{ type: i0.Input, args: [{ isSignal: true, alias: "mono", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
2467
2528
 
2468
2529
  /**
2469
2530
  * Circular avatar: an image when `src` is set, otherwise initials from `name`.
@@ -4996,6 +5057,15 @@ class StrctModal {
4996
5057
  * `dismissible` for lightweight, transient dialogs where quick dismissal is fine.
4997
5058
  */
4998
5059
  dismissible = input(false, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5060
+ /**
5061
+ * Escape closes the dialog. Defaults to `dismissible`; set it on its own for
5062
+ * a window that should close on Escape — nothing is lost — but not on a
5063
+ * stray click outside it. An Escape a focused control already handled
5064
+ * (`defaultPrevented`) is left alone.
5065
+ */
5066
+ closeOnEscape = input(null, { ...(ngDevMode ? { debugName: "closeOnEscape" } : /* istanbul ignore next */ {}), transform: (v) => (v === null || v === undefined ? null : booleanAttribute(v)) });
5067
+ /** A click on the backdrop closes it. Defaults to `dismissible`. */
5068
+ closeOnBackdrop = input(null, { ...(ngDevMode ? { debugName: "closeOnBackdrop" } : /* istanbul ignore next */ {}), transform: (v) => (v === null || v === undefined ? null : booleanAttribute(v)) });
4999
5069
  /** Allow repositioning the dialog by dragging its header (mouse + touch). */
5000
5070
  draggable = input(false, { ...(ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5001
5071
  /** Extra class(es) added to the dialog panel — style it from app-global CSS. */
@@ -5073,12 +5143,17 @@ class StrctModal {
5073
5143
  // that bubbled up from a child (e.g. a space typed in an input/textarea).
5074
5144
  if (event && event.target !== event.currentTarget)
5075
5145
  return;
5076
- if (this.dismissible())
5146
+ if (this.closeOnBackdrop() ?? this.dismissible())
5077
5147
  this.close();
5078
5148
  }
5079
- onEscape() {
5149
+ onEscape(event) {
5150
+ // A control that used Escape first keeps it: an IME composition, a
5151
+ // searchbox that clears. Both mark the event handled.
5152
+ if (event?.defaultPrevented)
5153
+ return;
5080
5154
  // With several modals open, only the topmost one reacts to Escape.
5081
- if (this.open() && this.dismissible() && isTopmostModal(this))
5155
+ const allowed = this.closeOnEscape() ?? this.dismissible();
5156
+ if (this.open() && allowed && isTopmostModal(this))
5082
5157
  this.close();
5083
5158
  }
5084
5159
  /** Wrap Tab focus within the dialog. */
@@ -5167,7 +5242,7 @@ class StrctModal {
5167
5242
  (items[0] ?? this.dialog())?.focus();
5168
5243
  }
5169
5244
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
5170
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctModal, isStandalone: true, selector: "strct-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, chromeless: { classPropertyName: "chromeless", publicName: "chromeless", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "lazyContent", first: true, predicate: StrctModalContent, descendants: true, isSignal: true }], ngImport: i0, template: `
5245
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctModal, isStandalone: true, selector: "strct-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, chromeless: { classPropertyName: "chromeless", publicName: "chromeless", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape($event)" } }, queries: [{ propertyName: "lazyContent", first: true, predicate: StrctModalContent, descendants: true, isSignal: true }], ngImport: i0, template: `
5171
5246
  @if (open()) {
5172
5247
  <!-- Backdrop: pointer-only dismiss target. No role/tabindex — keyboard users
5173
5248
  dismiss via Escape, and the focus trap makes the backdrop unreachable
@@ -5288,9 +5363,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
5288
5363
  </div>
5289
5364
  }
5290
5365
  `, host: {
5291
- '(document:keydown.escape)': 'onEscape()',
5366
+ '(document:keydown.escape)': 'onEscape($event)',
5292
5367
  }, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:var(--backdrop);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}@media(max-width:768px){.strct-modal__overlay{padding:var(--space-3)}}.strct-modal__dialog{width:100%;max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-xl);box-shadow:var(--shadow-elevated);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:min(480px,calc(100vw - 32px))}.strct-modal__dialog--md{max-width:min(640px,calc(100vw - 32px))}.strct-modal__dialog--lg{max-width:min(860px,calc(100vw - 32px))}.strct-modal__dialog--xl{max-width:min(1080px,calc(100vw - 32px))}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1)}.strct-modal__head--drag{cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-modal__overlay--glass{background:#00000061;-webkit-backdrop-filter:blur(10px) saturate(1.25);backdrop-filter:blur(10px) saturate(1.25)}.strct-modal__dialog--glass{background:color-mix(in srgb,var(--bg-1) 72%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.4);backdrop-filter:blur(24px) saturate(1.4)}.strct-modal__dialog--glass .strct-modal__foot{background:color-mix(in srgb,var(--bg-2) 55%,transparent)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:var(--space-4);overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__dialog--chromeless{width:calc(232px + var(--strct-wiz-content-min, 864px) + 2px);max-width:calc(100vw - 32px)}.strct-modal__dialog--chromeless:has(.strct-wiz__layout--aside){width:calc(232px + var(--strct-wiz-content-min, 864px) + 280px + 2px)}.strct-modal__dialog--chromeless .strct-modal__body{padding:0;overflow:hidden;display:flex;flex-direction:column;flex:1;min-height:0}.strct-modal__dialog--chromeless .strct-modal__body>*{flex:1;min-height:0}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}@media(prefers-reduced-motion:reduce){.strct-modal__overlay,.strct-modal__dialog{animation:none}}\n"] }]
5293
- }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], chromeless: [{ type: i0.Input, args: [{ isSignal: true, alias: "chromeless", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], lazyContent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctModalContent), { isSignal: true }] }] } });
5368
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], chromeless: [{ type: i0.Input, args: [{ isSignal: true, alias: "chromeless", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], lazyContent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctModalContent), { isSignal: true }] }] } });
5294
5369
 
5295
5370
  /** Marks the drawer's footer action area: `<ng-container strctDrawerFooter>…`. */
5296
5371
  class StrctDrawerFooter {
@@ -9225,9 +9300,19 @@ class StrctSegmented {
9225
9300
  <strct-icon [name]="opt.icon" [size]="16" />
9226
9301
  }
9227
9302
  <span>{{ opt.label }}</span>
9303
+ @if (opt.count !== undefined) {
9304
+ <span
9305
+ class="strct-seg__count strct-seg__count--{{ opt.countStatus ?? 'none' }}"
9306
+ aria-hidden="true"
9307
+ >{{ opt.count }}</span
9308
+ >
9309
+ <span class="strct-sr-only">{{
9310
+ opt.countLabel ? ', ' + opt.countLabel(opt.count) : ', ' + opt.count
9311
+ }}</span>
9312
+ }
9228
9313
  </button>
9229
9314
  }
9230
- `, isInline: true, styles: [".strct-seg{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b2);border-radius:var(--radius-md);max-width:100%}.strct-seg--block{display:flex;width:100%}.strct-seg__opt{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);flex:1 1 auto;padding:6px 14px;border:0;border-radius:calc(var(--radius-md) - 2px);background:transparent;color:var(--t2);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;transition:background .14s ease,color .14s ease}.strct-seg--sm .strct-seg__opt{padding:4px 10px;font-size:12px}.strct-seg__opt:hover:not(:disabled):not(.strct-seg__opt--selected){color:var(--t1)}.strct-seg__opt--selected{background:var(--bg-a);color:var(--t1);font-weight:600;box-shadow:var(--sh),0 0 0 1px var(--b1)}.strct-seg__opt:focus-visible{outline:none;box-shadow:0 0 0 2px var(--acc50)}.strct-seg__opt:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.strct-seg--disabled{opacity:var(--disabled-opacity)}.strct-seg--disabled .strct-seg__opt{cursor:not-allowed}\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 });
9315
+ `, isInline: true, styles: [".strct-seg__count{margin-inline-start:5px;font-variant-numeric:tabular-nums;color:var(--t3)}.strct-seg__count--accent{color:var(--acc)}.strct-seg__count--success{color:var(--success)}.strct-seg__count--warning{color:var(--warning)}.strct-seg__count--critical{color:var(--critical)}.strct-seg{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b2);border-radius:var(--radius-md);max-width:100%}.strct-seg--block{display:flex;width:100%}.strct-seg__opt{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);flex:1 1 auto;padding:6px 14px;border:0;border-radius:calc(var(--radius-md) - 2px);background:transparent;color:var(--t2);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;transition:background .14s ease,color .14s ease}.strct-seg--sm .strct-seg__opt{padding:4px 10px;font-size:12px}.strct-seg__opt:hover:not(:disabled):not(.strct-seg__opt--selected){color:var(--t1)}.strct-seg__opt--selected{background:var(--bg-a);color:var(--t1);font-weight:600;box-shadow:var(--sh),0 0 0 1px var(--b1)}.strct-seg__opt:focus-visible{outline:none;box-shadow:0 0 0 2px var(--acc50)}.strct-seg__opt:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.strct-seg--disabled{opacity:var(--disabled-opacity)}.strct-seg--disabled .strct-seg__opt{cursor:not-allowed}\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 });
9231
9316
  }
9232
9317
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctSegmented, decorators: [{
9233
9318
  type: Component,
@@ -9251,6 +9336,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
9251
9336
  <strct-icon [name]="opt.icon" [size]="16" />
9252
9337
  }
9253
9338
  <span>{{ opt.label }}</span>
9339
+ @if (opt.count !== undefined) {
9340
+ <span
9341
+ class="strct-seg__count strct-seg__count--{{ opt.countStatus ?? 'none' }}"
9342
+ aria-hidden="true"
9343
+ >{{ opt.count }}</span
9344
+ >
9345
+ <span class="strct-sr-only">{{
9346
+ opt.countLabel ? ', ' + opt.countLabel(opt.count) : ', ' + opt.count
9347
+ }}</span>
9348
+ }
9254
9349
  </button>
9255
9350
  }
9256
9351
  `, host: {
@@ -9260,7 +9355,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
9260
9355
  '[class.strct-seg--block]': 'block()',
9261
9356
  '[class.strct-seg--disabled]': 'isDisabled()',
9262
9357
  '(keydown)': 'onKeydown($event)',
9263
- }, styles: [".strct-seg{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b2);border-radius:var(--radius-md);max-width:100%}.strct-seg--block{display:flex;width:100%}.strct-seg__opt{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);flex:1 1 auto;padding:6px 14px;border:0;border-radius:calc(var(--radius-md) - 2px);background:transparent;color:var(--t2);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;transition:background .14s ease,color .14s ease}.strct-seg--sm .strct-seg__opt{padding:4px 10px;font-size:12px}.strct-seg__opt:hover:not(:disabled):not(.strct-seg__opt--selected){color:var(--t1)}.strct-seg__opt--selected{background:var(--bg-a);color:var(--t1);font-weight:600;box-shadow:var(--sh),0 0 0 1px var(--b1)}.strct-seg__opt:focus-visible{outline:none;box-shadow:0 0 0 2px var(--acc50)}.strct-seg__opt:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.strct-seg--disabled{opacity:var(--disabled-opacity)}.strct-seg--disabled .strct-seg__opt{cursor:not-allowed}\n"] }]
9358
+ }, styles: [".strct-seg__count{margin-inline-start:5px;font-variant-numeric:tabular-nums;color:var(--t3)}.strct-seg__count--accent{color:var(--acc)}.strct-seg__count--success{color:var(--success)}.strct-seg__count--warning{color:var(--warning)}.strct-seg__count--critical{color:var(--critical)}.strct-seg{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b2);border-radius:var(--radius-md);max-width:100%}.strct-seg--block{display:flex;width:100%}.strct-seg__opt{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);flex:1 1 auto;padding:6px 14px;border:0;border-radius:calc(var(--radius-md) - 2px);background:transparent;color:var(--t2);font-family:var(--font);font-size:13px;font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;transition:background .14s ease,color .14s ease}.strct-seg--sm .strct-seg__opt{padding:4px 10px;font-size:12px}.strct-seg__opt:hover:not(:disabled):not(.strct-seg__opt--selected){color:var(--t1)}.strct-seg__opt--selected{background:var(--bg-a);color:var(--t1);font-weight:600;box-shadow:var(--sh),0 0 0 1px var(--b1)}.strct-seg__opt:focus-visible{outline:none;box-shadow:0 0 0 2px var(--acc50)}.strct-seg__opt:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}.strct-seg--disabled{opacity:var(--disabled-opacity)}.strct-seg--disabled .strct-seg__opt{cursor:not-allowed}\n"] }]
9264
9359
  }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], segs: [{ type: i0.ViewChildren, args: ['seg', { ...{ read: ElementRef }, isSignal: true }] }] } });
9265
9360
 
9266
9361
  /**
@@ -9981,7 +10076,7 @@ class StrctChips {
9981
10076
  (blur)="commitDraft(); onTouched()"
9982
10077
  />
9983
10078
  </div>
9984
- `, isInline: true, styles: [".strct-chips{display:flex;flex-wrap:wrap;align-items:center;gap:6px;width:100%;min-height:38px;padding:5px 8px;background:var(--bg-2);border:1px solid var(--b2);border-radius:6px;cursor:text;transition:border-color .14s ease,box-shadow .14s ease}.strct-chips:focus-within{border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-chips__input{flex:1;min-width:80px;border:0;outline:none;background:transparent;font-family:var(--font);font-size:13px;color:var(--t1);padding:3px 2px}.strct-chips__input::placeholder{color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctTag, selector: "strct-tag", inputs: ["status", "removable", "disabled", "removeLabel", "activateLabel", "interactive", "shape", "mono"], outputs: ["removed", "activated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10079
+ `, isInline: true, styles: [".strct-chips{display:flex;flex-wrap:wrap;align-items:center;gap:6px;width:100%;min-height:38px;padding:5px 8px;background:var(--bg-2);border:1px solid var(--b2);border-radius:6px;cursor:text;transition:border-color .14s ease,box-shadow .14s ease}.strct-chips:focus-within{border-color:var(--acc50);box-shadow:0 0 0 3px var(--acc18);background:var(--bg-1)}.strct-chips__input{flex:1;min-width:80px;border:0;outline:none;background:transparent;font-family:var(--font);font-size:13px;color:var(--t1);padding:3px 2px}.strct-chips__input::placeholder{color:var(--t3)}\n"], dependencies: [{ kind: "component", type: StrctTag, selector: "strct-tag", inputs: ["status", "removable", "disabled", "removeLabel", "activateLabel", "href", "target", "interactive", "shape", "mono"], outputs: ["removed", "activated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
9985
10080
  }
9986
10081
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChips, decorators: [{
9987
10082
  type: Component,
@@ -12777,13 +12872,21 @@ class StrctStatusDot {
12777
12872
  * not jitter. Under `prefers-reduced-motion` the halo is a static ring.
12778
12873
  */
12779
12874
  pulse = input(false, { ...(ngDevMode ? { debugName: "pulse" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
12875
+ /**
12876
+ * `solid` is an outcome. `ring` — a 2px outline with a transparent centre —
12877
+ * is a state that is **not** one: "Inconclusive", "Not applicable",
12878
+ * "Unknown". They must not read as Warning or Passed with only the colour
12879
+ * to tell them apart, so the shape carries the difference (WCAG 1.4.1).
12880
+ */
12881
+ variant = input('solid', /* @ts-ignore */
12882
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
12780
12883
  text = computed(() => this.label() || DEFAULT_LABEL[this.status()], /* @ts-ignore */
12781
12884
  ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
12782
12885
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctStatusDot, deps: [], target: i0.ɵɵFactoryTarget.Component });
12783
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctStatusDot, isStandalone: true, selector: "strct-status-dot", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, pulse: { classPropertyName: "pulse", publicName: "pulse", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-dot--accent": "status() === 'accent'", "class.strct-dot--success": "status() === 'success'", "class.strct-dot--warning": "status() === 'warning'", "class.strct-dot--critical": "status() === 'critical'", "class.strct-dot--sm": "size() === 'sm'", "class.strct-dot--pulse": "pulse()" }, classAttribute: "strct-dot" }, ngImport: i0, template: `
12886
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctStatusDot, isStandalone: true, selector: "strct-status-dot", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, pulse: { classPropertyName: "pulse", publicName: "pulse", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.strct-dot--accent": "status() === 'accent'", "class.strct-dot--success": "status() === 'success'", "class.strct-dot--warning": "status() === 'warning'", "class.strct-dot--critical": "status() === 'critical'", "class.strct-dot--sm": "size() === 'sm'", "class.strct-dot--pulse": "pulse()", "class.strct-dot--ring": "variant() === 'ring'" }, classAttribute: "strct-dot" }, ngImport: i0, template: `
12784
12887
  <span class="strct-dot__dot" aria-hidden="true"></span>
12785
12888
  <span class="strct-dot__sr">{{ text() }}</span>
12786
- `, isInline: true, styles: [".strct-dot{display:inline-flex;align-items:center;flex:none;line-height:0}.strct-dot__dot{width:10px;height:10px;border-radius:50%;background:var(--t3)}.strct-dot--sm .strct-dot__dot{width:8px;height:8px}.strct-dot--accent .strct-dot__dot{background:var(--acc)}.strct-dot--success .strct-dot__dot{background:var(--success)}.strct-dot--warning .strct-dot__dot{background:var(--warning)}.strct-dot--critical .strct-dot__dot{background:var(--critical)}.strct-dot--pulse .strct-dot__dot{position:relative}.strct-dot--pulse .strct-dot__dot:after{content:\"\";position:absolute;inset:0;border-radius:50%;background:inherit;animation:strct-dot-pulse 1s ease-out infinite}@keyframes strct-dot-pulse{0%{box-shadow:0 0 0 0 currentColor;opacity:.55}to{box-shadow:0 0 0 5px transparent;opacity:0}}.strct-dot--pulse .strct-dot__dot{color:var(--t3)}.strct-dot--pulse.strct-dot--accent .strct-dot__dot{color:var(--acc)}.strct-dot--pulse.strct-dot--success .strct-dot__dot{color:var(--success)}.strct-dot--pulse.strct-dot--warning .strct-dot__dot{color:var(--warning)}.strct-dot--pulse.strct-dot--critical .strct-dot__dot{color:var(--critical)}@media(prefers-reduced-motion:reduce){.strct-dot--pulse .strct-dot__dot:after{animation:none;box-shadow:0 0 0 3px currentColor;opacity:.25}}.strct-dot__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
12889
+ `, isInline: true, styles: [".strct-dot{display:inline-flex;align-items:center;flex:none;line-height:0}.strct-dot__dot{width:10px;height:10px;border-radius:50%;background:var(--t3)}.strct-dot--sm .strct-dot__dot{width:8px;height:8px}.strct-dot--ring .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--t3)}.strct-dot--ring.strct-dot--accent .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--acc)}.strct-dot--ring.strct-dot--success .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--success)}.strct-dot--ring.strct-dot--warning .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--warning)}.strct-dot--ring.strct-dot--critical .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--critical)}.strct-dot--accent .strct-dot__dot{background:var(--acc)}.strct-dot--success .strct-dot__dot{background:var(--success)}.strct-dot--warning .strct-dot__dot{background:var(--warning)}.strct-dot--critical .strct-dot__dot{background:var(--critical)}.strct-dot--pulse .strct-dot__dot{position:relative}.strct-dot--pulse .strct-dot__dot:after{content:\"\";position:absolute;inset:0;border-radius:50%;background:inherit;animation:strct-dot-pulse 1s ease-out infinite}@keyframes strct-dot-pulse{0%{box-shadow:0 0 0 0 currentColor;opacity:.55}to{box-shadow:0 0 0 5px transparent;opacity:0}}.strct-dot--pulse .strct-dot__dot{color:var(--t3)}.strct-dot--pulse.strct-dot--accent .strct-dot__dot{color:var(--acc)}.strct-dot--pulse.strct-dot--success .strct-dot__dot{color:var(--success)}.strct-dot--pulse.strct-dot--warning .strct-dot__dot{color:var(--warning)}.strct-dot--pulse.strct-dot--critical .strct-dot__dot{color:var(--critical)}@media(prefers-reduced-motion:reduce){.strct-dot--pulse .strct-dot__dot:after{animation:none;box-shadow:0 0 0 3px currentColor;opacity:.25}}.strct-dot__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
12787
12890
  }
12788
12891
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctStatusDot, decorators: [{
12789
12892
  type: Component,
@@ -12798,8 +12901,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
12798
12901
  '[class.strct-dot--critical]': "status() === 'critical'",
12799
12902
  '[class.strct-dot--sm]': "size() === 'sm'",
12800
12903
  '[class.strct-dot--pulse]': 'pulse()',
12801
- }, styles: [".strct-dot{display:inline-flex;align-items:center;flex:none;line-height:0}.strct-dot__dot{width:10px;height:10px;border-radius:50%;background:var(--t3)}.strct-dot--sm .strct-dot__dot{width:8px;height:8px}.strct-dot--accent .strct-dot__dot{background:var(--acc)}.strct-dot--success .strct-dot__dot{background:var(--success)}.strct-dot--warning .strct-dot__dot{background:var(--warning)}.strct-dot--critical .strct-dot__dot{background:var(--critical)}.strct-dot--pulse .strct-dot__dot{position:relative}.strct-dot--pulse .strct-dot__dot:after{content:\"\";position:absolute;inset:0;border-radius:50%;background:inherit;animation:strct-dot-pulse 1s ease-out infinite}@keyframes strct-dot-pulse{0%{box-shadow:0 0 0 0 currentColor;opacity:.55}to{box-shadow:0 0 0 5px transparent;opacity:0}}.strct-dot--pulse .strct-dot__dot{color:var(--t3)}.strct-dot--pulse.strct-dot--accent .strct-dot__dot{color:var(--acc)}.strct-dot--pulse.strct-dot--success .strct-dot__dot{color:var(--success)}.strct-dot--pulse.strct-dot--warning .strct-dot__dot{color:var(--warning)}.strct-dot--pulse.strct-dot--critical .strct-dot__dot{color:var(--critical)}@media(prefers-reduced-motion:reduce){.strct-dot--pulse .strct-dot__dot:after{animation:none;box-shadow:0 0 0 3px currentColor;opacity:.25}}.strct-dot__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n"] }]
12802
- }], ctorParameters: () => [], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], pulse: [{ type: i0.Input, args: [{ isSignal: true, alias: "pulse", required: false }] }] } });
12904
+ '[class.strct-dot--ring]': "variant() === 'ring'",
12905
+ }, styles: [".strct-dot{display:inline-flex;align-items:center;flex:none;line-height:0}.strct-dot__dot{width:10px;height:10px;border-radius:50%;background:var(--t3)}.strct-dot--sm .strct-dot__dot{width:8px;height:8px}.strct-dot--ring .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--t3)}.strct-dot--ring.strct-dot--accent .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--acc)}.strct-dot--ring.strct-dot--success .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--success)}.strct-dot--ring.strct-dot--warning .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--warning)}.strct-dot--ring.strct-dot--critical .strct-dot__dot{background:transparent;box-shadow:inset 0 0 0 2px var(--critical)}.strct-dot--accent .strct-dot__dot{background:var(--acc)}.strct-dot--success .strct-dot__dot{background:var(--success)}.strct-dot--warning .strct-dot__dot{background:var(--warning)}.strct-dot--critical .strct-dot__dot{background:var(--critical)}.strct-dot--pulse .strct-dot__dot{position:relative}.strct-dot--pulse .strct-dot__dot:after{content:\"\";position:absolute;inset:0;border-radius:50%;background:inherit;animation:strct-dot-pulse 1s ease-out infinite}@keyframes strct-dot-pulse{0%{box-shadow:0 0 0 0 currentColor;opacity:.55}to{box-shadow:0 0 0 5px transparent;opacity:0}}.strct-dot--pulse .strct-dot__dot{color:var(--t3)}.strct-dot--pulse.strct-dot--accent .strct-dot__dot{color:var(--acc)}.strct-dot--pulse.strct-dot--success .strct-dot__dot{color:var(--success)}.strct-dot--pulse.strct-dot--warning .strct-dot__dot{color:var(--warning)}.strct-dot--pulse.strct-dot--critical .strct-dot__dot{color:var(--critical)}@media(prefers-reduced-motion:reduce){.strct-dot--pulse .strct-dot__dot:after{animation:none;box-shadow:0 0 0 3px currentColor;opacity:.25}}.strct-dot__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n"] }]
12906
+ }], ctorParameters: () => [], propDecorators: { status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], pulse: [{ type: i0.Input, args: [{ isSignal: true, alias: "pulse", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
12803
12907
 
12804
12908
  /**
12805
12909
  * Compact definition list: aligned `label : value` rows with an optional trailing
@@ -12915,7 +13019,7 @@ class StrctDesc {
12915
13019
  <span class="strct-desc__note">{{ note() }}</span>
12916
13020
  }
12917
13021
  </dd>
12918
- `, isInline: true, dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctStatusDot, selector: "strct-status-dot", inputs: ["status", "label", "size", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13022
+ `, isInline: true, dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctStatusDot, selector: "strct-status-dot", inputs: ["status", "label", "size", "pulse", "variant"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
12919
13023
  }
12920
13024
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDesc, decorators: [{
12921
13025
  type: Component,
@@ -13544,6 +13648,7 @@ const DG_LABELS = {
13544
13648
  openDetail: 'Open detail',
13545
13649
  toggleDetail: 'Toggle detail',
13546
13650
  closeDetail: 'Close detail',
13651
+ backToList: 'Back to the list',
13547
13652
  rowActions: 'Row actions',
13548
13653
  chooseColumns: 'Choose columns',
13549
13654
  refresh: 'Refresh data',
@@ -13559,6 +13664,49 @@ const DG_LABELS = {
13559
13664
  toggleChildren: 'Toggle children',
13560
13665
  quickFilter: 'Quick filter',
13561
13666
  };
13667
+ /**
13668
+ * A fully custom group header row:
13669
+ *
13670
+ * <ng-template strctGroupHeader let-group let-count="count">
13671
+ * <strct-badge [status]="group.status">{{ group.label }}</strct-badge> {{ count }}
13672
+ * </ng-template>
13673
+ */
13674
+ /** The pane header's own title, instead of the first column's value. */
13675
+ class StrctDetailPaneTitle {
13676
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDetailPaneTitle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13677
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctDetailPaneTitle, isStandalone: true, selector: "[strctDetailPaneTitle]", ngImport: i0 });
13678
+ }
13679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDetailPaneTitle, decorators: [{
13680
+ type: Directive,
13681
+ args: [{ selector: '[strctDetailPaneTitle]' }]
13682
+ }] });
13683
+ /** Status, category, nodes — what the row is, beside its title. */
13684
+ class StrctDetailPaneMeta {
13685
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDetailPaneMeta, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13686
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctDetailPaneMeta, isStandalone: true, selector: "[strctDetailPaneMeta]", ngImport: i0 });
13687
+ }
13688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDetailPaneMeta, decorators: [{
13689
+ type: Directive,
13690
+ args: [{ selector: '[strctDetailPaneMeta]' }]
13691
+ }] });
13692
+ /** Controls at the pane header's end; the close button stays the library's. */
13693
+ class StrctDetailPaneActions {
13694
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDetailPaneActions, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13695
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctDetailPaneActions, isStandalone: true, selector: "[strctDetailPaneActions]", ngImport: i0 });
13696
+ }
13697
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDetailPaneActions, decorators: [{
13698
+ type: Directive,
13699
+ args: [{ selector: '[strctDetailPaneActions]' }]
13700
+ }] });
13701
+ class StrctGroupHeaderDef {
13702
+ template = inject(TemplateRef);
13703
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctGroupHeaderDef, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13704
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctGroupHeaderDef, isStandalone: true, selector: "ng-template[strctGroupHeader]", ngImport: i0 });
13705
+ }
13706
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctGroupHeaderDef, decorators: [{
13707
+ type: Directive,
13708
+ args: [{ selector: 'ng-template[strctGroupHeader]' }]
13709
+ }] });
13562
13710
  let datagridCounter = 0;
13563
13711
  /** Utility-column widths used when sticky columns are active (px). */
13564
13712
  const UTIL_W = { detail: 36, expand: 36, sel: 40 };
@@ -13621,6 +13769,25 @@ class StrctDatagrid {
13621
13769
  /** Collapse the grid to a single column and open a side detail pane for the
13622
13770
  * clicked row (distinct from {@link expandable}). */
13623
13771
  detailPane = input(false, { ...(ngDevMode ? { debugName: "detailPane" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
13772
+ /**
13773
+ * How wide the list column is while the pane is open — px or any CSS width.
13774
+ * 260px cuts a test name like "Validate Switch Enabled Teaming
13775
+ * Configurations" in half and hides its status.
13776
+ */
13777
+ paneListWidth = input('260px', /* @ts-ignore */
13778
+ ...(ngDevMode ? [{ debugName: "paneListWidth" }] : /* istanbul ignore next */ []));
13779
+ /**
13780
+ * Below this container width (px) the pane takes the list's place, with a
13781
+ * way back in its header, rather than squeezing both into a phone.
13782
+ */
13783
+ paneTakeoverWidth = input(900, /* @ts-ignore */
13784
+ ...(ngDevMode ? [{ debugName: "paneTakeoverWidth" }] : /* istanbul ignore next */ []));
13785
+ /**
13786
+ * The row whose pane is open, two-way: a "what to do next" chip opens the
13787
+ * finding it settles, a URL fragment deep-links to a test, `null` closes it.
13788
+ */
13789
+ activeRowId = model(null, /* @ts-ignore */
13790
+ ...(ngDevMode ? [{ debugName: "activeRowId" }] : /* istanbul ignore next */ []));
13624
13791
  /** Compact density mode. */
13625
13792
  compact = input(false, { ...(ngDevMode ? { debugName: "compact" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
13626
13793
  /**
@@ -13772,6 +13939,21 @@ class StrctDatagrid {
13772
13939
  */
13773
13940
  groupBy = input(null, /* @ts-ignore */
13774
13941
  ...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
13942
+ /**
13943
+ * The groups themselves, beside `groupBy`: their order, their labels, a
13944
+ * tone, a note, whether they start folded and a count of the consumer's
13945
+ * own. Values no group mentions follow, in the order the rows arrived.
13946
+ */
13947
+ groups = input(null, /* @ts-ignore */
13948
+ ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
13949
+ /** Keep a declared group that holds no rows, rather than dropping it. */
13950
+ showEmptyGroups = input(false, { ...(ngDevMode ? { debugName: "showEmptyGroups" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
13951
+ /**
13952
+ * Which groups are folded, two-way — so a summary counter elsewhere on the
13953
+ * page can open the group it counts.
13954
+ */
13955
+ collapsedGroups = model([], /* @ts-ignore */
13956
+ ...(ngDevMode ? [{ debugName: "collapsedGroups" }] : /* istanbul ignore next */ []));
13775
13957
  /**
13776
13958
  * Two-way per-column filter state: `key → contains-text` (text filter) or
13777
13959
  * `key → unknown[]` (checked value set). Applied client-side; in `lazy`
@@ -13829,6 +14011,11 @@ class StrctDatagrid {
13829
14011
  menu = inject(StrctMenuService);
13830
14012
  detailDef = contentChild(StrctRowDetailDef, /* @ts-ignore */
13831
14013
  ...(ngDevMode ? [{ debugName: "detailDef" }] : /* istanbul ignore next */ []));
14014
+ /** An `<ng-template strctGroupHeader let-group let-count="count">`. */
14015
+ groupHeaderDef = contentChild(StrctGroupHeaderDef, /* @ts-ignore */
14016
+ ...(ngDevMode ? [{ debugName: "groupHeaderDef" }] : /* istanbul ignore next */ []));
14017
+ paneTitleDef = contentChild(StrctDetailPaneTitle, /* @ts-ignore */
14018
+ ...(ngDevMode ? [{ debugName: "paneTitleDef" }] : /* istanbul ignore next */ []));
13832
14019
  actionBarDef = contentChild(StrctDatagridActionBar, /* @ts-ignore */
13833
14020
  ...(ngDevMode ? [{ debugName: "actionBarDef" }] : /* istanbul ignore next */ []));
13834
14021
  /** A read-only grid with a note needed an empty action bar to show it. */
@@ -13892,15 +14079,20 @@ class StrctDatagrid {
13892
14079
  document.removeEventListener('mousemove', this.onMove);
13893
14080
  document.removeEventListener('mouseup', this.onUp);
13894
14081
  }
13895
- activeId = signal(null, /* @ts-ignore */
13896
- ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
13897
14082
  activeRow = computed(() => {
13898
- const id = this.activeId();
14083
+ const id = this.activeRowId();
13899
14084
  if (id == null)
13900
14085
  return null;
13901
14086
  return this.rows().find((r) => this.idOf(r) === id) ?? null;
13902
14087
  }, /* @ts-ignore */
13903
14088
  ...(ngDevMode ? [{ debugName: "activeRow" }] : /* istanbul ignore next */ []));
14089
+ /**
14090
+ * Whether the container is too narrow to show the list and the pane at once.
14091
+ * It is the grid's own width that decides, not the viewport: the same grid
14092
+ * is wide in a page and narrow in a drawer.
14093
+ */
14094
+ narrowPane = signal(false, /* @ts-ignore */
14095
+ ...(ngDevMode ? [{ debugName: "narrowPane" }] : /* istanbul ignore next */ []));
13904
14096
  canExpand = computed(() => this.expandable() && !this.detailPane() && !!this.detailDef(), /* @ts-ignore */
13905
14097
  ...(ngDevMode ? [{ debugName: "canExpand" }] : /* istanbul ignore next */ []));
13906
14098
  canDetail = computed(() => this.detailPane() && !!this.detailDef(), /* @ts-ignore */
@@ -13936,10 +14128,15 @@ class StrctDatagrid {
13936
14128
  ...(ngDevMode ? [{ debugName: "orderedColumns" }] : /* istanbul ignore next */ []));
13937
14129
  /** Only the first column is shown while the detail pane is open. */
13938
14130
  visibleColumns = computed(() => {
13939
- if (this.paneOpen())
13940
- return this.orderedColumns().slice(0, 1);
13941
14131
  const hidden = this.hiddenColumns();
13942
- return this.orderedColumns().filter((c) => !hidden.has(c.key));
14132
+ const shown = this.orderedColumns().filter((c) => !hidden.has(c.key));
14133
+ if (!this.paneOpen())
14134
+ return shown;
14135
+ // A results list keeps its status and its name while the pane is open;
14136
+ // one 260px column cut the name in half and hid the status. Columns that
14137
+ // ask to stay, stay; otherwise the first one, as before.
14138
+ const kept = shown.filter((c) => c.keepInPane);
14139
+ return kept.length ? kept : shown.slice(0, 1);
13943
14140
  }, /* @ts-ignore */
13944
14141
  ...(ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []));
13945
14142
  // ── Column drag-reorder ────────────────────────────────────────
@@ -13985,8 +14182,9 @@ class StrctDatagrid {
13985
14182
  this.dropKey.set(null);
13986
14183
  }
13987
14184
  // ── Row grouping ───────────────────────────────────────────────
13988
- collapsedGroups = signal(new Set(), /* @ts-ignore */
13989
- ...(ngDevMode ? [{ debugName: "collapsedGroups" }] : /* istanbul ignore next */ []));
14185
+ /** The folded groups as a set, from the two-way `collapsedGroups`. */
14186
+ collapsedSet = computed(() => new Set(this.collapsedGroups()), /* @ts-ignore */
14187
+ ...(ngDevMode ? [{ debugName: "collapsedSet" }] : /* istanbul ignore next */ []));
13990
14188
  /** Collapse / expand one group header. */
13991
14189
  toggleGroup(key) {
13992
14190
  const next = new Set(this.collapsedGroups());
@@ -13994,7 +14192,7 @@ class StrctDatagrid {
13994
14192
  next.delete(key);
13995
14193
  else
13996
14194
  next.add(key);
13997
- this.collapsedGroups.set(next);
14195
+ this.collapsedGroups.set([...next]);
13998
14196
  }
13999
14197
  /** What tbody renders: plain (virtual/paged) rows, or groups + their rows. */
14000
14198
  displayItems = computed(() => {
@@ -14010,10 +14208,34 @@ class StrctDatagrid {
14010
14208
  else
14011
14209
  map.set(key, [row]);
14012
14210
  }
14211
+ // Declared groups come first, in the order they were given: a triage page
14212
+ // orders by urgency, not alphabetically. Values nobody declared follow, in
14213
+ // the order the rows arrived — today's behaviour.
14214
+ const declared = this.groups() ?? [];
14215
+ const byValue = new Map(declared.map((d) => [d.value, d]));
14216
+ const order = [
14217
+ ...declared.map((d) => d.value),
14218
+ ...[...map.keys()].filter((k) => !byValue.has(k)),
14219
+ ];
14220
+ const collapsedSet = this.collapsedSet();
14013
14221
  const out = [];
14014
- for (const [key, rows] of map) {
14015
- const collapsed = this.collapsedGroups().has(key);
14016
- out.push({ group: { key, label: String(key ?? '—'), count: rows.length, collapsed } });
14222
+ for (const key of order) {
14223
+ const rows = map.get(key) ?? [];
14224
+ const def = byValue.get(key);
14225
+ // A declared group with nothing in it is dropped unless it is asked for.
14226
+ if (!rows.length && (!def || !this.showEmptyGroups()))
14227
+ continue;
14228
+ const collapsed = collapsedSet.has(key);
14229
+ out.push({
14230
+ group: {
14231
+ key,
14232
+ label: def?.label ?? String(key ?? '—'),
14233
+ count: def?.count ?? rows.length,
14234
+ collapsed,
14235
+ status: def?.status,
14236
+ note: def?.note,
14237
+ },
14238
+ });
14017
14239
  if (!collapsed)
14018
14240
  for (const row of rows)
14019
14241
  out.push({ row });
@@ -14196,6 +14418,8 @@ class StrctDatagrid {
14196
14418
  }
14197
14419
  // ── Inline cell editing ────────────────────────────────────────
14198
14420
  hostRef = inject(ElementRef);
14421
+ zone = inject(NgZone);
14422
+ destroyRef = inject(DestroyRef);
14199
14423
  editing = signal(null, /* @ts-ignore */
14200
14424
  ...(ngDevMode ? [{ debugName: "editing" }] : /* istanbul ignore next */ []));
14201
14425
  isEditingCell(row, col) {
@@ -14942,6 +15166,17 @@ class StrctDatagrid {
14942
15166
  this.lazyLoad.emit(state);
14943
15167
  });
14944
15168
  });
15169
+ // Below `paneTakeoverWidth` the pane replaces the list. The grid's own
15170
+ // width decides, not the viewport: the same grid is wide in a page and
15171
+ // narrow in a drawer.
15172
+ afterNextRender(() => {
15173
+ if (typeof ResizeObserver === 'undefined')
15174
+ return;
15175
+ const host = this.hostRef.nativeElement;
15176
+ const ro = new ResizeObserver(() => this.zone.run(() => this.narrowPane.set(host.clientWidth < this.paneTakeoverWidth())));
15177
+ ro.observe(host);
15178
+ this.destroyRef.onDestroy(() => ro.disconnect());
15179
+ });
14945
15180
  // The columns' own `hidden` flags, read once they exist — a required input
14946
15181
  // is not available in the constructor.
14947
15182
  effect(() => {
@@ -15109,9 +15344,60 @@ class StrctDatagrid {
15109
15344
  }
15110
15345
  /** Toggle the detail pane for a row (triggered by its » button, not the row,
15111
15346
  * so row cells remain selectable for copy). */
15347
+ /** One tab stop for the list while a pane can be opened from it. */
15348
+ paneRowTabindex(row) {
15349
+ const rows = this.renderRows();
15350
+ if (!rows.length)
15351
+ return -1;
15352
+ const active = this.activeRow();
15353
+ const current = active && rows.includes(active) ? active : rows[0];
15354
+ return current === row ? 0 : -1;
15355
+ }
15356
+ /**
15357
+ * The mail-client contract a triage list is read with: Enter or Space opens
15358
+ * the row's pane, the arrows move the active row while it is open, and
15359
+ * Escape closes the pane and leaves focus on the row it came from.
15360
+ */
15361
+ onPaneRowKeydown(row, event) {
15362
+ if (!this.canDetail())
15363
+ return;
15364
+ if (event.target?.closest('input, button, select, textarea'))
15365
+ return;
15366
+ const rows = this.renderRows();
15367
+ const idx = rows.indexOf(row);
15368
+ switch (event.key) {
15369
+ case 'Enter':
15370
+ case ' ':
15371
+ event.preventDefault();
15372
+ this.openDetail(row);
15373
+ break;
15374
+ case 'Escape':
15375
+ if (!this.paneOpen())
15376
+ return;
15377
+ event.preventDefault();
15378
+ this.closePane();
15379
+ break;
15380
+ case 'ArrowDown':
15381
+ case 'ArrowUp': {
15382
+ const next = rows[idx + (event.key === 'ArrowDown' ? 1 : -1)];
15383
+ if (!next)
15384
+ return;
15385
+ event.preventDefault();
15386
+ // While the pane is open the arrows move the pane with the row, as a
15387
+ // mail client does; closed, they only move focus.
15388
+ if (this.paneOpen())
15389
+ this.activeRowId.set(this.idOf(next));
15390
+ setTimeout(() => {
15391
+ const trs = this.hostRef.nativeElement.querySelectorAll('tbody tr[tabindex]');
15392
+ trs[idx + (event.key === 'ArrowDown' ? 1 : -1)]?.focus();
15393
+ });
15394
+ break;
15395
+ }
15396
+ }
15397
+ }
15112
15398
  openDetail(row) {
15113
15399
  const id = this.idOf(row);
15114
- this.activeId.set(this.activeId() === id ? null : id);
15400
+ this.activeRowId.set(this.activeRowId() === id ? null : id);
15115
15401
  }
15116
15402
  closePane() {
15117
15403
  // Hand focus back to the row's » button, but only when it was inside the
@@ -15119,7 +15405,7 @@ class StrctDatagrid {
15119
15405
  const host = this.hostRef.nativeElement;
15120
15406
  const focusInside = !!host.querySelector('.strct-dg__pane')?.contains(document.activeElement);
15121
15407
  const trigger = host.querySelector('.strct-dg__detailbtn--active');
15122
- this.activeId.set(null);
15408
+ this.activeRowId.set(null);
15123
15409
  if (focusInside)
15124
15410
  restoreFocus(trigger);
15125
15411
  }
@@ -15356,7 +15642,7 @@ class StrctDatagrid {
15356
15642
  return String(a ?? '').localeCompare(String(b ?? ''), undefined, { numeric: true });
15357
15643
  }
15358
15644
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDatagrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
15359
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDatagrid, isStandalone: true, selector: "strct-datagrid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPane: { classPropertyName: "detailPane", publicName: "detailPane", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, singleLine: { classPropertyName: "singleLine", publicName: "singleLine", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, columnChooser: { classPropertyName: "columnChooser", publicName: "columnChooser", isSignal: true, isRequired: false, transformFunction: null }, sync: { classPropertyName: "sync", publicName: "sync", isSignal: true, isRequired: false, transformFunction: null }, footerActionsDisabled: { classPropertyName: "footerActionsDisabled", publicName: "footerActionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, rowSelectable: { classPropertyName: "rowSelectable", publicName: "rowSelectable", isSignal: true, isRequired: false, transformFunction: null }, flush: { classPropertyName: "flush", publicName: "flush", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, paging: { classPropertyName: "paging", publicName: "paging", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, loadingMore: { classPropertyName: "loadingMore", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, moreTotal: { classPropertyName: "moreTotal", publicName: "moreTotal", isSignal: true, isRequired: false, transformFunction: null }, groupSelect: { classPropertyName: "groupSelect", publicName: "groupSelect", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, initialSelection: { classPropertyName: "initialSelection", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, virtual: { classPropertyName: "virtual", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, viewportHeight: { classPropertyName: "viewportHeight", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, editHint: { classPropertyName: "editHint", publicName: "editHint", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, quickFilter: { classPropertyName: "quickFilter", publicName: "quickFilter", isSignal: true, isRequired: false, transformFunction: null }, quickFilterFields: { classPropertyName: "quickFilterFields", publicName: "quickFilterFields", isSignal: true, isRequired: false, transformFunction: null }, quickFilterable: { classPropertyName: "quickFilterable", publicName: "quickFilterable", isSignal: true, isRequired: false, transformFunction: null }, quickFilterAlign: { classPropertyName: "quickFilterAlign", publicName: "quickFilterAlign", isSignal: true, isRequired: false, transformFunction: null }, childrenKey: { classPropertyName: "childrenKey", publicName: "childrenKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedId: "selectedIdChange", loadMore: "loadMore", selectedIds: "selectedIdsChange", columnState: "columnStateChange", filters: "filtersChange", quickFilter: "quickFilterChange", selectionChange: "selectionChange", syncChange: "syncChange", rowAction: "rowAction", lazyLoad: "lazyLoad", cellEdit: "cellEdit" }, host: { listeners: { "document:click": "onDocClickOverlays($event)", "document:keydown.escape": "onEscapeOverlays($event)" }, properties: { "class.strct-dg-host--compact": "compact()", "class.strct-dg-host--singleline": "singleLine()", "class.strct-dg-host--virtual": "virtual()", "class.strct-dg-host--bounded": "!virtual() && maxHeight() !== null", "class.strct-dg-host--sticky": "stickyActive()", "class.strct-dg-host--flush": "flush()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "actionBarCaptionDef", first: true, predicate: StrctDatagridActionBarCaption, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
15645
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDatagrid, isStandalone: true, selector: "strct-datagrid", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, detailPane: { classPropertyName: "detailPane", publicName: "detailPane", isSignal: true, isRequired: false, transformFunction: null }, paneListWidth: { classPropertyName: "paneListWidth", publicName: "paneListWidth", isSignal: true, isRequired: false, transformFunction: null }, paneTakeoverWidth: { classPropertyName: "paneTakeoverWidth", publicName: "paneTakeoverWidth", isSignal: true, isRequired: false, transformFunction: null }, activeRowId: { classPropertyName: "activeRowId", publicName: "activeRowId", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, singleLine: { classPropertyName: "singleLine", publicName: "singleLine", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, columnChooser: { classPropertyName: "columnChooser", publicName: "columnChooser", isSignal: true, isRequired: false, transformFunction: null }, sync: { classPropertyName: "sync", publicName: "sync", isSignal: true, isRequired: false, transformFunction: null }, footerActionsDisabled: { classPropertyName: "footerActionsDisabled", publicName: "footerActionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, rowId: { classPropertyName: "rowId", publicName: "rowId", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, rowSelectable: { classPropertyName: "rowSelectable", publicName: "rowSelectable", isSignal: true, isRequired: false, transformFunction: null }, flush: { classPropertyName: "flush", publicName: "flush", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, paging: { classPropertyName: "paging", publicName: "paging", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, loadingMore: { classPropertyName: "loadingMore", publicName: "loadingMore", isSignal: true, isRequired: false, transformFunction: null }, moreTotal: { classPropertyName: "moreTotal", publicName: "moreTotal", isSignal: true, isRequired: false, transformFunction: null }, groupSelect: { classPropertyName: "groupSelect", publicName: "groupSelect", isSignal: true, isRequired: false, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, initialSelection: { classPropertyName: "initialSelection", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, virtual: { classPropertyName: "virtual", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, viewportHeight: { classPropertyName: "viewportHeight", publicName: "viewportHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, editHint: { classPropertyName: "editHint", publicName: "editHint", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, showEmptyGroups: { classPropertyName: "showEmptyGroups", publicName: "showEmptyGroups", isSignal: true, isRequired: false, transformFunction: null }, collapsedGroups: { classPropertyName: "collapsedGroups", publicName: "collapsedGroups", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, quickFilter: { classPropertyName: "quickFilter", publicName: "quickFilter", isSignal: true, isRequired: false, transformFunction: null }, quickFilterFields: { classPropertyName: "quickFilterFields", publicName: "quickFilterFields", isSignal: true, isRequired: false, transformFunction: null }, quickFilterable: { classPropertyName: "quickFilterable", publicName: "quickFilterable", isSignal: true, isRequired: false, transformFunction: null }, quickFilterAlign: { classPropertyName: "quickFilterAlign", publicName: "quickFilterAlign", isSignal: true, isRequired: false, transformFunction: null }, childrenKey: { classPropertyName: "childrenKey", publicName: "childrenKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeRowId: "activeRowIdChange", selectedId: "selectedIdChange", loadMore: "loadMore", selectedIds: "selectedIdsChange", columnState: "columnStateChange", collapsedGroups: "collapsedGroupsChange", filters: "filtersChange", quickFilter: "quickFilterChange", selectionChange: "selectionChange", syncChange: "syncChange", rowAction: "rowAction", lazyLoad: "lazyLoad", cellEdit: "cellEdit" }, host: { listeners: { "document:click": "onDocClickOverlays($event)", "document:keydown.escape": "onEscapeOverlays($event)" }, properties: { "class.strct-dg-host--compact": "compact()", "class.strct-dg-host--singleline": "singleLine()", "class.strct-dg-host--virtual": "virtual()", "class.strct-dg-host--bounded": "!virtual() && maxHeight() !== null", "class.strct-dg-host--sticky": "stickyActive()", "class.strct-dg-host--flush": "flush()" }, classAttribute: "strct-dg-host" }, queries: [{ propertyName: "detailDef", first: true, predicate: StrctRowDetailDef, descendants: true, isSignal: true }, { propertyName: "groupHeaderDef", first: true, predicate: StrctGroupHeaderDef, descendants: true, isSignal: true }, { propertyName: "paneTitleDef", first: true, predicate: StrctDetailPaneTitle, descendants: true, isSignal: true }, { propertyName: "actionBarDef", first: true, predicate: StrctDatagridActionBar, descendants: true, isSignal: true }, { propertyName: "actionBarCaptionDef", first: true, predicate: StrctDatagridActionBarCaption, descendants: true, isSignal: true }, { propertyName: "cellDefs", predicate: StrctCellDef, isSignal: true }], ngImport: i0, template: `
15360
15646
  @if (actionBarDef() || quickFilterable() || actionBarCaptionDef()) {
15361
15647
  <div class="strct-dg__toolbar">
15362
15648
  @if (quickFilterable()) {
@@ -15397,7 +15683,12 @@ class StrctDatagrid {
15397
15683
  >
15398
15684
  }
15399
15685
 
15400
- <div class="strct-dg__layout" [class.strct-dg__layout--paned]="paneOpen()">
15686
+ <div
15687
+ class="strct-dg__layout"
15688
+ [class.strct-dg__layout--paned]="paneOpen()"
15689
+ [class.strct-dg__layout--panetakeover]="paneOpen() && narrowPane()"
15690
+ [style.--strct-dg-pane-list-w]="paneListWidth()"
15691
+ >
15401
15692
  <div
15402
15693
  class="strct-dg__scroll"
15403
15694
  tabindex="0"
@@ -15632,8 +15923,34 @@ class StrctDatagrid {
15632
15923
  >
15633
15924
  <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
15634
15925
  </span>
15635
- <span class="strct-dg__grouplabel">{{ grp.label }}</span>
15636
- <span class="strct-dg__groupcount">{{ grp.count }}</span>
15926
+ @if (groupHeaderDef(); as tpl) {
15927
+ <!-- The consumer draws the row; the button, its
15928
+ aria-expanded and the keyboard stay ours. -->
15929
+ <ng-container
15930
+ [ngTemplateOutlet]="tpl.template"
15931
+ [ngTemplateOutletContext]="{
15932
+ $implicit: grp,
15933
+ group: grp,
15934
+ count: grp.count,
15935
+ }"
15936
+ />
15937
+ } @else {
15938
+ <span
15939
+ class="strct-dg__grouplabel strct-dg__grouplabel--{{
15940
+ grp.status ?? 'none'
15941
+ }}"
15942
+ >{{ grp.label }}</span
15943
+ >
15944
+ <span
15945
+ class="strct-dg__groupcount strct-dg__groupcount--{{
15946
+ grp.status ?? 'none'
15947
+ }}"
15948
+ >{{ grp.count }}</span
15949
+ >
15950
+ @if (grp.note) {
15951
+ <span class="strct-dg__groupnote">{{ grp.note }}</span>
15952
+ }
15953
+ }
15637
15954
  </button>
15638
15955
  </td>
15639
15956
  </tr>
@@ -15651,8 +15968,16 @@ class StrctDatagrid {
15651
15968
  [attr.aria-expanded]="
15652
15969
  childrenKey() && treeHasChildren(row) ? treeExpanded(row) : null
15653
15970
  "
15654
- [attr.tabindex]="childrenKey() ? treeRowTabindex(row) : null"
15655
- (keydown)="childrenKey() && onTreeRowKeydown(row, $event)"
15971
+ [attr.tabindex]="
15972
+ childrenKey()
15973
+ ? treeRowTabindex(row)
15974
+ : canDetail()
15975
+ ? paneRowTabindex(row)
15976
+ : null
15977
+ "
15978
+ (keydown)="
15979
+ childrenKey() ? onTreeRowKeydown(row, $event) : onPaneRowKeydown(row, $event)
15980
+ "
15656
15981
  >
15657
15982
  @if (canDetail()) {
15658
15983
  <td
@@ -15888,7 +16213,29 @@ class StrctDatagrid {
15888
16213
  @if (paneOpen()) {
15889
16214
  <aside class="strct-dg__pane">
15890
16215
  <div class="strct-dg__pane-head">
15891
- <span class="strct-dg__pane-title">{{ activeRow()![columns()[0].key] }}</span>
16216
+ @if (narrowPane()) {
16217
+ <!-- The pane has taken the list's place, so there is a way back. -->
16218
+ <button
16219
+ type="button"
16220
+ class="strct-dg__pane-back"
16221
+ [attr.aria-label]="L().backToList"
16222
+ (click)="closePane()"
16223
+ >
16224
+ <strct-icon name="chevronLeft" [size]="13" />
16225
+ </button>
16226
+ }
16227
+ <span class="strct-dg__pane-title">
16228
+ <ng-content select="[strctDetailPaneTitle]" />
16229
+ @if (!paneTitleDef()) {
16230
+ {{ activeRow()![columns()[0].key] }}
16231
+ }
16232
+ </span>
16233
+ <span class="strct-dg__pane-meta">
16234
+ <ng-content select="[strctDetailPaneMeta]" />
16235
+ </span>
16236
+ <span class="strct-dg__pane-actions">
16237
+ <ng-content select="[strctDetailPaneActions]" />
16238
+ </span>
15892
16239
  <button
15893
16240
  type="button"
15894
16241
  class="strct-dg__pane-close"
@@ -15998,7 +16345,7 @@ class StrctDatagrid {
15998
16345
  </div>
15999
16346
  </div>
16000
16347
  }
16001
- `, isInline: true, styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t3)}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t3)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t3)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t3);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:9px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg-host--singleline .strct-dg,.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg tbody .strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned .strct-dg__scroll{flex:0 0 auto;width:260px;min-width:260px;max-width:260px}.strct-dg__layout--paned .strct-dg{width:260px;min-width:260px;max-width:260px;flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:8px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:11.5px;color:var(--t3);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{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-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:11.5px;cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput: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: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["prevLabel", "nextLabel", "regionLabel", "pageLabel", "total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCheckbox, selector: "strct-checkbox", inputs: ["checked", "disabled", "indeterminate", "ariaLabel", "description"], outputs: ["checkedChange"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }, { kind: "component", type: StrctButtonGroup, selector: "strct-button-group" }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }, { kind: "component", type: StrctSearchbox, selector: "strct-searchbox", inputs: ["placeholder", "hint", "trigger", "clearable", "ariaLabel", "clearLabel", "value"], outputs: ["valueChange", "search", "activated"] }, { kind: "component", type: StrctSelect, selector: "strct-select", inputs: ["options", "placeholder", "ariaLabel", "listLabel", "emptyText", "disabled", "compareWith"] }, { kind: "component", type: StrctNumber, selector: "strct-number", inputs: ["min", "max", "step", "placeholder", "ariaLabel", "incrementLabel", "decrementLabel", "disabled"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16348
+ `, isInline: true, styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t3)}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t3)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t3)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t3);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:9px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg-host--singleline .strct-dg,.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg tbody .strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned .strct-dg__scroll{flex:0 0 auto;width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px)}.strct-dg__layout--paned .strct-dg{width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px);flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__layout--panetakeover .strct-dg__scroll{display:none}.strct-dg__layout--panetakeover .strct-dg__pane{flex:1;min-width:0}.strct-dg__pane-meta,.strct-dg__pane-actions{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-dg__pane-meta:empty,.strct-dg__pane-actions:empty{display:none}.strct-dg__pane-actions{margin-inline-start:auto}.strct-dg__pane-back{display:inline-flex;align-items:center;border:0;background:none;color:var(--t2);cursor:pointer;padding:2px;border-radius:var(--radius-sm)}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:8px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:11.5px;color:var(--t3);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{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-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:11.5px;cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput: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: "component", type: StrctPagination, selector: "strct-pagination", inputs: ["prevLabel", "nextLabel", "regionLabel", "pageLabel", "total", "pageSize", "page"], outputs: ["pageChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCheckbox, selector: "strct-checkbox", inputs: ["checked", "disabled", "indeterminate", "ariaLabel", "description"], outputs: ["checkedChange"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }, { kind: "component", type: StrctButtonGroup, selector: "strct-button-group" }, { kind: "directive", type: StrctOverlay, selector: "[strctOverlay]", inputs: ["strctOverlay", "strctOverlayPlacement", "strctOverlayMatchWidth", "strctOverlayGap"] }, { kind: "component", type: StrctSearchbox, selector: "strct-searchbox", inputs: ["placeholder", "hint", "trigger", "clearable", "ariaLabel", "clearLabel", "value"], outputs: ["valueChange", "search", "activated"] }, { kind: "component", type: StrctSelect, selector: "strct-select", inputs: ["options", "placeholder", "ariaLabel", "listLabel", "emptyText", "disabled", "compareWith"] }, { kind: "component", type: StrctNumber, selector: "strct-number", inputs: ["min", "max", "step", "placeholder", "ariaLabel", "incrementLabel", "decrementLabel", "disabled"] }, { kind: "component", type: StrctSpinner, selector: "strct-spinner", inputs: ["size", "label", "caption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16002
16349
  }
16003
16350
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDatagrid, decorators: [{
16004
16351
  type: Component,
@@ -16056,7 +16403,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
16056
16403
  >
16057
16404
  }
16058
16405
 
16059
- <div class="strct-dg__layout" [class.strct-dg__layout--paned]="paneOpen()">
16406
+ <div
16407
+ class="strct-dg__layout"
16408
+ [class.strct-dg__layout--paned]="paneOpen()"
16409
+ [class.strct-dg__layout--panetakeover]="paneOpen() && narrowPane()"
16410
+ [style.--strct-dg-pane-list-w]="paneListWidth()"
16411
+ >
16060
16412
  <div
16061
16413
  class="strct-dg__scroll"
16062
16414
  tabindex="0"
@@ -16291,8 +16643,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
16291
16643
  >
16292
16644
  <strct-icon name="chevronRight" [size]="12" [strokeWidth]="1.7" />
16293
16645
  </span>
16294
- <span class="strct-dg__grouplabel">{{ grp.label }}</span>
16295
- <span class="strct-dg__groupcount">{{ grp.count }}</span>
16646
+ @if (groupHeaderDef(); as tpl) {
16647
+ <!-- The consumer draws the row; the button, its
16648
+ aria-expanded and the keyboard stay ours. -->
16649
+ <ng-container
16650
+ [ngTemplateOutlet]="tpl.template"
16651
+ [ngTemplateOutletContext]="{
16652
+ $implicit: grp,
16653
+ group: grp,
16654
+ count: grp.count,
16655
+ }"
16656
+ />
16657
+ } @else {
16658
+ <span
16659
+ class="strct-dg__grouplabel strct-dg__grouplabel--{{
16660
+ grp.status ?? 'none'
16661
+ }}"
16662
+ >{{ grp.label }}</span
16663
+ >
16664
+ <span
16665
+ class="strct-dg__groupcount strct-dg__groupcount--{{
16666
+ grp.status ?? 'none'
16667
+ }}"
16668
+ >{{ grp.count }}</span
16669
+ >
16670
+ @if (grp.note) {
16671
+ <span class="strct-dg__groupnote">{{ grp.note }}</span>
16672
+ }
16673
+ }
16296
16674
  </button>
16297
16675
  </td>
16298
16676
  </tr>
@@ -16310,8 +16688,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
16310
16688
  [attr.aria-expanded]="
16311
16689
  childrenKey() && treeHasChildren(row) ? treeExpanded(row) : null
16312
16690
  "
16313
- [attr.tabindex]="childrenKey() ? treeRowTabindex(row) : null"
16314
- (keydown)="childrenKey() && onTreeRowKeydown(row, $event)"
16691
+ [attr.tabindex]="
16692
+ childrenKey()
16693
+ ? treeRowTabindex(row)
16694
+ : canDetail()
16695
+ ? paneRowTabindex(row)
16696
+ : null
16697
+ "
16698
+ (keydown)="
16699
+ childrenKey() ? onTreeRowKeydown(row, $event) : onPaneRowKeydown(row, $event)
16700
+ "
16315
16701
  >
16316
16702
  @if (canDetail()) {
16317
16703
  <td
@@ -16547,7 +16933,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
16547
16933
  @if (paneOpen()) {
16548
16934
  <aside class="strct-dg__pane">
16549
16935
  <div class="strct-dg__pane-head">
16550
- <span class="strct-dg__pane-title">{{ activeRow()![columns()[0].key] }}</span>
16936
+ @if (narrowPane()) {
16937
+ <!-- The pane has taken the list's place, so there is a way back. -->
16938
+ <button
16939
+ type="button"
16940
+ class="strct-dg__pane-back"
16941
+ [attr.aria-label]="L().backToList"
16942
+ (click)="closePane()"
16943
+ >
16944
+ <strct-icon name="chevronLeft" [size]="13" />
16945
+ </button>
16946
+ }
16947
+ <span class="strct-dg__pane-title">
16948
+ <ng-content select="[strctDetailPaneTitle]" />
16949
+ @if (!paneTitleDef()) {
16950
+ {{ activeRow()![columns()[0].key] }}
16951
+ }
16952
+ </span>
16953
+ <span class="strct-dg__pane-meta">
16954
+ <ng-content select="[strctDetailPaneMeta]" />
16955
+ </span>
16956
+ <span class="strct-dg__pane-actions">
16957
+ <ng-content select="[strctDetailPaneActions]" />
16958
+ </span>
16551
16959
  <button
16552
16960
  type="button"
16553
16961
  class="strct-dg__pane-close"
@@ -16665,8 +17073,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
16665
17073
  '[class.strct-dg-host--bounded]': '!virtual() && maxHeight() !== null',
16666
17074
  '[class.strct-dg-host--sticky]': 'stickyActive()',
16667
17075
  '[class.strct-dg-host--flush]': 'flush()',
16668
- }, styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t3)}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t3)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t3)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t3);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:9px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg-host--singleline .strct-dg,.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg tbody .strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned .strct-dg__scroll{flex:0 0 auto;width:260px;min-width:260px;max-width:260px}.strct-dg__layout--paned .strct-dg{width:260px;min-width:260px;max-width:260px;flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:8px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:11.5px;color:var(--t3);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{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-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:11.5px;cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
16669
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPane: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], singleLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleLine", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], columnChooser: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnChooser", required: false }] }], sync: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: false }] }], footerActionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerActionsDisabled", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }, { type: i0.Output, args: ["selectedIdChange"] }], rowSelectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSelectable", required: false }] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], paging: [{ type: i0.Input, args: [{ isSignal: true, alias: "paging", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], loadingMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMore", required: false }] }], moreTotal: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreTotal", required: false }] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], groupSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupSelect", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], initialSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSelection", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }, { type: i0.Output, args: ["selectedIdsChange"] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], virtual: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtual", required: false }] }], viewportHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], editHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "editHint", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: false }] }, { type: i0.Output, args: ["columnStateChange"] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], quickFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilter", required: false }] }, { type: i0.Output, args: ["quickFilterChange"] }], quickFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterFields", required: false }] }], quickFilterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterable", required: false }] }], quickFilterAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterAlign", required: false }] }], childrenKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenKey", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], syncChange: [{ type: i0.Output, args: ["syncChange"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], actionBarCaptionDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBarCaption), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }], onDocClickOverlays: [{
17076
+ }, styles: [".strct-dg__radio{width:15px;height:15px;accent-color:var(--acc);cursor:pointer}.strct-dg__radio:disabled{cursor:not-allowed}.strct-dg__row--locked .strct-dg__sel{opacity:.55}.strct-dg__actioncaption:empty{display:none}.strct-dg__actioncaption{display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-sm);color:var(--t3)}.strct-dg-host{display:block;border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);box-shadow:var(--shadow-rest)}.strct-dg-host--flush{border:0;border-radius:0;background:transparent;box-shadow:none}.strct-dg__more strct-spinner{margin-inline-end:4px}.strct-dg__caption{caption-side:top;text-align:start;padding:var(--space-2) var(--space-3);font-size:var(--text-sm);font-weight:600;color:var(--t2)}.strct-dg td.strct-dg__cell--mono{font-family:var(--mono);font-size:var(--text-sm)}.strct-dg td.strct-dg__cell--muted{color:var(--t3)}.strct-dg td.strct-dg__cell--numeric{font-variant-numeric:tabular-nums}.strct-dg__empty{color:var(--t3)}.strct-dg__celldesc{display:block;font-size:var(--text-sm);color:var(--t3);line-height:1.3}.strct-dg__scroll{flex:1 1 auto;min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch}.strct-dg-host--virtual .strct-dg__scroll,.strct-dg-host--bounded .strct-dg__scroll{overflow-y:auto}.strct-dg-host--virtual .strct-dg thead th,.strct-dg-host--bounded .strct-dg thead th{position:sticky;top:0;z-index:var(--z-raised)}.strct-dg__vspacer td{padding:0;border:0;background:transparent}.strct-dg th[draggable]{cursor:grab}.strct-dg__th--drop{box-shadow:inset 3px 0 0 var(--acc)}.strct-dg__grouprow td{background:var(--bg-2)!important;padding:0}.strct-dg__groupbtn{display:flex;align-items:center;gap:8px;width:100%;padding:7px 13px;border:0;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;font-weight:600;cursor:pointer;text-align:start}.strct-dg__groupbtn:hover{background:var(--bg-3)}.strct-dg__groupbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__groupchev{display:inline-flex;color:var(--t3);transition:transform .15s ease}.strct-dg__groupchev--open{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){.strct-dg__groupchev{transition:none}}.strct-dg__groupcount{min-width:18px;height:18px;padding:0 5px;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border-radius:9px;background:var(--acc-m);color:var(--acc);font-variant-numeric:tabular-nums}.strct-dg-host--singleline .strct-dg,.strct-dg-host--sticky .strct-dg,.strct-dg-host--virtual .strct-dg,.strct-dg-host--bounded .strct-dg{border-collapse:separate;border-spacing:0;overflow:visible;border-radius:0}.strct-dg-host--sticky .strct-dg{width:max-content;min-width:100%}.strct-dg .strct-dg__cell--sticky{position:sticky;z-index:calc(var(--z-base) + 2)}.strct-dg thead th.strct-dg__cell--sticky{z-index:calc(var(--z-raised) + 1)}.strct-dg .strct-dg__cell--sticky-last:after{content:\"\";position:absolute;top:0;bottom:0;inset-inline-end:-1px;width:7px;pointer-events:none;background:linear-gradient(to right,rgba(0,0,0,.14),transparent)}[dir=rtl] .strct-dg .strct-dg__cell--sticky-last:after{background:linear-gradient(to left,rgba(0,0,0,.14),transparent)}.strct-dg-host--sticky .strct-dg__expandcol,.strct-dg-host--sticky .strct-dg__expandcell{width:36px;min-width:36px;max-width:36px;box-sizing:border-box}.strct-dg-host--sticky .strct-dg__sel{width:40px;min-width:40px;max-width:40px;box-sizing:border-box}.strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__cell--sticky{background:var(--bg-3)}.strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody tr:hover .strct-dg__cell--sticky{background:linear-gradient(var(--acc-s),var(--acc-s)) var(--bg-3)}.strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-1)}[data-theme=dark] .strct-dg-host--sticky tbody .strct-dg__row--selected .strct-dg__cell--sticky{background:linear-gradient(var(--acc-m),var(--acc-m)) var(--bg-3)}.strct-dg{width:100%;border-collapse:collapse;font-size:13px;overflow:hidden;background:var(--bg-2)}.strct-dg-host:not(:has(.strct-dg__toolbar)) .strct-dg{border-start-start-radius:9px;border-start-end-radius:9px}.strct-dg-host:not(:has(.strct-dg__foot)) .strct-dg{border-end-start-radius:9px;border-end-end-radius:9px}.strct-dg th,.strct-dg td{padding:9px 13px;text-align:start;border-bottom:1px solid var(--b1)}.strct-dg tbody td{background:var(--bg-1)}[data-theme=dark] .strct-dg tbody td{background:var(--bg-3)}.strct-dg-host--compact .strct-dg th,.strct-dg-host--compact .strct-dg td{padding:5px 11px}.strct-dg-host--singleline .strct-dg tbody tr:not(.strct-dg__detailrow)>td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}.strct-dg th{position:relative;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--t2);background:var(--bg-2);white-space:nowrap;-webkit-user-select:none;user-select:none}.strct-dg__th--sortable{cursor:pointer}.strct-dg__th--sortable:hover{color:var(--t1)}.strct-dg__th--sortable:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__hd{display:inline-flex;align-items:center;gap:5px}.strct-dg__sorticon{color:var(--t3)}.strct-dg__th--sortable:hover .strct-dg__sorticon{color:var(--acc)}.strct-dg__resize{position:absolute;inset-inline-end:0;top:0;bottom:0;width:4px;cursor:col-resize;background:transparent;z-index:calc(var(--z-base) + 1)}.strct-dg__resize:hover{background:var(--acc)}.strct-dg td{color:var(--t1)}.strct-dg tbody tr:last-child td{border-bottom:0}.strct-dg tbody tr:not(.strct-dg__detailrow):hover td{background:var(--acc-s)}.strct-dg tbody .strct-dg__row--selected td{background:var(--acc-m)}.strct-dg__sel{width:1%;white-space:nowrap}.strct-dg__sel input{accent-color:var(--acc);width:15px;height:15px;cursor:pointer}.strct-dg__expandcol,.strct-dg__expandcell{width:1%;white-space:nowrap}.strct-dg__actioncol,.strct-dg__actioncell{width:1%;white-space:nowrap;text-align:end}.strct-dg__kebab{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__kebab:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:transform .15s ease,color .15s ease}.strct-dg__expandbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__expandbtn--open{transform:rotate(90deg);color:var(--acc)}.strct-dg__detailbtn{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;transition:color .14s ease,background .14s ease}.strct-dg__detailbtn:hover{color:var(--acc);background:var(--bg-3)}.strct-dg__detailbtn--active{color:var(--acc);background:var(--acc-m)}.strct-dg__detailrow td{background:var(--bg-2);padding:0}.strct-dg__detail{padding:14px 16px;font-size:13px;color:var(--t2)}.strct-dg__layout{display:flex;align-items:flex-start;min-width:0}.strct-dg__layout--paned{gap:0}.strct-dg__layout--paned .strct-dg__scroll{flex:0 0 auto;width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px)}.strct-dg__layout--paned .strct-dg{width:var(--strct-dg-pane-list-w, 260px);min-width:var(--strct-dg-pane-list-w, 260px);max-width:var(--strct-dg-pane-list-w, 260px);flex-shrink:0;border-start-end-radius:0;border-end-end-radius:0}.strct-dg__layout--panetakeover .strct-dg__scroll{display:none}.strct-dg__layout--panetakeover .strct-dg__pane{flex:1;min-width:0}.strct-dg__pane-meta,.strct-dg__pane-actions{display:inline-flex;align-items:center;gap:var(--space-2)}.strct-dg__pane-meta:empty,.strct-dg__pane-actions:empty{display:none}.strct-dg__pane-actions{margin-inline-start:auto}.strct-dg__pane-back{display:inline-flex;align-items:center;border:0;background:none;color:var(--t2);cursor:pointer;padding:2px;border-radius:var(--radius-sm)}.strct-dg__row--clickable{cursor:pointer}.strct-dg tbody .strct-dg__row--active td{background:var(--acc-m)}.strct-dg__layout--paned .strct-dg__row--active td:last-child{position:relative;padding-inline-end:26px}.strct-dg__layout--paned .strct-dg__row--active td:last-child:after{content:\"\";position:absolute;inset-inline-end:11px;top:50%;width:6px;height:6px;border-top:1.6px solid var(--acc);border-inline-end:1.6px solid var(--acc);transform:translateY(-50%) rotate(45deg)}.strct-dg__pane{flex:1;min-width:0;align-self:stretch;background:var(--bg-1);border:1px solid var(--b2);border-inline-start:2px solid var(--acc);border-radius:8px;border-start-start-radius:0;border-end-start-radius:0;overflow:hidden;animation:strct-dg-pane-in .14s ease}.strct-dg__pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 14px;border-bottom:1px solid var(--b1);font-size:13px;font-weight:600;color:var(--t1)}.strct-dg__pane-close{display:inline-flex;padding:3px;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer}.strct-dg__pane-close:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__pane-body{padding:14px 16px;font-size:13px;color:var(--t2)}@keyframes strct-dg-pane-in{0%{opacity:0;transform:translate(8px)}}@keyframes strct-skeleton-pulse{0%,to{opacity:.4}50%{opacity:.7}}.strct-dg__skeleton-block{height:12px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--bg-3) 25%,var(--skeleton-hi, var(--acc18)) 50%,var(--bg-3) 75%);background-size:200% 100%;animation:strct-dg-skeleton-sweep 1.1s linear infinite}@keyframes strct-dg-skeleton-sweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.strct-dg__skeleton-block{animation:none;background:var(--skeleton-hi, var(--acc18))}}.strct-dg__skeleton-row td{border-bottom:1px solid var(--b1)}.strct-dg__empty{text-align:center;color:var(--t3);padding:22px}.strct-dg__quickfilter{min-width:180px;max-width:260px}.strct-dg__quickfilter--end{order:2;margin-inline-start:auto}.strct-dg__filternote--end{order:3}.strct-dg__filternote{font-size:11.5px;color:var(--t3);font-variant-numeric:tabular-nums;white-space:nowrap}.strct-dg__toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--b2)}.strct-dg__foot{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 14px;border-top:1px solid var(--b2);flex-wrap:wrap}.strct-dg__foot-left,.strct-dg__foot-right{display:flex;align-items:center;gap:12px}.strct-dg__actions{position:relative}.strct-dg__chooser-menu{position:absolute;bottom:calc(100% + 6px);inset-inline-start:0;z-index:var(--z-sticky);min-width:180px;background:var(--bg-1);border:1px solid var(--b2);border-radius:8px;box-shadow:var(--shadow-pop);padding:6px;display:flex;flex-direction:column;gap:2px}.strct-dg__chooser-menu--right{inset-inline-start:auto;inset-inline-end:0}.strct-dg__chooser-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--t1);transition:background .1s ease;-webkit-user-select:none;user-select:none}.strct-dg__chooser-item:hover{background:var(--bg-3)}.strct-dg__count{font-size:12px;color:var(--t2)}.strct-dg__count-sep{margin:0 8px;color:var(--b2)}.strct-dg__count-sel{color:var(--acc)}.strct-dg__filterbtn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-inline-start:2px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__filterbtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__filterbtn--active{color:var(--acc)}.strct-dg__filterbtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filterpanel{position:absolute;z-index:calc(var(--z-dropdown) + 10);display:flex;flex-direction:column;gap:6px;min-width:180px;padding:10px;background:var(--bg-1);border:1px solid var(--b2);border-radius:7px;box-shadow:var(--shh);font-weight:400;text-transform:none;letter-spacing:normal;white-space:nowrap}.strct-dg__filterinput{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-dg__filterinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__filteropt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--t1);cursor:pointer}.strct-dg__filterclear{align-self:flex-start;padding:3px 8px;border:1px solid var(--b2);border-radius:var(--radius-sm);background:transparent;color:var(--t2);font-family:var(--font);font-size:11.5px;cursor:pointer}.strct-dg__filterclear:hover:not(:disabled){color:var(--t1);background:var(--bg-3)}.strct-dg__filterclear:disabled{color:var(--t4);cursor:default}.strct-dg tbody tr[tabindex]:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-dg__treepad{display:inline-block;height:1px;vertical-align:middle}.strct-dg__treebtn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-inline-end:4px;padding:0;border:0;border-radius:4px;background:transparent;color:var(--t3);cursor:pointer;vertical-align:middle}.strct-dg__treebtn:hover{color:var(--t1);background:var(--bg-3)}.strct-dg__treebtn:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-dg__treebtn strct-icon{transition:transform .15s ease}.strct-dg__treebtn--open strct-icon{transform:rotate(90deg)}.strct-dg__treebtn--leaf{cursor:default;pointer-events:none}@media(prefers-reduced-motion:reduce){.strct-dg__treebtn strct-icon{transition:none}}.strct-dg__cell--editable{cursor:text;position:relative}.strct-dg__cell--editable:hover{box-shadow:inset 0 0 0 1px var(--b2)}.strct-dg__cell--editable:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--acc50)}.strct-dg__editpencil{position:absolute;top:50%;inset-inline-end:6px;transform:translateY(-50%);color:var(--t3);opacity:0;pointer-events:none}td:hover>.strct-dg__editpencil,td:focus-within>.strct-dg__editpencil{opacity:1}.strct-dg__editinput{width:100%;box-sizing:border-box;padding:3px 6px;border:1px solid var(--acc);border-radius:var(--radius-sm);background:var(--bg-1);color:var(--t1);font:inherit}.strct-dg__editselect,.strct-dg__editnumber{display:block;width:100%}.strct-dg__editinput:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}\n"] }]
17077
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], detailPane: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailPane", required: false }] }], paneListWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "paneListWidth", required: false }] }], paneTakeoverWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "paneTakeoverWidth", required: false }] }], activeRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeRowId", required: false }] }, { type: i0.Output, args: ["activeRowIdChange"] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], singleLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleLine", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], columnChooser: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnChooser", required: false }] }], sync: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: false }] }], footerActionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerActionsDisabled", required: false }] }], rowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowId", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }, { type: i0.Output, args: ["selectedIdChange"] }], rowSelectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSelectable", required: false }] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], paging: [{ type: i0.Input, args: [{ isSignal: true, alias: "paging", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], loadingMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMore", required: false }] }], moreTotal: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreTotal", required: false }] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], groupSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupSelect", required: false }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], initialSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSelection", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }, { type: i0.Output, args: ["selectedIdsChange"] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], virtual: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtual", required: false }] }], viewportHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], editHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "editHint", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: false }] }, { type: i0.Output, args: ["columnStateChange"] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], showEmptyGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmptyGroups", required: false }] }], collapsedGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedGroups", required: false }] }, { type: i0.Output, args: ["collapsedGroupsChange"] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], quickFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilter", required: false }] }, { type: i0.Output, args: ["quickFilterChange"] }], quickFilterFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterFields", required: false }] }], quickFilterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterable", required: false }] }], quickFilterAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterAlign", required: false }] }], childrenKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenKey", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], syncChange: [{ type: i0.Output, args: ["syncChange"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], detailDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctRowDetailDef), { isSignal: true }] }], groupHeaderDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctGroupHeaderDef), { isSignal: true }] }], paneTitleDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDetailPaneTitle), { isSignal: true }] }], actionBarDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBar), { isSignal: true }] }], actionBarCaptionDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctDatagridActionBarCaption), { isSignal: true }] }], cellDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctCellDef), { isSignal: true }] }], onDocClickOverlays: [{
16670
17078
  type: HostListener,
16671
17079
  args: ['document:click', ['$event']]
16672
17080
  }], onEscapeOverlays: [{
@@ -19681,6 +20089,18 @@ class StrctMetricTile {
19681
20089
  ...(ngDevMode ? [{ debugName: "href" }] : /* istanbul ignore next */ []));
19682
20090
  /** Makes the whole tile a control that emits `activated`. */
19683
20091
  interactive = input(false, { ...(ngDevMode ? { debugName: "interactive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
20092
+ /**
20093
+ * The tile is a filter: `true` draws it on and says `aria-pressed`, `false`
20094
+ * draws it off and still says so. `null` (the default) is a tile that is
20095
+ * not a toggle at all, which must not claim a pressed state.
20096
+ */
20097
+ pressed = input(null, { ...(ngDevMode ? { debugName: "pressed" } : /* istanbul ignore next */ {}), transform: (v) => (v === null || v === undefined ? null : booleanAttribute(v)) });
20098
+ /**
20099
+ * `sm` is the verdict-band size: six counters beside a one-line verdict at
20100
+ * 1440px, where the dashboard size fits three.
20101
+ */
20102
+ size = input('md', /* @ts-ignore */
20103
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
19684
20104
  /**
19685
20105
  * What a plain click on an `href` tile does. `browser` follows the link, as
19686
20106
  * today. `app` belongs to a single-page app: the click is prevented and
@@ -19762,7 +20182,7 @@ class StrctMetricTile {
19762
20182
  }, /* @ts-ignore */
19763
20183
  ...(ngDevMode ? [{ debugName: "sparkStatus" }] : /* istanbul ignore next */ []));
19764
20184
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMetricTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
19765
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctMetricTile, isStandalone: true, selector: "strct-metric-tile", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, captionStatus: { classPropertyName: "captionStatus", publicName: "captionStatus", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, navigate: { classPropertyName: "navigate", publicName: "navigate", isSignal: true, isRequired: false, transformFunction: null }, delta: { classPropertyName: "delta", publicName: "delta", isSignal: true, isRequired: false, transformFunction: null }, deltaSuffix: { classPropertyName: "deltaSuffix", publicName: "deltaSuffix", isSignal: true, isRequired: false, transformFunction: null }, deltaAriaLabel: { classPropertyName: "deltaAriaLabel", publicName: "deltaAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, invertDelta: { classPropertyName: "invertDelta", publicName: "invertDelta", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "activated" }, host: { properties: { "class.strct-mt--status": "status() !== 'neutral'", "attr.data-status": "status() !== 'neutral' ? status() : null", "class.strct-mt--actionable": "href() || interactive()", "class.strct-mt--loading": "loading()", "attr.aria-busy": "loading() ? \"true\" : null" }, classAttribute: "strct-mt" }, ngImport: i0, template: `
20185
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctMetricTile, isStandalone: true, selector: "strct-metric-tile", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, captionStatus: { classPropertyName: "captionStatus", publicName: "captionStatus", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, pressed: { classPropertyName: "pressed", publicName: "pressed", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, navigate: { classPropertyName: "navigate", publicName: "navigate", isSignal: true, isRequired: false, transformFunction: null }, delta: { classPropertyName: "delta", publicName: "delta", isSignal: true, isRequired: false, transformFunction: null }, deltaSuffix: { classPropertyName: "deltaSuffix", publicName: "deltaSuffix", isSignal: true, isRequired: false, transformFunction: null }, deltaAriaLabel: { classPropertyName: "deltaAriaLabel", publicName: "deltaAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, invertDelta: { classPropertyName: "invertDelta", publicName: "invertDelta", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "activated" }, host: { properties: { "class.strct-mt--status": "status() !== 'neutral'", "attr.data-status": "status() !== 'neutral' ? status() : null", "class.strct-mt--actionable": "href() || interactive()", "class.strct-mt--pressed": "pressed() === true", "class.strct-mt--sm": "size() === 'sm'", "class.strct-mt--loading": "loading()", "attr.aria-busy": "loading() ? \"true\" : null" }, classAttribute: "strct-mt" }, ngImport: i0, template: `
19766
20186
  @if (loading()) {
19767
20187
  <strct-skeleton width="45%" height="12px" />
19768
20188
  <strct-skeleton width="65%" height="28px" />
@@ -19818,10 +20238,11 @@ class StrctMetricTile {
19818
20238
  type="button"
19819
20239
  class="strct-mt__hit"
19820
20240
  [attr.aria-label]="hitLabel()"
20241
+ [attr.aria-pressed]="pressed() === null ? null : pressed() ? 'true' : 'false'"
19821
20242
  (click)="activated.emit()"
19822
20243
  ></button>
19823
20244
  }
19824
- `, isInline: true, styles: [".strct-mt{position:relative;display:flex;flex-direction:column;gap:6px;padding:var(--space-3) var(--space-4);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);min-width:0}.strct-mt--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:3px;border-start-start-radius:var(--radius-lg);border-end-start-radius:var(--radius-lg);background:var(--t3)}.strct-mt[data-status=accent]:before{background:var(--acc)}.strct-mt[data-status=success]:before{background:var(--success)}.strct-mt[data-status=warning]:before{background:var(--warning)}.strct-mt[data-status=critical]:before{background:var(--critical)}.strct-mt__top{display:flex;align-items:center;gap:7px}.strct-mt__icon{display:inline-flex;color:var(--t3);flex-shrink:0}.strct-mt__label{font-size:12px;font-weight:500;color:var(--t3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-mt__delta{display:inline-flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;flex-shrink:0}.strct-mt__delta--up{color:var(--success)}.strct-mt__delta--down{color:var(--critical)}.strct-mt__delta--flat{color:var(--t3)}.strct-mt__meter:empty{display:none}.strct-mt__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;border-radius:inherit;cursor:pointer}.strct-mt__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mt--actionable:hover{border-color:var(--b3);background:var(--bg-2)}.strct-mt__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-mt__value{display:flex;align-items:baseline;gap:4px;font-size:var(--text-3xl);font-weight:650;letter-spacing:-.01em;color:var(--t1);line-height:1.1}.strct-mt__value--accent{color:var(--acc)}.strct-mt__value--success{color:var(--success)}.strct-mt__value--warning{color:var(--warning)}.strct-mt__value--critical{color:var(--critical)}.strct-mt__unit{font-size:14px;font-weight:500;color:var(--t3);letter-spacing:0}.strct-mt__caption{font-size:12px;color:var(--t3)}.strct-mt__caption--accent{color:var(--acc)}.strct-mt__caption--success{color:var(--success)}.strct-mt__caption--warning{color:var(--warning)}.strct-mt__caption--critical{color:var(--critical)}.strct-mt__spark{margin-top:2px;line-height:0}.strct-mt__spark strct-sparkline,.strct-mt__spark .strct-spark__svg{width:100%}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctSkeleton, selector: "strct-skeleton", inputs: ["width", "height", "circle"] }, { kind: "component", type: StrctSparkline, selector: "strct-sparkline", inputs: ["data", "status", "area", "width", "height", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20245
+ `, isInline: true, styles: [".strct-mt{position:relative;display:flex;flex-direction:column;gap:6px;padding:var(--space-3) var(--space-4);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);min-width:0}.strct-mt--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:3px;border-start-start-radius:var(--radius-lg);border-end-start-radius:var(--radius-lg);background:var(--t3)}.strct-mt[data-status=accent]:before{background:var(--acc)}.strct-mt[data-status=success]:before{background:var(--success)}.strct-mt[data-status=warning]:before{background:var(--warning)}.strct-mt[data-status=critical]:before{background:var(--critical)}.strct-mt--pressed{border-color:var(--acc);background:var(--acc-m)}.strct-mt--sm{gap:2px;padding:6px 10px}.strct-mt--sm .strct-mt__label{font-size:12px}.strct-mt--sm .strct-mt__value{font-size:16px}.strct-mt--sm .strct-mt__icon strct-icon{width:13px;height:13px}.strct-mt__top{display:flex;align-items:center;gap:7px}.strct-mt__icon{display:inline-flex;color:var(--t3);flex-shrink:0}.strct-mt__label{font-size:12px;font-weight:500;color:var(--t3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-mt__delta{display:inline-flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;flex-shrink:0}.strct-mt__delta--up{color:var(--success)}.strct-mt__delta--down{color:var(--critical)}.strct-mt__delta--flat{color:var(--t3)}.strct-mt__meter:empty{display:none}.strct-mt__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;border-radius:inherit;cursor:pointer}.strct-mt__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mt--actionable:hover{border-color:var(--b3);background:var(--bg-2)}.strct-mt__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-mt__value{display:flex;align-items:baseline;gap:4px;font-size:var(--text-3xl);font-weight:650;letter-spacing:-.01em;color:var(--t1);line-height:1.1}.strct-mt__value--accent{color:var(--acc)}.strct-mt__value--success{color:var(--success)}.strct-mt__value--warning{color:var(--warning)}.strct-mt__value--critical{color:var(--critical)}.strct-mt__unit{font-size:14px;font-weight:500;color:var(--t3);letter-spacing:0}.strct-mt__caption{font-size:12px;color:var(--t3)}.strct-mt__caption--accent{color:var(--acc)}.strct-mt__caption--success{color:var(--success)}.strct-mt__caption--warning{color:var(--warning)}.strct-mt__caption--critical{color:var(--critical)}.strct-mt__spark{margin-top:2px;line-height:0}.strct-mt__spark strct-sparkline,.strct-mt__spark .strct-spark__svg{width:100%}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel", "count", "countMax", "countStatus", "countLabel"] }, { kind: "component", type: StrctSkeleton, selector: "strct-skeleton", inputs: ["width", "height", "circle"] }, { kind: "component", type: StrctSparkline, selector: "strct-sparkline", inputs: ["data", "status", "area", "width", "height", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19825
20246
  }
19826
20247
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMetricTile, decorators: [{
19827
20248
  type: Component,
@@ -19881,6 +20302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
19881
20302
  type="button"
19882
20303
  class="strct-mt__hit"
19883
20304
  [attr.aria-label]="hitLabel()"
20305
+ [attr.aria-pressed]="pressed() === null ? null : pressed() ? 'true' : 'false'"
19884
20306
  (click)="activated.emit()"
19885
20307
  ></button>
19886
20308
  }
@@ -19889,10 +20311,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
19889
20311
  '[class.strct-mt--status]': "status() !== 'neutral'",
19890
20312
  '[attr.data-status]': "status() !== 'neutral' ? status() : null",
19891
20313
  '[class.strct-mt--actionable]': 'href() || interactive()',
20314
+ '[class.strct-mt--pressed]': 'pressed() === true',
20315
+ '[class.strct-mt--sm]': "size() === 'sm'",
19892
20316
  '[class.strct-mt--loading]': 'loading()',
19893
20317
  '[attr.aria-busy]': 'loading() ? "true" : null',
19894
- }, styles: [".strct-mt{position:relative;display:flex;flex-direction:column;gap:6px;padding:var(--space-3) var(--space-4);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);min-width:0}.strct-mt--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:3px;border-start-start-radius:var(--radius-lg);border-end-start-radius:var(--radius-lg);background:var(--t3)}.strct-mt[data-status=accent]:before{background:var(--acc)}.strct-mt[data-status=success]:before{background:var(--success)}.strct-mt[data-status=warning]:before{background:var(--warning)}.strct-mt[data-status=critical]:before{background:var(--critical)}.strct-mt__top{display:flex;align-items:center;gap:7px}.strct-mt__icon{display:inline-flex;color:var(--t3);flex-shrink:0}.strct-mt__label{font-size:12px;font-weight:500;color:var(--t3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-mt__delta{display:inline-flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;flex-shrink:0}.strct-mt__delta--up{color:var(--success)}.strct-mt__delta--down{color:var(--critical)}.strct-mt__delta--flat{color:var(--t3)}.strct-mt__meter:empty{display:none}.strct-mt__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;border-radius:inherit;cursor:pointer}.strct-mt__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mt--actionable:hover{border-color:var(--b3);background:var(--bg-2)}.strct-mt__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-mt__value{display:flex;align-items:baseline;gap:4px;font-size:var(--text-3xl);font-weight:650;letter-spacing:-.01em;color:var(--t1);line-height:1.1}.strct-mt__value--accent{color:var(--acc)}.strct-mt__value--success{color:var(--success)}.strct-mt__value--warning{color:var(--warning)}.strct-mt__value--critical{color:var(--critical)}.strct-mt__unit{font-size:14px;font-weight:500;color:var(--t3);letter-spacing:0}.strct-mt__caption{font-size:12px;color:var(--t3)}.strct-mt__caption--accent{color:var(--acc)}.strct-mt__caption--success{color:var(--success)}.strct-mt__caption--warning{color:var(--warning)}.strct-mt__caption--critical{color:var(--critical)}.strct-mt__spark{margin-top:2px;line-height:0}.strct-mt__spark strct-sparkline,.strct-mt__spark .strct-spark__svg{width:100%}\n"] }]
19895
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], captionStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionStatus", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], navigate: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigate", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }], delta: [{ type: i0.Input, args: [{ isSignal: true, alias: "delta", required: false }] }], deltaSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "deltaSuffix", required: false }] }], deltaAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "deltaAriaLabel", required: false }] }], invertDelta: [{ type: i0.Input, args: [{ isSignal: true, alias: "invertDelta", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
20318
+ }, styles: [".strct-mt{position:relative;display:flex;flex-direction:column;gap:6px;padding:var(--space-3) var(--space-4);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-1);min-width:0}.strct-mt--status:before{content:\"\";position:absolute;inset-block:0;inset-inline-start:0;width:3px;border-start-start-radius:var(--radius-lg);border-end-start-radius:var(--radius-lg);background:var(--t3)}.strct-mt[data-status=accent]:before{background:var(--acc)}.strct-mt[data-status=success]:before{background:var(--success)}.strct-mt[data-status=warning]:before{background:var(--warning)}.strct-mt[data-status=critical]:before{background:var(--critical)}.strct-mt--pressed{border-color:var(--acc);background:var(--acc-m)}.strct-mt--sm{gap:2px;padding:6px 10px}.strct-mt--sm .strct-mt__label{font-size:12px}.strct-mt--sm .strct-mt__value{font-size:16px}.strct-mt--sm .strct-mt__icon strct-icon{width:13px;height:13px}.strct-mt__top{display:flex;align-items:center;gap:7px}.strct-mt__icon{display:inline-flex;color:var(--t3);flex-shrink:0}.strct-mt__label{font-size:12px;font-weight:500;color:var(--t3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.strct-mt__delta{display:inline-flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;flex-shrink:0}.strct-mt__delta--up{color:var(--success)}.strct-mt__delta--down{color:var(--critical)}.strct-mt__delta--flat{color:var(--t3)}.strct-mt__meter:empty{display:none}.strct-mt__hit{position:absolute;inset:-1px;padding:0;border:0;background:none;border-radius:inherit;cursor:pointer}.strct-mt__hit:focus-visible{outline:2px solid var(--acc50);outline-offset:2px}.strct-mt--actionable:hover{border-color:var(--b3);background:var(--bg-2)}.strct-mt__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.strct-mt__value{display:flex;align-items:baseline;gap:4px;font-size:var(--text-3xl);font-weight:650;letter-spacing:-.01em;color:var(--t1);line-height:1.1}.strct-mt__value--accent{color:var(--acc)}.strct-mt__value--success{color:var(--success)}.strct-mt__value--warning{color:var(--warning)}.strct-mt__value--critical{color:var(--critical)}.strct-mt__unit{font-size:14px;font-weight:500;color:var(--t3);letter-spacing:0}.strct-mt__caption{font-size:12px;color:var(--t3)}.strct-mt__caption--accent{color:var(--acc)}.strct-mt__caption--success{color:var(--success)}.strct-mt__caption--warning{color:var(--warning)}.strct-mt__caption--critical{color:var(--critical)}.strct-mt__spark{margin-top:2px;line-height:0}.strct-mt__spark strct-sparkline,.strct-mt__spark .strct-spark__svg{width:100%}\n"] }]
20319
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], captionStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionStatus", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], navigate: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigate", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }], delta: [{ type: i0.Input, args: [{ isSignal: true, alias: "delta", required: false }] }], deltaSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "deltaSuffix", required: false }] }], deltaAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "deltaAriaLabel", required: false }] }], invertDelta: [{ type: i0.Input, args: [{ isSignal: true, alias: "invertDelta", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
19896
20320
 
19897
20321
  let heroCounter = 0;
19898
20322
  /** Default leading icon per status, when `icon` is not supplied. */
@@ -24089,7 +24513,7 @@ class StrctLiveIndicator {
24089
24513
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.4", type: StrctLiveIndicator, isStandalone: true, selector: "strct-live-indicator", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: true, isRequired: false, transformFunction: null }, updatedAt: { classPropertyName: "updatedAt", publicName: "updatedAt", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status", "aria-live": "polite" }, properties: { "attr.data-state": "state()" }, classAttribute: "strct-live" }, ngImport: i0, template: `
24090
24514
  <strct-status-dot size="sm" [status]="tone()" [pulse]="pulsing()" [label]="text()" />
24091
24515
  <span class="strct-live__text">{{ text() }}</span>
24092
- `, isInline: true, styles: [".strct-live{display:inline-flex;align-items:center;gap:6px;font-size:var(--text-sm);color:var(--t3)}.strct-live[data-state=reconnecting] .strct-live__text,.strct-live[data-state=stale] .strct-live__text{color:var(--warning)}.strct-live .strct-dot__sr{display:none}\n"], dependencies: [{ kind: "component", type: StrctStatusDot, selector: "strct-status-dot", inputs: ["status", "label", "size", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24516
+ `, isInline: true, styles: [".strct-live{display:inline-flex;align-items:center;gap:6px;font-size:var(--text-sm);color:var(--t3)}.strct-live[data-state=reconnecting] .strct-live__text,.strct-live[data-state=stale] .strct-live__text{color:var(--warning)}.strct-live .strct-dot__sr{display:none}\n"], dependencies: [{ kind: "component", type: StrctStatusDot, selector: "strct-status-dot", inputs: ["status", "label", "size", "pulse", "variant"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
24093
24517
  }
24094
24518
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctLiveIndicator, decorators: [{
24095
24519
  type: Component,
@@ -25193,6 +25617,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
25193
25617
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], restoreLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreLabel", 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"] }] } });
25194
25618
 
25195
25619
  /** A card the message carries — an action to approve, a result to read. */
25620
+ /** A quiet row under the bubble — copy, a status, a fold. */
25621
+ class StrctChatMessageActions {
25622
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatMessageActions, deps: [], target: i0.ɵɵFactoryTarget.Directive });
25623
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctChatMessageActions, isStandalone: true, selector: "[strctChatMessageActions]", ngImport: i0 });
25624
+ }
25625
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatMessageActions, decorators: [{
25626
+ type: Directive,
25627
+ args: [{ selector: '[strctChatMessageActions]' }]
25628
+ }] });
25196
25629
  class StrctChatAttachment {
25197
25630
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatAttachment, deps: [], target: i0.ɵɵFactoryTarget.Directive });
25198
25631
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctChatAttachment, isStandalone: true, selector: "[strctChatAttachment]", host: { classAttribute: "strct-chat__attachment" }, ngImport: i0 });
@@ -25361,8 +25794,14 @@ class StrctChatMessage {
25361
25794
  }
25362
25795
  </div>
25363
25796
  <ng-content select="[strctChatAttachment]" />
25797
+ <!-- Copy, a status ("Stopped", "Model call failed"), a quiet "Used 3
25798
+ tools" fold. It was going into the attachment slot, which the
25799
+ library documents as a card the message carries. -->
25800
+ <div class="strct-msg__actions">
25801
+ <ng-content select="[strctChatMessageActions]" />
25802
+ </div>
25364
25803
  </div>
25365
- `, isInline: true, styles: [".strct-msg{display:flex;align-items:flex-start;gap:var(--space-2);min-width:0}.strct-msg[data-author=user]{flex-direction:row-reverse}.strct-msg[data-author=system]{justify-content:center}.strct-msg__avatar{flex:none}.strct-msg__body{display:flex;flex-direction:column;gap:4px;min-width:0;max-width:80%}.strct-msg[data-author=user] .strct-msg__body{align-items:flex-end}.strct-msg__meta{display:flex;align-items:baseline;gap:6px;font-size:var(--text-sm);color:var(--t3)}.strct-msg__name{font-weight:600}.strct-msg__bubble{padding:var(--space-2) var(--space-3);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);color:var(--t1);font-size:13px;line-height:1.5;min-width:0;overflow-wrap:anywhere}.strct-msg[data-author=user] .strct-msg__bubble{background:var(--acc-s);border-color:var(--acc30)}.strct-msg[data-author=system] .strct-msg__bubble{border:0;background:none;color:var(--t3);font-size:var(--text-sm);text-align:center}.strct-msg__caret{display:inline-block;width:2px;height:1em;margin-inline-start:2px;vertical-align:text-bottom;background:var(--acc);animation:strct-chat-caret 1s steps(2,start) infinite}@keyframes strct-chat-caret{to{opacity:0}}@media(prefers-reduced-motion:reduce){.strct-msg__caret{animation:none}}.strct-chat__attachment{display:block;margin-block-start:4px}\n"], dependencies: [{ kind: "component", type: StrctAvatar, selector: "strct-avatar", inputs: ["icon", "shape", "tone", "src", "name", "size", "status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
25804
+ `, isInline: true, styles: [".strct-msg{display:flex;align-items:flex-start;gap:var(--space-2);min-width:0}.strct-msg[data-author=user]{flex-direction:row-reverse}.strct-msg[data-author=system]{justify-content:center}.strct-msg__avatar{flex:none}.strct-msg__body{display:flex;flex-direction:column;gap:4px;min-width:0;max-width:80%}.strct-msg[data-author=user] .strct-msg__body{align-items:flex-end}.strct-msg__meta{display:flex;align-items:baseline;gap:6px;font-size:var(--text-sm);color:var(--t3)}.strct-msg__name{font-weight:600}.strct-msg__actions:empty{display:none}.strct-msg__actions{display:flex;align-items:center;gap:var(--space-2);margin-block-start:4px;font-size:var(--text-sm);color:var(--t3)}.strct-msg__bubble{padding:var(--space-2) var(--space-3);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);color:var(--t1);font-size:13px;line-height:1.5;min-width:0;overflow-wrap:anywhere}.strct-msg[data-author=user] .strct-msg__bubble{background:var(--acc-s);border-color:var(--acc30)}.strct-msg[data-author=system] .strct-msg__bubble{border:0;background:none;color:var(--t3);font-size:var(--text-sm);text-align:center}.strct-msg__caret{display:inline-block;width:2px;height:1em;margin-inline-start:2px;vertical-align:text-bottom;background:var(--acc);animation:strct-chat-caret 1s steps(2,start) infinite}@keyframes strct-chat-caret{to{opacity:0}}@media(prefers-reduced-motion:reduce){.strct-msg__caret{animation:none}}.strct-chat__attachment{display:block;margin-block-start:4px}\n"], dependencies: [{ kind: "component", type: StrctAvatar, selector: "strct-avatar", inputs: ["icon", "shape", "tone", "src", "name", "size", "status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
25366
25805
  }
25367
25806
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatMessage, decorators: [{
25368
25807
  type: Component,
@@ -25394,6 +25833,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
25394
25833
  }
25395
25834
  </div>
25396
25835
  <ng-content select="[strctChatAttachment]" />
25836
+ <!-- Copy, a status ("Stopped", "Model call failed"), a quiet "Used 3
25837
+ tools" fold. It was going into the attachment slot, which the
25838
+ library documents as a card the message carries. -->
25839
+ <div class="strct-msg__actions">
25840
+ <ng-content select="[strctChatMessageActions]" />
25841
+ </div>
25397
25842
  </div>
25398
25843
  `, host: {
25399
25844
  class: 'strct-msg',
@@ -25402,7 +25847,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
25402
25847
  '[attr.aria-label]': 'displayName()',
25403
25848
  // A streaming reply is announced when it finishes, not token by token.
25404
25849
  '[attr.aria-busy]': 'streaming() ? "true" : null',
25405
- }, styles: [".strct-msg{display:flex;align-items:flex-start;gap:var(--space-2);min-width:0}.strct-msg[data-author=user]{flex-direction:row-reverse}.strct-msg[data-author=system]{justify-content:center}.strct-msg__avatar{flex:none}.strct-msg__body{display:flex;flex-direction:column;gap:4px;min-width:0;max-width:80%}.strct-msg[data-author=user] .strct-msg__body{align-items:flex-end}.strct-msg__meta{display:flex;align-items:baseline;gap:6px;font-size:var(--text-sm);color:var(--t3)}.strct-msg__name{font-weight:600}.strct-msg__bubble{padding:var(--space-2) var(--space-3);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);color:var(--t1);font-size:13px;line-height:1.5;min-width:0;overflow-wrap:anywhere}.strct-msg[data-author=user] .strct-msg__bubble{background:var(--acc-s);border-color:var(--acc30)}.strct-msg[data-author=system] .strct-msg__bubble{border:0;background:none;color:var(--t3);font-size:var(--text-sm);text-align:center}.strct-msg__caret{display:inline-block;width:2px;height:1em;margin-inline-start:2px;vertical-align:text-bottom;background:var(--acc);animation:strct-chat-caret 1s steps(2,start) infinite}@keyframes strct-chat-caret{to{opacity:0}}@media(prefers-reduced-motion:reduce){.strct-msg__caret{animation:none}}.strct-chat__attachment{display:block;margin-block-start:4px}\n"] }]
25850
+ }, styles: [".strct-msg{display:flex;align-items:flex-start;gap:var(--space-2);min-width:0}.strct-msg[data-author=user]{flex-direction:row-reverse}.strct-msg[data-author=system]{justify-content:center}.strct-msg__avatar{flex:none}.strct-msg__body{display:flex;flex-direction:column;gap:4px;min-width:0;max-width:80%}.strct-msg[data-author=user] .strct-msg__body{align-items:flex-end}.strct-msg__meta{display:flex;align-items:baseline;gap:6px;font-size:var(--text-sm);color:var(--t3)}.strct-msg__name{font-weight:600}.strct-msg__actions:empty{display:none}.strct-msg__actions{display:flex;align-items:center;gap:var(--space-2);margin-block-start:4px;font-size:var(--text-sm);color:var(--t3)}.strct-msg__bubble{padding:var(--space-2) var(--space-3);border:1px solid var(--b2);border-radius:var(--radius-lg);background:var(--bg-2);color:var(--t1);font-size:13px;line-height:1.5;min-width:0;overflow-wrap:anywhere}.strct-msg[data-author=user] .strct-msg__bubble{background:var(--acc-s);border-color:var(--acc30)}.strct-msg[data-author=system] .strct-msg__bubble{border:0;background:none;color:var(--t3);font-size:var(--text-sm);text-align:center}.strct-msg__caret{display:inline-block;width:2px;height:1em;margin-inline-start:2px;vertical-align:text-bottom;background:var(--acc);animation:strct-chat-caret 1s steps(2,start) infinite}@keyframes strct-chat-caret{to{opacity:0}}@media(prefers-reduced-motion:reduce){.strct-msg__caret{animation:none}}.strct-chat__attachment{display:block;margin-block-start:4px}\n"] }]
25406
25851
  }], propDecorators: { author: [{ type: i0.Input, args: [{ isSignal: true, alias: "author", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], avatarIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarIcon", required: false }] }], streaming: [{ type: i0.Input, args: [{ isSignal: true, alias: "streaming", required: false }] }], time: [{ type: i0.Input, args: [{ isSignal: true, alias: "time", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], authorNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "authorNames", required: false }] }] } });
25407
25852
  /**
25408
25853
  * The box the user writes in: it grows with the text up to `maxRows`, sends on
@@ -25426,6 +25871,17 @@ class StrctChatComposer {
25426
25871
  * while a reply is still streaming. `disabled` stops the typing as well.
25427
25872
  */
25428
25873
  sendDisabled = input(false, { ...(ngDevMode ? { debugName: "sendDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
25874
+ /**
25875
+ * A reply is streaming: the one button becomes Stop, where every chat the
25876
+ * operators know puts it. It is enabled whatever the draft holds, and Enter
25877
+ * still never sends — the draft stays editable meanwhile.
25878
+ */
25879
+ busy = input(false, { ...(ngDevMode ? { debugName: "busy" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
25880
+ /** What the Stop button is called. */
25881
+ stopLabel = input('Stop', /* @ts-ignore */
25882
+ ...(ngDevMode ? [{ debugName: "stopLabel" }] : /* istanbul ignore next */ []));
25883
+ /** The reader asked for the reply to stop. */
25884
+ stop = output();
25429
25885
  /** How tall the box grows before it scrolls. */
25430
25886
  maxRows = input(8, /* @ts-ignore */
25431
25887
  ...(ngDevMode ? [{ debugName: "maxRows" }] : /* istanbul ignore next */ []));
@@ -25458,7 +25914,7 @@ class StrctChatComposer {
25458
25914
  }
25459
25915
  submit() {
25460
25916
  const text = this.value().trim();
25461
- if (!text || this.disabled() || this.sendDisabled())
25917
+ if (!text || this.disabled() || this.sendDisabled() || this.busy())
25462
25918
  return;
25463
25919
  this.send.emit(text);
25464
25920
  this.value.set('');
@@ -25470,7 +25926,7 @@ class StrctChatComposer {
25470
25926
  }
25471
25927
  }
25472
25928
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatComposer, deps: [], target: i0.ɵɵFactoryTarget.Component });
25473
- 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: `
25929
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.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 }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, stopLabel: { classPropertyName: "stopLabel", publicName: "stopLabel", 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", stop: "stop", send: "send" }, host: { classAttribute: "strct-composer" }, ngImport: i0, template: `
25474
25930
  <label class="strct-composer__label" [attr.for]="inputId">{{ label() }}</label>
25475
25931
  <div class="strct-composer__box">
25476
25932
  <textarea
@@ -25489,14 +25945,19 @@ class StrctChatComposer {
25489
25945
  <button
25490
25946
  type="button"
25491
25947
  class="strct-composer__send"
25492
- [attr.aria-label]="sendLabel()"
25493
- [disabled]="disabled() || sendDisabled() || !value().trim()"
25494
- (click)="submit()"
25948
+ [class.strct-composer__send--stop]="busy()"
25949
+ [attr.aria-label]="busy() ? stopLabel() : sendLabel()"
25950
+ [disabled]="busy() ? disabled() : disabled() || sendDisabled() || !value().trim()"
25951
+ (click)="busy() ? stop.emit() : submit()"
25495
25952
  >
25496
- <strct-icon strictName="arrowUp" [size]="15" [strokeWidth]="1.8" />
25953
+ @if (busy()) {
25954
+ <span class="strct-composer__stopmark" aria-hidden="true"></span>
25955
+ } @else {
25956
+ <strct-icon strictName="arrowUp" [size]="15" [strokeWidth]="1.8" />
25957
+ }
25497
25958
  </button>
25498
25959
  </div>
25499
- `, isInline: true, 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"], 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 });
25960
+ `, isInline: true, 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__stopmark{width:10px;height:10px;border-radius:2px;background:currentColor}.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"], 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 });
25500
25961
  }
25501
25962
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctChatComposer, decorators: [{
25502
25963
  type: Component,
@@ -25519,15 +25980,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
25519
25980
  <button
25520
25981
  type="button"
25521
25982
  class="strct-composer__send"
25522
- [attr.aria-label]="sendLabel()"
25523
- [disabled]="disabled() || sendDisabled() || !value().trim()"
25524
- (click)="submit()"
25983
+ [class.strct-composer__send--stop]="busy()"
25984
+ [attr.aria-label]="busy() ? stopLabel() : sendLabel()"
25985
+ [disabled]="busy() ? disabled() : disabled() || sendDisabled() || !value().trim()"
25986
+ (click)="busy() ? stop.emit() : submit()"
25525
25987
  >
25526
- <strct-icon strictName="arrowUp" [size]="15" [strokeWidth]="1.8" />
25988
+ @if (busy()) {
25989
+ <span class="strct-composer__stopmark" aria-hidden="true"></span>
25990
+ } @else {
25991
+ <strct-icon strictName="arrowUp" [size]="15" [strokeWidth]="1.8" />
25992
+ }
25527
25993
  </button>
25528
25994
  </div>
25529
- `, 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"] }]
25530
- }], 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"] }] } });
25995
+ `, 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__stopmark{width:10px;height:10px;border-radius:2px;background:currentColor}.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"] }]
25996
+ }], 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 }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], stopLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "stopLabel", required: false }] }], stop: [{ type: i0.Output, args: ["stop"] }], 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"] }] } });
25531
25997
  let composerCounter = 0;
25532
25998
 
25533
25999
  /**
@@ -26355,7 +26821,7 @@ class StrctConfirmOutlet {
26355
26821
  </ng-container>
26356
26822
  }
26357
26823
  </strct-modal>
26358
- `, isInline: true, styles: [".strct-confirm__message{margin:0;color:var(--t2)}\n"], dependencies: [{ kind: "component", type: StrctModal, selector: "strct-modal", inputs: ["open", "title", "size", "hideFooter", "chromeless", "closeLabel", "dismissible", "draggable", "panelClass", "backdropClass", "variant"], outputs: ["openChange", "closed"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
26824
+ `, isInline: true, styles: [".strct-confirm__message{margin:0;color:var(--t2)}\n"], dependencies: [{ kind: "component", type: StrctModal, selector: "strct-modal", inputs: ["open", "title", "size", "hideFooter", "chromeless", "closeLabel", "dismissible", "closeOnEscape", "closeOnBackdrop", "draggable", "panelClass", "backdropClass", "variant"], outputs: ["openChange", "closed"] }, { kind: "component", type: StrctButton, selector: "button[strct-button], a[strct-button]", inputs: ["variant", "size", "solid", "block", "iconOnly"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
26359
26825
  }
26360
26826
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctConfirmOutlet, decorators: [{
26361
26827
  type: Component,
@@ -27945,6 +28411,1035 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
27945
28411
  `, host: { class: 'strct-heatmap' }, styles: [".strct-heatmap{display:block}.strct-heatmap__svg{width:100%;display:block}.strct-heatmap__empty{display:flex;align-items:center;justify-content:center;min-height:60px;font-size:12px;color:var(--t3)}.strct-heatmap__label{fill:var(--t3);font-size:10px}.strct-heatmap__label--row{font-family:var(--font)}.strct-heatmap__label--col{font-family:var(--mono);font-variant-numeric:tabular-nums}.strct-heatmap__cell{stroke:var(--bg-1);stroke-width:1}@media(prefers-reduced-motion:no-preference){.strct-heatmap__cell{transition:opacity .12s ease}}.strct-heatmap__cell:hover{opacity:.75}\n"] }]
27946
28412
  }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], cols: [{ type: i0.Input, args: [{ isSignal: true, alias: "cols", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], colLabelEvery: [{ type: i0.Input, args: [{ isSignal: true, alias: "colLabelEvery", required: false }] }], colLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "colLabel", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }], thresholds: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholds", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], summaryFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryFormat", required: false }] }], cellHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellHeight", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], rowLabelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowLabelWidth", required: false }] }] } });
27947
28413
 
28414
+ /**
28415
+ * A Markdown reader that produces plain objects — never HTML.
28416
+ *
28417
+ * A model's reply is Markdown, and an app that reaches for a Markdown library
28418
+ * ends up handing the browser a string of HTML (`innerHTML` plus a sanitiser),
28419
+ * which a sealed, reviewed build cannot accept. This reader returns a tree the
28420
+ * templates draw with ordinary bindings, so every word reaches the page as a
28421
+ * text node and raw HTML is shown as the characters it is.
28422
+ *
28423
+ * It is deliberately a subset of CommonMark + GFM: paragraphs, ATX headings,
28424
+ * fenced code, lists (nested), block quotes, thematic breaks, tables with
28425
+ * alignment, and inline emphasis / strong / strikethrough / code / links /
28426
+ * autolinks. Everything else is text.
28427
+ *
28428
+ * Every loop is bounded, because the input is a remote model's output.
28429
+ */
28430
+ /** Hard limits, so hostile input costs a known amount of work. */
28431
+ const STRCT_MD_LIMITS = {
28432
+ /** Characters of source read at all. */
28433
+ source: 256 * 1024,
28434
+ /** Lines read at all. */
28435
+ lines: 20000,
28436
+ /** How deep lists and quotes may nest. */
28437
+ depth: 8,
28438
+ /** Inline delimiter runs considered per text span. */
28439
+ delimiters: 2000,
28440
+ };
28441
+ const RULE = /^ {0,3}((\*\s*){3,}|(-\s*){3,}|(_\s*){3,})$/;
28442
+ const ATX = /^ {0,3}(#{1,6})\s+(.*?)\s*#*\s*$/;
28443
+ const FENCE = /^ {0,3}(`{3,}|~{3,})\s*([^`]*)$/;
28444
+ const UL = /^(\s*)([-*+])\s+(.*)$/;
28445
+ const OL = /^(\s*)(\d{1,9})[.)]\s+(.*)$/;
28446
+ const QUOTE = /^ {0,3}>\s?(.*)$/;
28447
+ const TABLE_DELIM = /^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/;
28448
+ /**
28449
+ * Read Markdown into blocks.
28450
+ *
28451
+ * `streaming` says the source may be cut mid-token: an unterminated fence is
28452
+ * still a code block, so a reply that streams code looks like code from its
28453
+ * first line rather than flashing as a paragraph and then becoming one.
28454
+ */
28455
+ function strctParseMarkdown(source, options = {}) {
28456
+ const text = source.length > STRCT_MD_LIMITS.source ? source.slice(0, STRCT_MD_LIMITS.source) : source;
28457
+ const lines = text.replace(/\r\n?/g, '\n').split('\n').slice(0, STRCT_MD_LIMITS.lines);
28458
+ return parseBlocks(lines, 0, options);
28459
+ }
28460
+ function parseBlocks(lines, depth, options) {
28461
+ const out = [];
28462
+ let i = 0;
28463
+ const paragraph = [];
28464
+ const flushParagraph = () => {
28465
+ if (!paragraph.length)
28466
+ return;
28467
+ out.push({ kind: 'p', inlines: parseInlines(paragraph.join('\n'), options) });
28468
+ paragraph.length = 0;
28469
+ };
28470
+ while (i < lines.length) {
28471
+ const line = lines[i];
28472
+ // Blank line: ends a paragraph, nothing else.
28473
+ if (!line.trim()) {
28474
+ flushParagraph();
28475
+ i++;
28476
+ continue;
28477
+ }
28478
+ // Fenced code. An unclosed fence is still code while streaming.
28479
+ const fence = FENCE.exec(line);
28480
+ if (fence) {
28481
+ flushParagraph();
28482
+ const marker = fence[1][0];
28483
+ const width = fence[1].length;
28484
+ const lang = fence[2].trim();
28485
+ const body = [];
28486
+ let closed = false;
28487
+ i++;
28488
+ while (i < lines.length) {
28489
+ const candidate = lines[i];
28490
+ const end = new RegExp(`^ {0,3}${marker === '`' ? '`' : '~'}{${width},}\\s*$`).test(candidate);
28491
+ if (end) {
28492
+ closed = true;
28493
+ i++;
28494
+ break;
28495
+ }
28496
+ body.push(candidate);
28497
+ i++;
28498
+ }
28499
+ out.push({ kind: 'code', text: body.join('\n'), lang, closed });
28500
+ continue;
28501
+ }
28502
+ // Thematic break.
28503
+ if (RULE.test(line)) {
28504
+ flushParagraph();
28505
+ out.push({ kind: 'rule' });
28506
+ i++;
28507
+ continue;
28508
+ }
28509
+ // ATX heading.
28510
+ const atx = ATX.exec(line);
28511
+ if (atx) {
28512
+ flushParagraph();
28513
+ out.push({
28514
+ kind: 'heading',
28515
+ level: atx[1].length,
28516
+ inlines: parseInlines(atx[2], options),
28517
+ });
28518
+ i++;
28519
+ continue;
28520
+ }
28521
+ // Block quote: take the run of quoted lines and read them as blocks.
28522
+ const quote = QUOTE.exec(line);
28523
+ if (quote && depth < STRCT_MD_LIMITS.depth) {
28524
+ flushParagraph();
28525
+ const inner = [];
28526
+ while (i < lines.length) {
28527
+ const m = QUOTE.exec(lines[i]);
28528
+ if (m) {
28529
+ inner.push(m[1]);
28530
+ i++;
28531
+ }
28532
+ else if (lines[i].trim() && inner.length) {
28533
+ // A lazy continuation line belongs to the quote's last paragraph.
28534
+ inner.push(lines[i]);
28535
+ i++;
28536
+ }
28537
+ else
28538
+ break;
28539
+ }
28540
+ out.push({ kind: 'quote', blocks: parseBlocks(inner, depth + 1, options) });
28541
+ continue;
28542
+ }
28543
+ // Table: a header row followed by a delimiter row.
28544
+ if (line.includes('|') && i + 1 < lines.length && TABLE_DELIM.test(lines[i + 1])) {
28545
+ flushParagraph();
28546
+ const head = splitRow(lines[i]).map((c) => parseInlines(c, options));
28547
+ const align = splitRow(lines[i + 1]).map(toAlign);
28548
+ const rows = [];
28549
+ i += 2;
28550
+ while (i < lines.length && lines[i].includes('|') && lines[i].trim()) {
28551
+ rows.push(splitRow(lines[i]).map((c) => parseInlines(c, options)));
28552
+ i++;
28553
+ }
28554
+ out.push({ kind: 'table', head, align, rows });
28555
+ continue;
28556
+ }
28557
+ // Lists.
28558
+ const item = UL.exec(line) ?? OL.exec(line);
28559
+ if (item && depth < STRCT_MD_LIMITS.depth) {
28560
+ flushParagraph();
28561
+ const ordered = !UL.test(line);
28562
+ const start = ordered ? Number(OL.exec(line)[2]) : 1;
28563
+ const items = [];
28564
+ const baseIndent = item[1].length;
28565
+ while (i < lines.length) {
28566
+ const m = UL.exec(lines[i]) ?? OL.exec(lines[i]);
28567
+ const sameKind = m && !UL.test(lines[i]) === ordered;
28568
+ if (!m || !sameKind || m[1].length < baseIndent)
28569
+ break;
28570
+ if (m[1].length > baseIndent)
28571
+ break; // a deeper list is the item's own
28572
+ const buffer = [m[3]];
28573
+ i++;
28574
+ // Continuation lines: anything indented past the marker, and blanks
28575
+ // between them, belong to this item.
28576
+ while (i < lines.length) {
28577
+ const next = lines[i];
28578
+ if (!next.trim()) {
28579
+ const after = lines[i + 1] ?? '';
28580
+ if (after.trim() && /^\s{2,}/.test(after)) {
28581
+ buffer.push('');
28582
+ i++;
28583
+ continue;
28584
+ }
28585
+ break;
28586
+ }
28587
+ if (/^\s{2,}/.test(next) && !UL.test(next.slice(baseIndent)) === false) {
28588
+ buffer.push(next.slice(Math.min(baseIndent + 2, next.length - next.trimStart().length)));
28589
+ i++;
28590
+ continue;
28591
+ }
28592
+ if (/^\s{2,}/.test(next)) {
28593
+ buffer.push(next.trimStart());
28594
+ i++;
28595
+ continue;
28596
+ }
28597
+ break;
28598
+ }
28599
+ items.push(parseBlocks(buffer, depth + 1, options));
28600
+ }
28601
+ out.push({ kind: 'list', ordered, start, items });
28602
+ continue;
28603
+ }
28604
+ paragraph.push(line);
28605
+ i++;
28606
+ }
28607
+ flushParagraph();
28608
+ return out;
28609
+ }
28610
+ function splitRow(line) {
28611
+ const trimmed = line.trim().replace(/^\|/, '').replace(/\|$/, '');
28612
+ const cells = [];
28613
+ let cur = '';
28614
+ for (let i = 0; i < trimmed.length; i++) {
28615
+ const ch = trimmed[i];
28616
+ if (ch === '\\' && trimmed[i + 1] === '|') {
28617
+ cur += '|';
28618
+ i++;
28619
+ continue;
28620
+ }
28621
+ if (ch === '|') {
28622
+ cells.push(cur.trim());
28623
+ cur = '';
28624
+ continue;
28625
+ }
28626
+ cur += ch;
28627
+ }
28628
+ cells.push(cur.trim());
28629
+ return cells;
28630
+ }
28631
+ function toAlign(cell) {
28632
+ const c = cell.trim();
28633
+ const left = c.startsWith(':');
28634
+ const right = c.endsWith(':');
28635
+ if (left && right)
28636
+ return 'center';
28637
+ if (right)
28638
+ return 'end';
28639
+ if (left)
28640
+ return 'start';
28641
+ return null;
28642
+ }
28643
+ /**
28644
+ * Inline reading. Code spans win over everything (their content is literal),
28645
+ * then links, then the emphasis delimiters — each bounded.
28646
+ */
28647
+ function parseInlines(source, options = {}) {
28648
+ const out = [];
28649
+ let buf = '';
28650
+ let i = 0;
28651
+ let budget = STRCT_MD_LIMITS.delimiters;
28652
+ const flush = () => {
28653
+ if (!buf)
28654
+ return;
28655
+ out.push(...applyTokens(buf, options.tokenize));
28656
+ buf = '';
28657
+ };
28658
+ while (i < source.length) {
28659
+ const ch = source[i];
28660
+ // A backslash escapes the next punctuation character.
28661
+ if (ch === '\\' && i + 1 < source.length && /[\\`*_{}[\]()#+\-.!|~>]/.test(source[i + 1])) {
28662
+ buf += source[i + 1];
28663
+ i += 2;
28664
+ continue;
28665
+ }
28666
+ // Code span: the longest run of backticks closes it.
28667
+ if (ch === '`') {
28668
+ const run = /^`+/.exec(source.slice(i))[0];
28669
+ const close = source.indexOf(run, i + run.length);
28670
+ if (close !== -1) {
28671
+ flush();
28672
+ out.push({ kind: 'code', text: source.slice(i + run.length, close).trim() });
28673
+ i = close + run.length;
28674
+ continue;
28675
+ }
28676
+ }
28677
+ // Hard break: two spaces at the end of a line, or a backslash.
28678
+ if (ch === '\n') {
28679
+ const hard = buf.endsWith(' ') || buf.endsWith('\\');
28680
+ buf = buf.replace(/( {2,}|\\)$/, '');
28681
+ flush();
28682
+ out.push(hard ? { kind: 'break' } : { kind: 'text', text: ' ' });
28683
+ i++;
28684
+ continue;
28685
+ }
28686
+ // Autolink.
28687
+ if (ch === '<') {
28688
+ const auto = /^<((?:https?:\/\/|mailto:)[^ >]+)>/.exec(source.slice(i));
28689
+ if (auto) {
28690
+ flush();
28691
+ out.push({ kind: 'link', href: auto[1], children: [{ kind: 'text', text: auto[1] }] });
28692
+ i += auto[0].length;
28693
+ continue;
28694
+ }
28695
+ }
28696
+ // Link. An image is read as a link's text — nothing is ever loaded.
28697
+ if ((ch === '[' || (ch === '!' && source[i + 1] === '[')) && budget-- > 0) {
28698
+ const at = ch === '!' ? i + 1 : i;
28699
+ const close = matchBracket(source, at);
28700
+ if (close !== -1 && source[close + 1] === '(') {
28701
+ const end = source.indexOf(')', close + 2);
28702
+ if (end !== -1) {
28703
+ const label = source.slice(at + 1, close);
28704
+ const href = source
28705
+ .slice(close + 2, end)
28706
+ .trim()
28707
+ .split(/\s+/)[0];
28708
+ flush();
28709
+ if (ch === '!') {
28710
+ // An image's alt text is all a reader gets: no request is made.
28711
+ out.push({ kind: 'text', text: label });
28712
+ }
28713
+ else {
28714
+ out.push({ kind: 'link', href, children: parseInlines(label, options) });
28715
+ }
28716
+ i = end + 1;
28717
+ continue;
28718
+ }
28719
+ }
28720
+ }
28721
+ // Emphasis, strong, strikethrough. A delimiter only opens when something
28722
+ // follows it immediately and only closes when something precedes it —
28723
+ // the flanking rule, which is what keeps "2 * 3 * 4" arithmetic.
28724
+ if ((ch === '*' || ch === '_' || ch === '~') && budget-- > 0) {
28725
+ const run = new RegExp(`^\\${ch}+`).exec(source.slice(i))[0];
28726
+ const len = ch === '~' ? (run.length >= 2 ? 2 : 0) : Math.min(run.length, 2);
28727
+ const opens = !/^\s|^$/.test(source.slice(i + run.length, i + run.length + 1) || '');
28728
+ if (len && opens) {
28729
+ const marker = ch.repeat(len);
28730
+ const close = findCloser(source, marker, i + len);
28731
+ if (close !== -1 && close > i + len) {
28732
+ const inner = source.slice(i + len, close);
28733
+ flush();
28734
+ const children = parseInlines(inner, options);
28735
+ out.push(ch === '~'
28736
+ ? { kind: 'del', children }
28737
+ : len === 2
28738
+ ? { kind: 'strong', children }
28739
+ : { kind: 'em', children });
28740
+ i = close + len;
28741
+ continue;
28742
+ }
28743
+ }
28744
+ }
28745
+ buf += ch;
28746
+ i++;
28747
+ }
28748
+ flush();
28749
+ return out;
28750
+ }
28751
+ /**
28752
+ * The next closing delimiter: one with a non-space before it. An opener with
28753
+ * no such closer is not a delimiter at all, it is the character written.
28754
+ */
28755
+ function findCloser(source, marker, from) {
28756
+ let at = source.indexOf(marker, from);
28757
+ while (at !== -1) {
28758
+ const before = source[at - 1];
28759
+ if (before && !/\s/.test(before))
28760
+ return at;
28761
+ at = source.indexOf(marker, at + marker.length);
28762
+ }
28763
+ return -1;
28764
+ }
28765
+ /** The index of the `]` matching the `[` at `from`, or -1. */
28766
+ function matchBracket(source, from) {
28767
+ let depth = 0;
28768
+ for (let i = from; i < source.length; i++) {
28769
+ if (source[i] === '\\') {
28770
+ i++;
28771
+ continue;
28772
+ }
28773
+ if (source[i] === '[')
28774
+ depth++;
28775
+ else if (source[i] === ']') {
28776
+ depth--;
28777
+ if (!depth)
28778
+ return i;
28779
+ }
28780
+ }
28781
+ return -1;
28782
+ }
28783
+ /** Hand a run of plain text to the consumer's tokenizer, if it gave one. */
28784
+ function applyTokens(text, tokenize) {
28785
+ if (!tokenize)
28786
+ return [{ kind: 'text', text }];
28787
+ let found;
28788
+ try {
28789
+ found = tokenize(text) ?? [];
28790
+ }
28791
+ catch {
28792
+ return [{ kind: 'text', text }];
28793
+ }
28794
+ const valid = found
28795
+ .filter((t) => t && t.length > 0 && t.start >= 0 && t.start + t.length <= text.length)
28796
+ .sort((a, b) => a.start - b.start);
28797
+ const out = [];
28798
+ let at = 0;
28799
+ for (const t of valid) {
28800
+ if (t.start < at)
28801
+ continue; // overlapping claims are dropped
28802
+ if (t.start > at)
28803
+ out.push({ kind: 'text', text: text.slice(at, t.start) });
28804
+ out.push({
28805
+ kind: 'token',
28806
+ token: t.token,
28807
+ text: text.slice(t.start, t.start + t.length),
28808
+ data: t.data,
28809
+ });
28810
+ at = t.start + t.length;
28811
+ }
28812
+ if (at < text.length)
28813
+ out.push({ kind: 'text', text: text.slice(at) });
28814
+ return out.length ? out : [{ kind: 'text', text }];
28815
+ }
28816
+ /**
28817
+ * What a link may do. Anything that is not plainly safe stays the text the
28818
+ * model wrote: `javascript:`, `data:`, a protocol-relative `//host`, or
28819
+ * anything this does not recognise.
28820
+ */
28821
+ function strctClassifyHref(href) {
28822
+ const raw = (href ?? '').trim();
28823
+ if (!raw)
28824
+ return null;
28825
+ // Control characters and whitespace inside a URL are a smuggling trick.
28826
+ if (/[\u0000-\u001f\u007f\s]/.test(raw))
28827
+ return null;
28828
+ if (/^https?:\/\/[^/]/i.test(raw))
28829
+ return 'external';
28830
+ if (/^mailto:[^@\s]+@[^@\s]+$/i.test(raw))
28831
+ return 'external';
28832
+ if (raw.startsWith('//'))
28833
+ return null;
28834
+ if (raw.startsWith('/'))
28835
+ return 'internal';
28836
+ return null;
28837
+ }
28838
+
28839
+ /**
28840
+ * A template for a span the consumer claimed through `tokens`, keyed by the
28841
+ * token's kind:
28842
+ *
28843
+ * <ng-template strctMarkdownToken="object" let-text let-data="data">
28844
+ * <strct-tag [href]="data.url">{{ text }}</strct-tag>
28845
+ * </ng-template>
28846
+ */
28847
+ class StrctMarkdownToken {
28848
+ /** Which token kind this template draws. */
28849
+ strctMarkdownToken = input('', /* @ts-ignore */
28850
+ ...(ngDevMode ? [{ debugName: "strctMarkdownToken" }] : /* istanbul ignore next */ []));
28851
+ template = inject(TemplateRef);
28852
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMarkdownToken, deps: [], target: i0.ɵɵFactoryTarget.Directive });
28853
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.4", type: StrctMarkdownToken, isStandalone: true, selector: "ng-template[strctMarkdownToken]", inputs: { strctMarkdownToken: { classPropertyName: "strctMarkdownToken", publicName: "strctMarkdownToken", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
28854
+ }
28855
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMarkdownToken, decorators: [{
28856
+ type: Directive,
28857
+ args: [{ selector: 'ng-template[strctMarkdownToken]' }]
28858
+ }], propDecorators: { strctMarkdownToken: [{ type: i0.Input, args: [{ isSignal: true, alias: "strctMarkdownToken", required: false }] }] } });
28859
+ /**
28860
+ * Markdown as a tree of components, never as HTML.
28861
+ *
28862
+ * <strct-markdown [source]="reply()" [streaming]="busy()" />
28863
+ *
28864
+ * A model's reply is Markdown: drawn as plain text it leaves tables as rows of
28865
+ * pipes and `**` everywhere, and an app that reaches for a Markdown library
28866
+ * ends up handing the browser HTML — `innerHTML` plus a sanitiser — which a
28867
+ * sealed, reviewed build cannot accept.
28868
+ *
28869
+ * Every word reaches the page as a text node. Raw HTML is shown as the
28870
+ * characters it is. Images are never loaded: an image's alt text is all a
28871
+ * reader gets. A link opens in a new tab only when it is plainly http(s);
28872
+ * an in-app path is handed to `(navigate)`; anything else — `javascript:`,
28873
+ * `data:`, `//host` — stays the text the model wrote.
28874
+ */
28875
+ class StrctMarkdown {
28876
+ /** The Markdown to read. */
28877
+ source = input('', /* @ts-ignore */
28878
+ ...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
28879
+ /**
28880
+ * A tree read elsewhere, instead of `source` — how the component draws the
28881
+ * blocks inside a list item or a quote without re-reading them.
28882
+ */
28883
+ tree = input(null, /* @ts-ignore */
28884
+ ...(ngDevMode ? [{ debugName: "tree" }] : /* istanbul ignore next */ []));
28885
+ /**
28886
+ * The reply is still arriving: an unterminated fence is already a code
28887
+ * block, so streamed code does not flash as a paragraph first, and the
28888
+ * caret sits at the end of the last line.
28889
+ */
28890
+ streaming = input(false, { ...(ngDevMode ? { debugName: "streaming" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
28891
+ /**
28892
+ * How far the model's headings are pulled down. A message is a region
28893
+ * inside a dialog, so `#` should not be the page's `h1`: the default of 2
28894
+ * makes it an `h3`.
28895
+ */
28896
+ headingOffset = input(2, /* @ts-ignore */
28897
+ ...(ngDevMode ? [{ debugName: "headingOffset" }] : /* istanbul ignore next */ []));
28898
+ /**
28899
+ * What a link may do, when the default rule is not what the app wants.
28900
+ * Returning `null` leaves the link as text.
28901
+ */
28902
+ linkPolicy = input(null, /* @ts-ignore */
28903
+ ...(ngDevMode ? [{ debugName: "linkPolicy" }] : /* istanbul ignore next */ []));
28904
+ /** Claim runs of plain text — an inventory id becomes an object chip. */
28905
+ tokens = input(null, /* @ts-ignore */
28906
+ ...(ngDevMode ? [{ debugName: "tokens" }] : /* istanbul ignore next */ []));
28907
+ /** An in-app link was followed; the consumer routes it. */
28908
+ navigate = output();
28909
+ tokenDefs = contentChildren(StrctMarkdownToken, /* @ts-ignore */
28910
+ ...(ngDevMode ? [{ debugName: "tokenDefs" }] : /* istanbul ignore next */ []));
28911
+ blocks = computed(() => {
28912
+ const given = this.tree();
28913
+ if (given)
28914
+ return given;
28915
+ return strctParseMarkdown(this.source(), {
28916
+ streaming: this.streaming(),
28917
+ tokenize: this.tokens() ?? undefined,
28918
+ });
28919
+ }, /* @ts-ignore */
28920
+ ...(ngDevMode ? [{ debugName: "blocks" }] : /* istanbul ignore next */ []));
28921
+ level(level) {
28922
+ return Math.min(6, Math.max(1, level + this.headingOffset()));
28923
+ }
28924
+ hrefKind(href) {
28925
+ const own = this.linkPolicy();
28926
+ return own ? own(href) : strctClassifyHref(href);
28927
+ }
28928
+ tokenTemplate(kind) {
28929
+ return this.tokenDefs().find((d) => d.strctMarkdownToken() === kind)?.template ?? null;
28930
+ }
28931
+ /** The caret belongs to the last block, and only while streaming. */
28932
+ caretOn(index) {
28933
+ return this.streaming() && !this.tree() && index === this.blocks().length - 1;
28934
+ }
28935
+ onInternal(event, href) {
28936
+ // A modified click is the browser's — a new tab, a saved link.
28937
+ const e = event;
28938
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0)
28939
+ return;
28940
+ event.preventDefault();
28941
+ this.navigate.emit(href);
28942
+ }
28943
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMarkdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
28944
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctMarkdown, isStandalone: true, selector: "strct-markdown", inputs: { source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, tree: { classPropertyName: "tree", publicName: "tree", isSignal: true, isRequired: false, transformFunction: null }, streaming: { classPropertyName: "streaming", publicName: "streaming", isSignal: true, isRequired: false, transformFunction: null }, headingOffset: { classPropertyName: "headingOffset", publicName: "headingOffset", isSignal: true, isRequired: false, transformFunction: null }, linkPolicy: { classPropertyName: "linkPolicy", publicName: "linkPolicy", isSignal: true, isRequired: false, transformFunction: null }, tokens: { classPropertyName: "tokens", publicName: "tokens", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navigate: "navigate" }, host: { classAttribute: "strct-md" }, queries: [{ propertyName: "tokenDefs", predicate: StrctMarkdownToken, isSignal: true }], ngImport: i0, template: `
28945
+ @for (block of blocks(); track $index) {
28946
+ @switch (block.kind) {
28947
+ @case ('p') {
28948
+ <p class="strct-md__p">
28949
+ <ng-container
28950
+ [ngTemplateOutlet]="inlineRun"
28951
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
28952
+ />
28953
+ @if (caretOn($index)) {
28954
+ <span class="strct-md__caret" aria-hidden="true"></span>
28955
+ }
28956
+ </p>
28957
+ }
28958
+ @case ('heading') {
28959
+ <!-- A message is a region inside a dialog, so the document's own
28960
+ outline is not the model's to set: the offset pulls them down. -->
28961
+ @switch (level(block.level)) {
28962
+ @case (1) {
28963
+ <h1 class="strct-md__h">
28964
+ <ng-container
28965
+ [ngTemplateOutlet]="inlineRun"
28966
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
28967
+ />
28968
+ </h1>
28969
+ }
28970
+ @case (2) {
28971
+ <h2 class="strct-md__h">
28972
+ <ng-container
28973
+ [ngTemplateOutlet]="inlineRun"
28974
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
28975
+ />
28976
+ </h2>
28977
+ }
28978
+ @case (3) {
28979
+ <h3 class="strct-md__h">
28980
+ <ng-container
28981
+ [ngTemplateOutlet]="inlineRun"
28982
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
28983
+ />
28984
+ </h3>
28985
+ }
28986
+ @case (4) {
28987
+ <h4 class="strct-md__h">
28988
+ <ng-container
28989
+ [ngTemplateOutlet]="inlineRun"
28990
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
28991
+ />
28992
+ </h4>
28993
+ }
28994
+ @case (5) {
28995
+ <h5 class="strct-md__h">
28996
+ <ng-container
28997
+ [ngTemplateOutlet]="inlineRun"
28998
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
28999
+ />
29000
+ </h5>
29001
+ }
29002
+ @default {
29003
+ <h6 class="strct-md__h">
29004
+ <ng-container
29005
+ [ngTemplateOutlet]="inlineRun"
29006
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29007
+ />
29008
+ </h6>
29009
+ }
29010
+ }
29011
+ }
29012
+ @case ('code') {
29013
+ <strct-code class="strct-md__code" [code]="block.text" [language]="block.lang" wrap />
29014
+ }
29015
+ @case ('rule') {
29016
+ <hr class="strct-md__rule" />
29017
+ }
29018
+ @case ('quote') {
29019
+ <blockquote class="strct-md__quote">
29020
+ <ng-container
29021
+ [ngTemplateOutlet]="blockRun"
29022
+ [ngTemplateOutletContext]="{ $implicit: block.blocks }"
29023
+ />
29024
+ </blockquote>
29025
+ }
29026
+ @case ('list') {
29027
+ @if (block.ordered) {
29028
+ <ol class="strct-md__list" [attr.start]="block.start">
29029
+ @for (item of block.items; track $index) {
29030
+ <li>
29031
+ <ng-container
29032
+ [ngTemplateOutlet]="blockRun"
29033
+ [ngTemplateOutletContext]="{ $implicit: item }"
29034
+ />
29035
+ </li>
29036
+ }
29037
+ </ol>
29038
+ } @else {
29039
+ <ul class="strct-md__list">
29040
+ @for (item of block.items; track $index) {
29041
+ <li>
29042
+ <ng-container
29043
+ [ngTemplateOutlet]="blockRun"
29044
+ [ngTemplateOutletContext]="{ $implicit: item }"
29045
+ />
29046
+ </li>
29047
+ }
29048
+ </ul>
29049
+ }
29050
+ }
29051
+ @case ('table') {
29052
+ <div class="strct-md__tablewrap">
29053
+ <table class="strct-md__table">
29054
+ <thead>
29055
+ <tr>
29056
+ @for (cell of block.head; track $index) {
29057
+ <th scope="col" [style.text-align]="block.align[$index] ?? 'start'">
29058
+ <ng-container
29059
+ [ngTemplateOutlet]="inlineRun"
29060
+ [ngTemplateOutletContext]="{ $implicit: cell }"
29061
+ />
29062
+ </th>
29063
+ }
29064
+ </tr>
29065
+ </thead>
29066
+ <tbody>
29067
+ @for (row of block.rows; track $index) {
29068
+ <tr>
29069
+ @for (cell of row; track $index) {
29070
+ <td [style.text-align]="block.align[$index] ?? 'start'">
29071
+ <ng-container
29072
+ [ngTemplateOutlet]="inlineRun"
29073
+ [ngTemplateOutletContext]="{ $implicit: cell }"
29074
+ />
29075
+ </td>
29076
+ }
29077
+ </tr>
29078
+ }
29079
+ </tbody>
29080
+ </table>
29081
+ </div>
29082
+ }
29083
+ }
29084
+ }
29085
+
29086
+ <!-- Blocks inside a list item or a quote. -->
29087
+ <ng-template #blockRun let-blocks>
29088
+ @for (b of blocks; track $index) {
29089
+ <strct-markdown
29090
+ [tree]="[b]"
29091
+ [headingOffset]="headingOffset()"
29092
+ [linkPolicy]="linkPolicy()"
29093
+ (navigate)="navigate.emit($event)"
29094
+ />
29095
+ }
29096
+ </ng-template>
29097
+
29098
+ <!-- One run of inline nodes. -->
29099
+ <ng-template #inlineRun let-inlines>
29100
+ @for (node of inlines; track $index) {
29101
+ @switch (node.kind) {
29102
+ @case ('text') {
29103
+ <ng-container>{{ node.text }}</ng-container>
29104
+ }
29105
+ @case ('code') {
29106
+ <code class="strct-md__codespan">{{ node.text }}</code>
29107
+ }
29108
+ @case ('break') {
29109
+ <br />
29110
+ }
29111
+ @case ('strong') {
29112
+ <strong>
29113
+ <ng-container
29114
+ [ngTemplateOutlet]="inlineRun"
29115
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29116
+ />
29117
+ </strong>
29118
+ }
29119
+ @case ('em') {
29120
+ <em>
29121
+ <ng-container
29122
+ [ngTemplateOutlet]="inlineRun"
29123
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29124
+ />
29125
+ </em>
29126
+ }
29127
+ @case ('del') {
29128
+ <del>
29129
+ <ng-container
29130
+ [ngTemplateOutlet]="inlineRun"
29131
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29132
+ />
29133
+ </del>
29134
+ }
29135
+ @case ('token') {
29136
+ @if (tokenTemplate(node.token); as tpl) {
29137
+ <ng-container
29138
+ [ngTemplateOutlet]="tpl"
29139
+ [ngTemplateOutletContext]="{ $implicit: node.text, data: node.data }"
29140
+ />
29141
+ } @else {
29142
+ <ng-container>{{ node.text }}</ng-container>
29143
+ }
29144
+ }
29145
+ @case ('link') {
29146
+ @switch (hrefKind(node.href)) {
29147
+ @case ('external') {
29148
+ <a
29149
+ class="strct-md__link"
29150
+ [attr.href]="node.href"
29151
+ target="_blank"
29152
+ rel="noopener noreferrer"
29153
+ >
29154
+ <ng-container
29155
+ [ngTemplateOutlet]="inlineRun"
29156
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29157
+ />
29158
+ <strct-icon
29159
+ class="strct-md__ext"
29160
+ strictName="externalLink"
29161
+ [size]="11"
29162
+ aria-hidden="true"
29163
+ />
29164
+ </a>
29165
+ }
29166
+ @case ('internal') {
29167
+ <a
29168
+ class="strct-md__link"
29169
+ [attr.href]="node.href"
29170
+ (click)="onInternal($event, node.href)"
29171
+ >
29172
+ <ng-container
29173
+ [ngTemplateOutlet]="inlineRun"
29174
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29175
+ />
29176
+ </a>
29177
+ }
29178
+ @default {
29179
+ <!-- Not a link we will follow: the characters, as written. -->
29180
+ <ng-container
29181
+ [ngTemplateOutlet]="inlineRun"
29182
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29183
+ />
29184
+ }
29185
+ }
29186
+ }
29187
+ }
29188
+ }
29189
+ </ng-template>
29190
+ `, isInline: true, styles: [".strct-md{display:block;color:var(--t1);font-size:13px;line-height:1.55}.strct-md__p{margin:0 0 var(--space-2)}.strct-md__p:last-child{margin-bottom:0}.strct-md__h{margin:var(--space-3) 0 var(--space-2);font-size:14px;font-weight:600;color:var(--t1)}.strct-md__h:first-child{margin-top:0}.strct-md__list{margin:0 0 var(--space-2);padding-inline-start:20px}.strct-md__list li{margin-block:2px}.strct-md__quote{margin:0 0 var(--space-2);padding-inline-start:var(--space-3);border-inline-start:2px solid var(--b2);color:var(--t2)}.strct-md__rule{border:0;border-block-start:1px solid var(--b1);margin:var(--space-3) 0}.strct-md__codespan{font-family:var(--mono);font-size:.92em;background:var(--bg-2);border-radius:var(--radius-sm);padding:1px 4px}.strct-md__code{margin-block-end:var(--space-2)}.strct-md__link{color:var(--acc)}.strct-md__ext{margin-inline-start:2px;vertical-align:-1px}.strct-md__tablewrap{overflow-x:auto;margin-block-end:var(--space-2)}.strct-md__table{border-collapse:collapse;width:max-content;min-width:100%}.strct-md__table th,.strct-md__table td{border:1px solid var(--b1);padding:4px 8px;text-align:start}.strct-md__table th{background:var(--bg-2);font-weight:600}.strct-md__caret{display:inline-block;width:2px;height:1em;margin-inline-start:2px;vertical-align:-2px;background:var(--acc);animation:strct-md-caret 1s steps(2) infinite}@keyframes strct-md-caret{50%{opacity:0}}@media(prefers-reduced-motion:reduce){.strct-md__caret{animation:none}}\n"], dependencies: [{ kind: "component", type: StrctMarkdown, selector: "strct-markdown", inputs: ["source", "tree", "streaming", "headingOffset", "linkPolicy", "tokens"], outputs: ["navigate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StrctCode, selector: "strct-code", inputs: ["code", "title", "language", "copyable", "collapsible", "collapsed", "lineNumbers", "wrap", "maxHeight", "collapseLabel", "expandLabel", "regionLabel"], outputs: ["collapsedChange"] }, { 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 });
29191
+ }
29192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMarkdown, decorators: [{
29193
+ type: Component,
29194
+ args: [{ selector: 'strct-markdown', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [NgTemplateOutlet, StrctCode, StrctIcon], template: `
29195
+ @for (block of blocks(); track $index) {
29196
+ @switch (block.kind) {
29197
+ @case ('p') {
29198
+ <p class="strct-md__p">
29199
+ <ng-container
29200
+ [ngTemplateOutlet]="inlineRun"
29201
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29202
+ />
29203
+ @if (caretOn($index)) {
29204
+ <span class="strct-md__caret" aria-hidden="true"></span>
29205
+ }
29206
+ </p>
29207
+ }
29208
+ @case ('heading') {
29209
+ <!-- A message is a region inside a dialog, so the document's own
29210
+ outline is not the model's to set: the offset pulls them down. -->
29211
+ @switch (level(block.level)) {
29212
+ @case (1) {
29213
+ <h1 class="strct-md__h">
29214
+ <ng-container
29215
+ [ngTemplateOutlet]="inlineRun"
29216
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29217
+ />
29218
+ </h1>
29219
+ }
29220
+ @case (2) {
29221
+ <h2 class="strct-md__h">
29222
+ <ng-container
29223
+ [ngTemplateOutlet]="inlineRun"
29224
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29225
+ />
29226
+ </h2>
29227
+ }
29228
+ @case (3) {
29229
+ <h3 class="strct-md__h">
29230
+ <ng-container
29231
+ [ngTemplateOutlet]="inlineRun"
29232
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29233
+ />
29234
+ </h3>
29235
+ }
29236
+ @case (4) {
29237
+ <h4 class="strct-md__h">
29238
+ <ng-container
29239
+ [ngTemplateOutlet]="inlineRun"
29240
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29241
+ />
29242
+ </h4>
29243
+ }
29244
+ @case (5) {
29245
+ <h5 class="strct-md__h">
29246
+ <ng-container
29247
+ [ngTemplateOutlet]="inlineRun"
29248
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29249
+ />
29250
+ </h5>
29251
+ }
29252
+ @default {
29253
+ <h6 class="strct-md__h">
29254
+ <ng-container
29255
+ [ngTemplateOutlet]="inlineRun"
29256
+ [ngTemplateOutletContext]="{ $implicit: block.inlines }"
29257
+ />
29258
+ </h6>
29259
+ }
29260
+ }
29261
+ }
29262
+ @case ('code') {
29263
+ <strct-code class="strct-md__code" [code]="block.text" [language]="block.lang" wrap />
29264
+ }
29265
+ @case ('rule') {
29266
+ <hr class="strct-md__rule" />
29267
+ }
29268
+ @case ('quote') {
29269
+ <blockquote class="strct-md__quote">
29270
+ <ng-container
29271
+ [ngTemplateOutlet]="blockRun"
29272
+ [ngTemplateOutletContext]="{ $implicit: block.blocks }"
29273
+ />
29274
+ </blockquote>
29275
+ }
29276
+ @case ('list') {
29277
+ @if (block.ordered) {
29278
+ <ol class="strct-md__list" [attr.start]="block.start">
29279
+ @for (item of block.items; track $index) {
29280
+ <li>
29281
+ <ng-container
29282
+ [ngTemplateOutlet]="blockRun"
29283
+ [ngTemplateOutletContext]="{ $implicit: item }"
29284
+ />
29285
+ </li>
29286
+ }
29287
+ </ol>
29288
+ } @else {
29289
+ <ul class="strct-md__list">
29290
+ @for (item of block.items; track $index) {
29291
+ <li>
29292
+ <ng-container
29293
+ [ngTemplateOutlet]="blockRun"
29294
+ [ngTemplateOutletContext]="{ $implicit: item }"
29295
+ />
29296
+ </li>
29297
+ }
29298
+ </ul>
29299
+ }
29300
+ }
29301
+ @case ('table') {
29302
+ <div class="strct-md__tablewrap">
29303
+ <table class="strct-md__table">
29304
+ <thead>
29305
+ <tr>
29306
+ @for (cell of block.head; track $index) {
29307
+ <th scope="col" [style.text-align]="block.align[$index] ?? 'start'">
29308
+ <ng-container
29309
+ [ngTemplateOutlet]="inlineRun"
29310
+ [ngTemplateOutletContext]="{ $implicit: cell }"
29311
+ />
29312
+ </th>
29313
+ }
29314
+ </tr>
29315
+ </thead>
29316
+ <tbody>
29317
+ @for (row of block.rows; track $index) {
29318
+ <tr>
29319
+ @for (cell of row; track $index) {
29320
+ <td [style.text-align]="block.align[$index] ?? 'start'">
29321
+ <ng-container
29322
+ [ngTemplateOutlet]="inlineRun"
29323
+ [ngTemplateOutletContext]="{ $implicit: cell }"
29324
+ />
29325
+ </td>
29326
+ }
29327
+ </tr>
29328
+ }
29329
+ </tbody>
29330
+ </table>
29331
+ </div>
29332
+ }
29333
+ }
29334
+ }
29335
+
29336
+ <!-- Blocks inside a list item or a quote. -->
29337
+ <ng-template #blockRun let-blocks>
29338
+ @for (b of blocks; track $index) {
29339
+ <strct-markdown
29340
+ [tree]="[b]"
29341
+ [headingOffset]="headingOffset()"
29342
+ [linkPolicy]="linkPolicy()"
29343
+ (navigate)="navigate.emit($event)"
29344
+ />
29345
+ }
29346
+ </ng-template>
29347
+
29348
+ <!-- One run of inline nodes. -->
29349
+ <ng-template #inlineRun let-inlines>
29350
+ @for (node of inlines; track $index) {
29351
+ @switch (node.kind) {
29352
+ @case ('text') {
29353
+ <ng-container>{{ node.text }}</ng-container>
29354
+ }
29355
+ @case ('code') {
29356
+ <code class="strct-md__codespan">{{ node.text }}</code>
29357
+ }
29358
+ @case ('break') {
29359
+ <br />
29360
+ }
29361
+ @case ('strong') {
29362
+ <strong>
29363
+ <ng-container
29364
+ [ngTemplateOutlet]="inlineRun"
29365
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29366
+ />
29367
+ </strong>
29368
+ }
29369
+ @case ('em') {
29370
+ <em>
29371
+ <ng-container
29372
+ [ngTemplateOutlet]="inlineRun"
29373
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29374
+ />
29375
+ </em>
29376
+ }
29377
+ @case ('del') {
29378
+ <del>
29379
+ <ng-container
29380
+ [ngTemplateOutlet]="inlineRun"
29381
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29382
+ />
29383
+ </del>
29384
+ }
29385
+ @case ('token') {
29386
+ @if (tokenTemplate(node.token); as tpl) {
29387
+ <ng-container
29388
+ [ngTemplateOutlet]="tpl"
29389
+ [ngTemplateOutletContext]="{ $implicit: node.text, data: node.data }"
29390
+ />
29391
+ } @else {
29392
+ <ng-container>{{ node.text }}</ng-container>
29393
+ }
29394
+ }
29395
+ @case ('link') {
29396
+ @switch (hrefKind(node.href)) {
29397
+ @case ('external') {
29398
+ <a
29399
+ class="strct-md__link"
29400
+ [attr.href]="node.href"
29401
+ target="_blank"
29402
+ rel="noopener noreferrer"
29403
+ >
29404
+ <ng-container
29405
+ [ngTemplateOutlet]="inlineRun"
29406
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29407
+ />
29408
+ <strct-icon
29409
+ class="strct-md__ext"
29410
+ strictName="externalLink"
29411
+ [size]="11"
29412
+ aria-hidden="true"
29413
+ />
29414
+ </a>
29415
+ }
29416
+ @case ('internal') {
29417
+ <a
29418
+ class="strct-md__link"
29419
+ [attr.href]="node.href"
29420
+ (click)="onInternal($event, node.href)"
29421
+ >
29422
+ <ng-container
29423
+ [ngTemplateOutlet]="inlineRun"
29424
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29425
+ />
29426
+ </a>
29427
+ }
29428
+ @default {
29429
+ <!-- Not a link we will follow: the characters, as written. -->
29430
+ <ng-container
29431
+ [ngTemplateOutlet]="inlineRun"
29432
+ [ngTemplateOutletContext]="{ $implicit: node.children }"
29433
+ />
29434
+ }
29435
+ }
29436
+ }
29437
+ }
29438
+ }
29439
+ </ng-template>
29440
+ `, host: { class: 'strct-md' }, styles: [".strct-md{display:block;color:var(--t1);font-size:13px;line-height:1.55}.strct-md__p{margin:0 0 var(--space-2)}.strct-md__p:last-child{margin-bottom:0}.strct-md__h{margin:var(--space-3) 0 var(--space-2);font-size:14px;font-weight:600;color:var(--t1)}.strct-md__h:first-child{margin-top:0}.strct-md__list{margin:0 0 var(--space-2);padding-inline-start:20px}.strct-md__list li{margin-block:2px}.strct-md__quote{margin:0 0 var(--space-2);padding-inline-start:var(--space-3);border-inline-start:2px solid var(--b2);color:var(--t2)}.strct-md__rule{border:0;border-block-start:1px solid var(--b1);margin:var(--space-3) 0}.strct-md__codespan{font-family:var(--mono);font-size:.92em;background:var(--bg-2);border-radius:var(--radius-sm);padding:1px 4px}.strct-md__code{margin-block-end:var(--space-2)}.strct-md__link{color:var(--acc)}.strct-md__ext{margin-inline-start:2px;vertical-align:-1px}.strct-md__tablewrap{overflow-x:auto;margin-block-end:var(--space-2)}.strct-md__table{border-collapse:collapse;width:max-content;min-width:100%}.strct-md__table th,.strct-md__table td{border:1px solid var(--b1);padding:4px 8px;text-align:start}.strct-md__table th{background:var(--bg-2);font-weight:600}.strct-md__caret{display:inline-block;width:2px;height:1em;margin-inline-start:2px;vertical-align:-2px;background:var(--acc);animation:strct-md-caret 1s steps(2) infinite}@keyframes strct-md-caret{50%{opacity:0}}@media(prefers-reduced-motion:reduce){.strct-md__caret{animation:none}}\n"] }]
29441
+ }], propDecorators: { source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], tree: [{ type: i0.Input, args: [{ isSignal: true, alias: "tree", required: false }] }], streaming: [{ type: i0.Input, args: [{ isSignal: true, alias: "streaming", required: false }] }], headingOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingOffset", required: false }] }], linkPolicy: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkPolicy", required: false }] }], tokens: [{ type: i0.Input, args: [{ isSignal: true, alias: "tokens", required: false }] }], navigate: [{ type: i0.Output, args: ["navigate"] }], tokenDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctMarkdownToken), { isSignal: true }] }] } });
29442
+
27948
29443
  /**
27949
29444
  * Public API surface of the strct UI library.
27950
29445
  */
@@ -27954,5 +29449,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
27954
29449
  * Generated bundle index. Do not edit.
27955
29450
  */
27956
29451
 
27957
- 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 };
29452
+ export { FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_MD_LIMITS, 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, StrctChatMessageActions, StrctChatThread, StrctCheckbox, StrctChips, StrctCode, StrctCodeInline, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctControlDescription, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatagridActionBarCaption, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDetailPaneActions, StrctDetailPaneMeta, StrctDetailPaneTitle, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctDropdownItemAction, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFieldGroup, StrctFieldHint, StrctFieldPrefix, StrctFieldSuffix, StrctFieldValue, StrctFile, StrctFilterBar, StrctFlow, StrctFlowNodeTemplate, StrctFooter, StrctGauge, StrctGroupHeaderDef, StrctHeader, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLegend, StrctList, StrctListItem, StrctListItemDescription, StrctListItemLeading, StrctListItemMeta, StrctListItemTrailing, StrctLiveIndicator, StrctLogViewer, StrctLogin, StrctMarkdown, StrctMarkdownToken, 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, parseInlines, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctCheckHostDisplay, strctCheckHostInputs, strctClassifyHref, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctParseMarkdown, strctQrMatrix, strctValidationIcon, strctValidationTone, unlockBodyScroll };
27958
29453
  //# sourceMappingURL=akcelik-strct.mjs.map