@revolist/revogrid 4.25.1 → 4.26.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.
@@ -1225,8 +1225,84 @@ const lsEq = function (value, extra) {
1225
1225
  };
1226
1226
  lsEq.extra = 'input';
1227
1227
 
1228
- const set = (value) => !(value === '' || value === null || value === void 0);
1229
- const notSet = (value) => !set(value);
1228
+ const DEFAULT_BLANK_SEMANTICS = Object.freeze({
1229
+ null: true,
1230
+ undefined: true,
1231
+ emptyString: true,
1232
+ whitespaceOnlyString: false,
1233
+ emptyArray: false,
1234
+ missingProperty: true,
1235
+ });
1236
+ const BOOLEAN_FIELDS = [
1237
+ 'null',
1238
+ 'undefined',
1239
+ 'emptyString',
1240
+ 'whitespaceOnlyString',
1241
+ 'emptyArray',
1242
+ 'missingProperty',
1243
+ ];
1244
+ /** Merge a grid policy and a partial column policy over Core defaults. */
1245
+ function resolveBlankSemantics(gridPolicy, columnPolicy) {
1246
+ const resolved = Object.assign({}, DEFAULT_BLANK_SEMANTICS);
1247
+ for (const policy of [gridPolicy, columnPolicy]) {
1248
+ if (!policy) {
1249
+ continue;
1250
+ }
1251
+ for (const field of BOOLEAN_FIELDS) {
1252
+ if (policy[field] !== undefined) {
1253
+ resolved[field] = policy[field];
1254
+ }
1255
+ }
1256
+ if (policy.isBlank !== undefined) {
1257
+ resolved.isBlank = policy.isBlank;
1258
+ }
1259
+ }
1260
+ return resolved;
1261
+ }
1262
+ /** Evaluate blankness from the unparsed source value and property presence. */
1263
+ function isBlankValue(value, context) {
1264
+ const policy = context.blankSemantics;
1265
+ let fallbackResult;
1266
+ if (!context.hasOwnProperty) {
1267
+ fallbackResult = policy.missingProperty === true;
1268
+ }
1269
+ else if (value === null) {
1270
+ fallbackResult = policy.null === true;
1271
+ }
1272
+ else if (value === undefined) {
1273
+ fallbackResult = policy.undefined === true;
1274
+ }
1275
+ else if (value === '') {
1276
+ fallbackResult = policy.emptyString === true;
1277
+ }
1278
+ else if (typeof value === 'string' &&
1279
+ value.length > 0 &&
1280
+ value.trim() === '') {
1281
+ fallbackResult = policy.whitespaceOnlyString === true;
1282
+ }
1283
+ else if (Array.isArray(value) && value.length === 0) {
1284
+ fallbackResult = policy.emptyArray === true;
1285
+ }
1286
+ else {
1287
+ fallbackResult = false;
1288
+ }
1289
+ return policy.isBlank
1290
+ ? policy.isBlank(value, context, fallbackResult)
1291
+ : fallbackResult;
1292
+ }
1293
+
1294
+ function blankContext(value, context) {
1295
+ return context !== null && context !== void 0 ? context : {
1296
+ model: {},
1297
+ property: '',
1298
+ sourceValue: value,
1299
+ parsedValue: value,
1300
+ hasOwnProperty: true,
1301
+ blankSemantics: DEFAULT_BLANK_SEMANTICS,
1302
+ };
1303
+ }
1304
+ const notSet = (value, _extra, context) => isBlankValue(context ? context.sourceValue : value, blankContext(value, context));
1305
+ const set = (value, _extra, context) => !notSet(value, _extra, context);
1230
1306
 
1231
1307
  const beginsWith = (value, extra) => {
1232
1308
  if (!value) {
@@ -1286,11 +1362,13 @@ const filterCoreFunctionsIndexedByType = {
1286
1362
  const filterTypes = {
1287
1363
  string: ['notEmpty', 'empty', 'eq', 'notEq', 'begins', 'contains', 'notContains'],
1288
1364
  number: ['notEmpty', 'empty', 'eqN', 'neqN', 'gt', 'gte', 'lt', 'lte'],
1365
+ boolean: ['notEmpty', 'empty'],
1366
+ array: ['notEmpty', 'empty'],
1289
1367
  };
1290
1368
  const filterNames = {
1291
1369
  none: 'None',
1292
- empty: 'Not set',
1293
- notEmpty: 'Set',
1370
+ empty: 'Is blank',
1371
+ notEmpty: 'Is not blank',
1294
1372
  eq: 'Equal',
1295
1373
  notEq: 'Not equal',
1296
1374
  begins: 'Begins with',
@@ -1413,6 +1491,7 @@ class FilterPlugin extends BasePlugin {
1413
1491
  }
1414
1492
  initConfig(config) {
1415
1493
  var _a;
1494
+ this.config = config;
1416
1495
  this.allowDuplicateOperators = (_a = config.allowDuplicateOperators) !== null && _a !== void 0 ? _a : true;
1417
1496
  if (this.pop) {
1418
1497
  this.pop.allowDuplicateOperators = this.allowDuplicateOperators;
@@ -1629,38 +1708,56 @@ class FilterPlugin extends BasePlugin {
1629
1708
  * Get trimmed rows based on filter
1630
1709
  */
1631
1710
  getRowFilter(rows, filterItems, columnByProp) {
1711
+ var _a, _b;
1632
1712
  const propKeys = Object.keys(filterItems);
1713
+ const blankSemanticsByProp = {};
1714
+ for (const prop of propKeys) {
1715
+ blankSemanticsByProp[prop] = resolveBlankSemantics((_a = this.config) === null || _a === void 0 ? void 0 : _a.blankSemantics, (_b = columnByProp[prop]) === null || _b === void 0 ? void 0 : _b.blankSemantics);
1716
+ }
1633
1717
  const trimmed = {};
1634
1718
  // each rows
1635
1719
  for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
1636
1720
  // check filter by column properties
1637
1721
  for (const prop of propKeys) {
1638
1722
  // add to the list of removed/trimmed rows of filter condition is satisfied
1639
- if (this.shouldTrimRow(filterItems[prop], prop, columnByProp[prop], rows[rowIndex])) {
1723
+ if (this.shouldTrimRow(filterItems[prop], prop, blankSemanticsByProp[prop], columnByProp[prop], rows[rowIndex])) {
1640
1724
  trimmed[rowIndex] = true;
1641
1725
  }
1642
1726
  } // end of for-of propKeys
1643
1727
  }
1644
1728
  return trimmed;
1645
1729
  }
1646
- shouldTrimRow(propFilters, prop, column, model = {}) {
1730
+ shouldTrimRow(propFilters, prop, blankSemantics, column, model = {}) {
1647
1731
  // reset the count of satisfied filters
1648
1732
  let propFilterSatisfiedCount = 0;
1649
1733
  // reset the array of last filter results
1650
1734
  let lastFilterResults = [];
1735
+ // THE MAGIC OF FILTERING IS HERE
1736
+ // If there is no column but user wants to filter by a property
1737
+ const hasOwnProperty = Object.hasOwn(model, prop);
1738
+ const sourceValue = model[prop];
1739
+ const parsedValue = (column === null || column === void 0 ? void 0 : column.cellParser)
1740
+ ? column.cellParser(model, column)
1741
+ : sourceValue;
1742
+ const context = {
1743
+ model,
1744
+ column,
1745
+ property: prop,
1746
+ sourceValue,
1747
+ parsedValue,
1748
+ hasOwnProperty,
1749
+ blankSemantics,
1750
+ };
1651
1751
  // testing each filter for a prop
1652
1752
  for (const [filterIndex, filterData] of propFilters.entries()) {
1653
1753
  // the filter LogicFunction based on the type
1654
1754
  const filterFunc = this.filterFunctionsIndexedByType[filterData.type];
1655
- // THE MAGIC OF FILTERING IS HERE
1656
- // If there is no column but user wants to filter by a property
1657
- const value = column ? column_service.getCellDataParsed(model, column) : model[prop];
1658
1755
  // OR relation
1659
1756
  if (filterData.relation === 'or') {
1660
1757
  // reset the array of last filter results
1661
1758
  lastFilterResults = [];
1662
1759
  // if the filter is satisfied, continue to the next filter
1663
- if (filterFunc(value, filterData.value)) {
1760
+ if (filterFunc(parsedValue, filterData.value, context)) {
1664
1761
  continue;
1665
1762
  }
1666
1763
  // if the filter is not satisfied, count it
@@ -1670,7 +1767,7 @@ class FilterPlugin extends BasePlugin {
1670
1767
  else {
1671
1768
  // 'and' relation will need to know the next filter
1672
1769
  // so we save this current filter to include it in the next filter
1673
- lastFilterResults.push(!filterFunc(value, filterData.value));
1770
+ lastFilterResults.push(!filterFunc(parsedValue, filterData.value, context));
1674
1771
  if (isFinalAndFilter(filterIndex, propFilters)) {
1675
1772
  // let's just continue since for sure propFilterSatisfiedCount cannot be satisfied
1676
1773
  if (allAndConditionsSatisfied(lastFilterResults)) {
@@ -2960,6 +3057,7 @@ exports.COLUMN_DRAG_END_EVENT = COLUMN_DRAG_END_EVENT;
2960
3057
  exports.COLUMN_DRAG_MOVE_EVENT = COLUMN_DRAG_MOVE_EVENT;
2961
3058
  exports.COLUMN_DRAG_START_EVENT = COLUMN_DRAG_START_EVENT;
2962
3059
  exports.ColumnMovePlugin = ColumnMovePlugin;
3060
+ exports.DEFAULT_BLANK_SEMANTICS = DEFAULT_BLANK_SEMANTICS;
2963
3061
  exports.DimensionStore = DimensionStore;
2964
3062
  exports.ExportCsv = ExportCsv;
2965
3063
  exports.ExportFilePlugin = ExportFilePlugin;
@@ -2985,6 +3083,8 @@ exports.getLeftRelative = getLeftRelative;
2985
3083
  exports.getNextOrder = getNextOrder;
2986
3084
  exports.getSortingIndex = getSortingIndex;
2987
3085
  exports.hasActiveSorting = hasActiveSorting;
3086
+ exports.isBlankValue = isBlankValue;
2988
3087
  exports.isStretchPlugin = isStretchPlugin;
3088
+ exports.resolveBlankSemantics = resolveBlankSemantics;
2989
3089
  exports.sortIndexByItems = sortIndexByItems;
2990
3090
  exports.themeTokenCssVariables = themeTokenCssVariables;
@@ -3,7 +3,7 @@
3
3
  */
4
4
  'use strict';
5
5
 
6
- var column_drag_plugin = require('./column.drag.plugin-E_K6cIAy.js');
6
+ var column_drag_plugin = require('./column.drag.plugin-CK5HADlW.js');
7
7
  var column_service = require('./column.service-C7p5eC5V.js');
8
8
  var headerCellRenderer = require('./header-cell-renderer-DHClfIto.js');
9
9
  var cellRenderer = require('./cell-renderer-Cf2Pu4S0.js');
@@ -675,6 +675,7 @@ Object.defineProperty(exports, "ColumnAutoSizeMode", {
675
675
  get: function () { return column_drag_plugin.ColumnAutoSizeMode; }
676
676
  });
677
677
  exports.ColumnMovePlugin = column_drag_plugin.ColumnMovePlugin;
678
+ exports.DEFAULT_BLANK_SEMANTICS = column_drag_plugin.DEFAULT_BLANK_SEMANTICS;
678
679
  exports.DimensionStore = column_drag_plugin.DimensionStore;
679
680
  exports.ExportCsv = column_drag_plugin.ExportCsv;
680
681
  exports.ExportFilePlugin = column_drag_plugin.ExportFilePlugin;
@@ -700,7 +701,9 @@ exports.getLeftRelative = column_drag_plugin.getLeftRelative;
700
701
  exports.getNextOrder = column_drag_plugin.getNextOrder;
701
702
  exports.getSortingIndex = column_drag_plugin.getSortingIndex;
702
703
  exports.hasActiveSorting = column_drag_plugin.hasActiveSorting;
704
+ exports.isBlankValue = column_drag_plugin.isBlankValue;
703
705
  exports.isStretchPlugin = column_drag_plugin.isStretchPlugin;
706
+ exports.resolveBlankSemantics = column_drag_plugin.resolveBlankSemantics;
704
707
  exports.sortIndexByItems = column_drag_plugin.sortIndexByItems;
705
708
  exports.themeTokenCssVariables = column_drag_plugin.themeTokenCssVariables;
706
709
  exports.GROUPING_ROW_TYPE = column_service.GROUPING_ROW_TYPE;
@@ -8,7 +8,7 @@ var column_service = require('./column.service-C7p5eC5V.js');
8
8
  var dimension_helpers = require('./dimension.helpers-CgHhnN1d.js');
9
9
  var debounce = require('./debounce-CcpHiH2p.js');
10
10
  var viewport_helpers = require('./viewport.helpers-BND76K2j.js');
11
- var column_drag_plugin = require('./column.drag.plugin-E_K6cIAy.js');
11
+ var column_drag_plugin = require('./column.drag.plugin-CK5HADlW.js');
12
12
  var viewport_store = require('./viewport.store-B4Clk4m9.js');
13
13
  var index$1 = require('./index--FdNLz1Z.js');
14
14
  var events = require('./events-DeLDyZlb.js');
@@ -1,6 +1,17 @@
1
1
  /*!
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
- const set = (value) => !(value === '' || value === null || value === void 0);
5
- export const notSet = (value) => !set(value);
4
+ import { DEFAULT_BLANK_SEMANTICS, isBlankValue } from "../filter.blank";
5
+ function blankContext(value, context) {
6
+ return context !== null && context !== void 0 ? context : {
7
+ model: {},
8
+ property: '',
9
+ sourceValue: value,
10
+ parsedValue: value,
11
+ hasOwnProperty: true,
12
+ blankSemantics: DEFAULT_BLANK_SEMANTICS,
13
+ };
14
+ }
15
+ export const notSet = (value, _extra, context) => isBlankValue(context ? context.sourceValue : value, blankContext(value, context));
16
+ const set = (value, _extra, context) => !notSet(value, _extra, context);
6
17
  export default set;
@@ -0,0 +1,68 @@
1
+ /*!
2
+ * Built by Revolist OU ❤️
3
+ */
4
+ export const DEFAULT_BLANK_SEMANTICS = Object.freeze({
5
+ null: true,
6
+ undefined: true,
7
+ emptyString: true,
8
+ whitespaceOnlyString: false,
9
+ emptyArray: false,
10
+ missingProperty: true,
11
+ });
12
+ const BOOLEAN_FIELDS = [
13
+ 'null',
14
+ 'undefined',
15
+ 'emptyString',
16
+ 'whitespaceOnlyString',
17
+ 'emptyArray',
18
+ 'missingProperty',
19
+ ];
20
+ /** Merge a grid policy and a partial column policy over Core defaults. */
21
+ export function resolveBlankSemantics(gridPolicy, columnPolicy) {
22
+ const resolved = Object.assign({}, DEFAULT_BLANK_SEMANTICS);
23
+ for (const policy of [gridPolicy, columnPolicy]) {
24
+ if (!policy) {
25
+ continue;
26
+ }
27
+ for (const field of BOOLEAN_FIELDS) {
28
+ if (policy[field] !== undefined) {
29
+ resolved[field] = policy[field];
30
+ }
31
+ }
32
+ if (policy.isBlank !== undefined) {
33
+ resolved.isBlank = policy.isBlank;
34
+ }
35
+ }
36
+ return resolved;
37
+ }
38
+ /** Evaluate blankness from the unparsed source value and property presence. */
39
+ export function isBlankValue(value, context) {
40
+ const policy = context.blankSemantics;
41
+ let fallbackResult;
42
+ if (!context.hasOwnProperty) {
43
+ fallbackResult = policy.missingProperty === true;
44
+ }
45
+ else if (value === null) {
46
+ fallbackResult = policy.null === true;
47
+ }
48
+ else if (value === undefined) {
49
+ fallbackResult = policy.undefined === true;
50
+ }
51
+ else if (value === '') {
52
+ fallbackResult = policy.emptyString === true;
53
+ }
54
+ else if (typeof value === 'string' &&
55
+ value.length > 0 &&
56
+ value.trim() === '') {
57
+ fallbackResult = policy.whitespaceOnlyString === true;
58
+ }
59
+ else if (Array.isArray(value) && value.length === 0) {
60
+ fallbackResult = policy.emptyArray === true;
61
+ }
62
+ else {
63
+ fallbackResult = false;
64
+ }
65
+ return policy.isBlank
66
+ ? policy.isBlank(value, context, fallbackResult)
67
+ : fallbackResult;
68
+ }
@@ -29,11 +29,13 @@ export const filterCoreFunctionsIndexedByType = {
29
29
  export const filterTypes = {
30
30
  string: ['notEmpty', 'empty', 'eq', 'notEq', 'begins', 'contains', 'notContains'],
31
31
  number: ['notEmpty', 'empty', 'eqN', 'neqN', 'gt', 'gte', 'lt', 'lte'],
32
+ boolean: ['notEmpty', 'empty'],
33
+ array: ['notEmpty', 'empty'],
32
34
  };
33
35
  export const filterNames = {
34
36
  none: 'None',
35
- empty: 'Not set',
36
- notEmpty: 'Set',
37
+ empty: 'Is blank',
38
+ notEmpty: 'Is not blank',
37
39
  eq: 'Equal',
38
40
  notEq: 'Not equal',
39
41
  begins: 'Begins with',
@@ -6,9 +6,11 @@ import { h } from "@stencil/core";
6
6
  import { BasePlugin } from "../base.plugin";
7
7
  import { FILTER_PROP, isFilterBtn } from "./filter.button";
8
8
  import { filterCoreFunctionsIndexedByType, filterNames, filterTypes, } from "./filter.indexed";
9
- import { getCellDataParsed, timeout } from "../../utils";
9
+ import { timeout } from "../../utils";
10
+ import { resolveBlankSemantics } from "./filter.blank";
10
11
  export * from './filter.types';
11
12
  export * from './filter.indexed';
13
+ export * from './filter.blank';
12
14
  export * from './filter.button';
13
15
  export const FILTER_TRIMMED_TYPE = 'filter';
14
16
  export const FILTER_CONFIG_CHANGED_EVENT = 'filterconfigchanged';
@@ -118,6 +120,7 @@ export class FilterPlugin extends BasePlugin {
118
120
  }
119
121
  initConfig(config) {
120
122
  var _a;
123
+ this.config = config;
121
124
  this.allowDuplicateOperators = (_a = config.allowDuplicateOperators) !== null && _a !== void 0 ? _a : true;
122
125
  if (this.pop) {
123
126
  this.pop.allowDuplicateOperators = this.allowDuplicateOperators;
@@ -334,38 +337,56 @@ export class FilterPlugin extends BasePlugin {
334
337
  * Get trimmed rows based on filter
335
338
  */
336
339
  getRowFilter(rows, filterItems, columnByProp) {
340
+ var _a, _b;
337
341
  const propKeys = Object.keys(filterItems);
342
+ const blankSemanticsByProp = {};
343
+ for (const prop of propKeys) {
344
+ blankSemanticsByProp[prop] = resolveBlankSemantics((_a = this.config) === null || _a === void 0 ? void 0 : _a.blankSemantics, (_b = columnByProp[prop]) === null || _b === void 0 ? void 0 : _b.blankSemantics);
345
+ }
338
346
  const trimmed = {};
339
347
  // each rows
340
348
  for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
341
349
  // check filter by column properties
342
350
  for (const prop of propKeys) {
343
351
  // add to the list of removed/trimmed rows of filter condition is satisfied
344
- if (this.shouldTrimRow(filterItems[prop], prop, columnByProp[prop], rows[rowIndex])) {
352
+ if (this.shouldTrimRow(filterItems[prop], prop, blankSemanticsByProp[prop], columnByProp[prop], rows[rowIndex])) {
345
353
  trimmed[rowIndex] = true;
346
354
  }
347
355
  } // end of for-of propKeys
348
356
  }
349
357
  return trimmed;
350
358
  }
351
- shouldTrimRow(propFilters, prop, column, model = {}) {
359
+ shouldTrimRow(propFilters, prop, blankSemantics, column, model = {}) {
352
360
  // reset the count of satisfied filters
353
361
  let propFilterSatisfiedCount = 0;
354
362
  // reset the array of last filter results
355
363
  let lastFilterResults = [];
364
+ // THE MAGIC OF FILTERING IS HERE
365
+ // If there is no column but user wants to filter by a property
366
+ const hasOwnProperty = Object.hasOwn(model, prop);
367
+ const sourceValue = model[prop];
368
+ const parsedValue = (column === null || column === void 0 ? void 0 : column.cellParser)
369
+ ? column.cellParser(model, column)
370
+ : sourceValue;
371
+ const context = {
372
+ model,
373
+ column,
374
+ property: prop,
375
+ sourceValue,
376
+ parsedValue,
377
+ hasOwnProperty,
378
+ blankSemantics,
379
+ };
356
380
  // testing each filter for a prop
357
381
  for (const [filterIndex, filterData] of propFilters.entries()) {
358
382
  // the filter LogicFunction based on the type
359
383
  const filterFunc = this.filterFunctionsIndexedByType[filterData.type];
360
- // THE MAGIC OF FILTERING IS HERE
361
- // If there is no column but user wants to filter by a property
362
- const value = column ? getCellDataParsed(model, column) : model[prop];
363
384
  // OR relation
364
385
  if (filterData.relation === 'or') {
365
386
  // reset the array of last filter results
366
387
  lastFilterResults = [];
367
388
  // if the filter is satisfied, continue to the next filter
368
- if (filterFunc(value, filterData.value)) {
389
+ if (filterFunc(parsedValue, filterData.value, context)) {
369
390
  continue;
370
391
  }
371
392
  // if the filter is not satisfied, count it
@@ -375,7 +396,7 @@ export class FilterPlugin extends BasePlugin {
375
396
  else {
376
397
  // 'and' relation will need to know the next filter
377
398
  // so we save this current filter to include it in the next filter
378
- lastFilterResults.push(!filterFunc(value, filterData.value));
399
+ lastFilterResults.push(!filterFunc(parsedValue, filterData.value, context));
379
400
  if (isFinalAndFilter(filterIndex, propFilters)) {
380
401
  // let's just continue since for sure propFilterSatisfiedCount cannot be satisfied
381
402
  if (allAndConditionsSatisfied(lastFilterResults)) {
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
- import { J as reduce, g as getRange, K as baseEach, C as getColumnType, c as columnTypes, L as toInteger, u as isGrouping, t as getGroupingName, r as rowTypes, B as getCellDataParsed, A as getCellRaw, j as GROUP_COLUMN_PROP, I as getColumnByProp, h as GROUP_EXPANDED, x as getParsedGroup, y as isSameGroup, G as GROUP_DEPTH, e as PSEUDO_GROUP_ITEM_VALUE, d as PSEUDO_GROUP_ITEM_ID, o as GROUPING_ROW_TYPE, p as getSource, f as PSEUDO_GROUP_COLUMN, s as gatherGrouping, m as GROUP_EXPAND_EVENT, v as isGroupingColumn, q as getExpanded, E as isColGrouping } from './column.service-Cfw3L0PN.js';
4
+ import { J as reduce, g as getRange, K as baseEach, C as getColumnType, c as columnTypes, L as toInteger, u as isGrouping, t as getGroupingName, r as rowTypes, A as getCellRaw, j as GROUP_COLUMN_PROP, I as getColumnByProp, h as GROUP_EXPANDED, x as getParsedGroup, y as isSameGroup, G as GROUP_DEPTH, e as PSEUDO_GROUP_ITEM_VALUE, d as PSEUDO_GROUP_ITEM_ID, o as GROUPING_ROW_TYPE, p as getSource, f as PSEUDO_GROUP_COLUMN, s as gatherGrouping, m as GROUP_EXPAND_EVENT, v as isGroupingColumn, q as getExpanded, E as isColGrouping } from './column.service-Cfw3L0PN.js';
5
5
  import { K as createStore, l as setStore, i as calculateDimensionData, L as identity, N as isArray, b as getSourceItem, g as getPhysical, e as setItems, j as getItemByPosition } from './dimension.helpers-fl4HSSK9.js';
6
6
  import { j as calculateRowHeaderSize } from './viewport.store-BSXmsiZc.js';
7
7
  import { g as getScrollbarSize, t as timeout } from './index-D24ku9ej.js';
@@ -1223,8 +1223,84 @@ const lsEq = function (value, extra) {
1223
1223
  };
1224
1224
  lsEq.extra = 'input';
1225
1225
 
1226
- const set = (value) => !(value === '' || value === null || value === void 0);
1227
- const notSet = (value) => !set(value);
1226
+ const DEFAULT_BLANK_SEMANTICS = Object.freeze({
1227
+ null: true,
1228
+ undefined: true,
1229
+ emptyString: true,
1230
+ whitespaceOnlyString: false,
1231
+ emptyArray: false,
1232
+ missingProperty: true,
1233
+ });
1234
+ const BOOLEAN_FIELDS = [
1235
+ 'null',
1236
+ 'undefined',
1237
+ 'emptyString',
1238
+ 'whitespaceOnlyString',
1239
+ 'emptyArray',
1240
+ 'missingProperty',
1241
+ ];
1242
+ /** Merge a grid policy and a partial column policy over Core defaults. */
1243
+ function resolveBlankSemantics(gridPolicy, columnPolicy) {
1244
+ const resolved = Object.assign({}, DEFAULT_BLANK_SEMANTICS);
1245
+ for (const policy of [gridPolicy, columnPolicy]) {
1246
+ if (!policy) {
1247
+ continue;
1248
+ }
1249
+ for (const field of BOOLEAN_FIELDS) {
1250
+ if (policy[field] !== undefined) {
1251
+ resolved[field] = policy[field];
1252
+ }
1253
+ }
1254
+ if (policy.isBlank !== undefined) {
1255
+ resolved.isBlank = policy.isBlank;
1256
+ }
1257
+ }
1258
+ return resolved;
1259
+ }
1260
+ /** Evaluate blankness from the unparsed source value and property presence. */
1261
+ function isBlankValue(value, context) {
1262
+ const policy = context.blankSemantics;
1263
+ let fallbackResult;
1264
+ if (!context.hasOwnProperty) {
1265
+ fallbackResult = policy.missingProperty === true;
1266
+ }
1267
+ else if (value === null) {
1268
+ fallbackResult = policy.null === true;
1269
+ }
1270
+ else if (value === undefined) {
1271
+ fallbackResult = policy.undefined === true;
1272
+ }
1273
+ else if (value === '') {
1274
+ fallbackResult = policy.emptyString === true;
1275
+ }
1276
+ else if (typeof value === 'string' &&
1277
+ value.length > 0 &&
1278
+ value.trim() === '') {
1279
+ fallbackResult = policy.whitespaceOnlyString === true;
1280
+ }
1281
+ else if (Array.isArray(value) && value.length === 0) {
1282
+ fallbackResult = policy.emptyArray === true;
1283
+ }
1284
+ else {
1285
+ fallbackResult = false;
1286
+ }
1287
+ return policy.isBlank
1288
+ ? policy.isBlank(value, context, fallbackResult)
1289
+ : fallbackResult;
1290
+ }
1291
+
1292
+ function blankContext(value, context) {
1293
+ return context !== null && context !== void 0 ? context : {
1294
+ model: {},
1295
+ property: '',
1296
+ sourceValue: value,
1297
+ parsedValue: value,
1298
+ hasOwnProperty: true,
1299
+ blankSemantics: DEFAULT_BLANK_SEMANTICS,
1300
+ };
1301
+ }
1302
+ const notSet = (value, _extra, context) => isBlankValue(context ? context.sourceValue : value, blankContext(value, context));
1303
+ const set = (value, _extra, context) => !notSet(value, _extra, context);
1228
1304
 
1229
1305
  const beginsWith = (value, extra) => {
1230
1306
  if (!value) {
@@ -1284,11 +1360,13 @@ const filterCoreFunctionsIndexedByType = {
1284
1360
  const filterTypes = {
1285
1361
  string: ['notEmpty', 'empty', 'eq', 'notEq', 'begins', 'contains', 'notContains'],
1286
1362
  number: ['notEmpty', 'empty', 'eqN', 'neqN', 'gt', 'gte', 'lt', 'lte'],
1363
+ boolean: ['notEmpty', 'empty'],
1364
+ array: ['notEmpty', 'empty'],
1287
1365
  };
1288
1366
  const filterNames = {
1289
1367
  none: 'None',
1290
- empty: 'Not set',
1291
- notEmpty: 'Set',
1368
+ empty: 'Is blank',
1369
+ notEmpty: 'Is not blank',
1292
1370
  eq: 'Equal',
1293
1371
  notEq: 'Not equal',
1294
1372
  begins: 'Begins with',
@@ -1411,6 +1489,7 @@ class FilterPlugin extends BasePlugin {
1411
1489
  }
1412
1490
  initConfig(config) {
1413
1491
  var _a;
1492
+ this.config = config;
1414
1493
  this.allowDuplicateOperators = (_a = config.allowDuplicateOperators) !== null && _a !== void 0 ? _a : true;
1415
1494
  if (this.pop) {
1416
1495
  this.pop.allowDuplicateOperators = this.allowDuplicateOperators;
@@ -1627,38 +1706,56 @@ class FilterPlugin extends BasePlugin {
1627
1706
  * Get trimmed rows based on filter
1628
1707
  */
1629
1708
  getRowFilter(rows, filterItems, columnByProp) {
1709
+ var _a, _b;
1630
1710
  const propKeys = Object.keys(filterItems);
1711
+ const blankSemanticsByProp = {};
1712
+ for (const prop of propKeys) {
1713
+ blankSemanticsByProp[prop] = resolveBlankSemantics((_a = this.config) === null || _a === void 0 ? void 0 : _a.blankSemantics, (_b = columnByProp[prop]) === null || _b === void 0 ? void 0 : _b.blankSemantics);
1714
+ }
1631
1715
  const trimmed = {};
1632
1716
  // each rows
1633
1717
  for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
1634
1718
  // check filter by column properties
1635
1719
  for (const prop of propKeys) {
1636
1720
  // add to the list of removed/trimmed rows of filter condition is satisfied
1637
- if (this.shouldTrimRow(filterItems[prop], prop, columnByProp[prop], rows[rowIndex])) {
1721
+ if (this.shouldTrimRow(filterItems[prop], prop, blankSemanticsByProp[prop], columnByProp[prop], rows[rowIndex])) {
1638
1722
  trimmed[rowIndex] = true;
1639
1723
  }
1640
1724
  } // end of for-of propKeys
1641
1725
  }
1642
1726
  return trimmed;
1643
1727
  }
1644
- shouldTrimRow(propFilters, prop, column, model = {}) {
1728
+ shouldTrimRow(propFilters, prop, blankSemantics, column, model = {}) {
1645
1729
  // reset the count of satisfied filters
1646
1730
  let propFilterSatisfiedCount = 0;
1647
1731
  // reset the array of last filter results
1648
1732
  let lastFilterResults = [];
1733
+ // THE MAGIC OF FILTERING IS HERE
1734
+ // If there is no column but user wants to filter by a property
1735
+ const hasOwnProperty = Object.hasOwn(model, prop);
1736
+ const sourceValue = model[prop];
1737
+ const parsedValue = (column === null || column === void 0 ? void 0 : column.cellParser)
1738
+ ? column.cellParser(model, column)
1739
+ : sourceValue;
1740
+ const context = {
1741
+ model,
1742
+ column,
1743
+ property: prop,
1744
+ sourceValue,
1745
+ parsedValue,
1746
+ hasOwnProperty,
1747
+ blankSemantics,
1748
+ };
1649
1749
  // testing each filter for a prop
1650
1750
  for (const [filterIndex, filterData] of propFilters.entries()) {
1651
1751
  // the filter LogicFunction based on the type
1652
1752
  const filterFunc = this.filterFunctionsIndexedByType[filterData.type];
1653
- // THE MAGIC OF FILTERING IS HERE
1654
- // If there is no column but user wants to filter by a property
1655
- const value = column ? getCellDataParsed(model, column) : model[prop];
1656
1753
  // OR relation
1657
1754
  if (filterData.relation === 'or') {
1658
1755
  // reset the array of last filter results
1659
1756
  lastFilterResults = [];
1660
1757
  // if the filter is satisfied, continue to the next filter
1661
- if (filterFunc(value, filterData.value)) {
1758
+ if (filterFunc(parsedValue, filterData.value, context)) {
1662
1759
  continue;
1663
1760
  }
1664
1761
  // if the filter is not satisfied, count it
@@ -1668,7 +1765,7 @@ class FilterPlugin extends BasePlugin {
1668
1765
  else {
1669
1766
  // 'and' relation will need to know the next filter
1670
1767
  // so we save this current filter to include it in the next filter
1671
- lastFilterResults.push(!filterFunc(value, filterData.value));
1768
+ lastFilterResults.push(!filterFunc(parsedValue, filterData.value, context));
1672
1769
  if (isFinalAndFilter(filterIndex, propFilters)) {
1673
1770
  // let's just continue since for sure propFilterSatisfiedCount cannot be satisfied
1674
1771
  if (allAndConditionsSatisfied(lastFilterResults)) {
@@ -2951,4 +3048,4 @@ function getColumnDragPosition(targetItem, startItem, renderOffset, scrollOffset
2951
3048
  return insertionEdge - renderOffset + scrollOffset;
2952
3049
  }
2953
3050
 
2954
- export { AutoSizeColumnPlugin as A, BasePlugin as B, ColumnAutoSizeMode as C, DimensionStore as D, ExportFilePlugin as E, FILTER_TRIMMED_TYPE as F, GroupingRowPlugin as G, getNextOrder as H, getComparer as I, SelectionStore as S, StretchColumn as a, ExportCsv as b, FILTER_CONFIG_CHANGED_EVENT as c, defineTheme as d, FILTE_PANEL as e, FilterPlugin as f, filterCoreFunctionsIndexedByType as g, filterTypes as h, isStretchPlugin as i, filterNames as j, doCollapse as k, doExpand as l, COLUMN_DRAG_MOVE_EVENT as m, COLUMN_DRAG_END_EVENT as n, BEFORE_COLUMN_DRAG_END_EVENT as o, COLUMN_DRAG_START_EVENT as p, ColumnMovePlugin as q, getLeftRelative as r, getColumnDragPosition as s, themeTokenCssVariables as t, SortingPlugin as u, hasActiveSorting as v, getSortingIndex as w, sortIndexByItems as x, defaultCellCompare as y, descCellCompare as z };
3051
+ export { AutoSizeColumnPlugin as A, BasePlugin as B, ColumnAutoSizeMode as C, DimensionStore as D, ExportFilePlugin as E, FILTER_TRIMMED_TYPE as F, GroupingRowPlugin as G, sortIndexByItems as H, defaultCellCompare as I, descCellCompare as J, getNextOrder as K, getComparer as L, SelectionStore as S, StretchColumn as a, ExportCsv as b, FILTER_CONFIG_CHANGED_EVENT as c, defineTheme as d, FILTE_PANEL as e, FilterPlugin as f, filterCoreFunctionsIndexedByType as g, filterTypes as h, isStretchPlugin as i, filterNames as j, DEFAULT_BLANK_SEMANTICS as k, isBlankValue as l, doCollapse as m, doExpand as n, COLUMN_DRAG_MOVE_EVENT as o, COLUMN_DRAG_END_EVENT as p, BEFORE_COLUMN_DRAG_END_EVENT as q, resolveBlankSemantics as r, COLUMN_DRAG_START_EVENT as s, themeTokenCssVariables as t, ColumnMovePlugin as u, getLeftRelative as v, getColumnDragPosition as w, SortingPlugin as x, hasActiveSorting as y, getSortingIndex as z };
package/dist/esm/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /*!
2
2
  * Built by Revolist OU ❤️
3
3
  */
4
- import { d as defineTheme, B as BasePlugin } from './column.drag.plugin-DKgC_0I1.js';
5
- export { A as AutoSizeColumnPlugin, o as BEFORE_COLUMN_DRAG_END_EVENT, n as COLUMN_DRAG_END_EVENT, m as COLUMN_DRAG_MOVE_EVENT, p as COLUMN_DRAG_START_EVENT, C as ColumnAutoSizeMode, q as ColumnMovePlugin, D as DimensionStore, b as ExportCsv, E as ExportFilePlugin, c as FILTER_CONFIG_CHANGED_EVENT, F as FILTER_TRIMMED_TYPE, e as FILTE_PANEL, f as FilterPlugin, G as GroupingRowPlugin, S as SelectionStore, u as SortingPlugin, a as StretchColumn, y as defaultCellCompare, z as descCellCompare, k as doCollapse, l as doExpand, g as filterCoreFunctionsIndexedByType, j as filterNames, h as filterTypes, s as getColumnDragPosition, I as getComparer, r as getLeftRelative, H as getNextOrder, w as getSortingIndex, v as hasActiveSorting, i as isStretchPlugin, x as sortIndexByItems, t as themeTokenCssVariables } from './column.drag.plugin-DKgC_0I1.js';
4
+ import { d as defineTheme, B as BasePlugin } from './column.drag.plugin-DDBKeTGI.js';
5
+ export { A as AutoSizeColumnPlugin, q as BEFORE_COLUMN_DRAG_END_EVENT, p as COLUMN_DRAG_END_EVENT, o as COLUMN_DRAG_MOVE_EVENT, s as COLUMN_DRAG_START_EVENT, C as ColumnAutoSizeMode, u as ColumnMovePlugin, k as DEFAULT_BLANK_SEMANTICS, D as DimensionStore, b as ExportCsv, E as ExportFilePlugin, c as FILTER_CONFIG_CHANGED_EVENT, F as FILTER_TRIMMED_TYPE, e as FILTE_PANEL, f as FilterPlugin, G as GroupingRowPlugin, S as SelectionStore, x as SortingPlugin, a as StretchColumn, I as defaultCellCompare, J as descCellCompare, m as doCollapse, n as doExpand, g as filterCoreFunctionsIndexedByType, j as filterNames, h as filterTypes, w as getColumnDragPosition, L as getComparer, v as getLeftRelative, K as getNextOrder, z as getSortingIndex, y as hasActiveSorting, l as isBlankValue, i as isStretchPlugin, r as resolveBlankSemantics, H as sortIndexByItems, t as themeTokenCssVariables } from './column.drag.plugin-DDBKeTGI.js';
6
6
  export { o as GROUPING_ROW_TYPE, j as GROUP_COLUMN_PROP, G as GROUP_DEPTH, h as GROUP_EXPANDED, l as GROUP_EXPAND_BTN, m as GROUP_EXPAND_EVENT, k as GROUP_ORIGINAL_INDEX, f as PSEUDO_GROUP_COLUMN, P as PSEUDO_GROUP_ITEM, d as PSEUDO_GROUP_ITEM_ID, e as PSEUDO_GROUP_ITEM_VALUE, c as columnTypes, a as cropCellToMax, H as gatherGroup, s as gatherGrouping, z as getCellData, B as getCellDataParsed, A as getCellRaw, I as getColumnByProp, D as getColumnSizes, C as getColumnType, F as getColumns, q as getExpanded, t as getGroupingName, x as getParsedGroup, g as getRange, p as getSource, E as isColGrouping, u as isGrouping, v as isGroupingColumn, b as isRangeSingleCell, i as isRowType, y as isSameGroup, w as measureEqualDepth, n as nextCell, r as rowTypes } from './column.service-Cfw3L0PN.js';
7
7
  export { d as dispatch, a as dispatchByEvent } from './header-cell-renderer-Cqtg1ETB.js';
8
8
  export { C as CellRenderer, G as GroupingRowRenderer, S as SortingSign, e as expandEvent, a as expandSvgIconVNode, r as renderGroupCells } from './cell-renderer-11cf-lu3.js';
@@ -6,7 +6,7 @@ import { c as columnTypes, J as reduce, C as getColumnType, r as rowTypes, i as
6
6
  import { D as DataStore, b as getSourceItem, f as getSourceItemVirtualIndexByProp, d as setSourceByPhysicalIndex, s as setSourceByVirtualIndex, a as getVisibleSourceItem, h as gatherTrimmedItems, k as getItemByIndex, R as RESIZE_INTERVAL } from './dimension.helpers-fl4HSSK9.js';
7
7
  import { d as debounce } from './debounce-PCRWZliA.js';
8
8
  import { g as getScrollDimension, v as viewportDataPartition, F as FOOTER_SLOT, C as CONTENT_SLOT, H as HEADER_SLOT, D as DATA_SLOT } from './viewport.helpers-CoCAvmZs.js';
9
- import { D as DimensionStore, t as themeTokenCssVariables, S as SelectionStore, B as BasePlugin, G as GroupingRowPlugin, a as StretchColumn, i as isStretchPlugin, A as AutoSizeColumnPlugin, f as FilterPlugin, E as ExportFilePlugin, u as SortingPlugin, q as ColumnMovePlugin } from './column.drag.plugin-DKgC_0I1.js';
9
+ import { D as DimensionStore, t as themeTokenCssVariables, S as SelectionStore, B as BasePlugin, G as GroupingRowPlugin, a as StretchColumn, i as isStretchPlugin, A as AutoSizeColumnPlugin, f as FilterPlugin, E as ExportFilePlugin, x as SortingPlugin, u as ColumnMovePlugin } from './column.drag.plugin-DDBKeTGI.js';
10
10
  import { V as ViewportStore } from './viewport.store-BSXmsiZc.js';
11
11
  import { t as timeout } from './index-D24ku9ej.js';
12
12
  import { g as getPropertyFromEvent } from './events-BvSmBueA.js';