@ethlete/components 0.1.0-next.5 → 0.1.0-next.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { ChangeDetectionStrategy, ViewEncapsulation, Component, Directive, input, booleanAttribute, signal, effect, numberAttribute, computed, inject, ElementRef, InjectionToken, afterNextRender, untracked, DestroyRef, model, viewChild, Injector, output, ApplicationRef, EnvironmentInjector, DOCUMENT, createEnvironmentInjector, createComponent, TemplateRef, linkedSignal, afterRenderEffect, contentChild, inputBinding, PLATFORM_ID, isDevMode, contentChildren } from '@angular/core';
3
3
  import * as i2 from '@ethlete/core';
4
- import { injectStyleManager, createCanAnimateSignal, ColorInteractiveDirective, ProvideColorDirective, RuntimeError, injectErrorTheme, signalElementDimensions, createProvider, AnimatableDirective, ColorInteractiveContainerDirective, ColorInteractiveExcludeDirective, ProvideSurfaceDirective, SURFACE_PROVIDER, injectSurfaceThemes, resolveSurfaceByElevation, ColorInteractiveHasFocusDirective, createStaticRootProvider, signalHostElementDimensions, signalHostStyles, DragHandleDirective, injectRenderer, injectLocale, ResizeHandlesComponent, ANIMATED_LIFECYCLE_TOKEN, injectSurfaceContextTracker, AnimatedLifecycleDirective, createRootProvider, injectOverlayRuntime, typedBreakpointTransform, signalElementChildren, signalElementScrollState, signalElementIntersection, signalHostAttributes, signalHostClasses, getScrollContainerTarget, getScrollItemTarget, getElementScrollCoordinates, provideBreakpointInstance, signalClasses, useCursorDragScroll, signalStyles, getScrollSnapTarget, ScrollObserverDirective, ScrollObserverStartDirective, ScrollObserverEndDirective, injectViewportSize, createFlipAnimation, signalHostElementIntersection, injectHostElement, setInputSignal, SurfaceInteractiveDirective, injectRouterEvent, canUseSessionMemory, createAutoSessionMemoryKey, createSessionMemory, COLOR_PROVIDER, injectFocusVisibleTracker } from '@ethlete/core';
4
+ import { injectStyleManager, createCanAnimateSignal, ColorInteractiveDirective, ProvideColorDirective, RuntimeError, injectErrorTheme, signalElementDimensions, createProvider, AnimatableDirective, ColorInteractiveContainerDirective, ColorInteractiveExcludeDirective, ProvideSurfaceDirective, SURFACE_PROVIDER, injectSurfaceThemes, resolveSurfaceByElevation, ColorInteractiveHasFocusDirective, createStaticRootProvider, signalHostElementDimensions, DragHandleDirective, injectRenderer, injectLocale, ResizeHandlesComponent, ANIMATED_LIFECYCLE_TOKEN, injectSurfaceContextTracker, AnimatedLifecycleDirective, createRootProvider, injectOverlayRuntime, typedBreakpointTransform, signalElementChildren, signalElementScrollState, signalElementIntersection, signalHostAttributes, signalHostClasses, signalHostStyles, getScrollContainerTarget, getScrollItemTarget, getElementScrollCoordinates, provideBreakpointInstance, signalClasses, useCursorDragScroll, signalStyles, getScrollSnapTarget, ScrollObserverDirective, ScrollObserverStartDirective, ScrollObserverEndDirective, injectViewportSize, createFlipAnimation, signalHostElementIntersection, injectHostElement, setInputSignal, SurfaceInteractiveDirective, injectRouterEvent, canUseSessionMemory, createAutoSessionMemoryKey, createSessionMemory, COLOR_PROVIDER, injectFocusVisibleTracker } from '@ethlete/core';
5
5
  import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
6
6
  import { toObservable, takeUntilDestroyed, outputToObservable, outputFromObservable, rxResource } from '@angular/core/rxjs-interop';
7
- import { switchMap, EMPTY, filter, tap, take, of, timer, animationFrameScheduler, Subject, fromEvent, debounceTime, map, exhaustMap, takeUntil, finalize, distinctUntilChanged, Observable, shareReplay, catchError, interval } from 'rxjs';
7
+ import { switchMap, EMPTY, filter, tap, timer, take, of, animationFrameScheduler, Subject, fromEvent, debounceTime, map, exhaustMap, takeUntil, finalize, distinctUntilChanged, Observable, shareReplay, catchError, interval } from 'rxjs';
8
+ import { tap as tap$1 } from 'rxjs/operators';
8
9
  import { DomSanitizer } from '@angular/platform-browser';
9
10
  import * as i1 from '@angular/router';
10
11
  import { RouterLinkActive, NavigationEnd, RouterLink } from '@angular/router';
@@ -2384,14 +2385,38 @@ const itemsCollide = (a, b) => {
2384
2385
  * Returns the first item that collides with the given position, or undefined if none.
2385
2386
  */
2386
2387
  const findCollision = (options) => options.entries.find((entry) => entry.id !== options.excludeId && itemsCollide(entry.position, options.position));
2388
+ /**
2389
+ * Clamps a position so it fits horizontally within the given column count.
2390
+ * Reduces an over-wide span and slides an out-of-bounds column back in range.
2391
+ */
2392
+ const clampToColumns = (position, columns) => {
2393
+ const colSpan = Math.max(1, Math.min(position.colSpan, columns));
2394
+ const col = Math.max(0, Math.min(position.col, columns - colSpan));
2395
+ return { ...position, col, colSpan };
2396
+ };
2387
2397
  /**
2388
2398
  * Compacts the layout vertically (moves items up as far as possible without collision).
2399
+ *
2400
+ * Also acts as a self-healing normaliser: positions that overflow the grid horizontally
2401
+ * (e.g. stale data from a wider breakpoint clamped into a narrower one — a colSpan of 12
2402
+ * or a col of 8 in a 6-column grid) are first clamped back into bounds, then any items
2403
+ * left overlapping are pushed down before the upward compaction runs. This guarantees the
2404
+ * returned layout is always in-bounds and overlap-free regardless of the input — clamping
2405
+ * a column alone is not enough, because it can drop an item on top of an existing one.
2389
2406
  */
2390
- const compactLayout = (entries, _columns) => {
2391
- const sorted = [...entries].sort((a, b) => a.position.row - b.position.row || a.position.col - b.position.col);
2407
+ const compactLayout = (entries, columns) => {
2408
+ const sorted = [...entries]
2409
+ .map((entry) => ({ ...entry, position: clampToColumns(entry.position, columns) }))
2410
+ .sort((a, b) => a.position.row - b.position.row || a.position.col - b.position.col);
2392
2411
  const compacted = [];
2393
2412
  for (const entry of sorted) {
2394
2413
  const candidate = { ...entry, position: { ...entry.position } };
2414
+ // Push down past any already-placed item it overlaps. This resolves overlaps introduced
2415
+ // by clamping out-of-bounds columns (which the upward pass below cannot fix on its own).
2416
+ while (findCollision({ entries: compacted, position: candidate.position, excludeId: candidate.id })) {
2417
+ candidate.position.row += 1;
2418
+ }
2419
+ // Then pull up as far as possible without colliding.
2395
2420
  while (candidate.position.row > 0) {
2396
2421
  const moved = { ...candidate, position: { ...candidate.position, row: candidate.position.row - 1 } };
2397
2422
  if (findCollision({ entries: compacted, position: moved.position, excludeId: candidate.id })) {
@@ -2620,6 +2645,17 @@ const deserializeGridLayout = (state, breakpointMinWidths) => {
2620
2645
  return { breakpoints, items, rowHeight: state.rowHeight };
2621
2646
  };
2622
2647
 
2648
+ const positionsEqual = (a, b) => a.col === b.col && a.row === b.row && a.colSpan === b.colSpan && a.rowSpan === b.rowSpan;
2649
+ const layoutsEqual = (a, b) => {
2650
+ const aKeys = Object.keys(a);
2651
+ if (aKeys.length !== Object.keys(b).length)
2652
+ return false;
2653
+ return aKeys.every((k) => {
2654
+ const ap = a[k];
2655
+ const bp = b[k];
2656
+ return ap !== undefined && bp !== undefined && positionsEqual(ap, bp);
2657
+ });
2658
+ };
2623
2659
  const DEFAULT_CONSTRAINTS = {
2624
2660
  minColSpan: 1,
2625
2661
  maxColSpan: 12,
@@ -2719,14 +2755,41 @@ class GridDirective {
2719
2755
  this.itemConfigs.set(initial);
2720
2756
  return;
2721
2757
  }
2722
- const currentIds = new Set(current.map((c) => c.id));
2723
- const newItems = initial.filter((item) => !currentIds.has(item.id));
2758
+ const currentById = new Map(current.map((c) => [c.id, c]));
2759
+ const initialIds = new Set(initial.map((i) => i.id));
2760
+ const newItems = initial.filter((item) => !currentById.has(item.id));
2761
+ const removedIds = current.filter((c) => !initialIds.has(c.id)).map((c) => c.id);
2762
+ // Pure layout update — same item set but positions changed (e.g. the host
2763
+ // reset its signal to a saved snapshot after the user cancelled edits).
2764
+ // A structural add/remove takes precedence and is handled below.
2765
+ if (newItems.length === 0 && removedIds.length === 0) {
2766
+ const anyLayoutChanged = initial.some((incoming) => {
2767
+ const existing = currentById.get(incoming.id);
2768
+ return existing && !layoutsEqual(existing.layout, incoming.layout);
2769
+ });
2770
+ if (anyLayoutChanged) {
2771
+ // Restore itemConfigs from the incoming snapshot.
2772
+ this.itemConfigs.set(initial);
2773
+ // Rebuild layoutOverrides for every breakpoint that has already been
2774
+ // visited so the grid renders the restored positions immediately without
2775
+ // waiting for a breakpoint switch.
2776
+ const visitedBps = Object.keys(this.layoutOverrides());
2777
+ if (visitedBps.length > 0) {
2778
+ const restored = {};
2779
+ for (const bp of visitedBps) {
2780
+ restored[bp] = initial.map((item) => ({
2781
+ id: item.id,
2782
+ position: item.layout[bp] ?? { col: 0, row: 0, colSpan: 1, rowSpan: 1 },
2783
+ }));
2784
+ }
2785
+ this.layoutOverrides.set(restored);
2786
+ }
2787
+ }
2788
+ return;
2789
+ }
2724
2790
  for (const item of newItems) {
2725
2791
  this.placeItem(item);
2726
2792
  }
2727
- // Remove items no longer in initial
2728
- const initialIds = new Set(initial.map((i) => i.id));
2729
- const removedIds = current.filter((c) => !initialIds.has(c.id)).map((c) => c.id);
2730
2793
  for (const id of removedIds) {
2731
2794
  this.removeItem(id);
2732
2795
  }
@@ -2799,27 +2862,33 @@ class GridDirective {
2799
2862
  // On first registration the item may have been auto-placed with 1×1 defaults
2800
2863
  // (because addItem runs before the GridItemDirective initialises). If so,
2801
2864
  // re-place it now at the correct minimum size.
2802
- const breakpoint = this.activeBreakpoint();
2803
- const existing = this.layoutOverrides()[breakpoint];
2804
- if (!existing)
2805
- return;
2806
- const entry = existing.find((e) => e.id === id);
2807
- if (!entry)
2808
- return;
2809
- const pos = entry.position;
2810
- if (pos.colSpan >= constraints.minColSpan && pos.rowSpan >= constraints.minRowSpan)
2811
- return;
2812
- const cols = this.activeColumns();
2813
- const others = existing.filter((e) => e.id !== id);
2814
- const newPosition = autoPlace({
2815
- entries: others,
2816
- colSpan: Math.max(pos.colSpan, constraints.minColSpan),
2817
- rowSpan: Math.max(pos.rowSpan, constraints.minRowSpan),
2818
- columns: cols,
2865
+ // All signal reads are wrapped in untracked() to prevent this method from
2866
+ // inadvertently becoming a dependency of the caller's reactive context
2867
+ // (e.g. GridItemDirective's registration effect), which would cause the
2868
+ // layoutOverrides.update() write below to re-trigger that effect in a loop.
2869
+ untracked(() => {
2870
+ const breakpoint = this.activeBreakpoint();
2871
+ const existing = this.layoutOverrides()[breakpoint];
2872
+ if (!existing)
2873
+ return;
2874
+ const entry = existing.find((e) => e.id === id);
2875
+ if (!entry)
2876
+ return;
2877
+ const pos = entry.position;
2878
+ if (pos.colSpan >= constraints.minColSpan && pos.rowSpan >= constraints.minRowSpan)
2879
+ return;
2880
+ const cols = this.activeColumns();
2881
+ const others = existing.filter((e) => e.id !== id);
2882
+ const newPosition = autoPlace({
2883
+ entries: others,
2884
+ colSpan: Math.max(pos.colSpan, constraints.minColSpan),
2885
+ rowSpan: Math.max(pos.rowSpan, constraints.minRowSpan),
2886
+ columns: cols,
2887
+ });
2888
+ const updated = existing.map((e) => (e.id === id ? { ...e, position: newPosition } : e));
2889
+ const compacted = compactLayout(updated, cols);
2890
+ this.layoutOverrides.update((prev) => ({ ...prev, [breakpoint]: compacted }));
2819
2891
  });
2820
- const updated = existing.map((e) => (e.id === id ? { ...e, position: newPosition } : e));
2821
- const compacted = compactLayout(updated, cols);
2822
- this.layoutOverrides.update((prev) => ({ ...prev, [breakpoint]: compacted }));
2823
2892
  }
2824
2893
  registerItem(id, options) {
2825
2894
  this.itemElements.set(id, options.el);
@@ -2960,6 +3029,7 @@ class GridDirective {
2960
3029
  const currentLayout = this.baseLayout().filter((e) => e.id !== id);
2961
3030
  const compacted = compactLayout(currentLayout, columns);
2962
3031
  this.updateLayoutForCurrentBreakpoint(compacted);
3032
+ this.compactOtherBreakpoints(id);
2963
3033
  this.emitLayoutChange();
2964
3034
  this.animateLayoutTransition({ excludeIds: new Set([id]) });
2965
3035
  };
@@ -2970,6 +3040,7 @@ class GridDirective {
2970
3040
  const currentLayout = this.baseLayout().filter((e) => e.id !== id);
2971
3041
  const compacted = compactLayout(currentLayout, columns);
2972
3042
  this.updateLayoutForCurrentBreakpoint(compacted);
3043
+ this.compactOtherBreakpoints(id);
2973
3044
  this.emitLayoutChange();
2974
3045
  }
2975
3046
  }
@@ -3022,8 +3093,22 @@ class GridDirective {
3022
3093
  this.resizeBaseLayout.set(null);
3023
3094
  }
3024
3095
  getSerializedState() {
3096
+ const overrides = this.layoutOverrides();
3097
+ // layoutOverrides is the authoritative source for any breakpoint that has been visited.
3098
+ // itemConfigs.layout[bp] lags behind for breakpoints that haven't been written back
3099
+ // yet (e.g. items pushed by moveItem/resizeItem collision resolution, or items whose
3100
+ // non-current-breakpoint positions haven't been visited since the last change).
3101
+ const items = this.itemConfigs().map((item) => {
3102
+ const layout = { ...item.layout };
3103
+ for (const [bp, entries] of Object.entries(overrides)) {
3104
+ const entry = entries.find((e) => e.id === item.id);
3105
+ if (entry)
3106
+ layout[bp] = entry.position;
3107
+ }
3108
+ return { ...item, layout };
3109
+ });
3025
3110
  return serializeGridLayout({
3026
- items: this.itemConfigs(),
3111
+ items,
3027
3112
  breakpoints: this.breakpoints(),
3028
3113
  rowHeight: this.rowHeight(),
3029
3114
  });
@@ -3052,24 +3137,45 @@ class GridDirective {
3052
3137
  this.layoutOverrides.set(overrides);
3053
3138
  }
3054
3139
  placeItem(config) {
3055
- const breakpoint = this.activeBreakpoint();
3140
+ const activeBp = this.activeBreakpoint();
3056
3141
  const columns = this.activeColumns();
3057
3142
  const currentLayout = this.baseLayout();
3058
3143
  const constraints = this.getConstraints(config.id);
3059
- const position = config.layout[breakpoint] ??
3144
+ const allBreakpoints = this.breakpoints();
3145
+ const overrides = this.layoutOverrides();
3146
+ const existingItems = this.itemConfigs();
3147
+ // Start from any layouts already in the config (e.g. when re-adding from API data).
3148
+ const layout = { ...config.layout };
3149
+ // Place on the active breakpoint first so other breakpoints can use it as a reference.
3150
+ const position = layout[activeBp] ??
3060
3151
  autoPlace({
3061
3152
  entries: currentLayout,
3062
3153
  colSpan: constraints.minColSpan,
3063
3154
  rowSpan: constraints.minRowSpan,
3064
3155
  columns,
3065
3156
  });
3066
- const itemWithLayout = {
3067
- ...config,
3068
- layout: {
3069
- ...config.layout,
3070
- [breakpoint]: position,
3071
- },
3072
- };
3157
+ layout[activeBp] = position;
3158
+ // Auto-place on every other breakpoint that has no position yet.
3159
+ // This ensures the emitted layoutChange always carries all breakpoints so
3160
+ // the host's gridItems signal never loses sm/md positions for new items.
3161
+ for (const bp of allBreakpoints) {
3162
+ if (bp.name === activeBp || layout[bp.name])
3163
+ continue;
3164
+ // Effective layout for this breakpoint: prefer layoutOverrides (already visited),
3165
+ // fall back to itemConfigs.layout[bp] (original API positions).
3166
+ const bpEntries = overrides[bp.name] ??
3167
+ existingItems.map((item) => ({
3168
+ id: item.id,
3169
+ position: item.layout[bp.name] ?? { col: 0, row: 0, colSpan: 1, rowSpan: 1 },
3170
+ }));
3171
+ layout[bp.name] = autoPlace({
3172
+ entries: bpEntries,
3173
+ colSpan: Math.min(constraints.minColSpan, bp.columns),
3174
+ rowSpan: constraints.minRowSpan,
3175
+ columns: bp.columns,
3176
+ });
3177
+ }
3178
+ const itemWithLayout = { ...config, layout };
3073
3179
  this.itemConfigs.update((items) => [...items, itemWithLayout]);
3074
3180
  this.updateLayoutForCurrentBreakpoint([...currentLayout, { id: config.id, position }]);
3075
3181
  this.emitLayoutChange();
@@ -3153,6 +3259,19 @@ class GridDirective {
3153
3259
  return collides ? original : entry;
3154
3260
  });
3155
3261
  }
3262
+ /** Compact all visited breakpoints (layoutOverrides entries) after an item is removed. */
3263
+ compactOtherBreakpoints(removedId) {
3264
+ const activeBp = this.activeBreakpoint();
3265
+ const bpColumns = new Map(this.breakpoints().map((b) => [b.name, b.columns]));
3266
+ for (const [bp, entries] of Object.entries(this.layoutOverrides())) {
3267
+ if (bp === activeBp)
3268
+ continue;
3269
+ const withoutItem = entries.filter((e) => e.id !== removedId);
3270
+ const cols = bpColumns.get(bp) ?? 1;
3271
+ const compacted = compactLayout(withoutItem, cols);
3272
+ this.layoutOverrides.update((prev) => ({ ...prev, [bp]: compacted }));
3273
+ }
3274
+ }
3156
3275
  updateLayoutForCurrentBreakpoint(entries) {
3157
3276
  const breakpoint = this.activeBreakpoint();
3158
3277
  this.layoutOverrides.update((prev) => ({ ...prev, [breakpoint]: entries }));
@@ -3207,10 +3326,8 @@ class GridItemDirective {
3207
3326
  this.currentRow = computed(() => this.renderPosition()?.row ?? 0, ...(ngDevMode ? [{ debugName: "currentRow" }] : /* istanbul ignore next */ []));
3208
3327
  this.currentColSpan = computed(() => this.renderPosition()?.colSpan ?? 1, ...(ngDevMode ? [{ debugName: "currentColSpan" }] : /* istanbul ignore next */ []));
3209
3328
  this.currentRowSpan = computed(() => this.renderPosition()?.rowSpan ?? 1, ...(ngDevMode ? [{ debugName: "currentRowSpan" }] : /* istanbul ignore next */ []));
3210
- this.hostStyles = signalHostStyles({
3211
- 'grid-column': computed(() => `${this.currentCol() + 1} / span ${this.currentColSpan()}`),
3212
- 'grid-row': computed(() => `${this.currentRow() + 1} / span ${this.currentRowSpan()}`),
3213
- });
3329
+ this.gridColumn = computed(() => `${this.currentCol() + 1} / span ${this.currentColSpan()}`, ...(ngDevMode ? [{ debugName: "gridColumn" }] : /* istanbul ignore next */ []));
3330
+ this.gridRow = computed(() => `${this.currentRow() + 1} / span ${this.currentRowSpan()}`, ...(ngDevMode ? [{ debugName: "gridRow" }] : /* istanbul ignore next */ []));
3214
3331
  effect((onCleanup) => {
3215
3332
  const id = this.itemId();
3216
3333
  const el = this.hostElement.nativeElement;
@@ -3241,7 +3358,7 @@ class GridItemDirective {
3241
3358
  });
3242
3359
  }
3243
3360
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3244
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: GridItemDirective, isStandalone: true, selector: "[etGridItem]", inputs: { itemId: { classPropertyName: "itemId", publicName: "itemId", isSignal: true, isRequired: true, transformFunction: null }, minColSpan: { classPropertyName: "minColSpan", publicName: "minColSpan", isSignal: true, isRequired: false, transformFunction: null }, maxColSpan: { classPropertyName: "maxColSpan", publicName: "maxColSpan", isSignal: true, isRequired: false, transformFunction: null }, minRowSpan: { classPropertyName: "minRowSpan", publicName: "minRowSpan", isSignal: true, isRequired: false, transformFunction: null }, maxRowSpan: { classPropertyName: "maxRowSpan", publicName: "maxRowSpan", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "et-grid-item" }, exportAs: ["etGridItem"], ngImport: i0 }); }
3361
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: GridItemDirective, isStandalone: true, selector: "[etGridItem]", inputs: { itemId: { classPropertyName: "itemId", publicName: "itemId", isSignal: true, isRequired: true, transformFunction: null }, minColSpan: { classPropertyName: "minColSpan", publicName: "minColSpan", isSignal: true, isRequired: false, transformFunction: null }, maxColSpan: { classPropertyName: "maxColSpan", publicName: "maxColSpan", isSignal: true, isRequired: false, transformFunction: null }, minRowSpan: { classPropertyName: "minRowSpan", publicName: "minRowSpan", isSignal: true, isRequired: false, transformFunction: null }, maxRowSpan: { classPropertyName: "maxRowSpan", publicName: "maxRowSpan", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.grid-column": "gridColumn()", "style.grid-row": "gridRow()" }, classAttribute: "et-grid-item" }, exportAs: ["etGridItem"], ngImport: i0 }); }
3245
3362
  }
3246
3363
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridItemDirective, decorators: [{
3247
3364
  type: Directive,
@@ -3250,6 +3367,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
3250
3367
  exportAs: 'etGridItem',
3251
3368
  host: {
3252
3369
  class: 'et-grid-item',
3370
+ '[style.grid-column]': 'gridColumn()',
3371
+ '[style.grid-row]': 'gridRow()',
3253
3372
  },
3254
3373
  }]
3255
3374
  }], ctorParameters: () => [], propDecorators: { itemId: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemId", required: true }] }], minColSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "minColSpan", required: false }] }], maxColSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxColSpan", required: false }] }], minRowSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRowSpan", required: false }] }], maxRowSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRowSpan", required: false }] }] } });
@@ -3264,12 +3383,10 @@ class GridDragDirective {
3264
3383
  this.renderer = injectRenderer();
3265
3384
  this.dragStartClient = signal(null, ...(ngDevMode ? [{ debugName: "dragStartClient" }] : /* istanbul ignore next */ []));
3266
3385
  this.dragPixelOffset = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "dragPixelOffset" }] : /* istanbul ignore next */ []));
3267
- this.hostStyles = signalHostStyles({
3268
- transform: computed(() => {
3269
- const offset = this.dragPixelOffset();
3270
- return `translate(${offset.x}px, ${offset.y}px)`;
3271
- }),
3272
- });
3386
+ this.dragTransform = computed(() => {
3387
+ const offset = this.dragPixelOffset();
3388
+ return `translate(${offset.x}px, ${offset.y}px)`;
3389
+ }, ...(ngDevMode ? [{ debugName: "dragTransform" }] : /* istanbul ignore next */ []));
3273
3390
  outputToObservable(this.dragHandle.dragStarted)
3274
3391
  .pipe(filter(() => !this.grid.readOnly()), tap(() => {
3275
3392
  this.dragPixelOffset.set({ x: 0, y: 0 });
@@ -3383,7 +3500,7 @@ class GridDragDirective {
3383
3500
  this.renderer.removeStyles(el, 'position', 'left', 'top', 'width', 'height');
3384
3501
  }
3385
3502
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridDragDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3386
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: GridDragDirective, isStandalone: true, selector: "[etGridDrag]", host: { properties: { "class.et-grid-drag--active": "!grid.readOnly() && dragHandle.isDragging()", "attr.aria-grabbed": "!grid.readOnly() && dragHandle.isDragging()" }, classAttribute: "et-grid-drag" }, hostDirectives: [{ directive: i2.DragHandleDirective, outputs: ["dragStarted", "dragStarted", "dragMoved", "dragMoved", "dragEnded", "dragEnded"] }], ngImport: i0 }); }
3503
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.13", type: GridDragDirective, isStandalone: true, selector: "[etGridDrag]", host: { properties: { "class.et-grid-drag--active": "!grid.readOnly() && dragHandle.isDragging()", "attr.aria-grabbed": "!grid.readOnly() && dragHandle.isDragging()", "style.transform": "dragTransform()" }, classAttribute: "et-grid-drag" }, hostDirectives: [{ directive: i2.DragHandleDirective, outputs: ["dragStarted", "dragStarted", "dragMoved", "dragMoved", "dragEnded", "dragEnded"] }], ngImport: i0 }); }
3387
3504
  }
3388
3505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridDragDirective, decorators: [{
3389
3506
  type: Directive,
@@ -3399,6 +3516,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
3399
3516
  class: 'et-grid-drag',
3400
3517
  '[class.et-grid-drag--active]': '!grid.readOnly() && dragHandle.isDragging()',
3401
3518
  '[attr.aria-grabbed]': '!grid.readOnly() && dragHandle.isDragging()',
3519
+ '[style.transform]': 'dragTransform()',
3402
3520
  },
3403
3521
  }]
3404
3522
  }], ctorParameters: () => [] });
@@ -3528,17 +3646,15 @@ class GridComponent {
3528
3646
  const label = this.grid.readOnly() ? this.gridConfig.readonlyAriaLabel : this.gridConfig.interactiveAriaLabel;
3529
3647
  return this.gridConfig.transformer(label, this.locale.currentLocale());
3530
3648
  }, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
3531
- this.hostStyles = signalHostStyles({
3532
- '--_et-grid-columns': computed(() => `${this.grid.activeColumns()}`),
3533
- '--et-grid-gap': computed(() => `${this.grid.gap()}px`),
3534
- '--et-grid-row-height': computed(() => `${this.grid.rowHeight()}px`),
3535
- });
3649
+ this.gridColumns = computed(() => this.grid.activeColumns(), ...(ngDevMode ? [{ debugName: "gridColumns" }] : /* istanbul ignore next */ []));
3650
+ this.gridGap = computed(() => `${this.grid.gap()}px`, ...(ngDevMode ? [{ debugName: "gridGap" }] : /* istanbul ignore next */ []));
3651
+ this.gridRowHeight = computed(() => `${this.grid.rowHeight()}px`, ...(ngDevMode ? [{ debugName: "gridRowHeight" }] : /* istanbul ignore next */ []));
3536
3652
  effect(() => {
3537
3653
  this.grid.setGhostElement(this.ghostRef()?.nativeElement ?? null);
3538
3654
  });
3539
3655
  }
3540
3656
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3541
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: GridComponent, isStandalone: true, selector: "et-grid, [et-grid]", host: { attributes: { "role": "region" }, properties: { "attr.aria-label": "ariaLabel()" }, classAttribute: "et-grid" }, viewQueries: [{ propertyName: "ghostRef", first: true, predicate: ["ghostRef"], descendants: true, isSignal: true }], hostDirectives: [{ directive: GridDirective, inputs: ["breakpoints", "breakpoints", "rowHeight", "rowHeight", "gap", "gap", "initialItems", "initialItems", "readOnly", "readOnly"], outputs: ["layoutChange", "layoutChange"] }], ngImport: i0, template: `
3657
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: GridComponent, isStandalone: true, selector: "et-grid, [et-grid]", host: { attributes: { "role": "region" }, properties: { "attr.aria-label": "ariaLabel()", "style.--_et-grid-columns": "gridColumns()", "style.--et-grid-gap": "gridGap()", "style.--et-grid-row-height": "gridRowHeight()" }, classAttribute: "et-grid" }, viewQueries: [{ propertyName: "ghostRef", first: true, predicate: ["ghostRef"], descendants: true, isSignal: true }], hostDirectives: [{ directive: GridDirective, inputs: ["breakpoints", "breakpoints", "rowHeight", "rowHeight", "gap", "gap", "initialItems", "initialItems", "readOnly", "readOnly"], outputs: ["layoutChange", "layoutChange"] }], ngImport: i0, template: `
3542
3658
  <ng-content />
3543
3659
  @if (grid.ghostPosition(); as ghost) {
3544
3660
  <div
@@ -3572,6 +3688,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
3572
3688
  class: 'et-grid',
3573
3689
  role: 'region',
3574
3690
  '[attr.aria-label]': 'ariaLabel()',
3691
+ '[style.--_et-grid-columns]': 'gridColumns()',
3692
+ '[style.--et-grid-gap]': 'gridGap()',
3693
+ '[style.--et-grid-row-height]': 'gridRowHeight()',
3575
3694
  }, styles: ["@property --et-grid-gap{syntax: \"<length>\"; inherits: false; initial-value: 16px;}@property --et-grid-row-height{syntax: \"<length>\"; inherits: false; initial-value: 100px;}@property --et-grid-padding{syntax: \"<length>\"; inherits: false; initial-value: 0px;}.et-grid{display:grid;grid-template-columns:repeat(var(--_et-grid-columns, 12),1fr);grid-auto-rows:var(--et-grid-row-height);gap:var(--et-grid-gap);padding:var(--et-grid-padding);position:relative;min-height:0}.et-grid:has(.et-grid-item--dragging,.et-grid-item--resizing){-webkit-user-select:none;user-select:none;cursor:grabbing}.et-grid:has(.et-grid-item--resizing){cursor:nwse-resize}.et-grid-ghost{border-radius:8px;background:rgb(var(--et-surface-color, 23 23 23) / .08);border:2px dashed rgb(var(--et-surface-color, 23 23 23) / .2);pointer-events:none;transition:grid-column 0s,grid-row 0s}.et-grid--readonly .et-grid-item__drag-handle{cursor:default;pointer-events:none}.et-grid--readonly .et-grid-item__actions{display:none}.et-grid--readonly .et-grid-item:hover .et-resize-handle--e:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--s:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--w:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--n:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--se:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--sw:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--ne:after,.et-grid--readonly .et-grid-item:hover .et-resize-handle--nw:after{content:unset}\n"] }]
3576
3695
  }], ctorParameters: () => [], propDecorators: { ghostRef: [{ type: i0.ViewChild, args: ['ghostRef', { isSignal: true }] }] } });
3577
3696
 
@@ -3714,6 +3833,326 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
3714
3833
  }, styles: ["@property --et-grid-item-border-radius{syntax: \"<length>\"; inherits: false; initial-value: 8px;}@property --et-grid-item-bg{syntax: \"<color>\"; inherits: false; initial-value: rgb(var(--et-surface-background, 255 255 255));}@property --et-grid-item-shadow{syntax: \"*\"; inherits: false; initial-value: 0 1px 3px rgba(0,0,0,.12);}@property --et-grid-item-drag-handle-height{syntax: \"<length>\"; inherits: false; initial-value: 32px;}.et-grid-item{position:relative;border-radius:var(--et-grid-item-border-radius);background:var(--et-grid-item-bg);box-shadow:var(--et-grid-item-shadow);border:1px solid rgb(var(--et-surface-border, 229 229 229));color:rgb(var(--et-surface-color, 23 23 23));overflow:hidden;display:flex;flex-direction:column;outline:none;will-change:transform}.et-grid-item:focus-visible{box-shadow:0 0 0 2px var(--et-grid-item-focus-ring-color, #2563eb)}.et-grid-item:is(.et-grid-item--dragging){z-index:100;box-shadow:0 12px 32px #0003;opacity:.95;cursor:grabbing;-webkit-user-select:none;user-select:none}.et-grid-item:is(.et-grid-item--resizing){z-index:100;-webkit-user-select:none;user-select:none}.et-grid-item:hover .et-resize-handle--e:after,.et-grid-item:hover .et-resize-handle--s:after,.et-grid-item:hover .et-resize-handle--w:after,.et-grid-item:hover .et-resize-handle--n:after,.et-grid-item:hover .et-resize-handle--se:after,.et-grid-item:hover .et-resize-handle--sw:after,.et-grid-item:hover .et-resize-handle--ne:after,.et-grid-item:hover .et-resize-handle--nw:after,.et-grid-item--resizing .et-resize-handle--e:after,.et-grid-item--resizing .et-resize-handle--s:after,.et-grid-item--resizing .et-resize-handle--w:after,.et-grid-item--resizing .et-resize-handle--n:after,.et-grid-item--resizing .et-resize-handle--se:after,.et-grid-item--resizing .et-resize-handle--sw:after,.et-grid-item--resizing .et-resize-handle--ne:after,.et-grid-item--resizing .et-resize-handle--nw:after{content:\"\";position:absolute;border-radius:2px;background:rgb(var(--et-surface-color, 23 23 23) / .2);transition:opacity .15s ease}.et-grid-item:hover .et-resize-handle--e:after,.et-grid-item--resizing .et-resize-handle--e:after{right:2px;top:50%;transform:translateY(-50%);width:3px;height:24px}.et-grid-item:hover .et-resize-handle--w:after,.et-grid-item--resizing .et-resize-handle--w:after{left:2px;top:50%;transform:translateY(-50%);width:3px;height:24px}.et-grid-item:hover .et-resize-handle--s:after,.et-grid-item--resizing .et-resize-handle--s:after{bottom:2px;left:50%;transform:translate(-50%);height:3px;width:24px}.et-grid-item:hover .et-resize-handle--n:after,.et-grid-item--resizing .et-resize-handle--n:after{top:2px;left:50%;transform:translate(-50%);height:3px;width:24px}.et-grid-item:hover .et-resize-handle--se:after,.et-grid-item--resizing .et-resize-handle--se:after{bottom:3px;right:3px;width:8px;height:8px;border-radius:1px}.et-grid-item:hover .et-resize-handle--sw:after,.et-grid-item--resizing .et-resize-handle--sw:after{bottom:3px;left:3px;width:8px;height:8px;border-radius:1px}.et-grid-item:hover .et-resize-handle--ne:after,.et-grid-item--resizing .et-resize-handle--ne:after{top:3px;right:3px;width:8px;height:8px;border-radius:1px}.et-grid-item:hover .et-resize-handle--nw:after,.et-grid-item--resizing .et-resize-handle--nw:after{top:3px;left:3px;width:8px;height:8px;border-radius:1px}.et-grid-item__drag-handle{height:var(--et-grid-item-drag-handle-height);cursor:grab;display:flex;align-items:center;padding-inline:8px;-webkit-user-select:none;user-select:none;touch-action:none}.et-grid-item--dragging .et-grid-item__drag-handle{cursor:grabbing}.et-grid-item__content{flex:1;overflow:hidden;min-height:0}.et-grid-item__actions{position:absolute;top:4px;right:4px;display:flex;gap:4px}\n"] }]
3715
3834
  }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }] } });
3716
3835
 
3836
+ const posEq = (a, b) => {
3837
+ if (!a && !b)
3838
+ return true;
3839
+ if (!a || !b)
3840
+ return false;
3841
+ return a.col === b.col && a.row === b.row && a.colSpan === b.colSpan && a.rowSpan === b.rowSpan;
3842
+ };
3843
+ /**
3844
+ * Development-only debug overlay for an `et-grid` instance.
3845
+ *
3846
+ * ```html
3847
+ * <et-grid #myGrid [initialItems]="items()" ...></et-grid>
3848
+ * <et-grid-debug [grid]="myGrid" [externalItems]="items()" />
3849
+ * ```
3850
+ *
3851
+ * Pass `externalItems` to detect divergence between the host signal
3852
+ * and the grid's internal itemConfigs. The **Copy JSON** button writes
3853
+ * a full diagnostic snapshot to the clipboard without any console output.
3854
+ */
3855
+ class GridDebugComponent {
3856
+ constructor() {
3857
+ this.destroyRef = inject(DestroyRef);
3858
+ this.grid = input.required(...(ngDevMode ? [{ debugName: "grid" }] : /* istanbul ignore next */ []));
3859
+ this.externalItems = input(null, ...(ngDevMode ? [{ debugName: "externalItems" }] : /* istanbul ignore next */ []));
3860
+ this.activeBreakpoint = computed(() => this.grid().grid.activeBreakpoint(), ...(ngDevMode ? [{ debugName: "activeBreakpoint" }] : /* istanbul ignore next */ []));
3861
+ this.containerWidth = computed(() => this.grid().grid.containerWidth(), ...(ngDevMode ? [{ debugName: "containerWidth" }] : /* istanbul ignore next */ []));
3862
+ this.breakpoints = computed(() => this.grid().grid.breakpoints(), ...(ngDevMode ? [{ debugName: "breakpoints" }] : /* istanbul ignore next */ []));
3863
+ this.items = computed(() => this.grid().grid.items(), ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
3864
+ this.layout = computed(() => this.grid().grid.layout(), ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
3865
+ this.hasDrag = computed(() => this.grid().grid.dragState() !== null, ...(ngDevMode ? [{ debugName: "hasDrag" }] : /* istanbul ignore next */ []));
3866
+ this.hasExternal = computed(() => this.externalItems() !== null, ...(ngDevMode ? [{ debugName: "hasExternal" }] : /* istanbul ignore next */ []));
3867
+ this.copied = signal(false, ...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
3868
+ this.rows = computed(() => {
3869
+ const bps = this.breakpoints().map((b) => b.name);
3870
+ const internalItems = this.items();
3871
+ const external = this.externalItems();
3872
+ const extById = external ? new Map(external.map((i) => [i.id, i])) : null;
3873
+ return internalItems.map((item) => ({
3874
+ id: item.id,
3875
+ type: item.type,
3876
+ cells: bps.map((bp) => {
3877
+ const int = item.layout[bp];
3878
+ const ext = extById?.get(item.id)?.layout[bp];
3879
+ return {
3880
+ bp,
3881
+ int,
3882
+ ext,
3883
+ intMissing: !int,
3884
+ extMissing: extById !== null && !ext,
3885
+ mismatch: extById !== null && !posEq(int, ext),
3886
+ };
3887
+ }),
3888
+ }));
3889
+ }, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
3890
+ this.issueCount = computed(() => this.rows().reduce((n, row) => n + row.cells.filter((c) => c.intMissing || c.mismatch).length, 0), ...(ngDevMode ? [{ debugName: "issueCount" }] : /* istanbul ignore next */ []));
3891
+ }
3892
+ fmtPos(pos) {
3893
+ return pos ? `(${pos.col},${pos.row}) ${pos.colSpan}×${pos.rowSpan}` : '—';
3894
+ }
3895
+ copyJson($event) {
3896
+ $event.stopPropagation();
3897
+ const issues = [];
3898
+ for (const row of this.rows()) {
3899
+ for (const cell of row.cells) {
3900
+ if (cell.intMissing)
3901
+ issues.push({ type: 'missing-internal-layout', itemId: row.id, breakpoint: cell.bp });
3902
+ if (cell.mismatch)
3903
+ issues.push({ type: 'external-internal-mismatch', itemId: row.id, breakpoint: cell.bp });
3904
+ }
3905
+ }
3906
+ const external = this.externalItems();
3907
+ const snapshot = {
3908
+ timestamp: new Date().toISOString(),
3909
+ activeBreakpoint: this.activeBreakpoint(),
3910
+ containerWidth: this.containerWidth(),
3911
+ breakpoints: this.breakpoints(),
3912
+ internalItems: this.items().map((i) => ({ id: i.id, type: i.type, layout: i.layout })),
3913
+ activeLayout: this.layout(),
3914
+ ...(external ? { externalItems: external.map((i) => ({ id: i.id, type: i.type, layout: i.layout })) } : {}),
3915
+ issues,
3916
+ };
3917
+ navigator.clipboard.writeText(JSON.stringify(snapshot, null, 2)).catch(() => {
3918
+ /* clipboard unavailable in this context */
3919
+ });
3920
+ this.copied.set(true);
3921
+ timer(2000)
3922
+ .pipe(takeUntilDestroyed(this.destroyRef), tap$1(() => this.copied.set(false)))
3923
+ .subscribe();
3924
+ }
3925
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridDebugComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3926
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: GridDebugComponent, isStandalone: true, selector: "et-grid-debug", inputs: { grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: true, transformFunction: null }, externalItems: { classPropertyName: "externalItems", publicName: "externalItems", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
3927
+ <details
3928
+ style="font-family: monospace; font-size: 11px; border: 1px solid #d1d5db; border-radius: 4px; margin-top: 8px; background: #f9fafb; color: #111"
3929
+ >
3930
+ <summary
3931
+ style="padding: 6px 10px; cursor: pointer; list-style: none; display: flex; align-items: center; gap: 10px; user-select: none"
3932
+ >
3933
+ <span style="font-weight: 700; color: #6b7280">et-grid-debug</span>
3934
+
3935
+ <span style="color: #6b7280">
3936
+ bp: <strong style="color: #111827">{{ activeBreakpoint() }}</strong> &nbsp;·&nbsp; {{ containerWidth() }}px
3937
+ &nbsp;·&nbsp; {{ items().length }} items
3938
+ @if (hasDrag()) {
3939
+ &nbsp;·&nbsp; <span style="color: #d97706">⠿ dragging</span>
3940
+ }
3941
+ </span>
3942
+
3943
+ @if (issueCount() > 0) {
3944
+ <span style="color: #dc2626; font-weight: 700"
3945
+ >⚠ {{ issueCount() }} issue{{ issueCount() === 1 ? '' : 's' }}</span
3946
+ >
3947
+ }
3948
+
3949
+ <button
3950
+ (click)="copyJson($event)"
3951
+ style="margin-left: auto; padding: 2px 8px; border: 1px solid #d1d5db; border-radius: 3px; background: #fff; cursor: pointer; font-size: 11px; color: #374151"
3952
+ >
3953
+ Copy JSON
3954
+ </button>
3955
+
3956
+ @if (copied()) {
3957
+ <span style="color: #16a34a; font-size: 10px">✓ copied</span>
3958
+ }
3959
+ </summary>
3960
+
3961
+ <div style="padding: 8px 10px; overflow-x: auto; border-top: 1px solid #e5e7eb">
3962
+ <!-- Breakpoint legend -->
3963
+ <div style="display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap">
3964
+ @for (bp of breakpoints(); track bp.name) {
3965
+ <span
3966
+ [style.fontWeight]="bp.name === activeBreakpoint() ? '700' : '400'"
3967
+ [style.color]="bp.name === activeBreakpoint() ? '#1d4ed8' : '#9ca3af'"
3968
+ style="padding: 1px 7px; border: 1px solid currentColor; border-radius: 99px"
3969
+ >{{ bp.name }}&nbsp;{{ bp.columns }}col&nbsp;≥{{ bp.minWidth }}px</span
3970
+ >
3971
+ }
3972
+ </div>
3973
+
3974
+ <!-- Layout table -->
3975
+ <table style="border-collapse: collapse; white-space: nowrap">
3976
+ <thead>
3977
+ <tr style="background: #f3f4f6">
3978
+ <th style="padding: 3px 8px; text-align: left; border: 1px solid #e5e7eb">id</th>
3979
+ <th style="padding: 3px 8px; text-align: left; border: 1px solid #e5e7eb">type</th>
3980
+ @for (bp of breakpoints(); track bp.name) {
3981
+ <th
3982
+ [style.background]="bp.name === activeBreakpoint() ? '#dbeafe' : '#f3f4f6'"
3983
+ style="padding: 3px 8px; text-align: center; border: 1px solid #e5e7eb"
3984
+ >
3985
+ {{ bp.name }}{{ hasExternal() ? ' int' : '' }}
3986
+ </th>
3987
+ @if (hasExternal()) {
3988
+ <th
3989
+ [style.background]="bp.name === activeBreakpoint() ? '#dbeafe' : '#f3f4f6'"
3990
+ style="padding: 3px 8px; text-align: center; border: 1px solid #e5e7eb; opacity: .65"
3991
+ >
3992
+ {{ bp.name }} ext
3993
+ </th>
3994
+ }
3995
+ }
3996
+ </tr>
3997
+ </thead>
3998
+ <tbody>
3999
+ @for (row of rows(); track row.id) {
4000
+ <tr>
4001
+ <td style="padding: 3px 8px; border: 1px solid #e5e7eb; color: #6b7280">{{ row.id }}</td>
4002
+ <td style="padding: 3px 8px; border: 1px solid #e5e7eb; color: #9ca3af">{{ row.type }}</td>
4003
+ @for (cell of row.cells; track cell.bp) {
4004
+ <td
4005
+ [style.color]="cell.intMissing ? '#dc2626' : '#111'"
4006
+ [title]="cell.intMissing ? 'MISSING — layout.' + cell.bp + ' undefined in internal state' : ''"
4007
+ style="padding: 3px 8px; border: 1px solid #e5e7eb; text-align: center"
4008
+ >
4009
+ {{ fmtPos(cell.int) }}
4010
+ </td>
4011
+ @if (hasExternal()) {
4012
+ <td
4013
+ [style.color]="cell.extMissing ? '#dc2626' : cell.mismatch ? '#d97706' : '#9ca3af'"
4014
+ [title]="cell.mismatch ? 'MISMATCH — ext=' + fmtPos(cell.ext) + ' int=' + fmtPos(cell.int) : ''"
4015
+ style="padding: 3px 8px; border: 1px solid #e5e7eb; text-align: center"
4016
+ >
4017
+ {{ fmtPos(cell.ext) }}
4018
+ </td>
4019
+ }
4020
+ }
4021
+ </tr>
4022
+ }
4023
+ </tbody>
4024
+ </table>
4025
+
4026
+ @if (hasExternal()) {
4027
+ <p style="margin-top: 6px; color: #9ca3af; font-size: 10px">
4028
+ int = grid.items() (internal) &nbsp;·&nbsp; ext = externalItems input &nbsp;·&nbsp;
4029
+ <span style="color: #dc2626">red = undefined</span> &nbsp;·&nbsp;
4030
+ <span style="color: #d97706">orange = mismatch</span>
4031
+ </p>
4032
+ }
4033
+ </div>
4034
+ </details>
4035
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4036
+ }
4037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: GridDebugComponent, decorators: [{
4038
+ type: Component,
4039
+ args: [{
4040
+ selector: 'et-grid-debug',
4041
+ template: `
4042
+ <details
4043
+ style="font-family: monospace; font-size: 11px; border: 1px solid #d1d5db; border-radius: 4px; margin-top: 8px; background: #f9fafb; color: #111"
4044
+ >
4045
+ <summary
4046
+ style="padding: 6px 10px; cursor: pointer; list-style: none; display: flex; align-items: center; gap: 10px; user-select: none"
4047
+ >
4048
+ <span style="font-weight: 700; color: #6b7280">et-grid-debug</span>
4049
+
4050
+ <span style="color: #6b7280">
4051
+ bp: <strong style="color: #111827">{{ activeBreakpoint() }}</strong> &nbsp;·&nbsp; {{ containerWidth() }}px
4052
+ &nbsp;·&nbsp; {{ items().length }} items
4053
+ @if (hasDrag()) {
4054
+ &nbsp;·&nbsp; <span style="color: #d97706">⠿ dragging</span>
4055
+ }
4056
+ </span>
4057
+
4058
+ @if (issueCount() > 0) {
4059
+ <span style="color: #dc2626; font-weight: 700"
4060
+ >⚠ {{ issueCount() }} issue{{ issueCount() === 1 ? '' : 's' }}</span
4061
+ >
4062
+ }
4063
+
4064
+ <button
4065
+ (click)="copyJson($event)"
4066
+ style="margin-left: auto; padding: 2px 8px; border: 1px solid #d1d5db; border-radius: 3px; background: #fff; cursor: pointer; font-size: 11px; color: #374151"
4067
+ >
4068
+ Copy JSON
4069
+ </button>
4070
+
4071
+ @if (copied()) {
4072
+ <span style="color: #16a34a; font-size: 10px">✓ copied</span>
4073
+ }
4074
+ </summary>
4075
+
4076
+ <div style="padding: 8px 10px; overflow-x: auto; border-top: 1px solid #e5e7eb">
4077
+ <!-- Breakpoint legend -->
4078
+ <div style="display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap">
4079
+ @for (bp of breakpoints(); track bp.name) {
4080
+ <span
4081
+ [style.fontWeight]="bp.name === activeBreakpoint() ? '700' : '400'"
4082
+ [style.color]="bp.name === activeBreakpoint() ? '#1d4ed8' : '#9ca3af'"
4083
+ style="padding: 1px 7px; border: 1px solid currentColor; border-radius: 99px"
4084
+ >{{ bp.name }}&nbsp;{{ bp.columns }}col&nbsp;≥{{ bp.minWidth }}px</span
4085
+ >
4086
+ }
4087
+ </div>
4088
+
4089
+ <!-- Layout table -->
4090
+ <table style="border-collapse: collapse; white-space: nowrap">
4091
+ <thead>
4092
+ <tr style="background: #f3f4f6">
4093
+ <th style="padding: 3px 8px; text-align: left; border: 1px solid #e5e7eb">id</th>
4094
+ <th style="padding: 3px 8px; text-align: left; border: 1px solid #e5e7eb">type</th>
4095
+ @for (bp of breakpoints(); track bp.name) {
4096
+ <th
4097
+ [style.background]="bp.name === activeBreakpoint() ? '#dbeafe' : '#f3f4f6'"
4098
+ style="padding: 3px 8px; text-align: center; border: 1px solid #e5e7eb"
4099
+ >
4100
+ {{ bp.name }}{{ hasExternal() ? ' int' : '' }}
4101
+ </th>
4102
+ @if (hasExternal()) {
4103
+ <th
4104
+ [style.background]="bp.name === activeBreakpoint() ? '#dbeafe' : '#f3f4f6'"
4105
+ style="padding: 3px 8px; text-align: center; border: 1px solid #e5e7eb; opacity: .65"
4106
+ >
4107
+ {{ bp.name }} ext
4108
+ </th>
4109
+ }
4110
+ }
4111
+ </tr>
4112
+ </thead>
4113
+ <tbody>
4114
+ @for (row of rows(); track row.id) {
4115
+ <tr>
4116
+ <td style="padding: 3px 8px; border: 1px solid #e5e7eb; color: #6b7280">{{ row.id }}</td>
4117
+ <td style="padding: 3px 8px; border: 1px solid #e5e7eb; color: #9ca3af">{{ row.type }}</td>
4118
+ @for (cell of row.cells; track cell.bp) {
4119
+ <td
4120
+ [style.color]="cell.intMissing ? '#dc2626' : '#111'"
4121
+ [title]="cell.intMissing ? 'MISSING — layout.' + cell.bp + ' undefined in internal state' : ''"
4122
+ style="padding: 3px 8px; border: 1px solid #e5e7eb; text-align: center"
4123
+ >
4124
+ {{ fmtPos(cell.int) }}
4125
+ </td>
4126
+ @if (hasExternal()) {
4127
+ <td
4128
+ [style.color]="cell.extMissing ? '#dc2626' : cell.mismatch ? '#d97706' : '#9ca3af'"
4129
+ [title]="cell.mismatch ? 'MISMATCH — ext=' + fmtPos(cell.ext) + ' int=' + fmtPos(cell.int) : ''"
4130
+ style="padding: 3px 8px; border: 1px solid #e5e7eb; text-align: center"
4131
+ >
4132
+ {{ fmtPos(cell.ext) }}
4133
+ </td>
4134
+ }
4135
+ }
4136
+ </tr>
4137
+ }
4138
+ </tbody>
4139
+ </table>
4140
+
4141
+ @if (hasExternal()) {
4142
+ <p style="margin-top: 6px; color: #9ca3af; font-size: 10px">
4143
+ int = grid.items() (internal) &nbsp;·&nbsp; ext = externalItems input &nbsp;·&nbsp;
4144
+ <span style="color: #dc2626">red = undefined</span> &nbsp;·&nbsp;
4145
+ <span style="color: #d97706">orange = mismatch</span>
4146
+ </p>
4147
+ }
4148
+ </div>
4149
+ </details>
4150
+ `,
4151
+ encapsulation: ViewEncapsulation.None,
4152
+ changeDetection: ChangeDetectionStrategy.OnPush,
4153
+ }]
4154
+ }], propDecorators: { grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: true }] }], externalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "externalItems", required: false }] }] } });
4155
+
3717
4156
  const GRID_ERROR_CODES = {
3718
4157
  MISSING_GRID: 1900,
3719
4158
  MISSING_GRID_ITEM: 1901,
@@ -3721,7 +4160,7 @@ const GRID_ERROR_CODES = {
3721
4160
  INVALID_LAYOUT_STATE: 1903,
3722
4161
  };
3723
4162
 
3724
- const GridImports = [GridComponent, GridItemComponent];
4163
+ const GridImports = [GridComponent, GridItemComponent, GridDebugComponent];
3725
4164
 
3726
4165
  const ARROW_OUT_UP_RIGHT_ICON = {
3727
4166
  name: 'et-arrow-out-up-right',
@@ -11538,5 +11977,5 @@ const TOOLTIP_IMPORTS = [TooltipDirective, TooltipComponent];
11538
11977
  * Generated bundle index. Do not edit.
11539
11978
  */
11540
11979
 
11541
- export { ARROW_OUT_UP_RIGHT_ICON, ARROW_RIGHT_ICON, BUTTON_ICON_ALIGNMENTS, BUTTON_IMPORTS, BUTTON_SIZES, BUTTON_SPINNER_CONFIG, BUTTON_TYPES, BUTTON_VARIANTS, BrandLoaderComponent, ButtonComponent, ButtonDirective, ButtonStylesDirective, CHECKBOX_IMPORTS, CHEVRON_ICON, CHOICE_FIELD_IMPORTS, CLIPBOARD_CHECK_ICON, CheckboxComponent, CheckboxDirective, CheckboxGroupComponent, CheckboxOptionComponent, ChoiceFieldComponent, DAILYMOTION_PLAYER_TOKEN, DEFAULT_NOTIFICATION_MANAGER_CONFIG, DEFAULT_PIP_WINDOW_CONFIG, DEFAULT_STREAM_PLAYER_STATE, DailymotionPlayerComponent, DailymotionPlayerDirective, DailymotionPlayerParamsDirective, DailymotionPlayerSlotComponent, DescriptionComponent, FACEBOOK_PLAYER_TOKEN, FLOPPY_DISK_ICON, FOCUS_FRAME_ICON, FORM_FIELD_APPEARANCES, FORM_FIELD_CONTROL_TYPES, FORM_FIELD_ERROR_CODES, FORM_FIELD_FILLS, FORM_FIELD_IMPORTS, FORM_FIELD_LABEL_MODES, FORM_FIELD_SIZES, FORM_FIELD_TOKEN, FabComponent, FacebookPlayerComponent, FacebookPlayerDirective, FacebookPlayerParamsDirective, FacebookPlayerSlotComponent, FocusRingDirective, FormErrorComponent, FormFieldComponent, FormFieldDirective, GRID_2X2_ICON, GRID_ERROR_CODES, GRID_TOKEN, GridComponent, GridDirective, GridDragDirective, GridImports, GridItemComponent, GridItemDirective, GridItemRef, GridResizeDirective, HintComponent, ICONS_TOKEN, ICON_DIRECTIVE_TOKEN, ICON_ERROR_CODES, ICON_IMPORTS, INPUT_IMPORTS, INPUT_TEXT_ALIGNMENTS, INPUT_TYPES, IconButtonComponent, IconDirective, InputComponent, InputDirective, InputPrefixDirective, InputSuffixDirective, KICK_PLAYER_TOKEN, KickPlayerComponent, KickPlayerDirective, KickPlayerParamsDirective, KickPlayerSlotComponent, LOCK_ICON, LabelDirective, NAV_TABS_TOKEN, NOTIFICATION_ERROR_CODES, NOTIFICATION_IMPORTS, NOTIFICATION_STACK_CONTEXT_TOKEN, NOTIFICATION_STATUS, NavTabImports, NavTabLinkComponent, NavTabLinkDirective, NavTabsComponent, NavTabsDirective, NavTabsOutletComponent, NavTabsOutletDirective, NotificationActionDirective, NotificationComponent, NotificationDirective, NotificationDismissDirective, NotificationItemDirective, NotificationStackDirective, OVERLAY_ERROR_CODES, OVERLAY_IMPORTS, OVERLAY_REF, OverlayAnchorDirective, OverlayDirective, OverlaySurfaceDirective, OverlayTriggerDirective, PENCIL_ICON, PIP_CHROME_REF_TOKEN, PIP_ENTRY_TOKEN, PIP_WINDOW_ASPECT_RATIO_TOKEN, PLUS_ICON, PipBackDirective, PipBringBackDirective, PipCellDirective, PipCloseDirective, PipCollapseOverlayDirective, PipGridToggleDirective, PipPlayerComponent, PipSlotPlaceholderComponent, PipStageDirective, PipTitleBarDirective, PipTitleBarTemplateDirective, PipWindowComponent, PipWindowParamsDirective, ProgressBarComponent, RadioComponent, RadioGroupComponent, SCROLLABLE_IMPORTS, SELECTION_LIST_MULTIPLE, SELECTION_LIST_TOKEN, SOOP_PLAYER_TOKEN, STREAM_CONSENT_TOKEN, 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_USER_CONSENT_PROVIDER_TOKEN, SWITCH_IMPORTS, ScrollableActiveChildDirective, ScrollableButtonsDirective, ScrollableComponent, ScrollableDarkenDirective, ScrollableDirective, ScrollableDragDirective, ScrollableErrorCode, ScrollableIgnoreChildDirective, ScrollableLoadingTemplateDirective, ScrollableMasksDirective, ScrollableNavigationDirective, ScrollableSnapDirective, SegmentedButtonComponent, SegmentedButtonGroupComponent, SelectionListControlDirective, SelectionListDirective, SelectionOptionDirective, SoopPlayerComponent, SoopPlayerDirective, SoopPlayerParamsDirective, SoopPlayerSlotComponent, SpinnerComponent, StreamConsentAcceptDirective, StreamConsentComponent, StreamConsentDirective, StreamImports, StreamPipChromeComponent, StreamPlayerErrorComponent, StreamPlayerErrorDirective, StreamPlayerLoadingComponent, StreamPlayerSlotDirective, SwitchComponent, SwitchDirective, TAB_BAR_FITS, TAB_BAR_ORIENTATIONS, TAB_BAR_TOKEN, TAB_BAR_TRIGGER_TOKEN, TAB_BAR_VARIANTS, TAB_ERROR_CODES, TAB_GROUP_TOKEN, TAB_PANEL_TOKEN, TAB_SIZES, TIKTOK_PLAYER_TOKEN, TIMES_ICON, TOGGLETIP_ERROR_CODES, TOGGLETIP_IMPORTS, TOOLTIP_ERROR_CODES, TOOLTIP_IMPORTS, TRIANGLE_EXCLAMATION_ICON, TWITCH_PLAYER_TOKEN, TabBarDirective, TabBarTriggerDirective, TabBarUnderlineDirective, TabComponent, TabGroupComponent, TabGroupDirective, TabImports, TabLabelDirective, TabPanelDirective, TabTriggerDirective, TextButtonComponent, TikTokPlayerComponent, TikTokPlayerDirective, TikTokPlayerParamsDirective, TikTokPlayerSlotComponent, ToggletipCloseDirective, ToggletipComponent, ToggletipDirective, ToggletipTriggerDirective, TooltipComponent, TooltipDirective, TwitchPlayerComponent, TwitchPlayerDirective, TwitchPlayerParamsDirective, TwitchPlayerSlotComponent, VIMEO_PLAYER_TOKEN, VimeoPlayerComponent, VimeoPlayerDirective, VimeoPlayerParamsDirective, VimeoPlayerSlotComponent, WINDOW_CONTROL_BUTTON_KINDS, WINDOW_CONTROL_BUTTON_SIZES, WindowControlButtonComponent, YOUTUBE_PLAYER_SLOT_TOKEN, YOUTUBE_PLAYER_TOKEN, YoutubePlayerComponent, YoutubePlayerDirective, YoutubePlayerParamsDirective, YoutubePlayerSlotComponent, YoutubePlayerSlotDirective, createGridAdapter, createNotificationRef, createOverlayRef, createPipChromeAnimations, createPipChromeState, createStreamConfig, createStreamPlayerSlot, fromGridPosition, injectFormSupport, injectGridConfig, injectNotificationManager, injectNotificationManagerConfig, injectOverlayManager, injectPipChromeManager, injectPipManager, injectPipSlotPlaceholderConfig, injectStreamConfig, injectStreamConsentConfig, injectStreamManager, injectStreamPlayerErrorConfig, injectStreamPlayerLoadingConfig, injectStreamScriptLoader, injectStreamUserConsentProvider, provideFormSupport, provideGridConfig, provideIcons, provideNotificationManager, provideNotificationManagerConfig, provideNotificationManagerInstance, provideOverlayManager, providePipChromeManager, providePipManager, providePipSlotPlaceholderConfig, provideStreamConfig, provideStreamConsentConfig, provideStreamManager, provideStreamPlayerErrorConfig, provideStreamPlayerLoadingConfig, toGridPosition };
11980
+ export { ARROW_OUT_UP_RIGHT_ICON, ARROW_RIGHT_ICON, BUTTON_ICON_ALIGNMENTS, BUTTON_IMPORTS, BUTTON_SIZES, BUTTON_SPINNER_CONFIG, BUTTON_TYPES, BUTTON_VARIANTS, BrandLoaderComponent, ButtonComponent, ButtonDirective, ButtonStylesDirective, CHECKBOX_IMPORTS, CHEVRON_ICON, CHOICE_FIELD_IMPORTS, CLIPBOARD_CHECK_ICON, CheckboxComponent, CheckboxDirective, CheckboxGroupComponent, CheckboxOptionComponent, ChoiceFieldComponent, DAILYMOTION_PLAYER_TOKEN, DEFAULT_NOTIFICATION_MANAGER_CONFIG, DEFAULT_PIP_WINDOW_CONFIG, DEFAULT_STREAM_PLAYER_STATE, DailymotionPlayerComponent, DailymotionPlayerDirective, DailymotionPlayerParamsDirective, DailymotionPlayerSlotComponent, DescriptionComponent, FACEBOOK_PLAYER_TOKEN, FLOPPY_DISK_ICON, FOCUS_FRAME_ICON, FORM_FIELD_APPEARANCES, FORM_FIELD_CONTROL_TYPES, FORM_FIELD_ERROR_CODES, FORM_FIELD_FILLS, FORM_FIELD_IMPORTS, FORM_FIELD_LABEL_MODES, FORM_FIELD_SIZES, FORM_FIELD_TOKEN, FabComponent, FacebookPlayerComponent, FacebookPlayerDirective, FacebookPlayerParamsDirective, FacebookPlayerSlotComponent, FocusRingDirective, FormErrorComponent, FormFieldComponent, FormFieldDirective, GRID_2X2_ICON, GRID_ERROR_CODES, GRID_TOKEN, GridComponent, GridDebugComponent, GridDirective, GridDragDirective, GridImports, GridItemComponent, GridItemDirective, GridItemRef, GridResizeDirective, HintComponent, ICONS_TOKEN, ICON_DIRECTIVE_TOKEN, ICON_ERROR_CODES, ICON_IMPORTS, INPUT_IMPORTS, INPUT_TEXT_ALIGNMENTS, INPUT_TYPES, IconButtonComponent, IconDirective, InputComponent, InputDirective, InputPrefixDirective, InputSuffixDirective, KICK_PLAYER_TOKEN, KickPlayerComponent, KickPlayerDirective, KickPlayerParamsDirective, KickPlayerSlotComponent, LOCK_ICON, LabelDirective, NAV_TABS_TOKEN, NOTIFICATION_ERROR_CODES, NOTIFICATION_IMPORTS, NOTIFICATION_STACK_CONTEXT_TOKEN, NOTIFICATION_STATUS, NavTabImports, NavTabLinkComponent, NavTabLinkDirective, NavTabsComponent, NavTabsDirective, NavTabsOutletComponent, NavTabsOutletDirective, NotificationActionDirective, NotificationComponent, NotificationDirective, NotificationDismissDirective, NotificationItemDirective, NotificationStackDirective, OVERLAY_ERROR_CODES, OVERLAY_IMPORTS, OVERLAY_REF, OverlayAnchorDirective, OverlayDirective, OverlaySurfaceDirective, OverlayTriggerDirective, PENCIL_ICON, PIP_CHROME_REF_TOKEN, PIP_ENTRY_TOKEN, PIP_WINDOW_ASPECT_RATIO_TOKEN, PLUS_ICON, PipBackDirective, PipBringBackDirective, PipCellDirective, PipCloseDirective, PipCollapseOverlayDirective, PipGridToggleDirective, PipPlayerComponent, PipSlotPlaceholderComponent, PipStageDirective, PipTitleBarDirective, PipTitleBarTemplateDirective, PipWindowComponent, PipWindowParamsDirective, ProgressBarComponent, RadioComponent, RadioGroupComponent, SCROLLABLE_IMPORTS, SELECTION_LIST_MULTIPLE, SELECTION_LIST_TOKEN, SOOP_PLAYER_TOKEN, STREAM_CONSENT_TOKEN, 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_USER_CONSENT_PROVIDER_TOKEN, SWITCH_IMPORTS, ScrollableActiveChildDirective, ScrollableButtonsDirective, ScrollableComponent, ScrollableDarkenDirective, ScrollableDirective, ScrollableDragDirective, ScrollableErrorCode, ScrollableIgnoreChildDirective, ScrollableLoadingTemplateDirective, ScrollableMasksDirective, ScrollableNavigationDirective, ScrollableSnapDirective, SegmentedButtonComponent, SegmentedButtonGroupComponent, SelectionListControlDirective, SelectionListDirective, SelectionOptionDirective, SoopPlayerComponent, SoopPlayerDirective, SoopPlayerParamsDirective, SoopPlayerSlotComponent, SpinnerComponent, StreamConsentAcceptDirective, StreamConsentComponent, StreamConsentDirective, StreamImports, StreamPipChromeComponent, StreamPlayerErrorComponent, StreamPlayerErrorDirective, StreamPlayerLoadingComponent, StreamPlayerSlotDirective, SwitchComponent, SwitchDirective, TAB_BAR_FITS, TAB_BAR_ORIENTATIONS, TAB_BAR_TOKEN, TAB_BAR_TRIGGER_TOKEN, TAB_BAR_VARIANTS, TAB_ERROR_CODES, TAB_GROUP_TOKEN, TAB_PANEL_TOKEN, TAB_SIZES, TIKTOK_PLAYER_TOKEN, TIMES_ICON, TOGGLETIP_ERROR_CODES, TOGGLETIP_IMPORTS, TOOLTIP_ERROR_CODES, TOOLTIP_IMPORTS, TRIANGLE_EXCLAMATION_ICON, TWITCH_PLAYER_TOKEN, TabBarDirective, TabBarTriggerDirective, TabBarUnderlineDirective, TabComponent, TabGroupComponent, TabGroupDirective, TabImports, TabLabelDirective, TabPanelDirective, TabTriggerDirective, TextButtonComponent, TikTokPlayerComponent, TikTokPlayerDirective, TikTokPlayerParamsDirective, TikTokPlayerSlotComponent, ToggletipCloseDirective, ToggletipComponent, ToggletipDirective, ToggletipTriggerDirective, TooltipComponent, TooltipDirective, TwitchPlayerComponent, TwitchPlayerDirective, TwitchPlayerParamsDirective, TwitchPlayerSlotComponent, VIMEO_PLAYER_TOKEN, VimeoPlayerComponent, VimeoPlayerDirective, VimeoPlayerParamsDirective, VimeoPlayerSlotComponent, WINDOW_CONTROL_BUTTON_KINDS, WINDOW_CONTROL_BUTTON_SIZES, WindowControlButtonComponent, YOUTUBE_PLAYER_SLOT_TOKEN, YOUTUBE_PLAYER_TOKEN, YoutubePlayerComponent, YoutubePlayerDirective, YoutubePlayerParamsDirective, YoutubePlayerSlotComponent, YoutubePlayerSlotDirective, createGridAdapter, createNotificationRef, createOverlayRef, createPipChromeAnimations, createPipChromeState, createStreamConfig, createStreamPlayerSlot, fromGridPosition, injectFormSupport, injectGridConfig, injectNotificationManager, injectNotificationManagerConfig, injectOverlayManager, injectPipChromeManager, injectPipManager, injectPipSlotPlaceholderConfig, injectStreamConfig, injectStreamConsentConfig, injectStreamManager, injectStreamPlayerErrorConfig, injectStreamPlayerLoadingConfig, injectStreamScriptLoader, injectStreamUserConsentProvider, provideFormSupport, provideGridConfig, provideIcons, provideNotificationManager, provideNotificationManagerConfig, provideNotificationManagerInstance, provideOverlayManager, providePipChromeManager, providePipManager, providePipSlotPlaceholderConfig, provideStreamConfig, provideStreamConsentConfig, provideStreamManager, provideStreamPlayerErrorConfig, provideStreamPlayerLoadingConfig, toGridPosition };
11542
11981
  //# sourceMappingURL=ethlete-components.mjs.map