@ascentgl/ads-ui 21.78.0 → 21.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7265,6 +7265,7 @@ class AdsColumnSortFilterMenuComponent {
7265
7265
  allOptionKeys.every((key) => this.selectedFilterValues.includes(key));
7266
7266
  // Get the value formatter if provided
7267
7267
  const formatter = this.config.filterValueFormatter;
7268
+ const showDateOnly = this.config.showDateOnly ?? false;
7268
7269
  const options = this.config.filterOptions.map((rawValue) => {
7269
7270
  // Serialize raw value to stable string key for selection/persistence
7270
7271
  const key = this.serializeOptionValue(rawValue);
@@ -7279,8 +7280,12 @@ class AdsColumnSortFilterMenuComponent {
7279
7280
  }
7280
7281
  });
7281
7282
  this.optionSubscriptions.push(subscription);
7282
- // Use formatter with RAW VALUE if provided, otherwise convert to string
7283
- const label = formatter ? formatter(rawValue) : String(rawValue ?? '');
7283
+ // Build the label: use formatter if provided, otherwise convert to string
7284
+ let label = formatter ? formatter(rawValue) : String(rawValue ?? '');
7285
+ // When showDateOnly is enabled, trim date-time labels to date-only
7286
+ if (showDateOnly && label) {
7287
+ label = this.trimToDateOnly(label);
7288
+ }
7284
7289
  return {
7285
7290
  value: key,
7286
7291
  rawValue,
@@ -7309,6 +7314,26 @@ class AdsColumnSortFilterMenuComponent {
7309
7314
  return String(value);
7310
7315
  }
7311
7316
  }
7317
+ /**
7318
+ * @ignore - Trim a date-time string to date-only.
7319
+ * Handles common formatted patterns like "01/09/26, 02:00 AM" or "01/09/2026 14:30".
7320
+ * Strips everything after the date portion (comma+time, space+time).
7321
+ */
7322
+ trimToDateOnly(value) {
7323
+ // Already date-only (e.g., "01/09/2026") — no comma, no time pattern
7324
+ // Match patterns: "MM/DD/YY, HH:MM AM/PM" or "MM/DD/YYYY HH:MM" etc.
7325
+ // Strip from the comma or from the space before time digits
7326
+ const commaIdx = value.indexOf(',');
7327
+ if (commaIdx > 0) {
7328
+ return value.substring(0, commaIdx).trim();
7329
+ }
7330
+ // Match "date space time" pattern (e.g., "01/09/2026 14:30")
7331
+ const match = value.match(/^(\d{1,2}\/\d{1,2}\/\d{2,4})\s+\d/);
7332
+ if (match) {
7333
+ return match[1];
7334
+ }
7335
+ return value;
7336
+ }
7312
7337
  /** @ignore */
7313
7338
  setupSearchSubscription() {
7314
7339
  this.searchControl.valueChanges.pipe(takeUntil$1(this.destroy$)).subscribe((value) => {
@@ -8095,10 +8120,68 @@ class AdsTableComponent {
8095
8120
  }
8096
8121
  }
8097
8122
  // ============ Custom Sort/Filter Menu Methods ============
8098
- /** @ignore - Get the filterValueFormatter for a given column field */
8123
+ /** @ignore - Get the effective filter formatter for a given column field.
8124
+ * When showDateOnly is true, wraps the formatter (or uses a default date formatter)
8125
+ * that trims the output to date-only for dedup and comparison purposes.
8126
+ */
8099
8127
  getFilterValueFormatterForField(field) {
8100
8128
  const config = this.columnSortFilterConfigs.find(c => c.field === field);
8101
- return config?.filterValueFormatter;
8129
+ if (!config)
8130
+ return undefined;
8131
+ const baseFormatter = config.filterValueFormatter;
8132
+ const showDateOnly = config.showDateOnly ?? false;
8133
+ if (!baseFormatter && !showDateOnly) {
8134
+ return undefined;
8135
+ }
8136
+ if (showDateOnly) {
8137
+ // When showDateOnly is true, use the base formatter (if any) then trim to date-only
8138
+ return (value) => {
8139
+ const formatted = baseFormatter ? baseFormatter(value) : this.formatDateDefault(value);
8140
+ return this.trimToDateOnly(formatted);
8141
+ };
8142
+ }
8143
+ return baseFormatter;
8144
+ }
8145
+ /**
8146
+ * @ignore - Default date formatter for showDateOnly when no filterValueFormatter is provided.
8147
+ * Formats an ISO date-time string to the locale date string.
8148
+ */
8149
+ formatDateDefault(value) {
8150
+ if (value === null || value === undefined)
8151
+ return '';
8152
+ const str = String(value);
8153
+ try {
8154
+ const date = new Date(str);
8155
+ if (isNaN(date.getTime()))
8156
+ return str;
8157
+ return date.toLocaleDateString('en-US', {
8158
+ month: '2-digit',
8159
+ day: '2-digit',
8160
+ year: 'numeric',
8161
+ });
8162
+ }
8163
+ catch {
8164
+ return str;
8165
+ }
8166
+ }
8167
+ /**
8168
+ * @ignore - Trim a date-time string to date-only.
8169
+ * Strips time portion from common formatted date-time patterns.
8170
+ */
8171
+ trimToDateOnly(value) {
8172
+ if (!value)
8173
+ return value;
8174
+ // "MM/DD/YY, HH:MM AM/PM" — strip from comma
8175
+ const commaIdx = value.indexOf(',');
8176
+ if (commaIdx > 0) {
8177
+ return value.substring(0, commaIdx).trim();
8178
+ }
8179
+ // "MM/DD/YYYY HH:MM" — strip from space before time digits
8180
+ const match = value.match(/^(\d{1,2}\/\d{1,2}\/\d{2,4})\s+\d/);
8181
+ if (match) {
8182
+ return match[1];
8183
+ }
8184
+ return value;
8102
8185
  }
8103
8186
  /**
8104
8187
  * @ignore - Serialize a cell value for filter key purposes.
@@ -8116,19 +8199,13 @@ class AdsTableComponent {
8116
8199
  if (!this.rowData || this.rowData.length === 0) {
8117
8200
  return [];
8118
8201
  }
8119
- const formatter = this.getFilterValueFormatterForField(field);
8120
- // Don't cache results when a filterValueFormatter is configured,
8121
- // because the formatter output may change over time (e.g., timezone service
8122
- // becoming ready, user changing timezone). Caching could cause stale values
8123
- // that mismatch with doesExternalFilterPass comparisons.
8124
- if (!formatter) {
8125
- // Check cache first (only for fields without formatter)
8126
- const cacheKey = `${field}_v${this.dataVersion}`;
8127
- const cached = this.uniqueColumnValuesCache.get(cacheKey);
8128
- if (cached) {
8129
- return cached;
8130
- }
8202
+ // Check cache first
8203
+ const cacheKey = `${field}_v${this.dataVersion}`;
8204
+ const cached = this.uniqueColumnValuesCache.get(cacheKey);
8205
+ if (cached) {
8206
+ return cached;
8131
8207
  }
8208
+ const formatter = this.getFilterValueFormatterForField(field);
8132
8209
  // Use a Map to dedupe by serialized key while preserving raw values
8133
8210
  const byKey = new Map();
8134
8211
  this.rowData.forEach(row => {
@@ -8146,11 +8223,8 @@ class AdsTableComponent {
8146
8223
  const result = Array.from(byKey.entries())
8147
8224
  .sort(([a], [b]) => a.localeCompare(b))
8148
8225
  .map(([, v]) => v);
8149
- // Cache the result only for fields without formatter
8150
- if (!formatter) {
8151
- const cacheKey = `${field}_v${this.dataVersion}`;
8152
- this.uniqueColumnValuesCache.set(cacheKey, result);
8153
- }
8226
+ // Cache the result
8227
+ this.uniqueColumnValuesCache.set(cacheKey, result);
8154
8228
  return result;
8155
8229
  }
8156
8230
  /**
@@ -8163,27 +8237,21 @@ class AdsTableComponent {
8163
8237
  if (!this.rowData || this.rowData.length === 0) {
8164
8238
  return [];
8165
8239
  }
8166
- const formatter = this.getFilterValueFormatterForField(field);
8167
- // Don't cache results when a filterValueFormatter is configured (same reason as getUniqueColumnValues)
8168
- if (!formatter) {
8169
- // Check cache first (only for fields without formatter)
8170
- const cacheKey = `${field}_v${this.filterCacheVersion}`;
8171
- const cached = this.filteredColumnValuesCache.get(cacheKey);
8172
- if (cached) {
8173
- return cached;
8174
- }
8240
+ // Check cache first
8241
+ const cacheKey = `${field}_v${this.filterCacheVersion}`;
8242
+ const cached = this.filteredColumnValuesCache.get(cacheKey);
8243
+ if (cached) {
8244
+ return cached;
8175
8245
  }
8176
8246
  // Check if any filter is active (excluding the current field)
8177
8247
  const hasOtherActiveFilters = this.hasActiveFiltersExcluding(field);
8178
8248
  // If no other filters are active, return all unique values
8179
8249
  if (!hasOtherActiveFilters) {
8180
8250
  const values = this.getUniqueColumnValues(field);
8181
- if (!formatter) {
8182
- const cacheKey = `${field}_v${this.filterCacheVersion}`;
8183
- this.filteredColumnValuesCache.set(cacheKey, values);
8184
- }
8251
+ this.filteredColumnValuesCache.set(cacheKey, values);
8185
8252
  return values;
8186
8253
  }
8254
+ const formatter = this.getFilterValueFormatterForField(field);
8187
8255
  // Use a Map to dedupe by serialized key while preserving raw values
8188
8256
  const byKey = new Map();
8189
8257
  // Iterate through all rows and check if they pass filters from OTHER columns
@@ -8209,11 +8277,8 @@ class AdsTableComponent {
8209
8277
  .sort(([a], [b]) => a.localeCompare(b))
8210
8278
  .map(([, v]) => v);
8211
8279
  }
8212
- // Cache the result only for fields without formatter
8213
- if (!formatter) {
8214
- const cacheKey = `${field}_v${this.filterCacheVersion}`;
8215
- this.filteredColumnValuesCache.set(cacheKey, result);
8216
- }
8280
+ // Cache the result
8281
+ this.filteredColumnValuesCache.set(cacheKey, result);
8217
8282
  return result;
8218
8283
  }
8219
8284
  /** @ignore - Invalidate the filtered column values cache */