@revolist/revogrid 4.27.1 → 4.27.3

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.
Files changed (44) hide show
  1. package/dist/cjs/{filter.button-F2Bw3UAd.js → filter.button-C6ixuMmr.js} +3 -2
  2. package/dist/cjs/index.cjs.js +3 -2
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/revo-grid.cjs.entry.js +3 -3
  5. package/dist/cjs/revo-grid.cjs.js +1 -1
  6. package/dist/cjs/revogr-data_4.cjs.entry.js +9 -8
  7. package/dist/cjs/revogr-filter-panel.cjs.entry.js +141 -33
  8. package/dist/cjs/{row-resize.plugin-sK9_rcUN.js → row-resize.plugin-C4YOF1lN.js} +54 -5
  9. package/dist/collection/components/header/header-renderer.js +7 -6
  10. package/dist/collection/components/header/revogr-header-style.css +8 -3
  11. package/dist/collection/components/revoGrid/revo-grid-style.css +12 -2
  12. package/dist/collection/plugins/filter/filter.button.js +3 -2
  13. package/dist/collection/plugins/filter/filter.indexed.js +5 -0
  14. package/dist/collection/plugins/filter/filter.panel.js +140 -31
  15. package/dist/collection/plugins/filter/filter.plugin.js +48 -5
  16. package/dist/collection/plugins/filter/filter.style.css +25 -3
  17. package/dist/{revo-grid/filter.button-DMhpuAiw.js → esm/filter.button-CEPUxLUo.js} +3 -2
  18. package/dist/esm/index.js +3 -3
  19. package/dist/esm/loader.js +1 -1
  20. package/dist/esm/revo-grid.entry.js +3 -3
  21. package/dist/esm/revo-grid.js +1 -1
  22. package/dist/esm/revogr-data_4.entry.js +9 -8
  23. package/dist/esm/revogr-filter-panel.entry.js +141 -33
  24. package/dist/{revo-grid/row-resize.plugin-DBOgjLdE.js → esm/row-resize.plugin-Beu0pMds.js} +54 -6
  25. package/dist/{esm/filter.button-DMhpuAiw.js → revo-grid/filter.button-CEPUxLUo.js} +3 -2
  26. package/dist/revo-grid/index.esm.js +3 -3
  27. package/dist/revo-grid/revo-grid.entry.js +3 -3
  28. package/dist/revo-grid/revo-grid.esm.js +1 -1
  29. package/dist/revo-grid/revogr-data_4.entry.js +9 -8
  30. package/dist/revo-grid/revogr-filter-panel.entry.js +141 -33
  31. package/dist/{esm/row-resize.plugin-DBOgjLdE.js → revo-grid/row-resize.plugin-Beu0pMds.js} +54 -6
  32. package/dist/types/plugins/filter/filter.indexed.d.ts +2 -0
  33. package/dist/types/plugins/filter/filter.panel.d.ts +9 -2
  34. package/dist/types/plugins/filter/filter.plugin.d.ts +8 -1
  35. package/dist/types/plugins/filter/filter.types.d.ts +8 -0
  36. package/dist/types/types/interfaces.d.ts +13 -1
  37. package/hydrate/index.js +205 -46
  38. package/hydrate/index.mjs +205 -46
  39. package/package.json +1 -1
  40. package/standalone/filter.button.js +1 -1
  41. package/standalone/index.js +1 -1
  42. package/standalone/revo-grid.js +1 -1
  43. package/standalone/revogr-filter-panel.js +1 -1
  44. package/standalone/revogr-header2.js +1 -1
@@ -5,7 +5,7 @@
5
5
 
6
6
  var index = require('./index-DRvxCueo.js');
7
7
  var debounce = require('./debounce-CcpHiH2p.js');
8
- var filter_button = require('./filter.button-F2Bw3UAd.js');
8
+ var filter_button = require('./filter.button-C6ixuMmr.js');
9
9
 
10
10
  (function closest() {
11
11
  if (!Element.prototype.matches) {
@@ -68,7 +68,7 @@ function moveFilterItem(items, sourceId, targetId) {
68
68
  return true;
69
69
  }
70
70
 
71
- const filterStyleCss = () => `.revo-button{position:relative;overflow:hidden;color:var(--rg-theme-button-text);background-color:var(--rg-theme-button-bg);height:32px;line-height:32px;padding:0 15px;outline:0;border:0;border-radius:7px;box-sizing:border-box;cursor:pointer}.revo-button.green{background-color:var(--rg-theme-button-success-bg)}.revo-button.red{background-color:var(--rg-theme-button-danger-bg)}.revo-button:disabled,.revo-button[disabled]{cursor:not-allowed !important;filter:opacity(0.35) !important}.revo-button.outline{border:1px solid var(--rg-theme-button-outline-border);line-height:30px;background:none;color:var(--rg-theme-button-outline-text);box-shadow:none}revogr-filter-panel{display:block}revogr-filter-panel .filter-panel-dialog{position:fixed;top:0;left:0;z-index:100;max-height:calc(100vh - 16px);overflow:auto;opacity:1;transform:none;color:var(--rg-theme-filter-panel-text);background-color:var(--rg-theme-filter-panel-bg);border:1px solid var(--rg-theme-filter-panel-border);transform-origin:62px 0px;box-shadow:0 5px 18px -2px var(--rg-theme-filter-panel-shadow);box-sizing:border-box;padding:10px;border-radius:8px;margin:0;min-width:220px;text-align:left;animation:revogr-filter-panel-open 140ms cubic-bezier(0.2, 0, 0, 1)}revogr-filter-panel .filter-panel-dialog .filter-holder>div{display:flex;flex-direction:column}revogr-filter-panel .filter-panel-dialog label{font-size:13px;display:block;padding:8px 0}revogr-filter-panel .filter-panel-dialog select{width:100%}revogr-filter-panel .filter-panel-dialog input[type=text]{border:0;min-height:34px;margin:5px 0;color:var(--rg-theme-filter-panel-text);background:var(--rg-theme-filter-panel-input-bg);border-radius:5px;padding:0 10px;box-sizing:border-box;width:100%}revogr-filter-panel .filter-panel-dialog .filter-actions{position:sticky;right:0;bottom:-10px;left:0;z-index:1;text-align:right;margin:10px -10px -10px;padding:0 5px 10px 10px;background:var(--rg-theme-filter-panel-bg);border-top:1px solid var(--rg-theme-filter-panel-divider)}revogr-filter-panel .filter-panel-dialog .filter-actions button{margin-top:10px;margin-right:5px}@keyframes revogr-filter-panel-open{from{opacity:0;transform:translateY(-4px) scale(0.98)}to{opacity:1;transform:none}}@media (prefers-reduced-motion: reduce){revogr-filter-panel .filter-panel-dialog{animation:none}}.rgHeaderCell:hover .rv-filter{transition:opacity 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 178ms cubic-bezier(0.4, 0, 0.2, 1) 0ms}.rgHeaderCell:hover .rv-filter,.rgHeaderCell .rv-filter.active{opacity:1}.rgHeaderCell .rv-filter{height:24px;width:24px;background:none;border:0;opacity:0;visibility:visible;cursor:pointer;border-radius:4px;position:relative;z-index:1}.rgHeaderCell .rv-filter.active{color:var(--rg-theme-filter-panel-icon-active)}.rgHeaderCell .rv-filter .filter-img{color:var(--rg-theme-filter-panel-icon);width:11px}.select-css{display:block;font-family:sans-serif;line-height:1.3;padding:0.6em 1.4em 0.5em 0.8em;width:100%;max-width:100%;box-sizing:border-box;margin:0;color:var(--rg-theme-filter-panel-text);border:1px solid var(--rg-theme-filter-panel-select-border);box-shadow:transparent;border-radius:0.5em;appearance:none;background-color:var(--rg-theme-filter-panel-input-bg);background-image:var(--revo-grid-filter-panel-select-arrow, url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E"));background-repeat:no-repeat, repeat;background-position:right 0.7em top 50%, 0 0;background-size:0.65em auto, 100%;}.select-css::-ms-expand{display:none}.select-css{}.select-css:hover{border-color:var(--rg-theme-filter-panel-select-border)}.select-css{}.select-css:focus{border-color:var(--rg-theme-filter-panel-select-border-hover);box-shadow:var(--rg-theme-filter-panel-focus-ring);outline:none}.select-css{}.select-css option{font-weight:normal}.select-css{}.select-css:disabled,.select-css[aria-disabled=true]{color:var(--rg-theme-filter-panel-muted-text);background-image:var(--revo-grid-filter-panel-select-arrow-disabled, url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22graytext%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E"))}.select-css:disabled:hover,.select-css[aria-disabled=true]{border-color:var(--rg-theme-filter-panel-select-border)}.multi-filter-list{margin-top:5px;margin-bottom:5px}.multi-filter-list div{white-space:nowrap}.multi-filter-list .multi-filter-list-row{display:flex;align-items:center;gap:6px;position:relative}.multi-filter-list .multi-filter-list-row.filter-row-dragging{opacity:0.65}.multi-filter-list .multi-filter-list-row.filter-row-drag-over::before{content:"";position:absolute;top:-4px;right:0;left:0;z-index:2;height:2px;background:var(--rg-theme-filter-panel-reorder-accent);border-radius:999px;box-shadow:0 0 0 2px var(--rg-theme-filter-panel-bg)}.multi-filter-list .multi-filter-list-row.filter-row-drop-active .filter-row-drop-target{pointer-events:auto}.multi-filter-list .filter-row-drop-target{position:absolute;inset:0;z-index:1;padding:0;pointer-events:none;background:transparent;border:0}.multi-filter-list .multi-filter-list-action{display:flex;align-self:stretch;flex:0 0 auto;justify-content:flex-end;align-items:center}.multi-filter-list .and-or-button{margin:0 0 0 10px;min-width:58px;cursor:pointer}.multi-filter-list .trash-button{margin:0 0 -2px 6px;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;width:22px;height:100%;font-size:16px}.multi-filter-list .trash-button .trash-img{width:1em}.multi-filter-list .reorder-button{border:0;background:transparent;color:var(--rg-theme-filter-panel-reorder-color);cursor:grab;font-family:monospace;font-size:12px;letter-spacing:0;line-height:1;padding:6px 2px;transform:scaleX(0.8);width:16px}.multi-filter-list .reorder-button.filter-row-drag-over{color:var(--rg-theme-filter-panel-reorder-accent)}.multi-filter-list .reorder-button:active{cursor:grabbing}.multi-filter-list-container{padding:0;margin:0;list-style:none}.add-filter-divider{display:block;margin:0 -10px 10px -10px;border-bottom:1px solid var(--rg-theme-filter-panel-divider);height:10px}.select-input{display:flex;align-items:center;flex:1 1 auto;gap:6px;min-width:0}.select-input .select-filter,.select-input .filter-extra{flex:1 1 0;min-width:0}.select-input .select-filter{width:auto}.select-input .filter-extra{display:flex}.select-input .filter-extra>*{width:100%}.select-input input[type=text],.select-input input[type=date]{margin:0}`;
71
+ const filterStyleCss = () => `.revo-button{position:relative;overflow:hidden;color:var(--rg-theme-button-text);background-color:var(--rg-theme-button-bg);height:32px;line-height:32px;padding:0 15px;outline:0;border:0;border-radius:7px;box-sizing:border-box;cursor:pointer}.revo-button.green{background-color:var(--rg-theme-button-success-bg)}.revo-button.red{background-color:var(--rg-theme-button-danger-bg)}.revo-button:disabled,.revo-button[disabled]{cursor:not-allowed !important;filter:opacity(0.35) !important}.revo-button.outline{border:1px solid var(--rg-theme-button-outline-border);line-height:30px;background:none;color:var(--rg-theme-button-outline-text);box-shadow:none}revogr-filter-panel{display:block}revogr-filter-panel .filter-panel-dialog{position:fixed;top:0;left:0;z-index:100;max-height:calc(100vh - 16px);overflow:auto;opacity:1;transform:none;color:var(--rg-theme-filter-panel-text);background-color:var(--rg-theme-filter-panel-bg);border:1px solid var(--rg-theme-filter-panel-border);transform-origin:62px 0px;box-shadow:0 5px 18px -2px var(--rg-theme-filter-panel-shadow);box-sizing:border-box;padding:10px;border-radius:8px;margin:0;min-width:220px;text-align:left;animation:revogr-filter-panel-open 140ms cubic-bezier(0.2, 0, 0, 1)}revogr-filter-panel .filter-panel-dialog .filter-holder>div{display:flex;flex-direction:column}revogr-filter-panel .filter-panel-dialog label{font-size:13px;display:block;padding:8px 0}revogr-filter-panel .filter-panel-dialog select{width:100%}revogr-filter-panel .filter-panel-dialog input[type=text]{border:0;min-height:34px;margin:5px 0;color:var(--rg-theme-filter-panel-text);background:var(--rg-theme-filter-panel-input-bg);border-radius:5px;padding:0 10px;box-sizing:border-box;width:100%}revogr-filter-panel .filter-panel-dialog .filter-actions{position:sticky;right:0;bottom:-10px;left:0;z-index:1;text-align:right;margin:10px -10px -10px;padding:0 5px 10px 10px;background:var(--rg-theme-filter-panel-bg);border-top:1px solid var(--rg-theme-filter-panel-divider)}revogr-filter-panel .filter-panel-dialog .filter-actions button{margin-top:10px;margin-right:5px}@keyframes revogr-filter-panel-open{from{opacity:0;transform:translateY(-4px) scale(0.98)}to{opacity:1;transform:none}}@media (prefers-reduced-motion: reduce){revogr-filter-panel .filter-panel-dialog{animation:none}}.rgHeaderCell:hover .rv-filter{transition:opacity 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, width 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 178ms cubic-bezier(0.4, 0, 0.2, 1) 0ms}.rgHeaderCell:hover:has(.rv-filter) .header-content,.rgHeaderCell:focus-within:has(.rv-filter) .header-content,.rgHeaderCell:has(.rv-filter.active) .header-content{margin-right:24px}.rgHeaderCell:hover:has(.rv-filter):has(.desc) .header-content,.rgHeaderCell:hover:has(.rv-filter):has(.asc) .header-content,.rgHeaderCell:focus-within:has(.rv-filter):has(.desc) .header-content,.rgHeaderCell:focus-within:has(.rv-filter):has(.asc) .header-content,.rgHeaderCell:has(.rv-filter.active):has(.desc) .header-content,.rgHeaderCell:has(.rv-filter.active):has(.asc) .header-content{margin-right:8px;padding-right:24px}.rgHeaderCell:hover .rv-filter,.rgHeaderCell:focus-within .rv-filter,.rgHeaderCell .rv-filter.active{opacity:1;width:24px}@media (hover: none), (pointer: coarse){.rgHeaderCell:has(.rv-filter) .header-content{margin-right:24px}.rgHeaderCell:has(.rv-filter):has(.desc) .header-content,.rgHeaderCell:has(.rv-filter):has(.asc) .header-content{margin-right:8px;padding-right:24px}.rgHeaderCell .rv-filter{opacity:1;width:24px}}.rgHeaderCell .rv-filter{height:24px;width:0;background:none;border:0;opacity:0;visibility:visible;cursor:pointer;border-radius:4px;position:relative;z-index:1;padding:0}.rgHeaderCell .rv-filter.active{color:var(--rg-theme-filter-panel-icon-active)}.rgHeaderCell .rv-filter .filter-img{color:var(--rg-theme-filter-panel-icon);width:11px}.select-css{display:block;font-family:sans-serif;line-height:1.3;padding:0.6em 1.4em 0.5em 0.8em;width:100%;max-width:100%;box-sizing:border-box;margin:0;color:var(--rg-theme-filter-panel-text);border:1px solid var(--rg-theme-filter-panel-select-border);box-shadow:transparent;border-radius:0.5em;appearance:none;background-color:var(--rg-theme-filter-panel-input-bg);background-image:var(--revo-grid-filter-panel-select-arrow, url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E"));background-repeat:no-repeat, repeat;background-position:right 0.7em top 50%, 0 0;background-size:0.65em auto, 100%;}.select-css::-ms-expand{display:none}.select-css{}.select-css:hover{border-color:var(--rg-theme-filter-panel-select-border)}.select-css{}.select-css:focus{border-color:var(--rg-theme-filter-panel-select-border-hover);box-shadow:var(--rg-theme-filter-panel-focus-ring);outline:none}.select-css{}.select-css option{font-weight:normal}.select-css{}.select-css:disabled,.select-css[aria-disabled=true]{color:var(--rg-theme-filter-panel-muted-text);background-image:var(--revo-grid-filter-panel-select-arrow-disabled, url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22graytext%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E"))}.select-css:disabled:hover,.select-css[aria-disabled=true]{border-color:var(--rg-theme-filter-panel-select-border)}.multi-filter-list{margin-top:5px;margin-bottom:5px}.multi-filter-list div{white-space:nowrap}.multi-filter-list .multi-filter-list-row{display:flex;align-items:center;gap:6px;position:relative}.multi-filter-list .multi-filter-list-row.filter-row-dragging{opacity:0.65}.multi-filter-list .multi-filter-list-row.filter-row-drag-over::before{content:"";position:absolute;top:-4px;right:0;left:0;z-index:2;height:2px;background:var(--rg-theme-filter-panel-reorder-accent);border-radius:999px;box-shadow:0 0 0 2px var(--rg-theme-filter-panel-bg)}.multi-filter-list .multi-filter-list-row.filter-row-drop-active .filter-row-drop-target{pointer-events:auto}.multi-filter-list .filter-row-drop-target{position:absolute;inset:0;z-index:1;padding:0;pointer-events:none;background:transparent;border:0}.multi-filter-list .multi-filter-list-action{display:flex;align-self:stretch;flex:0 0 auto;justify-content:flex-end;align-items:center}.multi-filter-list .and-or-button{margin:0 0 0 10px;min-width:58px;cursor:pointer}.multi-filter-list .trash-button{margin:0 0 -2px 6px;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;width:22px;height:100%;font-size:16px}.multi-filter-list .trash-button .trash-img{width:1em}.multi-filter-list .reorder-button{border:0;background:transparent;color:var(--rg-theme-filter-panel-reorder-color);cursor:grab;font-family:monospace;font-size:12px;letter-spacing:0;line-height:1;padding:6px 2px;transform:scaleX(0.8);width:16px}.multi-filter-list .reorder-button.filter-row-drag-over{color:var(--rg-theme-filter-panel-reorder-accent)}.multi-filter-list .reorder-button:active{cursor:grabbing}.multi-filter-list-container{padding:0;margin:0;list-style:none}.add-filter-divider{display:block;margin:0 -10px 10px -10px;border-bottom:1px solid var(--rg-theme-filter-panel-divider);height:10px}.select-input{display:flex;align-items:center;flex:1 1 auto;gap:6px;min-width:0}.select-input .select-filter,.select-input .filter-extra{flex:1 1 0;min-width:0}.select-input .select-filter{width:auto}.select-input .filter-extra{display:flex}.select-input .filter-extra>*{width:100%}.select-input input[type=text],.select-input input[type=date]{margin:0}`;
72
72
 
73
73
  const defaultType = 'none';
74
74
  const FILTER_LIST_CLASS = 'multi-filter-list';
@@ -80,6 +80,7 @@ const FilterPanel = class {
80
80
  index.registerInstance(this, hostRef);
81
81
  this.filterChange = index.createEvent(this, "filterChange", 7);
82
82
  this.resetChange = index.createEvent(this, "resetChange", 7);
83
+ this.hasChanges = false;
83
84
  this.filterCaptionsInternal = {
84
85
  title: 'Filter by',
85
86
  ok: 'Close',
@@ -115,7 +116,7 @@ const FilterPanel = class {
115
116
  */
116
117
  this.allowDuplicateOperators = true;
117
118
  this.debouncedApplyFilter = debounce.debounce(() => {
118
- this.filterChange.emit(this.filterItems);
119
+ this.emitFilterChange();
119
120
  }, 400);
120
121
  }
121
122
  onMouseDown(e) {
@@ -145,10 +146,27 @@ const FilterPanel = class {
145
146
  }
146
147
  }
147
148
  async show(newEntity) {
149
+ this.hasChanges = false;
148
150
  this.changes = newEntity;
149
- this.filterItems = (newEntity === null || newEntity === void 0 ? void 0 : newEntity.filterItems) || {};
151
+ this.filterItems = this.cloneFilterItems((newEntity === null || newEntity === void 0 ? void 0 : newEntity.filterItems) || {});
152
+ this.draftFilter = undefined;
150
153
  if (this.changes) {
151
154
  this.changes.type = this.changes.type || defaultType;
155
+ const prop = this.changes.prop;
156
+ const propFilters = prop === undefined ? undefined : this.filterItems[prop];
157
+ if (!(propFilters === null || propFilters === void 0 ? void 0 : propFilters.length) &&
158
+ this.changes.showDefaultFilter !== false &&
159
+ this.changes.hideDefaultFilters !== true) {
160
+ const type = this.resolveDraftFilterType(this.changes.defaultFilterType);
161
+ if (type) {
162
+ this.draftFilter = {
163
+ id: ++this.filterId,
164
+ type,
165
+ value: '',
166
+ relation: 'and',
167
+ };
168
+ }
169
+ }
152
170
  }
153
171
  }
154
172
  async getChanges() {
@@ -169,29 +187,42 @@ const FilterPanel = class {
169
187
  const prop = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop;
170
188
  if (prop === undefined)
171
189
  return '';
172
- const propFilters = (_b = this.filterItems[prop]) !== null && _b !== void 0 ? _b : [];
173
- const visibleFilterCount = propFilters.filter(filter => !filter.hidden).length;
190
+ const propFilters = ((_b = this.filterItems[prop]) !== null && _b !== void 0 ? _b : []).map((filter, index) => ({
191
+ filter,
192
+ index,
193
+ isDraft: false,
194
+ }));
195
+ if (this.draftFilter) {
196
+ propFilters.push({
197
+ filter: this.draftFilter,
198
+ index: propFilters.length,
199
+ isDraft: true,
200
+ });
201
+ }
202
+ const visibleFilters = propFilters.filter(({ filter }) => !filter.hidden);
203
+ const visibleFilterCount = visibleFilters.length;
174
204
  const capts = Object.assign(Object.assign({}, this.filterCaptionsInternal), this.filterCaptions);
175
- return (index.h("div", { key: this.filterId }, index.h("ul", { class: "multi-filter-list-container" }, propFilters.map((filter, index$1) => {
205
+ return (index.h("div", { key: this.filterId }, index.h("ul", { class: "multi-filter-list-container" }, propFilters.map(({ filter, index: index$1, isDraft }) => {
206
+ var _a;
176
207
  let andOrButton;
177
208
  if (filter.hidden) {
178
209
  return;
179
210
  }
180
211
  // hide toggle button if there is only one filter and the last one
181
- if (index$1 !== this.filterItems[prop].length - 1) {
212
+ if (((_a = visibleFilters[visibleFilterCount - 1]) === null || _a === void 0 ? void 0 : _a.filter.id) !== filter.id) {
182
213
  andOrButton = (index.h(filter_button.AndOrButton, { text: filter.relation === 'and' ? capts.and : capts.or, onClick: () => this.toggleFilterAndOr(filter.id) }));
183
214
  }
184
- const extra = this.renderExtra(prop, index$1);
215
+ const extra = this.renderExtra(prop, index$1, isDraft);
185
216
  const isDragging = this.draggedFilterId === filter.id;
186
217
  const isDragOver = this.dragOverFilterId === filter.id && !isDragging;
187
- const canReorder = visibleFilterCount > 1;
218
+ const canReorder = visibleFilterCount > 1 && !isDraft;
188
219
  return (index.h("li", { key: filter.id, class: FILTER_LIST_CLASS, "aria-label": `${capts.filterCondition} ${index$1 + 1}` }, index.h("div", { class: {
189
220
  'multi-filter-list-row': true,
190
221
  'filter-row-drop-active': this.draggedFilterId !== undefined && !isDragging,
191
222
  'filter-row-dragging': isDragging,
192
223
  'filter-row-drag-over': isDragOver,
193
- } }, canReorder ? (index.h("button", { type: "button", class: "filter-row-drop-target", tabIndex: -1, "aria-label": `${capts.filterCondition} ${index$1 + 1}`, onDragOver: e => this.onFilterDragOver(e, filter.id), onDragLeave: () => this.onFilterDragLeave(filter.id), onDrop: e => this.onFilterDrop(e, prop, filter.id) })) : '', canReorder ? (index.h(filter_button.ReorderButton, { ariaLabel: capts.reorderFilter, dragging: isDragging, dragOver: isDragOver, onDragStart: e => this.onFilterDragStart(e, filter.id), onDragEnd: () => this.onFilterDragEnd(), onKeyDown: e => this.onFilterReorderKeyDown(e, prop, filter.id) })) : '', index.h("div", { class: { 'select-input': true } }, index.h("select", { class: "select-css select-filter", onChange: e => this.onFilterTypeChange(e, prop, index$1) }, this.renderSelectOptions(this.filterItems[prop][index$1].type, true)), extra ? index.h("div", { class: "filter-extra" }, extra) : ''), index.h("div", { class: FILTER_LIST_CLASS_ACTION }, andOrButton, index.h(filter_button.TrashButton, { ariaLabel: capts.removeFilter, onClick: () => this.onRemoveFilter(filter.id) })))));
194
- })), propFilters.some(f => !f.hidden) ? index.h("div", { class: "add-filter-divider" }) : ''));
224
+ } }, canReorder ? (index.h("button", { type: "button", class: "filter-row-drop-target", tabIndex: -1, "aria-label": `${capts.filterCondition} ${index$1 + 1}`, onDragOver: e => this.onFilterDragOver(e, filter.id), onDragLeave: () => this.onFilterDragLeave(filter.id), onDrop: e => this.onFilterDrop(e, prop, filter.id) })) : '', canReorder ? (index.h(filter_button.ReorderButton, { ariaLabel: capts.reorderFilter, dragging: isDragging, dragOver: isDragOver, onDragStart: e => this.onFilterDragStart(e, filter.id), onDragEnd: () => this.onFilterDragEnd(), onKeyDown: e => this.onFilterReorderKeyDown(e, prop, filter.id) })) : '', index.h("div", { class: { 'select-input': true } }, index.h("select", { class: "select-css select-filter", onChange: e => this.onFilterTypeChange(e, prop, index$1, isDraft) }, this.renderSelectOptions(filter.type, true)), extra ? index.h("div", { class: "filter-extra" }, extra) : ''), index.h("div", { class: FILTER_LIST_CLASS_ACTION }, andOrButton, index.h(filter_button.TrashButton, { ariaLabel: capts.removeFilter, onClick: () => this.onRemoveFilter(filter.id) })))));
225
+ })), visibleFilterCount ? index.h("div", { class: "add-filter-divider" }) : ''));
195
226
  }
196
227
  componentDidRender() {
197
228
  this.syncDialog();
@@ -240,16 +271,24 @@ const FilterPanel = class {
240
271
  el.style.left = `${left}px`;
241
272
  el.style.top = `${top}px`;
242
273
  }
243
- onFilterTypeChange(e, prop, index) {
274
+ onFilterTypeChange(e, prop, index, isDraft = false) {
244
275
  if (!(e.target instanceof HTMLSelectElement)) {
245
276
  return;
246
277
  }
247
- this.filterItems[prop][index].type = e.target.value;
278
+ const type = e.target.value;
279
+ const filter = isDraft
280
+ ? this.promoteDraft(prop, type)
281
+ : this.filterItems[prop][index];
282
+ if (!filter) {
283
+ return;
284
+ }
285
+ filter.type = type;
286
+ this.hasChanges = true;
248
287
  // this re-renders the input to know if we need extra input
249
288
  this.filterId++;
250
289
  // adding setTimeout will wait for the next tick DOM update then focus on input
251
290
  setTimeout(() => {
252
- const input = document.getElementById('filter-input-' + this.filterItems[prop][index].id);
291
+ const input = document.getElementById('filter-input-' + filter.id);
253
292
  if (input instanceof HTMLInputElement) {
254
293
  input.focus();
255
294
  }
@@ -284,12 +323,20 @@ const FilterPanel = class {
284
323
  return;
285
324
  this.filterId++;
286
325
  this.currentFilterId = this.filterId;
287
- this.filterItems[prop].push({
288
- id: this.currentFilterId,
289
- type: this.currentFilterType,
290
- value: '',
291
- relation: 'and',
292
- });
326
+ if (this.draftFilter) {
327
+ this.draftFilter.id = this.currentFilterId;
328
+ this.draftFilter.type = this.currentFilterType;
329
+ this.promoteDraft(prop);
330
+ }
331
+ else {
332
+ this.filterItems[prop].push({
333
+ id: this.currentFilterId,
334
+ type: this.currentFilterType,
335
+ value: '',
336
+ relation: 'and',
337
+ });
338
+ this.hasChanges = true;
339
+ }
293
340
  // adding setTimeout will wait for the next tick DOM update then focus on input
294
341
  setTimeout(() => {
295
342
  const input = document.getElementById('filter-input-' + this.currentFilterId);
@@ -298,7 +345,9 @@ const FilterPanel = class {
298
345
  }, 0);
299
346
  }
300
347
  onSave() {
301
- this.filterChange.emit(this.filterItems);
348
+ if (this.hasChanges) {
349
+ this.emitFilterChange();
350
+ }
302
351
  }
303
352
  onCancel() {
304
353
  this.changes = undefined;
@@ -306,16 +355,25 @@ const FilterPanel = class {
306
355
  onReset() {
307
356
  var _a;
308
357
  this.assertChanges();
309
- this.resetChange.emit((_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop);
358
+ this.draftFilter = undefined;
359
+ const prop = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop;
360
+ if (prop !== undefined) {
361
+ delete this.filterItems[prop];
362
+ }
363
+ this.resetChange.emit(prop);
310
364
  // this updates the DOM which is used by getFilterItemsList() key
311
365
  this.filterId++;
312
366
  }
313
367
  onRemoveFilter(id) {
314
- var _a;
368
+ var _a, _b;
315
369
  this.assertChanges();
316
370
  // this is for reactivity issues for getFilterItemsList()
317
371
  this.filterId++;
318
372
  const prop = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop;
373
+ if (((_b = this.draftFilter) === null || _b === void 0 ? void 0 : _b.id) === id) {
374
+ this.draftFilter = undefined;
375
+ return;
376
+ }
319
377
  const items = this.filterItems[prop !== null && prop !== void 0 ? prop : ''];
320
378
  if (!items)
321
379
  return;
@@ -323,6 +381,7 @@ const FilterPanel = class {
323
381
  if (index === -1)
324
382
  return;
325
383
  items.splice(index, 1);
384
+ this.hasChanges = true;
326
385
  // let's remove the prop if no more filters so the filter icon will be removed
327
386
  if (items.length === 0)
328
387
  delete this.filterItems[prop !== null && prop !== void 0 ? prop : ''];
@@ -364,6 +423,7 @@ const FilterPanel = class {
364
423
  if (!moveFilterItem(items, sourceId, targetId)) {
365
424
  return;
366
425
  }
426
+ this.hasChanges = true;
367
427
  this.filterId++;
368
428
  if (!this.disableDynamicFiltering) {
369
429
  this.debouncedApplyFilter();
@@ -399,6 +459,7 @@ const FilterPanel = class {
399
459
  if (!target || !moveFilterItem(items, sourceId, target.id)) {
400
460
  return;
401
461
  }
462
+ this.hasChanges = true;
402
463
  this.filterId++;
403
464
  if (!this.disableDynamicFiltering) {
404
465
  this.debouncedApplyFilter();
@@ -417,6 +478,7 @@ const FilterPanel = class {
417
478
  if (index === -1)
418
479
  return;
419
480
  items[index].relation = items[index].relation === 'and' ? 'or' : 'and';
481
+ this.hasChanges = true;
420
482
  if (!this.disableDynamicFiltering) {
421
483
  this.debouncedApplyFilter();
422
484
  }
@@ -465,12 +527,22 @@ const FilterPanel = class {
465
527
  }
466
528
  return options;
467
529
  }
468
- renderExtra(prop, index$1) {
469
- const currentFilter = this.filterItems[prop];
530
+ renderExtra(prop, index$1, isDraft = false) {
531
+ var _a, _b;
532
+ const currentFilter = isDraft
533
+ ? this.draftFilter
534
+ : (_a = this.filterItems[prop]) === null || _a === void 0 ? void 0 : _a[index$1];
470
535
  if (!currentFilter)
471
536
  return '';
472
537
  const applyFilter = (value) => {
473
- this.filterItems[prop][index$1].value = value;
538
+ currentFilter.value = value;
539
+ if (isDraft && !this.isMeaningfulDraftValue(value)) {
540
+ return;
541
+ }
542
+ if (isDraft && !this.promoteDraft(prop)) {
543
+ return;
544
+ }
545
+ this.hasChanges = true;
474
546
  if (!this.disableDynamicFiltering) {
475
547
  this.debouncedApplyFilter();
476
548
  }
@@ -485,11 +557,11 @@ const FilterPanel = class {
485
557
  }
486
558
  };
487
559
  const capts = Object.assign(Object.assign({}, this.filterCaptionsInternal), this.filterCaptions);
488
- const extra = this.filterEntities[currentFilter[index$1].type].extra;
560
+ const extra = (_b = this.filterEntities[currentFilter.type]) === null || _b === void 0 ? void 0 : _b.extra;
489
561
  if (typeof extra === 'function') {
490
562
  return extra(index.h, {
491
- value: currentFilter[index$1].value,
492
- filter: currentFilter[index$1],
563
+ value: currentFilter.value,
564
+ filter: currentFilter,
493
565
  prop,
494
566
  index: index$1,
495
567
  placeholder: capts.placeholder,
@@ -504,7 +576,7 @@ const FilterPanel = class {
504
576
  if (extra !== 'input' && extra !== 'datepicker') {
505
577
  return '';
506
578
  }
507
- return (index.h("input", { id: `filter-input-${currentFilter[index$1].id}`, placeholder: capts.placeholder, type: extra === 'datepicker' ? 'date' : 'text', value: currentFilter[index$1].value, onInput: (e) => {
579
+ return (index.h("input", { id: `filter-input-${currentFilter.id}`, placeholder: capts.placeholder, type: extra === 'datepicker' ? 'date' : 'text', value: currentFilter.value, onInput: (e) => {
508
580
  if (e.target instanceof HTMLInputElement) {
509
581
  applyFilter(e.target.value);
510
582
  }
@@ -520,6 +592,42 @@ const FilterPanel = class {
520
592
  e.stopPropagation();
521
593
  } }));
522
594
  }
595
+ resolveDraftFilterType(preferred) {
596
+ var _a, _b;
597
+ const available = Object.values((_b = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.filterTypes) !== null && _b !== void 0 ? _b : {}).flat();
598
+ const type = preferred && available.includes(preferred)
599
+ ? preferred
600
+ : available[0];
601
+ return type;
602
+ }
603
+ promoteDraft(prop, type) {
604
+ if (!this.draftFilter) {
605
+ return;
606
+ }
607
+ if (!this.filterItems[prop]) {
608
+ this.filterItems[prop] = [];
609
+ }
610
+ if (type) {
611
+ this.draftFilter.type = type;
612
+ }
613
+ const filter = this.draftFilter;
614
+ this.filterItems[prop].push(filter);
615
+ this.draftFilter = undefined;
616
+ this.hasChanges = true;
617
+ return filter;
618
+ }
619
+ isMeaningfulDraftValue(value) {
620
+ return value !== '' && value !== undefined && value !== null;
621
+ }
622
+ emitFilterChange() {
623
+ this.filterChange.emit(this.cloneFilterItems(this.filterItems));
624
+ }
625
+ cloneFilterItems(filterItems) {
626
+ return Object.fromEntries(Object.entries(filterItems).map(([prop, filters]) => [
627
+ prop,
628
+ filters.map(filter => (Object.assign({}, filter))),
629
+ ]));
630
+ }
523
631
  getAddFilterSelect() {
524
632
  return this.element.querySelector(`#${FILTER_ID}`);
525
633
  }
@@ -552,7 +660,7 @@ const FilterPanel = class {
552
660
  top: `${(_d = (_c = this.changes) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0}px`,
553
661
  };
554
662
  const capts = Object.assign(Object.assign({}, this.filterCaptionsInternal), this.filterCaptions);
555
- return (index.h(index.Host, { key: 'd0e4ebb408750b11b3965da6a25e581733c968e3' }, index.h("dialog", { key: '3df36777c931ec1063e8574169ca880a99dbfe41', class: "filter-panel-dialog", style: style, ref: el => (this.dialog = el), onCancel: e => {
663
+ return (index.h(index.Host, { key: 'f7ec3ca1855a9391b4f270ad7056f9c7a4a0204e' }, index.h("dialog", { key: 'a5c46aa4822934e7a6eb455fd686513b9101afb4', class: "filter-panel-dialog", style: style, ref: el => (this.dialog = el), onCancel: e => {
556
664
  e.preventDefault();
557
665
  this.onCancel();
558
666
  } }, this.changes && [
@@ -561,7 +669,7 @@ const FilterPanel = class {
561
669
  ((_g = this.changes) === null || _g === void 0 ? void 0 : _g.hideDefaultFilters) !== true && [
562
670
  index.h("label", { key: "filter-title" }, capts.title),
563
671
  index.h("div", { key: "filter-holder", class: "filter-holder" }, this.getFilterItemsList()),
564
- index.h("div", { key: "add-filter", class: "add-filter" }, index.h("select", { key: 'e2a8bd29f2090d3e6c933795427b71ca190b82aa', id: FILTER_ID, class: "select-css", onChange: e => this.onAddNewFilter(e) }, this.renderSelectOptions(this.currentFilterType))),
672
+ index.h("div", { key: "add-filter", class: "add-filter" }, index.h("select", { key: '3912f4bd9b1e66fda46e9b6d7c002d29da726345', id: FILTER_ID, class: "select-css", onChange: e => this.onAddNewFilter(e) }, this.renderSelectOptions(this.currentFilterType))),
565
673
  ],
566
674
  index.h("slot", { key: "default-slot" }),
567
675
  ((_j = (_h = this.changes).extraBottomContent) === null || _j === void 0 ? void 0 : _j.call(_h, this.changes)) || '',
@@ -8,7 +8,7 @@ var dimension_helpers = require('./dimension.helpers-CptesQOZ.js');
8
8
  var viewport_store = require('./viewport.store-mhsdi61t.js');
9
9
  var index$1 = require('./index-BVESmpqW.js');
10
10
  var index = require('./index-DRvxCueo.js');
11
- var filter_button = require('./filter.button-F2Bw3UAd.js');
11
+ var filter_button = require('./filter.button-C6ixuMmr.js');
12
12
  var debounce = require('./debounce-CcpHiH2p.js');
13
13
  var headerCellRenderer = require('./header-cell-renderer-B5Y4fdZC.js');
14
14
 
@@ -1363,6 +1363,11 @@ const filterTypes = {
1363
1363
  boolean: ['notEmpty', 'empty'],
1364
1364
  array: ['notEmpty', 'empty'],
1365
1365
  };
1366
+ /** Preferred initial operator for built-in filter families. */
1367
+ const filterTypeDefaults = {
1368
+ string: 'contains',
1369
+ number: 'eqN',
1370
+ };
1366
1371
  const filterNames = {
1367
1372
  none: 'None',
1368
1373
  empty: 'Is blank',
@@ -1405,6 +1410,8 @@ const FILTE_PANEL = 'revogr-filter-panel';
1405
1410
  *
1406
1411
  * @property {FilterLocalization|undefined} localization - translation for filter popup captions.
1407
1412
  *
1413
+ * @property {boolean|undefined} defaultFilter - creates a draft condition when an empty filter panel opens. Defaults to true.
1414
+ *
1408
1415
  * @property {boolean|undefined} disableDynamicFiltering - disables dynamic filtering. A way to apply filters on Save only.
1409
1416
  */
1410
1417
  /**
@@ -1426,7 +1433,7 @@ class FilterPlugin extends BasePlugin {
1426
1433
  * number: ['eqN', 'neqN', 'gt']
1427
1434
  * }
1428
1435
  */
1429
- this.filterByType = Object.assign({}, filterTypes);
1436
+ this.filterByType = Object.fromEntries(Object.entries(filterTypes).map(([type, filters]) => [type, [...filters]]));
1430
1437
  this.filterNameIndexByType = Object.assign({}, filterNames);
1431
1438
  this.filterFunctionsIndexedByType = Object.assign({}, filterCoreFunctionsIndexedByType);
1432
1439
  this.filterProp = filter_button.FILTER_PROP;
@@ -1510,11 +1517,16 @@ class FilterPlugin extends BasePlugin {
1510
1517
  return null;
1511
1518
  }
1512
1519
  initConfig(config) {
1513
- var _a;
1520
+ var _a, _b, _c, _d;
1514
1521
  this.config = config;
1515
1522
  this.allowDuplicateOperators = (_a = config.allowDuplicateOperators) !== null && _a !== void 0 ? _a : true;
1516
1523
  if (this.pop) {
1517
1524
  this.pop.allowDuplicateOperators = this.allowDuplicateOperators;
1525
+ this.pop.disableDynamicFiltering =
1526
+ (_b = config.disableDynamicFiltering) !== null && _b !== void 0 ? _b : false;
1527
+ this.pop.closeOnOutsideClick =
1528
+ (_c = config.closeFilterPanelOnOutsideClick) !== null && _c !== void 0 ? _c : true;
1529
+ this.pop.filterCaptions = (_d = config.localization) === null || _d === void 0 ? void 0 : _d.captions;
1518
1530
  }
1519
1531
  if (config.multiFilterItems) {
1520
1532
  this.multiFilterItems = Object.assign({}, config.multiFilterItems);
@@ -1603,11 +1615,12 @@ class FilterPlugin extends BasePlugin {
1603
1615
  }
1604
1616
  // filter button clicked, open filter dialog
1605
1617
  const buttonPos = (filterButton instanceof HTMLElement ? filterButton : el).getBoundingClientRect();
1606
- const data = Object.assign(Object.assign(Object.assign({}, e.detail), this.filterCollection[prop]), { x: buttonPos.x, y: buttonPos.y + buttonPos.height, anchorY: buttonPos.y, autoCorrect: true, filterTypes: this.getColumnFilter(e.detail.filter), filterItems: this.multiFilterItems, extraContent: this.extraHyperContent, extraBottomContent: this.extraBottomHyperContent });
1618
+ const data = Object.assign(Object.assign(Object.assign({}, e.detail), this.filterCollection[prop]), { x: buttonPos.x, y: buttonPos.y + buttonPos.height, anchorY: buttonPos.y, autoCorrect: true, filterTypes: this.getColumnFilter(e.detail.filter), defaultFilterType: this.getDefaultFilter(e.detail.filter), showDefaultFilter: this.shouldShowDefaultFilter(e.detail.filter), filterItems: this.multiFilterItems, extraContent: this.extraHyperContent, extraBottomContent: this.extraBottomHyperContent });
1607
1619
  (_b = this.beforeshow) === null || _b === void 0 ? void 0 : _b.call(this, data);
1608
1620
  this.pop.show(data);
1609
1621
  }
1610
- getColumnFilter(type) {
1622
+ getColumnFilter(config) {
1623
+ const type = this.isColumnFilterOption(config) ? config.type : config;
1611
1624
  let filterType = 'string';
1612
1625
  if (!type) {
1613
1626
  return { [filterType]: this.filterByType[filterType] };
@@ -1627,6 +1640,41 @@ class FilterPlugin extends BasePlugin {
1627
1640
  }
1628
1641
  return { [filterType]: this.filterByType[filterType] };
1629
1642
  }
1643
+ /** Resolve the preferred operator against the column's available filters. */
1644
+ getDefaultFilter(config) {
1645
+ var _a;
1646
+ const filters = this.getColumnFilter(config);
1647
+ const availableFilters = Object.values(filters).flat();
1648
+ const columnDefault = this.isColumnFilterOption(config)
1649
+ ? config.default
1650
+ : undefined;
1651
+ if (typeof columnDefault === 'string' &&
1652
+ availableFilters.includes(columnDefault)) {
1653
+ return columnDefault;
1654
+ }
1655
+ const firstFamily = Object.keys(filters)[0];
1656
+ const familyDefault = filterTypeDefaults[firstFamily];
1657
+ if (familyDefault && ((_a = filters[firstFamily]) === null || _a === void 0 ? void 0 : _a.includes(familyDefault))) {
1658
+ return familyDefault;
1659
+ }
1660
+ return availableFilters[0];
1661
+ }
1662
+ /** Resolve grid and column-level draft opt-outs. */
1663
+ shouldShowDefaultFilter(config) {
1664
+ var _a;
1665
+ if (this.isColumnFilterOption(config)) {
1666
+ if (config.default === false) {
1667
+ return false;
1668
+ }
1669
+ if (typeof config.default === 'string') {
1670
+ return true;
1671
+ }
1672
+ }
1673
+ return ((_a = this.config) === null || _a === void 0 ? void 0 : _a.defaultFilter) !== false;
1674
+ }
1675
+ isColumnFilterOption(value) {
1676
+ return !!value && typeof value === 'object' && !Array.isArray(value);
1677
+ }
1630
1678
  isValidType(type) {
1631
1679
  return !!(typeof type === 'string' && this.filterByType[type]);
1632
1680
  }
@@ -3746,6 +3794,7 @@ exports.doCollapse = doCollapse;
3746
3794
  exports.doExpand = doExpand;
3747
3795
  exports.filterCoreFunctionsIndexedByType = filterCoreFunctionsIndexedByType;
3748
3796
  exports.filterNames = filterNames;
3797
+ exports.filterTypeDefaults = filterTypeDefaults;
3749
3798
  exports.filterTypes = filterTypes;
3750
3799
  exports.getColumnDragPosition = getColumnDragPosition;
3751
3800
  exports.getComparer = getComparer;
@@ -11,19 +11,20 @@ const HeaderRenderer = (p) => {
11
11
  const hasSortingSign = !!(((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable) ||
12
12
  ((_b = p.data) === null || _b === void 0 ? void 0 : _b.order) ||
13
13
  ((_c = p.data) === null || _c === void 0 ? void 0 : _c.sortIndex));
14
+ const hasFilterButton = !!(p.canFilter && ((_d = p.data) === null || _d === void 0 ? void 0 : _d.filter) !== false);
14
15
  const cellClass = {
15
16
  [HEADER_CLASS]: true,
16
- [HEADER_SORTABLE_CLASS]: !!((_d = p.data) === null || _d === void 0 ? void 0 : _d.sortable),
17
+ [HEADER_SORTABLE_CLASS]: !!((_e = p.data) === null || _e === void 0 ? void 0 : _e.sortable),
17
18
  };
18
- if ((_e = p.data) === null || _e === void 0 ? void 0 : _e.order) {
19
+ if ((_f = p.data) === null || _f === void 0 ? void 0 : _f.order) {
19
20
  cellClass[p.data.order] = true;
20
21
  }
21
22
  const dataProps = {
22
- key: String((_g = (_f = p.data) === null || _f === void 0 ? void 0 : _f.prop) !== null && _g !== void 0 ? _g : p.column.itemIndex),
23
+ key: String((_h = (_g = p.data) === null || _g === void 0 ? void 0 : _g.prop) !== null && _h !== void 0 ? _h : p.column.itemIndex),
23
24
  [DATA_COL]: p.column.itemIndex,
24
25
  canResize: p.canResize,
25
- minWidth: ((_h = p.data) === null || _h === void 0 ? void 0 : _h.minSize) || MIN_COL_SIZE,
26
- maxWidth: (_j = p.data) === null || _j === void 0 ? void 0 : _j.maxSize,
26
+ minWidth: ((_j = p.data) === null || _j === void 0 ? void 0 : _j.minSize) || MIN_COL_SIZE,
27
+ maxWidth: (_k = p.data) === null || _k === void 0 ? void 0 : _k.maxSize,
27
28
  active: p.active || ['r'],
28
29
  class: cellClass,
29
30
  style: {
@@ -59,6 +60,6 @@ const HeaderRenderer = (p) => {
59
60
  }
60
61
  }
61
62
  }
62
- return (h(HeaderCellRenderer, { data: p.data, props: dataProps, additionalData: p.additionalData }, hasSortingSign ? h(SortingSign, { column: p.data }) : null, p.canFilter && ((_k = p.data) === null || _k === void 0 ? void 0 : _k.filter) !== false ? (h(FilterButton, { column: p.data })) : ('')));
63
+ return (h(HeaderCellRenderer, { data: p.data, props: dataProps, additionalData: p.additionalData }, hasSortingSign || hasFilterButton ? (h("span", { class: "header-controls" }, hasSortingSign ? h(SortingSign, { column: p.data }) : null, hasFilterButton ? h(FilterButton, { column: p.data }) : null)) : null));
63
64
  };
64
65
  export default HeaderRenderer;
@@ -71,10 +71,15 @@ revogr-header .rgHeaderCell .header-content {
71
71
  white-space: nowrap;
72
72
  flex-grow: 1;
73
73
  }
74
- revogr-header .rgHeaderCell > span:first-of-type {
75
- position: relative;
74
+ revogr-header .rgHeaderCell .header-controls {
75
+ position: absolute;
76
+ top: 0;
77
+ right: 1px;
78
+ bottom: 1px;
79
+ min-width: 15px;
76
80
  z-index: 1;
77
- margin-left: auto;
81
+ display: flex;
82
+ align-items: center;
78
83
  }
79
84
  revogr-header .rgHeaderCell .resizable {
80
85
  display: block;
@@ -175,9 +175,16 @@ revo-grid[theme]:not([theme=default],
175
175
  [theme=dark],
176
176
  [theme=compact],
177
177
  [theme=darkCompact]) revogr-header .rgHeaderCell {
178
- padding: var(--rg-theme-header-padding);
178
+ padding: 0;
179
179
  text-overflow: ellipsis;
180
180
  }
181
+ revo-grid:is([theme=material], [theme=darkMaterial]) revogr-header .rgHeaderCell .header-content,
182
+ revo-grid[theme]:not([theme=default],
183
+ [theme=dark],
184
+ [theme=compact],
185
+ [theme=darkCompact]) revogr-header .rgHeaderCell .header-content {
186
+ padding: var(--rg-theme-header-padding);
187
+ }
181
188
  revo-grid:is([theme=material], [theme=darkMaterial]) revogr-header .header-rgRow,
182
189
  revo-grid[theme]:not([theme=default],
183
190
  [theme=dark],
@@ -264,9 +271,12 @@ revo-grid:is([theme=compact], [theme=darkCompact]) revogr-header {
264
271
  text-align: var(--rg-theme-header-text-align);
265
272
  }
266
273
  revo-grid:is([theme=compact], [theme=darkCompact]) revogr-header .rgHeaderCell {
267
- padding: var(--rg-theme-header-padding);
274
+ padding: 0;
268
275
  text-overflow: ellipsis;
269
276
  }
277
+ revo-grid:is([theme=compact], [theme=darkCompact]) revogr-header .rgHeaderCell .header-content {
278
+ padding: var(--rg-theme-header-padding);
279
+ }
270
280
  revo-grid:is([theme=compact], [theme=darkCompact]) revogr-header .header-rgRow {
271
281
  height: var(--rg-theme-header-height);
272
282
  }
@@ -9,9 +9,10 @@ export const AND_OR_BUTTON = 'and-or-button';
9
9
  export const TRASH_BUTTON = 'trash-button';
10
10
  export const REORDER_BUTTON = 'reorder-button';
11
11
  export const FilterButton = ({ column }) => {
12
- return (h("span", null, h("button", { class: {
12
+ const active = !!(column === null || column === void 0 ? void 0 : column[FILTER_PROP]);
13
+ return (h("span", { class: "filter-button-wrapper" }, h("button", { class: {
13
14
  [FILTER_BUTTON_CLASS]: true,
14
- [FILTER_BUTTON_ACTIVE]: column && !!column[FILTER_PROP],
15
+ [FILTER_BUTTON_ACTIVE]: active,
15
16
  } }, h("svg", { class: "filter-img", viewBox: "0 0 64 64" }, h("g", { stroke: "none", "stroke-width": "1", fill: "none", "fill-rule": "evenodd" }, h("path", { d: "M43,48 L43,56 L21,56 L21,48 L43,48 Z M53,28 L53,36 L12,36 L12,28 L53,28 Z M64,8 L64,16 L0,16 L0,8 L64,8 Z", fill: "currentColor" }))))));
16
17
  };
17
18
  export const TrashButton = ({ ariaLabel, onClick }) => {
@@ -32,6 +32,11 @@ export const filterTypes = {
32
32
  boolean: ['notEmpty', 'empty'],
33
33
  array: ['notEmpty', 'empty'],
34
34
  };
35
+ /** Preferred initial operator for built-in filter families. */
36
+ export const filterTypeDefaults = {
37
+ string: 'contains',
38
+ number: 'eqN',
39
+ };
35
40
  export const filterNames = {
36
41
  none: 'None',
37
42
  empty: 'Is blank',