@ethlete/components 1.0.0-next.53 → 1.0.0-next.55

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.
@@ -6,9 +6,9 @@ import { NgTemplateOutlet, NgComponentOutlet, Location, DOCUMENT as DOCUMENT$1,
6
6
  import { DomSanitizer } from '@angular/platform-browser';
7
7
  import { format, startOfWeek, startOfDay, endOfWeek, isBefore, addDays, endOfMonth, startOfMonth, isSameYear, isSameMonth, isSameDay, startOfYear, isAfter, addYears, addMonths, setMonth, setYear, getDate, setDate, lastDayOfMonth, getWeek, endOfYear, parse, isValid, setSeconds, setMinutes, setHours, setMilliseconds, endOfDay, eachDayOfInterval, differenceInCalendarDays, addMinutes, differenceInMinutes, addHours } from 'date-fns';
8
8
  import { takeUntilDestroyed, toSignal, toObservable, outputFromObservable, outputToObservable, rxResource } from '@angular/core/rxjs-interop';
9
- import { Subject, take, tap, timer, takeUntil, fromEvent, filter, switchMap, map, combineLatest, distinctUntilChanged, EMPTY, debounceTime, merge, defer, finalize, of, isObservable, from, catchError, firstValueFrom, concat, scan, interval, animationFrameScheduler, EmptyError, exhaustMap, Observable, shareReplay, defaultIfEmpty, expand, toArray, mergeMap } from 'rxjs';
9
+ import { Subject, take, tap, timer, takeUntil, fromEvent, filter, switchMap, map, combineLatest, distinctUntilChanged, EMPTY, debounceTime, merge, defer, finalize, of, isObservable, from, catchError, firstValueFrom, concat, scan, interval, animationFrameScheduler, EmptyError, exhaustMap, Observable, shareReplay, defaultIfEmpty, expand, toArray, takeWhile, mergeMap } from 'rxjs';
10
10
  import * as i1$1 from '@angular/router';
11
- import { Router, RouterLink, RouterLinkActive, NavigationEnd } from '@angular/router';
11
+ import { Router, RouterLink, ActivatedRoute, RouterLinkActive, NavigationEnd } from '@angular/router';
12
12
  import { withArgs, queryStateSignal, isQueryStateSuccess, isQueryStateFailure, isQueryStateLoading, executeUntilSettled, extractQuery, queryComputed, parseHttpErrorCodeToMessageEn, parseHttpErrorCodeToTitleEn, parseHttpErrorCodeToMessageDe, parseHttpErrorCodeToTitleDe, queryErrorMessages, createQueryErrorResponse } from '@ethlete/query';
13
13
  import { createMetadataKey, metadata, FORM_FIELD, validate, createManagedMetadataKey, submit, form } from '@angular/forms/signals';
14
14
  import { enUS } from 'date-fns/locale/en-US';
@@ -36922,13 +36922,13 @@ class MenuComponent {
36922
36922
  });
36923
36923
  }
36924
36924
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
36925
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MenuComponent, isStandalone: true, selector: "et-menu", host: { classAttribute: "et-menu" }, viewQueries: [{ propertyName: "headerElement", first: true, predicate: ["menuHeader"], descendants: true, isSignal: true }, { propertyName: "bodyContentElement", first: true, predicate: ["menuBodyContent"], descendants: true, isSignal: true }], hostDirectives: [{ directive: MenuPanelDirective }, { directive: i1.ProvideColorDirective }, { directive: i1.AutoSurfaceDirective }], ngImport: i0, template: "<div #menuHeader class=\"et-menu-header\">\n <div class=\"et-menu-search-field\">\n <ng-content select=\"input[etMenuSearch]\" />\n\n @if (showSearchSpinner()) {\n <et-spinner class=\"et-menu-search-spinner\" diameter=\"16\" />\n }\n </div>\n\n @if (searchError(); as error) {\n <p [id]=\"searchErrorId\" [etProvideColor]=\"errorColorTheme\" class=\"et-menu-search-error\" role=\"alert\">\n {{ error }}\n </p>\n }\n</div>\n\n<div class=\"et-menu-body\">\n <div #menuBodyContent class=\"et-menu-body-content\">\n <ng-content />\n </div>\n</div>\n", styles: ["@layer components{@property --et-menu-min-width{syntax: \"<length>\"; inherits: false; initial-value: 180px;}@property --et-menu-max-height{syntax: \"<length-percentage>\"; inherits: false; initial-value: 40vh;}@property --et-menu-padding-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-padding-inline{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-item-height{syntax: \"<length>\"; inherits: true; initial-value: 36px;}@property --et-menu-item-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-gap{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-border-radius{syntax: \"<length>\"; inherits: true; initial-value: 6px;}@property --et-menu-item-font-size{syntax: \"<length>\"; inherits: true; initial-value: 14px;}@property --et-menu-item-icon-size{syntax: \"<length>\"; inherits: true; initial-value: 16px;}@property --et-menu-separator-margin-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-group-label-font-size{syntax: \"<length>\"; inherits: false; initial-value: 12px;}@property --et-menu-search-height{syntax: \"<length>\"; inherits: false; initial-value: 36px;}.et-overlay.et-overlay--menu{overflow:visible;background:transparent;box-shadow:none}.et-menu{--_et-menu-background: var(--et-surface-background-solid, var(--et-surface-2, rgb(32 32 32)));--_et-menu-color: var(--et-surface-color-solid, var(--et-color-main-contrast, rgb(244 244 245)));--_et-menu-border: var(--et-surface-border-solid, rgb(255 255 255 / .1));--_et-menu-shadow: 0 10px 24px rgb(0 0 0 / .16);--_et-menu-radius: 10px;--_et-menu-item-active-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 12%, transparent );--_et-menu-item-pressed-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 20%, transparent );--_et-menu-muted-color: var(--et-surface-color-muted-solid, rgb(255 255 255 / .55));--_et-menu-separator-color: var(--et-surface-border-solid, rgb(255 255 255 / .1));display:flex;flex-direction:column;min-inline-size:var(--et-menu-min-width);max-inline-size:min(320px,calc(100vw - 24px));max-block-size:min(var(--et-menu-max-height),var(--et-overlay-max-height, 100vh));border-radius:var(--_et-menu-radius);border:1px solid var(--_et-menu-border);background:var(--_et-menu-background);color:var(--_et-menu-color);font-family:var(--et-font-family, inherit);font-size:var(--et-menu-item-font-size);box-shadow:var(--_et-menu-shadow);outline:none}.et-menu.et-menu--resizing{overflow:clip}.et-menu.et-menu--resizing .et-menu-body{overflow:clip}.et-menu .et-menu-header{flex:none;padding:var(--et-menu-padding-block) var(--et-menu-padding-inline) 0;contain:inline-size}.et-menu .et-menu-header:not(:has(input[etmenusearch])){display:none}.et-menu .et-menu-header .et-menu-search-field{position:relative}.et-menu .et-menu-header .et-menu-search-field:has(.et-menu-search-spinner) input[etmenusearch]{padding-inline-end:calc(var(--et-menu-item-padding-inline) + 22px)}.et-menu .et-menu-header .et-menu-search-spinner{position:absolute;inset-block-start:50%;inset-inline-end:10px;translate:0 -50%;color:var(--_et-menu-muted-color)}.et-menu .et-menu-header .et-menu-search-error{margin:6px 2px 0;font-size:12px;color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-header input[etmenusearch]{inline-size:100%;block-size:var(--et-menu-search-height);padding-inline:var(--et-menu-item-padding-inline);border-radius:var(--et-menu-item-border-radius);border:1px solid var(--_et-menu-border);background:color-mix(in srgb,var(--et-surface-interaction-solid, rgb(255 255 255)) 6%,transparent);color:inherit;font:inherit;outline:none;box-sizing:border-box;transition:border-color .12s ease,background .12s ease}.et-menu .et-menu-header input[etmenusearch]:focus-visible{border-color:var(--et-theme-color-primary-solid, rgb(255 255 255 / .3))}.et-menu .et-menu-header input[etmenusearch]::placeholder{color:var(--_et-menu-muted-color)}.et-menu .et-menu-body{flex:1;min-block-size:0;padding:var(--et-menu-padding-block) var(--et-menu-padding-inline);overflow-y:auto;overscroll-behavior:contain}.et-menu .et-menu-group{display:block}.et-menu .et-menu-item{display:flex;align-items:center;gap:var(--et-menu-item-gap);inline-size:100%;min-block-size:var(--et-menu-item-height);padding-inline:var(--et-menu-item-padding-inline);border:none;border-radius:var(--et-menu-item-border-radius);background:transparent;color:inherit;font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent;transition:background .12s ease,color .12s ease,opacity .12s ease}.et-menu .et-menu-item[data-active]:where(:focus-visible),.et-menu .et-menu-item[data-menu-open]{background:var(--_et-menu-item-active-background)}@media(hover:hover){.et-menu .et-menu-item[data-active]:where(:hover){background:var(--_et-menu-item-active-background)}}.et-menu .et-menu-item:active:not([aria-disabled=true]){background:var(--_et-menu-item-pressed-background)}.et-menu .et-menu-item[aria-disabled=true]{opacity:.4;cursor:default}.et-menu .et-menu-item[data-variant=destructive]{color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-item .et-menu-item-content{flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-from,.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-to{opacity:0}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:transform .14s ease,opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:transform .1s ease,opacity .1s ease}.et-overlay--menu[data-overlay-placement^=top].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=top].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(.3rem)!important}.et-overlay--menu[data-overlay-placement^=bottom].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=bottom].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=right].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=right].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=left].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=left].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(.3rem)!important}@media(prefers-reduced-motion:reduce){.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:opacity .1s ease}.et-overlay--menu[data-overlay-placement].et-animation-enter-from,.et-overlay--menu[data-overlay-placement].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0)!important}}}\n"], dependencies: [{ kind: "directive", type: ProvideColorDirective, selector: "[etProvideColor]", inputs: ["etProvideColor"] }, { kind: "component", type: SpinnerComponent, selector: "et-spinner", inputs: ["diameter", "strokeWidth", "track", "value", "determinate"] }], encapsulation: i0.ViewEncapsulation.None }); }
36925
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MenuComponent, isStandalone: true, selector: "et-menu", host: { classAttribute: "et-menu" }, viewQueries: [{ propertyName: "headerElement", first: true, predicate: ["menuHeader"], descendants: true, isSignal: true }, { propertyName: "bodyContentElement", first: true, predicate: ["menuBodyContent"], descendants: true, isSignal: true }], hostDirectives: [{ directive: MenuPanelDirective }, { directive: i1.ProvideColorDirective }, { directive: i1.AutoSurfaceDirective }], ngImport: i0, template: "<div #menuHeader class=\"et-menu-header\">\n <div class=\"et-menu-search-field\">\n <ng-content select=\"input[etMenuSearch]\" />\n\n @if (showSearchSpinner()) {\n <et-spinner class=\"et-menu-search-spinner\" diameter=\"16\" />\n }\n </div>\n\n @if (searchError(); as error) {\n <p [id]=\"searchErrorId\" [etProvideColor]=\"errorColorTheme\" class=\"et-menu-search-error\" role=\"alert\">\n {{ error }}\n </p>\n }\n</div>\n\n<div class=\"et-menu-body\">\n <div #menuBodyContent class=\"et-menu-body-content\">\n <ng-content />\n </div>\n</div>\n", styles: ["@layer components{@property --et-menu-min-width{syntax: \"<length>\"; inherits: false; initial-value: 180px;}@property --et-menu-max-height{syntax: \"<length-percentage>\"; inherits: false; initial-value: 40vh;}@property --et-menu-padding-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-padding-inline{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-item-height{syntax: \"<length>\"; inherits: true; initial-value: 36px;}@property --et-menu-item-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-gap{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-border-radius{syntax: \"<length>\"; inherits: true; initial-value: 6px;}@property --et-menu-item-font-size{syntax: \"<length>\"; inherits: true; initial-value: 14px;}@property --et-menu-item-icon-size{syntax: \"<length>\"; inherits: true; initial-value: 16px;}@property --et-menu-separator-margin-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-group-label-font-size{syntax: \"<length>\"; inherits: false; initial-value: 12px;}@property --et-menu-search-height{syntax: \"<length>\"; inherits: false; initial-value: 36px;}.et-overlay.et-overlay--menu{overflow:visible;background:transparent;box-shadow:none}.et-menu{--_et-menu-background: var(--et-surface-background-solid, var(--et-surface-2, rgb(32 32 32)));--_et-menu-color: var(--et-surface-color-solid, var(--et-color-main-contrast, rgb(244 244 245)));--_et-menu-border: var(--et-surface-border-solid, rgb(255 255 255 / .1));--_et-menu-shadow: 0 10px 24px rgb(0 0 0 / .16);--_et-menu-radius: 10px;--_et-menu-item-active-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 12%, transparent );--_et-menu-item-pressed-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 20%, transparent );--_et-menu-muted-color: var(--et-surface-color-muted-solid, rgb(255 255 255 / .55));--_et-menu-separator-color: var(--et-surface-border-solid, rgb(255 255 255 / .1));display:flex;flex-direction:column;min-inline-size:var(--et-menu-min-width);max-inline-size:min(320px,calc(100vw - 24px));max-block-size:min(var(--et-menu-max-height),var(--et-overlay-max-height, 100vh));border-radius:var(--_et-menu-radius);border:1px solid var(--_et-menu-border);background:var(--_et-menu-background);color:var(--_et-menu-color);font-family:var(--et-font-family, inherit);font-size:var(--et-menu-item-font-size);box-shadow:var(--_et-menu-shadow);outline:none}.et-menu.et-menu--resizing{overflow:clip}.et-menu.et-menu--resizing .et-menu-body{overflow:clip}.et-menu .et-menu-header{flex:none;padding:var(--et-menu-padding-block) var(--et-menu-padding-inline) 0;contain:inline-size}.et-menu .et-menu-header:not(:has(input[etmenusearch])){display:none}.et-menu .et-menu-header .et-menu-search-field{position:relative}.et-menu .et-menu-header .et-menu-search-field:has(.et-menu-search-spinner) input[etmenusearch]{padding-inline-end:calc(var(--et-menu-item-padding-inline) + 22px)}.et-menu .et-menu-header .et-menu-search-spinner{position:absolute;inset-block-start:50%;inset-inline-end:10px;translate:0 -50%;color:var(--_et-menu-muted-color)}.et-menu .et-menu-header .et-menu-search-error{margin:6px 2px 0;font-size:12px;color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-header input[etmenusearch]{inline-size:100%;block-size:var(--et-menu-search-height);padding-inline:var(--et-menu-item-padding-inline);border-radius:var(--et-menu-item-border-radius);border:1px solid var(--_et-menu-border);background:color-mix(in srgb,var(--et-surface-interaction-solid, rgb(255 255 255)) 6%,transparent);color:inherit;font:inherit;outline:none;box-sizing:border-box;transition:border-color .12s ease,background .12s ease}.et-menu .et-menu-header input[etmenusearch]:focus-visible{border-color:var(--et-theme-color-primary-solid, rgb(255 255 255 / .3))}.et-menu .et-menu-header input[etmenusearch]::placeholder{color:var(--_et-menu-muted-color)}.et-menu .et-menu-body{flex:1;min-block-size:0;padding-inline:var(--et-menu-padding-inline);overflow-y:auto;overscroll-behavior:contain}.et-menu .et-menu-body-content{padding-block:var(--et-menu-padding-block)}.et-menu .et-menu-group{display:block}.et-menu .et-menu-item{display:flex;align-items:center;gap:var(--et-menu-item-gap);inline-size:100%;min-block-size:var(--et-menu-item-height);padding-inline:var(--et-menu-item-padding-inline);border:none;border-radius:var(--et-menu-item-border-radius);background:transparent;color:inherit;font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent;transition:background .12s ease,color .12s ease,opacity .12s ease}.et-menu .et-menu-item[data-active]:where(:focus-visible),.et-menu .et-menu-item[data-menu-open]{background:var(--_et-menu-item-active-background)}@media(hover:hover){.et-menu .et-menu-item[data-active]:where(:hover){background:var(--_et-menu-item-active-background)}}.et-menu .et-menu-item:active:not([aria-disabled=true]){background:var(--_et-menu-item-pressed-background)}.et-menu .et-menu-item[aria-disabled=true]{opacity:.4;cursor:default}.et-menu .et-menu-item[data-variant=destructive]{color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-item .et-menu-item-content{flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-from,.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-to{opacity:0}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:transform .14s ease,opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:transform .1s ease,opacity .1s ease}.et-overlay--menu[data-overlay-placement^=top].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=top].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(.3rem)!important}.et-overlay--menu[data-overlay-placement^=bottom].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=bottom].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=right].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=right].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=left].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=left].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(.3rem)!important}@media(prefers-reduced-motion:reduce){.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:opacity .1s ease}.et-overlay--menu[data-overlay-placement].et-animation-enter-from,.et-overlay--menu[data-overlay-placement].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0)!important}}}\n"], dependencies: [{ kind: "directive", type: ProvideColorDirective, selector: "[etProvideColor]", inputs: ["etProvideColor"] }, { kind: "component", type: SpinnerComponent, selector: "et-spinner", inputs: ["diameter", "strokeWidth", "track", "value", "determinate"] }], encapsulation: i0.ViewEncapsulation.None }); }
36926
36926
  }
36927
36927
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MenuComponent, decorators: [{
36928
36928
  type: Component,
36929
36929
  args: [{ selector: 'et-menu', encapsulation: ViewEncapsulation.None, imports: [ProvideColorDirective, SpinnerComponent], hostDirectives: [MenuPanelDirective, ProvideColorDirective, AutoSurfaceDirective], host: {
36930
36930
  class: 'et-menu',
36931
- }, template: "<div #menuHeader class=\"et-menu-header\">\n <div class=\"et-menu-search-field\">\n <ng-content select=\"input[etMenuSearch]\" />\n\n @if (showSearchSpinner()) {\n <et-spinner class=\"et-menu-search-spinner\" diameter=\"16\" />\n }\n </div>\n\n @if (searchError(); as error) {\n <p [id]=\"searchErrorId\" [etProvideColor]=\"errorColorTheme\" class=\"et-menu-search-error\" role=\"alert\">\n {{ error }}\n </p>\n }\n</div>\n\n<div class=\"et-menu-body\">\n <div #menuBodyContent class=\"et-menu-body-content\">\n <ng-content />\n </div>\n</div>\n", styles: ["@layer components{@property --et-menu-min-width{syntax: \"<length>\"; inherits: false; initial-value: 180px;}@property --et-menu-max-height{syntax: \"<length-percentage>\"; inherits: false; initial-value: 40vh;}@property --et-menu-padding-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-padding-inline{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-item-height{syntax: \"<length>\"; inherits: true; initial-value: 36px;}@property --et-menu-item-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-gap{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-border-radius{syntax: \"<length>\"; inherits: true; initial-value: 6px;}@property --et-menu-item-font-size{syntax: \"<length>\"; inherits: true; initial-value: 14px;}@property --et-menu-item-icon-size{syntax: \"<length>\"; inherits: true; initial-value: 16px;}@property --et-menu-separator-margin-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-group-label-font-size{syntax: \"<length>\"; inherits: false; initial-value: 12px;}@property --et-menu-search-height{syntax: \"<length>\"; inherits: false; initial-value: 36px;}.et-overlay.et-overlay--menu{overflow:visible;background:transparent;box-shadow:none}.et-menu{--_et-menu-background: var(--et-surface-background-solid, var(--et-surface-2, rgb(32 32 32)));--_et-menu-color: var(--et-surface-color-solid, var(--et-color-main-contrast, rgb(244 244 245)));--_et-menu-border: var(--et-surface-border-solid, rgb(255 255 255 / .1));--_et-menu-shadow: 0 10px 24px rgb(0 0 0 / .16);--_et-menu-radius: 10px;--_et-menu-item-active-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 12%, transparent );--_et-menu-item-pressed-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 20%, transparent );--_et-menu-muted-color: var(--et-surface-color-muted-solid, rgb(255 255 255 / .55));--_et-menu-separator-color: var(--et-surface-border-solid, rgb(255 255 255 / .1));display:flex;flex-direction:column;min-inline-size:var(--et-menu-min-width);max-inline-size:min(320px,calc(100vw - 24px));max-block-size:min(var(--et-menu-max-height),var(--et-overlay-max-height, 100vh));border-radius:var(--_et-menu-radius);border:1px solid var(--_et-menu-border);background:var(--_et-menu-background);color:var(--_et-menu-color);font-family:var(--et-font-family, inherit);font-size:var(--et-menu-item-font-size);box-shadow:var(--_et-menu-shadow);outline:none}.et-menu.et-menu--resizing{overflow:clip}.et-menu.et-menu--resizing .et-menu-body{overflow:clip}.et-menu .et-menu-header{flex:none;padding:var(--et-menu-padding-block) var(--et-menu-padding-inline) 0;contain:inline-size}.et-menu .et-menu-header:not(:has(input[etmenusearch])){display:none}.et-menu .et-menu-header .et-menu-search-field{position:relative}.et-menu .et-menu-header .et-menu-search-field:has(.et-menu-search-spinner) input[etmenusearch]{padding-inline-end:calc(var(--et-menu-item-padding-inline) + 22px)}.et-menu .et-menu-header .et-menu-search-spinner{position:absolute;inset-block-start:50%;inset-inline-end:10px;translate:0 -50%;color:var(--_et-menu-muted-color)}.et-menu .et-menu-header .et-menu-search-error{margin:6px 2px 0;font-size:12px;color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-header input[etmenusearch]{inline-size:100%;block-size:var(--et-menu-search-height);padding-inline:var(--et-menu-item-padding-inline);border-radius:var(--et-menu-item-border-radius);border:1px solid var(--_et-menu-border);background:color-mix(in srgb,var(--et-surface-interaction-solid, rgb(255 255 255)) 6%,transparent);color:inherit;font:inherit;outline:none;box-sizing:border-box;transition:border-color .12s ease,background .12s ease}.et-menu .et-menu-header input[etmenusearch]:focus-visible{border-color:var(--et-theme-color-primary-solid, rgb(255 255 255 / .3))}.et-menu .et-menu-header input[etmenusearch]::placeholder{color:var(--_et-menu-muted-color)}.et-menu .et-menu-body{flex:1;min-block-size:0;padding:var(--et-menu-padding-block) var(--et-menu-padding-inline);overflow-y:auto;overscroll-behavior:contain}.et-menu .et-menu-group{display:block}.et-menu .et-menu-item{display:flex;align-items:center;gap:var(--et-menu-item-gap);inline-size:100%;min-block-size:var(--et-menu-item-height);padding-inline:var(--et-menu-item-padding-inline);border:none;border-radius:var(--et-menu-item-border-radius);background:transparent;color:inherit;font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent;transition:background .12s ease,color .12s ease,opacity .12s ease}.et-menu .et-menu-item[data-active]:where(:focus-visible),.et-menu .et-menu-item[data-menu-open]{background:var(--_et-menu-item-active-background)}@media(hover:hover){.et-menu .et-menu-item[data-active]:where(:hover){background:var(--_et-menu-item-active-background)}}.et-menu .et-menu-item:active:not([aria-disabled=true]){background:var(--_et-menu-item-pressed-background)}.et-menu .et-menu-item[aria-disabled=true]{opacity:.4;cursor:default}.et-menu .et-menu-item[data-variant=destructive]{color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-item .et-menu-item-content{flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-from,.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-to{opacity:0}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:transform .14s ease,opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:transform .1s ease,opacity .1s ease}.et-overlay--menu[data-overlay-placement^=top].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=top].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(.3rem)!important}.et-overlay--menu[data-overlay-placement^=bottom].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=bottom].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=right].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=right].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=left].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=left].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(.3rem)!important}@media(prefers-reduced-motion:reduce){.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:opacity .1s ease}.et-overlay--menu[data-overlay-placement].et-animation-enter-from,.et-overlay--menu[data-overlay-placement].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0)!important}}}\n"] }]
36931
+ }, template: "<div #menuHeader class=\"et-menu-header\">\n <div class=\"et-menu-search-field\">\n <ng-content select=\"input[etMenuSearch]\" />\n\n @if (showSearchSpinner()) {\n <et-spinner class=\"et-menu-search-spinner\" diameter=\"16\" />\n }\n </div>\n\n @if (searchError(); as error) {\n <p [id]=\"searchErrorId\" [etProvideColor]=\"errorColorTheme\" class=\"et-menu-search-error\" role=\"alert\">\n {{ error }}\n </p>\n }\n</div>\n\n<div class=\"et-menu-body\">\n <div #menuBodyContent class=\"et-menu-body-content\">\n <ng-content />\n </div>\n</div>\n", styles: ["@layer components{@property --et-menu-min-width{syntax: \"<length>\"; inherits: false; initial-value: 180px;}@property --et-menu-max-height{syntax: \"<length-percentage>\"; inherits: false; initial-value: 40vh;}@property --et-menu-padding-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-padding-inline{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-item-height{syntax: \"<length>\"; inherits: true; initial-value: 36px;}@property --et-menu-item-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-gap{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-menu-item-border-radius{syntax: \"<length>\"; inherits: true; initial-value: 6px;}@property --et-menu-item-font-size{syntax: \"<length>\"; inherits: true; initial-value: 14px;}@property --et-menu-item-icon-size{syntax: \"<length>\"; inherits: true; initial-value: 16px;}@property --et-menu-separator-margin-block{syntax: \"<length>\"; inherits: false; initial-value: 6px;}@property --et-menu-group-label-font-size{syntax: \"<length>\"; inherits: false; initial-value: 12px;}@property --et-menu-search-height{syntax: \"<length>\"; inherits: false; initial-value: 36px;}.et-overlay.et-overlay--menu{overflow:visible;background:transparent;box-shadow:none}.et-menu{--_et-menu-background: var(--et-surface-background-solid, var(--et-surface-2, rgb(32 32 32)));--_et-menu-color: var(--et-surface-color-solid, var(--et-color-main-contrast, rgb(244 244 245)));--_et-menu-border: var(--et-surface-border-solid, rgb(255 255 255 / .1));--_et-menu-shadow: 0 10px 24px rgb(0 0 0 / .16);--_et-menu-radius: 10px;--_et-menu-item-active-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 12%, transparent );--_et-menu-item-pressed-background: color-mix( in srgb, var(--et-surface-interaction-solid, rgb(255 255 255)) 20%, transparent );--_et-menu-muted-color: var(--et-surface-color-muted-solid, rgb(255 255 255 / .55));--_et-menu-separator-color: var(--et-surface-border-solid, rgb(255 255 255 / .1));display:flex;flex-direction:column;min-inline-size:var(--et-menu-min-width);max-inline-size:min(320px,calc(100vw - 24px));max-block-size:min(var(--et-menu-max-height),var(--et-overlay-max-height, 100vh));border-radius:var(--_et-menu-radius);border:1px solid var(--_et-menu-border);background:var(--_et-menu-background);color:var(--_et-menu-color);font-family:var(--et-font-family, inherit);font-size:var(--et-menu-item-font-size);box-shadow:var(--_et-menu-shadow);outline:none}.et-menu.et-menu--resizing{overflow:clip}.et-menu.et-menu--resizing .et-menu-body{overflow:clip}.et-menu .et-menu-header{flex:none;padding:var(--et-menu-padding-block) var(--et-menu-padding-inline) 0;contain:inline-size}.et-menu .et-menu-header:not(:has(input[etmenusearch])){display:none}.et-menu .et-menu-header .et-menu-search-field{position:relative}.et-menu .et-menu-header .et-menu-search-field:has(.et-menu-search-spinner) input[etmenusearch]{padding-inline-end:calc(var(--et-menu-item-padding-inline) + 22px)}.et-menu .et-menu-header .et-menu-search-spinner{position:absolute;inset-block-start:50%;inset-inline-end:10px;translate:0 -50%;color:var(--_et-menu-muted-color)}.et-menu .et-menu-header .et-menu-search-error{margin:6px 2px 0;font-size:12px;color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-header input[etmenusearch]{inline-size:100%;block-size:var(--et-menu-search-height);padding-inline:var(--et-menu-item-padding-inline);border-radius:var(--et-menu-item-border-radius);border:1px solid var(--_et-menu-border);background:color-mix(in srgb,var(--et-surface-interaction-solid, rgb(255 255 255)) 6%,transparent);color:inherit;font:inherit;outline:none;box-sizing:border-box;transition:border-color .12s ease,background .12s ease}.et-menu .et-menu-header input[etmenusearch]:focus-visible{border-color:var(--et-theme-color-primary-solid, rgb(255 255 255 / .3))}.et-menu .et-menu-header input[etmenusearch]::placeholder{color:var(--_et-menu-muted-color)}.et-menu .et-menu-body{flex:1;min-block-size:0;padding-inline:var(--et-menu-padding-inline);overflow-y:auto;overscroll-behavior:contain}.et-menu .et-menu-body-content{padding-block:var(--et-menu-padding-block)}.et-menu .et-menu-group{display:block}.et-menu .et-menu-item{display:flex;align-items:center;gap:var(--et-menu-item-gap);inline-size:100%;min-block-size:var(--et-menu-item-height);padding-inline:var(--et-menu-item-padding-inline);border:none;border-radius:var(--et-menu-item-border-radius);background:transparent;color:inherit;font:inherit;text-align:start;text-decoration:none;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent;transition:background .12s ease,color .12s ease,opacity .12s ease}.et-menu .et-menu-item[data-active]:where(:focus-visible),.et-menu .et-menu-item[data-menu-open]{background:var(--_et-menu-item-active-background)}@media(hover:hover){.et-menu .et-menu-item[data-active]:where(:hover){background:var(--_et-menu-item-active-background)}}.et-menu .et-menu-item:active:not([aria-disabled=true]){background:var(--_et-menu-item-pressed-background)}.et-menu .et-menu-item[aria-disabled=true]{opacity:.4;cursor:default}.et-menu .et-menu-item[data-variant=destructive]{color:var(--et-theme-color-primary-solid, rgb(248 113 113))}.et-menu .et-menu-item .et-menu-item-content{flex:1;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-from,.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-to{opacity:0}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:transform .14s ease,opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:transform .1s ease,opacity .1s ease}.et-overlay--menu[data-overlay-placement^=top].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=top].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(.3rem)!important}.et-overlay--menu[data-overlay-placement^=bottom].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=bottom].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translateY(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=right].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=right].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(-.3rem)!important}.et-overlay--menu[data-overlay-placement^=left].et-animation-enter-from,.et-overlay--menu[data-overlay-placement^=left].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0) translate(.3rem)!important}@media(prefers-reduced-motion:reduce){.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-enter-active{transition:opacity .14s ease}.et-overlay.et-with-default-animation.et-overlay--menu.et-animation-leave-active{transition:opacity .1s ease}.et-overlay--menu[data-overlay-placement].et-animation-enter-from,.et-overlay--menu[data-overlay-placement].et-animation-leave-to{transform:translate3d(var(--et-overlay-anchored-x, 0px),var(--et-overlay-anchored-y, 0px),0)!important}}}\n"] }]
36932
36932
  }], ctorParameters: () => [], propDecorators: { headerElement: [{ type: i0.ViewChild, args: ['menuHeader', { isSignal: true }] }], bodyContentElement: [{ type: i0.ViewChild, args: ['menuBodyContent', { isSignal: true }] }] } });
36933
36933
 
36934
36934
  const MENU_IMPORTS = [
@@ -59591,6 +59591,8 @@ const TABLE_ERROR_CODES = {
59591
59591
  CONFLICTING_EXPORT_OPTIONS: 3507,
59592
59592
  /** An `expandedRowTemplate` was set on a table without `etTableRowExpansion` to render it. */
59593
59593
  MISSING_ROW_EXPANSION: 3508,
59594
+ /** A `rowLink` answered with router commands on a table without `etTableRowRouterLink` to resolve them. */
59595
+ MISSING_ROW_ROUTER_LINK: 3509,
59594
59596
  };
59595
59597
 
59596
59598
  // What tells Excel the file is UTF-8; see `bom`.
@@ -60289,11 +60291,16 @@ const isFlexibleTrack = (track) => /\bauto\b|[\d.]fr\b/.test(track);
60289
60291
  const sameJson = (a, b) => JSON.stringify(a) === JSON.stringify(b);
60290
60292
  /** Sub-pixel slack (px) before a scroll offset counts as "there is content over there". */
60291
60293
  const SCROLL_FADE_EPSILON = 1;
60294
+ /** Sort indicator enter duration (must match the CSS animation) - see {@link TableComponent.sortIndicatorEnter}. */
60295
+ const SORT_INDICATOR_ANIMATION_MS = 150;
60292
60296
  /** What a cell renders as when nothing pins columns - see `registerColumnPinning`. */
60293
60297
  const NO_PIN = { stickyStart: false, stickyEnd: false, offsetStart: null, offsetEnd: null };
60294
60298
  /** The same for a leading utility cell, and for the scroll fades' inline offsets. */
60295
60299
  const NO_LEAD_PIN = { sticky: false, offset: null };
60296
60300
  const NO_INSET = { start: 0, end: 0 };
60301
+ const EMPTY_COLUMN_KEYS = /* @__PURE__ */ new Set();
60302
+ // Per-table counter, so the ids a row link is named by are unique across every table on the page.
60303
+ let uniqueTableId = 0;
60297
60304
  /**
60298
60305
  * The default table. Renders typed rows and cells from a {@link TableColumns}
60299
60306
  * record on a CSS grid with a sticky header and an empty state. Light by
@@ -60312,6 +60319,8 @@ class TableComponent {
60312
60319
  constructor() {
60313
60320
  this.elementRef = inject(ElementRef);
60314
60321
  this.injector = inject(Injector);
60322
+ this.destroyRef = inject(DestroyRef);
60323
+ this.document = inject(DOCUMENT$1);
60315
60324
  this.injectedLabels = injectTableLabels();
60316
60325
  /** The rows to render. */
60317
60326
  this.data = input([], /* @ts-ignore */
@@ -60385,7 +60394,8 @@ class TableComponent {
60385
60394
  /**
60386
60395
  * The table's visual frame. `'enclosed'` (default) is a bordered, rounded surface panel with a
60387
60396
  * tinted header band; `'divided'` is borderless with row dividers; `'zebra'` stripes rows; `'grid'`
60388
- * draws full cell borders; `'bare'` has no chrome. @default 'enclosed'
60397
+ * draws full cell borders; `'bare'` has no chrome; `'cards'` gives every row a box of its own - a
60398
+ * tinted, rounded card, spaced by `--et-table-row-gap`. @default 'enclosed'
60389
60399
  */
60390
60400
  this.appearance = input('enclosed', /* @ts-ignore */
60391
60401
  ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
@@ -60435,9 +60445,31 @@ class TableComponent {
60435
60445
  ...(ngDevMode ? [undefined, { debugName: "expandedRowTemplate" }] : /* istanbul ignore next */ []));
60436
60446
  /**
60437
60447
  * Make whole rows respond to clicks: adds a hover/pointer affordance and emits {@link rowClick}
60438
- * (clicks landing on interactive cell content are ignored - see `rowClick`). @default false
60448
+ * (clicks landing on interactive cell content are ignored - see `rowClick`). For a row that
60449
+ * navigates, prefer {@link rowLink} - a real link, not a click handler. @default false
60439
60450
  */
60440
60451
  this.rowInteractive = input(false, { ...(ngDevMode ? { debugName: "rowInteractive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
60452
+ /**
60453
+ * Make every row a link, by saying where it goes: an `href` the browser follows, or the router
60454
+ * commands to navigate to - which need `etTableRowRouterLink` on the table, since the base table
60455
+ * depends on no router. Answer `null` for a row that links nowhere.
60456
+ *
60457
+ * The table renders **one** real `<a href>` per row and stretches it over the row, so middle click,
60458
+ * Ctrl/Cmd-click, "open in a new tab" and "copy link address" all work - none of which a
60459
+ * {@link rowInteractive} click handler can offer. The anchor sits in the first column that holds no
60460
+ * controls of its own and takes its accessible name from that cell, which keeps the row one link in
60461
+ * the accessibility tree and one stop in the tab order.
60462
+ *
60463
+ * A cell with a control in it keeps its clicks: the selection and expander cells always, and any
60464
+ * column that declares `interactive: true`.
60465
+ *
60466
+ * @example
60467
+ * <et-table [rowsSource]="source" [columns]="columns()" [rowLink]="orderLink" etTableRowRouterLink />
60468
+ *
60469
+ * protected orderLink = (order: Order) => ['/orders', order.id];
60470
+ */
60471
+ this.rowLink = input(/* @ts-ignore */
60472
+ ...(ngDevMode ? [undefined, { debugName: "rowLink" }] : /* istanbul ignore next */ []));
60441
60473
  /**
60442
60474
  * Emitted when an interactive row (see {@link rowInteractive}) is clicked, with the row as payload.
60443
60475
  * Clicks originating from interactive descendants - buttons, links, inputs, selects, a menu trigger,
@@ -60450,6 +60482,8 @@ class TableComponent {
60450
60482
  // renders only when there's actually footer content.
60451
60483
  this.footerSlot = contentChild(TableFooterDirective, /* @ts-ignore */
60452
60484
  ...(ngDevMode ? [{ debugName: "footerSlot" }] : /* istanbul ignore next */ []));
60485
+ this.gridRef = viewChild('grid', /* @ts-ignore */
60486
+ ...(ngDevMode ? [{ debugName: "gridRef" }] : /* istanbul ignore next */ []));
60453
60487
  this.headerCells = viewChildren('headerCell', /* @ts-ignore */
60454
60488
  ...(ngDevMode ? [{ debugName: "headerCells" }] : /* istanbul ignore next */ []));
60455
60489
  // Every rendered body cell (tagged with `data-col-key`); the first drives virtual-window
@@ -60460,6 +60494,11 @@ class TableComponent {
60460
60494
  // the pinned data columns know how far in they start.
60461
60495
  this.leadHeaderCells = viewChildren('leadHeaderCell', /* @ts-ignore */
60462
60496
  ...(ngDevMode ? [{ debugName: "leadHeaderCells" }] : /* istanbul ignore next */ []));
60497
+ // The same for the trailing utility columns, stacked from the trailing edge instead.
60498
+ this.trailHeaderCells = viewChildren('trailHeaderCell', /* @ts-ignore */
60499
+ ...(ngDevMode ? [{ debugName: "trailHeaderCells" }] : /* istanbul ignore next */ []));
60500
+ // Base of the ids a row link is named by - one per table, so two tables on a page can't collide.
60501
+ this.LINK_ID_PREFIX = `et-table-${uniqueTableId++}-row-link`;
60463
60502
  /** The sort mode in effect: what you set, else `'server'` when a {@link rowsSource} is bound. */
60464
60503
  this.resolvedSortMode = computed(() => this.sortMode() ?? (this.rowsSource() ? 'server' : 'client'), /* @ts-ignore */
60465
60504
  ...(ngDevMode ? [{ debugName: "resolvedSortMode" }] : /* istanbul ignore next */ []));
@@ -60494,6 +60533,12 @@ class TableComponent {
60494
60533
  ...(ngDevMode ? [{ debugName: "cellErrorMarkList" }] : /* istanbul ignore next */ []));
60495
60534
  this.cellErrorMark = computed(() => this.cellErrorMarkList().find((mark) => mark.enabled?.() ?? true) ?? null, /* @ts-ignore */
60496
60535
  ...(ngDevMode ? [{ debugName: "cellErrorMark" }] : /* istanbul ignore next */ []));
60536
+ // How a feature follows a row link given as router commands (etTableRowRouterLink). Null until one
60537
+ // registers, which is what keeps the router out of a table that links with plain hrefs - or not at all.
60538
+ this.rowNavigationList = signal([], /* @ts-ignore */
60539
+ ...(ngDevMode ? [{ debugName: "rowNavigationList" }] : /* istanbul ignore next */ []));
60540
+ this.rowNavigation = computed(() => this.rowNavigationList().find((navigation) => navigation.enabled?.() ?? true) ?? null, /* @ts-ignore */
60541
+ ...(ngDevMode ? [{ debugName: "rowNavigation" }] : /* istanbul ignore next */ []));
60497
60542
  // Floating UI contributed by features (the reorder drag ghost). The table hosts it so a feature
60498
60543
  // never needs a view - and never an element - of its own.
60499
60544
  this.layerList = signal([], /* @ts-ignore */
@@ -60561,17 +60606,44 @@ class TableComponent {
60561
60606
  // during an `autosizeColumns` pass.
60562
60607
  this.autosizing = signal(new Set(), /* @ts-ignore */
60563
60608
  ...(ngDevMode ? [{ debugName: "autosizing" }] : /* istanbul ignore next */ []));
60564
- /**
60565
- * Where content is currently scrolled out of view horizontally. Drives the edge gradients: they mark
60566
- * the boundary the rows disappear under, which is *not* the viewport edge when columns are pinned -
60567
- * a pinned column is the thing they slide beneath, so the fade sits at its inner edge instead. That
60568
- * offset is what a generic scroll-fade wrapper can't know, so the table draws its own.
60569
- */
60609
+ /** Where content is currently scrolled out of view horizontally. */
60570
60610
  this.scrollFades = signal({ start: false, end: false }, /* @ts-ignore */
60571
60611
  ...(ngDevMode ? [{ debugName: "scrollFades" }] : /* istanbul ignore next */ []));
60612
+ /** The columns currently covered by a pinned one - see {@link syncObscuredColumns}. */
60613
+ this.obscuredColumns = signal(EMPTY_COLUMN_KEYS, /* @ts-ignore */
60614
+ ...(ngDevMode ? [{ debugName: "obscuredColumns" }] : /* istanbul ignore next */ []));
60615
+ /**
60616
+ * Whether rows are currently passing under the sticky header, and whether more follow under the footer
60617
+ * bar. Both edges cut a row off mid-height - on `cards`, mid-card - and a cut with nothing to explain
60618
+ * it reads as a broken box, so each edge casts a shadow while there is something behind it.
60619
+ */
60620
+ this.blockScrollShadows = signal({
60621
+ blockStart: false,
60622
+ blockEnd: false,
60623
+ }, /* @ts-ignore */
60624
+ ...(ngDevMode ? [{ debugName: "blockScrollShadows" }] : /* istanbul ignore next */ []));
60572
60625
  /** The inline offset (px) each edge gradient is pushed in by, so it clears any pinned columns. */
60573
60626
  this.fadeInset = computed(() => this.columnPinning()?.insets() ?? NO_INSET, /* @ts-ignore */
60574
60627
  ...(ngDevMode ? [{ debugName: "fadeInset" }] : /* istanbul ignore next */ []));
60628
+ /**
60629
+ * The scroll viewport's own inline size, published as a custom property for the rules that have to
60630
+ * span it rather than the tracks - the empty and the error message. A row spans every column, which
60631
+ * on a table wider than its viewport is not where the reader is looking.
60632
+ */
60633
+ this.viewportInlineSize = computed(() => this.hostDimensions().client?.width ?? null, /* @ts-ignore */
60634
+ ...(ngDevMode ? [{ debugName: "viewportInlineSize" }] : /* istanbul ignore next */ []));
60635
+ /**
60636
+ * Which edge gradients actually show. A gradient marks the boundary rows slide out under - so an edge
60637
+ * that pins a column has one already: the pinned cells' own edge shadow, drawn per row. Two marks on
60638
+ * the same boundary read as a smear, and the gradient is the one that has to go: it spans the whole
60639
+ * grid, so on `cards` it paints across the gaps between them as well.
60640
+ */
60641
+ this.visibleScrollFades = computed(() => {
60642
+ const scrolled = this.scrollFades();
60643
+ const inset = this.fadeInset();
60644
+ return { start: scrolled.start && inset.start === 0, end: scrolled.end && inset.end === 0 };
60645
+ }, /* @ts-ignore */
60646
+ ...(ngDevMode ? [{ debugName: "visibleScrollFades" }] : /* istanbul ignore next */ []));
60575
60647
  // The declared columns paired with their keys, in declaration order - the form everything else
60576
60648
  // (rendering, features, state) works with. Keys are the record's, so they can't collide.
60577
60649
  this.columnDefs = computed(() => Object.entries(this.columns()).map(([key, column]) => ({ ...column, key })), /* @ts-ignore */
@@ -60636,11 +60708,17 @@ class TableComponent {
60636
60708
  return this.visibleColumns().some((column) => footers.has(column.key));
60637
60709
  }, /* @ts-ignore */
60638
60710
  ...(ngDevMode ? [{ debugName: "hasFooter" }] : /* istanbul ignore next */ []));
60639
- /** The leading utility columns in render order - whatever features registered (selection, expansion). */
60640
- this.leadColumns = computed(() => this.leadColumnList()
60711
+ // Every live utility column, in render order within its own side.
60712
+ this.utilityColumns = computed(() => this.leadColumnList()
60641
60713
  .filter((lead) => lead.enabled?.() ?? true)
60642
60714
  .sort((a, b) => (a.order ?? 0) - (b.order ?? 0)), /* @ts-ignore */
60715
+ ...(ngDevMode ? [{ debugName: "utilityColumns" }] : /* istanbul ignore next */ []));
60716
+ /** The leading utility columns in render order - whatever features registered (selection, expansion). */
60717
+ this.leadColumns = computed(() => this.utilityColumns().filter((column) => (column.side?.() ?? 'start') === 'start'), /* @ts-ignore */
60643
60718
  ...(ngDevMode ? [{ debugName: "leadColumns" }] : /* istanbul ignore next */ []));
60719
+ /** The trailing utility columns in render order - those a feature registered with `side: 'end'`. */
60720
+ this.trailColumns = computed(() => this.utilityColumns().filter((column) => column.side?.() === 'end'), /* @ts-ignore */
60721
+ ...(ngDevMode ? [{ debugName: "trailColumns" }] : /* istanbul ignore next */ []));
60644
60722
  /**
60645
60723
  * The column tracks, plus whether they are all rigid.
60646
60724
  *
@@ -60668,11 +60746,16 @@ class TableComponent {
60668
60746
  !measuring.size &&
60669
60747
  !tracks.some(isFlexibleTrack) &&
60670
60748
  !(this.columnPinning()?.hasStickyEnd() ?? false);
60671
- // Leading utility columns come first, in registration order (see `leadColumns`). Their widths are
60672
- // px, not rem: they must fit their control (a 24px button / 16px checkbox plus the cell's 4px
60673
- // inline padding) regardless of the host app's root font size.
60749
+ // Utility columns bracket the data columns, in registration order (see `leadColumns`). Their widths
60750
+ // are px, not rem: they must fit their control (a 24px button / 16px checkbox plus the cell's 4px
60751
+ // inline padding) regardless of the host app's root font size. A trailing one goes after the filler,
60752
+ // so the slack sits between the data and it rather than pushing it off the panel's edge.
60674
60753
  const leads = this.leadColumns().map((lead) => lead.width);
60675
- return { template: [...leads, ...tracks, ...(fixed ? [FILLER_TRACK] : [])].join(' '), fixed };
60754
+ const trails = this.trailColumns().map((trail) => trail.width);
60755
+ return {
60756
+ template: [...leads, ...tracks, ...(fixed ? [FILLER_TRACK] : []), ...trails].join(' '),
60757
+ fixed,
60758
+ };
60676
60759
  }, /* @ts-ignore */
60677
60760
  ...(ngDevMode ? [{ debugName: "columnTracks" }] : /* istanbul ignore next */ []));
60678
60761
  /** The `grid-template-columns` value for the visible columns (plus a leading expander track when expandable). */
@@ -60685,6 +60768,17 @@ class TableComponent {
60685
60768
  */
60686
60769
  this.hasFiller = computed(() => this.columnTracks().fixed, /* @ts-ignore */
60687
60770
  ...(ngDevMode ? [{ debugName: "hasFiller" }] : /* istanbul ignore next */ []));
60771
+ // Set while the sort the user just asked for renders, cleared once its animation has run. A sort that
60772
+ // arrives from a URL, a restored state or a bound source mounts the arrow too, and that one has to
60773
+ // appear already there rather than fade in over a table the reader is still taking in.
60774
+ this.sortGesture = signal(false, /* @ts-ignore */
60775
+ ...(ngDevMode ? [{ debugName: "sortGesture" }] : /* istanbul ignore next */ []));
60776
+ /** The arrow's enter animation, empty unless the sort was a gesture on this table. */
60777
+ this.sortIndicatorEnter = computed(() => (this.sortGesture() ? 'et-table-sort-indicator--enter' : ''), /* @ts-ignore */
60778
+ ...(ngDevMode ? [{ debugName: "sortIndicatorEnter" }] : /* istanbul ignore next */ []));
60779
+ /** The same for the arrow of a column the gesture unsorted. */
60780
+ this.sortIndicatorLeave = computed(() => (this.sortGesture() ? 'et-table-sort-indicator--leave' : ''), /* @ts-ignore */
60781
+ ...(ngDevMode ? [{ debugName: "sortIndicatorLeave" }] : /* istanbul ignore next */ []));
60688
60782
  /** The serializable, versioned table state - column order, visibility, sort, filters and feature slices. */
60689
60783
  this.state = computed(() => {
60690
60784
  const sort = this.sort();
@@ -60780,6 +60874,28 @@ class TableComponent {
60780
60874
  * nothing behind but a flicker under the header.
60781
60875
  */
60782
60876
  this.showBusyBar = signalDeferredLoading(this.refetchingOverRows);
60877
+ /**
60878
+ * Whether a body row gets a box of its own instead of being layout-transparent - a subgrid spanning
60879
+ * every track (see `.et-table-row--box`).
60880
+ *
60881
+ * Opt-in, because a box changes the containing block of everything positioned inside a row: a pinned
60882
+ * column, the row's own link. A card row needs one to paint, and a stretched row link needs one to
60883
+ * stretch over.
60884
+ */
60885
+ this.rowBox = computed(() => this.appearance() === 'cards' || !!this.rowLink(), /* @ts-ignore */
60886
+ ...(ngDevMode ? [{ debugName: "rowBox" }] : /* istanbul ignore next */ []));
60887
+ /**
60888
+ * The column whose cell hosts a row's link: the first visible one that doesn't hold controls of its
60889
+ * own, else the first visible one. Its content is what names the link, so it should be the column a
60890
+ * reader identifies the row by - which is what the leftmost column usually is.
60891
+ */
60892
+ this.linkColumnKey = computed(() => {
60893
+ if (!this.rowLink())
60894
+ return null;
60895
+ const columns = this.visibleColumns();
60896
+ return (columns.find((column) => !column.interactive) ?? columns[0])?.key ?? null;
60897
+ }, /* @ts-ignore */
60898
+ ...(ngDevMode ? [{ debugName: "linkColumnKey" }] : /* istanbul ignore next */ []));
60783
60899
  /** The leading utility cells, with the pinning every row kind applies to them. */
60784
60900
  this.leadCells = computed(() => {
60785
60901
  const pinning = this.columnPinning();
@@ -60791,10 +60907,22 @@ class TableComponent {
60791
60907
  }));
60792
60908
  }, /* @ts-ignore */
60793
60909
  ...(ngDevMode ? [{ debugName: "leadCells" }] : /* istanbul ignore next */ []));
60910
+ /** The trailing utility cells - the same, pinned to the trailing edge instead. */
60911
+ this.trailCells = computed(() => {
60912
+ const pinning = this.columnPinning();
60913
+ return this.trailColumns().map((trail) => ({
60914
+ key: trail.key,
60915
+ cellClass: trail.cellClass,
60916
+ ...(pinning?.trailPinning(trail.key) ?? NO_LEAD_PIN),
60917
+ lead: trail,
60918
+ }));
60919
+ }, /* @ts-ignore */
60920
+ ...(ngDevMode ? [{ debugName: "trailCells" }] : /* istanbul ignore next */ []));
60794
60921
  this.headerCellVms = computed(() => {
60795
60922
  const pinning = this.columnPinning();
60796
60923
  const templates = this.columnTemplates().header;
60797
60924
  const labels = this.resolvedLabels();
60925
+ const obscured = this.obscuredColumns();
60798
60926
  return this.visibleColumns().map((column) => {
60799
60927
  const direction = this.sortDirection(column.key);
60800
60928
  // The header announces what the *next* activation does, and the cycle is asc → desc → clear.
@@ -60815,34 +60943,70 @@ class TableComponent {
60815
60943
  sortLabel: column.sortable ? labels.sortAction(column.header ?? column.key, next) : null,
60816
60944
  direction,
60817
60945
  template: templates.get(column.key) ?? null,
60946
+ obscured: obscured.has(column.key),
60818
60947
  };
60819
60948
  });
60820
60949
  }, /* @ts-ignore */
60821
60950
  ...(ngDevMode ? [{ debugName: "headerCellVms" }] : /* istanbul ignore next */ []));
60951
+ this.footerCells = computed(() => {
60952
+ const pinning = this.columnPinning();
60953
+ const templates = this.columnTemplates().footer;
60954
+ return this.visibleColumns().map((column) => ({
60955
+ ...(pinning?.cellPinning(column.key) ?? NO_PIN),
60956
+ key: column.key,
60957
+ align: column.align ?? 'start',
60958
+ template: templates.get(column.key) ?? null,
60959
+ }));
60960
+ }, /* @ts-ignore */
60961
+ ...(ngDevMode ? [{ debugName: "footerCells" }] : /* istanbul ignore next */ []));
60962
+ /** Spacer sizes standing in for the rows a window leaves out, or `null` when every row renders. */
60963
+ this.spacers = computed(() => {
60964
+ const window = this.rowWindow();
60965
+ if (!window || !this.rows().length)
60966
+ return null;
60967
+ return { start: window.paddingStart(), end: window.paddingEnd() };
60968
+ }, /* @ts-ignore */
60969
+ ...(ngDevMode ? [{ debugName: "spacers" }] : /* istanbul ignore next */ []));
60822
60970
  this.bodyRows = computed(() => {
60823
60971
  const pinning = this.columnPinning();
60824
60972
  const templates = this.columnTemplates().cell;
60825
60973
  const columns = this.visibleColumns();
60826
60974
  const leads = this.leadCells();
60975
+ const trails = this.trailCells();
60827
60976
  const cellState = this.cellState();
60828
60977
  const indexOffset = this.rowIndexOffset();
60829
60978
  const detail = this.rowDetail();
60830
60979
  // At most one cell is ever open, so the edit templates are only looked up once there is one.
60831
60980
  const editing = this.cellEditing()?.cell() ?? null;
60832
60981
  const editTemplates = editing ? this.columnTemplates().cellEdit : null;
60833
- return this.renderedRows().map((row, index) => {
60982
+ const rowLink = this.rowLink();
60983
+ const linkColumn = this.linkColumnKey();
60984
+ const navigation = this.rowNavigation();
60985
+ const rendered = this.renderedRows();
60986
+ // A footer row separates itself with this rule, and an end spacer stands in for rows still below.
60987
+ const endsWithRows = !this.hasFooter() && !this.spacers()?.end;
60988
+ return rendered.map((row, index) => {
60834
60989
  const key = this.rowIdentity(row);
60990
+ const link = rowLink?.(row) ?? null;
60991
+ // A string is an href as given; commands are a URL only a navigator can build, so a table without
60992
+ // one renders no link at all rather than a wrong one (see the dev-mode check in the constructor).
60993
+ const href = link === null ? null : typeof link === 'string' ? link : (navigation?.href(link) ?? null);
60835
60994
  return {
60836
60995
  row,
60837
60996
  key,
60838
60997
  index: indexOffset + index,
60839
- classes: leads
60840
- .map((lead) => lead.lead.rowClass?.(row))
60998
+ link,
60999
+ href,
61000
+ linkLabelId: `${this.LINK_ID_PREFIX}-${indexOffset + index}`,
61001
+ classes: [...leads, ...trails]
61002
+ .map((utility) => utility.lead.rowClass?.(row))
60841
61003
  .filter((className) => !!className)
60842
61004
  .join(' '),
60843
61005
  stripe: (indexOffset + index) % 2 === 1,
61006
+ last: endsWithRows && index === rendered.length - 1,
60844
61007
  detail: detail?.isOpen(row) ? detail : null,
60845
61008
  leads,
61009
+ trails,
60846
61010
  cells: columns.map((column) => {
60847
61011
  const value = column.value(row);
60848
61012
  // The callback may answer with the bare state or with a message alongside it.
@@ -60855,6 +61019,8 @@ class TableComponent {
60855
61019
  ...(pinning?.cellPinning(column.key) ?? NO_PIN),
60856
61020
  key: column.key,
60857
61021
  align: column.align ?? 'start',
61022
+ linkHost: href !== null && column.key === linkColumn,
61023
+ interactive: !!column.interactive,
60858
61024
  state,
60859
61025
  message: typeof answer === 'string' ? null : (answer?.message ?? null),
60860
61026
  template: templates.get(column.key) ?? null,
@@ -60867,25 +61033,6 @@ class TableComponent {
60867
61033
  });
60868
61034
  }, /* @ts-ignore */
60869
61035
  ...(ngDevMode ? [{ debugName: "bodyRows" }] : /* istanbul ignore next */ []));
60870
- this.footerCells = computed(() => {
60871
- const pinning = this.columnPinning();
60872
- const templates = this.columnTemplates().footer;
60873
- return this.visibleColumns().map((column) => ({
60874
- ...(pinning?.cellPinning(column.key) ?? NO_PIN),
60875
- key: column.key,
60876
- align: column.align ?? 'start',
60877
- template: templates.get(column.key) ?? null,
60878
- }));
60879
- }, /* @ts-ignore */
60880
- ...(ngDevMode ? [{ debugName: "footerCells" }] : /* istanbul ignore next */ []));
60881
- /** Spacer sizes standing in for the rows a window leaves out, or `null` when every row renders. */
60882
- this.spacers = computed(() => {
60883
- const window = this.rowWindow();
60884
- if (!window || !this.rows().length)
60885
- return null;
60886
- return { start: window.paddingStart(), end: window.paddingEnd() };
60887
- }, /* @ts-ignore */
60888
- ...(ngDevMode ? [{ debugName: "spacers" }] : /* istanbul ignore next */ []));
60889
61036
  /**
60890
61037
  * The keys of the currently hidden columns, in declared order. Nothing in the table's own chrome
60891
61038
  * shows a hidden column - the column menu's "Hide column" takes one away and has no way back - so
@@ -60908,6 +61055,8 @@ class TableComponent {
60908
61055
  */
60909
61056
  this.allColumns = computed(() => this.orderedColumns(), /* @ts-ignore */
60910
61057
  ...(ngDevMode ? [{ debugName: "allColumns" }] : /* istanbul ignore next */ []));
61058
+ // Which feature owns the drag each live pointer started - see claimPointerGesture.
61059
+ this.pointerGestureClaims = new Map();
60911
61060
  // A detail template with nothing to render it looks like a broken template rather than a missing
60912
61061
  // import, so name the mistake. Deferred to an effect because a feature registers from its own
60913
61062
  // constructor, which runs after the table's - and it asks whether one registered at all rather
@@ -60918,6 +61067,17 @@ class TableComponent {
60918
61067
  return;
60919
61068
  throw new RuntimeError(TABLE_ERROR_CODES.MISSING_ROW_EXPANSION, '[et-table] [expandedRowTemplate] needs the row-expansion feature to render it. Add `etTableRowExpansion` to the table and import TABLE_ROW_EXPANSION_IMPORTS.', { element: this.elementRef.nativeElement });
60920
61069
  });
61070
+ // Router commands are a URL only the router can build, so such a row would otherwise render as a
61071
+ // row that looks like a link and leads nowhere. Asked of the rendered rows rather than of the
61072
+ // callback, since only a returned value says which form a table uses.
61073
+ effect(() => {
61074
+ const rowLink = this.rowLink();
61075
+ if (!rowLink || this.rowNavigationList().length)
61076
+ return;
61077
+ if (!this.renderedRows().some((row) => Array.isArray(rowLink(row))))
61078
+ return;
61079
+ throw new RuntimeError(TABLE_ERROR_CODES.MISSING_ROW_ROUTER_LINK, '[et-table] [rowLink] answered with router commands, which need the router feature to resolve them. Add `etTableRowRouterLink` to the table and import TABLE_ROW_ROUTER_LINK_IMPORTS, or answer with an href string instead.', { element: this.elementRef.nativeElement });
61080
+ });
60921
61081
  }
60922
61082
  // A bound rows source owns the sort/filter state, but everything here - features, `state()`, the
60923
61083
  // header models - reads `sort()` / `filters()`. Mirror the source into them rather than teaching
@@ -60941,10 +61101,10 @@ class TableComponent {
60941
61101
  effect(() => {
60942
61102
  this.hostDimensions();
60943
61103
  this.templateColumns();
60944
- afterNextRender({ read: () => this.syncScrollFades() }, { injector: this.injector });
61104
+ afterNextRender({ read: () => this.syncScrollState() }, { injector: this.injector });
60945
61105
  });
60946
61106
  }
60947
- syncScrollFades() {
61107
+ syncScrollState() {
60948
61108
  const element = this.elementRef.nativeElement;
60949
61109
  // `scrollLeft` counts down from 0 in RTL, so compare distances rather than raw offsets.
60950
61110
  const offset = Math.abs(element.scrollLeft);
@@ -60953,6 +61113,16 @@ class TableComponent {
60953
61113
  const current = this.scrollFades();
60954
61114
  if (next.start !== current.start || next.end !== current.end)
60955
61115
  this.scrollFades.set(next);
61116
+ const below = element.scrollHeight - element.clientHeight - element.scrollTop;
61117
+ const shadows = {
61118
+ blockStart: element.scrollTop > SCROLL_FADE_EPSILON,
61119
+ blockEnd: below > SCROLL_FADE_EPSILON,
61120
+ };
61121
+ const currentShadows = this.blockScrollShadows();
61122
+ if (shadows.blockStart !== currentShadows.blockStart || shadows.blockEnd !== currentShadows.blockEnd) {
61123
+ this.blockScrollShadows.set(shadows);
61124
+ }
61125
+ this.syncObscuredColumns();
60956
61126
  }
60957
61127
  /**
60958
61128
  * A template registered for one of a column's slots, or `null`. Part of the feature contract - the
@@ -61052,6 +61222,13 @@ class TableComponent {
61052
61222
  registerColumnPinning(pinning) {
61053
61223
  this.columnPinningList.update((list) => [...list, pinning]);
61054
61224
  }
61225
+ /**
61226
+ * Called by an opt-in feature to resolve and follow row links given as router commands
61227
+ * (`etTableRowRouterLink`). Part of the feature contract; consumers never call this.
61228
+ */
61229
+ registerRowNavigation(navigation) {
61230
+ this.rowNavigationList.update((list) => [...list, navigation]);
61231
+ }
61055
61232
  /** The rendered header cells of the leading utility columns. Part of the feature contract. */
61056
61233
  leadHeaderCellElements() {
61057
61234
  return this.leadHeaderCells().map((ref) => ref.nativeElement);
@@ -61060,10 +61237,22 @@ class TableComponent {
61060
61237
  leadColumnsMeta() {
61061
61238
  return this.leadColumns().map((lead) => ({ key: lead.key, cellClass: lead.cellClass }));
61062
61239
  }
61240
+ /** The rendered header cells of the trailing utility columns. Part of the feature contract. */
61241
+ trailHeaderCellElements() {
61242
+ return this.trailHeaderCells().map((ref) => ref.nativeElement);
61243
+ }
61244
+ /** The trailing utility columns, in render order. Part of the feature contract. */
61245
+ trailColumnsMeta() {
61246
+ return this.trailColumns().map((trail) => ({ key: trail.key, cellClass: trail.cellClass }));
61247
+ }
61063
61248
  /** Whether a trailing slack track is in play. Part of the feature contract. */
61064
61249
  hasFillerTrack() {
61065
61250
  return this.hasFiller();
61066
61251
  }
61252
+ /** Whether rows have a box of their own (a card, a row link). Part of the feature contract. */
61253
+ hasRowBox() {
61254
+ return this.rowBox();
61255
+ }
61067
61256
  /** The `expandedRowTemplate` input, type-erased for the feature contract. */
61068
61257
  detailTemplate() {
61069
61258
  return this.expandedRowTemplate() ?? null;
@@ -61090,6 +61279,29 @@ class TableComponent {
61090
61279
  editCell(rowIndex, columnIndex) {
61091
61280
  return this.cellEditing()?.editCell(rowIndex, columnIndex) ?? false;
61092
61281
  }
61282
+ /** What a pinned block covers at each inline edge. Part of the feature contract. */
61283
+ frozenInsets() {
61284
+ return this.fadeInset();
61285
+ }
61286
+ /**
61287
+ * Claim the drag a pointer started for one feature. Part of the feature contract - it is how
61288
+ * `etTableReorder` keeps a header drag away from `etTableDragScroll` without either knowing about
61289
+ * the other. Consumers never call this.
61290
+ */
61291
+ claimPointerGesture(event, feature) {
61292
+ const { pointerId } = event;
61293
+ this.pointerGestureClaims.set(pointerId, feature);
61294
+ // Released off the document, not off the table: a pointer let go outside the table sends its
61295
+ // `pointerup` nowhere near this element, and a claim left behind would block the next gesture
61296
+ // that reuses the id.
61297
+ merge(fromEvent(this.document, 'pointerup'), fromEvent(this.document, 'pointercancel'))
61298
+ .pipe(filter((ended) => ended.pointerId === pointerId), take(1), tap(() => this.pointerGestureClaims.delete(pointerId)), takeUntilDestroyed(this.destroyRef))
61299
+ .subscribe();
61300
+ }
61301
+ /** Which feature claimed this pointer's drag, or `null`. Part of the feature contract. */
61302
+ pointerGestureClaim(event) {
61303
+ return this.pointerGestureClaims.get(event.pointerId) ?? null;
61304
+ }
61093
61305
  /** A rendered body cell, for a feature measuring real row height. Part of the feature contract. */
61094
61306
  firstBodyCellElement() {
61095
61307
  return this.bodyCells()[0]?.nativeElement ?? null;
@@ -61142,7 +61354,11 @@ class TableComponent {
61142
61354
  return 1;
61143
61355
  return Math.max(1, Math.floor(viewport / rowHeight) - 1);
61144
61356
  }
61145
- /** Apply a previously captured {@link TableState} - column order, visibility, sort, filters and feature slices. */
61357
+ /**
61358
+ * Apply a previously captured {@link TableState} - column order, visibility, sort, filters and feature
61359
+ * slices. A bound {@link rowsSource} keeps the sort and the filters it publishes; only the layout and
61360
+ * the feature slices are restored onto such a table.
61361
+ */
61146
61362
  restoreState(next) {
61147
61363
  this.columnOrder.set(next.columns.map((column) => column.key));
61148
61364
  this.hiddenColumns.set(new Set(next.columns.filter((column) => column.hidden).map((column) => column.key)));
@@ -61152,15 +61368,24 @@ class TableComponent {
61152
61368
  widths[column.key] = column.width;
61153
61369
  }
61154
61370
  this.columnWidths.set(widths);
61155
- const sort = next.columns
61156
- .filter((column) => column.sort)
61157
- .sort((a, b) => (a.sortPriority ?? 0) - (b.sortPriority ?? 0))
61158
- .map((column) => ({ key: column.key, direction: column.sort }));
61159
- this.sort.set(sort);
61160
- const filters = next.columns
61161
- .filter((column) => column.filterValues?.length)
61162
- .map((column) => ({ key: column.key, values: column.filterValues ?? [] }));
61163
- this.filters.set(filters);
61371
+ // Whatever a bound source publishes, it owns (see the constructor). Writing it from a restored
61372
+ // state would leave the mirror holding a value the source never had: the source does not change,
61373
+ // so the effect does not re-run to correct it. A layout-only state would silently drop the sort
61374
+ // arrow off a header whose rows are still sorted.
61375
+ const source = this.rowsSource();
61376
+ if (!source?.sort) {
61377
+ const sort = next.columns
61378
+ .filter((column) => column.sort)
61379
+ .sort((a, b) => (a.sortPriority ?? 0) - (b.sortPriority ?? 0))
61380
+ .map((column) => ({ key: column.key, direction: column.sort }));
61381
+ this.sort.set(sort);
61382
+ }
61383
+ if (!source?.filters) {
61384
+ const filters = next.columns
61385
+ .filter((column) => column.filterValues?.length)
61386
+ .map((column) => ({ key: column.key, values: column.filterValues ?? [] }));
61387
+ this.filters.set(filters);
61388
+ }
61164
61389
  // Hand each feature its own slice back. A slice with no matching feature (it wasn't imported here)
61165
61390
  // is left alone rather than dropped, so a round-trip through a table that lacks a feature doesn't
61166
61391
  // erase that feature's state elsewhere.
@@ -61271,6 +61496,17 @@ class TableComponent {
61271
61496
  event.preventDefault();
61272
61497
  this.rowClick.emit(row);
61273
61498
  }
61499
+ /**
61500
+ * Follow a row link the browser would otherwise load as a whole page. Only a link given as router
61501
+ * commands is followed, and only on a plain left click - a middle or Ctrl/Cmd-click keeps the
61502
+ * browser's own behaviour, which is the reason the row carries a real `href` at all.
61503
+ */
61504
+ activateRowLink(link, event) {
61505
+ if (link === null || typeof link === 'string')
61506
+ return;
61507
+ if (this.rowNavigation()?.navigate(link, event))
61508
+ event.preventDefault();
61509
+ }
61274
61510
  /**
61275
61511
  * Stable identity for row-keyed state (change tracking, expansion, selection): the string form of
61276
61512
  * `rowKey` (so it matches its serialized form regardless of string/number), or the row reference.
@@ -61287,6 +61523,10 @@ class TableComponent {
61287
61523
  visibleColumnsMeta() {
61288
61524
  return this.visibleColumns();
61289
61525
  }
61526
+ /** The grid itself, for a feature measuring the whole of it. Part of the feature contract. */
61527
+ gridElement() {
61528
+ return this.gridRef()?.nativeElement ?? null;
61529
+ }
61290
61530
  /** The rendered header cells, ordered like {@link visibleColumnsMeta}. Part of the feature contract. */
61291
61531
  headerCellElements() {
61292
61532
  return this.headerCells().map((ref) => ref.nativeElement);
@@ -61386,12 +61626,52 @@ class TableComponent {
61386
61626
  return next;
61387
61627
  });
61388
61628
  }
61629
+ // Which columns have scrolled behind a pinned one. Their cells are hidden by the pinned cells' own
61630
+ // opaque fill, but anything a feature hangs off a header cell in a portal - a filter menu, a column
61631
+ // menu - is not: it floats over the pinned column, anchored to a cell nobody can see. floating-ui's
61632
+ // own `referenceHidden` can't catch this either, since the cell is clipped by nothing; it is covered.
61633
+ // So the table says when a column is covered, and the header drops its adornments.
61634
+ syncObscuredColumns() {
61635
+ const inset = this.fadeInset();
61636
+ if (inset.start === 0 && inset.end === 0) {
61637
+ if (this.obscuredColumns().size)
61638
+ this.obscuredColumns.set(EMPTY_COLUMN_KEYS);
61639
+ return;
61640
+ }
61641
+ const cells = this.headerCells();
61642
+ const columns = this.visibleColumns();
61643
+ // One live read per scroll tick over the header row only, which is what this has to compare against
61644
+ // the pinned edges - `signalElementDimensions` observes a single element and never sees a scroll.
61645
+ const host = this.elementRef.nativeElement.getBoundingClientRect();
61646
+ const startEdge = host.left + inset.start;
61647
+ const endEdge = host.right - inset.end;
61648
+ const next = new Set();
61649
+ columns.forEach((column, index) => {
61650
+ if (column.sticky)
61651
+ return;
61652
+ const cell = cells[index]?.nativeElement;
61653
+ if (!cell)
61654
+ return;
61655
+ const rect = cell.getBoundingClientRect();
61656
+ if (rect.right <= startEdge || rect.left >= endEdge)
61657
+ next.add(column.key);
61658
+ });
61659
+ const current = this.obscuredColumns();
61660
+ const changed = next.size !== current.size || [...next].some((key) => !current.has(key));
61661
+ if (changed)
61662
+ this.obscuredColumns.set(next);
61663
+ }
61389
61664
  /**
61390
61665
  * The one place sort state is written. A bound {@link rowsSource} owns it - it resets the page and
61391
61666
  * refetches - and its own value syncs back into `sort` (see the constructor), so everything else can
61392
61667
  * keep reading `sort()` whichever drives it.
61393
61668
  */
61394
61669
  applySort(sort) {
61670
+ this.sortGesture.set(true);
61671
+ this.sortGestureReset?.unsubscribe();
61672
+ this.sortGestureReset = timer(SORT_INDICATOR_ANIMATION_MS)
61673
+ .pipe(tap(() => this.sortGesture.set(false)), takeUntilDestroyed(this.destroyRef))
61674
+ .subscribe();
61395
61675
  const source = this.rowsSource();
61396
61676
  if (source?.setSort) {
61397
61677
  source.setSort(sort);
@@ -61423,10 +61703,10 @@ class TableComponent {
61423
61703
  return false;
61424
61704
  }
61425
61705
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
61426
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TableComponent, isStandalone: true, selector: "et-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, rowsSource: { classPropertyName: "rowsSource", publicName: "rowsSource", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, errorTemplate: { classPropertyName: "errorTemplate", publicName: "errorTemplate", isSignal: true, isRequired: false, transformFunction: null }, cellState: { classPropertyName: "cellState", publicName: "cellState", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, multiSort: { classPropertyName: "multiSort", publicName: "multiSort", isSignal: true, isRequired: false, transformFunction: null }, sortMode: { classPropertyName: "sortMode", publicName: "sortMode", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, filterMode: { classPropertyName: "filterMode", publicName: "filterMode", isSignal: true, isRequired: false, transformFunction: null }, expandedRowTemplate: { classPropertyName: "expandedRowTemplate", publicName: "expandedRowTemplate", isSignal: true, isRequired: false, transformFunction: null }, rowInteractive: { classPropertyName: "rowInteractive", publicName: "rowInteractive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sortChange", filters: "filtersChange", rowClick: "rowClick" }, host: { listeners: { "scroll": "syncScrollFades()" }, properties: { "attr.data-appearance": "appearance()", "attr.data-density": "density()", "attr.aria-busy": "resolvedLoading() ? \"true\" : null" }, classAttribute: "et-table-host" }, providers: [
61706
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TableComponent, isStandalone: true, selector: "et-table", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, rowsSource: { classPropertyName: "rowsSource", publicName: "rowsSource", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null }, errorTemplate: { classPropertyName: "errorTemplate", publicName: "errorTemplate", isSignal: true, isRequired: false, transformFunction: null }, cellState: { classPropertyName: "cellState", publicName: "cellState", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, multiSort: { classPropertyName: "multiSort", publicName: "multiSort", isSignal: true, isRequired: false, transformFunction: null }, sortMode: { classPropertyName: "sortMode", publicName: "sortMode", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, filterMode: { classPropertyName: "filterMode", publicName: "filterMode", isSignal: true, isRequired: false, transformFunction: null }, expandedRowTemplate: { classPropertyName: "expandedRowTemplate", publicName: "expandedRowTemplate", isSignal: true, isRequired: false, transformFunction: null }, rowInteractive: { classPropertyName: "rowInteractive", publicName: "rowInteractive", isSignal: true, isRequired: false, transformFunction: null }, rowLink: { classPropertyName: "rowLink", publicName: "rowLink", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sortChange", filters: "filtersChange", rowClick: "rowClick" }, host: { listeners: { "scroll": "syncScrollState()" }, properties: { "attr.data-appearance": "appearance()", "attr.data-density": "density()", "attr.aria-busy": "resolvedLoading() ? \"true\" : null", "class.et-table-host--scrolled-block-start": "blockScrollShadows().blockStart", "class.et-table-host--scrolled-block-end": "blockScrollShadows().blockEnd", "class.et-table-host--scrolled-inline-start": "scrollFades().start", "class.et-table-host--scrolled-inline-end": "scrollFades().end", "style.--_et-table-viewport-inline-size.px": "viewportInlineSize()" }, classAttribute: "et-table-host" }, providers: [
61427
61707
  { provide: TABLE_FEATURE_HOST, useExisting: TableComponent },
61428
61708
  provideIcons(ARROW_UP_ICON, TRIANGLE_EXCLAMATION_ICON),
61429
- ], queries: [{ propertyName: "footerSlot", first: true, predicate: TableFooterDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "headerCells", predicate: ["headerCell"], descendants: true, isSignal: true }, { propertyName: "bodyCells", predicate: ["bodyCell"], descendants: true, isSignal: true }, { propertyName: "leadHeaderCells", predicate: ["leadHeaderCell"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Every binding below reads a field off a render model (see the `\u2026Vm` types in the component):\n methods belong in event bindings, not in bindings the framework re-evaluates each pass. -->\n<div [style.grid-template-columns]=\"templateColumns()\" class=\"et-table\" role=\"grid\">\n <!-- Rows a feature renders above the column headers (etTableGroupHeaders' spanning group row). Each\n is display: contents and lays its own cells into these tracks \u2014 see registerHeaderRow. -->\n @for (headerRow of headerRows(); track $index) {\n <ng-container *ngComponentOutlet=\"headerRow.component; injector: headerRow.injector\" />\n }\n\n <div class=\"et-table-header-row\" role=\"row\">\n <!-- Leading utility columns (selection from a feature, the expander when expansion is on). The\n table owns the cell chrome; the feature only supplies what goes inside. -->\n @for (lead of leadCells(); track lead.key) {\n <div\n #leadHeaderCell\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n [attr.aria-hidden]=\"lead.lead.headerComponent ? null : 'true'\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n @if (lead.lead.headerComponent; as headerComponent) {\n <ng-container *ngComponentOutlet=\"headerComponent; injector: lead.lead.injector\" />\n }\n </div>\n }\n @for (cell of headerCellVms(); track cell.key) {\n <div\n #headerCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.aria-sort]=\"cell.ariaSort\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n <!-- Sorting is the whole header's job, not a control's: the label plus everything around it is\n one button, and the only sort affordance is the direction arrow, which appears once the\n column is actually sorted. Adornments sit outside it so their own clicks don't sort. -->\n @if (cell.sortable) {\n <button\n [attr.aria-label]=\"cell.sortLabel\"\n (click)=\"toggleSort(cell.key)\"\n class=\"et-table-header-label et-table-header-label--sortable\"\n type=\"button\"\n >\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n @if (cell.direction; as direction) {\n <!-- Flipping direction keeps this element mounted, so the arrow turns over rather than\n swapping; only appearing and disappearing are the fade. -->\n <i\n [attr.data-direction]=\"direction\"\n class=\"et-table-sort-indicator\"\n animate.enter=\"et-table-sort-indicator--enter\"\n animate.leave=\"et-table-sort-indicator--leave\"\n etIcon=\"et-arrow-up\"\n ></i>\n }\n </button>\n } @else {\n <span class=\"et-table-header-label\">\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n </span>\n }\n\n <!-- UI from opt-in features (filter menu, \u2026), each registered rather than referenced \u2014 see\n registerHeaderAdornment. Renders nothing when no feature is imported. -->\n @for (adornment of headerAdornments(); track $index) {\n <ng-container\n *ngComponentOutlet=\"adornment.component; inputs: { column: cell.column }; injector: adornment.injector\"\n />\n }\n </div>\n }\n <!-- Filler cell for the trailing slack track (see hasFiller): carries the header band to the\n panel's edge when every column is a rigid width. -->\n @if (hasFiller()) {\n <div class=\"et-table-header-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <!-- Refetching over rows that are already on screen: a 2px indeterminate bar right under the header,\n so the data stays readable and in place. Drawn here rather than with `et-progress-bar` \u2014 the base\n table takes no component dependencies, and this is 2px of chrome, not a control. -->\n @if (showBusyBar()) {\n <div class=\"et-table-busy-bar\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.start\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n @if (hasError()) {\n <!-- The error state stands in for the whole body: rows are either trustworthy or absent. -->\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-error-cell\" role=\"gridcell\" aria-live=\"polite\">\n @if (errorTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: error() }\" />\n } @else {\n <ng-content select=\"[etTableError]\">\n <i [etProvideColor]=\"errorColorTheme\" class=\"et-table-error-icon\" etIcon=\"et-triangle-exclamation\"></i>\n <span>{{ resolvedLabels().error }}</span>\n </ng-content>\n }\n </div>\n </div>\n } @else if (showPlaceholderRows()) {\n <!-- First load with nothing to show yet. What a loading body looks like belongs to a feature\n (etTableSkeleton draws placeholder rows in these tracks); with none the body stays blank rather\n than showing a misleading empty state \u2014 the host's `aria-busy` is the announcement. -->\n @if (bodyPlaceholder(); as placeholder) {\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n }\n } @else {\n @for (rowVm of bodyRows(); track rowVm.key) {\n <div\n [class]=\"rowVm.classes\"\n [class.et-table-row--stripe]=\"rowVm.stripe\"\n [class.et-table-row--interactive]=\"rowInteractive()\"\n [attr.tabindex]=\"rowInteractive() && !cellNavigation() ? 0 : null\"\n (click)=\"activateRow(rowVm.row, $event)\"\n (keydown.enter)=\"activateRow(rowVm.row, $event)\"\n (keydown.space)=\"activateRow(rowVm.row, $event)\"\n class=\"et-table-row\"\n role=\"row\"\n >\n @for (lead of rowVm.leads; track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n <ng-container\n *ngComponentOutlet=\"lead.lead.bodyComponent; inputs: { row: rowVm.row }; injector: lead.lead.injector\"\n />\n </div>\n }\n @for (cell of rowVm.cells; track cell.key) {\n <div\n #bodyCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.tabindex]=\"cellNavigation() ? -1 : null\"\n [attr.data-state]=\"cell.state\"\n [class.et-table-cell--editing]=\"cell.edit\"\n [class.et-skeleton--animated]=\"cell.state === 'loading'\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n @if (cell.edit; as edit) {\n <!-- The one cell in edit mode: the column's etTableCellEdit template, rendered with the\n editing feature's own context (the draft field). See registerCellEditing. -->\n <ng-container *ngTemplateOutlet=\"edit.template; context: edit.context\" />\n } @else if (cell.state === 'loading' && cellPlaceholder(); as placeholder) {\n <!-- A cell that is loading on its own (an inline edit saving) shows a feature's placeholder\n instead of its value; the row around it stays readable. Without one the value stays put\n and `data-state` carries the cue \u2014 see registerCellPlaceholder. -->\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n } @else {\n @if (cell.state === 'error') {\n @if (cellErrorMark(); as mark) {\n <!-- A feature (etTableCellErrorTooltip) draws the mark instead, so the overlay runtime\n only ships when a table actually wants a tooltip. -->\n <ng-container\n *ngComponentOutlet=\"mark.component; inputs: { message: cell.message }; injector: mark.injector\"\n />\n } @else {\n <!-- Color-scoped here rather than on the cell: the mark is the only part that must read\n as an error, and a provider per errored cell is cheap where one per cell would not\n be. The message rides along as `title`, which costs nothing. -->\n <i\n [etProvideColor]=\"errorColorTheme\"\n [attr.title]=\"cell.message\"\n [attr.aria-label]=\"cell.message\"\n [attr.aria-hidden]=\"cell.message ? null : 'true'\"\n class=\"et-table-cell-error-icon\"\n etIcon=\"et-triangle-exclamation\"\n ></i>\n }\n }\n @if (cell.template; as bodyTemplate) {\n <ng-container *ngTemplateOutlet=\"bodyTemplate; context: cell.context\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.value }}</span>\n }\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <!-- The detail row of an expanded row, from etTableRowExpansion \u2014 the whole row, its chrome and\n its animation belong to the feature, so a table that never expands carries none of them. -->\n @if (rowVm.detail; as detail) {\n <ng-container *ngComponentOutlet=\"detail.component; inputs: { row: rowVm.row }; injector: detail.injector\" />\n }\n } @empty {\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-empty-cell\" role=\"gridcell\">\n @if (emptyTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: rows() }\" />\n } @else {\n <ng-content select=\"[etTableEmpty]\">{{ resolvedLabels().empty }}</ng-content>\n }\n </div>\n </div>\n }\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.end\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n <!-- Edge gradients marking rows scrolled out of view horizontally. The layer is absolutely positioned\n over the whole grid \u2014 the full scroll extent, not just the viewport \u2014 which is what lets the two\n fades inside it hold their place with `position: sticky` for the entire scroll range. Their inline\n inset clears whatever columns are pinned at that edge, so the fade marks where rows actually\n disappear (a pinned column's inner edge) rather than the viewport's edge. -->\n <div class=\"et-table-scroll-fades\" role=\"presentation\" aria-hidden=\"true\">\n <div\n [style.inset-inline-start.px]=\"fadeInset().start\"\n [class.et-table-scroll-fade--visible]=\"scrollFades().start\"\n class=\"et-table-scroll-fade et-table-scroll-fade--start\"\n ></div>\n <div\n [style.inset-inline-end.px]=\"fadeInset().end\"\n [class.et-table-scroll-fade--visible]=\"scrollFades().end\"\n class=\"et-table-scroll-fade et-table-scroll-fade--end\"\n ></div>\n </div>\n\n @if (hasFooter()) {\n <div class=\"et-table-footer-row\" role=\"row\">\n @for (lead of leadCells(); track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n aria-hidden=\"true\"\n ></div>\n }\n @for (cell of footerCells(); track cell.key) {\n <div\n [attr.data-align]=\"cell.align\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n >\n @if (cell.template; as footerTemplate) {\n <ng-container *ngTemplateOutlet=\"footerTemplate; context: { $implicit: rows() }\" />\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-footer-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n }\n</div>\n\n<!-- Full-width footer slot (paginator, page-size, etc.), pinned to the bottom of the scroll viewport.\n Rendered only when the consumer projects `[etTableFooter]`, so the chrome never shows empty. -->\n@if (footerSlot()) {\n <div class=\"et-table-footer\">\n <ng-content select=\"[etTableFooter]\" />\n </div>\n}\n\n<!-- Floating UI from opt-in features (the reorder drag ghost / drop indicator), stamped here so a\n feature can draw without having a view \u2014 or an element \u2014 of its own. -->\n@for (layer of layers(); track $index) {\n <ng-container *ngComponentOutlet=\"layer.component; injector: layer.injector\" />\n}\n", styles: ["@layer components{@property --et-table-cell-padding-block{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-table-cell-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 12px;}:where(.et-table-host){display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:1fr auto;overflow:auto;--_et-table-band: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 7%, var(--et-surface-background-solid, Canvas) );--_et-table-header-bg: var(--et-surface-background-solid, Canvas);--_et-table-header-border: var(--et-surface-border-solid, rgb(128 128 128 / .3));--_et-table-row-divider: transparent;--_et-table-stripe-bg: transparent;--_et-table-stripe-solid: var(--et-surface-background-solid, Canvas)}.et-table-host:where([data-density=sm]){--et-table-cell-padding-block: 6px;--et-table-cell-padding-inline: 10px}.et-table-host:where([data-density=md]){--et-table-cell-padding-block: 10px;--et-table-cell-padding-inline: 12px}.et-table-host:where([data-density=lg]){--et-table-cell-padding-block: 15px;--et-table-cell-padding-inline: 16px}.et-table-host:where([data-appearance=enclosed],[data-appearance=zebra],[data-appearance=grid]){border:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3));border-radius:10px}.et-table-host:where([data-appearance=enclosed]){--_et-table-header-bg: var(--_et-table-band);--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15));box-shadow:0 1px 2px #0000000a,0 6px 16px #0000000f}.et-table-host:where([data-appearance=divided]){--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=zebra]){--_et-table-header-bg: var(--_et-table-band);--_et-table-stripe-bg: color-mix(in srgb, var(--et-surface-interaction-solid, gray) 4%, transparent);--_et-table-stripe-solid: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 4%, var(--et-surface-background-solid, Canvas) )}.et-table-host:where([data-appearance=grid]){--_et-table-header-bg: var(--_et-table-band);--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=bare]){--_et-table-header-border: transparent}.et-table{display:grid;position:relative;align-content:start;inline-size:min-content;min-inline-size:100%;background:var(--et-surface-background-solid, Canvas);color:var(--et-surface-color-solid, CanvasText);font-size:14px;line-height:1.4}.et-table-filler-cell{padding-inline:0}.et-table-header-row,.et-table-row{display:contents}.et-table-header-cell,.et-table-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}.et-table-cell-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-table-header-cell{position:sticky;inset-block-start:max(0px,calc(var(--_et-table-group-h, 0px) - 1px));gap:4px;z-index:1;font-weight:600;color:var(--et-surface-color-muted-solid, CanvasText);background:var(--_et-table-header-bg);border-block-end:1px solid var(--_et-table-header-border)}.et-table-cell{border-block-end:1px solid var(--_et-table-row-divider)}.et-table-row--stripe .et-table-cell{background:var(--_et-table-stripe-bg)}.et-table-host:where([data-appearance=grid]) .et-table-header-cell,.et-table-host:where([data-appearance=grid]) .et-table-cell{border-inline-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=grid]) .et-table-header-row .et-table-header-cell:last-child,.et-table-host:where([data-appearance=grid]) .et-table-row .et-table-cell:last-child{border-inline-end:0}.et-table-sticky-start,.et-table-sticky-end{position:sticky;z-index:1}.et-table-sticky-start{box-shadow:4px 0 6px -4px #0000002e}.et-table-sticky-end{box-shadow:-4px 0 6px -4px #0000002e}.et-table-cell:where(.et-table-sticky-start,.et-table-sticky-end){background:var(--et-surface-background-solid, Canvas)}.et-table-row--stripe .et-table-cell.et-table-sticky-start,.et-table-row--stripe .et-table-cell.et-table-sticky-end{background:var(--_et-table-stripe-solid)}@media(hover:hover){.et-table-row:hover .et-table-cell.et-table-sticky-start,.et-table-row:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 8%,var(--et-surface-background-solid, Canvas))}}.et-table-header-cell:where(.et-table-sticky-start,.et-table-sticky-end),.et-table-footer-cell:where(.et-table-sticky-start,.et-table-sticky-end){z-index:3}.et-table-footer-row{display:contents}.et-table-footer-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);position:sticky;inset-block-end:0;z-index:1;font-weight:600;background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-footer-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-scroll-fades{position:absolute;inset:0;display:flex;justify-content:space-between;z-index:3;pointer-events:none}.et-table-scroll-fade{position:sticky;flex:none;inline-size:var(--et-table-scroll-fade-size, 28px);opacity:0;transition:opacity .15s ease}.et-table-scroll-fade--visible{opacity:1}.et-table-scroll-fade--start{background:linear-gradient(to right,#00000029,#0000)}.et-table-scroll-fade--end{background:linear-gradient(to left,#00000029,#0000)}@media(prefers-reduced-motion:reduce){.et-table-scroll-fade{transition:none}}.et-table-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;position:sticky;inset-block-end:0;inset-inline-start:0;z-index:4;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-label{margin:0;font-size:14px;color:var(--et-surface-color-muted-solid, CanvasText)}@media(pointer:coarse){.et-table-footer{gap:8px;padding:8px var(--et-table-cell-padding-inline)}}.et-table-header-cell:where([data-align=center]),.et-table-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-header-cell:where([data-align=end]),.et-table-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-row--interactive .et-table-cell{cursor:pointer}@media(hover:hover){.et-table-row:hover .et-table-cell{background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 8%,transparent)}}.et-table-header-label{display:flex;align-items:center;gap:4px;flex:1;min-inline-size:0;margin:0;padding:0;font:inherit;color:inherit;text-align:inherit;background:none;border:none}.et-table-header-label:where(.et-table-header-label--sortable){cursor:pointer}.et-table-header-cell:where([data-align=center]) .et-table-header-label{justify-content:center}.et-table-header-cell:where([data-align=end]) .et-table-header-label{justify-content:flex-end}.et-table-sort-indicator{flex:none;inline-size:1.15em;block-size:1.15em;transform:translateY(-.045em);color:var(--et-theme-color-primary-solid, currentColor);transition:transform .2s var(--ease-out-5, ease)}.et-table-sort-indicator:where([data-direction=desc]){transform:translateY(-.045em) rotate(180deg)}.et-table-sort-indicator.et-table-sort-indicator--enter{animation:et-table-sort-in .15s ease}.et-table-sort-indicator.et-table-sort-indicator--leave{animation:et-table-sort-in .12s ease reverse forwards}@keyframes et-table-sort-in{0%{opacity:0}to{opacity:1}}@media(prefers-reduced-motion:reduce){.et-table-sort-indicator{transition:none}.et-table-sort-indicator.et-table-sort-indicator--enter,.et-table-sort-indicator.et-table-sort-indicator--leave{animation:none}}.et-table-message-row{display:contents}.et-table-empty-cell,.et-table-error-cell{grid-column:1 / -1;padding:32px var(--et-table-cell-padding-inline);color:var(--et-surface-color-muted-solid, CanvasText);text-align:center}.et-table-error-cell{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px}.et-table-error-icon{flex:none;inline-size:16px;block-size:16px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=error]){gap:6px}.et-table-cell-error-icon{flex:none;inline-size:14px;block-size:14px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=loading]){display:flex}.et-table-busy-bar{grid-column:1 / -1;block-size:2px;overflow:hidden;background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 10%,transparent)}.et-table-busy-bar:after{content:\"\";display:block;inline-size:40%;block-size:100%;border-radius:999px;background:var(--et-theme-color-primary-solid, currentColor);animation:et-table-busy-sweep 1.1s ease-in-out infinite}@keyframes et-table-busy-sweep{0%{transform:translate(-100%)}to{transform:translate(250%)}}@media(prefers-reduced-motion:reduce){.et-table-busy-bar:after{inline-size:100%;animation:none}}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconDirective, selector: "[etIcon]", inputs: ["etIcon", "variant", "allowHardcodedColor", "label"] }, { kind: "directive", type: ProvideColorDirective, selector: "[etProvideColor]", inputs: ["etProvideColor"] }], encapsulation: i0.ViewEncapsulation.None }); }
61709
+ ], queries: [{ propertyName: "footerSlot", first: true, predicate: TableFooterDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "gridRef", first: true, predicate: ["grid"], descendants: true, isSignal: true }, { propertyName: "headerCells", predicate: ["headerCell"], descendants: true, isSignal: true }, { propertyName: "bodyCells", predicate: ["bodyCell"], descendants: true, isSignal: true }, { propertyName: "leadHeaderCells", predicate: ["leadHeaderCell"], descendants: true, isSignal: true }, { propertyName: "trailHeaderCells", predicate: ["trailHeaderCell"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Every binding below reads a field off a render model (see the `\u2026Vm` types in the component):\n methods belong in event bindings, not in bindings the framework re-evaluates each pass. -->\n<div #grid [style.grid-template-columns]=\"templateColumns()\" class=\"et-table\" role=\"grid\">\n <!-- Rows a feature renders above the column headers (etTableGroupHeaders' spanning group row). Each\n is display: contents and lays its own cells into these tracks \u2014 see registerHeaderRow. -->\n @for (headerRow of headerRows(); track $index) {\n <ng-container *ngComponentOutlet=\"headerRow.component; injector: headerRow.injector\" />\n }\n\n <div class=\"et-table-header-row\" role=\"row\">\n <!-- Leading utility columns (selection from a feature, the expander when expansion is on). The\n table owns the cell chrome; the feature only supplies what goes inside. -->\n @for (lead of leadCells(); track lead.key) {\n <div\n #leadHeaderCell\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n [attr.aria-hidden]=\"lead.lead.headerComponent ? null : 'true'\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n @if (lead.lead.headerComponent; as headerComponent) {\n <ng-container *ngComponentOutlet=\"headerComponent; injector: lead.lead.injector\" />\n }\n </div>\n }\n @for (cell of headerCellVms(); track cell.key) {\n <div\n #headerCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.aria-sort]=\"cell.ariaSort\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n <!-- Sorting is the whole header's job, not a control's: the label plus everything around it is\n one button, and the only sort affordance is the direction arrow, which appears once the\n column is actually sorted. Adornments sit outside it so their own clicks don't sort. -->\n @if (cell.sortable) {\n <button\n [attr.aria-label]=\"cell.sortLabel\"\n (click)=\"toggleSort(cell.key)\"\n class=\"et-table-header-label et-table-header-label--sortable\"\n type=\"button\"\n >\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n @if (cell.direction; as direction) {\n <!-- Flipping direction keeps this element mounted, so the arrow turns over rather than\n swapping; only appearing and disappearing are the fade, and only for a sort the user\n just asked for (see sortIndicatorEnter). -->\n <i\n [attr.data-direction]=\"direction\"\n [animate.enter]=\"sortIndicatorEnter()\"\n [animate.leave]=\"sortIndicatorLeave()\"\n class=\"et-table-sort-indicator\"\n etIcon=\"et-arrow-up\"\n ></i>\n }\n </button>\n } @else {\n <span class=\"et-table-header-label\">\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n </span>\n }\n\n <!-- UI from opt-in features (filter menu, \u2026), each registered rather than referenced \u2014 see\n registerHeaderAdornment. Renders nothing when no feature is imported.\n\n Dropped once the column is covered by a pinned one: an adornment's menu is a portal, so it\n would go on floating over the pinned column, anchored to a cell nobody can see. Unmounting\n the trigger is what closes it. -->\n @if (!cell.obscured) {\n @for (adornment of headerAdornments(); track $index) {\n <ng-container\n *ngComponentOutlet=\"adornment.component; inputs: { column: cell.column }; injector: adornment.injector\"\n />\n }\n }\n </div>\n }\n <!-- Filler cell for the trailing slack track (see hasFiller): carries the header band to the\n panel's edge when every column is a rigid width. -->\n @if (hasFiller()) {\n <div class=\"et-table-header-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n <!-- Trailing utility columns (a selection column moved to this edge). Same chrome as the leading\n ones, pinned to the trailing edge instead - see TableLeadColumn.side. -->\n @for (trail of trailCells(); track trail.key) {\n <div\n #trailHeaderCell\n [class]=\"trail.cellClass\"\n [class.et-table-sticky-end]=\"trail.sticky\"\n [style.inset-inline-end.px]=\"trail.offset\"\n [attr.aria-hidden]=\"trail.lead.headerComponent ? null : 'true'\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n @if (trail.lead.headerComponent; as headerComponent) {\n <ng-container *ngComponentOutlet=\"headerComponent; injector: trail.lead.injector\" />\n }\n </div>\n }\n </div>\n\n <!-- Refetching over rows that are already on screen: a 2px indeterminate bar right under the header,\n so the data stays readable and in place. Drawn here rather than with `et-progress-bar` \u2014 the base\n table takes no component dependencies, and this is 2px of chrome, not a control. -->\n @if (showBusyBar()) {\n <!-- Faded in and out: a refetch is often over in a few hundred ms, and a bar that pops in and\n vanishes reads as a flicker rather than as work happening. -->\n <div\n class=\"et-table-busy-bar\"\n animate.enter=\"et-table-busy-bar--enter\"\n animate.leave=\"et-table-busy-bar--leave\"\n role=\"presentation\"\n aria-hidden=\"true\"\n ></div>\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.start\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n @if (hasError()) {\n <!-- The error state stands in for the whole body: rows are either trustworthy or absent. -->\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-error-cell\" role=\"gridcell\" aria-live=\"polite\">\n @if (errorTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: error() }\" />\n } @else {\n <ng-content select=\"[etTableError]\">\n <i [etProvideColor]=\"errorColorTheme\" class=\"et-table-error-icon\" etIcon=\"et-triangle-exclamation\"></i>\n <span>{{ resolvedLabels().error }}</span>\n </ng-content>\n }\n </div>\n </div>\n } @else if (showPlaceholderRows()) {\n <!-- First load with nothing to show yet. What a loading body looks like belongs to a feature\n (etTableSkeleton draws placeholder rows in these tracks); with none the body stays blank rather\n than showing a misleading empty state \u2014 the host's `aria-busy` is the announcement. -->\n @if (bodyPlaceholder(); as placeholder) {\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n }\n } @else {\n @for (rowVm of bodyRows(); track rowVm.key) {\n <!-- A linked row is not a tab stop of its own: its anchor is the one stop, and the one link. -->\n <div\n [class]=\"rowVm.classes\"\n [class.et-table-row--stripe]=\"rowVm.stripe\"\n [class.et-table-row--last]=\"rowVm.last\"\n [class.et-table-row--interactive]=\"rowInteractive()\"\n [class.et-table-row--box]=\"rowBox()\"\n [class.et-table-row--link]=\"rowVm.href !== null\"\n [attr.tabindex]=\"rowInteractive() && !cellNavigation() && rowVm.href === null ? 0 : null\"\n (click)=\"activateRow(rowVm.row, $event)\"\n (keydown.enter)=\"activateRow(rowVm.row, $event)\"\n (keydown.space)=\"activateRow(rowVm.row, $event)\"\n class=\"et-table-row\"\n role=\"row\"\n >\n @for (lead of rowVm.leads; track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n <ng-container\n *ngComponentOutlet=\"lead.lead.bodyComponent; inputs: { row: rowVm.row }; injector: lead.lead.injector\"\n />\n </div>\n }\n @for (cell of rowVm.cells; track cell.key) {\n <div\n #bodyCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.tabindex]=\"cellNavigation() ? -1 : null\"\n [attr.data-state]=\"cell.state\"\n [attr.id]=\"cell.linkHost ? rowVm.linkLabelId : null\"\n [class.et-table-cell--interactive]=\"cell.interactive\"\n [class.et-table-cell--editing]=\"cell.edit\"\n [class.et-skeleton--animated]=\"cell.state === 'loading'\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n @if (cell.edit; as edit) {\n <!-- The one cell in edit mode: the column's etTableCellEdit template, rendered with the\n editing feature's own context (the draft field). See registerCellEditing. -->\n <ng-container *ngTemplateOutlet=\"edit.template; context: edit.context\" />\n } @else if (cell.state === 'loading' && cellPlaceholder(); as placeholder) {\n <!-- A cell that is loading on its own (an inline edit saving) shows a feature's placeholder\n instead of its value; the row around it stays readable. Without one the value stays put\n and `data-state` carries the cue \u2014 see registerCellPlaceholder. -->\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n } @else {\n @if (cell.state === 'error') {\n @if (cellErrorMark(); as mark) {\n <!-- A feature (etTableCellErrorTooltip) draws the mark instead, so the overlay runtime\n only ships when a table actually wants a tooltip. -->\n <ng-container\n *ngComponentOutlet=\"mark.component; inputs: { message: cell.message }; injector: mark.injector\"\n />\n } @else {\n <!-- Color-scoped here rather than on the cell: the mark is the only part that must read\n as an error, and a provider per errored cell is cheap where one per cell would not\n be. The message rides along as `title`, which costs nothing. -->\n <i\n [etProvideColor]=\"errorColorTheme\"\n [attr.title]=\"cell.message\"\n [attr.aria-label]=\"cell.message\"\n [attr.aria-hidden]=\"cell.message ? null : 'true'\"\n class=\"et-table-cell-error-icon\"\n etIcon=\"et-triangle-exclamation\"\n ></i>\n }\n }\n @if (cell.template; as bodyTemplate) {\n <ng-container *ngTemplateOutlet=\"bodyTemplate; context: cell.context\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.value }}</span>\n }\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n @for (trail of rowVm.trails; track trail.key) {\n <div\n [class]=\"trail.cellClass\"\n [class.et-table-sticky-end]=\"trail.sticky\"\n [style.inset-inline-end.px]=\"trail.offset\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n <ng-container\n *ngComponentOutlet=\"trail.lead.bodyComponent; inputs: { row: rowVm.row }; injector: trail.lead.injector\"\n />\n </div>\n }\n\n @if (rowVm.href !== null) {\n <!-- The row's link: one real anchor, stretched over the row box (see rowBox) rather than\n wrapping any content, so the cells stay exactly as a table without links renders them.\n It carries no text of its own and is named by the identity cell instead - `aria-labelledby`\n resolves to that cell's content, which is the row's identity.\n\n A child of the row, not of a cell: a cell that is pinned is `position: sticky` and would\n therefore be the anchor's containing block, shrinking the row's hit area to that one\n column. The row box is the containing block that spans every cell. -->\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content -- the rule's\n allowList knows `aria-label` but not `aria-labelledby`, which names it just as well. -->\n <a\n [attr.href]=\"rowVm.href\"\n [attr.aria-labelledby]=\"rowVm.linkLabelId\"\n (click)=\"activateRowLink(rowVm.link, $event)\"\n class=\"et-table-row-link\"\n ></a>\n }\n\n @if (appearance() === 'cards') {\n <div class=\"et-table-card-corners\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <!-- The detail row of an expanded row, from etTableRowExpansion \u2014 the whole row, its chrome and\n its animation belong to the feature, so a table that never expands carries none of them. -->\n @if (rowVm.detail; as detail) {\n <ng-container *ngComponentOutlet=\"detail.component; inputs: { row: rowVm.row }; injector: detail.injector\" />\n }\n } @empty {\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-empty-cell\" role=\"gridcell\">\n @if (emptyTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: rows() }\" />\n } @else {\n <ng-content select=\"[etTableEmpty]\">{{ resolvedLabels().empty }}</ng-content>\n }\n </div>\n </div>\n }\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.end\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n <!-- Edge gradients marking rows scrolled out of view horizontally, on the edges no pinned column\n already marks (see visibleScrollFades). The layer is absolutely positioned over the whole grid \u2014\n the full scroll extent, not just the viewport \u2014 which is what lets the two fades inside it hold\n their place with `position: sticky` for the entire scroll range. -->\n <div class=\"et-table-scroll-fades\" role=\"presentation\" aria-hidden=\"true\">\n <div\n [style.inset-inline-start.px]=\"fadeInset().start\"\n [class.et-table-scroll-fade--visible]=\"visibleScrollFades().start\"\n class=\"et-table-scroll-fade et-table-scroll-fade--start\"\n ></div>\n <div\n [style.inset-inline-end.px]=\"fadeInset().end\"\n [class.et-table-scroll-fade--visible]=\"visibleScrollFades().end\"\n class=\"et-table-scroll-fade et-table-scroll-fade--end\"\n ></div>\n </div>\n\n @if (hasFooter()) {\n <div class=\"et-table-footer-row\" role=\"row\">\n @for (lead of leadCells(); track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n aria-hidden=\"true\"\n ></div>\n }\n @for (cell of footerCells(); track cell.key) {\n <div\n [attr.data-align]=\"cell.align\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n >\n @if (cell.template; as footerTemplate) {\n <ng-container *ngTemplateOutlet=\"footerTemplate; context: { $implicit: rows() }\" />\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-footer-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n @for (trail of trailCells(); track trail.key) {\n <div\n [class]=\"trail.cellClass\"\n [class.et-table-sticky-end]=\"trail.sticky\"\n [style.inset-inline-end.px]=\"trail.offset\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n aria-hidden=\"true\"\n ></div>\n }\n </div>\n }\n</div>\n\n<!-- Full-width footer slot (paginator, page-size, etc.), pinned to the bottom of the scroll viewport.\n Rendered only when the consumer projects `[etTableFooter]`, so the chrome never shows empty. -->\n@if (footerSlot()) {\n <div class=\"et-table-footer\">\n <ng-content select=\"[etTableFooter]\" />\n </div>\n}\n\n<!-- Floating UI from opt-in features (the reorder drag ghost / drop indicator), stamped here so a\n feature can draw without having a view \u2014 or an element \u2014 of its own. -->\n@for (layer of layers(); track $index) {\n <ng-container *ngComponentOutlet=\"layer.component; injector: layer.injector\" />\n}\n", styles: ["@layer components{@property --et-table-cell-padding-block{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-table-cell-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 12px;}:where(.et-table-host){display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:1fr auto;overflow:auto;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 35%,transparent) transparent;--_et-table-band: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 7%, var(--et-surface-background-solid, Canvas) );--_et-table-header-bg: var(--et-table-header-background-color, var(--et-surface-background-solid, Canvas));--_et-table-header-border: var(--et-surface-border-solid, rgb(128 128 128 / .3));--_et-table-row-divider: transparent;--_et-table-row-surface: var(--et-surface-background-solid, Canvas);--_et-table-stripe-bg: transparent;--_et-table-stripe-solid: var(--_et-table-row-surface);--_et-table-row-hover: color-mix(in srgb, var(--et-surface-interaction-solid, gray) 8%, transparent);--_et-table-row-hover-solid: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 8%, var(--_et-table-row-surface) );--_et-table-pin-shadow: var( --et-table-pin-shadow-color, color-mix(in srgb, var(--et-surface-interaction-solid, black) 30%, transparent) );--_et-table-pin-shadow-inline: var(--et-table-pin-shadow-color-inline, var(--_et-table-pin-shadow));--_et-table-pin-shadow-block: var(--et-table-pin-shadow-color-block, var(--_et-table-pin-shadow));--_et-table-edge-none: 0 0 transparent;--_et-table-edge-start: var(--_et-table-edge-none);--_et-table-edge-end: var(--_et-table-edge-none);--_et-table-edge-block-start: var(--_et-table-edge-none);--_et-table-edge-block-end: var(--_et-table-edge-none)}.et-table-host--scrolled-inline-start{--_et-table-edge-start: 8px 0 10px -6px var(--_et-table-pin-shadow-inline)}.et-table-host--scrolled-inline-end{--_et-table-edge-end: -8px 0 10px -6px var(--_et-table-pin-shadow-inline)}.et-table-host--scrolled-block-start{--_et-table-edge-block-start: 0 8px 10px -6px var(--_et-table-pin-shadow-block)}.et-table-host--scrolled-block-end{--_et-table-edge-block-end: 0 -8px 10px -6px var(--_et-table-pin-shadow-block)}.et-table-host:where([data-density=sm]){--et-table-cell-padding-block: 6px;--et-table-cell-padding-inline: 10px}.et-table-host:where([data-density=md]){--et-table-cell-padding-block: 10px;--et-table-cell-padding-inline: 12px}.et-table-host:where([data-density=lg]){--et-table-cell-padding-block: 15px;--et-table-cell-padding-inline: 16px}.et-table-host:where([data-appearance=enclosed],[data-appearance=zebra],[data-appearance=grid]){border:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3));border-radius:10px}.et-table-host:where([data-appearance=enclosed]){--_et-table-header-bg: var(--et-table-header-background-color, var(--_et-table-band));--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15));box-shadow:0 1px 2px #0000000a,0 6px 16px #0000000f}.et-table-host:where([data-appearance=divided]){--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=zebra]){--_et-table-header-bg: var(--et-table-header-background-color, var(--_et-table-band));--_et-table-stripe-bg: color-mix(in srgb, var(--et-surface-interaction-solid, gray) 4%, transparent);--_et-table-stripe-solid: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 4%, var(--_et-table-row-surface) )}.et-table-host:where([data-appearance=grid]){--_et-table-header-bg: var(--et-table-header-background-color, var(--_et-table-band));--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=bare]){--_et-table-header-border: transparent}.et-table-host:where([data-appearance=cards]){--_et-table-header-bg: var(--et-table-header-background-color, var(--et-surface-background-solid, Canvas));--_et-table-row-divider: transparent;--_et-table-row-surface: var(--_et-table-band)}.et-table{display:grid;position:relative;align-content:start;inline-size:min-content;min-inline-size:100%;background:var(--et-surface-background-solid, Canvas);color:var(--et-surface-color-solid, CanvasText);font-size:14px;line-height:1.4}.et-table-filler-cell{padding-inline:0}.et-table-header-row,.et-table-row{display:contents}.et-table-header-cell,.et-table-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}.et-table-cell-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-table-header-cell{position:sticky;inset-block-start:max(0px,calc(var(--_et-table-group-h, 0px) - 1px));gap:4px;z-index:1;font-weight:600;color:var(--et-surface-color-muted-solid, CanvasText);background:var(--_et-table-header-bg);border-block-end:1px solid var(--_et-table-header-border)}.et-table-header-cell .et-table-filter-trigger,.et-table-header-cell .et-table-column-menu-trigger{--et-icon-button-size: 2.8rem;--et-icon-button-icon-size: 1.6rem;min-width:24px;min-height:24px}.et-table-cell{border-block-end:1px solid var(--_et-table-row-divider)}.et-table-header-cell{box-shadow:var(--_et-table-edge-block-start)}.et-table-header-cell.et-table-sticky-start{box-shadow:var(--_et-table-edge-block-start),var(--_et-table-edge-start)}.et-table-header-cell.et-table-sticky-end{box-shadow:var(--_et-table-edge-block-start),var(--_et-table-edge-end)}.et-table-footer,.et-table-footer-cell{box-shadow:var(--_et-table-edge-block-end)}.et-table-footer-cell.et-table-sticky-start{box-shadow:var(--_et-table-edge-block-end),var(--_et-table-edge-start)}.et-table-footer-cell.et-table-sticky-end{box-shadow:var(--_et-table-edge-block-end),var(--_et-table-edge-end)}.et-table-row--last:not(:has(+.et-table-detail-row)) .et-table-cell{border-block-end:0}.et-table-row--stripe .et-table-cell{background:var(--_et-table-stripe-bg)}.et-table-host:where([data-appearance=grid]) .et-table-header-cell,.et-table-host:where([data-appearance=grid]) .et-table-cell{border-inline-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=grid]) .et-table-header-row .et-table-header-cell:last-child,.et-table-host:where([data-appearance=grid]) .et-table-row .et-table-cell:nth-last-child(1 of.et-table-cell){border-inline-end:0}.et-table-sticky-start,.et-table-sticky-end{position:sticky;z-index:1}.et-table-sticky-start{box-shadow:var(--_et-table-edge-start)}.et-table-sticky-end{box-shadow:var(--_et-table-edge-end)}.et-table-sticky-start:has(~.et-table-sticky-start){--_et-table-edge-start: 0 0 transparent}.et-table-sticky-end~.et-table-sticky-end{--_et-table-edge-end: 0 0 transparent}.et-table-cell:where(.et-table-sticky-start,.et-table-sticky-end){background:var(--_et-table-row-surface)}.et-table-row--stripe .et-table-cell.et-table-sticky-start,.et-table-row--stripe .et-table-cell.et-table-sticky-end{background:var(--_et-table-stripe-solid)}@media(hover:hover){.et-table-row:hover .et-table-cell.et-table-sticky-start,.et-table-row:hover .et-table-cell.et-table-sticky-end{background:var(--_et-table-row-hover-solid)}}.et-table-header-cell:where(.et-table-sticky-start,.et-table-sticky-end),.et-table-footer-cell:where(.et-table-sticky-start,.et-table-sticky-end){z-index:3}.et-table-footer-row{display:contents}.et-table-footer-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);position:sticky;inset-block-end:0;z-index:1;font-weight:600;background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-footer-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-scroll-fades{position:absolute;inset:0;display:flex;justify-content:space-between;z-index:3;pointer-events:none}.et-table-scroll-fade{position:sticky;flex:none;inline-size:var(--et-table-scroll-fade-size, 28px);opacity:0;transition:opacity .15s ease;--_et-table-scroll-fade-color: var( --et-table-scroll-fade-color, color-mix(in srgb, var(--et-surface-interaction-solid, black) 22%, transparent) )}.et-table-scroll-fade--visible{opacity:1}.et-table-scroll-fade--start{background:linear-gradient(to right,var(--_et-table-scroll-fade-color),transparent)}.et-table-scroll-fade--end{background:linear-gradient(to left,var(--_et-table-scroll-fade-color),transparent)}@media(prefers-reduced-motion:reduce){.et-table-scroll-fade{transition:none}}.et-table-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;position:sticky;inset-block-end:0;inset-inline-start:0;z-index:4;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-label{margin:0;font-size:14px;color:var(--et-surface-color-muted-solid, CanvasText)}@media(pointer:coarse){.et-table-footer{gap:8px;padding:8px var(--et-table-cell-padding-inline)}}.et-table-header-cell:where([data-align=center]),.et-table-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-header-cell:where([data-align=end]),.et-table-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-row--interactive .et-table-cell{cursor:pointer}@media(hover:hover){.et-table-row:hover .et-table-cell{background:var(--_et-table-row-hover)}}.et-table-row--box{grid-column:1 / -1;display:grid;grid-template-columns:subgrid;position:relative;z-index:0}.et-table-row-link{position:absolute;inset:0;z-index:2;cursor:pointer}.et-table-header-label:focus-visible,.et-table-expander:focus-visible,.et-table-cell:focus-visible{outline:2px solid var(--et-theme-color-primary-solid, currentColor);outline-offset:-2px}.et-table-header-label{border-radius:4px}.et-table-row-link:focus-visible{outline:2px solid var(--et-theme-color-primary-solid, currentColor);outline-offset:-4px}.et-table-row--link :where(.et-table-select-cell,.et-table-expander-cell,.et-table-cell--interactive,.et-table-cell--editing){z-index:3}.et-table-row--link :where(.et-table-select-cell,.et-table-expander-cell,.et-table-cell--interactive,.et-table-cell--editing):not(.et-table-sticky-start,.et-table-sticky-end){position:relative}.et-table-host:where([data-appearance=cards]) .et-table-row{margin-block-end:var(--et-table-row-gap, 8px);background:var(--_et-table-band);border-radius:var(--et-table-row-radius, 10px)}.et-table-host:where([data-appearance=cards]) .et-table-row--box:after{content:\"\";position:absolute;inset:0;z-index:4;border:1px solid var(--et-table-row-border-color, var(--et-surface-border-solid, rgb(128 128 128 / .3)));border-radius:inherit;pointer-events:none}.et-table-host:where([data-appearance=cards]) .et-table-cell:where(.et-table-sticky-start,.et-table-sticky-end){clip-path:inset(0 -24px)}.et-table-host:where([data-appearance=cards]) .et-table-header-cell{margin-block-end:var(--et-table-row-gap, 8px)}.et-table-host:where([data-appearance=cards]) .et-table-row:not(.et-table-row--interactive,.et-table-row--link){--_et-table-row-hover: transparent;--_et-table-row-hover-solid: var(--_et-table-band)}.et-table-host:where([data-appearance=cards]) .et-table-row>:first-child{border-start-start-radius:inherit;border-end-start-radius:inherit}.et-table-host:where([data-appearance=cards]) .et-table-row>.et-table-cell:nth-last-child(1 of.et-table-cell){border-start-end-radius:inherit;border-end-end-radius:inherit}.et-table-host:where([data-appearance=cards]) .et-table-row-link{border-radius:var(--et-table-row-radius, 10px)}.et-table-card-corners{position:absolute;inset:0;z-index:5;display:flex;justify-content:space-between;pointer-events:none}.et-table-host:where([data-appearance=cards]) .et-table-card-corners:before,.et-table-host:where([data-appearance=cards]) .et-table-card-corners:after{--_et-table-card-radius: var(--et-table-row-radius, 10px);--_et-table-card-edge: var(--et-table-row-border-color, var(--et-surface-border-solid, rgb(128 128 128 / .3)));--_et-table-card-outside: var(--et-surface-background-solid, Canvas);content:\"\";flex:0 0 auto;inline-size:var(--_et-table-card-radius)}.et-table-row:has(.et-table-sticky-start) .et-table-card-corners:before{position:sticky;inset-inline-start:0}.et-table-row:has(.et-table-sticky-end) .et-table-card-corners:after{position:sticky;inset-inline-end:0}.et-table-host:where([data-appearance=cards]) .et-table-card-corners:before{background:radial-gradient(circle at 100% 100%,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 0 / 100% var(--_et-table-card-radius) no-repeat,radial-gradient(circle at 100% 0,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 100% / 100% var(--_et-table-card-radius) no-repeat,linear-gradient(var(--_et-table-card-edge),var(--_et-table-card-edge)) 0 0 / 1px 100% no-repeat}.et-table-host:where([data-appearance=cards]) .et-table-card-corners:after{background:radial-gradient(circle at 0 100%,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 0 / 100% var(--_et-table-card-radius) no-repeat,radial-gradient(circle at 0 0,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 100% / 100% var(--_et-table-card-radius) no-repeat,linear-gradient(var(--_et-table-card-edge),var(--_et-table-card-edge)) 100% 0 / 1px 100% no-repeat}.et-table-header-label{display:flex;align-items:center;gap:4px;flex:1;min-inline-size:0;margin:0;padding:0;font:inherit;color:inherit;text-align:inherit;background:none;border:none}.et-table-header-label:where(.et-table-header-label--sortable){cursor:pointer}.et-table-header-cell:where([data-align=center]) .et-table-header-label{justify-content:center}.et-table-header-cell:where([data-align=end]) .et-table-header-label{justify-content:flex-end}.et-table-sort-indicator{flex:none;inline-size:1.15em;block-size:1.15em;transform:translateY(-.045em);color:var(--et-theme-color-primary-solid, currentColor);transition:transform .2s var(--ease-out-5, ease)}.et-table-sort-indicator:where([data-direction=desc]){transform:translateY(-.045em) rotate(180deg)}.et-table-sort-indicator.et-table-sort-indicator--enter{animation:et-table-sort-in .15s ease}.et-table-sort-indicator.et-table-sort-indicator--leave{animation:et-table-sort-in .12s ease reverse forwards}@keyframes et-table-sort-in{0%{opacity:0}to{opacity:1}}@media(prefers-reduced-motion:reduce){.et-table-sort-indicator{transition:none}.et-table-sort-indicator.et-table-sort-indicator--enter,.et-table-sort-indicator.et-table-sort-indicator--leave{animation:none}}.et-table-message-row{display:contents}.et-table-empty-cell,.et-table-error-cell{grid-column:1 / -1;position:sticky;inset-inline-start:0;inline-size:var(--_et-table-viewport-inline-size, 100%);padding:32px var(--et-table-cell-padding-inline);color:var(--et-surface-color-muted-solid, CanvasText);text-align:center}.et-table-empty-cell{display:grid;place-content:center;justify-items:center}.et-table-error-cell{display:flex;flex-wrap:wrap;align-items:center;align-content:center;justify-content:center;gap:8px}.et-table-error-icon{flex:none;inline-size:16px;block-size:16px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=error]){gap:6px}.et-table-cell-error-icon{flex:none;inline-size:14px;block-size:14px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=loading]){display:flex}.et-table-busy-bar{grid-column:1 / -1;block-size:2px;margin-block-end:-2px;overflow:hidden;background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 10%,transparent)}.et-table-host:where([data-appearance=cards]) .et-table-busy-bar{margin-block-start:calc((var(--et-table-row-gap, 8px) + 2px) / -2);margin-block-end:calc((var(--et-table-row-gap, 8px) - 2px) / 2)}.et-table-busy-bar.et-table-busy-bar--enter{animation:et-table-busy-fade .15s ease}.et-table-busy-bar.et-table-busy-bar--leave{animation:et-table-busy-fade .25s ease reverse forwards}@keyframes et-table-busy-fade{0%{opacity:0}to{opacity:1}}.et-table-busy-bar:after{content:\"\";display:block;inline-size:40%;block-size:100%;border-radius:999px;background:var(--et-theme-color-primary-solid, currentColor);animation:et-table-busy-sweep 1.1s ease-in-out infinite}@keyframes et-table-busy-sweep{0%{transform:translate(-100%)}to{transform:translate(250%)}}@media(prefers-reduced-motion:reduce){.et-table-busy-bar:after{inline-size:100%;animation:none}.et-table-busy-bar.et-table-busy-bar--enter,.et-table-busy-bar.et-table-busy-bar--leave{animation:none}}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconDirective, selector: "[etIcon]", inputs: ["etIcon", "variant", "allowHardcodedColor", "label"] }, { kind: "directive", type: ProvideColorDirective, selector: "[etProvideColor]", inputs: ["etProvideColor"] }], encapsulation: i0.ViewEncapsulation.None }); }
61430
61710
  }
61431
61711
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableComponent, decorators: [{
61432
61712
  type: Component,
@@ -61438,9 +61718,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
61438
61718
  '[attr.data-appearance]': 'appearance()',
61439
61719
  '[attr.data-density]': 'density()',
61440
61720
  '[attr.aria-busy]': 'resolvedLoading() ? "true" : null',
61441
- '(scroll)': 'syncScrollFades()',
61442
- }, template: "<!-- Every binding below reads a field off a render model (see the `\u2026Vm` types in the component):\n methods belong in event bindings, not in bindings the framework re-evaluates each pass. -->\n<div [style.grid-template-columns]=\"templateColumns()\" class=\"et-table\" role=\"grid\">\n <!-- Rows a feature renders above the column headers (etTableGroupHeaders' spanning group row). Each\n is display: contents and lays its own cells into these tracks \u2014 see registerHeaderRow. -->\n @for (headerRow of headerRows(); track $index) {\n <ng-container *ngComponentOutlet=\"headerRow.component; injector: headerRow.injector\" />\n }\n\n <div class=\"et-table-header-row\" role=\"row\">\n <!-- Leading utility columns (selection from a feature, the expander when expansion is on). The\n table owns the cell chrome; the feature only supplies what goes inside. -->\n @for (lead of leadCells(); track lead.key) {\n <div\n #leadHeaderCell\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n [attr.aria-hidden]=\"lead.lead.headerComponent ? null : 'true'\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n @if (lead.lead.headerComponent; as headerComponent) {\n <ng-container *ngComponentOutlet=\"headerComponent; injector: lead.lead.injector\" />\n }\n </div>\n }\n @for (cell of headerCellVms(); track cell.key) {\n <div\n #headerCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.aria-sort]=\"cell.ariaSort\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n <!-- Sorting is the whole header's job, not a control's: the label plus everything around it is\n one button, and the only sort affordance is the direction arrow, which appears once the\n column is actually sorted. Adornments sit outside it so their own clicks don't sort. -->\n @if (cell.sortable) {\n <button\n [attr.aria-label]=\"cell.sortLabel\"\n (click)=\"toggleSort(cell.key)\"\n class=\"et-table-header-label et-table-header-label--sortable\"\n type=\"button\"\n >\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n @if (cell.direction; as direction) {\n <!-- Flipping direction keeps this element mounted, so the arrow turns over rather than\n swapping; only appearing and disappearing are the fade. -->\n <i\n [attr.data-direction]=\"direction\"\n class=\"et-table-sort-indicator\"\n animate.enter=\"et-table-sort-indicator--enter\"\n animate.leave=\"et-table-sort-indicator--leave\"\n etIcon=\"et-arrow-up\"\n ></i>\n }\n </button>\n } @else {\n <span class=\"et-table-header-label\">\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n </span>\n }\n\n <!-- UI from opt-in features (filter menu, \u2026), each registered rather than referenced \u2014 see\n registerHeaderAdornment. Renders nothing when no feature is imported. -->\n @for (adornment of headerAdornments(); track $index) {\n <ng-container\n *ngComponentOutlet=\"adornment.component; inputs: { column: cell.column }; injector: adornment.injector\"\n />\n }\n </div>\n }\n <!-- Filler cell for the trailing slack track (see hasFiller): carries the header band to the\n panel's edge when every column is a rigid width. -->\n @if (hasFiller()) {\n <div class=\"et-table-header-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <!-- Refetching over rows that are already on screen: a 2px indeterminate bar right under the header,\n so the data stays readable and in place. Drawn here rather than with `et-progress-bar` \u2014 the base\n table takes no component dependencies, and this is 2px of chrome, not a control. -->\n @if (showBusyBar()) {\n <div class=\"et-table-busy-bar\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.start\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n @if (hasError()) {\n <!-- The error state stands in for the whole body: rows are either trustworthy or absent. -->\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-error-cell\" role=\"gridcell\" aria-live=\"polite\">\n @if (errorTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: error() }\" />\n } @else {\n <ng-content select=\"[etTableError]\">\n <i [etProvideColor]=\"errorColorTheme\" class=\"et-table-error-icon\" etIcon=\"et-triangle-exclamation\"></i>\n <span>{{ resolvedLabels().error }}</span>\n </ng-content>\n }\n </div>\n </div>\n } @else if (showPlaceholderRows()) {\n <!-- First load with nothing to show yet. What a loading body looks like belongs to a feature\n (etTableSkeleton draws placeholder rows in these tracks); with none the body stays blank rather\n than showing a misleading empty state \u2014 the host's `aria-busy` is the announcement. -->\n @if (bodyPlaceholder(); as placeholder) {\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n }\n } @else {\n @for (rowVm of bodyRows(); track rowVm.key) {\n <div\n [class]=\"rowVm.classes\"\n [class.et-table-row--stripe]=\"rowVm.stripe\"\n [class.et-table-row--interactive]=\"rowInteractive()\"\n [attr.tabindex]=\"rowInteractive() && !cellNavigation() ? 0 : null\"\n (click)=\"activateRow(rowVm.row, $event)\"\n (keydown.enter)=\"activateRow(rowVm.row, $event)\"\n (keydown.space)=\"activateRow(rowVm.row, $event)\"\n class=\"et-table-row\"\n role=\"row\"\n >\n @for (lead of rowVm.leads; track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n <ng-container\n *ngComponentOutlet=\"lead.lead.bodyComponent; inputs: { row: rowVm.row }; injector: lead.lead.injector\"\n />\n </div>\n }\n @for (cell of rowVm.cells; track cell.key) {\n <div\n #bodyCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.tabindex]=\"cellNavigation() ? -1 : null\"\n [attr.data-state]=\"cell.state\"\n [class.et-table-cell--editing]=\"cell.edit\"\n [class.et-skeleton--animated]=\"cell.state === 'loading'\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n @if (cell.edit; as edit) {\n <!-- The one cell in edit mode: the column's etTableCellEdit template, rendered with the\n editing feature's own context (the draft field). See registerCellEditing. -->\n <ng-container *ngTemplateOutlet=\"edit.template; context: edit.context\" />\n } @else if (cell.state === 'loading' && cellPlaceholder(); as placeholder) {\n <!-- A cell that is loading on its own (an inline edit saving) shows a feature's placeholder\n instead of its value; the row around it stays readable. Without one the value stays put\n and `data-state` carries the cue \u2014 see registerCellPlaceholder. -->\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n } @else {\n @if (cell.state === 'error') {\n @if (cellErrorMark(); as mark) {\n <!-- A feature (etTableCellErrorTooltip) draws the mark instead, so the overlay runtime\n only ships when a table actually wants a tooltip. -->\n <ng-container\n *ngComponentOutlet=\"mark.component; inputs: { message: cell.message }; injector: mark.injector\"\n />\n } @else {\n <!-- Color-scoped here rather than on the cell: the mark is the only part that must read\n as an error, and a provider per errored cell is cheap where one per cell would not\n be. The message rides along as `title`, which costs nothing. -->\n <i\n [etProvideColor]=\"errorColorTheme\"\n [attr.title]=\"cell.message\"\n [attr.aria-label]=\"cell.message\"\n [attr.aria-hidden]=\"cell.message ? null : 'true'\"\n class=\"et-table-cell-error-icon\"\n etIcon=\"et-triangle-exclamation\"\n ></i>\n }\n }\n @if (cell.template; as bodyTemplate) {\n <ng-container *ngTemplateOutlet=\"bodyTemplate; context: cell.context\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.value }}</span>\n }\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <!-- The detail row of an expanded row, from etTableRowExpansion \u2014 the whole row, its chrome and\n its animation belong to the feature, so a table that never expands carries none of them. -->\n @if (rowVm.detail; as detail) {\n <ng-container *ngComponentOutlet=\"detail.component; inputs: { row: rowVm.row }; injector: detail.injector\" />\n }\n } @empty {\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-empty-cell\" role=\"gridcell\">\n @if (emptyTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: rows() }\" />\n } @else {\n <ng-content select=\"[etTableEmpty]\">{{ resolvedLabels().empty }}</ng-content>\n }\n </div>\n </div>\n }\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.end\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n <!-- Edge gradients marking rows scrolled out of view horizontally. The layer is absolutely positioned\n over the whole grid \u2014 the full scroll extent, not just the viewport \u2014 which is what lets the two\n fades inside it hold their place with `position: sticky` for the entire scroll range. Their inline\n inset clears whatever columns are pinned at that edge, so the fade marks where rows actually\n disappear (a pinned column's inner edge) rather than the viewport's edge. -->\n <div class=\"et-table-scroll-fades\" role=\"presentation\" aria-hidden=\"true\">\n <div\n [style.inset-inline-start.px]=\"fadeInset().start\"\n [class.et-table-scroll-fade--visible]=\"scrollFades().start\"\n class=\"et-table-scroll-fade et-table-scroll-fade--start\"\n ></div>\n <div\n [style.inset-inline-end.px]=\"fadeInset().end\"\n [class.et-table-scroll-fade--visible]=\"scrollFades().end\"\n class=\"et-table-scroll-fade et-table-scroll-fade--end\"\n ></div>\n </div>\n\n @if (hasFooter()) {\n <div class=\"et-table-footer-row\" role=\"row\">\n @for (lead of leadCells(); track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n aria-hidden=\"true\"\n ></div>\n }\n @for (cell of footerCells(); track cell.key) {\n <div\n [attr.data-align]=\"cell.align\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n >\n @if (cell.template; as footerTemplate) {\n <ng-container *ngTemplateOutlet=\"footerTemplate; context: { $implicit: rows() }\" />\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-footer-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n }\n</div>\n\n<!-- Full-width footer slot (paginator, page-size, etc.), pinned to the bottom of the scroll viewport.\n Rendered only when the consumer projects `[etTableFooter]`, so the chrome never shows empty. -->\n@if (footerSlot()) {\n <div class=\"et-table-footer\">\n <ng-content select=\"[etTableFooter]\" />\n </div>\n}\n\n<!-- Floating UI from opt-in features (the reorder drag ghost / drop indicator), stamped here so a\n feature can draw without having a view \u2014 or an element \u2014 of its own. -->\n@for (layer of layers(); track $index) {\n <ng-container *ngComponentOutlet=\"layer.component; injector: layer.injector\" />\n}\n", styles: ["@layer components{@property --et-table-cell-padding-block{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-table-cell-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 12px;}:where(.et-table-host){display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:1fr auto;overflow:auto;--_et-table-band: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 7%, var(--et-surface-background-solid, Canvas) );--_et-table-header-bg: var(--et-surface-background-solid, Canvas);--_et-table-header-border: var(--et-surface-border-solid, rgb(128 128 128 / .3));--_et-table-row-divider: transparent;--_et-table-stripe-bg: transparent;--_et-table-stripe-solid: var(--et-surface-background-solid, Canvas)}.et-table-host:where([data-density=sm]){--et-table-cell-padding-block: 6px;--et-table-cell-padding-inline: 10px}.et-table-host:where([data-density=md]){--et-table-cell-padding-block: 10px;--et-table-cell-padding-inline: 12px}.et-table-host:where([data-density=lg]){--et-table-cell-padding-block: 15px;--et-table-cell-padding-inline: 16px}.et-table-host:where([data-appearance=enclosed],[data-appearance=zebra],[data-appearance=grid]){border:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3));border-radius:10px}.et-table-host:where([data-appearance=enclosed]){--_et-table-header-bg: var(--_et-table-band);--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15));box-shadow:0 1px 2px #0000000a,0 6px 16px #0000000f}.et-table-host:where([data-appearance=divided]){--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=zebra]){--_et-table-header-bg: var(--_et-table-band);--_et-table-stripe-bg: color-mix(in srgb, var(--et-surface-interaction-solid, gray) 4%, transparent);--_et-table-stripe-solid: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 4%, var(--et-surface-background-solid, Canvas) )}.et-table-host:where([data-appearance=grid]){--_et-table-header-bg: var(--_et-table-band);--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=bare]){--_et-table-header-border: transparent}.et-table{display:grid;position:relative;align-content:start;inline-size:min-content;min-inline-size:100%;background:var(--et-surface-background-solid, Canvas);color:var(--et-surface-color-solid, CanvasText);font-size:14px;line-height:1.4}.et-table-filler-cell{padding-inline:0}.et-table-header-row,.et-table-row{display:contents}.et-table-header-cell,.et-table-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}.et-table-cell-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-table-header-cell{position:sticky;inset-block-start:max(0px,calc(var(--_et-table-group-h, 0px) - 1px));gap:4px;z-index:1;font-weight:600;color:var(--et-surface-color-muted-solid, CanvasText);background:var(--_et-table-header-bg);border-block-end:1px solid var(--_et-table-header-border)}.et-table-cell{border-block-end:1px solid var(--_et-table-row-divider)}.et-table-row--stripe .et-table-cell{background:var(--_et-table-stripe-bg)}.et-table-host:where([data-appearance=grid]) .et-table-header-cell,.et-table-host:where([data-appearance=grid]) .et-table-cell{border-inline-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=grid]) .et-table-header-row .et-table-header-cell:last-child,.et-table-host:where([data-appearance=grid]) .et-table-row .et-table-cell:last-child{border-inline-end:0}.et-table-sticky-start,.et-table-sticky-end{position:sticky;z-index:1}.et-table-sticky-start{box-shadow:4px 0 6px -4px #0000002e}.et-table-sticky-end{box-shadow:-4px 0 6px -4px #0000002e}.et-table-cell:where(.et-table-sticky-start,.et-table-sticky-end){background:var(--et-surface-background-solid, Canvas)}.et-table-row--stripe .et-table-cell.et-table-sticky-start,.et-table-row--stripe .et-table-cell.et-table-sticky-end{background:var(--_et-table-stripe-solid)}@media(hover:hover){.et-table-row:hover .et-table-cell.et-table-sticky-start,.et-table-row:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 8%,var(--et-surface-background-solid, Canvas))}}.et-table-header-cell:where(.et-table-sticky-start,.et-table-sticky-end),.et-table-footer-cell:where(.et-table-sticky-start,.et-table-sticky-end){z-index:3}.et-table-footer-row{display:contents}.et-table-footer-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);position:sticky;inset-block-end:0;z-index:1;font-weight:600;background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-footer-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-scroll-fades{position:absolute;inset:0;display:flex;justify-content:space-between;z-index:3;pointer-events:none}.et-table-scroll-fade{position:sticky;flex:none;inline-size:var(--et-table-scroll-fade-size, 28px);opacity:0;transition:opacity .15s ease}.et-table-scroll-fade--visible{opacity:1}.et-table-scroll-fade--start{background:linear-gradient(to right,#00000029,#0000)}.et-table-scroll-fade--end{background:linear-gradient(to left,#00000029,#0000)}@media(prefers-reduced-motion:reduce){.et-table-scroll-fade{transition:none}}.et-table-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;position:sticky;inset-block-end:0;inset-inline-start:0;z-index:4;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-label{margin:0;font-size:14px;color:var(--et-surface-color-muted-solid, CanvasText)}@media(pointer:coarse){.et-table-footer{gap:8px;padding:8px var(--et-table-cell-padding-inline)}}.et-table-header-cell:where([data-align=center]),.et-table-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-header-cell:where([data-align=end]),.et-table-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-row--interactive .et-table-cell{cursor:pointer}@media(hover:hover){.et-table-row:hover .et-table-cell{background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 8%,transparent)}}.et-table-header-label{display:flex;align-items:center;gap:4px;flex:1;min-inline-size:0;margin:0;padding:0;font:inherit;color:inherit;text-align:inherit;background:none;border:none}.et-table-header-label:where(.et-table-header-label--sortable){cursor:pointer}.et-table-header-cell:where([data-align=center]) .et-table-header-label{justify-content:center}.et-table-header-cell:where([data-align=end]) .et-table-header-label{justify-content:flex-end}.et-table-sort-indicator{flex:none;inline-size:1.15em;block-size:1.15em;transform:translateY(-.045em);color:var(--et-theme-color-primary-solid, currentColor);transition:transform .2s var(--ease-out-5, ease)}.et-table-sort-indicator:where([data-direction=desc]){transform:translateY(-.045em) rotate(180deg)}.et-table-sort-indicator.et-table-sort-indicator--enter{animation:et-table-sort-in .15s ease}.et-table-sort-indicator.et-table-sort-indicator--leave{animation:et-table-sort-in .12s ease reverse forwards}@keyframes et-table-sort-in{0%{opacity:0}to{opacity:1}}@media(prefers-reduced-motion:reduce){.et-table-sort-indicator{transition:none}.et-table-sort-indicator.et-table-sort-indicator--enter,.et-table-sort-indicator.et-table-sort-indicator--leave{animation:none}}.et-table-message-row{display:contents}.et-table-empty-cell,.et-table-error-cell{grid-column:1 / -1;padding:32px var(--et-table-cell-padding-inline);color:var(--et-surface-color-muted-solid, CanvasText);text-align:center}.et-table-error-cell{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px}.et-table-error-icon{flex:none;inline-size:16px;block-size:16px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=error]){gap:6px}.et-table-cell-error-icon{flex:none;inline-size:14px;block-size:14px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=loading]){display:flex}.et-table-busy-bar{grid-column:1 / -1;block-size:2px;overflow:hidden;background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 10%,transparent)}.et-table-busy-bar:after{content:\"\";display:block;inline-size:40%;block-size:100%;border-radius:999px;background:var(--et-theme-color-primary-solid, currentColor);animation:et-table-busy-sweep 1.1s ease-in-out infinite}@keyframes et-table-busy-sweep{0%{transform:translate(-100%)}to{transform:translate(250%)}}@media(prefers-reduced-motion:reduce){.et-table-busy-bar:after{inline-size:100%;animation:none}}}\n"] }]
61443
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], rowsSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsSource", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], errorTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorTemplate", required: false }] }], cellState: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellState", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }, { type: i0.Output, args: ["sortChange"] }], multiSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSort", required: false }] }], sortMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortMode", required: false }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], filterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMode", required: false }] }], expandedRowTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedRowTemplate", required: false }] }], rowInteractive: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowInteractive", required: false }] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], footerSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TableFooterDirective), { isSignal: true }] }], headerCells: [{ type: i0.ViewChildren, args: ['headerCell', { isSignal: true }] }], bodyCells: [{ type: i0.ViewChildren, args: ['bodyCell', { isSignal: true }] }], leadHeaderCells: [{ type: i0.ViewChildren, args: ['leadHeaderCell', { isSignal: true }] }] } });
61721
+ '[class.et-table-host--scrolled-block-start]': 'blockScrollShadows().blockStart',
61722
+ '[class.et-table-host--scrolled-block-end]': 'blockScrollShadows().blockEnd',
61723
+ '[class.et-table-host--scrolled-inline-start]': 'scrollFades().start',
61724
+ '[class.et-table-host--scrolled-inline-end]': 'scrollFades().end',
61725
+ '[style.--_et-table-viewport-inline-size.px]': 'viewportInlineSize()',
61726
+ '(scroll)': 'syncScrollState()',
61727
+ }, template: "<!-- Every binding below reads a field off a render model (see the `\u2026Vm` types in the component):\n methods belong in event bindings, not in bindings the framework re-evaluates each pass. -->\n<div #grid [style.grid-template-columns]=\"templateColumns()\" class=\"et-table\" role=\"grid\">\n <!-- Rows a feature renders above the column headers (etTableGroupHeaders' spanning group row). Each\n is display: contents and lays its own cells into these tracks \u2014 see registerHeaderRow. -->\n @for (headerRow of headerRows(); track $index) {\n <ng-container *ngComponentOutlet=\"headerRow.component; injector: headerRow.injector\" />\n }\n\n <div class=\"et-table-header-row\" role=\"row\">\n <!-- Leading utility columns (selection from a feature, the expander when expansion is on). The\n table owns the cell chrome; the feature only supplies what goes inside. -->\n @for (lead of leadCells(); track lead.key) {\n <div\n #leadHeaderCell\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n [attr.aria-hidden]=\"lead.lead.headerComponent ? null : 'true'\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n @if (lead.lead.headerComponent; as headerComponent) {\n <ng-container *ngComponentOutlet=\"headerComponent; injector: lead.lead.injector\" />\n }\n </div>\n }\n @for (cell of headerCellVms(); track cell.key) {\n <div\n #headerCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.aria-sort]=\"cell.ariaSort\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n <!-- Sorting is the whole header's job, not a control's: the label plus everything around it is\n one button, and the only sort affordance is the direction arrow, which appears once the\n column is actually sorted. Adornments sit outside it so their own clicks don't sort. -->\n @if (cell.sortable) {\n <button\n [attr.aria-label]=\"cell.sortLabel\"\n (click)=\"toggleSort(cell.key)\"\n class=\"et-table-header-label et-table-header-label--sortable\"\n type=\"button\"\n >\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n @if (cell.direction; as direction) {\n <!-- Flipping direction keeps this element mounted, so the arrow turns over rather than\n swapping; only appearing and disappearing are the fade, and only for a sort the user\n just asked for (see sortIndicatorEnter). -->\n <i\n [attr.data-direction]=\"direction\"\n [animate.enter]=\"sortIndicatorEnter()\"\n [animate.leave]=\"sortIndicatorLeave()\"\n class=\"et-table-sort-indicator\"\n etIcon=\"et-arrow-up\"\n ></i>\n }\n </button>\n } @else {\n <span class=\"et-table-header-label\">\n @if (cell.template; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: cell.column.header }\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.column.header }}</span>\n }\n </span>\n }\n\n <!-- UI from opt-in features (filter menu, \u2026), each registered rather than referenced \u2014 see\n registerHeaderAdornment. Renders nothing when no feature is imported.\n\n Dropped once the column is covered by a pinned one: an adornment's menu is a portal, so it\n would go on floating over the pinned column, anchored to a cell nobody can see. Unmounting\n the trigger is what closes it. -->\n @if (!cell.obscured) {\n @for (adornment of headerAdornments(); track $index) {\n <ng-container\n *ngComponentOutlet=\"adornment.component; inputs: { column: cell.column }; injector: adornment.injector\"\n />\n }\n }\n </div>\n }\n <!-- Filler cell for the trailing slack track (see hasFiller): carries the header band to the\n panel's edge when every column is a rigid width. -->\n @if (hasFiller()) {\n <div class=\"et-table-header-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n <!-- Trailing utility columns (a selection column moved to this edge). Same chrome as the leading\n ones, pinned to the trailing edge instead - see TableLeadColumn.side. -->\n @for (trail of trailCells(); track trail.key) {\n <div\n #trailHeaderCell\n [class]=\"trail.cellClass\"\n [class.et-table-sticky-end]=\"trail.sticky\"\n [style.inset-inline-end.px]=\"trail.offset\"\n [attr.aria-hidden]=\"trail.lead.headerComponent ? null : 'true'\"\n class=\"et-table-header-cell\"\n role=\"columnheader\"\n >\n @if (trail.lead.headerComponent; as headerComponent) {\n <ng-container *ngComponentOutlet=\"headerComponent; injector: trail.lead.injector\" />\n }\n </div>\n }\n </div>\n\n <!-- Refetching over rows that are already on screen: a 2px indeterminate bar right under the header,\n so the data stays readable and in place. Drawn here rather than with `et-progress-bar` \u2014 the base\n table takes no component dependencies, and this is 2px of chrome, not a control. -->\n @if (showBusyBar()) {\n <!-- Faded in and out: a refetch is often over in a few hundred ms, and a bar that pops in and\n vanishes reads as a flicker rather than as work happening. -->\n <div\n class=\"et-table-busy-bar\"\n animate.enter=\"et-table-busy-bar--enter\"\n animate.leave=\"et-table-busy-bar--leave\"\n role=\"presentation\"\n aria-hidden=\"true\"\n ></div>\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.start\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n @if (hasError()) {\n <!-- The error state stands in for the whole body: rows are either trustworthy or absent. -->\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-error-cell\" role=\"gridcell\" aria-live=\"polite\">\n @if (errorTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: error() }\" />\n } @else {\n <ng-content select=\"[etTableError]\">\n <i [etProvideColor]=\"errorColorTheme\" class=\"et-table-error-icon\" etIcon=\"et-triangle-exclamation\"></i>\n <span>{{ resolvedLabels().error }}</span>\n </ng-content>\n }\n </div>\n </div>\n } @else if (showPlaceholderRows()) {\n <!-- First load with nothing to show yet. What a loading body looks like belongs to a feature\n (etTableSkeleton draws placeholder rows in these tracks); with none the body stays blank rather\n than showing a misleading empty state \u2014 the host's `aria-busy` is the announcement. -->\n @if (bodyPlaceholder(); as placeholder) {\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n }\n } @else {\n @for (rowVm of bodyRows(); track rowVm.key) {\n <!-- A linked row is not a tab stop of its own: its anchor is the one stop, and the one link. -->\n <div\n [class]=\"rowVm.classes\"\n [class.et-table-row--stripe]=\"rowVm.stripe\"\n [class.et-table-row--last]=\"rowVm.last\"\n [class.et-table-row--interactive]=\"rowInteractive()\"\n [class.et-table-row--box]=\"rowBox()\"\n [class.et-table-row--link]=\"rowVm.href !== null\"\n [attr.tabindex]=\"rowInteractive() && !cellNavigation() && rowVm.href === null ? 0 : null\"\n (click)=\"activateRow(rowVm.row, $event)\"\n (keydown.enter)=\"activateRow(rowVm.row, $event)\"\n (keydown.space)=\"activateRow(rowVm.row, $event)\"\n class=\"et-table-row\"\n role=\"row\"\n >\n @for (lead of rowVm.leads; track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n <ng-container\n *ngComponentOutlet=\"lead.lead.bodyComponent; inputs: { row: rowVm.row }; injector: lead.lead.injector\"\n />\n </div>\n }\n @for (cell of rowVm.cells; track cell.key) {\n <div\n #bodyCell\n [attr.data-align]=\"cell.align\"\n [attr.data-col-key]=\"cell.key\"\n [attr.tabindex]=\"cellNavigation() ? -1 : null\"\n [attr.data-state]=\"cell.state\"\n [attr.id]=\"cell.linkHost ? rowVm.linkLabelId : null\"\n [class.et-table-cell--interactive]=\"cell.interactive\"\n [class.et-table-cell--editing]=\"cell.edit\"\n [class.et-skeleton--animated]=\"cell.state === 'loading'\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n @if (cell.edit; as edit) {\n <!-- The one cell in edit mode: the column's etTableCellEdit template, rendered with the\n editing feature's own context (the draft field). See registerCellEditing. -->\n <ng-container *ngTemplateOutlet=\"edit.template; context: edit.context\" />\n } @else if (cell.state === 'loading' && cellPlaceholder(); as placeholder) {\n <!-- A cell that is loading on its own (an inline edit saving) shows a feature's placeholder\n instead of its value; the row around it stays readable. Without one the value stays put\n and `data-state` carries the cue \u2014 see registerCellPlaceholder. -->\n <ng-container *ngComponentOutlet=\"placeholder.component; injector: placeholder.injector\" />\n } @else {\n @if (cell.state === 'error') {\n @if (cellErrorMark(); as mark) {\n <!-- A feature (etTableCellErrorTooltip) draws the mark instead, so the overlay runtime\n only ships when a table actually wants a tooltip. -->\n <ng-container\n *ngComponentOutlet=\"mark.component; inputs: { message: cell.message }; injector: mark.injector\"\n />\n } @else {\n <!-- Color-scoped here rather than on the cell: the mark is the only part that must read\n as an error, and a provider per errored cell is cheap where one per cell would not\n be. The message rides along as `title`, which costs nothing. -->\n <i\n [etProvideColor]=\"errorColorTheme\"\n [attr.title]=\"cell.message\"\n [attr.aria-label]=\"cell.message\"\n [attr.aria-hidden]=\"cell.message ? null : 'true'\"\n class=\"et-table-cell-error-icon\"\n etIcon=\"et-triangle-exclamation\"\n ></i>\n }\n }\n @if (cell.template; as bodyTemplate) {\n <ng-container *ngTemplateOutlet=\"bodyTemplate; context: cell.context\" />\n } @else {\n <span class=\"et-table-cell-text\">{{ cell.value }}</span>\n }\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n @for (trail of rowVm.trails; track trail.key) {\n <div\n [class]=\"trail.cellClass\"\n [class.et-table-sticky-end]=\"trail.sticky\"\n [style.inset-inline-end.px]=\"trail.offset\"\n class=\"et-table-cell\"\n role=\"gridcell\"\n >\n <ng-container\n *ngComponentOutlet=\"trail.lead.bodyComponent; inputs: { row: rowVm.row }; injector: trail.lead.injector\"\n />\n </div>\n }\n\n @if (rowVm.href !== null) {\n <!-- The row's link: one real anchor, stretched over the row box (see rowBox) rather than\n wrapping any content, so the cells stay exactly as a table without links renders them.\n It carries no text of its own and is named by the identity cell instead - `aria-labelledby`\n resolves to that cell's content, which is the row's identity.\n\n A child of the row, not of a cell: a cell that is pinned is `position: sticky` and would\n therefore be the anchor's containing block, shrinking the row's hit area to that one\n column. The row box is the containing block that spans every cell. -->\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content -- the rule's\n allowList knows `aria-label` but not `aria-labelledby`, which names it just as well. -->\n <a\n [attr.href]=\"rowVm.href\"\n [attr.aria-labelledby]=\"rowVm.linkLabelId\"\n (click)=\"activateRowLink(rowVm.link, $event)\"\n class=\"et-table-row-link\"\n ></a>\n }\n\n @if (appearance() === 'cards') {\n <div class=\"et-table-card-corners\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <!-- The detail row of an expanded row, from etTableRowExpansion \u2014 the whole row, its chrome and\n its animation belong to the feature, so a table that never expands carries none of them. -->\n @if (rowVm.detail; as detail) {\n <ng-container *ngComponentOutlet=\"detail.component; inputs: { row: rowVm.row }; injector: detail.injector\" />\n }\n } @empty {\n <div class=\"et-table-message-row\" role=\"row\">\n <div class=\"et-table-empty-cell\" role=\"gridcell\">\n @if (emptyTemplate(); as template) {\n <ng-container *ngTemplateOutlet=\"template; context: { $implicit: rows() }\" />\n } @else {\n <ng-content select=\"[etTableEmpty]\">{{ resolvedLabels().empty }}</ng-content>\n }\n </div>\n </div>\n }\n }\n\n @if (spacers(); as spacer) {\n <div [style.block-size.px]=\"spacer.end\" class=\"et-table-spacer\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n\n <!-- Edge gradients marking rows scrolled out of view horizontally, on the edges no pinned column\n already marks (see visibleScrollFades). The layer is absolutely positioned over the whole grid \u2014\n the full scroll extent, not just the viewport \u2014 which is what lets the two fades inside it hold\n their place with `position: sticky` for the entire scroll range. -->\n <div class=\"et-table-scroll-fades\" role=\"presentation\" aria-hidden=\"true\">\n <div\n [style.inset-inline-start.px]=\"fadeInset().start\"\n [class.et-table-scroll-fade--visible]=\"visibleScrollFades().start\"\n class=\"et-table-scroll-fade et-table-scroll-fade--start\"\n ></div>\n <div\n [style.inset-inline-end.px]=\"fadeInset().end\"\n [class.et-table-scroll-fade--visible]=\"visibleScrollFades().end\"\n class=\"et-table-scroll-fade et-table-scroll-fade--end\"\n ></div>\n </div>\n\n @if (hasFooter()) {\n <div class=\"et-table-footer-row\" role=\"row\">\n @for (lead of leadCells(); track lead.key) {\n <div\n [class]=\"lead.cellClass\"\n [class.et-table-sticky-start]=\"lead.sticky\"\n [style.inset-inline-start.px]=\"lead.offset\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n aria-hidden=\"true\"\n ></div>\n }\n @for (cell of footerCells(); track cell.key) {\n <div\n [attr.data-align]=\"cell.align\"\n [class.et-table-sticky-start]=\"cell.stickyStart\"\n [class.et-table-sticky-end]=\"cell.stickyEnd\"\n [style.inset-inline-start.px]=\"cell.offsetStart\"\n [style.inset-inline-end.px]=\"cell.offsetEnd\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n >\n @if (cell.template; as footerTemplate) {\n <ng-container *ngTemplateOutlet=\"footerTemplate; context: { $implicit: rows() }\" />\n }\n </div>\n }\n @if (hasFiller()) {\n <div class=\"et-table-footer-cell et-table-filler-cell\" role=\"presentation\" aria-hidden=\"true\"></div>\n }\n @for (trail of trailCells(); track trail.key) {\n <div\n [class]=\"trail.cellClass\"\n [class.et-table-sticky-end]=\"trail.sticky\"\n [style.inset-inline-end.px]=\"trail.offset\"\n class=\"et-table-footer-cell\"\n role=\"gridcell\"\n aria-hidden=\"true\"\n ></div>\n }\n </div>\n }\n</div>\n\n<!-- Full-width footer slot (paginator, page-size, etc.), pinned to the bottom of the scroll viewport.\n Rendered only when the consumer projects `[etTableFooter]`, so the chrome never shows empty. -->\n@if (footerSlot()) {\n <div class=\"et-table-footer\">\n <ng-content select=\"[etTableFooter]\" />\n </div>\n}\n\n<!-- Floating UI from opt-in features (the reorder drag ghost / drop indicator), stamped here so a\n feature can draw without having a view \u2014 or an element \u2014 of its own. -->\n@for (layer of layers(); track $index) {\n <ng-container *ngComponentOutlet=\"layer.component; injector: layer.injector\" />\n}\n", styles: ["@layer components{@property --et-table-cell-padding-block{syntax: \"<length>\"; inherits: true; initial-value: 10px;}@property --et-table-cell-padding-inline{syntax: \"<length>\"; inherits: true; initial-value: 12px;}:where(.et-table-host){display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:1fr auto;overflow:auto;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 35%,transparent) transparent;--_et-table-band: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 7%, var(--et-surface-background-solid, Canvas) );--_et-table-header-bg: var(--et-table-header-background-color, var(--et-surface-background-solid, Canvas));--_et-table-header-border: var(--et-surface-border-solid, rgb(128 128 128 / .3));--_et-table-row-divider: transparent;--_et-table-row-surface: var(--et-surface-background-solid, Canvas);--_et-table-stripe-bg: transparent;--_et-table-stripe-solid: var(--_et-table-row-surface);--_et-table-row-hover: color-mix(in srgb, var(--et-surface-interaction-solid, gray) 8%, transparent);--_et-table-row-hover-solid: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 8%, var(--_et-table-row-surface) );--_et-table-pin-shadow: var( --et-table-pin-shadow-color, color-mix(in srgb, var(--et-surface-interaction-solid, black) 30%, transparent) );--_et-table-pin-shadow-inline: var(--et-table-pin-shadow-color-inline, var(--_et-table-pin-shadow));--_et-table-pin-shadow-block: var(--et-table-pin-shadow-color-block, var(--_et-table-pin-shadow));--_et-table-edge-none: 0 0 transparent;--_et-table-edge-start: var(--_et-table-edge-none);--_et-table-edge-end: var(--_et-table-edge-none);--_et-table-edge-block-start: var(--_et-table-edge-none);--_et-table-edge-block-end: var(--_et-table-edge-none)}.et-table-host--scrolled-inline-start{--_et-table-edge-start: 8px 0 10px -6px var(--_et-table-pin-shadow-inline)}.et-table-host--scrolled-inline-end{--_et-table-edge-end: -8px 0 10px -6px var(--_et-table-pin-shadow-inline)}.et-table-host--scrolled-block-start{--_et-table-edge-block-start: 0 8px 10px -6px var(--_et-table-pin-shadow-block)}.et-table-host--scrolled-block-end{--_et-table-edge-block-end: 0 -8px 10px -6px var(--_et-table-pin-shadow-block)}.et-table-host:where([data-density=sm]){--et-table-cell-padding-block: 6px;--et-table-cell-padding-inline: 10px}.et-table-host:where([data-density=md]){--et-table-cell-padding-block: 10px;--et-table-cell-padding-inline: 12px}.et-table-host:where([data-density=lg]){--et-table-cell-padding-block: 15px;--et-table-cell-padding-inline: 16px}.et-table-host:where([data-appearance=enclosed],[data-appearance=zebra],[data-appearance=grid]){border:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3));border-radius:10px}.et-table-host:where([data-appearance=enclosed]){--_et-table-header-bg: var(--et-table-header-background-color, var(--_et-table-band));--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15));box-shadow:0 1px 2px #0000000a,0 6px 16px #0000000f}.et-table-host:where([data-appearance=divided]){--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=zebra]){--_et-table-header-bg: var(--et-table-header-background-color, var(--_et-table-band));--_et-table-stripe-bg: color-mix(in srgb, var(--et-surface-interaction-solid, gray) 4%, transparent);--_et-table-stripe-solid: color-mix( in srgb, var(--et-surface-interaction-solid, gray) 4%, var(--_et-table-row-surface) )}.et-table-host:where([data-appearance=grid]){--_et-table-header-bg: var(--et-table-header-background-color, var(--_et-table-band));--_et-table-row-divider: var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=bare]){--_et-table-header-border: transparent}.et-table-host:where([data-appearance=cards]){--_et-table-header-bg: var(--et-table-header-background-color, var(--et-surface-background-solid, Canvas));--_et-table-row-divider: transparent;--_et-table-row-surface: var(--_et-table-band)}.et-table{display:grid;position:relative;align-content:start;inline-size:min-content;min-inline-size:100%;background:var(--et-surface-background-solid, Canvas);color:var(--et-surface-color-solid, CanvasText);font-size:14px;line-height:1.4}.et-table-filler-cell{padding-inline:0}.et-table-header-row,.et-table-row{display:contents}.et-table-header-cell,.et-table-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}.et-table-cell-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.et-table-header-cell{position:sticky;inset-block-start:max(0px,calc(var(--_et-table-group-h, 0px) - 1px));gap:4px;z-index:1;font-weight:600;color:var(--et-surface-color-muted-solid, CanvasText);background:var(--_et-table-header-bg);border-block-end:1px solid var(--_et-table-header-border)}.et-table-header-cell .et-table-filter-trigger,.et-table-header-cell .et-table-column-menu-trigger{--et-icon-button-size: 2.8rem;--et-icon-button-icon-size: 1.6rem;min-width:24px;min-height:24px}.et-table-cell{border-block-end:1px solid var(--_et-table-row-divider)}.et-table-header-cell{box-shadow:var(--_et-table-edge-block-start)}.et-table-header-cell.et-table-sticky-start{box-shadow:var(--_et-table-edge-block-start),var(--_et-table-edge-start)}.et-table-header-cell.et-table-sticky-end{box-shadow:var(--_et-table-edge-block-start),var(--_et-table-edge-end)}.et-table-footer,.et-table-footer-cell{box-shadow:var(--_et-table-edge-block-end)}.et-table-footer-cell.et-table-sticky-start{box-shadow:var(--_et-table-edge-block-end),var(--_et-table-edge-start)}.et-table-footer-cell.et-table-sticky-end{box-shadow:var(--_et-table-edge-block-end),var(--_et-table-edge-end)}.et-table-row--last:not(:has(+.et-table-detail-row)) .et-table-cell{border-block-end:0}.et-table-row--stripe .et-table-cell{background:var(--_et-table-stripe-bg)}.et-table-host:where([data-appearance=grid]) .et-table-header-cell,.et-table-host:where([data-appearance=grid]) .et-table-cell{border-inline-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=grid]) .et-table-header-row .et-table-header-cell:last-child,.et-table-host:where([data-appearance=grid]) .et-table-row .et-table-cell:nth-last-child(1 of.et-table-cell){border-inline-end:0}.et-table-sticky-start,.et-table-sticky-end{position:sticky;z-index:1}.et-table-sticky-start{box-shadow:var(--_et-table-edge-start)}.et-table-sticky-end{box-shadow:var(--_et-table-edge-end)}.et-table-sticky-start:has(~.et-table-sticky-start){--_et-table-edge-start: 0 0 transparent}.et-table-sticky-end~.et-table-sticky-end{--_et-table-edge-end: 0 0 transparent}.et-table-cell:where(.et-table-sticky-start,.et-table-sticky-end){background:var(--_et-table-row-surface)}.et-table-row--stripe .et-table-cell.et-table-sticky-start,.et-table-row--stripe .et-table-cell.et-table-sticky-end{background:var(--_et-table-stripe-solid)}@media(hover:hover){.et-table-row:hover .et-table-cell.et-table-sticky-start,.et-table-row:hover .et-table-cell.et-table-sticky-end{background:var(--_et-table-row-hover-solid)}}.et-table-header-cell:where(.et-table-sticky-start,.et-table-sticky-end),.et-table-footer-cell:where(.et-table-sticky-start,.et-table-sticky-end){z-index:3}.et-table-footer-row{display:contents}.et-table-footer-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);position:sticky;inset-block-end:0;z-index:1;font-weight:600;background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-footer-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-scroll-fades{position:absolute;inset:0;display:flex;justify-content:space-between;z-index:3;pointer-events:none}.et-table-scroll-fade{position:sticky;flex:none;inline-size:var(--et-table-scroll-fade-size, 28px);opacity:0;transition:opacity .15s ease;--_et-table-scroll-fade-color: var( --et-table-scroll-fade-color, color-mix(in srgb, var(--et-surface-interaction-solid, black) 22%, transparent) )}.et-table-scroll-fade--visible{opacity:1}.et-table-scroll-fade--start{background:linear-gradient(to right,var(--_et-table-scroll-fade-color),transparent)}.et-table-scroll-fade--end{background:linear-gradient(to left,var(--_et-table-scroll-fade-color),transparent)}@media(prefers-reduced-motion:reduce){.et-table-scroll-fade{transition:none}}.et-table-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;position:sticky;inset-block-end:0;inset-inline-start:0;z-index:4;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);background:var(--_et-table-header-bg);border-block-start:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3))}.et-table-footer-label{margin:0;font-size:14px;color:var(--et-surface-color-muted-solid, CanvasText)}@media(pointer:coarse){.et-table-footer{gap:8px;padding:8px var(--et-table-cell-padding-inline)}}.et-table-header-cell:where([data-align=center]),.et-table-cell:where([data-align=center]){justify-content:center;text-align:center}.et-table-header-cell:where([data-align=end]),.et-table-cell:where([data-align=end]){justify-content:flex-end;text-align:end}.et-table-row--interactive .et-table-cell{cursor:pointer}@media(hover:hover){.et-table-row:hover .et-table-cell{background:var(--_et-table-row-hover)}}.et-table-row--box{grid-column:1 / -1;display:grid;grid-template-columns:subgrid;position:relative;z-index:0}.et-table-row-link{position:absolute;inset:0;z-index:2;cursor:pointer}.et-table-header-label:focus-visible,.et-table-expander:focus-visible,.et-table-cell:focus-visible{outline:2px solid var(--et-theme-color-primary-solid, currentColor);outline-offset:-2px}.et-table-header-label{border-radius:4px}.et-table-row-link:focus-visible{outline:2px solid var(--et-theme-color-primary-solid, currentColor);outline-offset:-4px}.et-table-row--link :where(.et-table-select-cell,.et-table-expander-cell,.et-table-cell--interactive,.et-table-cell--editing){z-index:3}.et-table-row--link :where(.et-table-select-cell,.et-table-expander-cell,.et-table-cell--interactive,.et-table-cell--editing):not(.et-table-sticky-start,.et-table-sticky-end){position:relative}.et-table-host:where([data-appearance=cards]) .et-table-row{margin-block-end:var(--et-table-row-gap, 8px);background:var(--_et-table-band);border-radius:var(--et-table-row-radius, 10px)}.et-table-host:where([data-appearance=cards]) .et-table-row--box:after{content:\"\";position:absolute;inset:0;z-index:4;border:1px solid var(--et-table-row-border-color, var(--et-surface-border-solid, rgb(128 128 128 / .3)));border-radius:inherit;pointer-events:none}.et-table-host:where([data-appearance=cards]) .et-table-cell:where(.et-table-sticky-start,.et-table-sticky-end){clip-path:inset(0 -24px)}.et-table-host:where([data-appearance=cards]) .et-table-header-cell{margin-block-end:var(--et-table-row-gap, 8px)}.et-table-host:where([data-appearance=cards]) .et-table-row:not(.et-table-row--interactive,.et-table-row--link){--_et-table-row-hover: transparent;--_et-table-row-hover-solid: var(--_et-table-band)}.et-table-host:where([data-appearance=cards]) .et-table-row>:first-child{border-start-start-radius:inherit;border-end-start-radius:inherit}.et-table-host:where([data-appearance=cards]) .et-table-row>.et-table-cell:nth-last-child(1 of.et-table-cell){border-start-end-radius:inherit;border-end-end-radius:inherit}.et-table-host:where([data-appearance=cards]) .et-table-row-link{border-radius:var(--et-table-row-radius, 10px)}.et-table-card-corners{position:absolute;inset:0;z-index:5;display:flex;justify-content:space-between;pointer-events:none}.et-table-host:where([data-appearance=cards]) .et-table-card-corners:before,.et-table-host:where([data-appearance=cards]) .et-table-card-corners:after{--_et-table-card-radius: var(--et-table-row-radius, 10px);--_et-table-card-edge: var(--et-table-row-border-color, var(--et-surface-border-solid, rgb(128 128 128 / .3)));--_et-table-card-outside: var(--et-surface-background-solid, Canvas);content:\"\";flex:0 0 auto;inline-size:var(--_et-table-card-radius)}.et-table-row:has(.et-table-sticky-start) .et-table-card-corners:before{position:sticky;inset-inline-start:0}.et-table-row:has(.et-table-sticky-end) .et-table-card-corners:after{position:sticky;inset-inline-end:0}.et-table-host:where([data-appearance=cards]) .et-table-card-corners:before{background:radial-gradient(circle at 100% 100%,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 0 / 100% var(--_et-table-card-radius) no-repeat,radial-gradient(circle at 100% 0,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 100% / 100% var(--_et-table-card-radius) no-repeat,linear-gradient(var(--_et-table-card-edge),var(--_et-table-card-edge)) 0 0 / 1px 100% no-repeat}.et-table-host:where([data-appearance=cards]) .et-table-card-corners:after{background:radial-gradient(circle at 0 100%,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 0 / 100% var(--_et-table-card-radius) no-repeat,radial-gradient(circle at 0 0,transparent calc(var(--_et-table-card-radius) - 1.2px),var(--_et-table-card-edge) calc(var(--_et-table-card-radius) - .8px) calc(var(--_et-table-card-radius) - .2px),var(--_et-table-card-outside) calc(var(--_et-table-card-radius) + .2px)) 0 100% / 100% var(--_et-table-card-radius) no-repeat,linear-gradient(var(--_et-table-card-edge),var(--_et-table-card-edge)) 100% 0 / 1px 100% no-repeat}.et-table-header-label{display:flex;align-items:center;gap:4px;flex:1;min-inline-size:0;margin:0;padding:0;font:inherit;color:inherit;text-align:inherit;background:none;border:none}.et-table-header-label:where(.et-table-header-label--sortable){cursor:pointer}.et-table-header-cell:where([data-align=center]) .et-table-header-label{justify-content:center}.et-table-header-cell:where([data-align=end]) .et-table-header-label{justify-content:flex-end}.et-table-sort-indicator{flex:none;inline-size:1.15em;block-size:1.15em;transform:translateY(-.045em);color:var(--et-theme-color-primary-solid, currentColor);transition:transform .2s var(--ease-out-5, ease)}.et-table-sort-indicator:where([data-direction=desc]){transform:translateY(-.045em) rotate(180deg)}.et-table-sort-indicator.et-table-sort-indicator--enter{animation:et-table-sort-in .15s ease}.et-table-sort-indicator.et-table-sort-indicator--leave{animation:et-table-sort-in .12s ease reverse forwards}@keyframes et-table-sort-in{0%{opacity:0}to{opacity:1}}@media(prefers-reduced-motion:reduce){.et-table-sort-indicator{transition:none}.et-table-sort-indicator.et-table-sort-indicator--enter,.et-table-sort-indicator.et-table-sort-indicator--leave{animation:none}}.et-table-message-row{display:contents}.et-table-empty-cell,.et-table-error-cell{grid-column:1 / -1;position:sticky;inset-inline-start:0;inline-size:var(--_et-table-viewport-inline-size, 100%);padding:32px var(--et-table-cell-padding-inline);color:var(--et-surface-color-muted-solid, CanvasText);text-align:center}.et-table-empty-cell{display:grid;place-content:center;justify-items:center}.et-table-error-cell{display:flex;flex-wrap:wrap;align-items:center;align-content:center;justify-content:center;gap:8px}.et-table-error-icon{flex:none;inline-size:16px;block-size:16px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=error]){gap:6px}.et-table-cell-error-icon{flex:none;inline-size:14px;block-size:14px;color:var(--et-theme-color-ink-solid, currentColor)}.et-table-cell:where([data-state=loading]){display:flex}.et-table-busy-bar{grid-column:1 / -1;block-size:2px;margin-block-end:-2px;overflow:hidden;background:color-mix(in srgb,var(--et-surface-interaction-solid, gray) 10%,transparent)}.et-table-host:where([data-appearance=cards]) .et-table-busy-bar{margin-block-start:calc((var(--et-table-row-gap, 8px) + 2px) / -2);margin-block-end:calc((var(--et-table-row-gap, 8px) - 2px) / 2)}.et-table-busy-bar.et-table-busy-bar--enter{animation:et-table-busy-fade .15s ease}.et-table-busy-bar.et-table-busy-bar--leave{animation:et-table-busy-fade .25s ease reverse forwards}@keyframes et-table-busy-fade{0%{opacity:0}to{opacity:1}}.et-table-busy-bar:after{content:\"\";display:block;inline-size:40%;block-size:100%;border-radius:999px;background:var(--et-theme-color-primary-solid, currentColor);animation:et-table-busy-sweep 1.1s ease-in-out infinite}@keyframes et-table-busy-sweep{0%{transform:translate(-100%)}to{transform:translate(250%)}}@media(prefers-reduced-motion:reduce){.et-table-busy-bar:after{inline-size:100%;animation:none}.et-table-busy-bar.et-table-busy-bar--enter,.et-table-busy-bar.et-table-busy-bar--leave{animation:none}}}\n"] }]
61728
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], rowsSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsSource", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], errorTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorTemplate", required: false }] }], cellState: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellState", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }, { type: i0.Output, args: ["sortChange"] }], multiSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSort", required: false }] }], sortMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortMode", required: false }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], filterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMode", required: false }] }], expandedRowTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedRowTemplate", required: false }] }], rowInteractive: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowInteractive", required: false }] }], rowLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowLink", required: false }] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], footerSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TableFooterDirective), { isSignal: true }] }], gridRef: [{ type: i0.ViewChild, args: ['grid', { isSignal: true }] }], headerCells: [{ type: i0.ViewChildren, args: ['headerCell', { isSignal: true }] }], bodyCells: [{ type: i0.ViewChildren, args: ['bodyCell', { isSignal: true }] }], leadHeaderCells: [{ type: i0.ViewChildren, args: ['leadHeaderCell', { isSignal: true }] }], trailHeaderCells: [{ type: i0.ViewChildren, args: ['trailHeaderCell', { isSignal: true }] }] } });
61444
61729
 
61445
61730
  /**
61446
61731
  * Opt-in persistence for a table's setup - column order, visibility, widths, sort, filters, expanded
@@ -61838,6 +62123,18 @@ class TableColumnChooserComponent {
61838
62123
  /** The table whose columns this toggles - bind a template ref to the `<et-table>`. */
61839
62124
  this.table = input.required(/* @ts-ignore */
61840
62125
  ...(ngDevMode ? [{ debugName: "table" }] : /* istanbul ignore next */ []));
62126
+ /**
62127
+ * Size of the trigger button. The default suits the chooser sitting in the table's own chrome; match
62128
+ * it to the other controls when you put it in a toolbar of your own.
62129
+ */
62130
+ this.size = input(BUTTON_SIZES.SM, /* @ts-ignore */
62131
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
62132
+ /**
62133
+ * Shape of the trigger button, for the same reason as {@link size}: the default reads as table chrome,
62134
+ * and a chooser standing among an app's own buttons has to read as one of them.
62135
+ */
62136
+ this.variant = input(BUTTON_VARIANTS.TRANSPARENT, /* @ts-ignore */
62137
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
61841
62138
  /**
61842
62139
  * The bound table's wording, so the chooser needs no strings of its own - localize it with
61843
62140
  * `provideTableLabels` or the table's `labels` input like everything else.
@@ -61866,7 +62163,7 @@ class TableColumnChooserComponent {
61866
62163
  table.setColumnVisible(key, !table.isColumnVisible(key));
61867
62164
  }
61868
62165
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableColumnChooserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
61869
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TableColumnChooserComponent, isStandalone: true, selector: "et-table-column-chooser", inputs: { table: { classPropertyName: "table", publicName: "table", isSignal: true, isRequired: true, transformFunction: null } }, providers: [provideIcons(GRID_2X2_ICON, EYE_ICON)], ngImport: i0, template: "<div class=\"et-table-column-chooser\" etMenu>\n <button class=\"et-table-column-chooser-trigger\" et-button size=\"sm\" variant=\"transparent\" etMenuTrigger type=\"button\">\n <i etIcon=\"et-grid-2x2\"></i>\n {{ labels().columns }}\n </button>\n\n <ng-template etMenuSurface>\n <et-menu>\n <!-- Every declared column, hidden ones included: this list is the only way back from hiding one. -->\n @for (column of table().allColumns(); track column.key) {\n <et-menu-checkbox-item\n [value]=\"column.key\"\n [checked]=\"table().isColumnVisible(column.key)\"\n [disabled]=\"isLastVisible(column.key)\"\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n (activate)=\"toggle(column.key)\"\n >\n {{ column.header || column.key }}\n </et-menu-checkbox-item>\n }\n\n <!-- Always rendered, disabled when nothing is hidden: appearing and disappearing would resize the\n menu under the pointer while columns are being toggled. -->\n <et-menu-separator />\n <button\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n [disabled]=\"!hasHidden()\"\n (activate)=\"table().showAllColumns()\"\n et-menu-item\n type=\"button\"\n >\n <i class=\"et-table-column-chooser-icon\" etIcon=\"et-eye\"></i>\n {{ labels().showAllColumns }}\n </button>\n </et-menu>\n </ng-template>\n</div>\n", styles: ["@layer components{et-table-column-chooser{display:contents}.et-table-column-chooser{display:inline-flex;flex:none}.et-table-column-chooser-icon{inline-size:var(--et-menu-item-icon-size, 16px);block-size:var(--et-menu-item-icon-size, 16px)}}\n"], dependencies: [{ kind: "directive", type: MenuDirective, selector: "[etMenu]", inputs: ["placement", "fallbackPlacements", "offset", "viewportPadding", "arrow", "arrowPadding", "autoFocus", "hoverOpen", "loop", "hoverOpenDelay", "hoverCloseDelay", "disabled", "open"], outputs: ["openChange"], exportAs: ["etMenu"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[etMenuTrigger]", exportAs: ["etMenuTrigger"] }, { kind: "directive", type: MenuSurfaceDirective, selector: "ng-template[etMenuSurface]", exportAs: ["etMenuSurface"] }, { kind: "component", type: MenuComponent, selector: "et-menu" }, { kind: "component", type: MenuItemComponent, selector: "button[et-menu-item], a[et-menu-item]", inputs: ["variant"] }, { kind: "component", type: MenuSeparatorComponent, selector: "et-menu-separator" }, { kind: "component", type: MenuCheckboxItemComponent, selector: "et-menu-checkbox-item", inputs: ["icon"] }, { kind: "component", type: ButtonComponent, selector: "[et-button]", inputs: ["variant", "size", "iconAlignment"] }, { kind: "directive", type: IconDirective, selector: "[etIcon]", inputs: ["etIcon", "variant", "allowHardcodedColor", "label"] }], encapsulation: i0.ViewEncapsulation.None }); }
62166
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TableColumnChooserComponent, isStandalone: true, selector: "et-table-column-chooser", inputs: { table: { classPropertyName: "table", publicName: "table", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideIcons(GRID_2X2_ICON, EYE_ICON)], ngImport: i0, template: "<div class=\"et-table-column-chooser\" etMenu>\n <button\n [size]=\"size()\"\n [variant]=\"variant()\"\n class=\"et-table-column-chooser-trigger\"\n et-button\n etMenuTrigger\n type=\"button\"\n >\n <i etIcon=\"et-grid-2x2\"></i>\n {{ labels().columns }}\n </button>\n\n <ng-template etMenuSurface>\n <et-menu>\n <!-- Every declared column, hidden ones included: this list is the only way back from hiding one. -->\n @for (column of table().allColumns(); track column.key) {\n <et-menu-checkbox-item\n [value]=\"column.key\"\n [checked]=\"table().isColumnVisible(column.key)\"\n [disabled]=\"isLastVisible(column.key)\"\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n (activate)=\"toggle(column.key)\"\n >\n {{ column.header || column.key }}\n </et-menu-checkbox-item>\n }\n\n <!-- Always rendered, disabled when nothing is hidden: appearing and disappearing would resize the\n menu under the pointer while columns are being toggled. -->\n <et-menu-separator />\n <button\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n [disabled]=\"!hasHidden()\"\n (activate)=\"table().showAllColumns()\"\n et-menu-item\n type=\"button\"\n >\n <i class=\"et-table-column-chooser-icon\" etIcon=\"et-eye\"></i>\n {{ labels().showAllColumns }}\n </button>\n </et-menu>\n </ng-template>\n</div>\n", styles: ["@layer components{et-table-column-chooser{display:contents}.et-table-column-chooser{display:inline-flex;flex:none}.et-table-column-chooser-icon{inline-size:var(--et-menu-item-icon-size, 16px);block-size:var(--et-menu-item-icon-size, 16px)}}\n"], dependencies: [{ kind: "directive", type: MenuDirective, selector: "[etMenu]", inputs: ["placement", "fallbackPlacements", "offset", "viewportPadding", "arrow", "arrowPadding", "autoFocus", "hoverOpen", "loop", "hoverOpenDelay", "hoverCloseDelay", "disabled", "open"], outputs: ["openChange"], exportAs: ["etMenu"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[etMenuTrigger]", exportAs: ["etMenuTrigger"] }, { kind: "directive", type: MenuSurfaceDirective, selector: "ng-template[etMenuSurface]", exportAs: ["etMenuSurface"] }, { kind: "component", type: MenuComponent, selector: "et-menu" }, { kind: "component", type: MenuItemComponent, selector: "button[et-menu-item], a[et-menu-item]", inputs: ["variant"] }, { kind: "component", type: MenuSeparatorComponent, selector: "et-menu-separator" }, { kind: "component", type: MenuCheckboxItemComponent, selector: "et-menu-checkbox-item", inputs: ["icon"] }, { kind: "component", type: ButtonComponent, selector: "[et-button]", inputs: ["variant", "size", "iconAlignment"] }, { kind: "directive", type: IconDirective, selector: "[etIcon]", inputs: ["etIcon", "variant", "allowHardcodedColor", "label"] }], encapsulation: i0.ViewEncapsulation.None }); }
61870
62167
  }
61871
62168
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableColumnChooserComponent, decorators: [{
61872
62169
  type: Component,
@@ -61880,8 +62177,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
61880
62177
  MenuCheckboxItemComponent,
61881
62178
  ButtonComponent,
61882
62179
  IconDirective,
61883
- ], providers: [provideIcons(GRID_2X2_ICON, EYE_ICON)], template: "<div class=\"et-table-column-chooser\" etMenu>\n <button class=\"et-table-column-chooser-trigger\" et-button size=\"sm\" variant=\"transparent\" etMenuTrigger type=\"button\">\n <i etIcon=\"et-grid-2x2\"></i>\n {{ labels().columns }}\n </button>\n\n <ng-template etMenuSurface>\n <et-menu>\n <!-- Every declared column, hidden ones included: this list is the only way back from hiding one. -->\n @for (column of table().allColumns(); track column.key) {\n <et-menu-checkbox-item\n [value]=\"column.key\"\n [checked]=\"table().isColumnVisible(column.key)\"\n [disabled]=\"isLastVisible(column.key)\"\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n (activate)=\"toggle(column.key)\"\n >\n {{ column.header || column.key }}\n </et-menu-checkbox-item>\n }\n\n <!-- Always rendered, disabled when nothing is hidden: appearing and disappearing would resize the\n menu under the pointer while columns are being toggled. -->\n <et-menu-separator />\n <button\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n [disabled]=\"!hasHidden()\"\n (activate)=\"table().showAllColumns()\"\n et-menu-item\n type=\"button\"\n >\n <i class=\"et-table-column-chooser-icon\" etIcon=\"et-eye\"></i>\n {{ labels().showAllColumns }}\n </button>\n </et-menu>\n </ng-template>\n</div>\n", styles: ["@layer components{et-table-column-chooser{display:contents}.et-table-column-chooser{display:inline-flex;flex:none}.et-table-column-chooser-icon{inline-size:var(--et-menu-item-icon-size, 16px);block-size:var(--et-menu-item-icon-size, 16px)}}\n"] }]
61884
- }], propDecorators: { table: [{ type: i0.Input, args: [{ isSignal: true, alias: "table", required: true }] }] } });
62180
+ ], providers: [provideIcons(GRID_2X2_ICON, EYE_ICON)], template: "<div class=\"et-table-column-chooser\" etMenu>\n <button\n [size]=\"size()\"\n [variant]=\"variant()\"\n class=\"et-table-column-chooser-trigger\"\n et-button\n etMenuTrigger\n type=\"button\"\n >\n <i etIcon=\"et-grid-2x2\"></i>\n {{ labels().columns }}\n </button>\n\n <ng-template etMenuSurface>\n <et-menu>\n <!-- Every declared column, hidden ones included: this list is the only way back from hiding one. -->\n @for (column of table().allColumns(); track column.key) {\n <et-menu-checkbox-item\n [value]=\"column.key\"\n [checked]=\"table().isColumnVisible(column.key)\"\n [disabled]=\"isLastVisible(column.key)\"\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n (activate)=\"toggle(column.key)\"\n >\n {{ column.header || column.key }}\n </et-menu-checkbox-item>\n }\n\n <!-- Always rendered, disabled when nothing is hidden: appearing and disappearing would resize the\n menu under the pointer while columns are being toggled. -->\n <et-menu-separator />\n <button\n [closeOnActivate]=\"KEEP_MENU_OPEN\"\n [disabled]=\"!hasHidden()\"\n (activate)=\"table().showAllColumns()\"\n et-menu-item\n type=\"button\"\n >\n <i class=\"et-table-column-chooser-icon\" etIcon=\"et-eye\"></i>\n {{ labels().showAllColumns }}\n </button>\n </et-menu>\n </ng-template>\n</div>\n", styles: ["@layer components{et-table-column-chooser{display:contents}.et-table-column-chooser{display:inline-flex;flex:none}.et-table-column-chooser-icon{inline-size:var(--et-menu-item-icon-size, 16px);block-size:var(--et-menu-item-icon-size, 16px)}}\n"] }]
62181
+ }], propDecorators: { table: [{ type: i0.Input, args: [{ isSignal: true, alias: "table", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
61885
62182
 
61886
62183
  /**
61887
62184
  * Opt-in per-column menu for `et-table`: a `⋮` in every header cell opening the column's actions -
@@ -62103,13 +62400,157 @@ const injectHostTable$1 = () => {
62103
62400
  */
62104
62401
  class TableDetailStylesComponent {
62105
62402
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableDetailStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
62106
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: TableDetailStylesComponent, isStandalone: true, selector: "et-table-detail-styles", ngImport: i0, template: '', isInline: true, styles: ["@layer components{.et-table-detail-row{grid-column:1 / -1;display:grid;grid-template-rows:1fr;border-block-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-detail-row.et-table-detail--enter{animation:et-table-detail-in .18s ease}.et-table-detail-row.et-table-detail--leave{animation:et-table-detail-out .18s ease forwards}@keyframes et-table-detail-in{0%{grid-template-rows:0fr;opacity:0}to{grid-template-rows:1fr;opacity:1}}@keyframes et-table-detail-out{0%{grid-template-rows:1fr;opacity:1}to{grid-template-rows:0fr;opacity:0}}.et-table-detail-cell{min-block-size:0;overflow:hidden}.et-table-detail-body{padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}@media(prefers-reduced-motion:reduce){.et-table-detail-row.et-table-detail--enter,.et-table-detail-row.et-table-detail--leave{animation:none}}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
62403
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: TableDetailStylesComponent, isStandalone: true, selector: "et-table-detail-styles", ngImport: i0, template: '', isInline: true, styles: ["@layer components{.et-table-detail-row{grid-column:1 / -1;display:grid;grid-template-rows:1fr;border-block-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=cards]) .et-table-detail-row{border-block-end:0}.et-table-row--last+.et-table-detail-row{border-block-end:0}.et-table-detail-row.et-table-detail--enter{animation:et-table-detail-in .18s ease}.et-table-detail-row.et-table-detail--leave{animation:et-table-detail-out .18s ease forwards}@keyframes et-table-detail-in{0%{grid-template-rows:0fr;opacity:0}to{grid-template-rows:1fr;opacity:1}}@keyframes et-table-detail-out{0%{grid-template-rows:1fr;opacity:1}to{grid-template-rows:0fr;opacity:0}}.et-table-detail-cell{min-block-size:0;overflow:hidden}.et-table-detail-body{padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}@media(prefers-reduced-motion:reduce){.et-table-detail-row.et-table-detail--enter,.et-table-detail-row.et-table-detail--leave{animation:none}}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
62107
62404
  }
62108
62405
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableDetailStylesComponent, decorators: [{
62109
62406
  type: Component,
62110
- args: [{ selector: 'et-table-detail-styles', template: '', encapsulation: ViewEncapsulation.None, styles: ["@layer components{.et-table-detail-row{grid-column:1 / -1;display:grid;grid-template-rows:1fr;border-block-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-detail-row.et-table-detail--enter{animation:et-table-detail-in .18s ease}.et-table-detail-row.et-table-detail--leave{animation:et-table-detail-out .18s ease forwards}@keyframes et-table-detail-in{0%{grid-template-rows:0fr;opacity:0}to{grid-template-rows:1fr;opacity:1}}@keyframes et-table-detail-out{0%{grid-template-rows:1fr;opacity:1}to{grid-template-rows:0fr;opacity:0}}.et-table-detail-cell{min-block-size:0;overflow:hidden}.et-table-detail-body{padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}@media(prefers-reduced-motion:reduce){.et-table-detail-row.et-table-detail--enter,.et-table-detail-row.et-table-detail--leave{animation:none}}}\n"] }]
62407
+ args: [{ selector: 'et-table-detail-styles', template: '', encapsulation: ViewEncapsulation.None, styles: ["@layer components{.et-table-detail-row{grid-column:1 / -1;display:grid;grid-template-rows:1fr;border-block-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}.et-table-host:where([data-appearance=cards]) .et-table-detail-row{border-block-end:0}.et-table-row--last+.et-table-detail-row{border-block-end:0}.et-table-detail-row.et-table-detail--enter{animation:et-table-detail-in .18s ease}.et-table-detail-row.et-table-detail--leave{animation:et-table-detail-out .18s ease forwards}@keyframes et-table-detail-in{0%{grid-template-rows:0fr;opacity:0}to{grid-template-rows:1fr;opacity:1}}@keyframes et-table-detail-out{0%{grid-template-rows:1fr;opacity:1}to{grid-template-rows:0fr;opacity:0}}.et-table-detail-cell{min-block-size:0;overflow:hidden}.et-table-detail-body{padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline)}@media(prefers-reduced-motion:reduce){.et-table-detail-row.et-table-detail--enter,.et-table-detail-row.et-table-detail--leave{animation:none}}}\n"] }]
62111
62408
  }] });
62112
62409
 
62410
+ /**
62411
+ * The grab cursors a dragged table scrolls under, as a styles-only component mounted by
62412
+ * `etTableDragScroll` - see `TableDetailStylesComponent` for the same pattern.
62413
+ *
62414
+ * @internal
62415
+ */
62416
+ class TableDragScrollStylesComponent {
62417
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableDragScrollStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
62418
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: TableDragScrollStylesComponent, isStandalone: true, selector: "et-table-drag-scroll-styles", ngImport: i0, template: '', isInline: true, styles: ["@layer components{@media(hover:hover)and (pointer:fine){.et-table-host--drag-scrollable{cursor:grab}.et-table-host--dragging,.et-table-host--dragging *{cursor:grabbing!important;-webkit-user-select:none;user-select:none}}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
62419
+ }
62420
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableDragScrollStylesComponent, decorators: [{
62421
+ type: Component,
62422
+ args: [{ selector: 'et-table-drag-scroll-styles', template: '', encapsulation: ViewEncapsulation.None, styles: ["@layer components{@media(hover:hover)and (pointer:fine){.et-table-host--drag-scrollable{cursor:grab}.et-table-host--dragging,.et-table-host--dragging *{cursor:grabbing!important;-webkit-user-select:none;user-select:none}}}\n"] }]
62423
+ }] });
62424
+
62425
+ /** Whether a press landed in something whose own drag is the point of it: selecting text, not panning. */
62426
+ const isTextGesture = (target) => target instanceof HTMLInputElement ||
62427
+ target instanceof HTMLTextAreaElement ||
62428
+ target instanceof HTMLSelectElement ||
62429
+ // True inside a contenteditable region as well, not only on the element carrying the attribute.
62430
+ (target instanceof HTMLElement && target.isContentEditable);
62431
+ /**
62432
+ * Opt-in drag-to-scroll for `et-table`: pressing anywhere in the table and dragging scrolls it, the way
62433
+ * a map pans. A wide table is otherwise reachable only through the scrollbar or a horizontal wheel,
62434
+ * neither of which a mouse user has close to hand.
62435
+ *
62436
+ * A press that does not travel is still a click, so rows, row links and header controls behave exactly
62437
+ * as they did; a press that becomes a drag swallows the click it would have ended on, so panning off a
62438
+ * row link does not also follow it. Dragging inside a text field is left alone, and a touch pointer
62439
+ * keeps the browser's own scrolling.
62440
+ *
62441
+ * @example
62442
+ * <et-table [data]="rows()" [columns]="COLUMNS" etTableDragScroll />
62443
+ */
62444
+ class TableDragScrollDirective {
62445
+ constructor() {
62446
+ this.table = injectTableFeatureHost('etTableDragScroll');
62447
+ // The feature is a directive on the table, so its host *is* the table's scroll container.
62448
+ this.elementRef = inject(ElementRef);
62449
+ this.destroyRef = inject(DestroyRef);
62450
+ this.injector = inject(Injector);
62451
+ /** See {@link TableDragScrollConfig}. */
62452
+ this.config = input({}, { ...(ngDevMode ? { debugName: "config" } : /* istanbul ignore next */ {}), alias: 'etTableDragScroll',
62453
+ transform: (tableFeatureConfig) });
62454
+ this.hostDimensions = signalHostElementDimensions();
62455
+ /** Whether a drag is in progress, which is what the grabbing cursor reads. */
62456
+ this.dragging = signal(false, /* @ts-ignore */
62457
+ ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
62458
+ /** Whether the table overflows at all - a table that fits takes no grab cursor. */
62459
+ this.scrollable = signal(false, /* @ts-ignore */
62460
+ ...(ngDevMode ? [{ debugName: "scrollable" }] : /* istanbul ignore next */ []));
62461
+ this.enabled = computed(() => this.config().enabled ?? true, /* @ts-ignore */
62462
+ ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
62463
+ injectStyleManager().mount(TableDragScrollStylesComponent);
62464
+ // Whether the table overflows has no signal of its own: recheck whenever the host resizes or the
62465
+ // tracks change, both of which decide it.
62466
+ effect(() => {
62467
+ this.hostDimensions();
62468
+ this.table.columnWidths();
62469
+ this.table.visibleColumnsMeta();
62470
+ afterNextRender({ read: () => this.syncScrollable() }, { injector: this.injector });
62471
+ });
62472
+ }
62473
+ syncScrollable() {
62474
+ const host = this.elementRef.nativeElement;
62475
+ const scrollable = this.enabled() && (host.scrollWidth > host.clientWidth || host.scrollHeight > host.clientHeight);
62476
+ if (scrollable !== this.scrollable())
62477
+ this.scrollable.set(scrollable);
62478
+ }
62479
+ /**
62480
+ * A press that travels over an `<a>` or an image starts the browser's own drag-and-drop, which fires
62481
+ * `pointercancel` and takes the gesture away before it has moved far enough to count as a drag. A
62482
+ * table that pans by dragging has no room for the other kind.
62483
+ */
62484
+ preventNativeDrag(event) {
62485
+ if (this.enabled())
62486
+ event.preventDefault();
62487
+ }
62488
+ startDrag(event) {
62489
+ // Touch already pans by dragging, and a pen or a mouse is the only pointer the scrollbar is awkward
62490
+ // for. A non-primary button belongs to the browser's own menus.
62491
+ if (!this.enabled() || event.pointerType === 'touch' || event.button !== 0)
62492
+ return;
62493
+ if (!this.scrollable() || isTextGesture(event.target))
62494
+ return;
62495
+ const host = this.elementRef.nativeElement;
62496
+ const startLeft = host.scrollLeft;
62497
+ const startTop = host.scrollTop;
62498
+ dragGestureFrom(event, host)
62499
+ .pipe(
62500
+ // Column reorder starts from this same pointerdown and claims the gesture in that handler, so
62501
+ // reading the claim here - once the drag has already travelled - gives the same answer
62502
+ // whichever of the two listeners the browser ran first.
62503
+ takeWhile(() => {
62504
+ const claim = this.table.pointerGestureClaim(event);
62505
+ return claim === null || claim === 'etTableDragScroll';
62506
+ }), tap((gesture) => {
62507
+ if (gesture.type === 'start') {
62508
+ this.dragging.set(true);
62509
+ this.table.claimPointerGesture(event, 'etTableDragScroll');
62510
+ }
62511
+ if (gesture.type === 'move') {
62512
+ host.scrollLeft = startLeft - gesture.data.totalDx;
62513
+ host.scrollTop = startTop - gesture.data.totalDy;
62514
+ }
62515
+ if (gesture.type === 'end' || gesture.type === 'cancelled')
62516
+ this.swallowNextClick();
62517
+ }), finalize(() => this.dragging.set(false)), takeUntilDestroyed(this.destroyRef))
62518
+ .subscribe();
62519
+ }
62520
+ /**
62521
+ * The release ends on a `click` at whatever the pointer landed on. After a drag that click was never
62522
+ * meant - the row under the pointer is not the row the user pressed - so it is eaten in the capture
62523
+ * phase, before a row link or a header control can act on it. Only that one click, and only if it
62524
+ * arrives on this turn of the loop: the next real click has to get through.
62525
+ */
62526
+ swallowNextClick() {
62527
+ if (!this.dragging())
62528
+ return;
62529
+ fromEvent(this.elementRef.nativeElement, 'click', { capture: true })
62530
+ .pipe(takeUntil(timer(0)), take(1), tap((click) => {
62531
+ click.preventDefault();
62532
+ click.stopPropagation();
62533
+ }), takeUntilDestroyed(this.destroyRef))
62534
+ .subscribe();
62535
+ }
62536
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableDragScrollDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
62537
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: TableDragScrollDirective, isStandalone: true, selector: "[etTableDragScroll]", inputs: { config: { classPropertyName: "config", publicName: "etTableDragScroll", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointerdown": "startDrag($event)", "dragstart": "preventNativeDrag($event)", "scroll": "syncScrollable()" }, properties: { "class.et-table-host--drag-scrollable": "scrollable()", "class.et-table-host--dragging": "dragging()" } }, exportAs: ["etTableDragScroll"], ngImport: i0 }); }
62538
+ }
62539
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableDragScrollDirective, decorators: [{
62540
+ type: Directive,
62541
+ args: [{
62542
+ selector: '[etTableDragScroll]',
62543
+ exportAs: 'etTableDragScroll',
62544
+ host: {
62545
+ '[class.et-table-host--drag-scrollable]': 'scrollable()',
62546
+ '[class.et-table-host--dragging]': 'dragging()',
62547
+ '(pointerdown)': 'startDrag($event)',
62548
+ '(dragstart)': 'preventNativeDrag($event)',
62549
+ '(scroll)': 'syncScrollable()',
62550
+ },
62551
+ }]
62552
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "etTableDragScroll", required: false }] }] } });
62553
+
62113
62554
  const clamp = (value, max) => Math.min(Math.max(value, 0), max);
62114
62555
  /**
62115
62556
  * Opt-in arrow-key navigation over an `et-table`'s cells, following the
@@ -62812,12 +63253,13 @@ class TableGroupHeaderRowComponent {
62812
63253
  ...(ngDevMode ? [{ debugName: "blockSize" }] : /* istanbul ignore next */ []));
62813
63254
  this.leads = computed(() => this.table.leadColumnsMeta(), /* @ts-ignore */
62814
63255
  ...(ngDevMode ? [{ debugName: "leads" }] : /* istanbul ignore next */ []));
63256
+ this.trails = computed(() => this.table.trailColumnsMeta(), /* @ts-ignore */
63257
+ ...(ngDevMode ? [{ debugName: "trails" }] : /* istanbul ignore next */ []));
62815
63258
  this.feature.rowHeight.set(this.blockSize);
62816
63259
  }
62817
63260
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableGroupHeaderRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
62818
63261
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TableGroupHeaderRowComponent, isStandalone: true, selector: "et-table-group-header-row", host: { attributes: { "role": "row" }, classAttribute: "et-table-group-row" }, viewQueries: [{ propertyName: "groupCells", predicate: ["groupCell"], descendants: true, isSignal: true }], ngImport: i0, template: `
62819
- <!-- One empty cell per leading utility column (selection, expander), so the band covers their
62820
- tracks too. -->
63262
+ <!-- One empty cell per utility column (selection, expander), so the band covers their tracks too. -->
62821
63263
  @for (lead of leads(); track $index) {
62822
63264
  <div class="et-table-group-cell" aria-hidden="true"></div>
62823
63265
  }
@@ -62838,13 +63280,15 @@ class TableGroupHeaderRowComponent {
62838
63280
  @if (table.hasFillerTrack()) {
62839
63281
  <div class="et-table-group-cell et-table-filler-cell" role="presentation" aria-hidden="true"></div>
62840
63282
  }
63283
+ @for (trail of trails(); track $index) {
63284
+ <div class="et-table-group-cell" aria-hidden="true"></div>
63285
+ }
62841
63286
  `, isInline: true, styles: ["@layer components{.et-table-group-row{display:contents}.et-table-group-cell{display:flex;align-items:center;min-inline-size:0;overflow:hidden;padding:6px var(--et-table-cell-padding-inline);position:sticky;inset-block-start:0;z-index:2;background:var(--_et-table-header-bg);border-block-end:1px solid var(--_et-table-header-border)}.et-table-group-cell:where(.et-table-group-cell--labeled){justify-content:center;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--et-surface-color-muted-solid, CanvasText)}.et-table-host:where([data-appearance=grid]) .et-table-group-cell:where(.et-table-group-cell--labeled){border-inline-end:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .15))}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
62842
63287
  }
62843
63288
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableGroupHeaderRowComponent, decorators: [{
62844
63289
  type: Component,
62845
63290
  args: [{ selector: 'et-table-group-header-row', template: `
62846
- <!-- One empty cell per leading utility column (selection, expander), so the band covers their
62847
- tracks too. -->
63291
+ <!-- One empty cell per utility column (selection, expander), so the band covers their tracks too. -->
62848
63292
  @for (lead of leads(); track $index) {
62849
63293
  <div class="et-table-group-cell" aria-hidden="true"></div>
62850
63294
  }
@@ -62865,6 +63309,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
62865
63309
  @if (table.hasFillerTrack()) {
62866
63310
  <div class="et-table-group-cell et-table-filler-cell" role="presentation" aria-hidden="true"></div>
62867
63311
  }
63312
+ @for (trail of trails(); track $index) {
63313
+ <div class="et-table-group-cell" aria-hidden="true"></div>
63314
+ }
62868
63315
  `, encapsulation: ViewEncapsulation.None, host: {
62869
63316
  class: 'et-table-group-row',
62870
63317
  role: 'row',
@@ -63180,10 +63627,128 @@ const injectHostTable = () => {
63180
63627
  return table;
63181
63628
  };
63182
63629
 
63630
+ /**
63631
+ * The travelling header row, as a styles-only component mounted by `etTablePageStickyHeader` - see
63632
+ * `TableDragScrollStylesComponent` for the same pattern.
63633
+ *
63634
+ * @internal
63635
+ */
63636
+ class TablePageStickyHeaderStylesComponent {
63637
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TablePageStickyHeaderStylesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
63638
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: TablePageStickyHeaderStylesComponent, isStandalone: true, selector: "et-table-page-sticky-header-styles", ngImport: i0, template: '', isInline: true, styles: ["@layer components{@property --et-table-sticky-header-offset{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --_et-table-page-header-travel{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --_et-table-page-header-from{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --_et-table-page-header-to{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@keyframes et-table-page-header-travel{to{transform:translateY(var(--_et-table-page-header-travel))}}@supports (animation-timeline: scroll()){.et-table-host--page-sticky-header .et-table-header-cell{z-index:4;animation:et-table-page-header-travel linear both;animation-timeline:scroll(root block);animation-range:var(--_et-table-page-header-from) var(--_et-table-page-header-to)}.et-table-host--page-sticky-header .et-table-header-cell:where(.et-table-sticky-start,.et-table-sticky-end){z-index:6}}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
63639
+ }
63640
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TablePageStickyHeaderStylesComponent, decorators: [{
63641
+ type: Component,
63642
+ args: [{ selector: 'et-table-page-sticky-header-styles', template: '', encapsulation: ViewEncapsulation.None, styles: ["@layer components{@property --et-table-sticky-header-offset{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --_et-table-page-header-travel{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --_et-table-page-header-from{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@property --_et-table-page-header-to{syntax: \"<length>\"; inherits: true; initial-value: 0px;}@keyframes et-table-page-header-travel{to{transform:translateY(var(--_et-table-page-header-travel))}}@supports (animation-timeline: scroll()){.et-table-host--page-sticky-header .et-table-header-cell{z-index:4;animation:et-table-page-header-travel linear both;animation-timeline:scroll(root block);animation-range:var(--_et-table-page-header-from) var(--_et-table-page-header-to)}.et-table-host--page-sticky-header .et-table-header-cell:where(.et-table-sticky-start,.et-table-sticky-end){z-index:6}}}\n"] }]
63643
+ }] });
63644
+
63645
+ /**
63646
+ * Keeps the header row of a page-scrolled `et-table` at the top of the viewport. Use it on a table that
63647
+ * has no height of its own - one that grows to its rows while the document scrolls - where the header
63648
+ * would otherwise leave with the page.
63649
+ *
63650
+ * The table's own sticky header pins to the host, which is the table's horizontal scroll container, so
63651
+ * it can only ever stop at the host's top edge. This travels the header row down the grid instead, by
63652
+ * exactly the distance the page has scrolled past the table, and stops it at the last row. The row keeps
63653
+ * its place in the grid throughout, so the tracks, the pinned columns and the resize grips are untouched
63654
+ * and the header still scrolls sideways with the columns.
63655
+ *
63656
+ * The travel runs on a scroll timeline, so it is the compositor's work and the header never falls behind
63657
+ * the page. This directive only measures: it writes the distance and the two page offsets it runs
63658
+ * between whenever the layout changes, and nothing at all while scrolling.
63659
+ *
63660
+ * Set `--et-table-sticky-header-offset` on the table to stop the header lower than the top of the
63661
+ * viewport - under a page header or a toolbar that is pinned there itself.
63662
+ *
63663
+ * Not for a bounded table: one with a height of its own already pins its header, and one that virtual
63664
+ * scrolls needs the bounded height to do it.
63665
+ *
63666
+ * @example
63667
+ * <et-table [data]="rows()" [columns]="COLUMNS" style="--et-table-sticky-header-offset: 64px" etTablePageStickyHeader />
63668
+ */
63669
+ class TablePageStickyHeaderDirective {
63670
+ constructor() {
63671
+ this.table = injectTableFeatureHost('etTablePageStickyHeader');
63672
+ // The feature is a directive on the table, so its host *is* the table's scroll container.
63673
+ this.elementRef = inject(ElementRef);
63674
+ this.injector = inject(Injector);
63675
+ this.renderer = injectRenderer();
63676
+ // The offset is a length, so a media query can change it at a width the table itself does not resize at.
63677
+ this.viewportSize = injectViewportSize();
63678
+ /** See {@link TablePageStickyHeaderConfig}. */
63679
+ this.config = input({}, { ...(ngDevMode ? { debugName: "config" } : /* istanbul ignore next */ {}), alias: 'etTablePageStickyHeader',
63680
+ transform: (tableFeatureConfig) });
63681
+ this.hostDimensions = signalHostElementDimensions();
63682
+ this.enabled = computed(() => this.config().enabled ?? true, /* @ts-ignore */
63683
+ ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
63684
+ injectStyleManager().mount(TablePageStickyHeaderStylesComponent);
63685
+ // Everything the travel is made of comes out of the layout, so it is re-measured whenever the layout
63686
+ // can have changed: the host resized, a column was resized, columns came or went, the config was
63687
+ // rebound. Never on scroll - scrolling is the timeline's job, and reading geometry there is what
63688
+ // makes a pinned header lag behind the page.
63689
+ effect(() => {
63690
+ this.hostDimensions();
63691
+ this.viewportSize();
63692
+ this.enabled();
63693
+ this.config();
63694
+ this.table.columnWidths();
63695
+ this.table.visibleColumnsMeta();
63696
+ afterNextRender({ read: () => this.measure() }, { injector: this.injector });
63697
+ });
63698
+ }
63699
+ measure() {
63700
+ const host = this.elementRef.nativeElement;
63701
+ const grid = this.table.gridElement();
63702
+ const headerCell = this.table.headerCellElements()[0] ?? this.table.leadHeaderCellElements()[0];
63703
+ const view = host.ownerDocument.defaultView;
63704
+ if (!this.enabled() || !grid || !headerCell || !view) {
63705
+ this.write(host, { travel: 0, from: 0, to: 0 });
63706
+ return;
63707
+ }
63708
+ // Layout offsets, not the header's own rect: the rect carries the travel the timeline has already
63709
+ // applied, and reading it back would fold that into the next measurement.
63710
+ const headerTop = headerCell.offsetTop;
63711
+ const travel = Math.max(0, grid.offsetHeight - headerTop - headerCell.offsetHeight);
63712
+ // Where the header rests, in page coordinates, so the two ends of the range are page scroll offsets.
63713
+ const restingTop = grid.getBoundingClientRect().top + view.scrollY + headerTop;
63714
+ const from = Math.max(0, restingTop - this.resolveOffset(host));
63715
+ this.write(host, { travel, from, to: from + travel });
63716
+ }
63717
+ resolveOffset(host) {
63718
+ const raw = getComputedStyle(host).getPropertyValue('--et-table-sticky-header-offset');
63719
+ const parsed = Number.parseFloat(raw);
63720
+ // Registered as a `<length>` (see the stylesheet), so the computed value is always in px.
63721
+ return this.config().offset ?? (Number.isFinite(parsed) ? parsed : 0);
63722
+ }
63723
+ write(host, values) {
63724
+ this.renderer?.setCssProperties(host, {
63725
+ '--_et-table-page-header-travel': `${values.travel}px`,
63726
+ '--_et-table-page-header-from': `${values.from}px`,
63727
+ '--_et-table-page-header-to': `${values.to}px`,
63728
+ });
63729
+ }
63730
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TablePageStickyHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
63731
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: TablePageStickyHeaderDirective, isStandalone: true, selector: "[etTablePageStickyHeader]", inputs: { config: { classPropertyName: "config", publicName: "etTablePageStickyHeader", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.et-table-host--page-sticky-header": "enabled()" } }, exportAs: ["etTablePageStickyHeader"], ngImport: i0 }); }
63732
+ }
63733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TablePageStickyHeaderDirective, decorators: [{
63734
+ type: Directive,
63735
+ args: [{
63736
+ selector: '[etTablePageStickyHeader]',
63737
+ exportAs: 'etTablePageStickyHeader',
63738
+ host: {
63739
+ '[class.et-table-host--page-sticky-header]': 'enabled()',
63740
+ },
63741
+ }]
63742
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "etTablePageStickyHeader", required: false }] }] } });
63743
+
63183
63744
  /** How long a column takes to slide between preview positions. */
63184
63745
  const PREVIEW_DURATION_MS = 160;
63185
63746
  /** Dead zone (px) each side of a column's midpoint - see {@link TableReorderDirective.flipThresholdOf}. */
63186
63747
  const FLIP_HYSTERESIS_PX = 12;
63748
+ /** How near an inline edge a drag has to be held before the table scrolls itself under it. */
63749
+ const AUTO_SCROLL_ZONE_PX = 56;
63750
+ /** Fastest the edge auto-scroll runs, in px per frame - reached with the pointer on the edge itself. */
63751
+ const AUTO_SCROLL_MAX_STEP_PX = 18;
63187
63752
  /** The column order that dropping `key` next to `overKey` (on the given side) would produce. */
63188
63753
  const landingOrder = (order, move) => {
63189
63754
  const without = order.filter((candidate) => candidate !== move.key);
@@ -63242,6 +63807,11 @@ class TableReorderDirective {
63242
63807
  this.previewOffsets = new Map();
63243
63808
  // The last previewed landing order, to skip re-applying identical transforms on every pointer move.
63244
63809
  this.previewSignature = null;
63810
+ // The pointer's last x, which the edge auto-scroll re-resolves the drop target against: it moves the
63811
+ // columns while the pointer stands still, so no pointer event says the target changed.
63812
+ this.pointerX = 0;
63813
+ this.autoScrollFrame = null;
63814
+ this.autoScrollStep = 0;
63245
63815
  this.table.registerLayer({
63246
63816
  component: TableReorderOverlayComponent,
63247
63817
  injector: this.injector,
@@ -63261,6 +63831,10 @@ class TableReorderDirective {
63261
63831
  const hit = this.headerCellAt(event);
63262
63832
  if (!hit)
63263
63833
  return EMPTY;
63834
+ // Claimed here, in the pointerdown itself, so drag-to-scroll reads the claim whichever of
63835
+ // the two listeners the browser ran first. Without it a header drag reorders the column and
63836
+ // pans the table out from under it at the same time.
63837
+ this.table.claimPointerGesture(event, 'etTableReorder');
63264
63838
  return dragGestureFrom(event, hit.cell).pipe(tap((gesture) => {
63265
63839
  if (gesture.type === 'start')
63266
63840
  this.start(hit.key, gesture.data);
@@ -63295,6 +63869,7 @@ class TableReorderDirective {
63295
63869
  const header = this.table.visibleColumnsMeta().find((column) => column.key === key)?.header ?? key;
63296
63870
  this.dragging.set({ key, header });
63297
63871
  this.pointer.set({ x: at.clientX, y: at.clientY });
63872
+ this.pointerX = at.clientX;
63298
63873
  this.target.set(null);
63299
63874
  this.previewSignature = null;
63300
63875
  this.markDragging(key, true);
@@ -63303,8 +63878,10 @@ class TableReorderDirective {
63303
63878
  if (!this.dragging())
63304
63879
  return;
63305
63880
  this.pointer.set({ x: at.clientX, y: at.clientY });
63881
+ this.pointerX = at.clientX;
63306
63882
  this.resolveDropTarget(at.clientX);
63307
63883
  this.previewLandingOrder();
63884
+ this.syncAutoScroll(at.clientX);
63308
63885
  }
63309
63886
  /** The browser took the gesture away, so there is no drop the user chose - slide back and clean up. */
63310
63887
  cancel() {
@@ -63315,6 +63892,7 @@ class TableReorderDirective {
63315
63892
  end() {
63316
63893
  const dragging = this.dragging();
63317
63894
  const target = this.target();
63895
+ this.stopAutoScroll();
63318
63896
  if (dragging)
63319
63897
  this.markDragging(dragging.key, false);
63320
63898
  const moved = dragging && target && target.key !== dragging.key;
@@ -63334,6 +63912,52 @@ class TableReorderDirective {
63334
63912
  // frame. Cleared in the write phase of that render, which is before it paints.
63335
63913
  afterNextRender({ write: () => this.clearPreview({ animated: false }) }, { injector: this.injector });
63336
63914
  }
63915
+ /**
63916
+ * Scroll the table while the drag is held near an inline edge, so a column can be dropped past the
63917
+ * visible range. A reorder is otherwise limited to what fits the viewport: the pointer is already
63918
+ * down, so neither the wheel nor a drag-to-scroll pan is available to bring the target column in.
63919
+ *
63920
+ * The step grows with how far into the zone the pointer is, so the edge itself runs fastest and a
63921
+ * pointer that only grazes the zone barely moves the table.
63922
+ *
63923
+ * Measured from the inner edge of each pinned block, not from the table's own edges: a pinned column
63924
+ * covers that strip of the viewport, so a zone laid on the viewport edge sits underneath it and the
63925
+ * drag has to travel all the way past the pinned column before the table moves at all.
63926
+ */
63927
+ syncAutoScroll(clientX) {
63928
+ const bounds = this.table.element.getBoundingClientRect();
63929
+ const frozen = this.table.frozenInsets();
63930
+ const intoStart = AUTO_SCROLL_ZONE_PX - (clientX - (bounds.left + frozen.start));
63931
+ const intoEnd = AUTO_SCROLL_ZONE_PX - (bounds.right - frozen.end - clientX);
63932
+ const depth = intoStart > 0 ? -intoStart : intoEnd > 0 ? intoEnd : 0;
63933
+ const ratio = Math.min(Math.abs(depth), AUTO_SCROLL_ZONE_PX) / AUTO_SCROLL_ZONE_PX;
63934
+ this.autoScrollStep = Math.sign(depth) * ratio * AUTO_SCROLL_MAX_STEP_PX;
63935
+ if (this.autoScrollStep === 0) {
63936
+ this.stopAutoScroll();
63937
+ return;
63938
+ }
63939
+ if (this.autoScrollFrame === null)
63940
+ this.stepAutoScroll();
63941
+ }
63942
+ stepAutoScroll() {
63943
+ const host = this.table.element;
63944
+ const before = host.scrollLeft;
63945
+ host.scrollLeft = before + this.autoScrollStep;
63946
+ // The table is already at that end, so stop rather than run a frame per tick doing nothing.
63947
+ if (host.scrollLeft === before) {
63948
+ this.stopAutoScroll();
63949
+ return;
63950
+ }
63951
+ this.resolveDropTarget(this.pointerX);
63952
+ this.previewLandingOrder();
63953
+ this.autoScrollFrame = requestAnimationFrame(() => this.stepAutoScroll());
63954
+ }
63955
+ stopAutoScroll() {
63956
+ if (this.autoScrollFrame !== null)
63957
+ cancelAnimationFrame(this.autoScrollFrame);
63958
+ this.autoScrollFrame = null;
63959
+ this.autoScrollStep = 0;
63960
+ }
63337
63961
  /**
63338
63962
  * Resolve which column the pointer is over and which side it would drop on.
63339
63963
  *
@@ -63528,6 +64152,69 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
63528
64152
  `, encapsulation: ViewEncapsulation.None, styles: ["@layer components{.et-table-host--reorderable .et-table-header-cell:not(.et-table-sticky-start,.et-table-sticky-end,.et-table-select-cell,.et-table-expander-cell){cursor:grab;-webkit-user-select:none;user-select:none}.et-table-header-cell:where(.et-table-header-cell--dragging){cursor:grabbing;opacity:.4}.et-table-drag-ghost{position:fixed;z-index:10;transform:translate(12px,8px);max-inline-size:256px;padding:var(--et-table-cell-padding-block) var(--et-table-cell-padding-inline);overflow:hidden;font-size:14px;font-weight:600;white-space:nowrap;text-overflow:ellipsis;color:var(--et-surface-color-solid, CanvasText);background:var(--et-surface-background-solid, Canvas);border:1px solid var(--et-surface-border-solid, rgb(128 128 128 / .3));border-radius:6px;box-shadow:0 8px 24px #0000002e;pointer-events:none}}\n"] }]
63529
64153
  }] });
63530
64154
 
64155
+ /**
64156
+ * Whether the browser, not the router, should handle a click: a middle or right button, or any modifier
64157
+ * the user presses to open a link somewhere else. Exactly what `RouterLink` leaves alone, and the reason
64158
+ * the table renders a real `href` at all.
64159
+ */
64160
+ const opensElsewhere = (event) => event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey;
64161
+ /**
64162
+ * Opt-in Angular routing for an `et-table`'s [row links](/components/table#row-links): with it, a
64163
+ * `[rowLink]` may answer with router commands (`['/orders', order.id]`) instead of an `href` string, and
64164
+ * a plain click navigates through the router rather than loading the page again.
64165
+ *
64166
+ * The commands are resolved relative to the route the table sits on, the way `routerLink` resolves its
64167
+ * own. Modified clicks - middle button, Ctrl/Cmd/Shift - are left to the browser, which is what keeps
64168
+ * "open in a new tab" working on the same rows.
64169
+ *
64170
+ * It is a feature rather than part of the table because the base table depends on no router: a table that
64171
+ * links with plain `href` strings - or not at all - never pulls `@angular/router` into its bundle.
64172
+ *
64173
+ * @example
64174
+ * <et-table [data]="orders()" [columns]="COLUMNS" [rowLink]="orderLink" etTableRowRouterLink />
64175
+ *
64176
+ * protected orderLink = (order: Order) => ['/orders', order.id];
64177
+ */
64178
+ class TableRowRouterLinkDirective {
64179
+ constructor() {
64180
+ this.table = injectTableFeatureHost('etTableRowRouterLink');
64181
+ this.router = inject(Router);
64182
+ // eslint-disable-next-line ethlete/no-angular-router-api
64183
+ this.route = inject(ActivatedRoute, { optional: true });
64184
+ /** See {@link TableRowRouterLinkConfig}. */
64185
+ this.config = input({}, { ...(ngDevMode ? { debugName: "config" } : /* istanbul ignore next */ {}), alias: 'etTableRowRouterLink',
64186
+ transform: (tableFeatureConfig) });
64187
+ this.table.registerRowNavigation({
64188
+ href: (commands) => this.href(commands),
64189
+ navigate: (commands, event) => this.navigate(commands, event),
64190
+ enabled: computed(() => this.config().enabled ?? true),
64191
+ });
64192
+ }
64193
+ /** The URL these commands resolve to - what the row's anchor carries as its `href`. */
64194
+ href(commands) {
64195
+ return this.router.serializeUrl(this.urlTree(commands));
64196
+ }
64197
+ /** Navigate to these commands, unless the click asked for the browser's own behaviour. */
64198
+ navigate(commands, event) {
64199
+ if (opensElsewhere(event))
64200
+ return false;
64201
+ this.router.navigateByUrl(this.urlTree(commands));
64202
+ return true;
64203
+ }
64204
+ urlTree(commands) {
64205
+ return this.router.createUrlTree([...commands], { relativeTo: this.route });
64206
+ }
64207
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableRowRouterLinkDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
64208
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: TableRowRouterLinkDirective, isStandalone: true, selector: "[etTableRowRouterLink]", inputs: { config: { classPropertyName: "config", publicName: "etTableRowRouterLink", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["etTableRowRouterLink"], ngImport: i0 }); }
64209
+ }
64210
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableRowRouterLinkDirective, decorators: [{
64211
+ type: Directive,
64212
+ args: [{
64213
+ selector: '[etTableRowRouterLink]',
64214
+ exportAs: 'etTableRowRouterLink',
64215
+ }]
64216
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "etTableRowRouterLink", required: false }] }] } });
64217
+
63531
64218
  /**
63532
64219
  * Opt-in column resizing for `et-table`: adds a grip to every header cell's trailing edge that drags
63533
64220
  * the column's width, with a double-click to reset it.
@@ -63621,7 +64308,7 @@ class TableResizeGripComponent {
63621
64308
  etDragHandle
63622
64309
  aria-hidden="true"
63623
64310
  ></span>
63624
- `, isInline: true, styles: ["@layer components{et-table-resize-grip{display:contents}.et-table-resize-grip{position:absolute;inset-block:0;inset-inline-end:0;inline-size:9px;z-index:1;cursor:col-resize}.et-table-resize-grip:after{content:\"\";position:absolute;inset-block:20%;inset-inline-end:3px;inline-size:2px;border-radius:1px;background:var(--et-surface-border-solid, rgb(128 128 128 / .4));transition:background .12s ease}@media(hover:hover){.et-table-resize-grip:where(:hover):after{inset-block:0;background:var(--et-theme-color-primary-solid, currentColor)}}@media(pointer:coarse){.et-table-resize-grip{inline-size:28px}.et-table-resize-grip:after{inset-block:15%;inline-size:3px}}}\n"], dependencies: [{ kind: "directive", type: DragHandleDirective, selector: "[etDragHandle]", inputs: ["commitThreshold", "disabled"], outputs: ["dragTapped", "dragStarted", "dragMoved", "dragEnded", "dragCancelled"] }], encapsulation: i0.ViewEncapsulation.None }); }
64311
+ `, isInline: true, styles: ["@layer components{et-table-resize-grip{display:contents}.et-table-resize-grip{position:absolute;inset-block:0;inset-inline-end:0;inline-size:9px;z-index:1;cursor:col-resize}.et-table-resize-grip:after{content:\"\";position:absolute;inset-block:20%;inset-inline-end:0;inline-size:1px;background:var(--et-surface-border-solid, rgb(128 128 128 / .4));transition:background .12s ease}@media(hover:hover){.et-table-resize-grip:where(:hover):after{inset-block:0;inline-size:2px;background:var(--et-theme-color-primary-solid, currentColor)}}@media(pointer:coarse){.et-table-resize-grip{inline-size:28px}.et-table-resize-grip:after{inset-block:15%;inline-size:2px}}}\n"], dependencies: [{ kind: "directive", type: DragHandleDirective, selector: "[etDragHandle]", inputs: ["commitThreshold", "disabled"], outputs: ["dragTapped", "dragStarted", "dragMoved", "dragEnded", "dragCancelled"] }], encapsulation: i0.ViewEncapsulation.None }); }
63625
64312
  }
63626
64313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableResizeGripComponent, decorators: [{
63627
64314
  type: Component,
@@ -63636,7 +64323,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
63636
64323
  etDragHandle
63637
64324
  aria-hidden="true"
63638
64325
  ></span>
63639
- `, encapsulation: ViewEncapsulation.None, imports: [DragHandleDirective], styles: ["@layer components{et-table-resize-grip{display:contents}.et-table-resize-grip{position:absolute;inset-block:0;inset-inline-end:0;inline-size:9px;z-index:1;cursor:col-resize}.et-table-resize-grip:after{content:\"\";position:absolute;inset-block:20%;inset-inline-end:3px;inline-size:2px;border-radius:1px;background:var(--et-surface-border-solid, rgb(128 128 128 / .4));transition:background .12s ease}@media(hover:hover){.et-table-resize-grip:where(:hover):after{inset-block:0;background:var(--et-theme-color-primary-solid, currentColor)}}@media(pointer:coarse){.et-table-resize-grip{inline-size:28px}.et-table-resize-grip:after{inset-block:15%;inline-size:3px}}}\n"] }]
64326
+ `, encapsulation: ViewEncapsulation.None, imports: [DragHandleDirective], styles: ["@layer components{et-table-resize-grip{display:contents}.et-table-resize-grip{position:absolute;inset-block:0;inset-inline-end:0;inline-size:9px;z-index:1;cursor:col-resize}.et-table-resize-grip:after{content:\"\";position:absolute;inset-block:20%;inset-inline-end:0;inline-size:1px;background:var(--et-surface-border-solid, rgb(128 128 128 / .4));transition:background .12s ease}@media(hover:hover){.et-table-resize-grip:where(:hover):after{inset-block:0;inline-size:2px;background:var(--et-theme-color-primary-solid, currentColor)}}@media(pointer:coarse){.et-table-resize-grip{inline-size:28px}.et-table-resize-grip:after{inset-block:15%;inline-size:2px}}}\n"] }]
63640
64327
  }], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }] } });
63641
64328
 
63642
64329
  /**
@@ -63699,6 +64386,7 @@ class TableSelectionDirective {
63699
64386
  this.table.registerLeadColumn({
63700
64387
  key: 'et-table-selection',
63701
64388
  width: 'var(--et-table-select-width, 44px)',
64389
+ side: computed(() => this.config().side ?? 'start'),
63702
64390
  // leftmost: before the expander (order 100) and any other feature column
63703
64391
  order: 0,
63704
64392
  cellClass: 'et-table-select-cell',
@@ -63793,7 +64481,7 @@ class TableSelectAllCellComponent {
63793
64481
  [attr.aria-label]="selection.selectAllLabel()"
63794
64482
  (checkedChange)="selection.toggleAll()"
63795
64483
  />
63796
- `, isInline: true, styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--et-surface-background-solid, Canvas))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--et-surface-background-solid, Canvas))}}}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "et-checkbox" }], encapsulation: i0.ViewEncapsulation.None }); }
64484
+ `, isInline: true, styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-select-cell et-checkbox{--_et-focus-ring-offset: -2px}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}}}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "et-checkbox" }], encapsulation: i0.ViewEncapsulation.None }); }
63797
64485
  }
63798
64486
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableSelectAllCellComponent, decorators: [{
63799
64487
  type: Component,
@@ -63804,7 +64492,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
63804
64492
  [attr.aria-label]="selection.selectAllLabel()"
63805
64493
  (checkedChange)="selection.toggleAll()"
63806
64494
  />
63807
- `, encapsulation: ViewEncapsulation.None, imports: [CheckboxComponent], styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--et-surface-background-solid, Canvas))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--et-surface-background-solid, Canvas))}}}\n"] }]
64495
+ `, encapsulation: ViewEncapsulation.None, imports: [CheckboxComponent], styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-select-cell et-checkbox{--_et-focus-ring-offset: -2px}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}}}\n"] }]
63808
64496
  }] });
63809
64497
  /**
63810
64498
  * One row's selection checkbox, stamped into the selection column by `etTableSelection`. This is
@@ -63828,7 +64516,7 @@ class TableSelectCellComponent {
63828
64516
  (checkedChange)="selection.setSelected(row(), $event)"
63829
64517
  />
63830
64518
  }
63831
- `, isInline: true, styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--et-surface-background-solid, Canvas))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--et-surface-background-solid, Canvas))}}}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "et-checkbox" }], encapsulation: i0.ViewEncapsulation.None }); }
64519
+ `, isInline: true, styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-select-cell et-checkbox{--_et-focus-ring-offset: -2px}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}}}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "et-checkbox" }], encapsulation: i0.ViewEncapsulation.None }); }
63832
64520
  }
63833
64521
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableSelectCellComponent, decorators: [{
63834
64522
  type: Component,
@@ -63840,7 +64528,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
63840
64528
  (checkedChange)="selection.setSelected(row(), $event)"
63841
64529
  />
63842
64530
  }
63843
- `, encapsulation: ViewEncapsulation.None, imports: [CheckboxComponent], styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--et-surface-background-solid, Canvas))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--et-surface-background-solid, Canvas))}}}\n"] }]
64531
+ `, encapsulation: ViewEncapsulation.None, imports: [CheckboxComponent], styles: ["@layer components{et-table-select-cell,et-table-select-all-cell{display:contents}.et-table-select-cell{justify-content:center;padding:0 4px;--et-checkbox-size: 16px}.et-table-select-cell et-checkbox{flex:1;justify-content:center;align-self:stretch}.et-table-select-cell et-checkbox{--_et-focus-ring-offset: -2px}.et-table-row--selected .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,transparent)}.et-table-row--selected .et-table-cell.et-table-sticky-start,.et-table-row--selected .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 12%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}@media(hover:hover){.et-table-row--selected:hover .et-table-cell{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,transparent)}.et-table-row--selected:hover .et-table-cell.et-table-sticky-start,.et-table-row--selected:hover .et-table-cell.et-table-sticky-end{background:color-mix(in srgb,var(--et-theme-color-primary-solid, gray) 18%,var(--_et-table-row-surface, var(--et-surface-background-solid, Canvas)))}}}\n"] }]
63844
64532
  }], propDecorators: { row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }] } });
63845
64533
 
63846
64534
  /**
@@ -63878,6 +64566,8 @@ class TableStickyColumnsDirective {
63878
64566
  ...(ngDevMode ? [{ debugName: "offsets" }] : /* istanbul ignore next */ []));
63879
64567
  this.leadOffsets = signal({}, /* @ts-ignore */
63880
64568
  ...(ngDevMode ? [{ debugName: "leadOffsets" }] : /* istanbul ignore next */ []));
64569
+ this.trailOffsets = signal({}, /* @ts-ignore */
64570
+ ...(ngDevMode ? [{ debugName: "trailOffsets" }] : /* istanbul ignore next */ []));
63881
64571
  /**
63882
64572
  * True when pinning is measured to crowd the non-pinned columns off-screen. Pinning is then dropped so
63883
64573
  * every column scrolls normally instead of hiding behind the pins - which is what makes the same table
@@ -63887,17 +64577,19 @@ class TableStickyColumnsDirective {
63887
64577
  ...(ngDevMode ? [{ debugName: "suppressed" }] : /* istanbul ignore next */ []));
63888
64578
  this.insets = signal({ start: 0, end: 0 }, /* @ts-ignore */
63889
64579
  ...(ngDevMode ? [{ debugName: "insets" }] : /* istanbul ignore next */ []));
64580
+ this.enabled = computed(() => this.config().enabled ?? true, /* @ts-ignore */
64581
+ ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
63890
64582
  /** Whether any visible column is pinned to the inline-start edge (which also pins the lead columns). */
63891
64583
  this.hasStickyStart = computed(() => !this.suppressed() && this.table.visibleColumnsMeta().some((column) => column.sticky === 'start'), /* @ts-ignore */
63892
64584
  ...(ngDevMode ? [{ debugName: "hasStickyStart" }] : /* istanbul ignore next */ []));
63893
64585
  /** Whether any visible column is pinned to the trailing edge. */
63894
64586
  this.hasStickyEnd = computed(() => !this.suppressed() && this.table.visibleColumnsMeta().some((column) => column.sticky === 'end'), /* @ts-ignore */
63895
64587
  ...(ngDevMode ? [{ debugName: "hasStickyEnd" }] : /* istanbul ignore next */ []));
63896
- const enabled = computed(() => this.config().enabled ?? true, /* @ts-ignore */
63897
- ...(ngDevMode ? [{ debugName: "enabled" }] : /* istanbul ignore next */ []));
64588
+ const enabled = this.enabled;
63898
64589
  this.table.registerColumnPinning({
63899
64590
  cellPinning: (key) => this.cellPinning(key),
63900
64591
  leadPinning: (key) => this.leadPinning(key),
64592
+ trailPinning: (key) => this.trailPinning(key),
63901
64593
  insets: () => this.insets(),
63902
64594
  hasStickyEnd: () => this.hasStickyEnd(),
63903
64595
  enabled,
@@ -63927,6 +64619,21 @@ class TableStickyColumnsDirective {
63927
64619
  // eslint-disable-next-line ethlete/prefer-element-dimensions
63928
64620
  leadWidth += leadCells[index]?.getBoundingClientRect().width ?? 0;
63929
64621
  });
64622
+ // The trailing utility columns stack from the trailing edge, so they are summed in reverse: the
64623
+ // last one sits at the edge and each one before it clears the ones after it.
64624
+ const trailCells = this.table.trailHeaderCellElements();
64625
+ const trailMeta = this.table.trailColumnsMeta();
64626
+ const trailOffsets = {};
64627
+ let trailWidth = 0;
64628
+ for (let index = trailMeta.length - 1; index >= 0; index--) {
64629
+ const trail = trailMeta[index];
64630
+ if (!trail)
64631
+ continue;
64632
+ trailOffsets[trail.key] = trailWidth;
64633
+ // Same as above: a running sum over all trailing cells, not one observable element.
64634
+ // eslint-disable-next-line ethlete/prefer-element-dimensions
64635
+ trailWidth += trailCells[index]?.getBoundingClientRect().width ?? 0;
64636
+ }
63930
64637
  const start = {};
63931
64638
  let left = leadWidth;
63932
64639
  let pinnedStartWidth = 0;
@@ -63942,7 +64649,9 @@ class TableStickyColumnsDirective {
63942
64649
  left += width(index);
63943
64650
  }
63944
64651
  const end = {};
63945
- let right = 0;
64652
+ // The trailing utility columns own that edge, so an end-pinned data column stacks after them -
64653
+ // the mirror of `left` starting at the leading utility columns' width.
64654
+ let right = trailWidth;
63946
64655
  for (let index = columns.length - 1; index >= 0; index--) {
63947
64656
  const column = columns[index];
63948
64657
  if (column?.sticky === 'end') {
@@ -63955,15 +64664,17 @@ class TableStickyColumnsDirective {
63955
64664
  // start pin makes them sticky too) leave the scrollable ones too little room to ever surface. Track
63956
64665
  // widths don't change when we unpin, so this can't oscillate.
63957
64666
  const containerWidth = this.hostDimensions()?.client?.width ?? 0;
63958
- const pinnedWidth = pinnedStartWidth + pinnedEndWidth + (hasStartPin ? leadWidth : 0);
64667
+ // A trailing utility column is pinned whenever pinning is live, so its width always counts here.
64668
+ const pinnedWidth = pinnedStartWidth + pinnedEndWidth + (hasStartPin ? leadWidth : 0) + trailWidth;
63959
64669
  const hasUnpinned = columns.some((column) => !column?.sticky);
63960
64670
  const suppressed = hasUnpinned && containerWidth > 0 && containerWidth - pinnedWidth < MIN_UNPINNED_SPACE;
63961
64671
  this.leadOffsets.set(leadOffsets);
64672
+ this.trailOffsets.set(trailOffsets);
63962
64673
  this.offsets.set({ start, end });
63963
64674
  this.suppressed.set(suppressed);
63964
64675
  this.insets.set(suppressed
63965
64676
  ? { start: 0, end: 0 }
63966
- : { start: hasStartPin ? leadWidth + pinnedStartWidth : 0, end: pinnedEndWidth });
64677
+ : { start: hasStartPin ? leadWidth + pinnedStartWidth : 0, end: pinnedEndWidth + trailWidth });
63967
64678
  });
63968
64679
  }
63969
64680
  /** How a data column is pinned, as the table's header, body and footer cells render it. */
@@ -63984,6 +64695,15 @@ class TableStickyColumnsDirective {
63984
64695
  const pinned = this.hasStickyStart();
63985
64696
  return { sticky: pinned, offset: pinned ? (this.leadOffsets()[key] ?? 0) : null };
63986
64697
  }
64698
+ /**
64699
+ * Whether the trailing utility columns are pinned to the trailing edge, and how far in. Unlike the
64700
+ * leading ones, these do not wait for a pinned data column: a feature puts its column at that edge to
64701
+ * keep it reachable, so pinning is live means pinned - see {@link TableLeadColumn.side}.
64702
+ */
64703
+ trailPinning(key) {
64704
+ const pinned = this.enabled() && !this.suppressed();
64705
+ return { sticky: pinned, offset: pinned ? (this.trailOffsets()[key] ?? 0) : null };
64706
+ }
63987
64707
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TableStickyColumnsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
63988
64708
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: TableStickyColumnsDirective, isStandalone: true, selector: "[etTableStickyColumns]", inputs: { config: { classPropertyName: "config", publicName: "etTableStickyColumns", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["etTableStickyColumns"], ngImport: i0 }); }
63989
64709
  }
@@ -64092,6 +64812,7 @@ class TableSkeletonRowsComponent {
64092
64812
  @for (row of rows(); track row.key) {
64093
64813
  <div
64094
64814
  [style.--_et-table-row-h.px]="feature.measuredRowHeight()"
64815
+ [class.et-table-row--box]="table.hasRowBox()"
64095
64816
  class="et-table-row et-table-row--placeholder et-skeleton--animated"
64096
64817
  role="row"
64097
64818
  aria-hidden="true"
@@ -64115,6 +64836,12 @@ class TableSkeletonRowsComponent {
64115
64836
  @if (table.hasFillerTrack()) {
64116
64837
  <div class="et-table-cell et-table-filler-cell" role="presentation"></div>
64117
64838
  }
64839
+ @for (trail of table.trailColumnsMeta(); track trail.key) {
64840
+ <div [class]="trail.cellClass" class="et-table-cell" role="gridcell"></div>
64841
+ }
64842
+ @if (table.hasRowBox()) {
64843
+ <div class="et-table-card-corners" role="presentation" aria-hidden="true"></div>
64844
+ }
64118
64845
  </div>
64119
64846
  }
64120
64847
  `, isInline: true, styles: ["@layer components{.et-table-skeleton-rows{display:contents}.et-table-row--placeholder .et-table-cell{min-block-size:var(--_et-table-row-h, calc(1.4em + var(--et-table-cell-padding-block) * 2))}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SkeletonItemComponent, selector: "et-skeleton-item", inputs: ["shape"] }], encapsulation: i0.ViewEncapsulation.None }); }
@@ -64125,6 +64852,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
64125
64852
  @for (row of rows(); track row.key) {
64126
64853
  <div
64127
64854
  [style.--_et-table-row-h.px]="feature.measuredRowHeight()"
64855
+ [class.et-table-row--box]="table.hasRowBox()"
64128
64856
  class="et-table-row et-table-row--placeholder et-skeleton--animated"
64129
64857
  role="row"
64130
64858
  aria-hidden="true"
@@ -64148,6 +64876,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
64148
64876
  @if (table.hasFillerTrack()) {
64149
64877
  <div class="et-table-cell et-table-filler-cell" role="presentation"></div>
64150
64878
  }
64879
+ @for (trail of table.trailColumnsMeta(); track trail.key) {
64880
+ <div [class]="trail.cellClass" class="et-table-cell" role="gridcell"></div>
64881
+ }
64882
+ @if (table.hasRowBox()) {
64883
+ <div class="et-table-card-corners" role="presentation" aria-hidden="true"></div>
64884
+ }
64151
64885
  </div>
64152
64886
  }
64153
64887
  `, encapsulation: ViewEncapsulation.None, imports: [NgTemplateOutlet, SkeletonItemComponent], host: { class: 'et-table-skeleton-rows' }, styles: ["@layer components{.et-table-skeleton-rows{display:contents}.et-table-row--placeholder .et-table-cell{min-block-size:var(--_et-table-row-h, calc(1.4em + var(--et-table-cell-padding-block) * 2))}}\n"] }]
@@ -64283,6 +65017,12 @@ const TABLE_KEYBOARD_NAV_IMPORTS = [TableKeyboardNavDirective];
64283
65017
  const TABLE_INLINE_EDIT_IMPORTS = [TableInlineEditDirective, TableCellEditDirective];
64284
65018
  /** Drag-to-resize column widths (`etTableResize`). Pulls in the drag primitives. */
64285
65019
  const TABLE_RESIZE_IMPORTS = [TableResizeDirective];
65020
+ /**
65021
+ * Drag-to-scroll (`etTableDragScroll`): pressing in the table and dragging pans it, so a wide table is
65022
+ * reachable without the scrollbar. Pulls in the drag primitives - which it shares with
65023
+ * {@link TABLE_RESIZE_IMPORTS} and {@link TABLE_REORDER_IMPORTS} when those are used too.
65024
+ */
65025
+ const TABLE_DRAG_SCROLL_IMPORTS = [TableDragScrollDirective];
64286
65026
  /** Drag-to-reorder columns (`etTableReorder`), with the drag ghost and drop indicator. */
64287
65027
  const TABLE_REORDER_IMPORTS = [TableReorderDirective];
64288
65028
  /** Multi-row selection (`etTableSelection`). Pulls in the checkbox component. */
@@ -64298,6 +65038,11 @@ const TABLE_GROUP_HEADERS_IMPORTS = [TableGroupHeadersDirective];
64298
65038
  * chrome, which is why it is separate - a table that pins nothing measures nothing.
64299
65039
  */
64300
65040
  const TABLE_STICKY_COLUMNS_IMPORTS = [TableStickyColumnsDirective];
65041
+ /**
65042
+ * A viewport-pinned header row (`etTablePageStickyHeader`) for a table the page scrolls rather than the
65043
+ * table itself. A table with a height of its own pins its header without any of this.
65044
+ */
65045
+ const TABLE_PAGE_STICKY_HEADER_IMPORTS = [TablePageStickyHeaderDirective];
64301
65046
  /**
64302
65047
  * Loading placeholders (`etTableSkeleton`): a block of skeleton rows while loading with no rows yet, a
64303
65048
  * bone in a cell that is loading on its own, and the `etTableCellSkeleton` template for saying what a
@@ -64310,6 +65055,12 @@ const TABLE_SKELETON_IMPORTS = [TableSkeletonDirective, TableCellSkeletonDirecti
64310
65055
  * why it is separate - a table that never expands a row pays for none of it.
64311
65056
  */
64312
65057
  const TABLE_ROW_EXPANSION_IMPORTS = [TableRowExpansionDirective];
65058
+ /**
65059
+ * Angular routing for row links (`etTableRowRouterLink`): a `[rowLink]` may then answer with router
65060
+ * commands instead of an `href`, and a plain click navigates through the router. Separate because the
65061
+ * base table depends on no router - a table linking with plain `href` strings pays for none of it.
65062
+ */
65063
+ const TABLE_ROW_ROUTER_LINK_IMPORTS = [TableRowRouterLinkDirective];
64313
65064
  /**
64314
65065
  * Tooltips on failed cells (`etTableCellErrorTooltip`): a `cellState` message is shown on hover/focus
64315
65066
  * rather than as a native `title`. Pulls in the tooltip, and with it the overlay runtime.
@@ -66342,11 +67093,11 @@ const TREE_IMPORTS = [TreeComponent, TreeDirective, TreeNodeDirective, TreeNodeD
66342
67093
 
66343
67094
  // Generated from package.json by tools/scripts/generate-version.js - do not edit.
66344
67095
  /** The version of `@ethlete/components` this build was cut from. */
66345
- const COMPONENTS_VERSION = '1.0.0-next.53';
67096
+ const COMPONENTS_VERSION = '1.0.0-next.55';
66346
67097
 
66347
67098
  /**
66348
67099
  * Generated bundle index. Do not edit.
66349
67100
  */
66350
67101
 
66351
- export { ACCORDION_ERROR_CODES, ACCORDION_GROUP_TOKEN, ACCORDION_IMPORTS, ACCORDION_TOKEN, ALIGN_CENTER_ICON, ALIGN_JUSTIFY_ICON, ALIGN_LEFT_ICON, ALIGN_RIGHT_ICON, ARROWS_LEFT_RIGHT_ICON, ARROW_OUT_UP_RIGHT_ICON, ARROW_RIGHT_ICON, ARROW_UP_ICON, AVATAR_IMPORTS, AVATAR_SHAPES, AVATAR_SIZES, AccordionComponent, AccordionContentDirective, AccordionDirective, AccordionGroupComponent, AccordionGroupDirective, AccordionHintDirective, AccordionLabelDirective, AccordionPanelDirective, AccordionTriggerDirective, AvatarComponent, AvatarGroupComponent, BADGE_ICON_ALIGNMENTS, BADGE_IMPORTS, BADGE_SIZES, BADGE_VARIANTS, BANNER_IMPORTS, BANNER_LABELS, BANNER_TYPES, BOLD_ICON, BRACKET_CARD_CONTEXT, BRACKET_DATA_LAYOUT, BRACKET_DEFAULTS, BRACKET_DENSITY, BRACKET_DENSITY_PRESETS, BRACKET_ERROR_CODES, BRACKET_IMPORTS, BRACKET_LABELS, BRACKET_ROUND_MIRROR_TYPE, BRACKET_SWISS_GROUP_COLOR_TYPE, BREADCRUMB_COLLAPSE_IMPORTS, BREADCRUMB_COLLAPSE_TOKEN, BREADCRUMB_ERROR_CODES, BREADCRUMB_IMPORTS, BREADCRUMB_LABELS, BREADCRUMB_SEGMENT_TOKEN, BREADCRUMB_SEO_IMPORTS, BREADCRUMB_TOKEN, BUTTON_ICON_ALIGNMENTS, BUTTON_IMPORTS, BUTTON_SIZES, BUTTON_SPINNER_CONFIG, BUTTON_TYPES, BUTTON_VARIANTS, BadgeComponent, BannerComponent, BracketComponent, BracketDefaultContinueComponent, BracketDefaultFinalMatchComponent, BracketDefaultMatchComponent, BracketDefaultRoundHeaderComponent, BracketMap, BracketRoundsListComponent, BrandLoaderComponent, BreadcrumbCollapseDirective, BreadcrumbComponent, BreadcrumbDirective, BreadcrumbItemDirective, BreadcrumbItemTemplateDirective, BreadcrumbOutletComponent, BreadcrumbOverflowComponent, BreadcrumbSegmentDirective, BreadcrumbSeoDirective, BreadcrumbSeparatorDirective, ButtonColorDirective, ButtonComponent, ButtonDirective, ButtonStylesDirective, CALENDAR_ERROR_CODES, CALENDAR_ICON, CALENDAR_IMPORTS, CALENDAR_LABELS, CARD_IMPORTS, CARD_VARIANTS, CAROUSEL_AUTOPLAY_TOKEN, CAROUSEL_ERROR_CODES, CAROUSEL_IMPORTS, CAROUSEL_LABELS, CAROUSEL_SLIDE_ALIGNMENTS, CAROUSEL_TOKEN, CAROUSEL_TRANSITIONS, CAROUSEL_TRANSITION_DRIVERS, CASCADER_ERROR_CODES, CASCADER_IMPORTS, CASCADER_LABELS, CASCADER_SELECTABLE_LEVELS, CHECKBOX_GROUP_IMPORTS, CHECKBOX_IMPORTS, CHECKBOX_OPTION_VARIANTS, CHECK_ICON, CHEVRON_ICON, CHIP_ERROR_CODES, CHIP_IMPORTS, CHIP_LABELS, CHOICE_FIELD_IMPORTS, CHOICE_FIELD_VARIANTS, CIRCLE_CHECK_ICON, CIRCLE_INFO_ICON, CLIPBOARD_CHECK_ICON, CLOCK_ICON, CODE_BLOCK_ICON, CODE_ICON, COLOR_INPUT_IMPORTS, COMMON_BRACKET_ROUND_TYPE, COMPONENTS_VERSION, COPY_BUTTON_IMPORTS, CalendarCellDirective, CalendarComponent, CalendarDirective, CalendarGridDirective, CalendarHeaderDirective, CardComponent, CarouselAutoplayDirective, CarouselComponent, CarouselDirective, CarouselItemDirective, CarouselNextDirective, CarouselPlayToggleDirective, CarouselPreviousDirective, CarouselSlideDirective, CascaderColumnDirective, CascaderComponent, CascaderDirective, CascaderNodeDirective, CascaderPanelComponent, CascaderSearchDirective, CascaderSearchOptionDirective, CascaderSurfaceDirective, CascaderTriggerDirective, CheckboxComponent, CheckboxDirective, CheckboxGroupComponent, CheckboxGroupSelectAllComponent, CheckboxOptionComponent, ChipComponent, ChipDirective, ChipRemoveDirective, ChoiceFieldComponent, ColorInputComponent, ColorInputDirective, ControlSuffixDirective, CopyButtonDirective, CounterComponent, DAILYMOTION_PLAYER_TOKEN, DATE_FORMAT, DATE_INPUT_ERROR_CODES, DATE_INPUT_IMPORTS, DATE_LOCALE, DATE_PICKER_HOST, DATE_RANGE_INPUT_ERROR_CODES, DATE_RANGE_INPUT_IMPORTS, DATE_TIME_INPUT_ERROR_CODES, DATE_TIME_INPUT_IMPORTS, DATE_TIME_LABELS, DATE_TIME_RANGE_INPUT_ERROR_CODES, DATE_TIME_RANGE_INPUT_IMPORTS, DEFAULT_BANNER_LABELS, DEFAULT_BRACKET_LABELS, DEFAULT_BREADCRUMB_LABELS, DEFAULT_BREAKPOINTS, DEFAULT_CALENDAR_LABELS, DEFAULT_CALENDAR_RANGE_STRATEGY, DEFAULT_CAROUSEL_LABELS, DEFAULT_CASCADER_LABELS, DEFAULT_CHIP_LABELS, DEFAULT_DATE_TIME_LABELS, DEFAULT_DROPZONE_LABELS, DEFAULT_FILTER_OVERLAY_LABELS, DEFAULT_FORM_FIELD_LABELS, DEFAULT_GRID_LABELS, DEFAULT_ICON_VARIANT, DEFAULT_INPUT_LABELS, DEFAULT_LOADER_LABELS, DEFAULT_MATCH_CARD_START_TIME_FORMAT, DEFAULT_MATCH_LABELS, DEFAULT_NOTIFICATION_LABELS, DEFAULT_NOTIFICATION_MANAGER_CONFIG, DEFAULT_NOTIFICATION_STATUS_ICONS, DEFAULT_PAGINATION_LABELS, DEFAULT_PHONE_INPUT_LABELS, DEFAULT_PIP_WINDOW_CONFIG, DEFAULT_QUERY_ERROR_LABELS, DEFAULT_RICH_TEXT_EDITOR_LABELS, DEFAULT_RICH_TEXT_EDITOR_TOOLS, DEFAULT_SCHEDULER_LABELS, DEFAULT_SELECT_LABELS, DEFAULT_SLIDER_LABELS, DEFAULT_STANDINGS_LABELS, DEFAULT_STREAM_LABELS, DEFAULT_STREAM_PLAYER_STATE, DEFAULT_TABLE_LABELS, DEFAULT_TIME_PICKER_LABELS, DESCRIPTION_IMPORTS, DESCRIPTION_LIST_IMPORTS, DESCRIPTION_LIST_VARIANTS, DIVIDER_IMPORTS, DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE, DROPZONE_ENTRY_STATUSES, DROPZONE_ERROR_CODES, DROPZONE_FILES_ERROR_KIND, DROPZONE_FILE_CONSTRAINTS, DROPZONE_FILE_REJECTION_REASONS, DROPZONE_IMPORTS, DROPZONE_LABELS, DURATION_INPUT_ERROR_CODES, DURATION_INPUT_IMPORTS, DailymotionPlayerComponent, DailymotionPlayerDirective, DailymotionPlayerParamsDirective, DailymotionPlayerSlotComponent, DateInputComponent, DateInputDirective, DateInputFieldDirective, DatePickerPanelComponent, DatePickerSurfaceDirective, DatePickerTriggerDirective, DateRangeInputComponent, DateRangeInputDirective, DateRangeInputFieldDirective, DateTimeInputComponent, DateTimeInputDirective, DateTimeInputFieldDirective, DateTimeRangeInputComponent, DateTimeRangeInputDirective, DateTimeRangeInputFieldDirective, DescriptionComponent, DescriptionListComponent, DividerComponent, DropzoneComponent, DropzoneDirective, DurationInputComponent, DurationInputDirective, DurationInputFieldDirective, ELLIPSIS_ICON, ELLIPSIS_VERTICAL_ICON, EMPTY_STATE_IMPORTS, ET_BUILT_IN_ICON_NAMES, EYE_ICON, EYE_SLASH_ICON, EmptyStateComponent, FACEBOOK_PLAYER_TOKEN, FIELD_WARNINGS, FIELD_WARNING_KIND, FILE_ICON, FILTER_ICON, FILTER_OVERLAY_ERROR_CODES, FILTER_OVERLAY_IMPORTS, FILTER_OVERLAY_LABELS, FILTER_OVERLAY_TOKEN, FLOATING_ACTION_ERROR_CODES, FLOATING_ACTION_IMPORTS, FLOATING_ACTION_STATES, FLOATING_ACTION_TOKEN, FLOPPY_DISK_ICON, FOCUS_FRAME_ICON, FORM_ERROR_MESSAGE_RESOLVER, FORM_FIELD_APPEARANCES, FORM_FIELD_CONTROL_TYPES, FORM_FIELD_ERROR_CODES, FORM_FIELD_FILLS, FORM_FIELD_IMPORTS, FORM_FIELD_LABELS, FORM_FIELD_LABEL_MODES, FORM_FIELD_SIZES, FORM_FIELD_TOKEN, FORM_IMPORTS, FORM_WARNING_MESSAGE_RESOLVER, FabComponent, FacebookPlayerComponent, FacebookPlayerDirective, FacebookPlayerParamsDirective, FacebookPlayerSlotComponent, FilterOverlayResetDirective, FilterOverlaySubmitDirective, FloatingActionAnchorDirective, FloatingActionDirective, FloatingActionScopeDirective, FloatingActionTopDirective, FloatingActionTriggerDirective, FocusRingDirective, FormDirective, FormErrorComponent, FormFieldBarrierDirective, FormFieldComponent, FormFieldDirective, FormWarningComponent, GERMAN_FILTER_OVERLAY_LABELS, GERMAN_QUERY_ERROR_LABELS, GRID_2X2_ICON, GRID_DEBUG_IMPORTS, GRID_ERROR_CODES, GRID_IMPORTS, GRID_LABELS, GRID_TOKEN, GROUP_BRACKET_ROUND_TYPE, GridComponent, GridDebugComponent, GridDirective, GridDragDirective, GridItemComponent, GridItemDefaultActionsComponent, GridItemDirective, GridItemRef, GridItemToolbarComponent, GridResizeDirective, HEADING_1_ICON, HEADING_2_ICON, HEADING_3_ICON, HintComponent, ICONS_TOKEN, ICON_DIRECTIVE_TOKEN, ICON_ERROR_CODES, ICON_IMPORTS, ICON_OVERRIDES_TOKEN, IMAGE_ICON, INHERIT_COLOR, INITIAL_SUPPORT_PRESENTATION_STATE, INPUT_IMPORTS, INPUT_LABELS, INPUT_MASK_HOST, INPUT_TEXT_ALIGNMENTS, INPUT_TYPES, INTERACTIVE_TAGS, ITALIC_ICON, IconButtonComponent, IconDirective, InputComponent, InputDirective, InputMaskDirective, InputPrefixDirective, InputSuffixDirective, KBD_IMPORTS, KBD_PLATFORM, KICK_PLAYER_TOKEN, KbdComponent, KickPlayerComponent, KickPlayerDirective, KickPlayerParamsDirective, KickPlayerSlotComponent, LINK_ICON, LIST_BULLETED_ICON, LIST_NUMBERED_ICON, LOADER_LABELS, LOCATION_ICON, LOCK_ICON, LabelDirective, MASKED_INPUT_ERROR_CODES, MASKED_INPUT_IMPORTS, MASK_VALUE_MODES, MASONRY_ERROR_CODES, MASONRY_IMPORTS, MASONRY_TOKEN, MATCH_CARD_IMPORTS, MATCH_CARD_SIZES, MATCH_CARD_TOKEN, MATCH_ERROR_CODES, MATCH_LABELS, MATCH_PARTICIPANT_IMPORTS, MENU_ERROR_CODES, MENU_IMPORTS, MENU_ITEM_VARIANTS, MENU_SELECTION_GROUP_MULTIPLE, MENU_SELECTION_GROUP_TOKEN, MENU_SELECTION_ITEM_KIND, MINUS_ICON, MULTI_LANGUAGE_RICH_TEXT_EDITOR_ERROR_CODES, MULTI_LANGUAGE_RICH_TEXT_EDITOR_IMPORTS, MasonryDirective, MasonryItemDirective, MatchCardComponent, MatchCardDirective, MatchCardGameScoresDirective, MatchCardMetaDirective, MatchCardScoreDirective, MatchParticipantComponent, MatchScoreComponent, MenuCheckboxGroupComponent, MenuCheckboxItemComponent, MenuComponent, MenuContextTriggerDirective, MenuDirective, MenuGroupLabelComponent, MenuItemComponent, MenuItemDirective, MenuItemShortcutComponent, MenuPanelDirective, MenuRadioGroupComponent, MenuRadioItemComponent, MenuSearchDirective, MenuSelectionGroupDirective, MenuSelectionItemDirective, MenuSeparatorComponent, MenuSurfaceDirective, MenuTriggerDirective, MultiLanguageRichTextEditorComponent, MultiLanguageRichTextEditorDirective, MultiLanguageRichTextEditorLanguageToolComponent, NAV_TABS_TOKEN, NAV_TAB_IMPORTS, NOTIFICATION_ACTION_SLOTS, NOTIFICATION_ERROR_CODES, NOTIFICATION_IMPORTS, NOTIFICATION_LABELS, NOTIFICATION_STACK_CONTEXT_TOKEN, NOTIFICATION_STACK_OVERLAY_LAYER, NOTIFICATION_STATUS, NUMBER_INPUT_IMPORTS, NavTabLinkComponent, NavTabLinkDirective, NavTabLinkStylesComponent, NavTabsComponent, NavTabsDirective, NavTabsOutletComponent, NavTabsOutletDirective, NotificationActionDirective, NotificationComponent, NotificationDirective, NotificationDismissDirective, NotificationItemDirective, NotificationStackDirective, NotificationSwipeToDismissDirective, NumberInputComponent, NumberInputDirective, OTP_INPUT_IMPORTS, OVERLAY_BACK_OR_CLOSE_TOKEN, OVERLAY_BODY_TOKEN, OVERLAY_CONFIG_CLASS_KEYS, OVERLAY_CONTENT_IMPORTS, OVERLAY_ERROR_CODES, OVERLAY_FOOTER_TOKEN, OVERLAY_HEADER_TEMPLATE_TOKEN, OVERLAY_HEADER_TOKEN, OVERLAY_IMPORTS, OVERLAY_MAIN_TOKEN, OVERLAY_QUERY_PARAM_INPUT_NAME, OVERLAY_REF, OVERLAY_ROUTER_CONFIG_TOKEN, OVERLAY_ROUTER_LINK_TOKEN, OVERLAY_ROUTER_OUTLET_DISABLED_TEMPLATE_TOKEN, OVERLAY_ROUTER_OUTLET_TOKEN, OVERLAY_ROUTER_TOKEN, OVERLAY_SHARED_ROUTE_TEMPLATE_TOKEN, OtpInputComponent, OtpInputDirective, OverlayAnchorDirective, OverlayBackOrCloseDirective, OverlayBodyComponent, OverlayCloseDirective, OverlayContainerComponent, OverlayDirective, OverlayFooterDirective, OverlayHeaderDirective, OverlayHeaderTemplateDirective, OverlayMainDirective, OverlayNavTabLinkComponent, OverlayOriginCloneComponent, OverlayRouteHeaderTemplateOutletComponent, OverlayRouterLinkDirective, OverlayRouterOutletComponent, OverlayRouterOutletDisabledTemplateDirective, OverlaySharedRouteTemplateDirective, OverlaySharedRouteTemplateOutletComponent, OverlaySidebarComponent, OverlaySidebarPageComponent, OverlaySurfaceDirective, OverlayTitleDirective, OverlayTriggerDirective, PAGE_SIZE_SELECT_IMPORTS, PAGINATION_IMPORTS, PAGINATION_LABELS, PARAGRAPH_ICON, PASSWORD_INPUT_IMPORTS, PAUSE_ICON, PENCIL_ICON, PHONE_COUNTRIES, PHONE_INPUT_ERROR_CODES, PHONE_INPUT_IMPORTS, PHONE_INPUT_LABELS, PICTURE_IMPORTS, PICTURE_STATES, PIP_CHROME_REF_TOKEN, PIP_ENTRY_TOKEN, PIP_WINDOW_ASPECT_RATIO_TOKEN, PLAY_ICON, PLUS_ICON, PROGRESS_STEPS_IMPORTS, PROGRESS_STEPS_ORIENTATIONS, PROGRESS_STEP_STATES, PageSizeSelectComponent, PaginationComponent, PaginationDirective, PaginationSeoDirective, PasswordInputComponent, PasswordInputDirective, PhoneInputComponent, PhoneInputDirective, PhoneInputFieldDirective, PhoneInputFlagDirective, PictureComponent, PictureErrorDirective, PicturePlaceholderDirective, PipBackDirective, PipBringBackDirective, PipCellDirective, PipCloseDirective, PipCollapseOverlayDirective, PipGridToggleDirective, PipPlayerComponent, PipSlotPlaceholderComponent, PipStageDirective, PipTitleBarDirective, PipTitleBarTemplateDirective, PipWindowComponent, PipWindowParamsDirective, ProgressBarComponent, ProgressStepComponent, ProgressStepsComponent, QUERY_ERROR_ERROR_CODES, QUERY_ERROR_IMPORTS, QUERY_ERROR_LABELS, QUERY_ERROR_TOKEN, QUOTE_ICON, QueryErrorActionsDirective, QueryErrorComponent, QueryErrorDirective, QueryErrorTitleDirective, QueryParamOverlayLinkDirective, RADIO_GROUP_IMPORTS, RADIO_VARIANTS, RATING_IMPORTS, REDO_ICON, RICH_TEXT_EDITOR_FLOATING_TOOLBAR, RICH_TEXT_EDITOR_HEADING_OPTIONS, RICH_TEXT_EDITOR_IMPORTS, RICH_TEXT_EDITOR_INLINE_TOOLS, RICH_TEXT_EDITOR_LABELS, RICH_TEXT_EDITOR_LANGUAGE_TOOL, RICH_TEXT_EDITOR_LINK_EDITOR, RICH_TEXT_EDITOR_TOKEN_CODEC, RICH_TEXT_EDITOR_TOKEN_PALETTE_IMPORTS, RICH_TEXT_EDITOR_TOOL, RICH_TEXT_EDITOR_TOOLS, RICH_TEXT_EDITOR_TOOL_BUTTONS, RICH_TEXT_EDITOR_TRIGGERS_IMPORTS, ROTATE_RIGHT_ICON, RadioComponent, RadioGroupComponent, RangeSliderComponent, RangeSliderDirective, RatingComponent, RatingDirective, RatingIconDirective, RichTextEditorAlignToolComponent, RichTextEditorComponent, RichTextEditorDirective, RichTextEditorFloatingToolbarComponent, RichTextEditorFloatingToolbarDirective, RichTextEditorHeadingToolComponent, RichTextEditorImageEditorComponent, RichTextEditorImageStylesComponent, RichTextEditorImageToolComponent, RichTextEditorLinkEditorComponent, RichTextEditorLinkEditorDirective, RichTextEditorTableStylesComponent, RichTextEditorTableToolComponent, RichTextEditorTokenPaletteComponent, RichTextEditorTokenPopupComponent, RichTextEditorTriggersDirective, SCHEDULER_ADD_SURFACE_OVERLAY, SCHEDULER_EDIT_SURFACE_HOST, SCHEDULER_EDIT_SURFACE_OVERLAY, SCHEDULER_ERROR_CODES, SCHEDULER_FEATURE_HOST, SCHEDULER_IMPORTS, SCHEDULER_LABELS, SCROLLABLE_DARKEN_IMPORTS, SCROLLABLE_DRAG_IMPORTS, SCROLLABLE_ERROR_CODES, SCROLLABLE_IMPORTS, SCROLLABLE_NAVIGATION_IMPORTS, SEGMENTED_BUTTON_GROUP_VARIANTS, SEGMENTED_BUTTON_IMPORTS, SELECTION_CARD_CONTROL_POSITIONS, SELECTION_LIST_IMPORTS, SELECTION_LIST_MULTIPLE, SELECTION_LIST_TOKEN, SELECT_ERROR_CODES, SELECT_FILTER_MODES, SELECT_IMPORTS, SELECT_LABELS, SIDEBAR_OVERLAY_CONFIG, SIDEBAR_OVERLAY_TOKEN, SINGLE_ELIMINATION_BRACKET_ROUND_TYPE, SKELETON_IMPORTS, SLIDER_ERROR_CODES, SLIDER_IMPORTS, SLIDER_LABELS, SLIDER_MARK_VALUE_ATTRIBUTE, SLIDER_TOKEN, SNAP_HYSTERESIS, SOOP_PLAYER_TOKEN, SPLIT_BUTTON_ERROR_CODES, STANDINGS_ERROR_CODES, STANDINGS_IMPORTS, STANDINGS_LABELS, STAR_ICON, STREAM_ALL_IMPORTS, STREAM_CONSENT_TOKEN, STREAM_DAILYMOTION_IMPORTS, STREAM_FACEBOOK_IMPORTS, STREAM_IMPORTS, STREAM_KICK_IMPORTS, STREAM_LABELS, STREAM_PIP_IMPORTS, STREAM_PLAYER_COMPONENT_TOKEN, STREAM_PLAYER_ERROR_CONTEXT_TOKEN, STREAM_PLAYER_ERROR_TOKEN, STREAM_PLAYER_PARAMS_TOKEN, STREAM_PLAYER_SLOT_TOKEN, STREAM_PLAYER_TOKEN, STREAM_SLOT_PLAYER_ID_TOKEN, STREAM_SOOP_IMPORTS, STREAM_TIKTOK_IMPORTS, STREAM_TWITCH_IMPORTS, STREAM_USER_CONSENT_PROVIDER_TOKEN, STREAM_VIMEO_IMPORTS, STREAM_YOUTUBE_IMPORTS, STRIKETHROUGH_ICON, SUPPORT_CONTENT_STATE, SUPPORT_TRANSITION_DIRECTION, SWISS_BRACKET_ROUND_TYPE, SWITCH_IMPORTS, SchedulerActionAddAppointmentDirective, SchedulerActionAddSubAppointmentDirective, SchedulerActionDeleteDirective, SchedulerAgendaDirective, SchedulerAgendaViewComponent, SchedulerAppointmentDragDirective, SchedulerBadgeChainCountComponent, SchedulerBadgeChainCountDirective, SchedulerBadgeColorDotComponent, SchedulerBadgeColorDotDirective, SchedulerBadgeLocationComponent, SchedulerBadgeLocationDirective, SchedulerBadgeTimeRangeComponent, SchedulerBadgeTimeRangeDirective, SchedulerBadgeTitleComponent, SchedulerBadgeTitleDirective, SchedulerComponent, SchedulerDirective, SchedulerEditColorComponent, SchedulerEditColorDirective, SchedulerEditDescriptionComponent, SchedulerEditDescriptionDirective, SchedulerEditLocationComponent, SchedulerEditLocationDirective, SchedulerEditSurfaceComponent, SchedulerEditSurfaceDirective, SchedulerEditTimeRangeComponent, SchedulerEditTimeRangeDirective, SchedulerEditTitleComponent, SchedulerEditTitleDirective, SchedulerMonthDirective, SchedulerMonthViewComponent, SchedulerSwipeNavigationDirective, SchedulerTimeGridDirective, SchedulerTimeGridViewComponent, ScrollableActiveChildDirective, ScrollableButtonsComponent, ScrollableButtonsDirective, ScrollableComponent, ScrollableDarkenDirective, ScrollableDirective, ScrollableDragDirective, ScrollableIgnoreChildDirective, ScrollableLoadingTemplateDirective, ScrollableMasksComponent, ScrollableNavigationComponent, ScrollableNavigationDirective, ScrollableSnapDirective, SegmentedButtonComponent, SegmentedButtonGroupComponent, SelectComponent, SelectDirective, SelectEmptyDirective, SelectErrorDirective, SelectListboxDirective, SelectLoadingDirective, SelectOptionComponent, SelectOptionDirective, SelectOptionGroupComponent, SelectOptionGroupDirective, SelectOptionTemplateDirective, SelectOptionsDirective, SelectPanelComponent, SelectSearchDirective, SelectSurfaceDirective, SelectTriggerDirective, SelectValueDirective, SelectViewportDirective, SelectVirtualOptionComponent, SelectVirtualOptionDirective, SelectionListControlDirective, SelectionListDirective, SelectionOptionDirective, SkeletonComponent, SkeletonItemComponent, SkeletonTextComponent, SliderComponent, SliderDirective, SliderThumbDirective, SliderThumbLabelDirective, SliderTrackDirective, SoopPlayerComponent, SoopPlayerDirective, SoopPlayerParamsDirective, SoopPlayerSlotComponent, SpinnerComponent, SplitButtonActionDirective, SplitButtonComponent, SplitButtonDirective, SplitButtonTriggerDirective, StandingsComponent, StandingsDirective, StreamConsentAcceptDirective, StreamConsentComponent, StreamConsentDirective, StreamPipChromeComponent, StreamPlayerErrorComponent, StreamPlayerErrorDirective, StreamPlayerLoadingComponent, StreamPlayerSlotDirective, SwitchComponent, SwitchDirective, TABLE_CELL_ERROR_TOOLTIP_IMPORTS, TABLE_COLUMN_CHOOSER_IMPORTS, TABLE_COLUMN_MENU_IMPORTS, TABLE_CSV_EXPORT_IMPORTS, TABLE_ERROR_CODES, TABLE_FEATURE_HOST, TABLE_FILTER_IMPORTS, TABLE_GROUP_HEADERS_IMPORTS, TABLE_ICON, TABLE_IMPORTS, TABLE_INLINE_EDIT_IMPORTS, TABLE_KEYBOARD_NAV_IMPORTS, TABLE_LABELS, TABLE_REORDER_IMPORTS, TABLE_RESIZE_IMPORTS, TABLE_ROW_EXPANSION_IMPORTS, TABLE_SELECTION_IMPORTS, TABLE_SKELETON_IMPORTS, TABLE_STATE_PERSISTENCE_IMPORTS, TABLE_STICKY_COLUMNS_IMPORTS, TABLE_VIRTUAL_SCROLL_IMPORTS, TAB_BAR_FITS, TAB_BAR_ORIENTATIONS, TAB_BAR_TOKEN, TAB_BAR_TRIGGER_TOKEN, TAB_BAR_VARIANTS, TAB_ERROR_CODES, TAB_GROUP_TOKEN, TAB_IMPORTS, TAB_PANEL_TOKEN, TAB_SIZES, TAG_INPUT_ERROR_CODES, TAG_INPUT_IMPORTS, TEXTAREA_IMPORTS, TEXTAREA_RESIZE_MODES, TEXT_ALIGNS, TIKTOK_PLAYER_TOKEN, TIMELINE_IMPORTS, TIMES_ICON, TIME_FORMAT, TIME_INPUT_ERROR_CODES, TIME_INPUT_IMPORTS, TIME_PICKER_ERROR_CODES, TIME_PICKER_IMPORTS, TIME_PICKER_LABELS, TIME_RANGE_INPUT_ERROR_CODES, TIME_RANGE_INPUT_IMPORTS, TOGGLETIP_ERROR_CODES, TOGGLETIP_IMPORTS, TOOLBAR_IMPORTS, TOOLBAR_ORIENTATIONS, TOOLTIP_ERROR_CODES, TOOLTIP_IMPORTS, TOURNAMENT_MODE, TRASH_ICON, TREE_ERROR_CODES, TREE_IMPORTS, TREE_LEVEL_STATUSES, TREE_MARKERS, TREE_SELECTION_MODES, TRIANGLE_EXCLAMATION_ICON, TROPHY_ICON, TWITCH_PLAYER_TOKEN, TabBarDirective, TabBarTriggerDirective, TabBarUnderlineDirective, TabComponent, TabGroupComponent, TabGroupDirective, TabLabelDirective, TabPanelDirective, TabTriggerDirective, TableCellDirective, TableCellEditDirective, TableCellErrorMarkComponent, TableCellErrorTooltipDirective, TableCellSkeletonDirective, TableColumnChooserComponent, TableColumnMenuDirective, TableColumnMenuTriggerComponent, TableComponent, TableCsvExportDirective, TableDetailStylesComponent, TableExpanderCellComponent, TableFilterOptionDirective, TableFilterTriggerComponent, TableFiltersDirective, TableFooterCellDirective, TableFooterDirective, TableGroupHeaderRowComponent, TableGroupHeadersDirective, TableHeaderCellDirective, TableInlineEditDirective, TableInlineEditStylesComponent, TableKeyboardNavDirective, TableReorderDirective, TableReorderOverlayComponent, TableResizeDirective, TableResizeGripComponent, TableRowDetailComponent, TableRowExpansionDirective, TableSelectAllCellComponent, TableSelectCellComponent, TableSelectionDirective, TableSkeletonDirective, TableSkeletonRowsComponent, TableStatePersistenceDirective, TableStickyColumnsDirective, TableVirtualScrollDirective, TableVirtualScrollStylesComponent, TagInputComponent, TagInputDirective, TagInputFieldDirective, TextButtonComponent, TextFieldControlDirective, TextareaComponent, TextareaDirective, TikTokPlayerComponent, TikTokPlayerDirective, TikTokPlayerParamsDirective, TikTokPlayerSlotComponent, TimeInputComponent, TimeInputDirective, TimeInputFieldDirective, TimePickerColumnDirective, TimePickerComponent, TimePickerDirective, TimePickerOptionDirective, TimeRangeInputComponent, TimeRangeInputDirective, TimeRangeInputFieldDirective, TimelineComponent, TimelineItemComponent, ToggletipCloseDirective, ToggletipComponent, ToggletipDirective, ToggletipTriggerDirective, ToolbarComponent, ToolbarDirective, TooltipComponent, TooltipDirective, TreeComponent, TreeDirective, TreeMarkerComponent, TreeNodeDefDirective, TreeNodeDirective, TwitchPlayerComponent, TwitchPlayerDirective, TwitchPlayerParamsDirective, TwitchPlayerSlotComponent, UNDERLINE_ICON, UNDO_ICON, UNIT_MS, UPLOAD_ICON, VIMEO_PLAYER_TOKEN, VimeoPlayerComponent, VimeoPlayerDirective, VimeoPlayerParamsDirective, VimeoPlayerSlotComponent, WCAG_CONTRAST_RATIOS, WINDOW_CONTROL_BUTTON_KINDS, WINDOW_CONTROL_BUTTON_SIZES, WindowControlButtonComponent, YOUTUBE_PLAYER_SLOT_TOKEN, YOUTUBE_PLAYER_TOKEN, YoutubePlayerComponent, YoutubePlayerDirective, YoutubePlayerParamsDirective, YoutubePlayerSlotComponent, YoutubePlayerSlotDirective, abortFullscreenAnimation, anchoredDialogOverlayStrategy, anchoredOverlayStrategy, autoPlace, bottomSheetOverlayStrategy, bracketFitsWidth, bracketNaturalWidth, buildAnchoredRuntimePositionStrategy, canHaveChildren, cascaderFromQuery, centeredOverlayStrategy, clampPosition, clampResizeRect, cleanupFullscreenAnimation, cleanupFullscreenAnimationStyles, clearLeavingSupportStateOnExit, colorContrast, compactLayout, computeGeometry, computeGridHeight, countDescendants, createAnchoredPanelController, createAutoScroller, createCardMask, createCurrencyMask, createDefaultDropzoneArgs, createDropzoneUpload, createExistingDropzoneEntry, createFileDropzoneEntry, createFixedLengthRangeStrategy, createGridAdapter, createIbanMask, createNormalizedBracketMatch, createNotificationPromiseFn, createNotificationRef, createOverlayOpener, createOverlayRef, createOverlayStrategyController, createOverlayUnsavedChangesGuard, createPipChromeAnimations, createPipChromeState, createRichTextEditorTrigger, createRichTextEditorTriggerWithQuery, createStreamConfig, createStreamPlayerSlot, createTableRowsSource, createTableStateStorage, createV2DropzoneUpload, createWeekRangeStrategy, defaultCompareWith$1 as defaultCompareWith, defaultDropzoneRejectionMessage, defineOverlay, defineQueryParamOverlay, deriveDurationFormatSpec, deserializeGridLayout, deserializeTableState, detectKbdPlatform, dialogOverlayStrategy, disposeDropzoneEntry, doubleEliminationBracketLayout, dropzoneFiles, enableDragToDismiss, extractFirstImageUrl, filterOverlayLabelsForLocale, filterOverlayPreviewFromQuery, filterRows, findCollision, findNextRelevantHtmlElement, findScrollableAncestor, focusFirstInvalidField, formatDuration, formatFileSize, fromGridPosition, fullScreenDialogOverlayStrategy, generateBracketDataForEthlete, generateRoundTypeFromEthleteRoundType, generateTournamentModeFormEthleteRounds, getClosestOverlay, getColorContrastRatio, getOriginCoordinatesAndDimensions, hexColor, hysteresisRound, iconRegistryKey, indexOfNode, injectAnchoredDialogStrategy, injectAnchoredDialogStrategyDefaults, injectBannerLabels, injectBottomSheetStrategy, injectBottomSheetStrategyDefaults, injectBracketConfig, injectBracketLabels, injectBreadcrumbLabels, injectBreadcrumbManager, injectCalendarLabels, injectCarouselLabels, injectCascaderLabels, injectChipLabels, injectDateFormat, injectDateLocale, injectDateTimeLabels, injectDialogStrategy, injectDialogStrategyDefaults, injectDropzoneLabels, injectFilterOverlay, injectFilterOverlayLabels, injectFormFieldLabels, injectFormSupport, injectFullscreenDialogStrategy, injectFullscreenDialogStrategyDefaults, injectGridConfig, injectGridLabels, injectInputLabels, injectLeftSheetStrategy, injectLeftSheetStrategyDefaults, injectLoaderLabels, injectMatchLabels, injectNotificationLabels, injectNotificationManager, injectNotificationManagerConfig, injectOverlayManager, injectOverlayRouter, injectOverlayScrollBlocker, injectOverlaySurfaceContext, injectPaginationLabels, injectPhoneInputLabels, injectPictureConfig, injectPipChromeManager, injectPipManager, injectPipSlotPlaceholderConfig, injectQueryErrorLabels, injectRichTextEditorLabels, injectRichTextEditorTools, injectRightSheetStrategy, injectRightSheetStrategyDefaults, injectSchedulerEditSurfaceHost, injectSchedulerFeatureHost, injectSchedulerLabels, injectSelectLabels, injectSidebarOverlay, injectSliderLabels, injectStandingsLabels, injectStreamConfig, injectStreamConsentConfig, injectStreamLabels, injectStreamManager, injectStreamPlayerErrorConfig, injectStreamPlayerLoadingConfig, injectStreamScriptLoader, injectStreamUserConsentProvider, injectTableCsvExport, injectTableFeatureHost, injectTableLabels, injectTimeFormat, injectTimePickerLabels, injectTopSheetStrategy, injectTopSheetStrategyDefaults, isFileAccepted, isHtmlElement, isInteractiveElement, isPointerEvent, isTargetInsideOverlayTree, isTouchEvent, itemsCollide, kbdKeyLabel, kbdKeyName, leftSheetOverlayStrategy, legacyQueryErrorSource, mapGridLayout, mapLayoutToBreakpoint, matchCountryByDialCode, matchParticipantDisplayName, mergeOverlayBreakpointConfigs, mergeOverlayConfigs, mirroredDoubleEliminationBracketLayout, mirroredSingleEliminationBracketLayout, mountNavTabLinkStyles, mountRichTextEditorImageStyles, mountRichTextEditorTableStyles, nodesEqual$1 as nodesEqual, normalizeEthleteBracketMatch, normalizeEthleteGroupRanking, normalizeEthleteMatch, normalizeEthleteMatchStatus, normalizeEthleteMedia, normalizeEthleteParticipant, normalizeEthletePlacement, normalizePictureSizes, normalizePictureSource, numberInputStepMultiplierFrom, paginate, parseDuration, parseKbdKeys, phoneCountryFlag, phoneCountryName, pixelRectsEqual, positionToPixelRect, positionsEqual, projectDragCell, provideAnchoredDialogStrategy, provideAnchoredDialogStrategyDefaults, provideBannerLabels, provideBottomSheetStrategy, provideBottomSheetStrategyDefaults, provideBracketConfig, provideBracketLabels, provideBreadcrumbLabels, provideBreadcrumbManager, provideCalendarLabels, provideCarouselLabels, provideCascaderLabels, provideChipLabels, provideDateFormat, provideDateLocale, provideDateTimeLabels, provideDialogStrategy, provideDialogStrategyDefaults, provideDropzoneLabels, provideFilterOverlay, provideFilterOverlayLabels, provideFormErrorMessageResolver, provideFormFieldLabels, provideFormSupport, provideFormWarningMessageResolver, provideFullscreenDialogStrategy, provideFullscreenDialogStrategyDefaults, provideGridConfig, provideGridLabels, provideIconOverrides, provideIcons, provideInputLabels, provideLeftSheetStrategy, provideLeftSheetStrategyDefaults, provideLoaderLabels, provideMatchLabels, provideNotificationLabels, provideNotificationManager, provideNotificationManagerConfig, provideNotificationManagerInstance, provideOverlay, provideOverlayManager, provideOverlayRouter, provideOverlayRouterConfig, provideOverlayRouterService, provideOverlayScrollBlocker, providePaginationLabels, providePhoneInputLabels, providePictureConfig, providePipChromeManager, providePipManager, providePipSlotPlaceholderConfig, provideQueryErrorLabels, provideRichTextEditorAlignmentTool, provideRichTextEditorAutoformat, provideRichTextEditorBlockquoteTool, provideRichTextEditorCodeBlockTool, provideRichTextEditorDefaultTools, provideRichTextEditorFloatingToolbar, provideRichTextEditorHeadingTool, provideRichTextEditorImageTool, provideRichTextEditorLabels, provideRichTextEditorLanguageTool, provideRichTextEditorLinkEditor, provideRichTextEditorLinkTool, provideRichTextEditorTableTool, provideRichTextEditorTokenRendering, provideRichTextEditorTools, provideRightSheetStrategy, provideRightSheetStrategyDefaults, provideSchedulerLabels, provideSelectLabels, provideSidebarOverlay, provideSidebarOverlayConfig, provideSidebarOverlayService, provideSliderLabels, provideStandingsLabels, provideStreamConfig, provideStreamConsentConfig, provideStreamLabels, provideStreamManager, provideStreamPlayerErrorConfig, provideStreamPlayerLoadingConfig, provideTableLabels, provideTimeFormat, provideTimePickerLabels, provideTopSheetStrategy, provideTopSheetStrategyDefaults, queryErrorLabelsForLocale, queryErrorResponseFromLegacyError, reconcileColumnOrder, reconcileColumnWidths, reconcileHiddenColumns, reduceSupportPresentation, registerSingleton, requiredLanguages, resizeSpanBounds, resolveBracketLayout, resolveBreakpoint, resolveClosestOverlay, resolveCollisions, resolveFilterOverlaySubmitButton, resolveNotificationStatusIcon, resolveTableCsvRows, rgbColor, richTextEditorToolLabel, rightSheetOverlayStrategy, rowsToPixelHeight, schedulerFeatureConfig, selectOptionsFromQuery, selectOptionsFromV2Query, serializeGridLayout, serializeTableState, setupRichTextEditorFloatingToolbar, setupRichTextEditorLinkEditor, singleEliminationBracketLayout, snapResizeSpan, sortRows, spanHeight, spanWidth, startFullscreenEnterAnimation, startFullscreenLeaveAnimation, startImageUpload, startOfCalendarUnit, stripTrunkZero, supportPresentationIncludesState, swissBracketLayout, tableCsvRowsFromPages, tableFeatureConfig, tableRowsFromQuery, tableRowsFromV2Query, tableToCsv, toChildrenObservable$1 as toChildrenObservable, toGridPosition, toNotificationContent, toPathObservable, toSearchObservable, topSheetOverlayStrategy, transformingBottomSheetToDialogOverlayStrategy, transformingFullScreenDialogToDialogOverlayStrategy, transformingFullScreenDialogToRightSheetOverlayStrategy, warn, wireFormSupport, withPictureBaseUrl };
67102
+ export { ACCORDION_ERROR_CODES, ACCORDION_GROUP_TOKEN, ACCORDION_IMPORTS, ACCORDION_TOKEN, ALIGN_CENTER_ICON, ALIGN_JUSTIFY_ICON, ALIGN_LEFT_ICON, ALIGN_RIGHT_ICON, ARROWS_LEFT_RIGHT_ICON, ARROW_OUT_UP_RIGHT_ICON, ARROW_RIGHT_ICON, ARROW_UP_ICON, AVATAR_IMPORTS, AVATAR_SHAPES, AVATAR_SIZES, AccordionComponent, AccordionContentDirective, AccordionDirective, AccordionGroupComponent, AccordionGroupDirective, AccordionHintDirective, AccordionLabelDirective, AccordionPanelDirective, AccordionTriggerDirective, AvatarComponent, AvatarGroupComponent, BADGE_ICON_ALIGNMENTS, BADGE_IMPORTS, BADGE_SIZES, BADGE_VARIANTS, BANNER_IMPORTS, BANNER_LABELS, BANNER_TYPES, BOLD_ICON, BRACKET_CARD_CONTEXT, BRACKET_DATA_LAYOUT, BRACKET_DEFAULTS, BRACKET_DENSITY, BRACKET_DENSITY_PRESETS, BRACKET_ERROR_CODES, BRACKET_IMPORTS, BRACKET_LABELS, BRACKET_ROUND_MIRROR_TYPE, BRACKET_SWISS_GROUP_COLOR_TYPE, BREADCRUMB_COLLAPSE_IMPORTS, BREADCRUMB_COLLAPSE_TOKEN, BREADCRUMB_ERROR_CODES, BREADCRUMB_IMPORTS, BREADCRUMB_LABELS, BREADCRUMB_SEGMENT_TOKEN, BREADCRUMB_SEO_IMPORTS, BREADCRUMB_TOKEN, BUTTON_ICON_ALIGNMENTS, BUTTON_IMPORTS, BUTTON_SIZES, BUTTON_SPINNER_CONFIG, BUTTON_TYPES, BUTTON_VARIANTS, BadgeComponent, BannerComponent, BracketComponent, BracketDefaultContinueComponent, BracketDefaultFinalMatchComponent, BracketDefaultMatchComponent, BracketDefaultRoundHeaderComponent, BracketMap, BracketRoundsListComponent, BrandLoaderComponent, BreadcrumbCollapseDirective, BreadcrumbComponent, BreadcrumbDirective, BreadcrumbItemDirective, BreadcrumbItemTemplateDirective, BreadcrumbOutletComponent, BreadcrumbOverflowComponent, BreadcrumbSegmentDirective, BreadcrumbSeoDirective, BreadcrumbSeparatorDirective, ButtonColorDirective, ButtonComponent, ButtonDirective, ButtonStylesDirective, CALENDAR_ERROR_CODES, CALENDAR_ICON, CALENDAR_IMPORTS, CALENDAR_LABELS, CARD_IMPORTS, CARD_VARIANTS, CAROUSEL_AUTOPLAY_TOKEN, CAROUSEL_ERROR_CODES, CAROUSEL_IMPORTS, CAROUSEL_LABELS, CAROUSEL_SLIDE_ALIGNMENTS, CAROUSEL_TOKEN, CAROUSEL_TRANSITIONS, CAROUSEL_TRANSITION_DRIVERS, CASCADER_ERROR_CODES, CASCADER_IMPORTS, CASCADER_LABELS, CASCADER_SELECTABLE_LEVELS, CHECKBOX_GROUP_IMPORTS, CHECKBOX_IMPORTS, CHECKBOX_OPTION_VARIANTS, CHECK_ICON, CHEVRON_ICON, CHIP_ERROR_CODES, CHIP_IMPORTS, CHIP_LABELS, CHOICE_FIELD_IMPORTS, CHOICE_FIELD_VARIANTS, CIRCLE_CHECK_ICON, CIRCLE_INFO_ICON, CLIPBOARD_CHECK_ICON, CLOCK_ICON, CODE_BLOCK_ICON, CODE_ICON, COLOR_INPUT_IMPORTS, COMMON_BRACKET_ROUND_TYPE, COMPONENTS_VERSION, COPY_BUTTON_IMPORTS, CalendarCellDirective, CalendarComponent, CalendarDirective, CalendarGridDirective, CalendarHeaderDirective, CardComponent, CarouselAutoplayDirective, CarouselComponent, CarouselDirective, CarouselItemDirective, CarouselNextDirective, CarouselPlayToggleDirective, CarouselPreviousDirective, CarouselSlideDirective, CascaderColumnDirective, CascaderComponent, CascaderDirective, CascaderNodeDirective, CascaderPanelComponent, CascaderSearchDirective, CascaderSearchOptionDirective, CascaderSurfaceDirective, CascaderTriggerDirective, CheckboxComponent, CheckboxDirective, CheckboxGroupComponent, CheckboxGroupSelectAllComponent, CheckboxOptionComponent, ChipComponent, ChipDirective, ChipRemoveDirective, ChoiceFieldComponent, ColorInputComponent, ColorInputDirective, ControlSuffixDirective, CopyButtonDirective, CounterComponent, DAILYMOTION_PLAYER_TOKEN, DATE_FORMAT, DATE_INPUT_ERROR_CODES, DATE_INPUT_IMPORTS, DATE_LOCALE, DATE_PICKER_HOST, DATE_RANGE_INPUT_ERROR_CODES, DATE_RANGE_INPUT_IMPORTS, DATE_TIME_INPUT_ERROR_CODES, DATE_TIME_INPUT_IMPORTS, DATE_TIME_LABELS, DATE_TIME_RANGE_INPUT_ERROR_CODES, DATE_TIME_RANGE_INPUT_IMPORTS, DEFAULT_BANNER_LABELS, DEFAULT_BRACKET_LABELS, DEFAULT_BREADCRUMB_LABELS, DEFAULT_BREAKPOINTS, DEFAULT_CALENDAR_LABELS, DEFAULT_CALENDAR_RANGE_STRATEGY, DEFAULT_CAROUSEL_LABELS, DEFAULT_CASCADER_LABELS, DEFAULT_CHIP_LABELS, DEFAULT_DATE_TIME_LABELS, DEFAULT_DROPZONE_LABELS, DEFAULT_FILTER_OVERLAY_LABELS, DEFAULT_FORM_FIELD_LABELS, DEFAULT_GRID_LABELS, DEFAULT_ICON_VARIANT, DEFAULT_INPUT_LABELS, DEFAULT_LOADER_LABELS, DEFAULT_MATCH_CARD_START_TIME_FORMAT, DEFAULT_MATCH_LABELS, DEFAULT_NOTIFICATION_LABELS, DEFAULT_NOTIFICATION_MANAGER_CONFIG, DEFAULT_NOTIFICATION_STATUS_ICONS, DEFAULT_PAGINATION_LABELS, DEFAULT_PHONE_INPUT_LABELS, DEFAULT_PIP_WINDOW_CONFIG, DEFAULT_QUERY_ERROR_LABELS, DEFAULT_RICH_TEXT_EDITOR_LABELS, DEFAULT_RICH_TEXT_EDITOR_TOOLS, DEFAULT_SCHEDULER_LABELS, DEFAULT_SELECT_LABELS, DEFAULT_SLIDER_LABELS, DEFAULT_STANDINGS_LABELS, DEFAULT_STREAM_LABELS, DEFAULT_STREAM_PLAYER_STATE, DEFAULT_TABLE_LABELS, DEFAULT_TIME_PICKER_LABELS, DESCRIPTION_IMPORTS, DESCRIPTION_LIST_IMPORTS, DESCRIPTION_LIST_VARIANTS, DIVIDER_IMPORTS, DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE, DROPZONE_ENTRY_STATUSES, DROPZONE_ERROR_CODES, DROPZONE_FILES_ERROR_KIND, DROPZONE_FILE_CONSTRAINTS, DROPZONE_FILE_REJECTION_REASONS, DROPZONE_IMPORTS, DROPZONE_LABELS, DURATION_INPUT_ERROR_CODES, DURATION_INPUT_IMPORTS, DailymotionPlayerComponent, DailymotionPlayerDirective, DailymotionPlayerParamsDirective, DailymotionPlayerSlotComponent, DateInputComponent, DateInputDirective, DateInputFieldDirective, DatePickerPanelComponent, DatePickerSurfaceDirective, DatePickerTriggerDirective, DateRangeInputComponent, DateRangeInputDirective, DateRangeInputFieldDirective, DateTimeInputComponent, DateTimeInputDirective, DateTimeInputFieldDirective, DateTimeRangeInputComponent, DateTimeRangeInputDirective, DateTimeRangeInputFieldDirective, DescriptionComponent, DescriptionListComponent, DividerComponent, DropzoneComponent, DropzoneDirective, DurationInputComponent, DurationInputDirective, DurationInputFieldDirective, ELLIPSIS_ICON, ELLIPSIS_VERTICAL_ICON, EMPTY_STATE_IMPORTS, ET_BUILT_IN_ICON_NAMES, EYE_ICON, EYE_SLASH_ICON, EmptyStateComponent, FACEBOOK_PLAYER_TOKEN, FIELD_WARNINGS, FIELD_WARNING_KIND, FILE_ICON, FILTER_ICON, FILTER_OVERLAY_ERROR_CODES, FILTER_OVERLAY_IMPORTS, FILTER_OVERLAY_LABELS, FILTER_OVERLAY_TOKEN, FLOATING_ACTION_ERROR_CODES, FLOATING_ACTION_IMPORTS, FLOATING_ACTION_STATES, FLOATING_ACTION_TOKEN, FLOPPY_DISK_ICON, FOCUS_FRAME_ICON, FORM_ERROR_MESSAGE_RESOLVER, FORM_FIELD_APPEARANCES, FORM_FIELD_CONTROL_TYPES, FORM_FIELD_ERROR_CODES, FORM_FIELD_FILLS, FORM_FIELD_IMPORTS, FORM_FIELD_LABELS, FORM_FIELD_LABEL_MODES, FORM_FIELD_SIZES, FORM_FIELD_TOKEN, FORM_IMPORTS, FORM_WARNING_MESSAGE_RESOLVER, FabComponent, FacebookPlayerComponent, FacebookPlayerDirective, FacebookPlayerParamsDirective, FacebookPlayerSlotComponent, FilterOverlayResetDirective, FilterOverlaySubmitDirective, FloatingActionAnchorDirective, FloatingActionDirective, FloatingActionScopeDirective, FloatingActionTopDirective, FloatingActionTriggerDirective, FocusRingDirective, FormDirective, FormErrorComponent, FormFieldBarrierDirective, FormFieldComponent, FormFieldDirective, FormWarningComponent, GERMAN_FILTER_OVERLAY_LABELS, GERMAN_QUERY_ERROR_LABELS, GRID_2X2_ICON, GRID_DEBUG_IMPORTS, GRID_ERROR_CODES, GRID_IMPORTS, GRID_LABELS, GRID_TOKEN, GROUP_BRACKET_ROUND_TYPE, GridComponent, GridDebugComponent, GridDirective, GridDragDirective, GridItemComponent, GridItemDefaultActionsComponent, GridItemDirective, GridItemRef, GridItemToolbarComponent, GridResizeDirective, HEADING_1_ICON, HEADING_2_ICON, HEADING_3_ICON, HintComponent, ICONS_TOKEN, ICON_DIRECTIVE_TOKEN, ICON_ERROR_CODES, ICON_IMPORTS, ICON_OVERRIDES_TOKEN, IMAGE_ICON, INHERIT_COLOR, INITIAL_SUPPORT_PRESENTATION_STATE, INPUT_IMPORTS, INPUT_LABELS, INPUT_MASK_HOST, INPUT_TEXT_ALIGNMENTS, INPUT_TYPES, INTERACTIVE_TAGS, ITALIC_ICON, IconButtonComponent, IconDirective, InputComponent, InputDirective, InputMaskDirective, InputPrefixDirective, InputSuffixDirective, KBD_IMPORTS, KBD_PLATFORM, KICK_PLAYER_TOKEN, KbdComponent, KickPlayerComponent, KickPlayerDirective, KickPlayerParamsDirective, KickPlayerSlotComponent, LINK_ICON, LIST_BULLETED_ICON, LIST_NUMBERED_ICON, LOADER_LABELS, LOCATION_ICON, LOCK_ICON, LabelDirective, MASKED_INPUT_ERROR_CODES, MASKED_INPUT_IMPORTS, MASK_VALUE_MODES, MASONRY_ERROR_CODES, MASONRY_IMPORTS, MASONRY_TOKEN, MATCH_CARD_IMPORTS, MATCH_CARD_SIZES, MATCH_CARD_TOKEN, MATCH_ERROR_CODES, MATCH_LABELS, MATCH_PARTICIPANT_IMPORTS, MENU_ERROR_CODES, MENU_IMPORTS, MENU_ITEM_VARIANTS, MENU_SELECTION_GROUP_MULTIPLE, MENU_SELECTION_GROUP_TOKEN, MENU_SELECTION_ITEM_KIND, MINUS_ICON, MULTI_LANGUAGE_RICH_TEXT_EDITOR_ERROR_CODES, MULTI_LANGUAGE_RICH_TEXT_EDITOR_IMPORTS, MasonryDirective, MasonryItemDirective, MatchCardComponent, MatchCardDirective, MatchCardGameScoresDirective, MatchCardMetaDirective, MatchCardScoreDirective, MatchParticipantComponent, MatchScoreComponent, MenuCheckboxGroupComponent, MenuCheckboxItemComponent, MenuComponent, MenuContextTriggerDirective, MenuDirective, MenuGroupLabelComponent, MenuItemComponent, MenuItemDirective, MenuItemShortcutComponent, MenuPanelDirective, MenuRadioGroupComponent, MenuRadioItemComponent, MenuSearchDirective, MenuSelectionGroupDirective, MenuSelectionItemDirective, MenuSeparatorComponent, MenuSurfaceDirective, MenuTriggerDirective, MultiLanguageRichTextEditorComponent, MultiLanguageRichTextEditorDirective, MultiLanguageRichTextEditorLanguageToolComponent, NAV_TABS_TOKEN, NAV_TAB_IMPORTS, NOTIFICATION_ACTION_SLOTS, NOTIFICATION_ERROR_CODES, NOTIFICATION_IMPORTS, NOTIFICATION_LABELS, NOTIFICATION_STACK_CONTEXT_TOKEN, NOTIFICATION_STACK_OVERLAY_LAYER, NOTIFICATION_STATUS, NUMBER_INPUT_IMPORTS, NavTabLinkComponent, NavTabLinkDirective, NavTabLinkStylesComponent, NavTabsComponent, NavTabsDirective, NavTabsOutletComponent, NavTabsOutletDirective, NotificationActionDirective, NotificationComponent, NotificationDirective, NotificationDismissDirective, NotificationItemDirective, NotificationStackDirective, NotificationSwipeToDismissDirective, NumberInputComponent, NumberInputDirective, OTP_INPUT_IMPORTS, OVERLAY_BACK_OR_CLOSE_TOKEN, OVERLAY_BODY_TOKEN, OVERLAY_CONFIG_CLASS_KEYS, OVERLAY_CONTENT_IMPORTS, OVERLAY_ERROR_CODES, OVERLAY_FOOTER_TOKEN, OVERLAY_HEADER_TEMPLATE_TOKEN, OVERLAY_HEADER_TOKEN, OVERLAY_IMPORTS, OVERLAY_MAIN_TOKEN, OVERLAY_QUERY_PARAM_INPUT_NAME, OVERLAY_REF, OVERLAY_ROUTER_CONFIG_TOKEN, OVERLAY_ROUTER_LINK_TOKEN, OVERLAY_ROUTER_OUTLET_DISABLED_TEMPLATE_TOKEN, OVERLAY_ROUTER_OUTLET_TOKEN, OVERLAY_ROUTER_TOKEN, OVERLAY_SHARED_ROUTE_TEMPLATE_TOKEN, OtpInputComponent, OtpInputDirective, OverlayAnchorDirective, OverlayBackOrCloseDirective, OverlayBodyComponent, OverlayCloseDirective, OverlayContainerComponent, OverlayDirective, OverlayFooterDirective, OverlayHeaderDirective, OverlayHeaderTemplateDirective, OverlayMainDirective, OverlayNavTabLinkComponent, OverlayOriginCloneComponent, OverlayRouteHeaderTemplateOutletComponent, OverlayRouterLinkDirective, OverlayRouterOutletComponent, OverlayRouterOutletDisabledTemplateDirective, OverlaySharedRouteTemplateDirective, OverlaySharedRouteTemplateOutletComponent, OverlaySidebarComponent, OverlaySidebarPageComponent, OverlaySurfaceDirective, OverlayTitleDirective, OverlayTriggerDirective, PAGE_SIZE_SELECT_IMPORTS, PAGINATION_IMPORTS, PAGINATION_LABELS, PARAGRAPH_ICON, PASSWORD_INPUT_IMPORTS, PAUSE_ICON, PENCIL_ICON, PHONE_COUNTRIES, PHONE_INPUT_ERROR_CODES, PHONE_INPUT_IMPORTS, PHONE_INPUT_LABELS, PICTURE_IMPORTS, PICTURE_STATES, PIP_CHROME_REF_TOKEN, PIP_ENTRY_TOKEN, PIP_WINDOW_ASPECT_RATIO_TOKEN, PLAY_ICON, PLUS_ICON, PROGRESS_STEPS_IMPORTS, PROGRESS_STEPS_ORIENTATIONS, PROGRESS_STEP_STATES, PageSizeSelectComponent, PaginationComponent, PaginationDirective, PaginationSeoDirective, PasswordInputComponent, PasswordInputDirective, PhoneInputComponent, PhoneInputDirective, PhoneInputFieldDirective, PhoneInputFlagDirective, PictureComponent, PictureErrorDirective, PicturePlaceholderDirective, PipBackDirective, PipBringBackDirective, PipCellDirective, PipCloseDirective, PipCollapseOverlayDirective, PipGridToggleDirective, PipPlayerComponent, PipSlotPlaceholderComponent, PipStageDirective, PipTitleBarDirective, PipTitleBarTemplateDirective, PipWindowComponent, PipWindowParamsDirective, ProgressBarComponent, ProgressStepComponent, ProgressStepsComponent, QUERY_ERROR_ERROR_CODES, QUERY_ERROR_IMPORTS, QUERY_ERROR_LABELS, QUERY_ERROR_TOKEN, QUOTE_ICON, QueryErrorActionsDirective, QueryErrorComponent, QueryErrorDirective, QueryErrorTitleDirective, QueryParamOverlayLinkDirective, RADIO_GROUP_IMPORTS, RADIO_VARIANTS, RATING_IMPORTS, REDO_ICON, RICH_TEXT_EDITOR_FLOATING_TOOLBAR, RICH_TEXT_EDITOR_HEADING_OPTIONS, RICH_TEXT_EDITOR_IMPORTS, RICH_TEXT_EDITOR_INLINE_TOOLS, RICH_TEXT_EDITOR_LABELS, RICH_TEXT_EDITOR_LANGUAGE_TOOL, RICH_TEXT_EDITOR_LINK_EDITOR, RICH_TEXT_EDITOR_TOKEN_CODEC, RICH_TEXT_EDITOR_TOKEN_PALETTE_IMPORTS, RICH_TEXT_EDITOR_TOOL, RICH_TEXT_EDITOR_TOOLS, RICH_TEXT_EDITOR_TOOL_BUTTONS, RICH_TEXT_EDITOR_TRIGGERS_IMPORTS, ROTATE_RIGHT_ICON, RadioComponent, RadioGroupComponent, RangeSliderComponent, RangeSliderDirective, RatingComponent, RatingDirective, RatingIconDirective, RichTextEditorAlignToolComponent, RichTextEditorComponent, RichTextEditorDirective, RichTextEditorFloatingToolbarComponent, RichTextEditorFloatingToolbarDirective, RichTextEditorHeadingToolComponent, RichTextEditorImageEditorComponent, RichTextEditorImageStylesComponent, RichTextEditorImageToolComponent, RichTextEditorLinkEditorComponent, RichTextEditorLinkEditorDirective, RichTextEditorTableStylesComponent, RichTextEditorTableToolComponent, RichTextEditorTokenPaletteComponent, RichTextEditorTokenPopupComponent, RichTextEditorTriggersDirective, SCHEDULER_ADD_SURFACE_OVERLAY, SCHEDULER_EDIT_SURFACE_HOST, SCHEDULER_EDIT_SURFACE_OVERLAY, SCHEDULER_ERROR_CODES, SCHEDULER_FEATURE_HOST, SCHEDULER_IMPORTS, SCHEDULER_LABELS, SCROLLABLE_DARKEN_IMPORTS, SCROLLABLE_DRAG_IMPORTS, SCROLLABLE_ERROR_CODES, SCROLLABLE_IMPORTS, SCROLLABLE_NAVIGATION_IMPORTS, SEGMENTED_BUTTON_GROUP_VARIANTS, SEGMENTED_BUTTON_IMPORTS, SELECTION_CARD_CONTROL_POSITIONS, SELECTION_LIST_IMPORTS, SELECTION_LIST_MULTIPLE, SELECTION_LIST_TOKEN, SELECT_ERROR_CODES, SELECT_FILTER_MODES, SELECT_IMPORTS, SELECT_LABELS, SIDEBAR_OVERLAY_CONFIG, SIDEBAR_OVERLAY_TOKEN, SINGLE_ELIMINATION_BRACKET_ROUND_TYPE, SKELETON_IMPORTS, SLIDER_ERROR_CODES, SLIDER_IMPORTS, SLIDER_LABELS, SLIDER_MARK_VALUE_ATTRIBUTE, SLIDER_TOKEN, SNAP_HYSTERESIS, SOOP_PLAYER_TOKEN, SPLIT_BUTTON_ERROR_CODES, STANDINGS_ERROR_CODES, STANDINGS_IMPORTS, STANDINGS_LABELS, STAR_ICON, STREAM_ALL_IMPORTS, STREAM_CONSENT_TOKEN, STREAM_DAILYMOTION_IMPORTS, STREAM_FACEBOOK_IMPORTS, STREAM_IMPORTS, STREAM_KICK_IMPORTS, STREAM_LABELS, STREAM_PIP_IMPORTS, STREAM_PLAYER_COMPONENT_TOKEN, STREAM_PLAYER_ERROR_CONTEXT_TOKEN, STREAM_PLAYER_ERROR_TOKEN, STREAM_PLAYER_PARAMS_TOKEN, STREAM_PLAYER_SLOT_TOKEN, STREAM_PLAYER_TOKEN, STREAM_SLOT_PLAYER_ID_TOKEN, STREAM_SOOP_IMPORTS, STREAM_TIKTOK_IMPORTS, STREAM_TWITCH_IMPORTS, STREAM_USER_CONSENT_PROVIDER_TOKEN, STREAM_VIMEO_IMPORTS, STREAM_YOUTUBE_IMPORTS, STRIKETHROUGH_ICON, SUPPORT_CONTENT_STATE, SUPPORT_TRANSITION_DIRECTION, SWISS_BRACKET_ROUND_TYPE, SWITCH_IMPORTS, SchedulerActionAddAppointmentDirective, SchedulerActionAddSubAppointmentDirective, SchedulerActionDeleteDirective, SchedulerAgendaDirective, SchedulerAgendaViewComponent, SchedulerAppointmentDragDirective, SchedulerBadgeChainCountComponent, SchedulerBadgeChainCountDirective, SchedulerBadgeColorDotComponent, SchedulerBadgeColorDotDirective, SchedulerBadgeLocationComponent, SchedulerBadgeLocationDirective, SchedulerBadgeTimeRangeComponent, SchedulerBadgeTimeRangeDirective, SchedulerBadgeTitleComponent, SchedulerBadgeTitleDirective, SchedulerComponent, SchedulerDirective, SchedulerEditColorComponent, SchedulerEditColorDirective, SchedulerEditDescriptionComponent, SchedulerEditDescriptionDirective, SchedulerEditLocationComponent, SchedulerEditLocationDirective, SchedulerEditSurfaceComponent, SchedulerEditSurfaceDirective, SchedulerEditTimeRangeComponent, SchedulerEditTimeRangeDirective, SchedulerEditTitleComponent, SchedulerEditTitleDirective, SchedulerMonthDirective, SchedulerMonthViewComponent, SchedulerSwipeNavigationDirective, SchedulerTimeGridDirective, SchedulerTimeGridViewComponent, ScrollableActiveChildDirective, ScrollableButtonsComponent, ScrollableButtonsDirective, ScrollableComponent, ScrollableDarkenDirective, ScrollableDirective, ScrollableDragDirective, ScrollableIgnoreChildDirective, ScrollableLoadingTemplateDirective, ScrollableMasksComponent, ScrollableNavigationComponent, ScrollableNavigationDirective, ScrollableSnapDirective, SegmentedButtonComponent, SegmentedButtonGroupComponent, SelectComponent, SelectDirective, SelectEmptyDirective, SelectErrorDirective, SelectListboxDirective, SelectLoadingDirective, SelectOptionComponent, SelectOptionDirective, SelectOptionGroupComponent, SelectOptionGroupDirective, SelectOptionTemplateDirective, SelectOptionsDirective, SelectPanelComponent, SelectSearchDirective, SelectSurfaceDirective, SelectTriggerDirective, SelectValueDirective, SelectViewportDirective, SelectVirtualOptionComponent, SelectVirtualOptionDirective, SelectionListControlDirective, SelectionListDirective, SelectionOptionDirective, SkeletonComponent, SkeletonItemComponent, SkeletonTextComponent, SliderComponent, SliderDirective, SliderThumbDirective, SliderThumbLabelDirective, SliderTrackDirective, SoopPlayerComponent, SoopPlayerDirective, SoopPlayerParamsDirective, SoopPlayerSlotComponent, SpinnerComponent, SplitButtonActionDirective, SplitButtonComponent, SplitButtonDirective, SplitButtonTriggerDirective, StandingsComponent, StandingsDirective, StreamConsentAcceptDirective, StreamConsentComponent, StreamConsentDirective, StreamPipChromeComponent, StreamPlayerErrorComponent, StreamPlayerErrorDirective, StreamPlayerLoadingComponent, StreamPlayerSlotDirective, SwitchComponent, SwitchDirective, TABLE_CELL_ERROR_TOOLTIP_IMPORTS, TABLE_COLUMN_CHOOSER_IMPORTS, TABLE_COLUMN_MENU_IMPORTS, TABLE_CSV_EXPORT_IMPORTS, TABLE_DRAG_SCROLL_IMPORTS, TABLE_ERROR_CODES, TABLE_FEATURE_HOST, TABLE_FILTER_IMPORTS, TABLE_GROUP_HEADERS_IMPORTS, TABLE_ICON, TABLE_IMPORTS, TABLE_INLINE_EDIT_IMPORTS, TABLE_KEYBOARD_NAV_IMPORTS, TABLE_LABELS, TABLE_PAGE_STICKY_HEADER_IMPORTS, TABLE_REORDER_IMPORTS, TABLE_RESIZE_IMPORTS, TABLE_ROW_EXPANSION_IMPORTS, TABLE_ROW_ROUTER_LINK_IMPORTS, TABLE_SELECTION_IMPORTS, TABLE_SKELETON_IMPORTS, TABLE_STATE_PERSISTENCE_IMPORTS, TABLE_STICKY_COLUMNS_IMPORTS, TABLE_VIRTUAL_SCROLL_IMPORTS, TAB_BAR_FITS, TAB_BAR_ORIENTATIONS, TAB_BAR_TOKEN, TAB_BAR_TRIGGER_TOKEN, TAB_BAR_VARIANTS, TAB_ERROR_CODES, TAB_GROUP_TOKEN, TAB_IMPORTS, TAB_PANEL_TOKEN, TAB_SIZES, TAG_INPUT_ERROR_CODES, TAG_INPUT_IMPORTS, TEXTAREA_IMPORTS, TEXTAREA_RESIZE_MODES, TEXT_ALIGNS, TIKTOK_PLAYER_TOKEN, TIMELINE_IMPORTS, TIMES_ICON, TIME_FORMAT, TIME_INPUT_ERROR_CODES, TIME_INPUT_IMPORTS, TIME_PICKER_ERROR_CODES, TIME_PICKER_IMPORTS, TIME_PICKER_LABELS, TIME_RANGE_INPUT_ERROR_CODES, TIME_RANGE_INPUT_IMPORTS, TOGGLETIP_ERROR_CODES, TOGGLETIP_IMPORTS, TOOLBAR_IMPORTS, TOOLBAR_ORIENTATIONS, TOOLTIP_ERROR_CODES, TOOLTIP_IMPORTS, TOURNAMENT_MODE, TRASH_ICON, TREE_ERROR_CODES, TREE_IMPORTS, TREE_LEVEL_STATUSES, TREE_MARKERS, TREE_SELECTION_MODES, TRIANGLE_EXCLAMATION_ICON, TROPHY_ICON, TWITCH_PLAYER_TOKEN, TabBarDirective, TabBarTriggerDirective, TabBarUnderlineDirective, TabComponent, TabGroupComponent, TabGroupDirective, TabLabelDirective, TabPanelDirective, TabTriggerDirective, TableCellDirective, TableCellEditDirective, TableCellErrorMarkComponent, TableCellErrorTooltipDirective, TableCellSkeletonDirective, TableColumnChooserComponent, TableColumnMenuDirective, TableColumnMenuTriggerComponent, TableComponent, TableCsvExportDirective, TableDetailStylesComponent, TableDragScrollDirective, TableDragScrollStylesComponent, TableExpanderCellComponent, TableFilterOptionDirective, TableFilterTriggerComponent, TableFiltersDirective, TableFooterCellDirective, TableFooterDirective, TableGroupHeaderRowComponent, TableGroupHeadersDirective, TableHeaderCellDirective, TableInlineEditDirective, TableInlineEditStylesComponent, TableKeyboardNavDirective, TablePageStickyHeaderDirective, TablePageStickyHeaderStylesComponent, TableReorderDirective, TableReorderOverlayComponent, TableResizeDirective, TableResizeGripComponent, TableRowDetailComponent, TableRowExpansionDirective, TableRowRouterLinkDirective, TableSelectAllCellComponent, TableSelectCellComponent, TableSelectionDirective, TableSkeletonDirective, TableSkeletonRowsComponent, TableStatePersistenceDirective, TableStickyColumnsDirective, TableVirtualScrollDirective, TableVirtualScrollStylesComponent, TagInputComponent, TagInputDirective, TagInputFieldDirective, TextButtonComponent, TextFieldControlDirective, TextareaComponent, TextareaDirective, TikTokPlayerComponent, TikTokPlayerDirective, TikTokPlayerParamsDirective, TikTokPlayerSlotComponent, TimeInputComponent, TimeInputDirective, TimeInputFieldDirective, TimePickerColumnDirective, TimePickerComponent, TimePickerDirective, TimePickerOptionDirective, TimeRangeInputComponent, TimeRangeInputDirective, TimeRangeInputFieldDirective, TimelineComponent, TimelineItemComponent, ToggletipCloseDirective, ToggletipComponent, ToggletipDirective, ToggletipTriggerDirective, ToolbarComponent, ToolbarDirective, TooltipComponent, TooltipDirective, TreeComponent, TreeDirective, TreeMarkerComponent, TreeNodeDefDirective, TreeNodeDirective, TwitchPlayerComponent, TwitchPlayerDirective, TwitchPlayerParamsDirective, TwitchPlayerSlotComponent, UNDERLINE_ICON, UNDO_ICON, UNIT_MS, UPLOAD_ICON, VIMEO_PLAYER_TOKEN, VimeoPlayerComponent, VimeoPlayerDirective, VimeoPlayerParamsDirective, VimeoPlayerSlotComponent, WCAG_CONTRAST_RATIOS, WINDOW_CONTROL_BUTTON_KINDS, WINDOW_CONTROL_BUTTON_SIZES, WindowControlButtonComponent, YOUTUBE_PLAYER_SLOT_TOKEN, YOUTUBE_PLAYER_TOKEN, YoutubePlayerComponent, YoutubePlayerDirective, YoutubePlayerParamsDirective, YoutubePlayerSlotComponent, YoutubePlayerSlotDirective, abortFullscreenAnimation, anchoredDialogOverlayStrategy, anchoredOverlayStrategy, autoPlace, bottomSheetOverlayStrategy, bracketFitsWidth, bracketNaturalWidth, buildAnchoredRuntimePositionStrategy, canHaveChildren, cascaderFromQuery, centeredOverlayStrategy, clampPosition, clampResizeRect, cleanupFullscreenAnimation, cleanupFullscreenAnimationStyles, clearLeavingSupportStateOnExit, colorContrast, compactLayout, computeGeometry, computeGridHeight, countDescendants, createAnchoredPanelController, createAutoScroller, createCardMask, createCurrencyMask, createDefaultDropzoneArgs, createDropzoneUpload, createExistingDropzoneEntry, createFileDropzoneEntry, createFixedLengthRangeStrategy, createGridAdapter, createIbanMask, createNormalizedBracketMatch, createNotificationPromiseFn, createNotificationRef, createOverlayOpener, createOverlayRef, createOverlayStrategyController, createOverlayUnsavedChangesGuard, createPipChromeAnimations, createPipChromeState, createRichTextEditorTrigger, createRichTextEditorTriggerWithQuery, createStreamConfig, createStreamPlayerSlot, createTableRowsSource, createTableStateStorage, createV2DropzoneUpload, createWeekRangeStrategy, defaultCompareWith$1 as defaultCompareWith, defaultDropzoneRejectionMessage, defineOverlay, defineQueryParamOverlay, deriveDurationFormatSpec, deserializeGridLayout, deserializeTableState, detectKbdPlatform, dialogOverlayStrategy, disposeDropzoneEntry, doubleEliminationBracketLayout, dropzoneFiles, enableDragToDismiss, extractFirstImageUrl, filterOverlayLabelsForLocale, filterOverlayPreviewFromQuery, filterRows, findCollision, findNextRelevantHtmlElement, findScrollableAncestor, focusFirstInvalidField, formatDuration, formatFileSize, fromGridPosition, fullScreenDialogOverlayStrategy, generateBracketDataForEthlete, generateRoundTypeFromEthleteRoundType, generateTournamentModeFormEthleteRounds, getClosestOverlay, getColorContrastRatio, getOriginCoordinatesAndDimensions, hexColor, hysteresisRound, iconRegistryKey, indexOfNode, injectAnchoredDialogStrategy, injectAnchoredDialogStrategyDefaults, injectBannerLabels, injectBottomSheetStrategy, injectBottomSheetStrategyDefaults, injectBracketConfig, injectBracketLabels, injectBreadcrumbLabels, injectBreadcrumbManager, injectCalendarLabels, injectCarouselLabels, injectCascaderLabels, injectChipLabels, injectDateFormat, injectDateLocale, injectDateTimeLabels, injectDialogStrategy, injectDialogStrategyDefaults, injectDropzoneLabels, injectFilterOverlay, injectFilterOverlayLabels, injectFormFieldLabels, injectFormSupport, injectFullscreenDialogStrategy, injectFullscreenDialogStrategyDefaults, injectGridConfig, injectGridLabels, injectInputLabels, injectLeftSheetStrategy, injectLeftSheetStrategyDefaults, injectLoaderLabels, injectMatchLabels, injectNotificationLabels, injectNotificationManager, injectNotificationManagerConfig, injectOverlayManager, injectOverlayRouter, injectOverlayScrollBlocker, injectOverlaySurfaceContext, injectPaginationLabels, injectPhoneInputLabels, injectPictureConfig, injectPipChromeManager, injectPipManager, injectPipSlotPlaceholderConfig, injectQueryErrorLabels, injectRichTextEditorLabels, injectRichTextEditorTools, injectRightSheetStrategy, injectRightSheetStrategyDefaults, injectSchedulerEditSurfaceHost, injectSchedulerFeatureHost, injectSchedulerLabels, injectSelectLabels, injectSidebarOverlay, injectSliderLabels, injectStandingsLabels, injectStreamConfig, injectStreamConsentConfig, injectStreamLabels, injectStreamManager, injectStreamPlayerErrorConfig, injectStreamPlayerLoadingConfig, injectStreamScriptLoader, injectStreamUserConsentProvider, injectTableCsvExport, injectTableFeatureHost, injectTableLabels, injectTimeFormat, injectTimePickerLabels, injectTopSheetStrategy, injectTopSheetStrategyDefaults, isFileAccepted, isHtmlElement, isInteractiveElement, isPointerEvent, isTargetInsideOverlayTree, isTouchEvent, itemsCollide, kbdKeyLabel, kbdKeyName, leftSheetOverlayStrategy, legacyQueryErrorSource, mapGridLayout, mapLayoutToBreakpoint, matchCountryByDialCode, matchParticipantDisplayName, mergeOverlayBreakpointConfigs, mergeOverlayConfigs, mirroredDoubleEliminationBracketLayout, mirroredSingleEliminationBracketLayout, mountNavTabLinkStyles, mountRichTextEditorImageStyles, mountRichTextEditorTableStyles, nodesEqual$1 as nodesEqual, normalizeEthleteBracketMatch, normalizeEthleteGroupRanking, normalizeEthleteMatch, normalizeEthleteMatchStatus, normalizeEthleteMedia, normalizeEthleteParticipant, normalizeEthletePlacement, normalizePictureSizes, normalizePictureSource, numberInputStepMultiplierFrom, paginate, parseDuration, parseKbdKeys, phoneCountryFlag, phoneCountryName, pixelRectsEqual, positionToPixelRect, positionsEqual, projectDragCell, provideAnchoredDialogStrategy, provideAnchoredDialogStrategyDefaults, provideBannerLabels, provideBottomSheetStrategy, provideBottomSheetStrategyDefaults, provideBracketConfig, provideBracketLabels, provideBreadcrumbLabels, provideBreadcrumbManager, provideCalendarLabels, provideCarouselLabels, provideCascaderLabels, provideChipLabels, provideDateFormat, provideDateLocale, provideDateTimeLabels, provideDialogStrategy, provideDialogStrategyDefaults, provideDropzoneLabels, provideFilterOverlay, provideFilterOverlayLabels, provideFormErrorMessageResolver, provideFormFieldLabels, provideFormSupport, provideFormWarningMessageResolver, provideFullscreenDialogStrategy, provideFullscreenDialogStrategyDefaults, provideGridConfig, provideGridLabels, provideIconOverrides, provideIcons, provideInputLabels, provideLeftSheetStrategy, provideLeftSheetStrategyDefaults, provideLoaderLabels, provideMatchLabels, provideNotificationLabels, provideNotificationManager, provideNotificationManagerConfig, provideNotificationManagerInstance, provideOverlay, provideOverlayManager, provideOverlayRouter, provideOverlayRouterConfig, provideOverlayRouterService, provideOverlayScrollBlocker, providePaginationLabels, providePhoneInputLabels, providePictureConfig, providePipChromeManager, providePipManager, providePipSlotPlaceholderConfig, provideQueryErrorLabels, provideRichTextEditorAlignmentTool, provideRichTextEditorAutoformat, provideRichTextEditorBlockquoteTool, provideRichTextEditorCodeBlockTool, provideRichTextEditorDefaultTools, provideRichTextEditorFloatingToolbar, provideRichTextEditorHeadingTool, provideRichTextEditorImageTool, provideRichTextEditorLabels, provideRichTextEditorLanguageTool, provideRichTextEditorLinkEditor, provideRichTextEditorLinkTool, provideRichTextEditorTableTool, provideRichTextEditorTokenRendering, provideRichTextEditorTools, provideRightSheetStrategy, provideRightSheetStrategyDefaults, provideSchedulerLabels, provideSelectLabels, provideSidebarOverlay, provideSidebarOverlayConfig, provideSidebarOverlayService, provideSliderLabels, provideStandingsLabels, provideStreamConfig, provideStreamConsentConfig, provideStreamLabels, provideStreamManager, provideStreamPlayerErrorConfig, provideStreamPlayerLoadingConfig, provideTableLabels, provideTimeFormat, provideTimePickerLabels, provideTopSheetStrategy, provideTopSheetStrategyDefaults, queryErrorLabelsForLocale, queryErrorResponseFromLegacyError, reconcileColumnOrder, reconcileColumnWidths, reconcileHiddenColumns, reduceSupportPresentation, registerSingleton, requiredLanguages, resizeSpanBounds, resolveBracketLayout, resolveBreakpoint, resolveClosestOverlay, resolveCollisions, resolveFilterOverlaySubmitButton, resolveNotificationStatusIcon, resolveTableCsvRows, rgbColor, richTextEditorToolLabel, rightSheetOverlayStrategy, rowsToPixelHeight, schedulerFeatureConfig, selectOptionsFromQuery, selectOptionsFromV2Query, serializeGridLayout, serializeTableState, setupRichTextEditorFloatingToolbar, setupRichTextEditorLinkEditor, singleEliminationBracketLayout, snapResizeSpan, sortRows, spanHeight, spanWidth, startFullscreenEnterAnimation, startFullscreenLeaveAnimation, startImageUpload, startOfCalendarUnit, stripTrunkZero, supportPresentationIncludesState, swissBracketLayout, tableCsvRowsFromPages, tableFeatureConfig, tableRowsFromQuery, tableRowsFromV2Query, tableToCsv, toChildrenObservable$1 as toChildrenObservable, toGridPosition, toNotificationContent, toPathObservable, toSearchObservable, topSheetOverlayStrategy, transformingBottomSheetToDialogOverlayStrategy, transformingFullScreenDialogToDialogOverlayStrategy, transformingFullScreenDialogToRightSheetOverlayStrategy, warn, wireFormSupport, withPictureBaseUrl };
66352
67103
  //# sourceMappingURL=ethlete-components.mjs.map