function M(f) {
  const { totalRows: e, viewportHeight: t, scrollTop: r, rowHeight: l, overscan: a } = f, i = Math.ceil(t / l);
  let n = Math.floor(r / l) - a;
  n < 0 && (n = 0);
  let u = n + i + a * 2;
  return u > e && (u = e), u === e && n > 0 && (n = Math.max(0, u - i - a * 2)), {
    start: n,
    end: u,
    offsetY: n * l,
    totalHeight: e * l
  };
}
function P(f, e) {
  return f <= e;
}
const _ = {
  expand: "▶",
  collapse: "▼",
  sortAsc: "▲",
  sortDesc: "▼",
  sortNone: "⇅",
  submenuArrow: "▶",
  dragHandle: "⋮⋮",
  toolPanel: "☰"
};
class V {
  /** Plugin version - override in subclass if needed */
  version = "1.0.0";
  /** CSS styles to inject into the grid's shadow DOM */
  styles;
  /** Custom cell renderers keyed by type name */
  cellRenderers;
  /** Custom header renderers keyed by type name */
  headerRenderers;
  /** Custom cell editors keyed by type name */
  cellEditors;
  /** The grid instance this plugin is attached to */
  grid;
  /** Plugin configuration - merged with defaults in attach() */
  config;
  /** User-provided configuration from constructor */
  userConfig;
  /**
   * Default configuration - subclasses should override this getter.
   * Note: This must be a getter (not property initializer) for proper inheritance
   * since property initializers run after parent constructor.
   */
  get defaultConfig() {
    return {};
  }
  constructor(e = {}) {
    this.userConfig = e;
  }
  /**
   * Called when the plugin is attached to a grid.
   * Override to set up event listeners, initialize state, etc.
   */
  attach(e) {
    this.grid = e, this.config = { ...this.defaultConfig, ...this.userConfig };
  }
  /**
   * Called when the plugin is detached from a grid.
   * Override to clean up event listeners, timers, etc.
   */
  detach() {
  }
  /**
   * Get another plugin instance from the same grid.
   * Use for inter-plugin communication.
   */
  getPlugin(e) {
    return this.grid?.getPlugin(e);
  }
  /**
   * Emit a custom event from the grid.
   */
  emit(e, t) {
    this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
  }
  /**
   * Request a re-render of the grid.
   */
  requestRender() {
    this.grid?.requestRender?.();
  }
  /**
   * Request a lightweight style update without rebuilding DOM.
   * Use this instead of requestRender() when only CSS classes need updating.
   */
  requestAfterRender() {
    this.grid?.requestAfterRender?.();
  }
  /**
   * Get the current rows from the grid.
   */
  get rows() {
    return this.grid?.rows ?? [];
  }
  /**
   * Get the original unfiltered/unprocessed rows from the grid.
   * Use this when you need all source data regardless of active filters.
   */
  get sourceRows() {
    return this.grid?.sourceRows ?? [];
  }
  /**
   * Get the current columns from the grid.
   */
  get columns() {
    return this.grid?.columns ?? [];
  }
  /**
   * Get only visible columns from the grid (excludes hidden).
   * Use this for rendering that needs to match the grid template.
   */
  get visibleColumns() {
    return this.grid?.visibleColumns ?? [];
  }
  /**
   * Get the shadow root of the grid.
   */
  get shadowRoot() {
    return this.grid?.shadowRoot ?? null;
  }
  /**
   * Get the disconnect signal for event listener cleanup.
   * This signal is aborted when the grid disconnects from the DOM.
   * Use this when adding event listeners that should be cleaned up automatically.
   *
   * Best for:
   * - Document/window-level listeners added in attach()
   * - Listeners on the grid element itself
   * - Any listener that should persist across renders
   *
   * Not needed for:
   * - Listeners on elements created in afterRender() (removed with element)
   *
   * @example
   * element.addEventListener('click', handler, { signal: this.disconnectSignal });
   * document.addEventListener('keydown', handler, { signal: this.disconnectSignal });
   */
  get disconnectSignal() {
    return this.grid?.disconnectSignal;
  }
  /**
   * Get the grid-level icons configuration.
   * Returns merged icons (user config + defaults).
   */
  get gridIcons() {
    const e = this.grid?.gridConfig?.icons ?? {};
    return { ..._, ...e };
  }
  /**
   * Resolve an icon value to string or HTMLElement.
   * Checks plugin config first, then grid-level icons, then defaults.
   *
   * @param iconKey - The icon key in GridIcons (e.g., 'expand', 'collapse')
   * @param pluginOverride - Optional plugin-level override
   * @returns The resolved icon value
   */
  resolveIcon(e, t) {
    return t !== void 0 ? t : this.gridIcons[e];
  }
  /**
   * Set an icon value on an element.
   * Handles both string (text/HTML) and HTMLElement values.
   *
   * @param element - The element to set the icon on
   * @param icon - The icon value (string or HTMLElement)
   */
  setIcon(e, t) {
    typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
  }
  /**
   * Log a warning message.
   */
  warn(e) {
    console.warn(`[tbw-grid:${this.name}] ${e}`);
  }
  // #endregion
}
function q(f, e, t = !1) {
  const r = f[e.field];
  if (e.operator === "blank")
    return r == null || r === "";
  if (e.operator === "notBlank")
    return r != null && r !== "";
  if (r == null) return !1;
  const l = String(r), a = t ? l : l.toLowerCase(), i = t ? String(e.value) : String(e.value).toLowerCase();
  switch (e.operator) {
    // Text operators
    case "contains":
      return a.includes(i);
    case "notContains":
      return !a.includes(i);
    case "equals":
      return a === i;
    case "notEquals":
      return a !== i;
    case "startsWith":
      return a.startsWith(i);
    case "endsWith":
      return a.endsWith(i);
    // Number/Date operators (use raw numeric values)
    case "lessThan":
      return Number(r) < Number(e.value);
    case "lessThanOrEqual":
      return Number(r) <= Number(e.value);
    case "greaterThan":
      return Number(r) > Number(e.value);
    case "greaterThanOrEqual":
      return Number(r) >= Number(e.value);
    case "between":
      return Number(r) >= Number(e.value) && Number(r) <= Number(e.valueTo);
    // Set operators
    case "in":
      return Array.isArray(e.value) && e.value.includes(r);
    case "notIn":
      return Array.isArray(e.value) && !e.value.includes(r);
    default:
      return !0;
  }
}
function B(f, e, t = !1) {
  return e.length ? f.filter((r) => e.every((l) => q(r, l, t))) : f;
}
function z(f) {
  return JSON.stringify(
    f.map((e) => ({
      field: e.field,
      operator: e.operator,
      value: e.value,
      valueTo: e.valueTo
    }))
  );
}
function H(f, e) {
  const t = /* @__PURE__ */ new Set();
  for (const r of f) {
    const l = r[e];
    l != null && t.add(l);
  }
  return [...t].sort((r, l) => typeof r == "number" && typeof l == "number" ? r - l : String(r).localeCompare(String(l)));
}
const K = '.header-cell.filtered:before{content:"";position:absolute;top:4px;right:4px;width:6px;height:6px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}.tbw-filter-btn{display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:4px;opacity:.4;transition:opacity .15s;color:inherit;vertical-align:middle}.tbw-filter-btn:hover,.tbw-filter-btn.active{opacity:1}.tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}', $ = ".tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, 4px));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:12px;z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, 13px)}.tbw-filter-search{margin-bottom:8px}.tbw-filter-search-input{width:100%;padding:6px 10px;background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, 4px);font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:4px 2px;margin-bottom:8px;border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-action-btn{background:transparent;border:none;color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));cursor:pointer;font-size:12px;padding:2px 0}.tbw-filter-action-btn:hover{text-decoration:underline}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:8px;max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:8px;padding:4px 2px;cursor:pointer;border-radius:3px}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:8px 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:8px;padding-top:8px;border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:6px 12px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:6px 12px;background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}";
class x extends V {
  name = "filtering";
  version = "1.0.0";
  get defaultConfig() {
    return {
      debounceMs: 300,
      caseSensitive: !1,
      trimInput: !0,
      useWorker: !0
    };
  }
  // #region Internal State
  filters = /* @__PURE__ */ new Map();
  cachedResult = null;
  cacheKey = null;
  openPanelField = null;
  panelElement = null;
  searchText = /* @__PURE__ */ new Map();
  excludedValues = /* @__PURE__ */ new Map();
  panelAbortController = null;
  // For panel-scoped listeners
  globalStylesInjected = !1;
  // Virtualization constants for filter value list
  static LIST_ITEM_HEIGHT = 28;
  static LIST_OVERSCAN = 3;
  static LIST_BYPASS_THRESHOLD = 50;
  // Don't virtualize if < 50 items
  // #endregion
  // #region Lifecycle
  attach(e) {
    super.attach(e), this.injectGlobalStyles();
  }
  detach() {
    this.filters.clear(), this.cachedResult = null, this.cacheKey = null, this.openPanelField = null, this.panelElement && (this.panelElement.remove(), this.panelElement = null), this.searchText.clear(), this.excludedValues.clear(), this.panelAbortController?.abort(), this.panelAbortController = null;
  }
  // #endregion
  // #region Hooks
  processRows(e) {
    const t = [...this.filters.values()];
    if (!t.length) return [...e];
    const r = z(t);
    if (this.cacheKey === r && this.cachedResult)
      return this.cachedResult;
    const l = B([...e], t, this.config.caseSensitive);
    return this.cachedResult = l, this.cacheKey = r, l;
  }
  afterRender() {
    const e = this.shadowRoot;
    if (!e) return;
    e.querySelectorAll('[part~="header-cell"]').forEach((r) => {
      const l = r.getAttribute("data-col");
      if (l === null) return;
      const a = this.columns[parseInt(l, 10)];
      if (!a || a.filterable === !1 || r.querySelector(".tbw-filter-btn")) return;
      const i = a.field;
      if (!i) return;
      const n = document.createElement("button");
      n.className = "tbw-filter-btn", n.setAttribute("aria-label", `Filter ${a.header ?? i}`), n.innerHTML = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', this.filters.has(i) && (n.classList.add("active"), r.classList.add("filtered")), n.addEventListener("click", (u) => {
        u.stopPropagation(), this.toggleFilterPanel(i, a, n);
      }), r.appendChild(n);
    });
  }
  // #endregion
  // #region Public API
  /**
   * Set a filter on a specific field.
   * Pass null to remove the filter.
   */
  setFilter(e, t) {
    t === null ? this.filters.delete(e) : this.filters.set(e, { ...t, field: e }), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
      filters: [...this.filters.values()],
      filteredRowCount: 0
      // Will be accurate after processRows
    }), this.requestRender();
  }
  /**
   * Get the current filter for a field.
   */
  getFilter(e) {
    return this.filters.get(e);
  }
  /**
   * Get all active filters.
   */
  getFilters() {
    return [...this.filters.values()];
  }
  /**
   * Alias for getFilters() to match functional API naming.
   */
  getFilterModel() {
    return this.getFilters();
  }
  /**
   * Set filters from an array (replaces all existing filters).
   */
  setFilterModel(e) {
    this.filters.clear();
    for (const t of e)
      this.filters.set(t.field, t);
    this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
      filters: [...this.filters.values()],
      filteredRowCount: 0
    }), this.requestRender();
  }
  /**
   * Clear all filters.
   */
  clearAllFilters() {
    this.filters.clear(), this.excludedValues.clear(), this.searchText.clear(), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
      filters: [],
      filteredRowCount: this.rows.length
    }), this.requestRender();
  }
  /**
   * Clear filter for a specific field.
   */
  clearFieldFilter(e) {
    this.filters.delete(e), this.excludedValues.delete(e), this.searchText.delete(e), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
      filters: [...this.filters.values()],
      filteredRowCount: 0
    }), this.requestRender();
  }
  /**
   * Check if a field has an active filter.
   */
  isFieldFiltered(e) {
    return this.filters.has(e);
  }
  /**
   * Get the count of filtered rows (from cache).
   */
  getFilteredRowCount() {
    return this.cachedResult?.length ?? this.rows.length;
  }
  /**
   * Get all active filters (alias for getFilters).
   */
  getActiveFilters() {
    return this.getFilters();
  }
  /**
   * Get unique values for a field (for set filter dropdowns).
   * Uses sourceRows to include all values regardless of current filter.
   */
  getUniqueValues(e) {
    return H(this.sourceRows, e);
  }
  // #endregion
  // #region Private Methods
  /**
   * Inject global styles for filter panel (rendered in document.body)
   */
  injectGlobalStyles() {
    if (this.globalStylesInjected) return;
    if (document.getElementById("tbw-filter-panel-styles")) {
      this.globalStylesInjected = !0;
      return;
    }
    const e = document.createElement("style");
    e.id = "tbw-filter-panel-styles", e.textContent = $, document.head.appendChild(e), this.globalStylesInjected = !0;
  }
  /**
   * Toggle the filter panel for a field
   */
  toggleFilterPanel(e, t, r) {
    if (this.openPanelField === e) {
      this.closeFilterPanel();
      return;
    }
    this.closeFilterPanel();
    const l = document.createElement("div");
    l.className = "tbw-filter-panel", this.panelElement = l, this.openPanelField = e;
    const a = H(this.sourceRows, e);
    let i = this.excludedValues.get(e);
    i || (i = /* @__PURE__ */ new Set(), this.excludedValues.set(e, i));
    const n = this.searchText.get(e) ?? "", u = {
      field: e,
      column: t,
      uniqueValues: a,
      excludedValues: i,
      searchText: n,
      applySetFilter: (h) => {
        this.applySetFilter(e, h), this.closeFilterPanel();
      },
      applyTextFilter: (h, E, C) => {
        this.applyTextFilter(e, h, E, C), this.closeFilterPanel();
      },
      clearFilter: () => {
        this.clearFieldFilter(e), this.closeFilterPanel();
      },
      closePanel: () => this.closeFilterPanel()
    };
    let g = !1;
    this.config.filterPanelRenderer && (this.config.filterPanelRenderer(l, u), g = l.children.length > 0), g || this.renderDefaultFilterPanel(l, u, a, i), document.body.appendChild(l), this.positionPanel(l, r), this.panelAbortController = new AbortController(), setTimeout(() => {
      document.addEventListener(
        "click",
        (h) => {
          !l.contains(h.target) && h.target !== r && this.closeFilterPanel();
        },
        { signal: this.panelAbortController?.signal }
      );
    }, 0);
  }
  /**
   * Close the filter panel
   */
  closeFilterPanel() {
    this.panelElement && (this.panelElement.remove(), this.panelElement = null), this.openPanelField = null, this.panelAbortController?.abort(), this.panelAbortController = null;
  }
  /**
   * Position the panel below the button
   */
  positionPanel(e, t) {
    const r = t.getBoundingClientRect();
    e.style.position = "fixed", e.style.top = `${r.bottom + 4}px`, e.style.left = `${r.left}px`, requestAnimationFrame(() => {
      const l = e.getBoundingClientRect();
      l.right > window.innerWidth - 8 && (e.style.left = `${window.innerWidth - l.width - 8}px`), l.bottom > window.innerHeight - 8 && (e.style.top = `${r.top - l.height - 4}px`);
    });
  }
  /**
   * Render the default filter panel content
   */
  renderDefaultFilterPanel(e, t, r, l) {
    const { field: a } = t, i = document.createElement("div");
    i.className = "tbw-filter-search";
    const n = document.createElement("input");
    n.type = "text", n.placeholder = "Search...", n.className = "tbw-filter-search-input", n.value = this.searchText.get(a) ?? "", i.appendChild(n), e.appendChild(i);
    const u = document.createElement("div");
    u.className = "tbw-filter-actions";
    const g = document.createElement("label");
    g.className = "tbw-filter-value-item", g.style.padding = "0", g.style.margin = "0";
    const h = document.createElement("input");
    h.type = "checkbox", h.className = "tbw-filter-checkbox";
    const E = document.createElement("span");
    E.textContent = "Select All", g.appendChild(h), g.appendChild(E), u.appendChild(g);
    const C = () => {
      const s = [...v.values()], d = s.every((c) => c), p = s.every((c) => !c);
      h.checked = d, h.indeterminate = !d && !p;
    };
    h.addEventListener("change", () => {
      const s = h.checked;
      for (const d of v.keys())
        v.set(d, s);
      C(), F();
    }), e.appendChild(u);
    const m = document.createElement("div");
    m.className = "tbw-filter-values";
    const R = document.createElement("div");
    R.className = "tbw-filter-values-spacer", m.appendChild(R);
    const b = document.createElement("div");
    b.className = "tbw-filter-values-content", m.appendChild(b);
    const v = /* @__PURE__ */ new Map();
    r.forEach((s) => {
      const d = s == null ? "__null__" : String(s);
      v.set(d, !l.has(s));
    }), C();
    let y = [];
    const I = (s, d) => {
      const p = s == null ? "(Blank)" : String(s), c = s == null ? "__null__" : String(s), o = document.createElement("label");
      o.className = "tbw-filter-value-item", o.style.position = "absolute", o.style.top = `${d * x.LIST_ITEM_HEIGHT}px`, o.style.left = "0", o.style.right = "0", o.style.height = `${x.LIST_ITEM_HEIGHT}px`, o.style.boxSizing = "border-box";
      const w = document.createElement("input");
      w.type = "checkbox", w.className = "tbw-filter-checkbox", w.checked = v.get(c) ?? !0, w.dataset.value = c, w.addEventListener("change", () => {
        v.set(c, w.checked), C();
      });
      const A = document.createElement("span");
      return A.textContent = p, o.appendChild(w), o.appendChild(A), o;
    }, F = () => {
      const s = y.length, d = m.clientHeight, p = m.scrollTop;
      if (R.style.height = `${s * x.LIST_ITEM_HEIGHT}px`, P(s, x.LIST_BYPASS_THRESHOLD / 3)) {
        b.innerHTML = "", b.style.transform = "translateY(0px)", y.forEach((o, w) => {
          b.appendChild(I(o, w));
        });
        return;
      }
      const c = M({
        totalRows: s,
        viewportHeight: d,
        scrollTop: p,
        rowHeight: x.LIST_ITEM_HEIGHT,
        overscan: x.LIST_OVERSCAN
      });
      b.style.transform = `translateY(${c.offsetY}px)`, b.innerHTML = "";
      for (let o = c.start; o < c.end; o++)
        b.appendChild(I(y[o], o - c.start));
    }, L = (s) => {
      const d = s.toLowerCase();
      if (y = r.filter((p) => {
        const c = p == null ? "(Blank)" : String(p);
        return !s || c.toLowerCase().includes(d);
      }), y.length === 0) {
        R.style.height = "0px", b.innerHTML = "";
        const p = document.createElement("div");
        p.className = "tbw-filter-no-match", p.textContent = "No matching values", b.appendChild(p);
        return;
      }
      F();
    };
    m.addEventListener(
      "scroll",
      () => {
        y.length > 0 && F();
      },
      { passive: !0 }
    ), L(n.value), e.appendChild(m);
    let N;
    n.addEventListener("input", () => {
      clearTimeout(N), N = setTimeout(() => {
        this.searchText.set(a, n.value), L(n.value);
      }, this.config.debounceMs ?? 150);
    });
    const S = document.createElement("div");
    S.className = "tbw-filter-buttons";
    const T = document.createElement("button");
    T.className = "tbw-filter-apply-btn", T.textContent = "Apply", T.addEventListener("click", () => {
      const s = [];
      for (const [d, p] of v)
        if (!p)
          if (d === "__null__")
            s.push(null);
          else {
            const c = r.find((o) => String(o) === d);
            s.push(c !== void 0 ? c : d);
          }
      t.applySetFilter(s);
    }), S.appendChild(T);
    const k = document.createElement("button");
    k.className = "tbw-filter-clear-btn", k.textContent = "Clear Filter", k.addEventListener("click", () => {
      t.clearFilter();
    }), S.appendChild(k), e.appendChild(S);
  }
  /**
   * Apply a set filter (exclude values)
   */
  applySetFilter(e, t) {
    this.excludedValues.set(e, new Set(t)), t.length === 0 ? this.filters.delete(e) : this.filters.set(e, {
      field: e,
      type: "set",
      operator: "notIn",
      value: t
    }), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
      filters: [...this.filters.values()],
      filteredRowCount: 0
    }), this.requestRender();
  }
  /**
   * Apply a text filter
   */
  applyTextFilter(e, t, r, l) {
    this.filters.set(e, {
      field: e,
      type: "text",
      operator: t,
      value: r,
      valueTo: l
    }), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
      filters: [...this.filters.values()],
      filteredRowCount: 0
    }), this.requestRender();
  }
  // #endregion
  // #region Column State Hooks
  /**
   * Return filter state for a column if it has an active filter.
   */
  getColumnState(e) {
    const t = this.filters.get(e);
    if (t)
      return {
        filter: {
          type: t.type,
          operator: t.operator,
          value: t.value,
          valueTo: t.valueTo
        }
      };
  }
  /**
   * Apply filter state from column state.
   */
  applyColumnState(e, t) {
    if (!t.filter) {
      this.filters.delete(e);
      return;
    }
    const r = {
      field: e,
      type: t.filter.type,
      operator: t.filter.operator,
      value: t.filter.value,
      valueTo: t.filter.valueTo
    };
    this.filters.set(e, r), this.cachedResult = null, this.cacheKey = null;
  }
  // #endregion
  // #region Styles
  styles = K;
  // #endregion
}
export {
  x as FilteringPlugin
};
//# sourceMappingURL=index.js.map
