@reforgium/data-grid 3.2.3 → 3.2.5

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, inject, TemplateRef, Directive, booleanAttribute, contentChild, Component, numberAttribute, InjectionToken, makeEnvironmentProviders, signal, computed, effect, Injectable, ChangeDetectionStrategy, output, untracked, DestroyRef, afterRenderEffect, viewChild, NgZone, contentChildren, afterNextRender } from '@angular/core';
2
+ import { input, inject, TemplateRef, Directive, booleanAttribute, contentChild, Component, numberAttribute, InjectionToken, makeEnvironmentProviders, signal, computed, effect, Injectable, ChangeDetectionStrategy, isDevMode, output, untracked, DestroyRef, afterRenderEffect, viewChild, NgZone, contentChildren, afterNextRender } from '@angular/core';
3
3
  import { NgTemplateOutlet, DatePipe, DecimalPipe } from '@angular/common';
4
4
 
5
5
  /**
@@ -162,6 +162,7 @@ class DataGridDeclarativeColumn {
162
162
  defaultValue = input(undefined, ...(ngDevMode ? [{ debugName: "defaultValue" }] : /* istanbul ignore next */ []));
163
163
  value = input(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
164
164
  transformer = input(undefined, ...(ngDevMode ? [{ debugName: "transformer" }] : /* istanbul ignore next */ []));
165
+ /** @deprecated Not consumed by the renderer. Use the grid-level rowKey input. */
165
166
  track = input(undefined, ...(ngDevMode ? [{ debugName: "track" }] : /* istanbul ignore next */ []));
166
167
  tooltip = input(undefined, ...(ngDevMode ? [{ debugName: "tooltip" }] : /* istanbul ignore next */ []));
167
168
  headerTplRef = contentChild(DataGridDeclarativeHeaderDirective, ...(ngDevMode ? [{ debugName: "headerTplRef" }] : /* istanbul ignore next */ []));
@@ -1621,11 +1622,33 @@ function createGridColumnResizeFeature(ctx) {
1621
1622
  targetWindow.addEventListener('mousemove', onMoveRef);
1622
1623
  targetWindow.addEventListener('mouseup', onUpRef);
1623
1624
  };
1625
+ const onResizeKeydown = (event, column) => {
1626
+ const direction = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
1627
+ if (!direction) {
1628
+ return;
1629
+ }
1630
+ event.preventDefault();
1631
+ event.stopPropagation();
1632
+ const key = String(column.key);
1633
+ const step = event.shiftKey ? 1 : 10;
1634
+ const previousKey = activeKey;
1635
+ const previousMinWidth = minWidth;
1636
+ const previousMaxWidth = maxWidth;
1637
+ activeKey = key;
1638
+ minWidth = Math.max(0, column.minWidth ?? DEFAULT_MIN_RESIZE_WIDTH);
1639
+ maxWidth = column.maxWidth ?? Number.POSITIVE_INFINITY;
1640
+ applyWidth(ctx.resolveWidth(key) + direction * step);
1641
+ activeKey = previousKey;
1642
+ minWidth = previousMinWidth;
1643
+ maxWidth = previousMaxWidth;
1644
+ ctx.emitResizeEnd?.(key, ctx.resolveWidth(key));
1645
+ };
1624
1646
  const destroy = () => {
1625
1647
  stopResize();
1626
1648
  };
1627
1649
  return {
1628
1650
  onResizeStart,
1651
+ onResizeKeydown,
1629
1652
  destroy,
1630
1653
  };
1631
1654
  }
@@ -1990,27 +2013,35 @@ function createGridScrollLoopFeature(ctx) {
1990
2013
 
1991
2014
  // noinspection ES6PreferShortImport
1992
2015
  function createGridSelectionReconcileFeature(ctx) {
1993
- let lastSelectionKeyField = '';
2016
+ let lastSelectionKeyField;
1994
2017
  let lastValidSelectionKeys = new Set();
1995
2018
  const reconcile = () => {
1996
2019
  const selection = ctx.getSelection();
1997
2020
  if (selection.mode === 'none' || !('key' in selection)) {
1998
- lastSelectionKeyField = '';
2021
+ lastSelectionKeyField = undefined;
2022
+ lastValidSelectionKeys.clear();
2023
+ return;
2024
+ }
2025
+ const keyField = String(selection.key);
2026
+ if (lastSelectionKeyField !== undefined && lastSelectionKeyField !== keyField) {
2027
+ lastSelectionKeyField = keyField;
1999
2028
  lastValidSelectionKeys.clear();
2029
+ ctx.setSelectedKeys([]);
2030
+ ctx.emitSelectChange([]);
2031
+ return;
2032
+ }
2033
+ lastSelectionKeyField = keyField;
2034
+ if (ctx.getSelectionPolicy() === 'preserve-unloaded') {
2000
2035
  return;
2001
2036
  }
2002
2037
  const data = ctx.getData() ?? [];
2003
- const key = selection.key;
2004
- const validKeys = data.map((row) => row[key]).filter((rowKey) => rowKey !== null && rowKey !== undefined);
2038
+ const validKeys = data.map((row) => row[selection.key]).filter((rowKey) => rowKey !== null && rowKey !== undefined);
2005
2039
  const keySet = new Set(validKeys);
2006
- const keyField = String(key);
2007
- const sameSetAsPrevious = lastSelectionKeyField === keyField &&
2008
- keySet.size === lastValidSelectionKeys.size &&
2040
+ const sameSetAsPrevious = keySet.size === lastValidSelectionKeys.size &&
2009
2041
  Array.from(keySet).every((rowKey) => lastValidSelectionKeys.has(rowKey));
2010
2042
  if (sameSetAsPrevious) {
2011
2043
  return;
2012
2044
  }
2013
- lastSelectionKeyField = keyField;
2014
2045
  lastValidSelectionKeys = new Set(keySet);
2015
2046
  const currentSelected = ctx.getSelectedKeys();
2016
2047
  const nextSelected = currentSelected.filter((selectedKey) => selectedKey !== null && selectedKey !== undefined && keySet.has(selectedKey));
@@ -2036,11 +2067,7 @@ function createGridSlotsFeature(ctx) {
2036
2067
  }
2037
2068
  const headerMap = new Map();
2038
2069
  ctx.getHeaderTemplateRefs()?.forEach((headerRef) => headerMap.set(headerRef.key(), headerRef.tpl));
2039
- ctx.getExtendedColumns().forEach((column) => {
2040
- if (!column.headerTemplate && headerMap.has(column.key)) {
2041
- column.headerTemplate = headerMap.get(column.key);
2042
- }
2043
- });
2070
+ ctx.setHeaderTemplates(headerMap);
2044
2071
  };
2045
2072
  return { initRefs };
2046
2073
  }
@@ -2061,10 +2088,12 @@ function createGridSortFeature(ctx) {
2061
2088
  ctx.emitSortChange({ sort: sortKey, order });
2062
2089
  };
2063
2090
  const resetSort = () => {
2064
- const prevKey = (ctx.getSortField() ?? '');
2091
+ const prevKey = ctx.getSortField();
2065
2092
  ctx.setSortField(undefined);
2066
2093
  ctx.setSorts([]);
2067
- emitSortChange(prevKey, undefined);
2094
+ if (prevKey) {
2095
+ emitSortChange(prevKey, undefined);
2096
+ }
2068
2097
  ctx.emitMultiSortChange([]);
2069
2098
  };
2070
2099
  const setSort = (sort) => {
@@ -2156,10 +2185,18 @@ function createGridSourceDataFeature(ctx) {
2156
2185
  const bufferVersion = signal(0, ...(ngDevMode ? [{ debugName: "bufferVersion" }] : /* istanbul ignore next */ []));
2157
2186
  const pendingPages = new Set();
2158
2187
  const queuedPages = [];
2188
+ const statelessRequestControllers = new Set();
2159
2189
  let lastSourceRef = null;
2190
+ let warnedStatefulParallelSource = null;
2191
+ let warnedInfinitySourceWithoutVersion = null;
2160
2192
  let lastSourceVersion = null;
2161
2193
  let activeRequests = 0;
2194
+ let statelessPageRequests = 0;
2195
+ let statelessPageRequestId = 0;
2196
+ let activePageRequestController = null;
2197
+ let currentPageResult = null;
2162
2198
  let requestGeneration = 0;
2199
+ let activeSortRequestId = 0;
2163
2200
  let hasReceivedData = false;
2164
2201
  let pageBase = 0;
2165
2202
  // Row knowledge accounting. Decoupled from `sourcePages` so that buffer eviction
@@ -2169,7 +2206,56 @@ function createGridSourceDataFeature(ctx) {
2169
2206
  let endReached = false;
2170
2207
  let confirmedTotal = null;
2171
2208
  const hasSessionState = () => sourcePages.size > 0 || pendingPages.size > 0 || queuedPages.length > 0 || activeRequests > 0 || hasReceivedData;
2172
- const resolvedLoading = () => ctx.getSource()?.loading() ?? ctx.getFallbackLoading();
2209
+ const resolvedLoading = () => {
2210
+ bufferVersion();
2211
+ return (ctx.getSource()?.loading() ?? ctx.getFallbackLoading()) || statelessPageRequests > 0;
2212
+ };
2213
+ const effectiveItems = (source) => currentPageResult ? [...currentPageResult.items] : (source.items() ?? []);
2214
+ const hasRenderableRows = () => {
2215
+ const source = ctx.getSource();
2216
+ if (!source) {
2217
+ return (ctx.getFallbackData()?.length ?? 0) > 0;
2218
+ }
2219
+ if (ctx.getMode() === 'infinity') {
2220
+ return hasReceivedData;
2221
+ }
2222
+ return effectiveItems(source).length > 0;
2223
+ };
2224
+ const resolvedBlockingLoading = () => resolvedLoading() && !hasRenderableRows();
2225
+ const effectivePageSize = (source) => currentPageResult?.pageSize || source.pageSize || ctx.getFallbackPageSize();
2226
+ const effectiveTotalElements = (source) => currentPageResult?.totalElements ?? source.totalElements;
2227
+ const normalizePageResult = (result, requestedPage, source) => {
2228
+ if (!result || !Number.isInteger(result.page) || result.page < 0 || !Array.isArray(result.items)) {
2229
+ throw new TypeError('Grid source loadPage() must return a page result with page and items');
2230
+ }
2231
+ if (result.page !== requestedPage) {
2232
+ throw new Error(`Grid source loadPage() returned page ${result.page} for requested page ${requestedPage}`);
2233
+ }
2234
+ return {
2235
+ page: result.page,
2236
+ items: [...result.items],
2237
+ pageSize: result.pageSize || source.pageSize || ctx.getFallbackPageSize(),
2238
+ totalElements: result.totalElements ?? source.totalElements,
2239
+ };
2240
+ };
2241
+ const loadPageResult = (source, page, signal) => source.loadPage(page, { signal }).then((result) => normalizePageResult(result, page, source));
2242
+ const normalizeRequest = (request) => {
2243
+ try {
2244
+ return Promise.resolve(request());
2245
+ }
2246
+ catch (error) {
2247
+ return Promise.reject(error);
2248
+ }
2249
+ };
2250
+ const isAbortError = (error) => error instanceof DOMException && error.name === 'AbortError';
2251
+ const reportRequestError = (source, event, error) => {
2252
+ if (!source.error && !isAbortError(error)) {
2253
+ ctx.emitSourceError?.({ ...event, error });
2254
+ }
2255
+ };
2256
+ const settleRequest = (request, source, event) => normalizeRequest(request).then(() => undefined, (error) => {
2257
+ reportRequestError(source, event, error);
2258
+ });
2173
2259
  const totalRowCount = () => {
2174
2260
  const source = ctx.getSource();
2175
2261
  if (!source) {
@@ -2191,18 +2277,29 @@ function createGridSourceDataFeature(ctx) {
2191
2277
  }
2192
2278
  return knownRowCount + Math.max(1, source.pageSize || ctx.getFallbackPageSize());
2193
2279
  }
2194
- const knownTotal = resolvedTotalElements(source);
2280
+ const knownTotal = resolvedTotalElements(source, effectiveTotalElements(source));
2195
2281
  if (knownTotal !== null) {
2196
2282
  return knownTotal;
2197
2283
  }
2198
2284
  return estimateOpenEndedPaginationTotal(source);
2199
2285
  };
2286
+ const renderRowCount = () => {
2287
+ const source = ctx.getSource();
2288
+ if (!source) {
2289
+ return ctx.getFallbackData()?.length ?? 0;
2290
+ }
2291
+ if (ctx.getMode() !== 'infinity') {
2292
+ return effectiveItems(source).length;
2293
+ }
2294
+ return totalRowCount();
2295
+ };
2200
2296
  const selectionRows = () => {
2201
2297
  const source = ctx.getSource();
2202
2298
  if (!source) {
2203
2299
  return ctx.getFallbackData() ?? [];
2204
2300
  }
2205
- const items = source.items() ?? [];
2301
+ bufferVersion();
2302
+ const items = effectiveItems(source);
2206
2303
  if (ctx.getMode() !== 'infinity') {
2207
2304
  return items;
2208
2305
  }
@@ -2224,7 +2321,8 @@ function createGridSourceDataFeature(ctx) {
2224
2321
  return ctx.getFallbackData()?.[index] ?? null;
2225
2322
  }
2226
2323
  if (ctx.getMode() !== 'infinity') {
2227
- return source.items()?.[index] ?? null;
2324
+ bufferVersion();
2325
+ return effectiveItems(source)[index] ?? null;
2228
2326
  }
2229
2327
  bufferVersion();
2230
2328
  const pageSize = Math.max(1, source.pageSize || ctx.getFallbackPageSize());
@@ -2236,7 +2334,22 @@ function createGridSourceDataFeature(ctx) {
2236
2334
  }
2237
2335
  return pageItems[index - localPage * pageSize] ?? null;
2238
2336
  };
2239
- const activePageSize = () => ctx.getSource()?.pageSize || ctx.getFallbackPageSize();
2337
+ const dataRowOffset = () => {
2338
+ const source = ctx.getSource();
2339
+ if (!source || ctx.getMode() === 'none') {
2340
+ return 0;
2341
+ }
2342
+ const page = ctx.getMode() === 'pagination' ? (currentPageResult?.page ?? source.page) : pageBase;
2343
+ return Math.max(0, page) * Math.max(1, effectivePageSize(source));
2344
+ };
2345
+ const activePageSize = () => {
2346
+ const source = ctx.getSource();
2347
+ if (!source) {
2348
+ return ctx.getFallbackPageSize();
2349
+ }
2350
+ bufferVersion();
2351
+ return effectivePageSize(source);
2352
+ };
2240
2353
  const requestRowCount = () => {
2241
2354
  const source = ctx.getSource();
2242
2355
  if (!source || ctx.getMode() !== 'infinity') {
@@ -2245,15 +2358,74 @@ function createGridSourceDataFeature(ctx) {
2245
2358
  bufferVersion();
2246
2359
  return Math.min(totalRowCount(), contiguousLoadedRowCount(source));
2247
2360
  };
2361
+ const requestStatelessPage = (source, page) => {
2362
+ activePageRequestController?.abort();
2363
+ const controller = new AbortController();
2364
+ activePageRequestController = controller;
2365
+ statelessRequestControllers.add(controller);
2366
+ const capturedGeneration = requestGeneration;
2367
+ const requestId = ++statelessPageRequestId;
2368
+ statelessPageRequests += 1;
2369
+ bufferVersion.update((current) => current + 1);
2370
+ void normalizeRequest(() => loadPageResult(source, page, controller.signal))
2371
+ .then((result) => {
2372
+ if (ctx.getSource() !== source ||
2373
+ requestGeneration !== capturedGeneration ||
2374
+ requestId !== statelessPageRequestId) {
2375
+ return;
2376
+ }
2377
+ if (ctx.getMode() === 'infinity') {
2378
+ sourcePages.set(result.page, [...result.items]);
2379
+ recordPageKnowledge(result.page, [...result.items], result.pageSize || ctx.getFallbackPageSize());
2380
+ }
2381
+ else {
2382
+ currentPageResult = result;
2383
+ }
2384
+ bufferVersion.update((current) => current + 1);
2385
+ })
2386
+ .catch((error) => {
2387
+ if (!controller.signal.aborted &&
2388
+ ctx.getSource() === source &&
2389
+ requestGeneration === capturedGeneration &&
2390
+ requestId === statelessPageRequestId) {
2391
+ reportRequestError(source, { operation: 'page', page }, error);
2392
+ }
2393
+ })
2394
+ .finally(() => {
2395
+ statelessRequestControllers.delete(controller);
2396
+ if (activePageRequestController === controller) {
2397
+ activePageRequestController = null;
2398
+ }
2399
+ statelessPageRequests = Math.max(0, statelessPageRequests - 1);
2400
+ bufferVersion.update((current) => current + 1);
2401
+ });
2402
+ };
2248
2403
  const requestPage = (event) => {
2249
2404
  const source = ctx.getSource();
2250
2405
  if (source) {
2406
+ if (activeSortRequestId > 0) {
2407
+ return;
2408
+ }
2251
2409
  const targetPage = ctx.getMode() === 'infinity' ? Math.max(0, localToAbsolutePage(event.page)) : event.page;
2252
2410
  if (source.updatePageSize && event.rows > 0 && event.rows !== source.pageSize) {
2253
- void source.updatePageSize(event.rows);
2411
+ resetSession();
2412
+ currentPageResult = null;
2413
+ bufferVersion.update((current) => current + 1);
2414
+ void settleRequest(() => source.updatePageSize(event.rows), source, {
2415
+ operation: 'page-size',
2416
+ pageSize: event.rows,
2417
+ });
2254
2418
  return;
2255
2419
  }
2256
- void source.updatePage(targetPage);
2420
+ if (source.loadPage) {
2421
+ requestStatelessPage(source, targetPage);
2422
+ return;
2423
+ }
2424
+ if (source.updatePage) {
2425
+ void settleRequest(() => source.updatePage(targetPage), source, { operation: 'page', page: targetPage });
2426
+ return;
2427
+ }
2428
+ reportRequestError(source, { operation: 'page', page: targetPage }, new TypeError('Grid source must implement loadPage() or updatePage()'));
2257
2429
  return;
2258
2430
  }
2259
2431
  ctx.emitPageChange(event);
@@ -2264,11 +2436,13 @@ function createGridSourceDataFeature(ctx) {
2264
2436
  return;
2265
2437
  }
2266
2438
  if (source.updateSort) {
2267
- void source.updateSort(sort ?? null);
2439
+ resetSession();
2440
+ void runSortRequest(source, { operation: 'sort', sort: sort ?? null }, () => source.updateSort(sort ?? null));
2268
2441
  return;
2269
2442
  }
2270
2443
  if (source.updateSorts) {
2271
- void source.updateSorts(sort ? [sort] : []);
2444
+ resetSession();
2445
+ void runSortRequest(source, { operation: 'multi-sort', sorts: sort ? [sort] : [] }, () => source.updateSorts(sort ? [sort] : []));
2272
2446
  }
2273
2447
  };
2274
2448
  const requestMultiSort = (sorts) => {
@@ -2277,14 +2451,31 @@ function createGridSourceDataFeature(ctx) {
2277
2451
  return;
2278
2452
  }
2279
2453
  if (source.updateSorts) {
2280
- void source.updateSorts(sorts);
2454
+ resetSession();
2455
+ void runSortRequest(source, { operation: 'multi-sort', sorts }, () => source.updateSorts(sorts));
2281
2456
  return;
2282
2457
  }
2283
2458
  if (source.updateSort) {
2459
+ resetSession();
2284
2460
  const active = sorts[sorts.length - 1] ?? null;
2285
- void source.updateSort(active);
2461
+ void runSortRequest(source, { operation: 'sort', sort: active }, () => source.updateSort(active));
2286
2462
  }
2287
2463
  };
2464
+ const runSortRequest = (source, event, request) => {
2465
+ const requestId = activeSortRequestId + 1;
2466
+ activeSortRequestId = requestId;
2467
+ return normalizeRequest(request)
2468
+ .catch((error) => {
2469
+ if (activeSortRequestId === requestId) {
2470
+ reportRequestError(source, event, error);
2471
+ }
2472
+ })
2473
+ .finally(() => {
2474
+ if (activeSortRequestId === requestId) {
2475
+ activeSortRequestId = 0;
2476
+ }
2477
+ });
2478
+ };
2288
2479
  const ensureBufferedRange = (state) => {
2289
2480
  const source = ctx.getSource();
2290
2481
  if (!source || ctx.getMode() !== 'infinity' || state.total <= 0 || !hasReceivedData) {
@@ -2324,6 +2515,14 @@ function createGridSourceDataFeature(ctx) {
2324
2515
  return;
2325
2516
  }
2326
2517
  const version = source.version?.();
2518
+ if (mode === 'infinity' &&
2519
+ !source.version &&
2520
+ !source.immutable &&
2521
+ isDevMode() &&
2522
+ warnedInfinitySourceWithoutVersion !== source) {
2523
+ warnedInfinitySourceWithoutVersion = source;
2524
+ console.warn('[data-grid] Infinity sources without version cannot invalidate mutable datasets automatically. Expose version or call resetSourceBuffer() after replacement/filter changes.');
2525
+ }
2327
2526
  if (lastSourceRef !== source) {
2328
2527
  lastSourceRef = source;
2329
2528
  lastSourceVersion = version ?? null;
@@ -2358,18 +2557,25 @@ function createGridSourceDataFeature(ctx) {
2358
2557
  const clearState = () => {
2359
2558
  lastSourceRef = null;
2360
2559
  lastSourceVersion = null;
2361
- if (!hasSessionState()) {
2560
+ if (!hasSessionState() && !currentPageResult) {
2362
2561
  return;
2363
2562
  }
2364
2563
  resetSession();
2365
2564
  };
2366
2565
  const resetSession = () => {
2566
+ for (const controller of statelessRequestControllers) {
2567
+ controller.abort();
2568
+ }
2569
+ statelessRequestControllers.clear();
2570
+ activePageRequestController = null;
2367
2571
  requestGeneration++;
2368
2572
  hasReceivedData = false;
2369
2573
  pageBase = 0;
2370
2574
  queuedPages.length = 0;
2371
2575
  pendingPages.clear();
2372
2576
  activeRequests = 0;
2577
+ statelessPageRequestId++;
2578
+ currentPageResult = null;
2373
2579
  sourcePages.clear();
2374
2580
  knownRowCount = 0;
2375
2581
  endReached = false;
@@ -2408,12 +2614,48 @@ function createGridSourceDataFeature(ctx) {
2408
2614
  }
2409
2615
  pages.push(page);
2410
2616
  };
2617
+ const runPrefetchRequest = (source, page, generation, controller, request, onSuccess) => {
2618
+ void normalizeRequest(request)
2619
+ .then((result) => {
2620
+ if (requestGeneration === generation && ctx.getSource() === source && ctx.getMode() === 'infinity') {
2621
+ onSuccess(result);
2622
+ }
2623
+ })
2624
+ .catch((error) => {
2625
+ if (requestGeneration === generation && ctx.getSource() === source && !controller?.signal.aborted) {
2626
+ reportRequestError(source, { operation: 'prefetch', page }, error);
2627
+ }
2628
+ })
2629
+ .finally(() => {
2630
+ if (controller) {
2631
+ statelessRequestControllers.delete(controller);
2632
+ }
2633
+ // Stateful updatePage requests cannot be aborted. A stale completion must
2634
+ // not release a same-page request created by the next source generation.
2635
+ if (requestGeneration !== generation) {
2636
+ return;
2637
+ }
2638
+ pendingPages.delete(page);
2639
+ activeRequests = Math.max(0, activeRequests - 1);
2640
+ bufferVersion.update((current) => current + 1);
2641
+ if (queuedPages.length) {
2642
+ queueMicrotask(() => drainQueuedPages());
2643
+ }
2644
+ });
2645
+ };
2411
2646
  const drainQueuedPages = () => {
2412
2647
  const source = ctx.getSource();
2413
2648
  if (!source || ctx.getMode() !== 'infinity' || !hasReceivedData) {
2414
2649
  return;
2415
2650
  }
2416
- const maxConcurrentRequests = source.prefetchMode === 'parallel' ? PARALLEL_PREFETCH_REQUESTS : SEQUENTIAL_PREFETCH_REQUESTS;
2651
+ if (source.prefetchMode === 'parallel' &&
2652
+ !source.loadPage &&
2653
+ isDevMode() &&
2654
+ warnedStatefulParallelSource !== source) {
2655
+ warnedStatefulParallelSource = source;
2656
+ console.warn('[data-grid] Parallel prefetch requires the stateless loadPage() capability. Falling back to sequential updatePage().');
2657
+ }
2658
+ const maxConcurrentRequests = source.prefetchMode === 'parallel' && source.loadPage ? PARALLEL_PREFETCH_REQUESTS : SEQUENTIAL_PREFETCH_REQUESTS;
2417
2659
  while (activeRequests < maxConcurrentRequests && queuedPages.length) {
2418
2660
  const nextPage = queuedPages.shift();
2419
2661
  const activeSource = ctx.getSource();
@@ -2427,34 +2669,31 @@ function createGridSourceDataFeature(ctx) {
2427
2669
  pendingPages.add(nextPage);
2428
2670
  bufferVersion.update((current) => current + 1);
2429
2671
  const capturedGeneration = requestGeneration;
2430
- void activeSource
2431
- .updatePage(nextPage)
2432
- .then(() => {
2433
- // Пропускаем запись если буфер был сброшен пока запрос летел
2434
- // (смена источника, смена версии, clearState). Без этой проверки
2435
- // устаревший ответ затирал бы свежий буфер.
2436
- if (requestGeneration !== capturedGeneration) {
2437
- return;
2438
- }
2439
- // Параллельный режим: захватываем данные страницы сразу, пока источник
2440
- // ещё хранит именно эту страницу. Без этого sync() (Angular effect) видит
2441
- // только последнюю из страниц, если несколько запросов завершились до
2442
- // того, как эффект успел выполниться, и все промежуточные страницы теряются.
2443
- if (ctx.getMode() === 'infinity' && !sourcePages.has(nextPage)) {
2444
- const capturedItems = activeSource.items() ?? [];
2445
- const pageSize = Math.max(1, activeSource.pageSize || ctx.getFallbackPageSize());
2446
- sourcePages.set(nextPage, capturedItems);
2447
- recordPageKnowledge(nextPage, capturedItems, pageSize);
2448
- }
2449
- })
2450
- .finally(() => {
2451
- pendingPages.delete(nextPage);
2452
- activeRequests = Math.max(0, activeRequests - 1);
2453
- bufferVersion.update((current) => current + 1);
2454
- if (queuedPages.length) {
2455
- queueMicrotask(() => drainQueuedPages());
2456
- }
2457
- });
2672
+ if (activeSource.loadPage) {
2673
+ const requestController = new AbortController();
2674
+ statelessRequestControllers.add(requestController);
2675
+ runPrefetchRequest(activeSource, nextPage, capturedGeneration, requestController, () => loadPageResult(activeSource, nextPage, requestController.signal), (result) => {
2676
+ if (!sourcePages.has(result.page)) {
2677
+ const capturedItems = [...result.items];
2678
+ sourcePages.set(result.page, capturedItems);
2679
+ recordPageKnowledge(result.page, capturedItems, result.pageSize || ctx.getFallbackPageSize());
2680
+ }
2681
+ });
2682
+ }
2683
+ else if (activeSource.updatePage) {
2684
+ runPrefetchRequest(activeSource, nextPage, capturedGeneration, null, () => activeSource.updatePage(nextPage), (result) => {
2685
+ if (!sourcePages.has(nextPage)) {
2686
+ // Capture legacy source state immediately so parallel completions cannot collapse to the last snapshot.
2687
+ const capturedItems = Array.isArray(result) ? [...result] : (activeSource.items() ?? []);
2688
+ const pageSize = Math.max(1, activeSource.pageSize || ctx.getFallbackPageSize());
2689
+ sourcePages.set(nextPage, capturedItems);
2690
+ recordPageKnowledge(nextPage, capturedItems, pageSize);
2691
+ }
2692
+ });
2693
+ }
2694
+ else {
2695
+ runPrefetchRequest(activeSource, nextPage, capturedGeneration, null, () => Promise.reject(new TypeError('Grid source must implement loadPage() or updatePage()')), () => undefined);
2696
+ }
2458
2697
  }
2459
2698
  };
2460
2699
  const contiguousLoadedRowCount = (source) => {
@@ -2471,16 +2710,16 @@ function createGridSourceDataFeature(ctx) {
2471
2710
  }
2472
2711
  return loaded;
2473
2712
  };
2474
- const resolvedTotalElements = (source) => {
2475
- if (typeof source.totalElements !== 'number' || !Number.isFinite(source.totalElements)) {
2713
+ const resolvedTotalElements = (source, totalElements = source.totalElements) => {
2714
+ if (typeof totalElements !== 'number' || !Number.isFinite(totalElements)) {
2476
2715
  return null;
2477
2716
  }
2478
- return Math.max(0, source.totalElements);
2717
+ return Math.max(0, totalElements);
2479
2718
  };
2480
2719
  const estimateOpenEndedPaginationTotal = (source) => {
2481
- const pageSize = Math.max(1, source.pageSize || ctx.getFallbackPageSize());
2482
- const page = Math.max(0, source.page || 0);
2483
- const itemsCount = source.items()?.length ?? 0;
2720
+ const pageSize = Math.max(1, effectivePageSize(source));
2721
+ const page = Math.max(0, currentPageResult?.page ?? source.page ?? 0);
2722
+ const itemsCount = effectiveItems(source).length;
2484
2723
  const loadedBefore = page * pageSize;
2485
2724
  const hasUnknownNextPage = itemsCount === pageSize;
2486
2725
  return loadedBefore + itemsCount + (hasUnknownNextPage ? pageSize : 0);
@@ -2515,11 +2754,15 @@ function createGridSourceDataFeature(ctx) {
2515
2754
  const localToAbsolutePage = (page) => pageBase + page;
2516
2755
  return {
2517
2756
  activePageSize,
2757
+ dataRowOffset,
2518
2758
  ensureBufferedRange,
2519
2759
  requestMultiSort,
2520
2760
  requestPage,
2521
2761
  requestRowCount,
2762
+ resetSourceBuffer: resetSession,
2763
+ renderRowCount,
2522
2764
  requestSort,
2765
+ resolvedBlockingLoading,
2523
2766
  resolvedLoading,
2524
2767
  rowAt,
2525
2768
  selectionRows,
@@ -2637,7 +2880,7 @@ function createGridVirtualScrollFeature(ctx) {
2637
2880
  total,
2638
2881
  });
2639
2882
  if (viewportHeight <= 0 || !isFinite(viewportHeight) || !isFinite(rowHeight)) {
2640
- const fallbackCount = Math.min(total, Math.max(1, ctx.getPageSize()));
2883
+ const fallbackCount = ctx.getMode() === 'pagination' ? Math.min(total, Math.max(1, ctx.getPageSize())) : total;
2641
2884
  ctx.setRenderCount(fallbackCount);
2642
2885
  ensureRenderSlots(fallbackCount);
2643
2886
  ctx.updateStickyRow(scrollTop, rowHeight, pinnedTopH);
@@ -3116,7 +3359,8 @@ class DataGrid {
3116
3359
  /**
3117
3360
  * Pagination mode: 'none', 'pagination', or 'infinity'.
3118
3361
  *
3119
- * - `none` - No pagination, all data is rendered
3362
+ * -
3363
+ one` - No pagination, all data is rendered
3120
3364
  * - `pagination` - Classic page-based pagination with fixed page size
3121
3365
  * - `infinity` - Infinite scroll mode, loads more data as user scrolls
3122
3366
  */
@@ -3165,6 +3409,10 @@ class DataGrid {
3165
3409
  * When selection is enabled, a `key` must be provided to identify rows.
3166
3410
  */
3167
3411
  selection = input(this.defaults.selection, ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
3412
+ /** Controlled selection values. When set, the consumer owns selection state. */
3413
+ selectedKeys = input(undefined, ...(ngDevMode ? [{ debugName: "selectedKeys" }] : /* istanbul ignore next */ []));
3414
+ /** Selection reconciliation policy. Defaults to preserving keys across source pages. */
3415
+ selectionPolicy = input('preserve-unloaded', ...(ngDevMode ? [{ debugName: "selectionPolicy" }] : /* istanbul ignore next */ []));
3168
3416
  /**
3169
3417
  * Number of items per page.
3170
3418
  *
@@ -3182,7 +3430,8 @@ class DataGrid {
3182
3430
  /**
3183
3431
  * Grid height configuration.
3184
3432
  *
3185
- * - `number` - Fixed height in pixels
3433
+ * -
3434
+ umber` - Fixed height in pixels
3186
3435
  * - `'full'` - Fill container height (100%), can be managed by host component style
3187
3436
  * - `'default'` - Height by CSS var (--re-data-grid-height)
3188
3437
  */
@@ -3264,6 +3513,8 @@ class DataGrid {
3264
3513
  * ```
3265
3514
  */
3266
3515
  pageChange = output();
3516
+ /** Emitted for a failed source request when the source has no error signal. */
3517
+ sourceError = output();
3267
3518
  /**
3268
3519
  * Event emitted when sort order changes.
3269
3520
  *
@@ -3286,6 +3537,8 @@ class DataGrid {
3286
3537
  * Contains an array of currently selected row keys.
3287
3538
  */
3288
3539
  selectChange = output();
3540
+ /** Emits proposed controlled selection values after user interaction. */
3541
+ selectedKeysChange = output();
3289
3542
  /**
3290
3543
  * Event emitted when a row is clicked.
3291
3544
  *
@@ -3345,7 +3598,7 @@ class DataGrid {
3345
3598
  isRowDisabled: (row, index) => this.isDisabledRow(row, index),
3346
3599
  getSelectionMode: () => this.selection().mode,
3347
3600
  selectRow: (row) => this.selector.select(row),
3348
- emitSelectChange: (selected) => this.selectChange.emit({ selected }),
3601
+ emitSelectChange: (selected) => this.emitSelectionChange(selected),
3349
3602
  emitCellClick: (payload) => this.cellClick.emit(payload),
3350
3603
  emitCellContext: (payload) => this.cellContext.emit(payload),
3351
3604
  emitCellDoubleClick: (payload) => this.cellDoubleClick.emit(payload),
@@ -3365,7 +3618,7 @@ class DataGrid {
3365
3618
  getPageSize: () => this.activePageSize(),
3366
3619
  isPageStartFromZero: () => this.pageStartFromZero(),
3367
3620
  isLoading: () => this.resolvedLoading(),
3368
- emitPageChange: (event) => this.requestPage(event),
3621
+ emitPageChange: (event) => this.handlePageRequest(event),
3369
3622
  });
3370
3623
  expanderFeature = createGridExpanderFeature({
3371
3624
  runUntracked: (fn) => untracked(fn),
@@ -3389,15 +3642,16 @@ class DataGrid {
3389
3642
  getSelection: () => this.selection(),
3390
3643
  getData: () => this.selectionRows(),
3391
3644
  getSelectedKeys: () => this.selector.selectedKeys(),
3645
+ getSelectionPolicy: () => this.selectionPolicy(),
3392
3646
  setSelectedKeys: (keys) => this.selector.selectedKeys.set(keys),
3393
- emitSelectChange: (keys) => this.selectChange.emit({ selected: keys }),
3647
+ emitSelectChange: (keys) => this.emitSelectionChange(keys),
3394
3648
  });
3395
3649
  gridApiFeature = createGridApiFeature({
3396
3650
  getSelectionFeature: () => this.selectionFeatureRef,
3397
3651
  getSelectionMode: () => this.selection().mode,
3398
3652
  clearSelectedKeys: () => this.selector.selectedKeys.set([]),
3399
3653
  selectAll: () => this.selector.selectAll(),
3400
- emitSelectChange: (selected) => this.selectChange.emit({ selected }),
3654
+ emitSelectChange: (selected) => this.emitSelectionChange(selected),
3401
3655
  loadSelectionFeature: () => this.loadSelectionFeature(),
3402
3656
  resetSort: () => this.sortFeature.resetSort(),
3403
3657
  setSort: (sort) => this.sortFeature.setSort(sort),
@@ -3415,10 +3669,11 @@ class DataGrid {
3415
3669
  getFallbackLoading: () => this.loading(),
3416
3670
  getFallbackPageSize: () => this.pageSize(),
3417
3671
  emitPageChange: (event) => this.pageChange.emit(event),
3672
+ emitSourceError: (event) => this.sourceError.emit(event),
3418
3673
  });
3419
3674
  virtualScrollFeature = createGridVirtualScrollFeature({
3420
3675
  getScrollElement: () => this.scrollEl()?.nativeElement ?? null,
3421
- getTotalCount: () => this.totalRowCount(),
3676
+ getTotalCount: () => this.sourceDataFeature.renderRowCount(),
3422
3677
  getRequestTotalCount: () => this.sourceDataFeature.requestRowCount(),
3423
3678
  getRowHeight: () => this.rowHeight(),
3424
3679
  getVirtualBuffer: () => this.virtualBuffer(),
@@ -3479,7 +3734,7 @@ class DataGrid {
3479
3734
  gapLoaderFeature = createGridGapLoaderFeature({
3480
3735
  hasSource: () => !!this.source(),
3481
3736
  getMode: () => this.mode(),
3482
- getTotalCount: () => this.totalRowCount(),
3737
+ getTotalCount: () => this.sourceDataFeature.renderRowCount(),
3483
3738
  getStartIndex: () => this.startIndex,
3484
3739
  getRenderCount: () => this.renderCount,
3485
3740
  isStickyRowIndex: (index) => this.isStickyRowIndex(index),
@@ -3520,6 +3775,10 @@ class DataGrid {
3520
3775
  stickyRowTpl = computed(() => this.stickyRowSlotRefs()?.at(0), ...(ngDevMode ? [{ debugName: "stickyRowTpl" }] : /* istanbul ignore next */ []));
3521
3776
  rowTpl = computed(() => this.rowSlotRefs()?.at(0), ...(ngDevMode ? [{ debugName: "rowTpl" }] : /* istanbul ignore next */ []));
3522
3777
  renderSlots = signal([], ...(ngDevMode ? [{ debugName: "renderSlots" }] : /* istanbul ignore next */ []));
3778
+ renderSlotEntries = computed(() => this.renderSlots().map((slot) => ({
3779
+ slot,
3780
+ key: this.trackVirtualRow(slot, this.startIndex, this.rowAt(this.startIndex + slot)),
3781
+ })), ...(ngDevMode ? [{ debugName: "renderSlotEntries" }] : /* istanbul ignore next */ []));
3523
3782
  renderCount = 0;
3524
3783
  lastStartIndex = -1;
3525
3784
  lastEndIndex = -1;
@@ -3533,13 +3792,15 @@ class DataGrid {
3533
3792
  visible: false,
3534
3793
  }, ...(ngDevMode ? [{ debugName: "tooltipState" }] : /* istanbul ignore next */ []));
3535
3794
  activeTooltipCellId = signal(null, ...(ngDevMode ? [{ debugName: "activeTooltipCellId" }] : /* istanbul ignore next */ []));
3536
- tooltipId = `re-dg-tooltip-${DataGrid.nextAriaId++}`;
3795
+ ariaInstanceId = DataGrid.nextAriaId++;
3796
+ tooltipId = `re-dg-tooltip-${this.ariaInstanceId}`;
3537
3797
  expanderRegionId = `re-dg-expander-${DataGrid.nextAriaId++}`;
3798
+ warnedPinnedIds = new Set();
3538
3799
  stickyRowIndex = signal(null, ...(ngDevMode ? [{ debugName: "stickyRowIndex" }] : /* istanbul ignore next */ []));
3539
3800
  stickyRowTopPx = signal(0, ...(ngDevMode ? [{ debugName: "stickyRowTopPx" }] : /* istanbul ignore next */ []));
3540
3801
  stickyRowData = computed(() => {
3541
3802
  const index = this.stickyRowIndex();
3542
- if (index === null || index < 0 || index >= this.totalRowCount()) {
3803
+ if (index === null || index < 0 || index >= this.renderRowCount()) {
3543
3804
  return null;
3544
3805
  }
3545
3806
  return this.rowAt(index);
@@ -3555,6 +3816,7 @@ class DataGrid {
3555
3816
  return normalizeDeclarativeColumns(this.declarativeColumnRefs().map((columnRef) => columnRef.toDeclarativeColumn()), this.rowKey());
3556
3817
  }, ...(ngDevMode ? [{ debugName: "declarativeColumns" }] : /* istanbul ignore next */ []));
3557
3818
  sourceColumns = computed(() => mergeDeclarativeColumns(this.declarativeColumns().columns, this.columns()), ...(ngDevMode ? [{ debugName: "sourceColumns" }] : /* istanbul ignore next */ []));
3819
+ resolvedHeaderTemplates = signal(new Map(), ...(ngDevMode ? [{ debugName: "resolvedHeaderTemplates" }] : /* istanbul ignore next */ []));
3558
3820
  slotsFeature = createGridSlotsFeature({
3559
3821
  clearTypeTemplates: () => this.vm.globalTypeCellTpls.clear(),
3560
3822
  clearDataTemplates: () => this.vm.globalDataCellTpls.clear(),
@@ -3562,6 +3824,7 @@ class DataGrid {
3562
3824
  setTypeTemplate: (type, tpl) => this.vm.globalTypeCellTpls.set(type, tpl),
3563
3825
  setDataTemplate: (key, tpl) => this.vm.globalDataCellTpls.set(key, tpl),
3564
3826
  setRowTemplate: (key, tpl) => this.vm.globalRowCellTpls.set(key, tpl),
3827
+ setHeaderTemplates: (templates) => this.resolvedHeaderTemplates.set(templates),
3565
3828
  getTypeTemplateRefs: () => this.cellTypedSlotRefs(),
3566
3829
  getDataTemplateRefs: () => this.cellDataSlotRefs(),
3567
3830
  getHeaderTemplateRefs: () => this.headerSlotRefs(),
@@ -3579,7 +3842,12 @@ class DataGrid {
3579
3842
  header: this.defaults.translations.indexColumnHeader,
3580
3843
  resizable: this.defaults.resizable,
3581
3844
  });
3582
- return [...newColumns, ...this.sourceColumns()];
3845
+ const resolvedHeaderTemplates = this.resolvedHeaderTemplates();
3846
+ const resolvedColumns = this.sourceColumns().map((column) => {
3847
+ const headerTemplate = resolvedHeaderTemplates.get(String(column.key));
3848
+ return !column.headerTemplate && headerTemplate ? { ...column, headerTemplate } : column;
3849
+ });
3850
+ return [...newColumns, ...resolvedColumns];
3583
3851
  }, ...(ngDevMode ? [{ debugName: "extendedColumns" }] : /* istanbul ignore next */ []));
3584
3852
  /**
3585
3853
  * Computed CSS height value based on height setting.
@@ -3595,7 +3863,9 @@ class DataGrid {
3595
3863
  return 'var(--re-data-grid-height)';
3596
3864
  }, ...(ngDevMode ? [{ debugName: "styleHeight" }] : /* istanbul ignore next */ []));
3597
3865
  resolvedLoading = computed(() => this.sourceDataFeature.resolvedLoading(), ...(ngDevMode ? [{ debugName: "resolvedLoading" }] : /* istanbul ignore next */ []));
3866
+ resolvedBlockingLoading = computed(() => this.sourceDataFeature.resolvedBlockingLoading(), ...(ngDevMode ? [{ debugName: "resolvedBlockingLoading" }] : /* istanbul ignore next */ []));
3598
3867
  totalRowCount = computed(() => this.sourceDataFeature.totalRowCount(), ...(ngDevMode ? [{ debugName: "totalRowCount" }] : /* istanbul ignore next */ []));
3868
+ renderRowCount = computed(() => this.sourceDataFeature.renderRowCount(), ...(ngDevMode ? [{ debugName: "renderRowCount" }] : /* istanbul ignore next */ []));
3599
3869
  selectionRows = computed(() => this.sourceDataFeature.selectionRows(), ...(ngDevMode ? [{ debugName: "selectionRows" }] : /* istanbul ignore next */ []));
3600
3870
  ariaColCount = computed(() => this.vm.columnsToShow().length, ...(ngDevMode ? [{ debugName: "ariaColCount" }] : /* istanbul ignore next */ []));
3601
3871
  ariaHeaderRowCount = computed(() => 1 + (this.vm.normalizedHeaderGroups().length ? 1 : 0), ...(ngDevMode ? [{ debugName: "ariaHeaderRowCount" }] : /* istanbul ignore next */ []));
@@ -3644,16 +3914,26 @@ class DataGrid {
3644
3914
  this.onVerticalScroll(true);
3645
3915
  },
3646
3916
  () => {
3647
- this.pinnedRows();
3648
- this.vm.pinnedRows.set(this.pinnedRows());
3917
+ const pinnedRows = this.pinnedRows();
3918
+ this.vm.pinnedRows.set(pinnedRows);
3919
+ this.warnDuplicatePinnedIds(pinnedRows);
3649
3920
  this.vm.containerWidth();
3650
3921
  this.onVerticalScroll();
3651
3922
  },
3652
3923
  () => this.infinityPageRequestFeature.onDataTotalChanged(this.sourceDataFeature.requestRowCount()),
3653
3924
  () => {
3654
3925
  const selection = this.selection();
3655
- if ('defaultSelected' in selection) {
3656
- this.selector.selectedKeys.set(selection.defaultSelected || []);
3926
+ const controlledSelectedKeys = this.selectedKeys();
3927
+ const defaultSelectedKeys = 'defaultSelectedKeys' in selection
3928
+ ? selection.defaultSelectedKeys
3929
+ : 'defaultSelected' in selection
3930
+ ? selection.defaultSelected
3931
+ : undefined;
3932
+ if (controlledSelectedKeys !== undefined) {
3933
+ this.selector.selectedKeys.set([...controlledSelectedKeys]);
3934
+ }
3935
+ else if (defaultSelectedKeys !== undefined) {
3936
+ this.selector.selectedKeys.set([...defaultSelectedKeys]);
3657
3937
  }
3658
3938
  if (selection.mode !== 'none') {
3659
3939
  void this.loadSelectionFeature();
@@ -3683,6 +3963,7 @@ class DataGrid {
3683
3963
  this.cleanupCallbacks.splice(0).forEach((cleanup) => cleanup());
3684
3964
  this.resizeObserverFeature.disconnect();
3685
3965
  this.infinityPageRequestFeature.reset();
3966
+ this.overlayScrollFeatureRef?.destroy();
3686
3967
  clearTimeout(this.hideSbTimeout);
3687
3968
  this.headerMeasureFeature.clearMeasure();
3688
3969
  this.clearScrollRaf();
@@ -3706,6 +3987,22 @@ class DataGrid {
3706
3987
  this.gridApiFeature.resetSort();
3707
3988
  this.sourceDataFeature.requestMultiSort([]);
3708
3989
  }
3990
+ /** Clears the grid-owned source page buffer and invalidates in-flight page results. */
3991
+ resetSourceBuffer() {
3992
+ this.sourceDataFeature.resetSourceBuffer();
3993
+ }
3994
+ /** Requests a page through the source contract or legacy pageChange output. */
3995
+ requestPage(page) {
3996
+ this.handlePageRequest({ page: Math.max(0, page), rows: this.activePageSize() });
3997
+ }
3998
+ /** Changes the page size and restarts from page zero through the shared request path. */
3999
+ requestPageSize(pageSize) {
4000
+ this.handlePageRequest({ page: 0, rows: pageSize });
4001
+ }
4002
+ /** Retries the current source page, or an explicitly supplied page. */
4003
+ retryPage(page = this.source()?.page ?? 0) {
4004
+ this.requestPage(page);
4005
+ }
3709
4006
  /** Sets a single-column sorting state and emits sort events. */
3710
4007
  setSort(sort) {
3711
4008
  this.gridApiFeature.setSort(sort);
@@ -3739,6 +4036,11 @@ class DataGrid {
3739
4036
  onColumnResizeStart(event, col) {
3740
4037
  this.columnResizeFeature.onResizeStart(event, col);
3741
4038
  }
4039
+ onColumnResizeKeydown(event, col) {
4040
+ if (event instanceof KeyboardEvent) {
4041
+ this.columnResizeFeature.onResizeKeydown(event, col);
4042
+ }
4043
+ }
3742
4044
  /**
3743
4045
  * Handles cell click events.
3744
4046
  *
@@ -3773,7 +4075,7 @@ class DataGrid {
3773
4075
  if (this.isDisabledRow(row, index) || this.selection().mode === 'none') {
3774
4076
  return;
3775
4077
  }
3776
- this.selectChange.emit({ selected: this.selector.select(row) });
4078
+ this.emitSelectionChange(this.selector.select(row));
3777
4079
  void this.loadSelectionFeature();
3778
4080
  }
3779
4081
  onSelectAllKeydown(event) {
@@ -3799,6 +4101,48 @@ class DataGrid {
3799
4101
  onRowClick(row, index, event) {
3800
4102
  this.rowInteractionsFeature.onRowClick(row, index, event);
3801
4103
  }
4104
+ onRowKeydown(index, event) {
4105
+ if (!(event instanceof KeyboardEvent)) {
4106
+ return;
4107
+ }
4108
+ const direction = event.key === 'ArrowDown' ? 1 : event.key === 'ArrowUp' ? -1 : 0;
4109
+ if (!direction) {
4110
+ return;
4111
+ }
4112
+ const targetIndex = Math.max(0, Math.min(this.renderRowCount() - 1, index + direction));
4113
+ if (targetIndex === index) {
4114
+ return;
4115
+ }
4116
+ event.preventDefault();
4117
+ this.focusVirtualRow(targetIndex);
4118
+ }
4119
+ focusVirtualRow(index) {
4120
+ const scrollEl = this.scrollEl()?.nativeElement;
4121
+ if (!scrollEl) {
4122
+ return;
4123
+ }
4124
+ const focusTarget = () => {
4125
+ const target = scrollEl.querySelector(`[data-re-dg-row-index="${index}"]`);
4126
+ if (!target) {
4127
+ return false;
4128
+ }
4129
+ target.focus({ preventScroll: true });
4130
+ return true;
4131
+ };
4132
+ if (focusTarget()) {
4133
+ return;
4134
+ }
4135
+ scrollEl.scrollTop = Math.max(0, index * this.rowHeight());
4136
+ scrollEl.dispatchEvent(new Event('scroll'));
4137
+ let remainingFrames = 3;
4138
+ const focusWhenRendered = () => {
4139
+ if (focusTarget() || --remainingFrames === 0) {
4140
+ return;
4141
+ }
4142
+ requestAnimationFrame(focusWhenRendered);
4143
+ };
4144
+ requestAnimationFrame(focusWhenRendered);
4145
+ }
3802
4146
  onRowContext(row, index, event) {
3803
4147
  this.rowInteractionsFeature.onRowContext(row, index, event);
3804
4148
  }
@@ -3846,7 +4190,7 @@ class DataGrid {
3846
4190
  * to track thumb position and update scroll position accordingly.
3847
4191
  * Automatically cleans up listeners when dragging ends.
3848
4192
  *
3849
- * @param e - Mouse down event from a scrollbar thumb element
4193
+ * @param e - Pointer down event from a scrollbar thumb element
3850
4194
  */
3851
4195
  onThumbDown(e) {
3852
4196
  if (this.overlayScrollFeatureRef) {
@@ -3876,7 +4220,7 @@ class DataGrid {
3876
4220
  this.hideSbTimeout = setTimeout(() => this.vm.scrollbarVisible.set(false), delay);
3877
4221
  void this.loadOverlayScrollFeature();
3878
4222
  }
3879
- trackPinnedRow = (row) => row.order;
4223
+ trackPinnedRow = (row, region, index) => row.id ?? `${region}-${index}`;
3880
4224
  isDisabledRow(row, index) {
3881
4225
  if (index < 0) {
3882
4226
  return false;
@@ -3917,6 +4261,13 @@ class DataGrid {
3917
4261
  this.activeTooltipCellId.set(cellId);
3918
4262
  this.showTooltip(event, row, col, index);
3919
4263
  }
4264
+ onTooltipFocus(event, row, col, index, cellId) {
4265
+ const element = event.currentTarget instanceof HTMLElement ? event.currentTarget : null;
4266
+ const rect = element?.getBoundingClientRect();
4267
+ const x = rect ? rect.left + rect.width / 2 : 0;
4268
+ const y = rect ? rect.top + rect.height / 2 : 0;
4269
+ this.onTooltipEnter({ clientX: x, clientY: y }, row, col, index, cellId);
4270
+ }
3920
4271
  isStickyRowIndex(index) {
3921
4272
  return this.stickyFeatureRef?.isStickyRowIndex(index) ?? false;
3922
4273
  }
@@ -3932,6 +4283,19 @@ class DataGrid {
3932
4283
  }
3933
4284
  rowAt(index) {
3934
4285
  return this.sourceDataFeature.rowAt(index);
4286
+ } /**
4287
+ * Keys virtual row views by record identity rather than by recyclable slot.
4288
+ * Without a rowKey, the absolute index still prevents a replaced row from inheriting slot state.
4289
+ */
4290
+ trackVirtualRow(slot, startIndex, row) {
4291
+ const rowIndex = startIndex + slot;
4292
+ const currentRow = row ?? this.rowAt(rowIndex);
4293
+ const rowKey = this.rowKey();
4294
+ if (!currentRow || !rowKey) {
4295
+ return `index-${rowIndex}`;
4296
+ }
4297
+ const key = typeof rowKey === 'function' ? rowKey(currentRow) : currentRow[rowKey];
4298
+ return `row-${String(key)}`;
3935
4299
  }
3936
4300
  shouldRenderLoadingRow(index, topGap, bottomGap) {
3937
4301
  return this.gapLoaderFeature.shouldRenderInnerSkeleton(index, topGap, bottomGap);
@@ -3947,7 +4311,7 @@ class DataGrid {
3947
4311
  return this.readResolvedHeaderText(cacheKey, () => this.headerTextResolver(col.header, { kind: 'column', column: col }));
3948
4312
  }
3949
4313
  ariaDataRowIndex(index) {
3950
- return this.ariaHeaderRowCount() + this.vm.pinnedTop().length + index + 1;
4314
+ return this.ariaHeaderRowCount() + this.vm.pinnedTop().length + this.sourceDataFeature.dataRowOffset() + index + 1;
3951
4315
  }
3952
4316
  ariaPinnedTopRowIndex(index) {
3953
4317
  return this.ariaHeaderRowCount() + index + 1;
@@ -3972,6 +4336,15 @@ class DataGrid {
3972
4336
  ariaResizeLabel(col) {
3973
4337
  return `Resize column ${this.resolveHeaderText(col)}`;
3974
4338
  }
4339
+ ariaResizeMin(col) {
4340
+ return Math.max(0, col.minWidth ?? 40);
4341
+ }
4342
+ ariaResizeMax(col) {
4343
+ return typeof col.maxWidth === 'number' ? col.maxWidth : null;
4344
+ }
4345
+ ariaResizeValue(col) {
4346
+ return this.vm.widthByKey(col.key);
4347
+ }
3975
4348
  ariaHeaderGroupColIndex(group) {
3976
4349
  if (!group.startKey) {
3977
4350
  return null;
@@ -3980,7 +4353,10 @@ class DataGrid {
3980
4353
  return colIndex >= 0 ? colIndex + 1 : null;
3981
4354
  }
3982
4355
  cellAriaId(colKey, rowIndex, isPinned) {
3983
- return `re-dg-cell-${isPinned ? 'p' : 'r'}-${rowIndex}-${String(colKey)}`;
4356
+ return `re-dg-cell-${this.ariaInstanceId}-${isPinned ? 'p' : 'r'}-${rowIndex}-${String(colKey)}`;
4357
+ }
4358
+ pinnedCellAriaId(colKey, row, region, index) {
4359
+ return `re-dg-cell-${this.ariaInstanceId}-p-${region}-${row.id ?? index}-${String(colKey)}`;
3984
4360
  }
3985
4361
  isTooltipTarget(cellId) {
3986
4362
  return this.tooltipState().visible && this.activeTooltipCellId() === cellId;
@@ -4003,7 +4379,36 @@ class DataGrid {
4003
4379
  activePageSize() {
4004
4380
  return this.sourceDataFeature.activePageSize();
4005
4381
  }
4006
- requestPage(event) {
4382
+ warnDuplicatePinnedIds(rows) {
4383
+ if (!ngDevMode) {
4384
+ return;
4385
+ }
4386
+ for (const region of ['top', 'bottom']) {
4387
+ const seen = new Set();
4388
+ for (const row of rows) {
4389
+ if (row.position !== region || row.id === undefined) {
4390
+ continue;
4391
+ }
4392
+ if (seen.has(row.id)) {
4393
+ const warningKey = `${region}:${row.id}`;
4394
+ if (!this.warnedPinnedIds.has(warningKey)) {
4395
+ this.warnedPinnedIds.add(warningKey);
4396
+ console.warn(`[DataGrid] Duplicate pinned row id "${row.id}" in the ${region} region.`);
4397
+ }
4398
+ }
4399
+ seen.add(row.id);
4400
+ }
4401
+ }
4402
+ }
4403
+ emitSelectionChange(selected) {
4404
+ this.selectChange.emit({ selected: [...selected] });
4405
+ this.selectedKeysChange.emit([...selected]);
4406
+ const controlledSelectedKeys = this.selectedKeys();
4407
+ if (controlledSelectedKeys !== undefined) {
4408
+ this.selector.selectedKeys.set([...controlledSelectedKeys]);
4409
+ }
4410
+ }
4411
+ handlePageRequest(event) {
4007
4412
  this.sourceDataFeature.requestPage(event);
4008
4413
  }
4009
4414
  initVm() {
@@ -4087,7 +4492,7 @@ class DataGrid {
4087
4492
  clearSelectedKeys: () => this.selector.selectedKeys.set([]),
4088
4493
  selectAll: () => this.selector.selectAll(),
4089
4494
  selectRow: (row) => this.selector.select(row),
4090
- emitSelectChange: (selected) => this.selectChange.emit({ selected }),
4495
+ emitSelectChange: (selected) => this.emitSelectionChange(selected),
4091
4496
  isRowDisabled: (row, index) => this.isDisabledRow(row, index),
4092
4497
  });
4093
4498
  this.selectionFeatureRef = feature;
@@ -4121,7 +4526,7 @@ class DataGrid {
4121
4526
  if (this.overlayScrollFeaturePromise) {
4122
4527
  return this.overlayScrollFeaturePromise;
4123
4528
  }
4124
- this.overlayScrollFeaturePromise = import('./reforgium-data-grid-grid-overlay-scroll.feature-DQp-sU6c.mjs').then(({ createGridOverlayScrollFeature }) => {
4529
+ this.overlayScrollFeaturePromise = import('./reforgium-data-grid-grid-overlay-scroll.feature-XfJnWjT5.mjs').then(({ createGridOverlayScrollFeature }) => {
4125
4530
  const feature = createGridOverlayScrollFeature({
4126
4531
  getScrollElement: () => this.scrollEl()?.nativeElement ?? null,
4127
4532
  getThumbTop: () => this.vm.thumbTopPx(),
@@ -4234,16 +4639,19 @@ class DataGrid {
4234
4639
  void this.loadStickyFeature().then((feature) => feature.updateStickyFromScroll());
4235
4640
  }
4236
4641
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DataGrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
4237
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: DataGrid, isStandalone: true, selector: "re-data-grid", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, pinnedRows: { classPropertyName: "pinnedRows", publicName: "pinnedRows", isSignal: true, isRequired: false, transformFunction: null }, isRowSticky: { classPropertyName: "isRowSticky", publicName: "isRowSticky", isSignal: true, isRequired: false, transformFunction: null }, isRowDisabled: { classPropertyName: "isRowDisabled", publicName: "isRowDisabled", isSignal: true, isRequired: false, transformFunction: null }, getRowClass: { classPropertyName: "getRowClass", publicName: "getRowClass", isSignal: true, isRequired: false, transformFunction: null }, getRowTemplate: { classPropertyName: "getRowTemplate", publicName: "getRowTemplate", isSignal: true, isRequired: false, transformFunction: null }, hasIndexColumn: { classPropertyName: "hasIndexColumn", publicName: "hasIndexColumn", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, virtualBuffer: { classPropertyName: "virtualBuffer", publicName: "virtualBuffer", isSignal: true, isRequired: false, transformFunction: null }, lockVerticalScroll: { classPropertyName: "lockVerticalScroll", publicName: "lockVerticalScroll", isSignal: true, isRequired: false, transformFunction: null }, headerGroups: { classPropertyName: "headerGroups", publicName: "headerGroups", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMode: { classPropertyName: "loadingMode", publicName: "loadingMode", isSignal: true, isRequired: false, transformFunction: null }, deferContent: { classPropertyName: "deferContent", publicName: "deferContent", isSignal: true, isRequired: false, transformFunction: null }, deferHeader: { classPropertyName: "deferHeader", publicName: "deferHeader", isSignal: true, isRequired: false, transformFunction: null }, deferPinned: { classPropertyName: "deferPinned", publicName: "deferPinned", isSignal: true, isRequired: false, transformFunction: null }, deferCells: { classPropertyName: "deferCells", publicName: "deferCells", isSignal: true, isRequired: false, transformFunction: null }, deferIcons: { classPropertyName: "deferIcons", publicName: "deferIcons", isSignal: true, isRequired: false, transformFunction: null }, deferTooltip: { classPropertyName: "deferTooltip", publicName: "deferTooltip", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, pageStartFromZero: { classPropertyName: "pageStartFromZero", publicName: "pageStartFromZero", isSignal: true, isRequired: false, transformFunction: null }, sortMode: { classPropertyName: "sortMode", publicName: "sortMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", sortChange: "sortChange", multiSortChange: "multiSortChange", selectChange: "selectChange", rowClick: "rowClick", rowContext: "rowContext", rowDoubleClick: "rowDoubleClick", cellClick: "cellClick", cellContext: "cellContext", cellDoubleClick: "cellDoubleClick", columnResizeEnd: "columnResizeEnd" }, providers: [DataGridVm], queries: [{ propertyName: "cellTypedSlotRefs", predicate: DataGridTypeCellTemplateDirective, isSignal: true }, { propertyName: "cellDataSlotRefs", predicate: DataGridCellTemplateDirective, isSignal: true }, { propertyName: "declarativeColumnRefs", predicate: DataGridDeclarativeColumn, isSignal: true }, { propertyName: "headerSlotRefs", predicate: DataGridHeaderTemplateDirective, isSignal: true }, { propertyName: "emptySlotRefs", predicate: DataGridCellEmptyDirective, isSignal: true }, { propertyName: "loadingSlotRefs", predicate: DataGridCellLoadingDirective, isSignal: true }, { propertyName: "sortIcSlotRefs", predicate: DataGridSortIconDirective, isSignal: true }, { propertyName: "expanderIcSlotRefs", predicate: DataGridExpanderIconDirective, isSignal: true }, { propertyName: "stickyRowSlotRefs", predicate: DataGridStickyRowDirective, isSignal: true }, { propertyName: "rowSlotRefs", predicate: DataGridRowDirective, isSignal: true }], viewQueries: [{ propertyName: "rootEl", first: true, predicate: ["root"], descendants: true, isSignal: true }, { propertyName: "scrollEl", first: true, predicate: ["scroll"], descendants: true, isSignal: true }, { propertyName: "headerEl", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "tooltipEl", first: true, predicate: ["tooltip"], descendants: true, isSignal: true }], ngImport: i0, template: "@let items = selectionRows();\r\n@let totalRows = totalRowCount();\r\n@let empty = !resolvedLoading() && !totalRows;\r\n@let notEmpty = !!totalRows;\r\n@let skeletonRowsCount = 4;\r\n@let skeletonMode = loadingMode() === 'skeleton';\r\n@let spinnerMode = loadingMode() === 'spinner';\r\n@let showInfinitySkeleton = resolvedLoading() && skeletonMode && mode() === 'infinity';\r\n@let showPaginationSkeleton = resolvedLoading() && skeletonMode && mode() === 'pagination' && !notEmpty;\r\n@let showSpinnerLoading = resolvedLoading() && spinnerMode;\r\n@let extraInfinitySkeletonRows = showInfinitySkeleton ? skeletonRowsCount : 0;\r\n\r\n@let pinnedTopH = vm.pinnedTop().length * rowHeight();\r\n@let pinnedBottomH = vm.pinnedBottom().length * rowHeight();\r\n@let rowH = rowHeight();\r\n@let contentW = vm.contentWidth();\r\n@let cols = vm.columnsToShow();\r\n@let stickyTop = pinnedTopH + headerHeight();\r\n@let normalizedHeaderGroups = vm.normalizedHeaderGroups();\r\n@let stickyRow = stickyRowData();\r\n@let stickyIndex = stickyRowIndex();\r\n\r\n<div\r\n #root\r\n class=\"re-dg-root\"\r\n [attr.id]=\"expanderRegionId\"\r\n [class.re-dg-loading]=\"showSpinnerLoading\"\r\n [class.lock-vertical-scroll]=\"lockVerticalScroll()\"\r\n [class.resizing-columns]=\"isColumnResizing()\"\r\n [style.height]=\"styleHeight()\"\r\n [attr.aria-multiselectable]=\"selection().mode === 'multi' ? true : null\"\r\n [attr.aria-rowcount]=\"ariaRowCount()\"\r\n [attr.aria-colcount]=\"ariaColCount()\"\r\n role=\"grid\"\r\n>\r\n @if (showSpinnerLoading) {\r\n <div class=\"re-dg-loader\" aria-live=\"polite\" role=\"status\">\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n <span class=\"re-dg-loader-spinner\" aria-label=\"Loading\"></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n #scroll\r\n class=\"re-dg-body\"\r\n role=\"rowgroup\"\r\n (mouseenter)=\"showScrollbar()\"\r\n (mouseleave)=\"hideScrollbarSoon()\"\r\n >\r\n <ng-template #headerContent>\r\n <div\r\n class=\"re-dg-header\"\r\n role=\"rowgroup\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n >\r\n <div #header class=\"re-dg-header-rows\">\r\n @if (normalizedHeaderGroups.length) {\r\n <div class=\"re-dg-row re-dg-header-group-row\" role=\"row\" [style.width.px]=\"vm.contentWidth()\" [style.min-width.%]=\"100\">\r\n @for (group of normalizedHeaderGroups; track group.key; let groupIndex = $index) {\r\n @let groupStickyLeft = !!group.startKey && !!group.endKey && vm.isStickyLeft(group.startKey) && vm.isStickyLeft(group.endKey);\r\n @let groupStickyRight = !!group.startKey && !!group.endKey && vm.isStickyRight(group.startKey) && vm.isStickyRight(group.endKey);\r\n\r\n @let resolvedGroupTitle = resolveHeaderGroupTitle(group);\r\n\r\n <div\r\n class=\"re-dg-header-cell re-dg-header-group-cell\"\r\n role=\"columnheader\"\r\n [class.sticky-left]=\"groupStickyLeft\"\r\n [class.sticky-right]=\"groupStickyRight\"\r\n [style.left.px]=\"groupStickyLeft && group.startKey ? vm.stickyOffset(group.startKey, 'left') : null\"\r\n [style.right.px]=\"groupStickyRight && group.endKey ? vm.stickyOffset(group.endKey, 'right') : null\"\r\n [style.width.px]=\"group.widthPx\"\r\n [style.justify-content]=\"group.align || 'left'\"\r\n [title]=\"resolvedGroupTitle\"\r\n [attr.aria-colindex]=\"ariaHeaderGroupColIndex(group)\"\r\n [attr.aria-rowindex]=\"groupIndex + 1\"\r\n >\r\n @if (group.titleTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"group.titleTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedGroupTitle }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedGroupTitle }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"re-dg-row re-dg-header-row\" role=\"row\" [style.width.px]=\"vm.contentWidth()\" [style.min-width.%]=\"100\">\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-header-cell\"\r\n role=\"columnheader\"\r\n [class.sortable]=\"!!col.sortKey\"\r\n [class.active-sort]=\"isActiveSort(col)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [style.min-width.px]=\"col.minWidth || null\"\r\n [style.max-width.px]=\"col.maxWidth || null\"\r\n [style.justify-content]=\"col.align || 'left'\"\r\n [attr.aria-sort]=\"ariaSort(col)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-rowindex]=\"normalizedHeaderGroups.length ? 2 : 1\"\r\n [attr.aria-label]=\"col.sortKey ? ariaSortLabel(col) : null\"\r\n [attr.tabindex]=\"col.sortKey ? 0 : -1\"\r\n (click)=\"col.sortKey && onSort(col)\"\r\n (keydown.enter)=\"col.sortKey && onSort(col)\"\r\n >\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isMultiSelect = selection().mode === 'multi';\r\n\r\n @if (isCheckbox && isMultiSelect) {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\" />\r\n }\r\n } @else {\r\n @let resolvedHeader = resolveHeaderText(col);\r\n\r\n @if (col.headerTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"col.headerTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedHeader }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedHeader }}</span>\r\n }\r\n }\r\n\r\n @if (col.sortKey) {\r\n <span class=\"re-dg-sort-ind\">\r\n @let direction = sortOrderFor(col);\r\n\r\n @if (sortTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"sortTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: direction }\"\r\n />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-sort-ic [direction]=\"direction\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-sort-ic [direction]=\"direction\" />\r\n }\r\n }\r\n </span>\r\n }\r\n\r\n @if (isExpandable(col)) {\r\n <button\r\n [attr.aria-controls]=\"expanderRegionId\"\r\n [attr.aria-expanded]=\"expanderMap().get(col.key) ? 'true' : 'false'\"\r\n [attr.aria-label]=\"ariaExpandLabel(col)\"\r\n (click)=\"$event.stopPropagation(); onExpand(col)\"\r\n >\r\n @let expanded = expanderMap().get(col.key);\r\n\r\n @if (expanderTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"expanderTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: expanded }\" />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n }\r\n }\r\n </button>\r\n }\r\n\r\n @if (canResizeColumn(col)) {\r\n <button\r\n class=\"re-dg-column-resize-handle\"\r\n aria-orientation=\"vertical\"\r\n role=\"separator\"\r\n [attr.aria-label]=\"ariaResizeLabel(col)\"\r\n (mousedown)=\"onColumnResizeStart($event, col)\"\r\n (click)=\"$event.stopPropagation()\"\r\n ></button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- PINNED TOP ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedTopContent>\r\n @for (pr of vm.pinnedTop(); track trackPinnedRow(pr); let pinnedTopIndex = $index) {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-top\" role=\"row\" [style.width.px]=\"contentW\" [style.min-width.%]=\"100\" [attr.aria-rowindex]=\"ariaPinnedTopRowIndex(pinnedTopIndex)\">\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n } @loading {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferHeader()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n } @loading {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n }\r\n\r\n <ng-template #dataCellContent let-row let-col=\"col\" let-index=\"index\" let-isPinned=\"isPinned\">\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n\r\n @if (isCheckbox) {\r\n <re-checkbox-ic\r\n aria-label=\"Toggle row selection\"\r\n [state]=\"selector.isSelected(row)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, index)\"\r\n [attr.tabindex]=\"isDisabledRow(row, index) ? -1 : 0\"\r\n (click)=\"onCheckboxToggle(row, index, $event)\"\r\n (keydown.enter)=\"onCheckboxKeydown(row, index, $event)\"\r\n (keydown.space)=\"onCheckboxKeydown(row, index, $event)\" />\r\n } @else {\r\n @if (deferCells()) {\r\n @defer (when true) {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n } @placeholder {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n } @loading {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n }\r\n } @else {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n <ng-template #gridContent>\r\n\r\n <!-- STICKY ROW -->\r\n @if (stickyRow && stickyIndex !== null) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-sticky-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(stickyRow, stickyIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.top.px]=\"stickyRowTopPx()\"\r\n [attr.aria-rowindex]=\"ariaDataRowIndex(stickyIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(stickyRow) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(stickyRow, stickyIndex, $event)\"\r\n (contextmenu)=\"onRowContext(stickyRow, stickyIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(stickyRow, stickyIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(stickyRow, stickyIndex, $event)\"\r\n >\r\n @let stickyTemplate = stickyRowTpl();\r\n @let rowTemplate = resolveRowTemplate(stickyRow, stickyIndex);\r\n\r\n @if (stickyTemplate?.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"stickyTemplate!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, index: stickyIndex }\"\r\n />\r\n } @else if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: stickyRow,\r\n index: stickyIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: true\r\n }\"\r\n />\r\n } @else {\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, stickyRow)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, stickyIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, stickyIndex, false)) ? tooltipId : null\"\r\n [attr.tabindex]=\"0\"\r\n (mouseenter)=\"onTooltipEnter($event, stickyRow, col, stickyIndex, cellAriaId(col.key, stickyIndex, false))\"\r\n (mouseleave)=\"hideTooltip()\"\r\n (click)=\"onCellClick(stickyRow, col, stickyIndex, $event);\"\r\n (contextmenu)=\"onCellContext(stickyRow, col, stickyIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(stickyRow, col, stickyIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(stickyRow, col, stickyIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, col: col, index: stickyIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n @if (empty) {\r\n @let emptyTemplate = emptyTpl()?.tpl;\r\n\r\n <div class=\"re-dg-empty\" aria-live=\"polite\" role=\"status\">\r\n @if (emptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\" />\r\n } @else {\r\n <span class=\"re-dg-empty-text\">{{ defaults.translations.emptyState }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Content -->\r\n @if (notEmpty) {\r\n @let topGap = topGapLoader();\r\n @let bottomGap = bottomGapLoader();\r\n <div\r\n class=\"re-dg-spacer\"\r\n [style.width.px]=\"contentW\"\r\n [style.height.px]=\"(totalRows + extraInfinitySkeletonRows) * rowH - pinnedBottomH\"></div>\r\n\r\n @if (topGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"topGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (topGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n\r\n @for (slot of renderSlots(); track slot) {\r\n @let rowIndex = startIndex + slot;\r\n @let row = rowAt(rowIndex);\r\n @let rowTemplate = row ? resolveRowTemplate(row, rowIndex) : null;\r\n\r\n @if (row && !isStickyRowIndex(rowIndex)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(row, rowIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n [attr.aria-rowindex]=\"ariaDataRowIndex(rowIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(row) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(row, rowIndex, $event)\"\r\n (contextmenu)=\"onRowContext(row, rowIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(row, rowIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(row, rowIndex, $event)\"\r\n >\r\n @if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: row,\r\n index: rowIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: false\r\n }\"\r\n />\r\n } @else {\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, row)\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, rowIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, rowIndex, false)) ? tooltipId : null\"\r\n [attr.tabindex]=\"0\"\r\n (mouseenter)=\"onTooltipEnter($event, row, col, rowIndex, cellAriaId(col.key, rowIndex, false))\"\r\n (mouseleave)=\"hideTooltip()\"\r\n (click)=\"onCellClick(row, col, rowIndex, $event);\"\r\n (contextmenu)=\"onCellContext(row, col, rowIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(row, col, rowIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(row, col, rowIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: row, col: col, index: rowIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n } @else if (shouldRenderLoadingRow(rowIndex, topGap, bottomGap)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (bottomGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"bottomGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (bottomGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (showInfinitySkeleton || showPaginationSkeleton) {\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n @for (si of [0, 1, 2, 3]; track si) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (((showInfinitySkeleton ? items.length : 0) + si) * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n <!-- PINNED BOTTOM ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedBottomContent>\r\n <div class=\"re-dg-footer\" role=\"rowgroup\">\r\n @for (pr of vm.pinnedBottom(); track trackPinnedRow(pr); let pinnedBottomIndex = $index) {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-bottom\" role=\"row\" [style.width.px]=\"contentW\" [style.min-width.%]=\"100\" [attr.aria-rowindex]=\"ariaPinnedBottomRowIndex(pinnedBottomIndex)\">\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n } @loading {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n @if (deferContent()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n } @loading {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n }\r\n </div>\r\n\r\n <ng-template #pinnedRowCells let-row>\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isIndex = 'type' in col && col.type === 'index';\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, $any(row))\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.height.px]=\"rowH\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, -1, true)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, -1, true)) ? tooltipId : null\"\r\n [attr.tabindex]=\"isCheckbox || isIndex ? -1 : 0\"\r\n (mouseenter)=\"!isCheckbox && !isIndex && onTooltipEnter($event, $any(row), col, -1, cellAriaId(col.key, -1, true))\"\r\n (mouseleave)=\"!isCheckbox && !isIndex && hideTooltip()\"\r\n (click)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event);\"\r\n (contextmenu)=\"!isCheckbox && !isIndex && onCellContext($any(row), col, -1, $event)\"\r\n (dblclick)=\"!isCheckbox && !isIndex && onCellDoubleClick($any(row), col, -1, $event)\"\r\n (keydown.enter)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event)\"\r\n >\r\n @if (!isCheckbox && !isIndex) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: $any(row), col: col, index: -1, isPinned: true }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferTooltip()) {\r\n @defer (when true) {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tooltipStateValue.tpl\"\r\n [ngTemplateOutletContext]=\"tooltipStateValue.ctx\"\r\n />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tooltipStateValue.tpl\"\r\n [ngTemplateOutletContext]=\"tooltipStateValue.ctx\"\r\n />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Overlay scrollbar -->\r\n <div class=\"re-dg-scrollbar\" [class.visible]=\"vm.scrollbarVisible()\">\r\n <div\r\n class=\"re-dg-scrollbar-thumb\"\r\n role=\"scrollbar\"\r\n aria-orientation=\"vertical\"\r\n aria-hidden=\"false\"\r\n [style.height.px]=\"vm.thumbHeightPx()\"\r\n [style.transform]=\"'translateY(' + vm.thumbTopPx() + 'px)'\"\r\n (mousedown)=\"onThumbDown($event)\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [":host{--re-data-grid-min-height: 200px;--re-data-grid-height: 400px;--re-data-grid-rounded: var(--radius-md, 6px);--re-data-grid-separator-color: var(--border-color);--re-data-grid-separator: 1px solid var(--re-data-grid-separator-color);--re-data-grid-surface: var(--surface-neutral, #fff);--re-data-grid-active: var(--primary-color, #2a90f4);--re-data-grid-empty-color: #777;--re-data-grid-empty-surface: transparent;--re-data-grid-loading-color: #444;--re-data-grid-loading-surface: rgba(255, 255, 255, .5);--re-data-grid-spinner-size: 2rem;--re-data-grid-spinner-width: .25rem;--re-data-grid-spinner-track-color: rgba(0, 0, 0, .12);--re-data-grid-skeleton-width: 100%;--re-data-grid-skeleton-height: 100%;--re-data-grid-skeleton-rounded: var(--re-data-grid-rounded, .75rem);--re-data-grid-skeleton-shine: rgba(255, 255, 255, .8);--re-data-grid-skeleton-line: #e7ebf0;--re-data-grid-scrollbar-size: 4px;--re-data-grid-scrollbar-offset: 2px;--re-data-grid-scrollbar-track-rounded: .25rem;--re-data-grid-scrollbar-track-surface: transparent;--re-data-grid-scrollbar-thumb-size: 8px;--re-data-grid-scrollbar-thumb-color: rgba(0, 0, 0, .25);--re-data-grid-scrollbar-thumb-active-color: rgba(0, 0, 0, .45);--re-data-grid-scrollbar-thumb-rounded: var(--re-data-grid-scrollbar-track-rounded);--re-data-grid-tooltip-surface: #0f172a;--re-data-grid-tooltip-color: #f8fafc;--re-data-grid-tooltip-radius: .5rem;--re-data-grid-tooltip-padding: .4rem .6rem;--re-data-grid-tooltip-shadow: 0 8px 24px rgba(15, 23, 42, .25);--re-data-grid-tooltip-z: 60;--re-data-grid-header-rounded: var(--re-data-grid-rounded);--re-data-grid-header-surface: #fff;--re-data-grid-header-body-gap: 0px;--re-data-grid-header-row-height: 40px;--re-data-grid-header-row-separator-color: #ccc;--re-data-grid-header-row-separator: 1px solid var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-height: var(--re-data-grid-header-row-height);--re-data-grid-header-group-row-separator-color: var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-separator: 1px solid var(--re-data-grid-header-group-row-separator-color);--re-data-grid-header-group-cell-font-weight: var(--re-data-grid-header-cell-font-weight);--re-data-grid-header-group-cell-font-size: var(--re-data-grid-header-cell-font-size);--re-data-grid-header-group-cell-color: var(--re-data-grid-header-cell-color);--re-data-grid-header-group-cell-surface: var(--re-data-grid-header-cell-surface);--re-data-grid-header-cell-font-weight: 600;--re-data-grid-header-cell-font-size: .8rem;--re-data-grid-header-cell-color: #000;--re-data-grid-header-cell-surface: #fafafa;--re-data-grid-header-cell-line-height: 1.2;--re-data-grid-header-cell-max-lines: 2;--re-data-grid-footer-separator-color: #ccc;--re-data-grid-footer-separator: 1px solid var(--re-data-grid-footer-separator-color);--re-data-grid-footer-surface: #fff;--re-data-grid-row-separator-color: #bbb;--re-data-grid-row-separator: 1px solid var(--re-data-grid-row-separator-color);--re-data-grid-row-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-color: var(--re-data-grid-cell-color);--re-data-grid-row-hover-rounded: 0px;--re-data-grid-column-separator-color: transparent;--re-data-grid-column-separator: 1px solid var(--re-data-grid-column-separator-color);--re-data-grid-column-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-cell-paddings: .4rem .625rem;--re-data-grid-cell-font-weight: 400;--re-data-grid-cell-font-size: .75rem;--re-data-grid-cell-color: #000;--re-data-grid-cell-surface: #fff;--re-data-grid-cell-line-height: 1.2;--re-data-grid-cell-max-lines: 2;--re-data-grid-sticky-header-cell-surface: #fff;--re-data-grid-sticky-cell-surface: #fdfdfd;--re-data-grid-sticky-cell-row-odd-surface: #fdfdfd;--re-data-grid-sticky-cell-left-shadow: 2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-sticky-cell-right-shadow: -2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-pinned-surface: #fcfcfc;--re-data-grid-pinned-separator-color: #eee;--re-data-grid-pinned-separator: 1px solid var(--re-data-grid-pinned-separator-color);--re-data-grid-expander-color: var(--primary-color, currentColor);--re-data-grid-expanded-color: var(--re-data-grid-cell-color, #000);--re-data-grid-expanded-surface: var(--re-data-grid-cell-surface, #fff);--re-data-grid-focus-ring-color: color-mix(in srgb, var(--primary-color, #2a90f4) 55%, transparent);--re-data-grid-focus-ring-width: 2px;--re-data-grid-focus-ring-offset: -2px;display:block;min-height:0;min-width:0}:host,:host *,:host *:before,:host *:after{box-sizing:border-box;outline:none}:host button{outline:none}.re-dg-root{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;min-height:var(--re-data-grid-min-height);border-radius:var(--re-data-grid-rounded);border:var(--re-data-grid-separator)}.re-dg-root.fill{display:block}.re-dg-root.re-dg-loading{pointer-events:none;-webkit-user-select:none;user-select:none;cursor:wait}.re-dg-root.re-dg-loading .re-dg-body{overflow:hidden}.re-dg-root.re-dg-loading .re-dg-scrollbar{display:none!important}.re-dg-root.re-dg-loading .re-dg-loader{pointer-events:all}.re-dg-root.lock-vertical-scroll .re-dg-body{overflow-x:auto;overflow-y:hidden}.re-dg-root.lock-vertical-scroll .re-dg-scrollbar{display:none!important}.re-dg-root.resizing-columns{-webkit-user-select:none;user-select:none;cursor:col-resize}.re-dg-body{position:relative;flex:1 1 auto;min-height:0;min-width:0;height:inherit;border:var(--re-data-grid-separator);border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-surface);overflow:auto;scrollbar-width:auto;-ms-overflow-style:auto}.re-dg-body::-webkit-scrollbar{width:var(--re-data-grid-scrollbar-size);height:var(--re-data-grid-scrollbar-size)}.re-dg-body::-webkit-scrollbar:vertical{width:0}.re-dg-body::-webkit-scrollbar-track{border-radius:var(--re-data-grid-scrollbar-track-rounded);background:var(--re-data-grid-scrollbar-track-surface)}.re-dg-body::-webkit-scrollbar-thumb{border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);transition:opacity .3s ease}.re-dg-body::-webkit-scrollbar-thumb:hover{background:var(--re-data-grid-scrollbar-thumb-active-color)}.re-dg-header,.re-dg-footer{position:sticky;z-index:3}.re-dg-header{top:0;background-color:var(--re-data-grid-header-surface)}.re-dg-header-row{min-height:var(--re-data-grid-header-row-height)}.re-dg-header-group-row{min-height:var(--re-data-grid-header-group-row-height)}.re-dg-header-rows{display:flex;flex-direction:column;padding-bottom:var(--re-data-grid-header-body-gap)}.re-dg-footer{bottom:0;border-radius:0 0 var(--re-data-grid-rounded) var(--re-data-grid-rounded);background-color:var(--re-data-grid-footer-surface)}.re-dg-row{position:relative;display:flex}.re-dg-data-row{position:absolute;left:0;top:0;min-width:100%;cursor:default;will-change:transform}.re-dg-sticky-row{z-index:2;top:0}.re-dg-cell,.re-dg-header-cell{display:flex;flex:0 0 auto;align-items:center;padding:var(--re-data-grid-cell-paddings);border-right:var(--re-data-grid-column-separator);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.re-dg-cell:focus-visible,.re-dg-header-cell:focus-visible,.re-dg-header-cell button:focus-visible,.re-dg-row[tabindex=\"0\"]:focus-visible{outline:var(--re-data-grid-focus-ring-width) solid var(--re-data-grid-focus-ring-color);outline-offset:var(--re-data-grid-focus-ring-offset);z-index:4}.re-dg-cell{width:100%;border-bottom:var(--re-data-grid-row-separator);font-weight:var(--re-data-grid-cell-font-weight);font-size:var(--re-data-grid-cell-font-size);color:var(--re-data-grid-cell-color);background-color:var(--re-data-grid-cell-surface)}.re-dg-row:nth-child(odd) .re-dg-cell{background-color:var(--re-data-grid-row-odd-surface)}.re-dg-row.re-dg-row-disabled .re-dg-cell{opacity:.6;cursor:not-allowed}.re-dg-row:nth-child(odd) .re-dg-cell.sticky-left,.re-dg-row:nth-child(odd) .re-dg-cell.sticky-right{background-color:var(--re-data-grid-sticky-cell-row-odd-surface)}.re-dg-cell:nth-child(odd){background-color:var(--re-data-grid-column-odd-surface)}.re-dg-bottom>.re-dg-cell{border-top:var(--re-data-grid-footer-separator)}.re-dg-header-cell{position:relative;align-items:center;gap:.75rem;border-bottom:var(--re-data-grid-header-row-separator);font-weight:var(--re-data-grid-header-cell-font-weight);font-size:var(--re-data-grid-header-cell-font-size);color:var(--re-data-grid-header-cell-color);background:var(--re-data-grid-header-cell-surface);-webkit-user-select:none;user-select:none;transition:color .3s ease-in-out}.re-dg-column-resize-handle{position:absolute;top:0;right:-4px;width:8px;height:100%;cursor:col-resize;z-index:5}.re-dg-header-cell.re-dg-header-group-cell{border-bottom:var(--re-data-grid-header-group-row-separator);font-weight:var(--re-data-grid-header-group-cell-font-weight);font-size:var(--re-data-grid-header-group-cell-font-size);color:var(--re-data-grid-header-group-cell-color);background:var(--re-data-grid-header-group-cell-surface)}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:first-child{border-radius:var(--re-data-grid-header-rounded) 0 0 0}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:last-child{border-radius:0 var(--re-data-grid-header-rounded) 0 0}.re-dg-data-row:last-child .re-dg-cell:first-child{border-radius:0 0 0 var(--re-data-grid-rounded)}.re-dg-data-row:last-child .re-dg-cell:last-child{border-radius:0 0 var(--re-data-grid-rounded) 0}.re-dg-header-cell .re-dg-header-text{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:var(--re-data-grid-header-cell-line-height);-webkit-box-orient:vertical;-webkit-line-clamp:var(--re-data-grid-header-cell-max-lines)}.re-dg-row.re-dg-pinned>.re-dg-cell{border-bottom:var(--re-data-grid-pinned-separator);background-color:var(--re-data-grid-pinned-surface)}.re-dg-row .re-dg-header-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row .re-dg-header-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-left,.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-pinned-surface)}.re-dg-row:hover>.re-dg-cell,.re-dg-row:hover>.re-dg-cell.sticky-left,.re-dg-row:hover>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-row-hover-surface)!important;color:var(--re-data-grid-row-hover-color)!important}.re-dg-row:hover>.re-dg-cell:first-child{border-radius:var(--re-data-grid-row-hover-rounded) 0 0 var(--re-data-grid-row-hover-rounded)}.re-dg-row:hover>.re-dg-cell:last-child{border-radius:0 var(--re-data-grid-row-hover-rounded) var(--re-data-grid-row-hover-rounded) 0}.sticky-left,.sticky-right{position:sticky;z-index:2}.sortable{cursor:pointer}.active-sort{color:var(--re-data-grid-active)}.re-dg-sort-ind{margin-left:6px}.re-dg-icon-placeholder{display:inline-block;width:1rem;height:1rem}.re-dg-cell-deferred{display:block;width:100%;height:100%}.re-dg-deferred-placeholder{background:transparent}.re-dg-data-row .re-dg-cell.expanded{color:var(--re-data-grid-expanded-color);background:var(--re-data-grid-expanded-surface)}.re-dg-empty{position:absolute;inset:0;display:grid;place-items:center;height:inherit;width:100%;border-radius:var(--re-data-grid-rounded);color:var(--re-data-grid-empty-color);background:var(--re-data-grid-empty-surface)}.re-dg-empty-text{width:100%;text-align:center}.re-dg-loader{position:absolute;inset:0;display:grid;place-items:center;height:inherit;border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-loading-surface);color:var(--re-data-grid-loading-color);z-index:5}.re-dg-tooltip{position:fixed;left:0;top:0;max-width:min(28rem,70vw);padding:var(--re-data-grid-tooltip-padding);border-radius:var(--re-data-grid-tooltip-radius);background:var(--re-data-grid-tooltip-surface);color:var(--re-data-grid-tooltip-color);box-shadow:var(--re-data-grid-tooltip-shadow);font-size:.75rem;line-height:1.2;z-index:var(--re-data-grid-tooltip-z);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease}.re-dg-tooltip.visible{opacity:1;transform:translateY(0)}.re-dg-loader-spinner{width:var(--re-data-grid-spinner-size);height:var(--re-data-grid-spinner-size);border-radius:50%;border:var(--re-data-grid-spinner-width) solid var(--re-data-grid-spinner-track-color);border-top-color:var(--re-data-grid-loading-color);animation:re-dg-spinner .8s linear infinite}.re-dg-skeleton-row{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:var(--re-data-grid-cell-surface);pointer-events:none}.re-dg-gap-loader{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:color-mix(in srgb,var(--re-data-grid-cell-surface) 88%,var(--re-data-grid-skeleton-line));pointer-events:none;opacity:.9}.re-dg-skeleton-row-line{display:block;width:var(--re-data-grid-skeleton-width);height:var(--re-data-grid-skeleton-height);border-radius:var(--re-data-grid-skeleton-rounded);background:linear-gradient(90deg,var(--re-data-grid-skeleton-line) 0%,var(--re-data-grid-skeleton-shine) 50%,var(--re-data-grid-skeleton-line) 100%);background-size:200% 100%;animation:re-dg-skeleton 1.2s ease-in-out infinite}@keyframes re-dg-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes re-dg-spinner{to{transform:rotate(360deg)}}.re-dg-scrollbar{position:absolute;right:0;top:0;bottom:0;opacity:0;transition:opacity .15s ease-in-out;pointer-events:none;z-index:4}.re-dg-scrollbar.visible{opacity:1}.re-dg-scrollbar-thumb{position:absolute;right:var(--re-data-grid-scrollbar-offset);width:var(--re-data-grid-scrollbar-thumb-size);border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);pointer-events:auto;-webkit-user-select:none;user-select:none}.re-dg-spacer{width:1px}.re-dg-top{top:0}.re-dg-bottom{bottom:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DataGridCellComponent, selector: "re-data-grid-cell", inputs: ["index", "item", "isPinned", "column"] }, { kind: "component", type: SortIcon, selector: "re-sort-ic", inputs: ["direction"] }, { kind: "component", type: ExpandIcon, selector: "re-expand-ic", inputs: ["expanded"] }, { kind: "component", type: CheckboxIcon, selector: "re-checkbox-ic", inputs: ["state", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [CheckboxIcon], () => [SortIcon], () => [ExpandIcon], () => [NgTemplateOutlet], () => [NgTemplateOutlet], () => [DataGridCellComponent], () => [NgTemplateOutlet], () => [NgTemplateOutlet], () => [NgTemplateOutlet]] });
4642
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: DataGrid, isStandalone: true, selector: "re-data-grid", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, pinnedRows: { classPropertyName: "pinnedRows", publicName: "pinnedRows", isSignal: true, isRequired: false, transformFunction: null }, isRowSticky: { classPropertyName: "isRowSticky", publicName: "isRowSticky", isSignal: true, isRequired: false, transformFunction: null }, isRowDisabled: { classPropertyName: "isRowDisabled", publicName: "isRowDisabled", isSignal: true, isRequired: false, transformFunction: null }, getRowClass: { classPropertyName: "getRowClass", publicName: "getRowClass", isSignal: true, isRequired: false, transformFunction: null }, getRowTemplate: { classPropertyName: "getRowTemplate", publicName: "getRowTemplate", isSignal: true, isRequired: false, transformFunction: null }, hasIndexColumn: { classPropertyName: "hasIndexColumn", publicName: "hasIndexColumn", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, selectedKeys: { classPropertyName: "selectedKeys", publicName: "selectedKeys", isSignal: true, isRequired: false, transformFunction: null }, selectionPolicy: { classPropertyName: "selectionPolicy", publicName: "selectionPolicy", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, virtualBuffer: { classPropertyName: "virtualBuffer", publicName: "virtualBuffer", isSignal: true, isRequired: false, transformFunction: null }, lockVerticalScroll: { classPropertyName: "lockVerticalScroll", publicName: "lockVerticalScroll", isSignal: true, isRequired: false, transformFunction: null }, headerGroups: { classPropertyName: "headerGroups", publicName: "headerGroups", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMode: { classPropertyName: "loadingMode", publicName: "loadingMode", isSignal: true, isRequired: false, transformFunction: null }, deferContent: { classPropertyName: "deferContent", publicName: "deferContent", isSignal: true, isRequired: false, transformFunction: null }, deferHeader: { classPropertyName: "deferHeader", publicName: "deferHeader", isSignal: true, isRequired: false, transformFunction: null }, deferPinned: { classPropertyName: "deferPinned", publicName: "deferPinned", isSignal: true, isRequired: false, transformFunction: null }, deferCells: { classPropertyName: "deferCells", publicName: "deferCells", isSignal: true, isRequired: false, transformFunction: null }, deferIcons: { classPropertyName: "deferIcons", publicName: "deferIcons", isSignal: true, isRequired: false, transformFunction: null }, deferTooltip: { classPropertyName: "deferTooltip", publicName: "deferTooltip", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, pageStartFromZero: { classPropertyName: "pageStartFromZero", publicName: "pageStartFromZero", isSignal: true, isRequired: false, transformFunction: null }, sortMode: { classPropertyName: "sortMode", publicName: "sortMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", sourceError: "sourceError", sortChange: "sortChange", multiSortChange: "multiSortChange", selectChange: "selectChange", selectedKeysChange: "selectedKeysChange", rowClick: "rowClick", rowContext: "rowContext", rowDoubleClick: "rowDoubleClick", cellClick: "cellClick", cellContext: "cellContext", cellDoubleClick: "cellDoubleClick", columnResizeEnd: "columnResizeEnd" }, providers: [DataGridVm], queries: [{ propertyName: "cellTypedSlotRefs", predicate: DataGridTypeCellTemplateDirective, isSignal: true }, { propertyName: "cellDataSlotRefs", predicate: DataGridCellTemplateDirective, isSignal: true }, { propertyName: "declarativeColumnRefs", predicate: DataGridDeclarativeColumn, isSignal: true }, { propertyName: "headerSlotRefs", predicate: DataGridHeaderTemplateDirective, isSignal: true }, { propertyName: "emptySlotRefs", predicate: DataGridCellEmptyDirective, isSignal: true }, { propertyName: "loadingSlotRefs", predicate: DataGridCellLoadingDirective, isSignal: true }, { propertyName: "sortIcSlotRefs", predicate: DataGridSortIconDirective, isSignal: true }, { propertyName: "expanderIcSlotRefs", predicate: DataGridExpanderIconDirective, isSignal: true }, { propertyName: "stickyRowSlotRefs", predicate: DataGridStickyRowDirective, isSignal: true }, { propertyName: "rowSlotRefs", predicate: DataGridRowDirective, isSignal: true }], viewQueries: [{ propertyName: "rootEl", first: true, predicate: ["root"], descendants: true, isSignal: true }, { propertyName: "scrollEl", first: true, predicate: ["scroll"], descendants: true, isSignal: true }, { propertyName: "headerEl", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "tooltipEl", first: true, predicate: ["tooltip"], descendants: true, isSignal: true }], ngImport: i0, template: "@let items = selectionRows();\r\n@let totalRows = totalRowCount();\r\n@let renderRows = renderRowCount();\r\n@let empty = !resolvedLoading() && !renderRows;\r\n@let notEmpty = !!renderRows;\r\n@let skeletonRowsCount = 4;\r\n@let skeletonMode = loadingMode() === 'skeleton';\r\n@let spinnerMode = loadingMode() === 'spinner';\r\n@let showInfinitySkeleton = resolvedBlockingLoading() && skeletonMode && mode() === 'infinity';\r\n@let showPaginationSkeleton = resolvedBlockingLoading() && skeletonMode && mode() === 'pagination';\r\n@let showSpinnerLoading = resolvedBlockingLoading() && spinnerMode;\r\n@let extraInfinitySkeletonRows = showInfinitySkeleton ? skeletonRowsCount : 0;\r\n\r\n@let pinnedTopH = vm.pinnedTop().length * rowHeight();\r\n@let pinnedBottomH = vm.pinnedBottom().length * rowHeight();\r\n@let rowH = rowHeight();\r\n@let contentW = vm.contentWidth();\r\n@let cols = vm.columnsToShow();\r\n@let stickyTop = pinnedTopH + headerHeight();\r\n@let normalizedHeaderGroups = vm.normalizedHeaderGroups();\r\n@let stickyRow = stickyRowData();\r\n@let stickyIndex = stickyRowIndex();\r\n\r\n<div\r\n #root\r\n class=\"re-dg-root\"\r\n [attr.id]=\"expanderRegionId\"\r\n [class.re-dg-loading]=\"showSpinnerLoading\"\r\n [class.lock-vertical-scroll]=\"lockVerticalScroll()\"\r\n [class.resizing-columns]=\"isColumnResizing()\"\r\n [style.height]=\"styleHeight()\"\r\n [attr.aria-multiselectable]=\"selection().mode === 'multi' ? true : null\"\r\n [attr.aria-rowcount]=\"ariaRowCount()\"\r\n [attr.aria-colcount]=\"ariaColCount()\"\r\n role=\"grid\"\r\n>\r\n @if (showSpinnerLoading) {\r\n <div class=\"re-dg-loader\" aria-live=\"polite\" role=\"status\">\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n <span class=\"re-dg-loader-spinner\" aria-label=\"Loading\"></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div #scroll class=\"re-dg-body\" role=\"rowgroup\" (mouseenter)=\"showScrollbar()\" (mouseleave)=\"hideScrollbarSoon()\">\r\n <ng-template #headerContent>\r\n <div class=\"re-dg-header\" role=\"rowgroup\" [style.width.px]=\"vm.contentWidth()\" [style.min-width.%]=\"100\">\r\n <div #header class=\"re-dg-header-rows\">\r\n @if (normalizedHeaderGroups.length) {\r\n <div\r\n class=\"re-dg-row re-dg-header-group-row\"\r\n role=\"row\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n >\r\n @for (group of normalizedHeaderGroups; track group.key; let groupIndex = $index) {\r\n @let groupStickyLeft =\r\n !!group.startKey &&\r\n !!group.endKey &&\r\n vm.isStickyLeft(group.startKey) &&\r\n vm.isStickyLeft(group.endKey);\r\n @let groupStickyRight =\r\n !!group.startKey &&\r\n !!group.endKey &&\r\n vm.isStickyRight(group.startKey) &&\r\n vm.isStickyRight(group.endKey);\r\n\r\n @let resolvedGroupTitle = resolveHeaderGroupTitle(group);\r\n\r\n <div\r\n class=\"re-dg-header-cell re-dg-header-group-cell\"\r\n role=\"columnheader\"\r\n [class.sticky-left]=\"groupStickyLeft\"\r\n [class.sticky-right]=\"groupStickyRight\"\r\n [style.left.px]=\"groupStickyLeft && group.startKey ? vm.stickyOffset(group.startKey, 'left') : null\"\r\n [style.right.px]=\"groupStickyRight && group.endKey ? vm.stickyOffset(group.endKey, 'right') : null\"\r\n [style.width.px]=\"group.widthPx\"\r\n [style.justify-content]=\"group.align || 'left'\"\r\n [title]=\"resolvedGroupTitle\"\r\n [attr.aria-colindex]=\"ariaHeaderGroupColIndex(group)\"\r\n [attr.aria-rowindex]=\"groupIndex + 1\"\r\n >\r\n @if (group.titleTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"group.titleTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedGroupTitle }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedGroupTitle }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"re-dg-row re-dg-header-row\"\r\n role=\"row\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n >\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-header-cell\"\r\n role=\"columnheader\"\r\n [class.sortable]=\"!!col.sortKey\"\r\n [class.active-sort]=\"isActiveSort(col)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [style.min-width.px]=\"col.minWidth || null\"\r\n [style.max-width.px]=\"col.maxWidth || null\"\r\n [style.justify-content]=\"col.align || 'left'\"\r\n [attr.aria-sort]=\"ariaSort(col)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-rowindex]=\"normalizedHeaderGroups.length ? 2 : 1\"\r\n [attr.aria-label]=\"col.sortKey ? ariaSortLabel(col) : null\"\r\n [attr.tabindex]=\"col.sortKey ? 0 : -1\"\r\n (click)=\"col.sortKey && onSort(col)\"\r\n (keydown.enter)=\"col.sortKey && onSort(col)\"\r\n >\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isMultiSelect = selection().mode === 'multi';\r\n\r\n @if (isCheckbox && isMultiSelect) {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\"\r\n />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\"\r\n />\r\n }\r\n } @else {\r\n @let resolvedHeader = resolveHeaderText(col);\r\n\r\n @if (col.headerTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"col.headerTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedHeader }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedHeader }}</span>\r\n }\r\n }\r\n\r\n @if (col.sortKey) {\r\n <span class=\"re-dg-sort-ind\">\r\n @let direction = sortOrderFor(col);\r\n\r\n @if (sortTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"sortTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: direction }\"\r\n />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-sort-ic [direction]=\"direction\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-sort-ic [direction]=\"direction\" />\r\n }\r\n }\r\n </span>\r\n }\r\n\r\n @if (isExpandable(col)) {\r\n <button\r\n [attr.aria-controls]=\"expanderRegionId\"\r\n [attr.aria-expanded]=\"expanderMap().get(col.key) ? 'true' : 'false'\"\r\n [attr.aria-label]=\"ariaExpandLabel(col)\"\r\n (click)=\"$event.stopPropagation(); onExpand(col)\"\r\n >\r\n @let expanded = expanderMap().get(col.key);\r\n\r\n @if (expanderTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"expanderTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: expanded }\"\r\n />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n }\r\n }\r\n </button>\r\n }\r\n\r\n @if (canResizeColumn(col)) {\r\n <div\n class=\"re-dg-column-resize-handle\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"ariaResizeLabel(col)\"\n [attr.aria-valuemin]=\"ariaResizeMin(col)\"\n [attr.aria-valuemax]=\"ariaResizeMax(col)\"\n [attr.aria-valuenow]=\"ariaResizeValue(col)\"\n tabindex=\"0\"\n (mousedown)=\"onColumnResizeStart($event, col)\"\n (keydown)=\"onColumnResizeKeydown($event, col)\"\n (click)=\"$event.stopPropagation()\"\n ></div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- PINNED TOP ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedTopContent>\r\n @for (pr of vm.pinnedTop(); track trackPinnedRow(pr, 'top', pinnedTopIndex); let pinnedTopIndex = $index) {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-top\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [attr.aria-rowindex]=\"ariaPinnedTopRowIndex(pinnedTopIndex)\"\r\n >\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: resolvePinnedData(pr),\r\n row: pr,\r\n index: pinnedTopIndex,\r\n region: 'top',\r\n }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n } @placeholder {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\"\r\n [style.min-height.px]=\"rowH\"\r\n ></div>\r\n } @loading {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\"\r\n [style.min-height.px]=\"rowH\"\r\n ></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferHeader()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n } @loading {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n }\r\n\r\n <ng-template #dataCellContent let-row let-col=\"col\" let-index=\"index\" let-isPinned=\"isPinned\">\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n\r\n @if (isCheckbox) {\r\n <re-checkbox-ic\r\n aria-label=\"Toggle row selection\"\r\n [state]=\"selector.isSelected(row)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, index)\"\r\n [attr.tabindex]=\"isDisabledRow(row, index) ? -1 : 0\"\r\n (click)=\"onCheckboxToggle(row, index, $event)\"\r\n (keydown.enter)=\"onCheckboxKeydown(row, index, $event)\"\r\n (keydown.space)=\"onCheckboxKeydown(row, index, $event)\"\r\n />\r\n } @else {\r\n @if (deferCells()) {\r\n @defer (when true) {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n } @placeholder {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n } @loading {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n }\r\n } @else {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n <ng-template #gridContent>\r\n <!-- STICKY ROW -->\r\n @if (stickyRow && stickyIndex !== null) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-sticky-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(stickyRow, stickyIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.top.px]=\"stickyRowTopPx()\"\r\n [attr.data-re-dg-row-index]=\"stickyIndex\"\n [attr.aria-rowindex]=\"ariaDataRowIndex(stickyIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(stickyRow) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(stickyRow, stickyIndex, $event)\"\r\n (contextmenu)=\"onRowContext(stickyRow, stickyIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(stickyRow, stickyIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(stickyRow, stickyIndex, $event)\"\n (keydown.arrowdown)=\"onRowKeydown(stickyIndex, $event)\"\n (keydown.arrowup)=\"onRowKeydown(stickyIndex, $event)\"\r\n >\r\n @let stickyTemplate = stickyRowTpl();\r\n @let rowTemplate = resolveRowTemplate(stickyRow, stickyIndex);\r\n\r\n @if (stickyTemplate?.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"stickyTemplate!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, index: stickyIndex }\"\r\n />\r\n } @else if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: stickyRow,\r\n index: stickyIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: true,\r\n }\"\r\n />\r\n } @else {\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, stickyRow)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, stickyIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, stickyIndex, false)) ? tooltipId : null\"\r\n (mouseenter)=\"\r\n onTooltipEnter($event, stickyRow, col, stickyIndex, cellAriaId(col.key, stickyIndex, false))\r\n \"\r\n (mouseleave)=\"hideTooltip()\"\r\n (focusin)=\"onTooltipFocus($event, stickyRow, col, stickyIndex, cellAriaId(col.key, stickyIndex, false))\"\r\n (focusout)=\"hideTooltip()\"\r\n (keydown.escape)=\"hideTooltip()\"\r\n (click)=\"onCellClick(stickyRow, col, stickyIndex, $event)\"\r\n (contextmenu)=\"onCellContext(stickyRow, col, stickyIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(stickyRow, col, stickyIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(stickyRow, col, stickyIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, col: col, index: stickyIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n @if (empty) {\r\n @let emptyTemplate = emptyTpl()?.tpl;\r\n\r\n <div class=\"re-dg-empty\" aria-live=\"polite\" role=\"status\">\r\n @if (emptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\" />\r\n } @else {\r\n <span class=\"re-dg-empty-text\">{{ defaults.translations.emptyState }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Content -->\r\n @if (notEmpty) {\r\n @let topGap = topGapLoader();\r\n @let bottomGap = bottomGapLoader();\r\n <div\r\n class=\"re-dg-spacer\"\r\n [style.width.px]=\"contentW\"\r\n [style.height.px]=\"(renderRows + extraInfinitySkeletonRows) * rowH - pinnedBottomH\"\r\n ></div>\r\n\r\n @if (topGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"topGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (topGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n\r\n @for (entry of renderSlotEntries(); track entry.key) {\n @let slot = entry.slot;\r\n @let rowIndex = startIndex + slot;\r\n @let row = rowAt(rowIndex);\r\n @let rowTemplate = row ? resolveRowTemplate(row, rowIndex) : null;\r\n\r\n @if (row && !isStickyRowIndex(rowIndex)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(row, rowIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n [attr.data-re-dg-row-index]=\"rowIndex\"\n [attr.aria-rowindex]=\"ariaDataRowIndex(rowIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(row) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(row, rowIndex, $event)\"\r\n (contextmenu)=\"onRowContext(row, rowIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(row, rowIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(row, rowIndex, $event)\"\n (keydown.arrowdown)=\"onRowKeydown(rowIndex, $event)\"\n (keydown.arrowup)=\"onRowKeydown(rowIndex, $event)\"\r\n >\r\n @if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: row,\r\n index: rowIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: false,\r\n }\"\r\n />\r\n } @else {\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, row)\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, rowIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, rowIndex, false)) ? tooltipId : null\"\r\n (mouseenter)=\"onTooltipEnter($event, row, col, rowIndex, cellAriaId(col.key, rowIndex, false))\"\r\n (mouseleave)=\"hideTooltip()\"\r\n (focusin)=\"onTooltipFocus($event, row, col, rowIndex, cellAriaId(col.key, rowIndex, false))\"\r\n (focusout)=\"hideTooltip()\"\r\n (keydown.escape)=\"hideTooltip()\"\r\n (click)=\"onCellClick(row, col, rowIndex, $event)\"\r\n (contextmenu)=\"onCellContext(row, col, rowIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(row, col, rowIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(row, col, rowIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: row, col: col, index: rowIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n } @else if (shouldRenderLoadingRow(rowIndex, topGap, bottomGap)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (bottomGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"bottomGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (bottomGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (showInfinitySkeleton || showPaginationSkeleton) {\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n @for (si of [0, 1, 2, 3]; track si) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"\r\n 'translateY(' + (((showInfinitySkeleton ? items.length : 0) + si) * rowH + stickyTop) + 'px)'\r\n \"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n <!-- PINNED BOTTOM ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedBottomContent>\r\n <div class=\"re-dg-footer\" role=\"rowgroup\">\r\n @for (\r\n pr of vm.pinnedBottom();\r\n track trackPinnedRow(pr, 'bottom', pinnedBottomIndex);\r\n let pinnedBottomIndex = $index\r\n ) {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-bottom\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [attr.aria-rowindex]=\"ariaPinnedBottomRowIndex(pinnedBottomIndex)\"\r\n >\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: resolvePinnedData(pr),\r\n row: pr,\r\n index: pinnedBottomIndex,\r\n region: 'bottom',\r\n }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n } @loading {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n @if (deferContent()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n } @loading {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n }\r\n </div>\r\n\r\n <ng-template #pinnedRowCells let-row let-pinnedRow=\"row\" let-pinnedIndex=\"index\" let-pinnedRegion=\"region\">\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isIndex = 'type' in col && col.type === 'index';\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, $any(row))\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.height.px]=\"rowH\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"\r\n isTooltipTarget(pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex)) ? tooltipId : null\r\n \"\r\n (mouseenter)=\"\r\n !isCheckbox &&\r\n !isIndex &&\r\n onTooltipEnter($event, $any(row), col, -1, pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex))\r\n \"\r\n (mouseleave)=\"!isCheckbox && !isIndex && hideTooltip()\"\r\n (focusin)=\"\r\n !isCheckbox &&\r\n !isIndex &&\r\n onTooltipFocus($event, $any(row), col, -1, pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex))\r\n \"\r\n (focusout)=\"!isCheckbox && !isIndex && hideTooltip()\"\r\n (keydown.escape)=\"hideTooltip()\"\r\n (click)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event)\"\r\n (contextmenu)=\"!isCheckbox && !isIndex && onCellContext($any(row), col, -1, $event)\"\r\n (dblclick)=\"!isCheckbox && !isIndex && onCellDoubleClick($any(row), col, -1, $event)\"\r\n (keydown.enter)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event)\"\r\n >\r\n @if (!isCheckbox && !isIndex) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: $any(row), col: col, index: -1, isPinned: true }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferTooltip()) {\r\n @defer (when true) {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"tooltipStateValue.tpl\" [ngTemplateOutletContext]=\"tooltipStateValue.ctx\" />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"tooltipStateValue.tpl\" [ngTemplateOutletContext]=\"tooltipStateValue.ctx\" />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Overlay scrollbar -->\r\n <div class=\"re-dg-scrollbar\" [class.visible]=\"vm.scrollbarVisible()\">\r\n <div\r\n class=\"re-dg-scrollbar-thumb\"\r\n [style.height.px]=\"vm.thumbHeightPx()\"\r\n [style.transform]=\"'translateY(' + vm.thumbTopPx() + 'px)'\"\r\n (pointerdown)=\"onThumbDown($event)\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [":host{--re-data-grid-min-height: 200px;--re-data-grid-height: 400px;--re-data-grid-rounded: var(--radius-md, 6px);--re-data-grid-separator-color: var(--border-color);--re-data-grid-separator: 1px solid var(--re-data-grid-separator-color);--re-data-grid-surface: var(--surface-neutral, #fff);--re-data-grid-active: var(--primary-color, #2a90f4);--re-data-grid-empty-color: #777;--re-data-grid-empty-surface: transparent;--re-data-grid-loading-color: #444;--re-data-grid-loading-surface: rgba(255, 255, 255, .5);--re-data-grid-spinner-size: 2rem;--re-data-grid-spinner-width: .25rem;--re-data-grid-spinner-track-color: rgba(0, 0, 0, .12);--re-data-grid-skeleton-width: 100%;--re-data-grid-skeleton-height: 100%;--re-data-grid-skeleton-rounded: var(--re-data-grid-rounded, .75rem);--re-data-grid-skeleton-shine: rgba(255, 255, 255, .8);--re-data-grid-skeleton-line: #e7ebf0;--re-data-grid-scrollbar-size: 4px;--re-data-grid-scrollbar-offset: 2px;--re-data-grid-scrollbar-track-rounded: .25rem;--re-data-grid-scrollbar-track-surface: transparent;--re-data-grid-scrollbar-thumb-size: 8px;--re-data-grid-scrollbar-thumb-color: rgba(0, 0, 0, .25);--re-data-grid-scrollbar-thumb-active-color: rgba(0, 0, 0, .45);--re-data-grid-scrollbar-thumb-rounded: var(--re-data-grid-scrollbar-track-rounded);--re-data-grid-tooltip-surface: #0f172a;--re-data-grid-tooltip-color: #f8fafc;--re-data-grid-tooltip-radius: .5rem;--re-data-grid-tooltip-padding: .4rem .6rem;--re-data-grid-tooltip-shadow: 0 8px 24px rgba(15, 23, 42, .25);--re-data-grid-tooltip-z: 60;--re-data-grid-header-rounded: var(--re-data-grid-rounded);--re-data-grid-header-surface: #fff;--re-data-grid-header-body-gap: 0px;--re-data-grid-header-row-height: 40px;--re-data-grid-header-row-separator-color: #ccc;--re-data-grid-header-row-separator: 1px solid var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-height: var(--re-data-grid-header-row-height);--re-data-grid-header-group-row-separator-color: var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-separator: 1px solid var(--re-data-grid-header-group-row-separator-color);--re-data-grid-header-group-cell-font-weight: var(--re-data-grid-header-cell-font-weight);--re-data-grid-header-group-cell-font-size: var(--re-data-grid-header-cell-font-size);--re-data-grid-header-group-cell-color: var(--re-data-grid-header-cell-color);--re-data-grid-header-group-cell-surface: var(--re-data-grid-header-cell-surface);--re-data-grid-header-cell-font-weight: 600;--re-data-grid-header-cell-font-size: .8rem;--re-data-grid-header-cell-color: #000;--re-data-grid-header-cell-surface: #fafafa;--re-data-grid-header-cell-line-height: 1.2;--re-data-grid-header-cell-max-lines: 2;--re-data-grid-footer-separator-color: #ccc;--re-data-grid-footer-separator: 1px solid var(--re-data-grid-footer-separator-color);--re-data-grid-footer-surface: #fff;--re-data-grid-row-separator-color: #bbb;--re-data-grid-row-separator: 1px solid var(--re-data-grid-row-separator-color);--re-data-grid-row-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-color: var(--re-data-grid-cell-color);--re-data-grid-row-hover-rounded: 0px;--re-data-grid-column-separator-color: transparent;--re-data-grid-column-separator: 1px solid var(--re-data-grid-column-separator-color);--re-data-grid-column-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-cell-paddings: .4rem .625rem;--re-data-grid-cell-font-weight: 400;--re-data-grid-cell-font-size: .75rem;--re-data-grid-cell-color: #000;--re-data-grid-cell-surface: #fff;--re-data-grid-cell-line-height: 1.2;--re-data-grid-cell-max-lines: 2;--re-data-grid-sticky-header-cell-surface: #fff;--re-data-grid-sticky-cell-surface: #fdfdfd;--re-data-grid-sticky-cell-row-odd-surface: #fdfdfd;--re-data-grid-sticky-cell-left-shadow: 2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-sticky-cell-right-shadow: -2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-pinned-surface: #fcfcfc;--re-data-grid-pinned-separator-color: #eee;--re-data-grid-pinned-separator: 1px solid var(--re-data-grid-pinned-separator-color);--re-data-grid-expander-color: var(--primary-color, currentColor);--re-data-grid-expanded-color: var(--re-data-grid-cell-color, #000);--re-data-grid-expanded-surface: var(--re-data-grid-cell-surface, #fff);--re-data-grid-focus-ring-color: color-mix(in srgb, var(--primary-color, #2a90f4) 55%, transparent);--re-data-grid-focus-ring-width: 2px;--re-data-grid-focus-ring-offset: -2px;display:block;min-height:0;min-width:0}:host,:host *,:host *:before,:host *:after{box-sizing:border-box;outline:none}:host button{outline:none}.re-dg-root{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;min-height:var(--re-data-grid-min-height);border-radius:var(--re-data-grid-rounded);border:var(--re-data-grid-separator)}.re-dg-root.fill{display:block}.re-dg-root.re-dg-loading{pointer-events:none;-webkit-user-select:none;user-select:none;cursor:wait}.re-dg-root.re-dg-loading .re-dg-body{overflow:hidden}.re-dg-root.re-dg-loading .re-dg-scrollbar{display:none!important}.re-dg-root.re-dg-loading .re-dg-loader{pointer-events:all}.re-dg-root.lock-vertical-scroll .re-dg-body{overflow-x:auto;overflow-y:hidden}.re-dg-root.lock-vertical-scroll .re-dg-scrollbar{display:none!important}.re-dg-root.resizing-columns{-webkit-user-select:none;user-select:none;cursor:col-resize}.re-dg-body{position:relative;flex:1 1 auto;min-height:0;min-width:0;height:inherit;border:var(--re-data-grid-separator);border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-surface);overflow:auto;scrollbar-width:auto;-ms-overflow-style:auto}.re-dg-body::-webkit-scrollbar{width:var(--re-data-grid-scrollbar-size);height:var(--re-data-grid-scrollbar-size)}.re-dg-body::-webkit-scrollbar:vertical{width:0}.re-dg-body::-webkit-scrollbar-track{border-radius:var(--re-data-grid-scrollbar-track-rounded);background:var(--re-data-grid-scrollbar-track-surface)}.re-dg-body::-webkit-scrollbar-thumb{border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);transition:opacity .3s ease}.re-dg-body::-webkit-scrollbar-thumb:hover{background:var(--re-data-grid-scrollbar-thumb-active-color)}.re-dg-header,.re-dg-footer{position:sticky;z-index:3}.re-dg-header{top:0;background-color:var(--re-data-grid-header-surface)}.re-dg-header-row{min-height:var(--re-data-grid-header-row-height)}.re-dg-header-group-row{min-height:var(--re-data-grid-header-group-row-height)}.re-dg-header-rows{display:flex;flex-direction:column;padding-bottom:var(--re-data-grid-header-body-gap)}.re-dg-footer{bottom:0;border-radius:0 0 var(--re-data-grid-rounded) var(--re-data-grid-rounded);background-color:var(--re-data-grid-footer-surface)}.re-dg-row{position:relative;display:flex}.re-dg-data-row{position:absolute;left:0;top:0;min-width:100%;cursor:default;will-change:transform}.re-dg-sticky-row{z-index:2;top:0}.re-dg-cell,.re-dg-header-cell{display:flex;flex:0 0 auto;align-items:center;padding:var(--re-data-grid-cell-paddings);border-right:var(--re-data-grid-column-separator);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.re-dg-cell:focus-visible,.re-dg-header-cell:focus-visible,.re-dg-header-cell button:focus-visible,.re-dg-row[tabindex=\"0\"]:focus-visible{outline:var(--re-data-grid-focus-ring-width) solid var(--re-data-grid-focus-ring-color);outline-offset:var(--re-data-grid-focus-ring-offset);z-index:4}.re-dg-cell{width:100%;border-bottom:var(--re-data-grid-row-separator);font-weight:var(--re-data-grid-cell-font-weight);font-size:var(--re-data-grid-cell-font-size);color:var(--re-data-grid-cell-color);background-color:var(--re-data-grid-cell-surface)}.re-dg-row:nth-child(odd) .re-dg-cell{background-color:var(--re-data-grid-row-odd-surface)}.re-dg-row.re-dg-row-disabled .re-dg-cell{opacity:.6;cursor:not-allowed}.re-dg-row:nth-child(odd) .re-dg-cell.sticky-left,.re-dg-row:nth-child(odd) .re-dg-cell.sticky-right{background-color:var(--re-data-grid-sticky-cell-row-odd-surface)}.re-dg-cell:nth-child(odd){background-color:var(--re-data-grid-column-odd-surface)}.re-dg-bottom>.re-dg-cell{border-top:var(--re-data-grid-footer-separator)}.re-dg-header-cell{position:relative;align-items:center;gap:.75rem;border-bottom:var(--re-data-grid-header-row-separator);font-weight:var(--re-data-grid-header-cell-font-weight);font-size:var(--re-data-grid-header-cell-font-size);color:var(--re-data-grid-header-cell-color);background:var(--re-data-grid-header-cell-surface);-webkit-user-select:none;user-select:none;transition:color .3s ease-in-out}.re-dg-column-resize-handle{position:absolute;top:0;right:-4px;width:8px;height:100%;cursor:col-resize;z-index:5}.re-dg-header-cell.re-dg-header-group-cell{border-bottom:var(--re-data-grid-header-group-row-separator);font-weight:var(--re-data-grid-header-group-cell-font-weight);font-size:var(--re-data-grid-header-group-cell-font-size);color:var(--re-data-grid-header-group-cell-color);background:var(--re-data-grid-header-group-cell-surface)}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:first-child{border-radius:var(--re-data-grid-header-rounded) 0 0 0}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:last-child{border-radius:0 var(--re-data-grid-header-rounded) 0 0}.re-dg-data-row:last-child .re-dg-cell:first-child{border-radius:0 0 0 var(--re-data-grid-rounded)}.re-dg-data-row:last-child .re-dg-cell:last-child{border-radius:0 0 var(--re-data-grid-rounded) 0}.re-dg-header-cell .re-dg-header-text{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:var(--re-data-grid-header-cell-line-height);-webkit-box-orient:vertical;-webkit-line-clamp:var(--re-data-grid-header-cell-max-lines)}.re-dg-row.re-dg-pinned>.re-dg-cell{border-bottom:var(--re-data-grid-pinned-separator);background-color:var(--re-data-grid-pinned-surface)}.re-dg-row .re-dg-header-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row .re-dg-header-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-left,.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-pinned-surface)}.re-dg-row:hover>.re-dg-cell,.re-dg-row:hover>.re-dg-cell.sticky-left,.re-dg-row:hover>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-row-hover-surface)!important;color:var(--re-data-grid-row-hover-color)!important}.re-dg-row:hover>.re-dg-cell:first-child{border-radius:var(--re-data-grid-row-hover-rounded) 0 0 var(--re-data-grid-row-hover-rounded)}.re-dg-row:hover>.re-dg-cell:last-child{border-radius:0 var(--re-data-grid-row-hover-rounded) var(--re-data-grid-row-hover-rounded) 0}.sticky-left,.sticky-right{position:sticky;z-index:2}.sortable{cursor:pointer}.active-sort{color:var(--re-data-grid-active)}.re-dg-sort-ind{margin-left:6px}.re-dg-icon-placeholder{display:inline-block;width:1rem;height:1rem}.re-dg-cell-deferred{display:block;width:100%;height:100%}.re-dg-deferred-placeholder{background:transparent}.re-dg-data-row .re-dg-cell.expanded{color:var(--re-data-grid-expanded-color);background:var(--re-data-grid-expanded-surface)}.re-dg-empty{position:absolute;inset:0;display:grid;place-items:center;height:inherit;width:100%;border-radius:var(--re-data-grid-rounded);color:var(--re-data-grid-empty-color);background:var(--re-data-grid-empty-surface)}.re-dg-empty-text{width:100%;text-align:center}.re-dg-loader{position:absolute;inset:0;display:grid;place-items:center;height:inherit;border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-loading-surface);color:var(--re-data-grid-loading-color);z-index:5}.re-dg-tooltip{position:fixed;left:0;top:0;max-width:min(28rem,70vw);padding:var(--re-data-grid-tooltip-padding);border-radius:var(--re-data-grid-tooltip-radius);background:var(--re-data-grid-tooltip-surface);color:var(--re-data-grid-tooltip-color);box-shadow:var(--re-data-grid-tooltip-shadow);font-size:.75rem;line-height:1.2;z-index:var(--re-data-grid-tooltip-z);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease}.re-dg-tooltip.visible{opacity:1;transform:translateY(0)}.re-dg-loader-spinner{width:var(--re-data-grid-spinner-size);height:var(--re-data-grid-spinner-size);border-radius:50%;border:var(--re-data-grid-spinner-width) solid var(--re-data-grid-spinner-track-color);border-top-color:var(--re-data-grid-loading-color);animation:re-dg-spinner .8s linear infinite}.re-dg-skeleton-row{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:var(--re-data-grid-cell-surface);pointer-events:none}.re-dg-gap-loader{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:color-mix(in srgb,var(--re-data-grid-cell-surface) 88%,var(--re-data-grid-skeleton-line));pointer-events:none;opacity:.9}.re-dg-skeleton-row-line{display:block;width:var(--re-data-grid-skeleton-width);height:var(--re-data-grid-skeleton-height);border-radius:var(--re-data-grid-skeleton-rounded);background:linear-gradient(90deg,var(--re-data-grid-skeleton-line) 0%,var(--re-data-grid-skeleton-shine) 50%,var(--re-data-grid-skeleton-line) 100%);background-size:200% 100%;animation:re-dg-skeleton 1.2s ease-in-out infinite}@keyframes re-dg-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes re-dg-spinner{to{transform:rotate(360deg)}}.re-dg-scrollbar{position:absolute;right:0;top:0;bottom:0;opacity:0;transition:opacity .15s ease-in-out;pointer-events:none;z-index:4}.re-dg-scrollbar.visible{opacity:1}.re-dg-scrollbar-thumb{position:absolute;right:var(--re-data-grid-scrollbar-offset);width:var(--re-data-grid-scrollbar-thumb-size);border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);pointer-events:auto;-webkit-user-select:none;user-select:none;touch-action:none}.re-dg-spacer{width:1px}.re-dg-top{top:0}.re-dg-bottom{bottom:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DataGridCellComponent, selector: "re-data-grid-cell", inputs: ["index", "item", "isPinned", "column"] }, { kind: "component", type: SortIcon, selector: "re-sort-ic", inputs: ["direction"] }, { kind: "component", type: ExpandIcon, selector: "re-expand-ic", inputs: ["expanded"] }, { kind: "component", type: CheckboxIcon, selector: "re-checkbox-ic", inputs: ["state", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [CheckboxIcon], () => [SortIcon], () => [ExpandIcon], () => [NgTemplateOutlet], () => [NgTemplateOutlet], () => [DataGridCellComponent], () => [NgTemplateOutlet], () => [NgTemplateOutlet], () => [NgTemplateOutlet]] });
4238
4643
  }
4239
4644
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DataGrid, decorators: [{
4240
4645
  type: Component,
4241
- args: [{ selector: 're-data-grid', imports: [NgTemplateOutlet, DataGridCellComponent, SortIcon, ExpandIcon, CheckboxIcon], providers: [DataGridVm], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let items = selectionRows();\r\n@let totalRows = totalRowCount();\r\n@let empty = !resolvedLoading() && !totalRows;\r\n@let notEmpty = !!totalRows;\r\n@let skeletonRowsCount = 4;\r\n@let skeletonMode = loadingMode() === 'skeleton';\r\n@let spinnerMode = loadingMode() === 'spinner';\r\n@let showInfinitySkeleton = resolvedLoading() && skeletonMode && mode() === 'infinity';\r\n@let showPaginationSkeleton = resolvedLoading() && skeletonMode && mode() === 'pagination' && !notEmpty;\r\n@let showSpinnerLoading = resolvedLoading() && spinnerMode;\r\n@let extraInfinitySkeletonRows = showInfinitySkeleton ? skeletonRowsCount : 0;\r\n\r\n@let pinnedTopH = vm.pinnedTop().length * rowHeight();\r\n@let pinnedBottomH = vm.pinnedBottom().length * rowHeight();\r\n@let rowH = rowHeight();\r\n@let contentW = vm.contentWidth();\r\n@let cols = vm.columnsToShow();\r\n@let stickyTop = pinnedTopH + headerHeight();\r\n@let normalizedHeaderGroups = vm.normalizedHeaderGroups();\r\n@let stickyRow = stickyRowData();\r\n@let stickyIndex = stickyRowIndex();\r\n\r\n<div\r\n #root\r\n class=\"re-dg-root\"\r\n [attr.id]=\"expanderRegionId\"\r\n [class.re-dg-loading]=\"showSpinnerLoading\"\r\n [class.lock-vertical-scroll]=\"lockVerticalScroll()\"\r\n [class.resizing-columns]=\"isColumnResizing()\"\r\n [style.height]=\"styleHeight()\"\r\n [attr.aria-multiselectable]=\"selection().mode === 'multi' ? true : null\"\r\n [attr.aria-rowcount]=\"ariaRowCount()\"\r\n [attr.aria-colcount]=\"ariaColCount()\"\r\n role=\"grid\"\r\n>\r\n @if (showSpinnerLoading) {\r\n <div class=\"re-dg-loader\" aria-live=\"polite\" role=\"status\">\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n <span class=\"re-dg-loader-spinner\" aria-label=\"Loading\"></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n #scroll\r\n class=\"re-dg-body\"\r\n role=\"rowgroup\"\r\n (mouseenter)=\"showScrollbar()\"\r\n (mouseleave)=\"hideScrollbarSoon()\"\r\n >\r\n <ng-template #headerContent>\r\n <div\r\n class=\"re-dg-header\"\r\n role=\"rowgroup\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n >\r\n <div #header class=\"re-dg-header-rows\">\r\n @if (normalizedHeaderGroups.length) {\r\n <div class=\"re-dg-row re-dg-header-group-row\" role=\"row\" [style.width.px]=\"vm.contentWidth()\" [style.min-width.%]=\"100\">\r\n @for (group of normalizedHeaderGroups; track group.key; let groupIndex = $index) {\r\n @let groupStickyLeft = !!group.startKey && !!group.endKey && vm.isStickyLeft(group.startKey) && vm.isStickyLeft(group.endKey);\r\n @let groupStickyRight = !!group.startKey && !!group.endKey && vm.isStickyRight(group.startKey) && vm.isStickyRight(group.endKey);\r\n\r\n @let resolvedGroupTitle = resolveHeaderGroupTitle(group);\r\n\r\n <div\r\n class=\"re-dg-header-cell re-dg-header-group-cell\"\r\n role=\"columnheader\"\r\n [class.sticky-left]=\"groupStickyLeft\"\r\n [class.sticky-right]=\"groupStickyRight\"\r\n [style.left.px]=\"groupStickyLeft && group.startKey ? vm.stickyOffset(group.startKey, 'left') : null\"\r\n [style.right.px]=\"groupStickyRight && group.endKey ? vm.stickyOffset(group.endKey, 'right') : null\"\r\n [style.width.px]=\"group.widthPx\"\r\n [style.justify-content]=\"group.align || 'left'\"\r\n [title]=\"resolvedGroupTitle\"\r\n [attr.aria-colindex]=\"ariaHeaderGroupColIndex(group)\"\r\n [attr.aria-rowindex]=\"groupIndex + 1\"\r\n >\r\n @if (group.titleTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"group.titleTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedGroupTitle }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedGroupTitle }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"re-dg-row re-dg-header-row\" role=\"row\" [style.width.px]=\"vm.contentWidth()\" [style.min-width.%]=\"100\">\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-header-cell\"\r\n role=\"columnheader\"\r\n [class.sortable]=\"!!col.sortKey\"\r\n [class.active-sort]=\"isActiveSort(col)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [style.min-width.px]=\"col.minWidth || null\"\r\n [style.max-width.px]=\"col.maxWidth || null\"\r\n [style.justify-content]=\"col.align || 'left'\"\r\n [attr.aria-sort]=\"ariaSort(col)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-rowindex]=\"normalizedHeaderGroups.length ? 2 : 1\"\r\n [attr.aria-label]=\"col.sortKey ? ariaSortLabel(col) : null\"\r\n [attr.tabindex]=\"col.sortKey ? 0 : -1\"\r\n (click)=\"col.sortKey && onSort(col)\"\r\n (keydown.enter)=\"col.sortKey && onSort(col)\"\r\n >\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isMultiSelect = selection().mode === 'multi';\r\n\r\n @if (isCheckbox && isMultiSelect) {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\" />\r\n }\r\n } @else {\r\n @let resolvedHeader = resolveHeaderText(col);\r\n\r\n @if (col.headerTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"col.headerTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedHeader }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedHeader }}</span>\r\n }\r\n }\r\n\r\n @if (col.sortKey) {\r\n <span class=\"re-dg-sort-ind\">\r\n @let direction = sortOrderFor(col);\r\n\r\n @if (sortTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"sortTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: direction }\"\r\n />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-sort-ic [direction]=\"direction\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-sort-ic [direction]=\"direction\" />\r\n }\r\n }\r\n </span>\r\n }\r\n\r\n @if (isExpandable(col)) {\r\n <button\r\n [attr.aria-controls]=\"expanderRegionId\"\r\n [attr.aria-expanded]=\"expanderMap().get(col.key) ? 'true' : 'false'\"\r\n [attr.aria-label]=\"ariaExpandLabel(col)\"\r\n (click)=\"$event.stopPropagation(); onExpand(col)\"\r\n >\r\n @let expanded = expanderMap().get(col.key);\r\n\r\n @if (expanderTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"expanderTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: expanded }\" />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n }\r\n }\r\n </button>\r\n }\r\n\r\n @if (canResizeColumn(col)) {\r\n <button\r\n class=\"re-dg-column-resize-handle\"\r\n aria-orientation=\"vertical\"\r\n role=\"separator\"\r\n [attr.aria-label]=\"ariaResizeLabel(col)\"\r\n (mousedown)=\"onColumnResizeStart($event, col)\"\r\n (click)=\"$event.stopPropagation()\"\r\n ></button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- PINNED TOP ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedTopContent>\r\n @for (pr of vm.pinnedTop(); track trackPinnedRow(pr); let pinnedTopIndex = $index) {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-top\" role=\"row\" [style.width.px]=\"contentW\" [style.min-width.%]=\"100\" [attr.aria-rowindex]=\"ariaPinnedTopRowIndex(pinnedTopIndex)\">\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n } @loading {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferHeader()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n } @loading {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n }\r\n\r\n <ng-template #dataCellContent let-row let-col=\"col\" let-index=\"index\" let-isPinned=\"isPinned\">\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n\r\n @if (isCheckbox) {\r\n <re-checkbox-ic\r\n aria-label=\"Toggle row selection\"\r\n [state]=\"selector.isSelected(row)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, index)\"\r\n [attr.tabindex]=\"isDisabledRow(row, index) ? -1 : 0\"\r\n (click)=\"onCheckboxToggle(row, index, $event)\"\r\n (keydown.enter)=\"onCheckboxKeydown(row, index, $event)\"\r\n (keydown.space)=\"onCheckboxKeydown(row, index, $event)\" />\r\n } @else {\r\n @if (deferCells()) {\r\n @defer (when true) {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n } @placeholder {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n } @loading {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n }\r\n } @else {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n <ng-template #gridContent>\r\n\r\n <!-- STICKY ROW -->\r\n @if (stickyRow && stickyIndex !== null) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-sticky-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(stickyRow, stickyIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.top.px]=\"stickyRowTopPx()\"\r\n [attr.aria-rowindex]=\"ariaDataRowIndex(stickyIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(stickyRow) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(stickyRow, stickyIndex, $event)\"\r\n (contextmenu)=\"onRowContext(stickyRow, stickyIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(stickyRow, stickyIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(stickyRow, stickyIndex, $event)\"\r\n >\r\n @let stickyTemplate = stickyRowTpl();\r\n @let rowTemplate = resolveRowTemplate(stickyRow, stickyIndex);\r\n\r\n @if (stickyTemplate?.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"stickyTemplate!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, index: stickyIndex }\"\r\n />\r\n } @else if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: stickyRow,\r\n index: stickyIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: true\r\n }\"\r\n />\r\n } @else {\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, stickyRow)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, stickyIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, stickyIndex, false)) ? tooltipId : null\"\r\n [attr.tabindex]=\"0\"\r\n (mouseenter)=\"onTooltipEnter($event, stickyRow, col, stickyIndex, cellAriaId(col.key, stickyIndex, false))\"\r\n (mouseleave)=\"hideTooltip()\"\r\n (click)=\"onCellClick(stickyRow, col, stickyIndex, $event);\"\r\n (contextmenu)=\"onCellContext(stickyRow, col, stickyIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(stickyRow, col, stickyIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(stickyRow, col, stickyIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, col: col, index: stickyIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n @if (empty) {\r\n @let emptyTemplate = emptyTpl()?.tpl;\r\n\r\n <div class=\"re-dg-empty\" aria-live=\"polite\" role=\"status\">\r\n @if (emptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\" />\r\n } @else {\r\n <span class=\"re-dg-empty-text\">{{ defaults.translations.emptyState }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Content -->\r\n @if (notEmpty) {\r\n @let topGap = topGapLoader();\r\n @let bottomGap = bottomGapLoader();\r\n <div\r\n class=\"re-dg-spacer\"\r\n [style.width.px]=\"contentW\"\r\n [style.height.px]=\"(totalRows + extraInfinitySkeletonRows) * rowH - pinnedBottomH\"></div>\r\n\r\n @if (topGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"topGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (topGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n\r\n @for (slot of renderSlots(); track slot) {\r\n @let rowIndex = startIndex + slot;\r\n @let row = rowAt(rowIndex);\r\n @let rowTemplate = row ? resolveRowTemplate(row, rowIndex) : null;\r\n\r\n @if (row && !isStickyRowIndex(rowIndex)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(row, rowIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n [attr.aria-rowindex]=\"ariaDataRowIndex(rowIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(row) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(row, rowIndex, $event)\"\r\n (contextmenu)=\"onRowContext(row, rowIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(row, rowIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(row, rowIndex, $event)\"\r\n >\r\n @if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: row,\r\n index: rowIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: false\r\n }\"\r\n />\r\n } @else {\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, row)\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, rowIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, rowIndex, false)) ? tooltipId : null\"\r\n [attr.tabindex]=\"0\"\r\n (mouseenter)=\"onTooltipEnter($event, row, col, rowIndex, cellAriaId(col.key, rowIndex, false))\"\r\n (mouseleave)=\"hideTooltip()\"\r\n (click)=\"onCellClick(row, col, rowIndex, $event);\"\r\n (contextmenu)=\"onCellContext(row, col, rowIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(row, col, rowIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(row, col, rowIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: row, col: col, index: rowIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n } @else if (shouldRenderLoadingRow(rowIndex, topGap, bottomGap)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (bottomGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"bottomGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (bottomGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (showInfinitySkeleton || showPaginationSkeleton) {\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n @for (si of [0, 1, 2, 3]; track si) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (((showInfinitySkeleton ? items.length : 0) + si) * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n <!-- PINNED BOTTOM ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedBottomContent>\r\n <div class=\"re-dg-footer\" role=\"rowgroup\">\r\n @for (pr of vm.pinnedBottom(); track trackPinnedRow(pr); let pinnedBottomIndex = $index) {\r\n <div class=\"re-dg-row re-dg-pinned re-dg-bottom\" role=\"row\" [style.width.px]=\"contentW\" [style.min-width.%]=\"100\" [attr.aria-rowindex]=\"ariaPinnedBottomRowIndex(pinnedBottomIndex)\">\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n } @loading {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n @if (deferContent()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n } @loading {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n }\r\n </div>\r\n\r\n <ng-template #pinnedRowCells let-row>\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isIndex = 'type' in col && col.type === 'index';\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, $any(row))\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.height.px]=\"rowH\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, -1, true)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, -1, true)) ? tooltipId : null\"\r\n [attr.tabindex]=\"isCheckbox || isIndex ? -1 : 0\"\r\n (mouseenter)=\"!isCheckbox && !isIndex && onTooltipEnter($event, $any(row), col, -1, cellAriaId(col.key, -1, true))\"\r\n (mouseleave)=\"!isCheckbox && !isIndex && hideTooltip()\"\r\n (click)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event);\"\r\n (contextmenu)=\"!isCheckbox && !isIndex && onCellContext($any(row), col, -1, $event)\"\r\n (dblclick)=\"!isCheckbox && !isIndex && onCellDoubleClick($any(row), col, -1, $event)\"\r\n (keydown.enter)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event)\"\r\n >\r\n @if (!isCheckbox && !isIndex) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: $any(row), col: col, index: -1, isPinned: true }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferTooltip()) {\r\n @defer (when true) {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tooltipStateValue.tpl\"\r\n [ngTemplateOutletContext]=\"tooltipStateValue.ctx\"\r\n />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"tooltipStateValue.tpl\"\r\n [ngTemplateOutletContext]=\"tooltipStateValue.ctx\"\r\n />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Overlay scrollbar -->\r\n <div class=\"re-dg-scrollbar\" [class.visible]=\"vm.scrollbarVisible()\">\r\n <div\r\n class=\"re-dg-scrollbar-thumb\"\r\n role=\"scrollbar\"\r\n aria-orientation=\"vertical\"\r\n aria-hidden=\"false\"\r\n [style.height.px]=\"vm.thumbHeightPx()\"\r\n [style.transform]=\"'translateY(' + vm.thumbTopPx() + 'px)'\"\r\n (mousedown)=\"onThumbDown($event)\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [":host{--re-data-grid-min-height: 200px;--re-data-grid-height: 400px;--re-data-grid-rounded: var(--radius-md, 6px);--re-data-grid-separator-color: var(--border-color);--re-data-grid-separator: 1px solid var(--re-data-grid-separator-color);--re-data-grid-surface: var(--surface-neutral, #fff);--re-data-grid-active: var(--primary-color, #2a90f4);--re-data-grid-empty-color: #777;--re-data-grid-empty-surface: transparent;--re-data-grid-loading-color: #444;--re-data-grid-loading-surface: rgba(255, 255, 255, .5);--re-data-grid-spinner-size: 2rem;--re-data-grid-spinner-width: .25rem;--re-data-grid-spinner-track-color: rgba(0, 0, 0, .12);--re-data-grid-skeleton-width: 100%;--re-data-grid-skeleton-height: 100%;--re-data-grid-skeleton-rounded: var(--re-data-grid-rounded, .75rem);--re-data-grid-skeleton-shine: rgba(255, 255, 255, .8);--re-data-grid-skeleton-line: #e7ebf0;--re-data-grid-scrollbar-size: 4px;--re-data-grid-scrollbar-offset: 2px;--re-data-grid-scrollbar-track-rounded: .25rem;--re-data-grid-scrollbar-track-surface: transparent;--re-data-grid-scrollbar-thumb-size: 8px;--re-data-grid-scrollbar-thumb-color: rgba(0, 0, 0, .25);--re-data-grid-scrollbar-thumb-active-color: rgba(0, 0, 0, .45);--re-data-grid-scrollbar-thumb-rounded: var(--re-data-grid-scrollbar-track-rounded);--re-data-grid-tooltip-surface: #0f172a;--re-data-grid-tooltip-color: #f8fafc;--re-data-grid-tooltip-radius: .5rem;--re-data-grid-tooltip-padding: .4rem .6rem;--re-data-grid-tooltip-shadow: 0 8px 24px rgba(15, 23, 42, .25);--re-data-grid-tooltip-z: 60;--re-data-grid-header-rounded: var(--re-data-grid-rounded);--re-data-grid-header-surface: #fff;--re-data-grid-header-body-gap: 0px;--re-data-grid-header-row-height: 40px;--re-data-grid-header-row-separator-color: #ccc;--re-data-grid-header-row-separator: 1px solid var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-height: var(--re-data-grid-header-row-height);--re-data-grid-header-group-row-separator-color: var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-separator: 1px solid var(--re-data-grid-header-group-row-separator-color);--re-data-grid-header-group-cell-font-weight: var(--re-data-grid-header-cell-font-weight);--re-data-grid-header-group-cell-font-size: var(--re-data-grid-header-cell-font-size);--re-data-grid-header-group-cell-color: var(--re-data-grid-header-cell-color);--re-data-grid-header-group-cell-surface: var(--re-data-grid-header-cell-surface);--re-data-grid-header-cell-font-weight: 600;--re-data-grid-header-cell-font-size: .8rem;--re-data-grid-header-cell-color: #000;--re-data-grid-header-cell-surface: #fafafa;--re-data-grid-header-cell-line-height: 1.2;--re-data-grid-header-cell-max-lines: 2;--re-data-grid-footer-separator-color: #ccc;--re-data-grid-footer-separator: 1px solid var(--re-data-grid-footer-separator-color);--re-data-grid-footer-surface: #fff;--re-data-grid-row-separator-color: #bbb;--re-data-grid-row-separator: 1px solid var(--re-data-grid-row-separator-color);--re-data-grid-row-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-color: var(--re-data-grid-cell-color);--re-data-grid-row-hover-rounded: 0px;--re-data-grid-column-separator-color: transparent;--re-data-grid-column-separator: 1px solid var(--re-data-grid-column-separator-color);--re-data-grid-column-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-cell-paddings: .4rem .625rem;--re-data-grid-cell-font-weight: 400;--re-data-grid-cell-font-size: .75rem;--re-data-grid-cell-color: #000;--re-data-grid-cell-surface: #fff;--re-data-grid-cell-line-height: 1.2;--re-data-grid-cell-max-lines: 2;--re-data-grid-sticky-header-cell-surface: #fff;--re-data-grid-sticky-cell-surface: #fdfdfd;--re-data-grid-sticky-cell-row-odd-surface: #fdfdfd;--re-data-grid-sticky-cell-left-shadow: 2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-sticky-cell-right-shadow: -2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-pinned-surface: #fcfcfc;--re-data-grid-pinned-separator-color: #eee;--re-data-grid-pinned-separator: 1px solid var(--re-data-grid-pinned-separator-color);--re-data-grid-expander-color: var(--primary-color, currentColor);--re-data-grid-expanded-color: var(--re-data-grid-cell-color, #000);--re-data-grid-expanded-surface: var(--re-data-grid-cell-surface, #fff);--re-data-grid-focus-ring-color: color-mix(in srgb, var(--primary-color, #2a90f4) 55%, transparent);--re-data-grid-focus-ring-width: 2px;--re-data-grid-focus-ring-offset: -2px;display:block;min-height:0;min-width:0}:host,:host *,:host *:before,:host *:after{box-sizing:border-box;outline:none}:host button{outline:none}.re-dg-root{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;min-height:var(--re-data-grid-min-height);border-radius:var(--re-data-grid-rounded);border:var(--re-data-grid-separator)}.re-dg-root.fill{display:block}.re-dg-root.re-dg-loading{pointer-events:none;-webkit-user-select:none;user-select:none;cursor:wait}.re-dg-root.re-dg-loading .re-dg-body{overflow:hidden}.re-dg-root.re-dg-loading .re-dg-scrollbar{display:none!important}.re-dg-root.re-dg-loading .re-dg-loader{pointer-events:all}.re-dg-root.lock-vertical-scroll .re-dg-body{overflow-x:auto;overflow-y:hidden}.re-dg-root.lock-vertical-scroll .re-dg-scrollbar{display:none!important}.re-dg-root.resizing-columns{-webkit-user-select:none;user-select:none;cursor:col-resize}.re-dg-body{position:relative;flex:1 1 auto;min-height:0;min-width:0;height:inherit;border:var(--re-data-grid-separator);border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-surface);overflow:auto;scrollbar-width:auto;-ms-overflow-style:auto}.re-dg-body::-webkit-scrollbar{width:var(--re-data-grid-scrollbar-size);height:var(--re-data-grid-scrollbar-size)}.re-dg-body::-webkit-scrollbar:vertical{width:0}.re-dg-body::-webkit-scrollbar-track{border-radius:var(--re-data-grid-scrollbar-track-rounded);background:var(--re-data-grid-scrollbar-track-surface)}.re-dg-body::-webkit-scrollbar-thumb{border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);transition:opacity .3s ease}.re-dg-body::-webkit-scrollbar-thumb:hover{background:var(--re-data-grid-scrollbar-thumb-active-color)}.re-dg-header,.re-dg-footer{position:sticky;z-index:3}.re-dg-header{top:0;background-color:var(--re-data-grid-header-surface)}.re-dg-header-row{min-height:var(--re-data-grid-header-row-height)}.re-dg-header-group-row{min-height:var(--re-data-grid-header-group-row-height)}.re-dg-header-rows{display:flex;flex-direction:column;padding-bottom:var(--re-data-grid-header-body-gap)}.re-dg-footer{bottom:0;border-radius:0 0 var(--re-data-grid-rounded) var(--re-data-grid-rounded);background-color:var(--re-data-grid-footer-surface)}.re-dg-row{position:relative;display:flex}.re-dg-data-row{position:absolute;left:0;top:0;min-width:100%;cursor:default;will-change:transform}.re-dg-sticky-row{z-index:2;top:0}.re-dg-cell,.re-dg-header-cell{display:flex;flex:0 0 auto;align-items:center;padding:var(--re-data-grid-cell-paddings);border-right:var(--re-data-grid-column-separator);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.re-dg-cell:focus-visible,.re-dg-header-cell:focus-visible,.re-dg-header-cell button:focus-visible,.re-dg-row[tabindex=\"0\"]:focus-visible{outline:var(--re-data-grid-focus-ring-width) solid var(--re-data-grid-focus-ring-color);outline-offset:var(--re-data-grid-focus-ring-offset);z-index:4}.re-dg-cell{width:100%;border-bottom:var(--re-data-grid-row-separator);font-weight:var(--re-data-grid-cell-font-weight);font-size:var(--re-data-grid-cell-font-size);color:var(--re-data-grid-cell-color);background-color:var(--re-data-grid-cell-surface)}.re-dg-row:nth-child(odd) .re-dg-cell{background-color:var(--re-data-grid-row-odd-surface)}.re-dg-row.re-dg-row-disabled .re-dg-cell{opacity:.6;cursor:not-allowed}.re-dg-row:nth-child(odd) .re-dg-cell.sticky-left,.re-dg-row:nth-child(odd) .re-dg-cell.sticky-right{background-color:var(--re-data-grid-sticky-cell-row-odd-surface)}.re-dg-cell:nth-child(odd){background-color:var(--re-data-grid-column-odd-surface)}.re-dg-bottom>.re-dg-cell{border-top:var(--re-data-grid-footer-separator)}.re-dg-header-cell{position:relative;align-items:center;gap:.75rem;border-bottom:var(--re-data-grid-header-row-separator);font-weight:var(--re-data-grid-header-cell-font-weight);font-size:var(--re-data-grid-header-cell-font-size);color:var(--re-data-grid-header-cell-color);background:var(--re-data-grid-header-cell-surface);-webkit-user-select:none;user-select:none;transition:color .3s ease-in-out}.re-dg-column-resize-handle{position:absolute;top:0;right:-4px;width:8px;height:100%;cursor:col-resize;z-index:5}.re-dg-header-cell.re-dg-header-group-cell{border-bottom:var(--re-data-grid-header-group-row-separator);font-weight:var(--re-data-grid-header-group-cell-font-weight);font-size:var(--re-data-grid-header-group-cell-font-size);color:var(--re-data-grid-header-group-cell-color);background:var(--re-data-grid-header-group-cell-surface)}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:first-child{border-radius:var(--re-data-grid-header-rounded) 0 0 0}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:last-child{border-radius:0 var(--re-data-grid-header-rounded) 0 0}.re-dg-data-row:last-child .re-dg-cell:first-child{border-radius:0 0 0 var(--re-data-grid-rounded)}.re-dg-data-row:last-child .re-dg-cell:last-child{border-radius:0 0 var(--re-data-grid-rounded) 0}.re-dg-header-cell .re-dg-header-text{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:var(--re-data-grid-header-cell-line-height);-webkit-box-orient:vertical;-webkit-line-clamp:var(--re-data-grid-header-cell-max-lines)}.re-dg-row.re-dg-pinned>.re-dg-cell{border-bottom:var(--re-data-grid-pinned-separator);background-color:var(--re-data-grid-pinned-surface)}.re-dg-row .re-dg-header-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row .re-dg-header-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-left,.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-pinned-surface)}.re-dg-row:hover>.re-dg-cell,.re-dg-row:hover>.re-dg-cell.sticky-left,.re-dg-row:hover>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-row-hover-surface)!important;color:var(--re-data-grid-row-hover-color)!important}.re-dg-row:hover>.re-dg-cell:first-child{border-radius:var(--re-data-grid-row-hover-rounded) 0 0 var(--re-data-grid-row-hover-rounded)}.re-dg-row:hover>.re-dg-cell:last-child{border-radius:0 var(--re-data-grid-row-hover-rounded) var(--re-data-grid-row-hover-rounded) 0}.sticky-left,.sticky-right{position:sticky;z-index:2}.sortable{cursor:pointer}.active-sort{color:var(--re-data-grid-active)}.re-dg-sort-ind{margin-left:6px}.re-dg-icon-placeholder{display:inline-block;width:1rem;height:1rem}.re-dg-cell-deferred{display:block;width:100%;height:100%}.re-dg-deferred-placeholder{background:transparent}.re-dg-data-row .re-dg-cell.expanded{color:var(--re-data-grid-expanded-color);background:var(--re-data-grid-expanded-surface)}.re-dg-empty{position:absolute;inset:0;display:grid;place-items:center;height:inherit;width:100%;border-radius:var(--re-data-grid-rounded);color:var(--re-data-grid-empty-color);background:var(--re-data-grid-empty-surface)}.re-dg-empty-text{width:100%;text-align:center}.re-dg-loader{position:absolute;inset:0;display:grid;place-items:center;height:inherit;border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-loading-surface);color:var(--re-data-grid-loading-color);z-index:5}.re-dg-tooltip{position:fixed;left:0;top:0;max-width:min(28rem,70vw);padding:var(--re-data-grid-tooltip-padding);border-radius:var(--re-data-grid-tooltip-radius);background:var(--re-data-grid-tooltip-surface);color:var(--re-data-grid-tooltip-color);box-shadow:var(--re-data-grid-tooltip-shadow);font-size:.75rem;line-height:1.2;z-index:var(--re-data-grid-tooltip-z);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease}.re-dg-tooltip.visible{opacity:1;transform:translateY(0)}.re-dg-loader-spinner{width:var(--re-data-grid-spinner-size);height:var(--re-data-grid-spinner-size);border-radius:50%;border:var(--re-data-grid-spinner-width) solid var(--re-data-grid-spinner-track-color);border-top-color:var(--re-data-grid-loading-color);animation:re-dg-spinner .8s linear infinite}.re-dg-skeleton-row{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:var(--re-data-grid-cell-surface);pointer-events:none}.re-dg-gap-loader{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:color-mix(in srgb,var(--re-data-grid-cell-surface) 88%,var(--re-data-grid-skeleton-line));pointer-events:none;opacity:.9}.re-dg-skeleton-row-line{display:block;width:var(--re-data-grid-skeleton-width);height:var(--re-data-grid-skeleton-height);border-radius:var(--re-data-grid-skeleton-rounded);background:linear-gradient(90deg,var(--re-data-grid-skeleton-line) 0%,var(--re-data-grid-skeleton-shine) 50%,var(--re-data-grid-skeleton-line) 100%);background-size:200% 100%;animation:re-dg-skeleton 1.2s ease-in-out infinite}@keyframes re-dg-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes re-dg-spinner{to{transform:rotate(360deg)}}.re-dg-scrollbar{position:absolute;right:0;top:0;bottom:0;opacity:0;transition:opacity .15s ease-in-out;pointer-events:none;z-index:4}.re-dg-scrollbar.visible{opacity:1}.re-dg-scrollbar-thumb{position:absolute;right:var(--re-data-grid-scrollbar-offset);width:var(--re-data-grid-scrollbar-thumb-size);border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);pointer-events:auto;-webkit-user-select:none;user-select:none}.re-dg-spacer{width:1px}.re-dg-top{top:0}.re-dg-bottom{bottom:0}\n"] }]
4242
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], pinnedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedRows", required: false }] }], isRowSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowSticky", required: false }] }], isRowDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowDisabled", required: false }] }], getRowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowClass", required: false }] }], getRowTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowTemplate", required: false }] }], hasIndexColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasIndexColumn", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], virtualBuffer: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualBuffer", required: false }] }], lockVerticalScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockVerticalScroll", required: false }] }], headerGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerGroups", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMode", required: false }] }], deferContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferContent", required: false }] }], deferHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferHeader", required: false }] }], deferPinned: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferPinned", required: false }] }], deferCells: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferCells", required: false }] }], deferIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferIcons", required: false }] }], deferTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferTooltip", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], pageStartFromZero: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageStartFromZero", required: false }] }], sortMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortMode", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], multiSortChange: [{ type: i0.Output, args: ["multiSortChange"] }], selectChange: [{ type: i0.Output, args: ["selectChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowContext: [{ type: i0.Output, args: ["rowContext"] }], rowDoubleClick: [{ type: i0.Output, args: ["rowDoubleClick"] }], cellClick: [{ type: i0.Output, args: ["cellClick"] }], cellContext: [{ type: i0.Output, args: ["cellContext"] }], cellDoubleClick: [{ type: i0.Output, args: ["cellDoubleClick"] }], columnResizeEnd: [{ type: i0.Output, args: ["columnResizeEnd"] }], rootEl: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }], scrollEl: [{ type: i0.ViewChild, args: ['scroll', { isSignal: true }] }], headerEl: [{ type: i0.ViewChild, args: ['header', { isSignal: true }] }], cellTypedSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridTypeCellTemplateDirective), { isSignal: true }] }], cellDataSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridCellTemplateDirective), { isSignal: true }] }], declarativeColumnRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridDeclarativeColumn), { isSignal: true }] }], headerSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridHeaderTemplateDirective), { isSignal: true }] }], emptySlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridCellEmptyDirective), { isSignal: true }] }], loadingSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridCellLoadingDirective), { isSignal: true }] }], sortIcSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridSortIconDirective), { isSignal: true }] }], expanderIcSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridExpanderIconDirective), { isSignal: true }] }], stickyRowSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridStickyRowDirective), { isSignal: true }] }], rowSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridRowDirective), { isSignal: true }] }], tooltipEl: [{ type: i0.ViewChild, args: ['tooltip', { isSignal: true }] }] } });
4646
+ args: [{ selector: 're-data-grid', imports: [NgTemplateOutlet, DataGridCellComponent, SortIcon, ExpandIcon, CheckboxIcon], providers: [DataGridVm], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let items = selectionRows();\r\n@let totalRows = totalRowCount();\r\n@let renderRows = renderRowCount();\r\n@let empty = !resolvedLoading() && !renderRows;\r\n@let notEmpty = !!renderRows;\r\n@let skeletonRowsCount = 4;\r\n@let skeletonMode = loadingMode() === 'skeleton';\r\n@let spinnerMode = loadingMode() === 'spinner';\r\n@let showInfinitySkeleton = resolvedBlockingLoading() && skeletonMode && mode() === 'infinity';\r\n@let showPaginationSkeleton = resolvedBlockingLoading() && skeletonMode && mode() === 'pagination';\r\n@let showSpinnerLoading = resolvedBlockingLoading() && spinnerMode;\r\n@let extraInfinitySkeletonRows = showInfinitySkeleton ? skeletonRowsCount : 0;\r\n\r\n@let pinnedTopH = vm.pinnedTop().length * rowHeight();\r\n@let pinnedBottomH = vm.pinnedBottom().length * rowHeight();\r\n@let rowH = rowHeight();\r\n@let contentW = vm.contentWidth();\r\n@let cols = vm.columnsToShow();\r\n@let stickyTop = pinnedTopH + headerHeight();\r\n@let normalizedHeaderGroups = vm.normalizedHeaderGroups();\r\n@let stickyRow = stickyRowData();\r\n@let stickyIndex = stickyRowIndex();\r\n\r\n<div\r\n #root\r\n class=\"re-dg-root\"\r\n [attr.id]=\"expanderRegionId\"\r\n [class.re-dg-loading]=\"showSpinnerLoading\"\r\n [class.lock-vertical-scroll]=\"lockVerticalScroll()\"\r\n [class.resizing-columns]=\"isColumnResizing()\"\r\n [style.height]=\"styleHeight()\"\r\n [attr.aria-multiselectable]=\"selection().mode === 'multi' ? true : null\"\r\n [attr.aria-rowcount]=\"ariaRowCount()\"\r\n [attr.aria-colcount]=\"ariaColCount()\"\r\n role=\"grid\"\r\n>\r\n @if (showSpinnerLoading) {\r\n <div class=\"re-dg-loader\" aria-live=\"polite\" role=\"status\">\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n <span class=\"re-dg-loader-spinner\" aria-label=\"Loading\"></span>\r\n }\r\n </div>\r\n }\r\n\r\n <div #scroll class=\"re-dg-body\" role=\"rowgroup\" (mouseenter)=\"showScrollbar()\" (mouseleave)=\"hideScrollbarSoon()\">\r\n <ng-template #headerContent>\r\n <div class=\"re-dg-header\" role=\"rowgroup\" [style.width.px]=\"vm.contentWidth()\" [style.min-width.%]=\"100\">\r\n <div #header class=\"re-dg-header-rows\">\r\n @if (normalizedHeaderGroups.length) {\r\n <div\r\n class=\"re-dg-row re-dg-header-group-row\"\r\n role=\"row\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n >\r\n @for (group of normalizedHeaderGroups; track group.key; let groupIndex = $index) {\r\n @let groupStickyLeft =\r\n !!group.startKey &&\r\n !!group.endKey &&\r\n vm.isStickyLeft(group.startKey) &&\r\n vm.isStickyLeft(group.endKey);\r\n @let groupStickyRight =\r\n !!group.startKey &&\r\n !!group.endKey &&\r\n vm.isStickyRight(group.startKey) &&\r\n vm.isStickyRight(group.endKey);\r\n\r\n @let resolvedGroupTitle = resolveHeaderGroupTitle(group);\r\n\r\n <div\r\n class=\"re-dg-header-cell re-dg-header-group-cell\"\r\n role=\"columnheader\"\r\n [class.sticky-left]=\"groupStickyLeft\"\r\n [class.sticky-right]=\"groupStickyRight\"\r\n [style.left.px]=\"groupStickyLeft && group.startKey ? vm.stickyOffset(group.startKey, 'left') : null\"\r\n [style.right.px]=\"groupStickyRight && group.endKey ? vm.stickyOffset(group.endKey, 'right') : null\"\r\n [style.width.px]=\"group.widthPx\"\r\n [style.justify-content]=\"group.align || 'left'\"\r\n [title]=\"resolvedGroupTitle\"\r\n [attr.aria-colindex]=\"ariaHeaderGroupColIndex(group)\"\r\n [attr.aria-rowindex]=\"groupIndex + 1\"\r\n >\r\n @if (group.titleTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"group.titleTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedGroupTitle }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedGroupTitle }}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"re-dg-row re-dg-header-row\"\r\n role=\"row\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n >\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-header-cell\"\r\n role=\"columnheader\"\r\n [class.sortable]=\"!!col.sortKey\"\r\n [class.active-sort]=\"isActiveSort(col)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [style.min-width.px]=\"col.minWidth || null\"\r\n [style.max-width.px]=\"col.maxWidth || null\"\r\n [style.justify-content]=\"col.align || 'left'\"\r\n [attr.aria-sort]=\"ariaSort(col)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-rowindex]=\"normalizedHeaderGroups.length ? 2 : 1\"\r\n [attr.aria-label]=\"col.sortKey ? ariaSortLabel(col) : null\"\r\n [attr.tabindex]=\"col.sortKey ? 0 : -1\"\r\n (click)=\"col.sortKey && onSort(col)\"\r\n (keydown.enter)=\"col.sortKey && onSort(col)\"\r\n >\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isMultiSelect = selection().mode === 'multi';\r\n\r\n @if (isCheckbox && isMultiSelect) {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\"\r\n />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-checkbox-ic\r\n aria-label=\"Select loaded rows\"\r\n [state]=\"selector.isAllSelected()\"\r\n tabindex=\"0\"\r\n (click)=\"onSelectAll($event)\"\r\n (keydown.enter)=\"onSelectAllKeydown($event)\"\r\n (keydown.space)=\"onSelectAllKeydown($event)\"\r\n />\r\n }\r\n } @else {\r\n @let resolvedHeader = resolveHeaderText(col);\r\n\r\n @if (col.headerTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"col.headerTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvedHeader }\"\r\n />\r\n } @else {\r\n <span class=\"re-dg-header-text\">{{ resolvedHeader }}</span>\r\n }\r\n }\r\n\r\n @if (col.sortKey) {\r\n <span class=\"re-dg-sort-ind\">\r\n @let direction = sortOrderFor(col);\r\n\r\n @if (sortTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"sortTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: direction }\"\r\n />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-sort-ic [direction]=\"direction\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-sort-ic [direction]=\"direction\" />\r\n }\r\n }\r\n </span>\r\n }\r\n\r\n @if (isExpandable(col)) {\r\n <button\r\n [attr.aria-controls]=\"expanderRegionId\"\r\n [attr.aria-expanded]=\"expanderMap().get(col.key) ? 'true' : 'false'\"\r\n [attr.aria-label]=\"ariaExpandLabel(col)\"\r\n (click)=\"$event.stopPropagation(); onExpand(col)\"\r\n >\r\n @let expanded = expanderMap().get(col.key);\r\n\r\n @if (expanderTpl()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"expanderTpl()!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: expanded }\"\r\n />\r\n } @else {\r\n @if (deferIcons()) {\r\n @defer (when true) {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n } @placeholder {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n } @loading {\r\n <span class=\"re-dg-icon-placeholder\"></span>\r\n }\r\n } @else {\r\n <re-expand-ic [expanded]=\"expanded\" />\r\n }\r\n }\r\n </button>\r\n }\r\n\r\n @if (canResizeColumn(col)) {\r\n <div\n class=\"re-dg-column-resize-handle\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"ariaResizeLabel(col)\"\n [attr.aria-valuemin]=\"ariaResizeMin(col)\"\n [attr.aria-valuemax]=\"ariaResizeMax(col)\"\n [attr.aria-valuenow]=\"ariaResizeValue(col)\"\n tabindex=\"0\"\n (mousedown)=\"onColumnResizeStart($event, col)\"\n (keydown)=\"onColumnResizeKeydown($event, col)\"\n (click)=\"$event.stopPropagation()\"\n ></div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- PINNED TOP ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedTopContent>\r\n @for (pr of vm.pinnedTop(); track trackPinnedRow(pr, 'top', pinnedTopIndex); let pinnedTopIndex = $index) {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-top\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [attr.aria-rowindex]=\"ariaPinnedTopRowIndex(pinnedTopIndex)\"\r\n >\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: resolvePinnedData(pr),\r\n row: pr,\r\n index: pinnedTopIndex,\r\n region: 'top',\r\n }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n } @placeholder {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\"\r\n [style.min-height.px]=\"rowH\"\r\n ></div>\r\n } @loading {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-top re-dg-deferred-placeholder\"\r\n [style.min-height.px]=\"rowH\"\r\n ></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedTopContent\" />\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferHeader()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n } @loading {\r\n <div class=\"re-dg-header re-dg-deferred-placeholder\" [style.min-height.px]=\"headerHeight()\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"headerContent\" />\r\n }\r\n\r\n <ng-template #dataCellContent let-row let-col=\"col\" let-index=\"index\" let-isPinned=\"isPinned\">\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n\r\n @if (isCheckbox) {\r\n <re-checkbox-ic\r\n aria-label=\"Toggle row selection\"\r\n [state]=\"selector.isSelected(row)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, index)\"\r\n [attr.tabindex]=\"isDisabledRow(row, index) ? -1 : 0\"\r\n (click)=\"onCheckboxToggle(row, index, $event)\"\r\n (keydown.enter)=\"onCheckboxKeydown(row, index, $event)\"\r\n (keydown.space)=\"onCheckboxKeydown(row, index, $event)\"\r\n />\r\n } @else {\r\n @if (deferCells()) {\r\n @defer (when true) {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n } @placeholder {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n } @loading {\r\n <span class=\"re-dg-cell-deferred\"></span>\r\n }\r\n } @else {\r\n <re-data-grid-cell [index]=\"index\" [item]=\"row\" [column]=\"col\" [isPinned]=\"!!isPinned\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n <ng-template #gridContent>\r\n <!-- STICKY ROW -->\r\n @if (stickyRow && stickyIndex !== null) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-sticky-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(stickyRow, stickyIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [style.width.px]=\"vm.contentWidth()\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.top.px]=\"stickyRowTopPx()\"\r\n [attr.data-re-dg-row-index]=\"stickyIndex\"\n [attr.aria-rowindex]=\"ariaDataRowIndex(stickyIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(stickyRow, stickyIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(stickyRow) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(stickyRow, stickyIndex, $event)\"\r\n (contextmenu)=\"onRowContext(stickyRow, stickyIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(stickyRow, stickyIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(stickyRow, stickyIndex, $event)\"\n (keydown.arrowdown)=\"onRowKeydown(stickyIndex, $event)\"\n (keydown.arrowup)=\"onRowKeydown(stickyIndex, $event)\"\r\n >\r\n @let stickyTemplate = stickyRowTpl();\r\n @let rowTemplate = resolveRowTemplate(stickyRow, stickyIndex);\r\n\r\n @if (stickyTemplate?.tpl) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"stickyTemplate!.tpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, index: stickyIndex }\"\r\n />\r\n } @else if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: stickyRow,\r\n index: stickyIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: true,\r\n }\"\r\n />\r\n } @else {\r\n @for (col of vm.columnsToShow(); track col.key; let colIndex = $index) {\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, stickyRow)\"\r\n [class.sticky-left]=\"vm.isStickyLeft(col.key)\"\r\n [class.sticky-right]=\"vm.isStickyRight(col.key)\"\r\n [style.left.px]=\"vm.stickyOffset(col.key, 'left')\"\r\n [style.right.px]=\"vm.stickyOffset(col.key, 'right')\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, stickyIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, stickyIndex, false)) ? tooltipId : null\"\r\n (mouseenter)=\"\r\n onTooltipEnter($event, stickyRow, col, stickyIndex, cellAriaId(col.key, stickyIndex, false))\r\n \"\r\n (mouseleave)=\"hideTooltip()\"\r\n (focusin)=\"onTooltipFocus($event, stickyRow, col, stickyIndex, cellAriaId(col.key, stickyIndex, false))\"\r\n (focusout)=\"hideTooltip()\"\r\n (keydown.escape)=\"hideTooltip()\"\r\n (click)=\"onCellClick(stickyRow, col, stickyIndex, $event)\"\r\n (contextmenu)=\"onCellContext(stickyRow, col, stickyIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(stickyRow, col, stickyIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(stickyRow, col, stickyIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: stickyRow, col: col, index: stickyIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n @if (empty) {\r\n @let emptyTemplate = emptyTpl()?.tpl;\r\n\r\n <div class=\"re-dg-empty\" aria-live=\"polite\" role=\"status\">\r\n @if (emptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\" />\r\n } @else {\r\n <span class=\"re-dg-empty-text\">{{ defaults.translations.emptyState }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Content -->\r\n @if (notEmpty) {\r\n @let topGap = topGapLoader();\r\n @let bottomGap = bottomGapLoader();\r\n <div\r\n class=\"re-dg-spacer\"\r\n [style.width.px]=\"contentW\"\r\n [style.height.px]=\"(renderRows + extraInfinitySkeletonRows) * rowH - pinnedBottomH\"\r\n ></div>\r\n\r\n @if (topGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"topGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (topGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n\r\n @for (entry of renderSlotEntries(); track entry.key) {\n @let slot = entry.slot;\r\n @let rowIndex = startIndex + slot;\r\n @let row = rowAt(rowIndex);\r\n @let rowTemplate = row ? resolveRowTemplate(row, rowIndex) : null;\r\n\r\n @if (row && !isStickyRowIndex(rowIndex)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row\"\r\n role=\"row\"\r\n [class]=\"resolveRowClass(row, rowIndex)\"\r\n [class.re-dg-row-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n [attr.data-re-dg-row-index]=\"rowIndex\"\n [attr.aria-rowindex]=\"ariaDataRowIndex(rowIndex)\"\r\n [attr.aria-disabled]=\"isDisabledRow(row, rowIndex)\"\r\n [attr.aria-selected]=\"selection().mode !== 'none' ? selector.isSelected(row) : null\"\r\n [attr.tabindex]=\"0\"\r\n (click)=\"onRowClick(row, rowIndex, $event)\"\r\n (contextmenu)=\"onRowContext(row, rowIndex, $event)\"\r\n (dblclick)=\"onRowDoubleClick(row, rowIndex, $event)\"\r\n (keydown.enter)=\"onRowClick(row, rowIndex, $event)\"\n (keydown.arrowdown)=\"onRowKeydown(rowIndex, $event)\"\n (keydown.arrowup)=\"onRowKeydown(rowIndex, $event)\"\r\n >\r\n @if (rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: row,\r\n index: rowIndex,\r\n columns: vm.columnsToShow(),\r\n rowHeight: rowHeight(),\r\n isSticky: false,\r\n }\"\r\n />\r\n } @else {\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, row)\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"cellAriaId(col.key, rowIndex, false)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"isTooltipTarget(cellAriaId(col.key, rowIndex, false)) ? tooltipId : null\"\r\n (mouseenter)=\"onTooltipEnter($event, row, col, rowIndex, cellAriaId(col.key, rowIndex, false))\"\r\n (mouseleave)=\"hideTooltip()\"\r\n (focusin)=\"onTooltipFocus($event, row, col, rowIndex, cellAriaId(col.key, rowIndex, false))\"\r\n (focusout)=\"hideTooltip()\"\r\n (keydown.escape)=\"hideTooltip()\"\r\n (click)=\"onCellClick(row, col, rowIndex, $event)\"\r\n (contextmenu)=\"onCellContext(row, col, rowIndex, $event)\"\r\n (dblclick)=\"onCellDoubleClick(row, col, rowIndex, $event)\"\r\n (keydown.enter)=\"onCellClick(row, col, rowIndex, $event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: row, col: col, index: rowIndex, isPinned: false }\"\r\n />\r\n </div>\r\n }\r\n }\r\n </div>\r\n } @else if (shouldRenderLoadingRow(rowIndex, topGap, bottomGap)) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"'translateY(' + (rowIndex * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (bottomGap) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-gap-loader\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"bottomGap.count * rowH\"\r\n [style.transform]=\"'translateY(' + (bottomGap.start * rowH + stickyTop) + 'px)'\"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (showInfinitySkeleton || showPaginationSkeleton) {\r\n @let loadingTemplate = loadingTpl();\r\n\r\n @if (loadingTemplate?.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"loadingTemplate!.tpl\" />\r\n } @else {\r\n @for (si of [0, 1, 2, 3]; track si) {\r\n <div\r\n class=\"re-dg-row re-dg-data-row re-dg-skeleton-row\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [style.height.px]=\"rowH\"\r\n [style.transform]=\"\r\n 'translateY(' + (((showInfinitySkeleton ? items.length : 0) + si) * rowH + stickyTop) + 'px)'\r\n \"\r\n >\r\n <span class=\"re-dg-skeleton-row-line\"></span>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n <!-- PINNED BOTTOM ROWS -->\r\n @if (notEmpty) {\r\n <ng-template #pinnedBottomContent>\r\n <div class=\"re-dg-footer\" role=\"rowgroup\">\r\n @for (\r\n pr of vm.pinnedBottom();\r\n track trackPinnedRow(pr, 'bottom', pinnedBottomIndex);\r\n let pinnedBottomIndex = $index\r\n ) {\r\n <div\r\n class=\"re-dg-row re-dg-pinned re-dg-bottom\"\r\n role=\"row\"\r\n [style.width.px]=\"contentW\"\r\n [style.min-width.%]=\"100\"\r\n [attr.aria-rowindex]=\"ariaPinnedBottomRowIndex(pinnedBottomIndex)\"\r\n >\r\n @if (pr.rowTemplate) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pr.rowTemplate!\"\r\n [ngTemplateOutletContext]=\"{ $implicit: resolvePinnedData(pr) }\"\r\n />\r\n } @else {\r\n <ng-container\r\n [ngTemplateOutlet]=\"pinnedRowCells\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: resolvePinnedData(pr),\r\n row: pr,\r\n index: pinnedBottomIndex,\r\n region: 'bottom',\r\n }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (deferPinned()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n } @loading {\r\n <div class=\"re-dg-footer re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"pinnedBottomContent\" />\r\n }\r\n }\r\n </ng-template>\r\n\r\n @if (deferContent()) {\r\n @defer (when true) {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n } @placeholder {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n } @loading {\r\n <div class=\"re-dg-deferred-placeholder\" [style.min-height.px]=\"rowH * 3\"></div>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"gridContent\" />\r\n }\r\n </div>\r\n\r\n <ng-template #pinnedRowCells let-row let-pinnedRow=\"row\" let-pinnedIndex=\"index\" let-pinnedRegion=\"region\">\r\n @for (col of cols; track col.key; let colIndex = $index) {\r\n @let isCheckbox = 'type' in col && col.type === 'checkbox';\r\n @let isIndex = 'type' in col && col.type === 'index';\r\n @let stickyLeft = vm.stickyOffset(col.key, 'left');\r\n @let stickyRight = vm.stickyOffset(col.key, 'right');\r\n @let isLeft = vm.isStickyLeft(col.key);\r\n @let isRight = vm.isStickyRight(col.key);\r\n\r\n <div\r\n class=\"re-dg-cell\"\r\n role=\"gridcell\"\r\n [class.expanded]=\"!!col.expandBy\"\r\n [class]=\"cellClass(col, $any(row))\"\r\n [class.sticky-left]=\"isLeft\"\r\n [class.sticky-right]=\"isRight\"\r\n [style.left.px]=\"stickyLeft\"\r\n [style.right.px]=\"stickyRight\"\r\n [style.justify-items]=\"col.align || 'left'\"\r\n [style.text-align]=\"col.align || 'left'\"\r\n [style.height.px]=\"rowH\"\r\n [style.width.px]=\"vm.widthByKey(col.key)\"\r\n [attr.id]=\"pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex)\"\r\n [attr.aria-colindex]=\"colIndex + 1\"\r\n [attr.aria-describedby]=\"\r\n isTooltipTarget(pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex)) ? tooltipId : null\r\n \"\r\n (mouseenter)=\"\r\n !isCheckbox &&\r\n !isIndex &&\r\n onTooltipEnter($event, $any(row), col, -1, pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex))\r\n \"\r\n (mouseleave)=\"!isCheckbox && !isIndex && hideTooltip()\"\r\n (focusin)=\"\r\n !isCheckbox &&\r\n !isIndex &&\r\n onTooltipFocus($event, $any(row), col, -1, pinnedCellAriaId(col.key, pinnedRow, pinnedRegion, pinnedIndex))\r\n \"\r\n (focusout)=\"!isCheckbox && !isIndex && hideTooltip()\"\r\n (keydown.escape)=\"hideTooltip()\"\r\n (click)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event)\"\r\n (contextmenu)=\"!isCheckbox && !isIndex && onCellContext($any(row), col, -1, $event)\"\r\n (dblclick)=\"!isCheckbox && !isIndex && onCellDoubleClick($any(row), col, -1, $event)\"\r\n (keydown.enter)=\"!isCheckbox && !isIndex && onCellClick($any(row), col, -1, $event)\"\r\n >\r\n @if (!isCheckbox && !isIndex) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"dataCellContent\"\r\n [ngTemplateOutletContext]=\"{ $implicit: $any(row), col: col, index: -1, isPinned: true }\"\r\n />\r\n }\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (deferTooltip()) {\r\n @defer (when true) {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"tooltipStateValue.tpl\" [ngTemplateOutletContext]=\"tooltipStateValue.ctx\" />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n } @else {\r\n @let tooltipStateValue = tooltipState();\r\n <div\r\n class=\"re-dg-tooltip\"\r\n #tooltip\r\n role=\"tooltip\"\r\n [attr.id]=\"tooltipId\"\r\n [class.visible]=\"tooltipStateValue.visible\"\r\n [style.left.px]=\"tooltipStateValue.x\"\r\n [style.top.px]=\"tooltipStateValue.y\"\r\n >\r\n @if (tooltipStateValue.tpl) {\r\n <ng-container [ngTemplateOutlet]=\"tooltipStateValue.tpl\" [ngTemplateOutletContext]=\"tooltipStateValue.ctx\" />\r\n } @else {\r\n {{ tooltipStateValue.text }}\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Overlay scrollbar -->\r\n <div class=\"re-dg-scrollbar\" [class.visible]=\"vm.scrollbarVisible()\">\r\n <div\r\n class=\"re-dg-scrollbar-thumb\"\r\n [style.height.px]=\"vm.thumbHeightPx()\"\r\n [style.transform]=\"'translateY(' + vm.thumbTopPx() + 'px)'\"\r\n (pointerdown)=\"onThumbDown($event)\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [":host{--re-data-grid-min-height: 200px;--re-data-grid-height: 400px;--re-data-grid-rounded: var(--radius-md, 6px);--re-data-grid-separator-color: var(--border-color);--re-data-grid-separator: 1px solid var(--re-data-grid-separator-color);--re-data-grid-surface: var(--surface-neutral, #fff);--re-data-grid-active: var(--primary-color, #2a90f4);--re-data-grid-empty-color: #777;--re-data-grid-empty-surface: transparent;--re-data-grid-loading-color: #444;--re-data-grid-loading-surface: rgba(255, 255, 255, .5);--re-data-grid-spinner-size: 2rem;--re-data-grid-spinner-width: .25rem;--re-data-grid-spinner-track-color: rgba(0, 0, 0, .12);--re-data-grid-skeleton-width: 100%;--re-data-grid-skeleton-height: 100%;--re-data-grid-skeleton-rounded: var(--re-data-grid-rounded, .75rem);--re-data-grid-skeleton-shine: rgba(255, 255, 255, .8);--re-data-grid-skeleton-line: #e7ebf0;--re-data-grid-scrollbar-size: 4px;--re-data-grid-scrollbar-offset: 2px;--re-data-grid-scrollbar-track-rounded: .25rem;--re-data-grid-scrollbar-track-surface: transparent;--re-data-grid-scrollbar-thumb-size: 8px;--re-data-grid-scrollbar-thumb-color: rgba(0, 0, 0, .25);--re-data-grid-scrollbar-thumb-active-color: rgba(0, 0, 0, .45);--re-data-grid-scrollbar-thumb-rounded: var(--re-data-grid-scrollbar-track-rounded);--re-data-grid-tooltip-surface: #0f172a;--re-data-grid-tooltip-color: #f8fafc;--re-data-grid-tooltip-radius: .5rem;--re-data-grid-tooltip-padding: .4rem .6rem;--re-data-grid-tooltip-shadow: 0 8px 24px rgba(15, 23, 42, .25);--re-data-grid-tooltip-z: 60;--re-data-grid-header-rounded: var(--re-data-grid-rounded);--re-data-grid-header-surface: #fff;--re-data-grid-header-body-gap: 0px;--re-data-grid-header-row-height: 40px;--re-data-grid-header-row-separator-color: #ccc;--re-data-grid-header-row-separator: 1px solid var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-height: var(--re-data-grid-header-row-height);--re-data-grid-header-group-row-separator-color: var(--re-data-grid-header-row-separator-color);--re-data-grid-header-group-row-separator: 1px solid var(--re-data-grid-header-group-row-separator-color);--re-data-grid-header-group-cell-font-weight: var(--re-data-grid-header-cell-font-weight);--re-data-grid-header-group-cell-font-size: var(--re-data-grid-header-cell-font-size);--re-data-grid-header-group-cell-color: var(--re-data-grid-header-cell-color);--re-data-grid-header-group-cell-surface: var(--re-data-grid-header-cell-surface);--re-data-grid-header-cell-font-weight: 600;--re-data-grid-header-cell-font-size: .8rem;--re-data-grid-header-cell-color: #000;--re-data-grid-header-cell-surface: #fafafa;--re-data-grid-header-cell-line-height: 1.2;--re-data-grid-header-cell-max-lines: 2;--re-data-grid-footer-separator-color: #ccc;--re-data-grid-footer-separator: 1px solid var(--re-data-grid-footer-separator-color);--re-data-grid-footer-surface: #fff;--re-data-grid-row-separator-color: #bbb;--re-data-grid-row-separator: 1px solid var(--re-data-grid-row-separator-color);--re-data-grid-row-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-surface: var(--re-data-grid-cell-surface);--re-data-grid-row-hover-color: var(--re-data-grid-cell-color);--re-data-grid-row-hover-rounded: 0px;--re-data-grid-column-separator-color: transparent;--re-data-grid-column-separator: 1px solid var(--re-data-grid-column-separator-color);--re-data-grid-column-odd-surface: var(--re-data-grid-cell-surface);--re-data-grid-cell-paddings: .4rem .625rem;--re-data-grid-cell-font-weight: 400;--re-data-grid-cell-font-size: .75rem;--re-data-grid-cell-color: #000;--re-data-grid-cell-surface: #fff;--re-data-grid-cell-line-height: 1.2;--re-data-grid-cell-max-lines: 2;--re-data-grid-sticky-header-cell-surface: #fff;--re-data-grid-sticky-cell-surface: #fdfdfd;--re-data-grid-sticky-cell-row-odd-surface: #fdfdfd;--re-data-grid-sticky-cell-left-shadow: 2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-sticky-cell-right-shadow: -2px 0 2px rgba(0, 0, 0, .03);--re-data-grid-pinned-surface: #fcfcfc;--re-data-grid-pinned-separator-color: #eee;--re-data-grid-pinned-separator: 1px solid var(--re-data-grid-pinned-separator-color);--re-data-grid-expander-color: var(--primary-color, currentColor);--re-data-grid-expanded-color: var(--re-data-grid-cell-color, #000);--re-data-grid-expanded-surface: var(--re-data-grid-cell-surface, #fff);--re-data-grid-focus-ring-color: color-mix(in srgb, var(--primary-color, #2a90f4) 55%, transparent);--re-data-grid-focus-ring-width: 2px;--re-data-grid-focus-ring-offset: -2px;display:block;min-height:0;min-width:0}:host,:host *,:host *:before,:host *:after{box-sizing:border-box;outline:none}:host button{outline:none}.re-dg-root{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;min-height:var(--re-data-grid-min-height);border-radius:var(--re-data-grid-rounded);border:var(--re-data-grid-separator)}.re-dg-root.fill{display:block}.re-dg-root.re-dg-loading{pointer-events:none;-webkit-user-select:none;user-select:none;cursor:wait}.re-dg-root.re-dg-loading .re-dg-body{overflow:hidden}.re-dg-root.re-dg-loading .re-dg-scrollbar{display:none!important}.re-dg-root.re-dg-loading .re-dg-loader{pointer-events:all}.re-dg-root.lock-vertical-scroll .re-dg-body{overflow-x:auto;overflow-y:hidden}.re-dg-root.lock-vertical-scroll .re-dg-scrollbar{display:none!important}.re-dg-root.resizing-columns{-webkit-user-select:none;user-select:none;cursor:col-resize}.re-dg-body{position:relative;flex:1 1 auto;min-height:0;min-width:0;height:inherit;border:var(--re-data-grid-separator);border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-surface);overflow:auto;scrollbar-width:auto;-ms-overflow-style:auto}.re-dg-body::-webkit-scrollbar{width:var(--re-data-grid-scrollbar-size);height:var(--re-data-grid-scrollbar-size)}.re-dg-body::-webkit-scrollbar:vertical{width:0}.re-dg-body::-webkit-scrollbar-track{border-radius:var(--re-data-grid-scrollbar-track-rounded);background:var(--re-data-grid-scrollbar-track-surface)}.re-dg-body::-webkit-scrollbar-thumb{border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);transition:opacity .3s ease}.re-dg-body::-webkit-scrollbar-thumb:hover{background:var(--re-data-grid-scrollbar-thumb-active-color)}.re-dg-header,.re-dg-footer{position:sticky;z-index:3}.re-dg-header{top:0;background-color:var(--re-data-grid-header-surface)}.re-dg-header-row{min-height:var(--re-data-grid-header-row-height)}.re-dg-header-group-row{min-height:var(--re-data-grid-header-group-row-height)}.re-dg-header-rows{display:flex;flex-direction:column;padding-bottom:var(--re-data-grid-header-body-gap)}.re-dg-footer{bottom:0;border-radius:0 0 var(--re-data-grid-rounded) var(--re-data-grid-rounded);background-color:var(--re-data-grid-footer-surface)}.re-dg-row{position:relative;display:flex}.re-dg-data-row{position:absolute;left:0;top:0;min-width:100%;cursor:default;will-change:transform}.re-dg-sticky-row{z-index:2;top:0}.re-dg-cell,.re-dg-header-cell{display:flex;flex:0 0 auto;align-items:center;padding:var(--re-data-grid-cell-paddings);border-right:var(--re-data-grid-column-separator);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.re-dg-cell:focus-visible,.re-dg-header-cell:focus-visible,.re-dg-header-cell button:focus-visible,.re-dg-row[tabindex=\"0\"]:focus-visible{outline:var(--re-data-grid-focus-ring-width) solid var(--re-data-grid-focus-ring-color);outline-offset:var(--re-data-grid-focus-ring-offset);z-index:4}.re-dg-cell{width:100%;border-bottom:var(--re-data-grid-row-separator);font-weight:var(--re-data-grid-cell-font-weight);font-size:var(--re-data-grid-cell-font-size);color:var(--re-data-grid-cell-color);background-color:var(--re-data-grid-cell-surface)}.re-dg-row:nth-child(odd) .re-dg-cell{background-color:var(--re-data-grid-row-odd-surface)}.re-dg-row.re-dg-row-disabled .re-dg-cell{opacity:.6;cursor:not-allowed}.re-dg-row:nth-child(odd) .re-dg-cell.sticky-left,.re-dg-row:nth-child(odd) .re-dg-cell.sticky-right{background-color:var(--re-data-grid-sticky-cell-row-odd-surface)}.re-dg-cell:nth-child(odd){background-color:var(--re-data-grid-column-odd-surface)}.re-dg-bottom>.re-dg-cell{border-top:var(--re-data-grid-footer-separator)}.re-dg-header-cell{position:relative;align-items:center;gap:.75rem;border-bottom:var(--re-data-grid-header-row-separator);font-weight:var(--re-data-grid-header-cell-font-weight);font-size:var(--re-data-grid-header-cell-font-size);color:var(--re-data-grid-header-cell-color);background:var(--re-data-grid-header-cell-surface);-webkit-user-select:none;user-select:none;transition:color .3s ease-in-out}.re-dg-column-resize-handle{position:absolute;top:0;right:-4px;width:8px;height:100%;cursor:col-resize;z-index:5}.re-dg-header-cell.re-dg-header-group-cell{border-bottom:var(--re-data-grid-header-group-row-separator);font-weight:var(--re-data-grid-header-group-cell-font-weight);font-size:var(--re-data-grid-header-group-cell-font-size);color:var(--re-data-grid-header-group-cell-color);background:var(--re-data-grid-header-group-cell-surface)}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:first-child{border-radius:var(--re-data-grid-header-rounded) 0 0 0}.re-dg-header-rows>.re-dg-row:first-child .re-dg-header-cell:last-child{border-radius:0 var(--re-data-grid-header-rounded) 0 0}.re-dg-data-row:last-child .re-dg-cell:first-child{border-radius:0 0 0 var(--re-data-grid-rounded)}.re-dg-data-row:last-child .re-dg-cell:last-child{border-radius:0 0 var(--re-data-grid-rounded) 0}.re-dg-header-cell .re-dg-header-text{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:var(--re-data-grid-header-cell-line-height);-webkit-box-orient:vertical;-webkit-line-clamp:var(--re-data-grid-header-cell-max-lines)}.re-dg-row.re-dg-pinned>.re-dg-cell{border-bottom:var(--re-data-grid-pinned-separator);background-color:var(--re-data-grid-pinned-surface)}.re-dg-row .re-dg-header-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-left{box-shadow:var(--re-data-grid-sticky-cell-left-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row .re-dg-header-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-header-cell-surface)}.re-dg-row .re-dg-cell.sticky-right{box-shadow:var(--re-data-grid-sticky-cell-right-shadow);background-color:var(--re-data-grid-sticky-cell-surface)}.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-left,.re-dg-row.re-dg-pinned>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-pinned-surface)}.re-dg-row:hover>.re-dg-cell,.re-dg-row:hover>.re-dg-cell.sticky-left,.re-dg-row:hover>.re-dg-cell.sticky-right{background-color:var(--re-data-grid-row-hover-surface)!important;color:var(--re-data-grid-row-hover-color)!important}.re-dg-row:hover>.re-dg-cell:first-child{border-radius:var(--re-data-grid-row-hover-rounded) 0 0 var(--re-data-grid-row-hover-rounded)}.re-dg-row:hover>.re-dg-cell:last-child{border-radius:0 var(--re-data-grid-row-hover-rounded) var(--re-data-grid-row-hover-rounded) 0}.sticky-left,.sticky-right{position:sticky;z-index:2}.sortable{cursor:pointer}.active-sort{color:var(--re-data-grid-active)}.re-dg-sort-ind{margin-left:6px}.re-dg-icon-placeholder{display:inline-block;width:1rem;height:1rem}.re-dg-cell-deferred{display:block;width:100%;height:100%}.re-dg-deferred-placeholder{background:transparent}.re-dg-data-row .re-dg-cell.expanded{color:var(--re-data-grid-expanded-color);background:var(--re-data-grid-expanded-surface)}.re-dg-empty{position:absolute;inset:0;display:grid;place-items:center;height:inherit;width:100%;border-radius:var(--re-data-grid-rounded);color:var(--re-data-grid-empty-color);background:var(--re-data-grid-empty-surface)}.re-dg-empty-text{width:100%;text-align:center}.re-dg-loader{position:absolute;inset:0;display:grid;place-items:center;height:inherit;border-radius:var(--re-data-grid-rounded);background-color:var(--re-data-grid-loading-surface);color:var(--re-data-grid-loading-color);z-index:5}.re-dg-tooltip{position:fixed;left:0;top:0;max-width:min(28rem,70vw);padding:var(--re-data-grid-tooltip-padding);border-radius:var(--re-data-grid-tooltip-radius);background:var(--re-data-grid-tooltip-surface);color:var(--re-data-grid-tooltip-color);box-shadow:var(--re-data-grid-tooltip-shadow);font-size:.75rem;line-height:1.2;z-index:var(--re-data-grid-tooltip-z);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .12s ease,transform .12s ease}.re-dg-tooltip.visible{opacity:1;transform:translateY(0)}.re-dg-loader-spinner{width:var(--re-data-grid-spinner-size);height:var(--re-data-grid-spinner-size);border-radius:50%;border:var(--re-data-grid-spinner-width) solid var(--re-data-grid-spinner-track-color);border-top-color:var(--re-data-grid-loading-color);animation:re-dg-spinner .8s linear infinite}.re-dg-skeleton-row{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:var(--re-data-grid-cell-surface);pointer-events:none}.re-dg-gap-loader{display:flex;align-items:center;padding:var(--re-data-grid-cell-paddings);border-bottom:var(--re-data-grid-row-separator);background-color:color-mix(in srgb,var(--re-data-grid-cell-surface) 88%,var(--re-data-grid-skeleton-line));pointer-events:none;opacity:.9}.re-dg-skeleton-row-line{display:block;width:var(--re-data-grid-skeleton-width);height:var(--re-data-grid-skeleton-height);border-radius:var(--re-data-grid-skeleton-rounded);background:linear-gradient(90deg,var(--re-data-grid-skeleton-line) 0%,var(--re-data-grid-skeleton-shine) 50%,var(--re-data-grid-skeleton-line) 100%);background-size:200% 100%;animation:re-dg-skeleton 1.2s ease-in-out infinite}@keyframes re-dg-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes re-dg-spinner{to{transform:rotate(360deg)}}.re-dg-scrollbar{position:absolute;right:0;top:0;bottom:0;opacity:0;transition:opacity .15s ease-in-out;pointer-events:none;z-index:4}.re-dg-scrollbar.visible{opacity:1}.re-dg-scrollbar-thumb{position:absolute;right:var(--re-data-grid-scrollbar-offset);width:var(--re-data-grid-scrollbar-thumb-size);border-radius:var(--re-data-grid-scrollbar-thumb-rounded);background:var(--re-data-grid-scrollbar-thumb-color);pointer-events:auto;-webkit-user-select:none;user-select:none;touch-action:none}.re-dg-spacer{width:1px}.re-dg-top{top:0}.re-dg-bottom{bottom:0}\n"] }]
4647
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], pinnedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedRows", required: false }] }], isRowSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowSticky", required: false }] }], isRowDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowDisabled", required: false }] }], getRowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowClass", required: false }] }], getRowTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowTemplate", required: false }] }], hasIndexColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasIndexColumn", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], selectedKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedKeys", required: false }] }], selectionPolicy: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionPolicy", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], virtualBuffer: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualBuffer", required: false }] }], lockVerticalScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockVerticalScroll", required: false }] }], headerGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerGroups", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMode", required: false }] }], deferContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferContent", required: false }] }], deferHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferHeader", required: false }] }], deferPinned: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferPinned", required: false }] }], deferCells: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferCells", required: false }] }], deferIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferIcons", required: false }] }], deferTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "deferTooltip", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], pageStartFromZero: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageStartFromZero", required: false }] }], sortMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortMode", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], sourceError: [{ type: i0.Output, args: ["sourceError"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], multiSortChange: [{ type: i0.Output, args: ["multiSortChange"] }], selectChange: [{ type: i0.Output, args: ["selectChange"] }], selectedKeysChange: [{ type: i0.Output, args: ["selectedKeysChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowContext: [{ type: i0.Output, args: ["rowContext"] }], rowDoubleClick: [{ type: i0.Output, args: ["rowDoubleClick"] }], cellClick: [{ type: i0.Output, args: ["cellClick"] }], cellContext: [{ type: i0.Output, args: ["cellContext"] }], cellDoubleClick: [{ type: i0.Output, args: ["cellDoubleClick"] }], columnResizeEnd: [{ type: i0.Output, args: ["columnResizeEnd"] }], rootEl: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }], scrollEl: [{ type: i0.ViewChild, args: ['scroll', { isSignal: true }] }], headerEl: [{ type: i0.ViewChild, args: ['header', { isSignal: true }] }], cellTypedSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridTypeCellTemplateDirective), { isSignal: true }] }], cellDataSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridCellTemplateDirective), { isSignal: true }] }], declarativeColumnRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridDeclarativeColumn), { isSignal: true }] }], headerSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridHeaderTemplateDirective), { isSignal: true }] }], emptySlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridCellEmptyDirective), { isSignal: true }] }], loadingSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridCellLoadingDirective), { isSignal: true }] }], sortIcSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridSortIconDirective), { isSignal: true }] }], expanderIcSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridExpanderIconDirective), { isSignal: true }] }], stickyRowSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridStickyRowDirective), { isSignal: true }] }], rowSlotRefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DataGridRowDirective), { isSignal: true }] }], tooltipEl: [{ type: i0.ViewChild, args: ['tooltip', { isSignal: true }] }] } });
4648
+
4649
+ /** Marks a backend-only sort field explicitly at the call site. */
4650
+ const gridBackendSortField = (field) => field;
4243
4651
 
4244
4652
  /**
4245
4653
  * Generated bundle index. Do not edit.
4246
4654
  */
4247
4655
 
4248
- export { DataGridTypeCellTemplateDirective as D, clampThumbTop as a, DataGridCellTemplateDirective as b, computeScrollbarState as c, DataGridHeaderTemplateDirective as d, DataGridRowDirective as e, DataGridDeclarativeColumn as f, DataGridDeclarativeHeaderDirective as g, DataGridDeclarativeCellDirective as h, DataGridCellEmptyDirective as i, DataGridCellLoadingDirective as j, DataGridStickyRowDirective as k, DataGridSortIconDirective as l, mapThumbTopToScrollTop as m, DataGridExpanderIconDirective as n, DATA_GRID_CONFIG as o, DATA_GRID_HEADER_TEXT_RESOLVER as p, DATA_GRID_TYPE_RENDERERS as q, DATA_GRID_TYPE_TRANSFORMERS as r, DEFAULT_DATA_GRID_DEFAULTS as s, provideDataGridDefaults as t, provideDataGridHeaderTextResolver as u, provideDataGridHeaderTextResolverWithParent as v, provideDataGridTypeRenderers as w, provideDataGridTypeTransformers as x, DataGrid as y };
4249
- //# sourceMappingURL=reforgium-data-grid-reforgium-data-grid-DUpCJ9P0.mjs.map
4656
+ export { DataGridTypeCellTemplateDirective as D, clampThumbTop as a, DataGridCellTemplateDirective as b, computeScrollbarState as c, DataGridHeaderTemplateDirective as d, DataGridRowDirective as e, DataGridDeclarativeColumn as f, DataGridDeclarativeHeaderDirective as g, DataGridDeclarativeCellDirective as h, DataGridCellEmptyDirective as i, DataGridCellLoadingDirective as j, DataGridStickyRowDirective as k, DataGridSortIconDirective as l, mapThumbTopToScrollTop as m, DataGridExpanderIconDirective as n, DATA_GRID_CONFIG as o, DATA_GRID_HEADER_TEXT_RESOLVER as p, DATA_GRID_TYPE_RENDERERS as q, DATA_GRID_TYPE_TRANSFORMERS as r, DEFAULT_DATA_GRID_DEFAULTS as s, provideDataGridDefaults as t, provideDataGridHeaderTextResolver as u, provideDataGridHeaderTextResolverWithParent as v, provideDataGridTypeRenderers as w, provideDataGridTypeTransformers as x, DataGrid as y, gridBackendSortField as z };
4657
+ //# sourceMappingURL=reforgium-data-grid-reforgium-data-grid-YzRaXPVK.mjs.map