@ascentgl/ads-ui 21.76.1 → 21.78.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.
@@ -7720,10 +7720,9 @@ class AdsTableComponent {
7720
7720
  // For columns without explicit config (like supplier, destination),
7721
7721
  // always apply the filter based on selectedValues
7722
7722
  const cellValue = node.data[field];
7723
- // For objects, use JSON.stringify to match the format used in filterOptions
7724
- const cellValueStr = cellValue != null
7725
- ? (typeof cellValue === 'object' ? JSON.stringify(cellValue) : String(cellValue))
7726
- : '';
7723
+ // Use formatter if available to produce a consistent key for comparison
7724
+ const formatter = this.getFilterValueFormatterForField(field);
7725
+ const cellValueStr = this.serializeCellValueForFilter(cellValue, formatter);
7727
7726
  if (!selectedValues.includes(cellValueStr)) {
7728
7727
  return false;
7729
7728
  }
@@ -8096,25 +8095,50 @@ class AdsTableComponent {
8096
8095
  }
8097
8096
  }
8098
8097
  // ============ Custom Sort/Filter Menu Methods ============
8098
+ /** @ignore - Get the filterValueFormatter for a given column field */
8099
+ getFilterValueFormatterForField(field) {
8100
+ const config = this.columnSortFilterConfigs.find(c => c.field === field);
8101
+ return config?.filterValueFormatter;
8102
+ }
8103
+ /**
8104
+ * @ignore - Serialize a cell value for filter key purposes.
8105
+ * When a filterValueFormatter exists, uses the formatted value as the key
8106
+ * so that values with the same display (e.g. same date, different time) are deduplicated.
8107
+ */
8108
+ serializeCellValueForFilter(value, formatter) {
8109
+ if (formatter) {
8110
+ return formatter(value);
8111
+ }
8112
+ return this.serializeCellValue(value);
8113
+ }
8099
8114
  /** @ignore - Extract unique RAW values from a column in rowData (with caching) */
8100
8115
  getUniqueColumnValues(field) {
8101
8116
  if (!this.rowData || this.rowData.length === 0) {
8102
8117
  return [];
8103
8118
  }
8104
- // Check cache first
8105
- const cacheKey = `${field}_v${this.dataVersion}`;
8106
- const cached = this.uniqueColumnValuesCache.get(cacheKey);
8107
- if (cached) {
8108
- return cached;
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
+ }
8109
8131
  }
8110
8132
  // Use a Map to dedupe by serialized key while preserving raw values
8111
8133
  const byKey = new Map();
8112
8134
  this.rowData.forEach(row => {
8113
8135
  const value = row[field];
8114
8136
  if (value !== null && value !== undefined) {
8115
- const key = this.serializeCellValue(value);
8137
+ const key = this.serializeCellValueForFilter(value, formatter);
8116
8138
  if (!byKey.has(key)) {
8117
- byKey.set(key, value);
8139
+ // When a formatter exists, store the formatted string as the value
8140
+ // so downstream consumers (menu, filter matching) use a consistent key
8141
+ byKey.set(key, formatter ? key : value);
8118
8142
  }
8119
8143
  }
8120
8144
  });
@@ -8122,8 +8146,11 @@ class AdsTableComponent {
8122
8146
  const result = Array.from(byKey.entries())
8123
8147
  .sort(([a], [b]) => a.localeCompare(b))
8124
8148
  .map(([, v]) => v);
8125
- // Cache the result
8126
- this.uniqueColumnValuesCache.set(cacheKey, result);
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
+ }
8127
8154
  return result;
8128
8155
  }
8129
8156
  /**
@@ -8136,18 +8163,25 @@ class AdsTableComponent {
8136
8163
  if (!this.rowData || this.rowData.length === 0) {
8137
8164
  return [];
8138
8165
  }
8139
- // Check cache first
8140
- const cacheKey = `${field}_v${this.filterCacheVersion}`;
8141
- const cached = this.filteredColumnValuesCache.get(cacheKey);
8142
- if (cached) {
8143
- return cached;
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
+ }
8144
8175
  }
8145
8176
  // Check if any filter is active (excluding the current field)
8146
8177
  const hasOtherActiveFilters = this.hasActiveFiltersExcluding(field);
8147
8178
  // If no other filters are active, return all unique values
8148
8179
  if (!hasOtherActiveFilters) {
8149
8180
  const values = this.getUniqueColumnValues(field);
8150
- this.filteredColumnValuesCache.set(cacheKey, values);
8181
+ if (!formatter) {
8182
+ const cacheKey = `${field}_v${this.filterCacheVersion}`;
8183
+ this.filteredColumnValuesCache.set(cacheKey, values);
8184
+ }
8151
8185
  return values;
8152
8186
  }
8153
8187
  // Use a Map to dedupe by serialized key while preserving raw values
@@ -8157,9 +8191,9 @@ class AdsTableComponent {
8157
8191
  if (this.doesRowPassFiltersExcluding(row, field)) {
8158
8192
  const value = row[field];
8159
8193
  if (value !== null && value !== undefined) {
8160
- const key = this.serializeCellValue(value);
8194
+ const key = this.serializeCellValueForFilter(value, formatter);
8161
8195
  if (!byKey.has(key)) {
8162
- byKey.set(key, value);
8196
+ byKey.set(key, formatter ? key : value);
8163
8197
  }
8164
8198
  }
8165
8199
  }
@@ -8175,8 +8209,11 @@ class AdsTableComponent {
8175
8209
  .sort(([a], [b]) => a.localeCompare(b))
8176
8210
  .map(([, v]) => v);
8177
8211
  }
8178
- // Cache the result
8179
- this.filteredColumnValuesCache.set(cacheKey, result);
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
+ }
8180
8217
  return result;
8181
8218
  }
8182
8219
  /** @ignore - Invalidate the filtered column values cache */
@@ -8223,10 +8260,9 @@ class AdsTableComponent {
8223
8260
  return false;
8224
8261
  }
8225
8262
  const cellValue = row[field];
8226
- // For objects, use JSON.stringify to match the format used in filterOptions
8227
- const cellValueStr = cellValue != null
8228
- ? (typeof cellValue === 'object' ? JSON.stringify(cellValue) : String(cellValue))
8229
- : '';
8263
+ // Use formatter if available to produce a consistent key for comparison
8264
+ const formatter = this.getFilterValueFormatterForField(field);
8265
+ const cellValueStr = this.serializeCellValueForFilter(cellValue, formatter);
8230
8266
  if (!selectedValues.includes(cellValueStr)) {
8231
8267
  return false;
8232
8268
  }