(a: TValue | null, b: TValue | null): number {
+ if (a == null) {
+ return -1;
+ }
+ if (b == null) {
+ return 1;
+ }
+ const valueA = _parseBigIntOrNull(a);
+ const valueB = _parseBigIntOrNull(b);
+ if (valueA != null && valueB != null) {
+ if (valueA === valueB) {
+ return 0;
+ }
+ return valueA > valueB ? 1 : -1;
+ }
+ return String(a).localeCompare(String(b));
+}
+
function isValidDate(value: any): boolean {
return value instanceof Date && !isNaN(value.getTime());
}
@@ -72,6 +92,7 @@ type FilterParamCallback = (
type FilterParamsDefMap = CheckDataTypes<{
number: FilterParamCallback;
+ bigint: FilterParamCallback;
boolean: FilterParamCallback;
date: FilterParamCallback;
dateString: FilterParamCallback;
@@ -84,6 +105,7 @@ type FilterParamsDefMap = CheckDataTypes<{
// using an object here to enforce dev to not forget to implement new types as they are added
const filterParamsForEachDataType: FilterParamsDefMap = {
number: () => undefined,
+ bigint: () => undefined,
boolean: () => ({
maxNumConditions: 1,
debounceMs: 0,
@@ -128,6 +150,7 @@ const filterParamsForEachDataType: FilterParamsDefMap = {
// using an object here to enforce dev to not forget to implement new types as they are added
const setFilterParamsForEachDataType: FilterParamsDefMap = {
number: () => ({ comparator: setFilterNumberComparator }),
+ bigint: () => ({ comparator: setFilterBigIntComparator }),
boolean: ({ t }) => ({
valueFormatter: (params: ValueFormatterParams) =>
_exists(params.value) ? t(String(params.value), params.value ? 'True' : 'False') : t('blanks', '(Blanks)'),
@@ -221,6 +244,7 @@ const defaultFilters: Record = {
dateString: 'agDateColumnFilter',
dateTime: 'agDateColumnFilter',
dateTimeString: 'agDateColumnFilter',
+ bigint: 'agBigIntColumnFilter',
number: 'agNumberColumnFilter',
object: 'agTextColumnFilter',
text: 'agTextColumnFilter',
@@ -232,6 +256,7 @@ const defaultFloatingFilters: Record = {
dateString: 'agDateColumnFloatingFilter',
dateTime: 'agDateColumnFloatingFilter',
dateTimeString: 'agDateColumnFloatingFilter',
+ bigint: 'agBigIntColumnFloatingFilter',
number: 'agNumberColumnFloatingFilter',
object: 'agTextColumnFloatingFilter',
text: 'agTextColumnFloatingFilter',
diff --git a/packages/ag-grid-community/src/filter/filterLocaleText.ts b/packages/ag-grid-community/src/filter/filterLocaleText.ts
index 4007a4abe29..07e9eb0c66f 100644
--- a/packages/ag-grid-community/src/filter/filterLocaleText.ts
+++ b/packages/ag-grid-community/src/filter/filterLocaleText.ts
@@ -8,6 +8,7 @@ const FILTER_LOCALE_TEXT = {
cancelFilter: 'Cancel',
textFilter: 'Text Filter',
numberFilter: 'Number Filter',
+ bigintFilter: 'BigInt Filter',
dateFilter: 'Date Filter',
setFilter: 'Set Filter',
filterOoo: 'Filter...',
diff --git a/packages/ag-grid-community/src/filter/filterModule.ts b/packages/ag-grid-community/src/filter/filterModule.ts
index 6f70206282b..2a6aba24ad3 100644
--- a/packages/ag-grid-community/src/filter/filterModule.ts
+++ b/packages/ag-grid-community/src/filter/filterModule.ts
@@ -26,6 +26,9 @@ import { FilterManager } from './filterManager';
import { FilterMenuFactory } from './filterMenuFactory';
import { FilterValueService } from './filterValueService';
import { ReadOnlyFloatingFilter } from './floating/provided/readOnlyFloatingFilter';
+import { BigIntFilter } from './provided/bigInt/bigIntFilter';
+import { BigIntFilterHandler } from './provided/bigInt/bigIntFilterHandler';
+import { BigIntFloatingFilter } from './provided/bigInt/bigIntFloatingFilter';
import { DateFilter } from './provided/date/dateFilter';
import { DateFilterHandler } from './provided/date/dateFilterHandler';
import { DateFloatingFilter } from './provided/date/dateFloatingFilter';
@@ -155,6 +158,27 @@ export const NumberFilterModule: _ModuleWithoutApi = {
},
};
+/**
+ * @feature Filtering -> BigInt Filter
+ */
+export const BigIntFilterModule: _ModuleWithoutApi = {
+ moduleName: 'BigIntFilter',
+ version: VERSION,
+ dependsOn: [ColumnFilterModule],
+ userComponents: {
+ agBigIntColumnFilter: {
+ classImp: BigIntFilter,
+ params: {
+ useForm: true,
+ } as FilterWrapperParams,
+ },
+ agBigIntColumnFloatingFilter: BigIntFloatingFilter,
+ },
+ dynamicBeans: {
+ agBigIntColumnFilterHandler: BigIntFilterHandler,
+ },
+};
+
/**
* @feature Filtering -> Date Filter
*/
diff --git a/packages/ag-grid-community/src/filter/floating/floatingFilterMapper.ts b/packages/ag-grid-community/src/filter/floating/floatingFilterMapper.ts
index 9bf24c4c0ca..02a96a24e8d 100644
--- a/packages/ag-grid-community/src/filter/floating/floatingFilterMapper.ts
+++ b/packages/ag-grid-community/src/filter/floating/floatingFilterMapper.ts
@@ -21,6 +21,7 @@ export function _getDefaultFloatingFilterType(
agMultiColumnFilter: 'agMultiColumnFloatingFilter',
agGroupColumnFilter: 'agGroupColumnFloatingFilter',
agNumberColumnFilter: 'agNumberColumnFloatingFilter',
+ agBigIntColumnFilter: 'agBigIntColumnFloatingFilter',
agDateColumnFilter: 'agDateColumnFloatingFilter',
agTextColumnFilter: 'agTextColumnFloatingFilter',
};
diff --git a/packages/ag-grid-community/src/filter/floating/provided/simpleFloatingFilter.ts b/packages/ag-grid-community/src/filter/floating/provided/simpleFloatingFilter.ts
index b3a20b77824..f7ec357cd10 100644
--- a/packages/ag-grid-community/src/filter/floating/provided/simpleFloatingFilter.ts
+++ b/packages/ag-grid-community/src/filter/floating/provided/simpleFloatingFilter.ts
@@ -33,7 +33,7 @@ export abstract class SimpleFloatingFilter>;
+
+export class BigIntFilter extends SimpleFilter<
+ BigIntFilterModel,
+ bigint,
+ GridInputTextField,
+ BigIntFilterDisplayParams
+> {
+ private readonly eValuesFrom: GridInputTextField[] = [];
+ private readonly eValuesTo: GridInputTextField[] = [];
+
+ public readonly filterType = 'bigint' as const;
+
+ constructor() {
+ super('bigintFilter', mapValuesFromBigIntFilterModel, DEFAULT_BIGINT_FILTER_OPTIONS);
+ }
+
+ protected override defaultDebounceMs = 500;
+
+ public override afterGuiAttached(params?: IAfterGuiAttachedParams | undefined): void {
+ super.afterGuiAttached(params);
+
+ this.refreshInputValidation();
+ }
+
+ protected override shouldKeepInvalidInputState(): boolean {
+ return !_isBrowserFirefox() && this.hasInvalidInputs() && this.getConditionTypes().includes('inRange');
+ }
+
+ private refreshInputValidation(): void {
+ for (let i = 0; i < this.eValuesFrom.length; i++) {
+ const from = this.eValuesFrom[i];
+ const to = this.eValuesTo[i];
+ this.refreshInputPairValidation(from, to);
+ }
+ }
+
+ private refreshInputPairValidation(from: GridInputTextField, to: GridInputTextField, isFrom = false): void {
+ const localeKey = getValidityMessageKey(_parseBigIntOrNull(from), _parseBigIntOrNull(to), isFrom);
+ const validityMessage = localeKey
+ ? this.translate(localeKey, [String(isFrom ? to.getValue() : from.getValue())])
+ : '';
+ (isFrom ? from : to).setCustomValidity(validityMessage);
+ (isFrom ? to : from).setCustomValidity('');
+ if (validityMessage.length > 0) {
+ this.beans.ariaAnnounce.announceValue(validityMessage, 'dateFilter');
+ }
+ }
+
+ protected override getState(): { isInvalid: boolean } {
+ return { isInvalid: this.hasInvalidInputs() };
+ }
+
+ protected override areStatesEqual(stateA?: { isInvalid: boolean }, stateB?: { isInvalid: boolean }): boolean {
+ return (stateA?.isInvalid ?? false) === (stateB?.isInvalid ?? false);
+ }
+
+ public override refresh(legacyNewParams: ProvidedFilterParams): boolean {
+ const result = super.refresh(legacyNewParams);
+
+ const { state: newState, additionalEventAttributes } = legacyNewParams as unknown as BigIntFilterDisplayParams;
+ const oldState = this.state;
+
+ const fromAction = additionalEventAttributes?.fromAction;
+ const forceRefreshValidation = fromAction && fromAction != 'apply';
+
+ if (
+ forceRefreshValidation ||
+ newState.model !== oldState.model ||
+ !this.areStatesEqual(newState.state, oldState.state)
+ ) {
+ this.refreshInputValidation();
+ }
+
+ return result;
+ }
+
+ protected override setElementValue(
+ element: GridInputTextField,
+ value: bigint | null,
+ fromFloatingFilter?: boolean
+ ): void {
+ super.setElementValue(element, value as any, fromFloatingFilter);
+ if (value === null) {
+ element.setCustomValidity('');
+ }
+ }
+
+ protected createEValue(): HTMLElement {
+ const { params, eValuesFrom, eValuesTo } = this;
+ const allowedCharPattern = getAllowedCharPattern(params);
+
+ const eCondition = _createElement({ tag: 'div', cls: 'ag-filter-body', role: 'presentation' });
+
+ const from = this.createFromToElement(eCondition, eValuesFrom, 'from', allowedCharPattern);
+ const to = this.createFromToElement(eCondition, eValuesTo, 'to', allowedCharPattern);
+
+ const getFieldChangedListener = (fromEl: GridInputTextField, toEl: GridInputTextField, isFrom: boolean) => () =>
+ this.refreshInputPairValidation(fromEl, toEl, isFrom);
+
+ const fromListener = getFieldChangedListener(from, to, true);
+ from.onValueChange(fromListener);
+ from.addGuiEventListener('focusin', fromListener);
+
+ const toListener = getFieldChangedListener(from, to, false);
+ to.onValueChange(toListener);
+ to.addGuiEventListener('focusin', toListener);
+
+ return eCondition;
+ }
+
+ private createFromToElement(
+ eCondition: HTMLElement,
+ eValues: GridInputTextField[],
+ fromTo: string,
+ allowedCharPattern: string | null
+ ): GridInputTextField {
+ const eValue = this.createManagedBean(
+ allowedCharPattern ? new AgInputTextField({ allowedCharPattern }) : new AgInputTextField()
+ );
+ eValue.addCss(`ag-filter-${fromTo}`);
+ eValue.addCss('ag-filter-filter');
+ eValues.push(eValue);
+ eCondition.appendChild(eValue.getGui());
+ return eValue;
+ }
+
+ protected removeEValues(startPosition: number, deleteCount?: number): void {
+ const removeComps = (eGui: GridInputTextField[]) => this.removeComponents(eGui, startPosition, deleteCount);
+
+ removeComps(this.eValuesFrom);
+ removeComps(this.eValuesTo);
+ }
+
+ protected getValues(position: number): Tuple {
+ const result: Tuple = [];
+ this.forEachPositionInput(position, (element, index, _elPosition, numberOfInputs) => {
+ if (index < numberOfInputs) {
+ result.push(_parseBigIntOrNull(element.getValue() ?? null));
+ }
+ });
+
+ return result;
+ }
+
+ protected areSimpleModelsEqual(aSimple: BigIntFilterModel, bSimple: BigIntFilterModel): boolean {
+ return (
+ aSimple.filter === bSimple.filter && aSimple.filterTo === bSimple.filterTo && aSimple.type === bSimple.type
+ );
+ }
+
+ protected createCondition(position: number): BigIntFilterModel {
+ const type = this.getConditionType(position);
+ const model: BigIntFilterModel = {
+ filterType: this.filterType,
+ type,
+ };
+
+ const values = this.getValues(position);
+ if (values.length > 0) {
+ model.filter = String(values[0]);
+ }
+ if (values.length > 1) {
+ model.filterTo = String(values[1]);
+ }
+
+ return model;
+ }
+
+ protected override removeConditionsAndOperators(startPosition: number, deleteCount?: number | undefined): void {
+ if (this.hasInvalidInputs()) {
+ return;
+ }
+
+ return super.removeConditionsAndOperators(startPosition, deleteCount);
+ }
+
+ protected override getInputs(position: number): Tuple {
+ const { eValuesFrom, eValuesTo } = this;
+ if (position >= eValuesFrom.length) {
+ return [null, null];
+ }
+ return [eValuesFrom[position], eValuesTo[position]];
+ }
+
+ protected override hasInvalidInputs(): boolean {
+ let invalidInputs = false;
+ this.forEachInput((element) => (invalidInputs ||= !element.getInputElement().validity.valid));
+ return invalidInputs;
+ }
+
+ protected override positionHasInvalidInputs(position: number): boolean {
+ let invalidInputs = false;
+ this.forEachPositionInput(position, (element) => (invalidInputs ||= !element.getInputElement().validity.valid));
+ return invalidInputs;
+ }
+
+ protected override canApply(_model: BigIntFilterModel | ICombinedSimpleModel | null): boolean {
+ return !this.hasInvalidInputs();
+ }
+}
+
+function getValidityMessageKey(
+ fromValue: bigint | null,
+ toValue: bigint | null,
+ isFrom: boolean
+): FilterLocaleTextKey | null {
+ const isInvalid = fromValue != null && toValue != null && fromValue >= toValue;
+ if (!isInvalid) {
+ return null;
+ }
+ return `strict${isFrom ? 'Max' : 'Min'}ValueValidation`;
+}
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterConstants.ts b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterConstants.ts
new file mode 100644
index 00000000000..12e7009501e
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterConstants.ts
@@ -0,0 +1,13 @@
+import type { ISimpleFilterModelType } from '../iSimpleFilter';
+
+export const DEFAULT_BIGINT_FILTER_OPTIONS: ISimpleFilterModelType[] = [
+ 'equals',
+ 'notEqual',
+ 'greaterThan',
+ 'greaterThanOrEqual',
+ 'lessThan',
+ 'lessThanOrEqual',
+ 'inRange',
+ 'blank',
+ 'notBlank',
+];
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterHandler.test.ts b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterHandler.test.ts
new file mode 100644
index 00000000000..cd81004b80d
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterHandler.test.ts
@@ -0,0 +1,104 @@
+import { BigIntFilterHandler } from './bigIntFilterHandler';
+
+describe('BigIntFilterHandler', () => {
+ let handler: BigIntFilterHandler;
+
+ beforeEach(() => {
+ handler = new BigIntFilterHandler();
+ (handler as any).createManagedBean = (bean: any) => bean;
+ (handler as any).addDestroyFunc = () => {};
+ });
+
+ const createParams = (filterParams: any = {}, model: any = null): any => ({
+ filterParams: {
+ filterOptions: [
+ 'equals',
+ 'notEqual',
+ 'lessThan',
+ 'lessThanOrEqual',
+ 'greaterThan',
+ 'greaterThanOrEqual',
+ 'inRange',
+ 'blank',
+ 'notBlank',
+ ],
+ ...filterParams,
+ },
+ model,
+ getValue: (node: any) => node.value,
+ onModelChange: () => {},
+ });
+
+ it('should pass for equal bigint values', () => {
+ const params = createParams({}, { filterType: 'bigint', type: 'equals', filter: '10' });
+ handler.init(params);
+
+ expect(handler.doesFilterPass({ node: { value: 10n }, model: params.model } as any)).toBe(true);
+ expect(handler.doesFilterPass({ node: { value: 11n }, model: params.model } as any)).toBe(false);
+ });
+
+ it('should handle null cell values with default settings', () => {
+ const params = createParams({}, { filterType: 'bigint', type: 'equals', filter: '10' });
+ handler.init(params);
+
+ expect(handler.doesFilterPass({ node: { value: null }, model: params.model } as any)).toBe(false);
+ });
+
+ it('should handle null cell values with includeBlanksInEquals', () => {
+ const params = createParams(
+ { includeBlanksInEquals: true },
+ { filterType: 'bigint', type: 'equals', filter: '10' }
+ );
+ handler.init(params);
+
+ expect(handler.doesFilterPass({ node: { value: null }, model: params.model } as any)).toBe(true);
+ });
+
+ it('should handle invalid cell values (mixed data)', () => {
+ const params = createParams({}, { filterType: 'bigint', type: 'equals', filter: '10' });
+ handler.init(params);
+
+ // Equals should still return false for mixed types because of === in comparator
+ expect(handler.doesFilterPass({ node: { value: 10 }, model: params.model } as any)).toBe(false);
+ expect(handler.doesFilterPass({ node: { value: '10' }, model: params.model } as any)).toBe(false);
+
+ // But lessThan should work if we updated isValid to be more robust
+ const lessThanParams = createParams({}, { filterType: 'bigint', type: 'lessThan', filter: '20' });
+ handler.init(lessThanParams);
+ expect(handler.doesFilterPass({ node: { value: 10 }, model: lessThanParams.model } as any)).toBe(true);
+ expect(handler.doesFilterPass({ node: { value: '10' }, model: lessThanParams.model } as any)).toBe(true);
+ });
+
+ it('should handle null and undefined values in model', () => {
+ // null filter value should pass everything for equals (standard SimpleFilter behavior)
+ const params = createParams({}, { filterType: 'bigint', type: 'equals', filter: null });
+ handler.init(params);
+ expect(handler.doesFilterPass({ node: { value: 10n }, model: params.model } as any)).toBe(true);
+
+ const undefinedParams = createParams({}, { filterType: 'bigint', type: 'equals', filter: undefined });
+ handler.init(undefinedParams);
+ expect(handler.doesFilterPass({ node: { value: 10n }, model: undefinedParams.model } as any)).toBe(true);
+ });
+
+ it('should handle inRange with null filterTo', () => {
+ const params = createParams({}, { filterType: 'bigint', type: 'inRange', filter: '10', filterTo: null });
+ handler.init(params);
+
+ // 15n should not pass inRange(10n, null) because null < 15n returns 1 (compareToResult > 0)
+ expect(handler.doesFilterPass({ node: { value: 15n }, model: params.model } as any)).toBe(false);
+ });
+
+ it('should handle blank and notBlank types correctly', () => {
+ const params = createParams({}, { filterType: 'bigint', type: 'blank' });
+ handler.init(params);
+
+ expect(handler.doesFilterPass({ node: { value: null }, model: params.model } as any)).toBe(true);
+ expect(handler.doesFilterPass({ node: { value: undefined }, model: params.model } as any)).toBe(true);
+ expect(handler.doesFilterPass({ node: { value: 10n }, model: params.model } as any)).toBe(false);
+
+ const notBlankParams = createParams({}, { filterType: 'bigint', type: 'notBlank' });
+ handler.init(notBlankParams);
+ expect(handler.doesFilterPass({ node: { value: null }, model: notBlankParams.model } as any)).toBe(false);
+ expect(handler.doesFilterPass({ node: { value: 10n }, model: notBlankParams.model } as any)).toBe(true);
+ });
+});
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterHandler.ts b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterHandler.ts
new file mode 100644
index 00000000000..e6ebd446137
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterHandler.ts
@@ -0,0 +1,30 @@
+import { _parseBigIntOrNull } from '../../../agStack/utils/bigInt';
+import type { Comparator } from '../iScalarFilter';
+import { ScalarFilterHandler } from '../scalarFilterHandler';
+import { DEFAULT_BIGINT_FILTER_OPTIONS } from './bigIntFilterConstants';
+import { BigIntFilterModelFormatter } from './bigIntFilterModelFormatter';
+import { mapValuesFromBigIntFilterModel } from './bigIntFilterUtils';
+import type { BigIntFilterModel, IBigIntFilterParams } from './iBigIntFilter';
+
+export class BigIntFilterHandler extends ScalarFilterHandler {
+ public readonly filterType = 'bigint' as const;
+ protected readonly FilterModelFormatterClass = BigIntFilterModelFormatter;
+
+ constructor() {
+ super(mapValuesFromBigIntFilterModel, DEFAULT_BIGINT_FILTER_OPTIONS);
+ }
+
+ protected override comparator(): Comparator {
+ return (left: bigint, right: bigint): number => {
+ if (left === right) {
+ return 0;
+ }
+
+ return left < right ? 1 : -1;
+ };
+ }
+
+ protected override isValid(value: bigint): boolean {
+ return _parseBigIntOrNull(value) !== null;
+ }
+}
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterModelFormatter.ts b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterModelFormatter.ts
new file mode 100644
index 00000000000..1abf97972cd
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterModelFormatter.ts
@@ -0,0 +1,53 @@
+import { _parseBigIntOrNull } from '../../../agStack/utils/bigInt';
+import type { OptionsFactory } from '../optionsFactory';
+import { SCALAR_FILTER_TYPE_KEYS, SimpleFilterModelFormatter } from '../simpleFilterModelFormatter';
+import type { BigIntFilterModel, IBigIntFilterParams } from './iBigIntFilter';
+
+export class BigIntFilterModelFormatter extends SimpleFilterModelFormatter<
+ IBigIntFilterParams,
+ typeof SCALAR_FILTER_TYPE_KEYS,
+ bigint
+> {
+ protected readonly filterTypeKeys = SCALAR_FILTER_TYPE_KEYS;
+
+ constructor(optionsFactory: OptionsFactory, filterParams: IBigIntFilterParams) {
+ super(optionsFactory, filterParams, filterParams.bigintFormatter);
+ }
+
+ protected conditionToString(
+ condition: BigIntFilterModel,
+ forToolPanel: boolean,
+ isRange: boolean,
+ customDisplayKey: string | undefined,
+ customDisplayName: string | undefined
+ ): string {
+ const { filter, filterTo, type } = condition;
+ const format = this.formatValue.bind(this);
+
+ const parsedFrom = _parseBigIntOrNull(filter);
+ const parsedTo = _parseBigIntOrNull(filterTo);
+ if (forToolPanel) {
+ const valueForToolPanel = this.conditionForToolPanel(
+ type,
+ isRange,
+ () => format(parsedFrom),
+ () => format(parsedTo),
+ customDisplayKey,
+ customDisplayName
+ );
+ if (valueForToolPanel != null) {
+ return valueForToolPanel;
+ }
+ }
+
+ if (isRange) {
+ return `${format(parsedFrom)}-${format(parsedTo)}`;
+ }
+
+ if (filter != null) {
+ return format(parsedFrom);
+ }
+
+ return `${type}`;
+ }
+}
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterUtils.ts b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterUtils.ts
new file mode 100644
index 00000000000..68ddbeacfe6
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFilterUtils.ts
@@ -0,0 +1,17 @@
+import { _parseBigIntOrNull } from '../../../agStack/utils/bigInt';
+import type { Tuple } from '../iSimpleFilter';
+import type { OptionsFactory } from '../optionsFactory';
+import { getNumberOfInputs } from '../simpleFilterUtils';
+import type { BigIntFilterModel, IBigIntFilterParams } from './iBigIntFilter';
+
+export function getAllowedCharPattern(filterParams?: IBigIntFilterParams): string | null {
+ return filterParams?.allowedCharPattern ?? null;
+}
+
+export function mapValuesFromBigIntFilterModel(
+ filterModel: BigIntFilterModel | null,
+ optionsFactory: OptionsFactory
+): Tuple {
+ const { filter, filterTo, type } = filterModel || {};
+ return [_parseBigIntOrNull(filter), _parseBigIntOrNull(filterTo)].slice(0, getNumberOfInputs(type, optionsFactory));
+}
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFloatingFilter.ts b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFloatingFilter.ts
new file mode 100644
index 00000000000..18069f9c442
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/bigIntFloatingFilter.ts
@@ -0,0 +1,46 @@
+import { _parseBigIntOrNull } from '../../../agStack/utils/bigInt';
+import { FloatingFilterTextInputService } from '../../floating/provided/floatingFilterTextInputService';
+import type { FloatingFilterInputService } from '../../floating/provided/iFloatingFilterInputService';
+import { TextInputFloatingFilter } from '../../floating/provided/textInputFloatingFilter';
+import { DEFAULT_BIGINT_FILTER_OPTIONS } from './bigIntFilterConstants';
+import { BigIntFilterModelFormatter } from './bigIntFilterModelFormatter';
+import { getAllowedCharPattern } from './bigIntFilterUtils';
+import type { BigIntFilterModel, BigIntFilterParams, IBigIntFloatingFilterParams } from './iBigIntFilter';
+
+export class BigIntFloatingFilter extends TextInputFloatingFilter {
+ protected readonly FilterModelFormatterClass = BigIntFilterModelFormatter;
+ private allowedCharPattern: string | null;
+ private bigintParser: BigIntFilterParams['bigintParser'] | undefined;
+ protected readonly filterType = 'bigint';
+ protected readonly defaultOptions = DEFAULT_BIGINT_FILTER_OPTIONS;
+
+ protected override updateParams(params: IBigIntFloatingFilterParams): void {
+ const filterParams = params.filterParams as BigIntFilterParams;
+ const allowedCharPattern = getAllowedCharPattern(filterParams);
+ if (allowedCharPattern !== this.allowedCharPattern) {
+ this.recreateFloatingFilterInputService(params);
+ }
+ this.bigintParser = filterParams?.bigintParser;
+ super.updateParams(params);
+ }
+
+ protected createFloatingFilterInputService(params: IBigIntFloatingFilterParams): FloatingFilterInputService {
+ const filterParams = params.filterParams as BigIntFilterParams;
+ this.allowedCharPattern = getAllowedCharPattern(filterParams);
+ this.bigintParser = filterParams?.bigintParser;
+
+ const config = this.allowedCharPattern ? { allowedCharPattern: this.allowedCharPattern } : undefined;
+ return this.createManagedBean(new FloatingFilterTextInputService({ config }));
+ }
+
+ protected override convertValue(value: string | null | undefined): TValue | null {
+ if (value == null || value === '') {
+ return null;
+ }
+
+ if (this.bigintParser) {
+ return this.bigintParser(value) as TValue | null;
+ }
+ return _parseBigIntOrNull(value) as TValue | null;
+ }
+}
diff --git a/packages/ag-grid-community/src/filter/provided/bigInt/iBigIntFilter.ts b/packages/ag-grid-community/src/filter/provided/bigInt/iBigIntFilter.ts
new file mode 100644
index 00000000000..95fd6892d2f
--- /dev/null
+++ b/packages/ag-grid-community/src/filter/provided/bigInt/iBigIntFilter.ts
@@ -0,0 +1,47 @@
+import type { IFilterParams } from '../../../interfaces/iFilter';
+import type { IScalarFilterParams } from '../iScalarFilter';
+import type { ISimpleFilterModel } from '../iSimpleFilter';
+import type { ITextInputFloatingFilterParams } from '../text/iTextFilter';
+
+export interface BigIntFilterModel extends ISimpleFilterModel {
+ /** Filter type is always `'bigint'` */
+ filterType?: 'bigint';
+ /**
+ * The bigint value(s) associated with the filter.
+ * Custom filters can have no values (hence both are optional).
+ * Range filter has two values (from and to), where `filter` acts as a `from` value.
+ */
+ filter?: string | null;
+ /**
+ * Range filter `to` value.
+ */
+ filterTo?: string | null;
+}
+
+/**
+ * Parameters provided by the grid to the `init` method of a `BigIntFilter`.
+ * Do not use in `colDef.filterParams` - see `IBigIntFilterParams` instead.
+ */
+export type BigIntFilterParams = IBigIntFilterParams & IFilterParams;
+
+/**
+ * Parameters used in `colDef.filterParams` to configure a BigInt Filter (`agBigIntColumnFilter`).
+ */
+export interface IBigIntFilterParams extends IScalarFilterParams {
+ /**
+ * When specified, the input field will be of type `text`, and this will be used as a regex of all the characters that are allowed to be typed.
+ * This will be compared against any typed character and prevent the character from appearing in the input if it does not match.
+ */
+ allowedCharPattern?: string;
+ /**
+ * Typically used alongside `allowedCharPattern`, this provides a custom parser to convert the value entered in the filter inputs into a bigint that can be used for comparisons.
+ */
+ bigintParser?: (text: string | null) => bigint | null;
+ /**
+ * Typically used alongside `allowedCharPattern`, this provides a custom formatter to convert the bigint value in the filter model
+ * into a string to be used in the filter input. This is the inverse of the `bigintParser`.
+ */
+ bigintFormatter?: (value: bigint | null) => string | null;
+}
+
+export interface IBigIntFloatingFilterParams extends ITextInputFloatingFilterParams {}
diff --git a/packages/ag-grid-community/src/filter/provided/iProvidedFilter.ts b/packages/ag-grid-community/src/filter/provided/iProvidedFilter.ts
index 227ba5c3a41..806370e5dbc 100644
--- a/packages/ag-grid-community/src/filter/provided/iProvidedFilter.ts
+++ b/packages/ag-grid-community/src/filter/provided/iProvidedFilter.ts
@@ -45,7 +45,7 @@ export interface IProvidedFilterParams {
export interface IProvidedFilter extends IFilter {
/** The type of filter. Matches the `filterType` property in the filter model */
- readonly filterType: 'text' | 'number' | 'date' | 'set' | 'multi';
+ readonly filterType: 'text' | 'number' | 'bigint' | 'date' | 'set' | 'multi';
/**
* Applies the model shown in the UI (so that `getModel()` will now return what was in the UI
* when `applyModel()` was called).
diff --git a/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts b/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts
index 0abdea07871..1a09dc187e5 100644
--- a/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts
+++ b/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts
@@ -18,7 +18,7 @@ export type JoinOperator = 'AND' | 'OR';
/** Interface contract for the public aspects of the SimpleFilter implementation(s). */
export interface ISimpleFilter extends IProvidedFilter, IFloatingFilterParent {
- readonly filterType: 'text' | 'number' | 'date';
+ readonly filterType: 'text' | 'number' | 'bigint' | 'date';
}
export interface IFilterPlaceholderFunctionParams {
diff --git a/packages/ag-grid-community/src/filter/provided/providedFilter.ts b/packages/ag-grid-community/src/filter/provided/providedFilter.ts
index 03cbb95365b..25ead490cdf 100644
--- a/packages/ag-grid-community/src/filter/provided/providedFilter.ts
+++ b/packages/ag-grid-community/src/filter/provided/providedFilter.ts
@@ -71,7 +71,7 @@ export abstract class ProvidedFilter<
protected abstract areNonNullModelsEqual(a: M, b: M): boolean;
/** Used to get the filter type for filter models. */
- public abstract readonly filterType: 'text' | 'number' | 'date' | 'set' | 'multi';
+ public abstract readonly filterType: 'text' | 'number' | 'bigint' | 'date' | 'set' | 'multi';
public postConstruct(): void {
const element: ElementParams = {
diff --git a/packages/ag-grid-community/src/filter/provided/simpleFilter.ts b/packages/ag-grid-community/src/filter/provided/simpleFilter.ts
index ca1963b5150..6f1fa91c3bd 100644
--- a/packages/ag-grid-community/src/filter/provided/simpleFilter.ts
+++ b/packages/ag-grid-community/src/filter/provided/simpleFilter.ts
@@ -58,7 +58,7 @@ export abstract class SimpleFilter<
extends ProvidedFilter, V, P>
implements ISimpleFilter
{
- public abstract override readonly filterType: 'number' | 'text' | 'date';
+ public abstract override readonly filterType: 'number' | 'bigint' | 'text' | 'date';
protected readonly eTypes: GridSelect[] = [];
protected readonly eJoinPanels: HTMLElement[] = [];
diff --git a/packages/ag-grid-community/src/filter/provided/simpleFilterHandler.ts b/packages/ag-grid-community/src/filter/provided/simpleFilterHandler.ts
index 6120488e6c4..064f25e15c3 100644
--- a/packages/ag-grid-community/src/filter/provided/simpleFilterHandler.ts
+++ b/packages/ag-grid-community/src/filter/provided/simpleFilterHandler.ts
@@ -27,7 +27,7 @@ export abstract class SimpleFilterHandler<
implements FilterHandler, TParams>
{
/** Used to get the filter type for filter models. */
- public abstract readonly filterType: 'text' | 'number' | 'date';
+ public abstract readonly filterType: 'text' | 'number' | 'bigint' | 'date';
protected abstract readonly FilterModelFormatterClass: new (
optionsFactory: OptionsFactory,
diff --git a/packages/ag-grid-community/src/interfaces/advancedFilterModel.ts b/packages/ag-grid-community/src/interfaces/advancedFilterModel.ts
index a8c535e3f56..37cdbb6f486 100644
--- a/packages/ag-grid-community/src/interfaces/advancedFilterModel.ts
+++ b/packages/ag-grid-community/src/interfaces/advancedFilterModel.ts
@@ -55,6 +55,17 @@ export interface NumberAdvancedFilterModel {
filter?: number;
}
+/** Represents a single filter condition for a bigint column */
+interface BigIntAdvancedFilterModel {
+ filterType: 'bigint';
+ /** The ID of the column being filtered. */
+ colId: string;
+ /** The filter option that is being applied. */
+ type: ScalarAdvancedFilterModelType;
+ /** The value to filter on. */
+ filter?: string;
+}
+
/** Represents a single filter condition for a date column */
export interface DateAdvancedFilterModel {
filterType: 'date';
@@ -125,6 +136,7 @@ export type ColumnAdvancedFilterModel =
| DateStringAdvancedFilterModel
| DateTimeAdvancedFilterModel
| DateTimeStringAdvancedFilterModel
+ | BigIntAdvancedFilterModel
| NumberAdvancedFilterModel
| TextAdvancedFilterModel;
diff --git a/packages/ag-grid-community/src/interfaces/iFilter.ts b/packages/ag-grid-community/src/interfaces/iFilter.ts
index 5d626216d6d..70c77b1d31e 100644
--- a/packages/ag-grid-community/src/interfaces/iFilter.ts
+++ b/packages/ag-grid-community/src/interfaces/iFilter.ts
@@ -95,7 +95,7 @@ export type FilterHandlers {
/**
* Filter component to use for this column.
- * - Set to the name of a provided filter: `agNumberColumnFilter`, `agTextColumnFilter`, `agDateColumnFilter`, `agMultiColumnFilter`, `agSetColumnFilter`.
+ * - Set to the name of a provided filter: `agNumberColumnFilter`, `agBigIntColumnFilter`, `agTextColumnFilter`, `agDateColumnFilter`, `agMultiColumnFilter`, `agSetColumnFilter`.
* - Set to a custom filter `FilterDisplay`
*/
component: any;
@@ -124,7 +124,7 @@ export interface IFilterDef {
/**
* Filter to use for this column.
* - Set to `true` to use the default filter.
- * - Set to the name of a provided filter: `agNumberColumnFilter`, `agTextColumnFilter`, `agDateColumnFilter`, `agMultiColumnFilter`, `agSetColumnFilter`.
+ * - Set to the name of a provided filter: `agNumberColumnFilter`, `agBigIntColumnFilter`, `agTextColumnFilter`, `agDateColumnFilter`, `agMultiColumnFilter`, `agSetColumnFilter`.
* - Set to a custom filter `IFilterComp` when `enableFilterHandlers = false`.
* - Set to a `ColumnFilter` when `enableFilterHandlers = true`
*/
diff --git a/packages/ag-grid-community/src/interfaces/iGroupEditService.ts b/packages/ag-grid-community/src/interfaces/iGroupEditService.ts
index 134e627ccbe..21e4e277d4e 100644
--- a/packages/ag-grid-community/src/interfaces/iGroupEditService.ts
+++ b/packages/ag-grid-community/src/interfaces/iGroupEditService.ts
@@ -6,7 +6,6 @@ export interface IGroupEditService {
isGroupingDrop(rowsDrop: RowsDrop): boolean;
dropGroupEdit(rowsDrop: RowsDrop): boolean;
canDropRow(row: IRowNode, rowsDrop: RowsDrop): boolean;
- canDropStartGroup(target: IRowNode | null | undefined): boolean;
fixRowsDrop(rowsDrop: RowsDrop, canSetParent: boolean, moving: boolean, yDelta: number): void;
stopDragging(final: boolean): void;
csrmFirstLeaf(parent: IRowNode | null): IRowNode | null;
diff --git a/packages/ag-grid-community/src/interfaces/iModule.ts b/packages/ag-grid-community/src/interfaces/iModule.ts
index 7742ce07a1d..eed2db6eaef 100644
--- a/packages/ag-grid-community/src/interfaces/iModule.ts
+++ b/packages/ag-grid-community/src/interfaces/iModule.ts
@@ -148,6 +148,7 @@ export type CommunityModuleName =
| 'Locale'
| 'NumberEditor'
| 'NumberFilter'
+ | 'BigIntFilter'
| 'Pagination'
| 'PinnedRow'
| 'QuickFilter'
@@ -231,6 +232,7 @@ export type AgModuleName =
| 'LocaleModule'
| 'NumberEditorModule'
| 'NumberFilterModule'
+ | 'BigIntFilterModule'
| 'PaginationModule'
| 'PinnedRowModule'
| 'QuickFilterModule'
diff --git a/packages/ag-grid-community/src/interfaces/iNewFiltersToolPanel.ts b/packages/ag-grid-community/src/interfaces/iNewFiltersToolPanel.ts
index e0f81ab8d8d..907b6fec8b2 100644
--- a/packages/ag-grid-community/src/interfaces/iNewFiltersToolPanel.ts
+++ b/packages/ag-grid-community/src/interfaces/iNewFiltersToolPanel.ts
@@ -15,7 +15,7 @@ export interface SelectableFilterDef {
/**
* Filter to use for this column.
* - Set to `true` to use the default filter.
- * - Set to the name of a provided filter: `agNumberColumnFilter`, `agTextColumnFilter`, `agDateColumnFilter`, `agMultiColumnFilter`, `agSetColumnFilter`.
+ * - Set to the name of a provided filter: `agNumberColumnFilter`, `agBigIntColumnFilter`, `agTextColumnFilter`, `agDateColumnFilter`, `agMultiColumnFilter`, `agSetColumnFilter`.
* - Set to a `ColumnFilter`
*/
filter: any;
diff --git a/packages/ag-grid-community/src/main-internal.ts b/packages/ag-grid-community/src/main-internal.ts
index 2557ea2ad17..7771fcc35b2 100644
--- a/packages/ag-grid-community/src/main-internal.ts
+++ b/packages/ag-grid-community/src/main-internal.ts
@@ -126,6 +126,7 @@ export {
} from './agStack/utils/aria';
export { _EmptyArray, _areEqual, _flatten, _last, _removeAllFromArray, _removeFromArray } from './agStack/utils/array';
export { _isBrowserFirefox, _isBrowserSafari, _isIOSUserAgent } from './agStack/utils/browser';
+export { _parseBigIntOrNull } from './agStack/utils/bigInt';
export { MONTHS as _MONTHS, _getDateParts, _parseDateTimeFromString, _serialiseDate } from './agStack/utils/date';
export {
_getActiveDomElement,
diff --git a/packages/ag-grid-community/src/main.ts b/packages/ag-grid-community/src/main.ts
index 021b830c7ca..20ff7587af2 100644
--- a/packages/ag-grid-community/src/main.ts
+++ b/packages/ag-grid-community/src/main.ts
@@ -193,6 +193,13 @@ export {
NumberFilterParams,
} from './filter/provided/number/iNumberFilter';
export type { NumberFilter } from './filter/provided/number/numberFilter';
+export {
+ IBigIntFilterParams,
+ IBigIntFloatingFilterParams,
+ BigIntFilterModel,
+ BigIntFilterParams,
+} from './filter/provided/bigInt/iBigIntFilter';
+export type { BigIntFilter } from './filter/provided/bigInt/bigIntFilter';
export { ProvidedFilter } from './filter/provided/providedFilter';
export {
ITextFilterParams,
@@ -939,6 +946,7 @@ export {
CustomFilterModule,
DateFilterModule,
ExternalFilterModule,
+ BigIntFilterModule,
NumberFilterModule,
QuickFilterModule,
TextFilterModule,
diff --git a/packages/ag-grid-community/src/sort/rowNodeSorter.ts b/packages/ag-grid-community/src/sort/rowNodeSorter.ts
index 983b50d905c..ab16f303657 100644
--- a/packages/ag-grid-community/src/sort/rowNodeSorter.ts
+++ b/packages/ag-grid-community/src/sort/rowNodeSorter.ts
@@ -194,10 +194,13 @@ const defaultGetLeaf = (row: RowNode): RowNode | undefined => {
}
};
-const absoluteValueTransformer = (value: any): number | null => {
+const absoluteValueTransformer = (value: any): number | bigint | null => {
if (!value) {
return value;
}
+ if (typeof value === 'bigint') {
+ return value < 0n ? -value : value;
+ }
const numberValue = Number(value);
return isNaN(numberValue) ? value : Math.abs(numberValue);
};
diff --git a/packages/ag-grid-community/src/validation/resolvableModuleNames.ts b/packages/ag-grid-community/src/validation/resolvableModuleNames.ts
index 292013916d3..a320a9a3a31 100644
--- a/packages/ag-grid-community/src/validation/resolvableModuleNames.ts
+++ b/packages/ag-grid-community/src/validation/resolvableModuleNames.ts
@@ -9,6 +9,7 @@ import type { RowModelType } from '../interfaces/iRowModel';
const ALL_COLUMN_FILTERS = [
'TextFilter',
'NumberFilter',
+ 'BigIntFilter',
'DateFilter',
'SetFilter',
'MultiFilter',
diff --git a/packages/ag-grid-community/src/validation/rules/dynamicBeanValidations.ts b/packages/ag-grid-community/src/validation/rules/dynamicBeanValidations.ts
index b6eeac075ee..62fe8521adb 100644
--- a/packages/ag-grid-community/src/validation/rules/dynamicBeanValidations.ts
+++ b/packages/ag-grid-community/src/validation/rules/dynamicBeanValidations.ts
@@ -21,6 +21,7 @@ export const DYNAMIC_BEAN_MODULES: Record
agMultiColumnFilterHandler: 'MultiFilter',
agGroupColumnFilterHandler: 'GroupFilter',
agNumberColumnFilterHandler: 'NumberFilter',
+ agBigIntColumnFilterHandler: 'BigIntFilter',
agDateColumnFilterHandler: 'DateFilter',
agTextColumnFilterHandler: 'TextFilter',
};
diff --git a/packages/ag-grid-community/src/validation/rules/userCompValidations.ts b/packages/ag-grid-community/src/validation/rules/userCompValidations.ts
index 8649d61d3bc..eea655b9b87 100644
--- a/packages/ag-grid-community/src/validation/rules/userCompValidations.ts
+++ b/packages/ag-grid-community/src/validation/rules/userCompValidations.ts
@@ -31,10 +31,12 @@ export const USER_COMP_MODULES: Record
agReadOnlyFloatingFilter: 'CustomFilter',
agTextColumnFilter: 'TextFilter',
agNumberColumnFilter: 'NumberFilter',
+ agBigIntColumnFilter: 'BigIntFilter',
agDateColumnFilter: 'DateFilter',
agDateInput: 'DateFilter',
agTextColumnFloatingFilter: 'TextFilter',
agNumberColumnFloatingFilter: 'NumberFilter',
+ agBigIntColumnFloatingFilter: 'BigIntFilter',
agDateColumnFloatingFilter: 'DateFilter',
agFormulaCellEditor: 'Formula',
agCellEditor: 'TextEditor',
diff --git a/packages/ag-grid-community/src/valueService/valueService.ts b/packages/ag-grid-community/src/valueService/valueService.ts
index 07854a0f84b..b7bdeaebbc8 100644
--- a/packages/ag-grid-community/src/valueService/valueService.ts
+++ b/packages/ag-grid-community/src/valueService/valueService.ts
@@ -305,12 +305,17 @@ export class ValueService extends BeanStub implements NamedBean {
return undefined;
}
- public parseValue(column: AgColumn, rowNode: IRowNode | null, newValue: any, oldValue: any): any {
+ public parseValue(
+ column: AgColumn,
+ rowNode: IRowNode | null,
+ newValue: TValueNew,
+ oldValue: TValueOld
+ ): TValue {
const colDef = column.getColDef();
// we do not allow parsing of formulas
if (colDef.allowFormula && this.beans.formula?.isFormula(newValue)) {
- return newValue;
+ return newValue as TValue;
}
const valueParser = colDef.valueParser;
@@ -320,7 +325,7 @@ export class ValueService extends BeanStub implements NamedBean {
node: rowNode,
data: rowNode?.data,
oldValue,
- newValue,
+ newValue: newValue as any,
colDef,
column,
});
@@ -329,7 +334,7 @@ export class ValueService extends BeanStub implements NamedBean {
}
return this.expressionSvc?.evaluate(valueParser, params);
}
- return newValue;
+ return newValue as unknown as TValue;
}
public getDeleteValue(column: AgColumn, rowNode: IRowNode): any {
diff --git a/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterExpressionService.ts b/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterExpressionService.ts
index f3af8eea4b5..76f975a58fe 100644
--- a/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterExpressionService.ts
+++ b/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterExpressionService.ts
@@ -2,6 +2,7 @@ import type {
AgColumn,
BaseCellDataType,
BeanCollection,
+ BooleanAdvancedFilterModel,
ColumnAdvancedFilterModel,
ColumnModel,
ColumnNameService,
@@ -35,14 +36,22 @@ export class AdvancedFilterExpressionService extends BeanStub implements NamedBe
private colNames: ColumnNameService;
private dataTypeSvc?: DataTypeService;
- private readonly filterOperandGetters: Record string | null> = {
+ private readonly filterOperandGetters: Record<
+ BaseCellDataType,
+ (model: { filter?: string | number; colId: string }) => string | null
+ > = {
number: (model) => _toStringOrNull(model.filter) ?? '',
+ bigint: (model) => _toStringOrNull(model.filter) ?? '',
date: (model) => {
const column = this.colModel.getColDefCol(model.colId);
if (!column) {
return null;
}
- return this.valueSvc.formatValue(column, null, _parseDateTimeFromString(model.filter));
+ return this.valueSvc.formatValue(
+ column,
+ null,
+ _parseDateTimeFromString(_toStringOrNull(model.filter) ?? '')
+ );
},
dateTime: (model) => this.filterOperandGetters.date(model),
dateString: (model) => {
@@ -52,7 +61,8 @@ export class AdvancedFilterExpressionService extends BeanStub implements NamedBe
}
const { filter } = model;
const dateFormatFn = this.dataTypeSvc?.getDateFormatterFunction(column);
- const dateStringStringValue = dateFormatFn?.(_parseDateTimeFromString(filter) ?? undefined) ?? filter;
+ const dateStringStringValue =
+ dateFormatFn?.(_parseDateTimeFromString(_toStringOrNull(model.filter) ?? '') ?? undefined) ?? filter;
return this.valueSvc.formatValue(column, null, dateStringStringValue);
},
dateTimeString: (model) => this.filterOperandGetters.dateString(model),
@@ -66,9 +76,10 @@ export class AdvancedFilterExpressionService extends BeanStub implements NamedBe
(op: string, cln: AgColumn, dt: BaseCellDataType) => number | string | null
> = {
number: (operand) => (_exists(operand) ? Number(operand) : null),
+ bigint: (operand) => operand,
date: (operand, column, baseCellDataType) =>
_serialiseDate(
- this.valueSvc.parseValue(column, null, operand, undefined),
+ this.valueSvc.parseValue(column, null, operand, undefined) as Date,
!!this.dataTypeSvc?.getDateIncludesTimeFlag(baseCellDataType)
),
dateTime: (...args) => this.operandModelValueGetters.date(...args),
@@ -138,13 +149,15 @@ export class AdvancedFilterExpressionService extends BeanStub implements NamedBe
}
public getOperandDisplayValue(model: ColumnAdvancedFilterModel, skipFormatting?: boolean): string {
- const { filter } = model as any;
+ const { filter, filterType } = model as Exclude;
if (filter == null) {
return '';
}
- let operand1 = this.filterOperandGetters[model.filterType](model);
- if (model.filterType !== 'number') {
+ let operand1 = this.filterOperandGetters[filterType](
+ model as Exclude
+ );
+ if (filterType !== 'number' && filterType !== 'bigint') {
operand1 ??= _toStringOrNull(filter) ?? '';
if (!skipFormatting) {
operand1 = `"${operand1}"`;
@@ -350,6 +363,7 @@ export class AdvancedFilterExpressionService extends BeanStub implements NamedBe
boolean: new BooleanFilterExpressionOperators({ translate }),
object: new TextFilterExpressionOperators({ translate }),
number: new ScalarFilterExpressionOperators({ translate, equals: (v, o) => v === o }),
+ bigint: new ScalarFilterExpressionOperators({ translate, equals: (v, o) => v === o }),
date: new ScalarFilterExpressionOperators(dateOperatorsParams),
dateString: new ScalarFilterExpressionOperators(dateOperatorsParams),
dateTime: new ScalarFilterExpressionOperators(dateOperatorsParams),
diff --git a/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterLocaleText.ts b/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterLocaleText.ts
index f251cfd6ae4..afb0f79da0f 100644
--- a/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterLocaleText.ts
+++ b/packages/ag-grid-enterprise/src/advancedFilter/advancedFilterLocaleText.ts
@@ -43,6 +43,7 @@ export const ADVANCED_FILTER_LOCALE_TEXT = {
advancedFilterValidationInvalidOption: 'Option not found',
advancedFilterValidationMissingQuote: 'Value is missing an end quote',
advancedFilterValidationNotANumber: 'Value is not a number',
+ advancedFilterValidationNotABigInt: 'Value is not a big integer',
advancedFilterValidationInvalidDate: 'Value is not a valid date',
advancedFilterValidationMissingCondition: 'Condition is missing',
advancedFilterValidationJoinOperatorMismatch: 'Join operators within a condition must be the same',
diff --git a/packages/ag-grid-enterprise/src/advancedFilter/builder/conditionPillWrapperComp.ts b/packages/ag-grid-enterprise/src/advancedFilter/builder/conditionPillWrapperComp.ts
index 5a0730091c4..0287c2479c9 100644
--- a/packages/ag-grid-enterprise/src/advancedFilter/builder/conditionPillWrapperComp.ts
+++ b/packages/ag-grid-enterprise/src/advancedFilter/builder/conditionPillWrapperComp.ts
@@ -116,7 +116,7 @@ export class ConditionPillWrapperComp extends Component;
- const key = (typeof filter === 'number' ? _toStringOrNull(filter) : filter) ?? '';
+ const key = (typeof filter === 'number' || typeof filter === 'bigint' ? _toStringOrNull(filter) : filter) ?? '';
this.eOperandPill = this.createPill({
key,
// Convert from the input format to display format.
diff --git a/packages/ag-grid-enterprise/src/advancedFilter/builder/inputPillComp.ts b/packages/ag-grid-enterprise/src/advancedFilter/builder/inputPillComp.ts
index 9c9e26c138a..dfde65c5bb8 100644
--- a/packages/ag-grid-enterprise/src/advancedFilter/builder/inputPillComp.ts
+++ b/packages/ag-grid-enterprise/src/advancedFilter/builder/inputPillComp.ts
@@ -34,6 +34,7 @@ const inputComponentDescriptors: {
[S in BaseCellDataType]: [SupportedComponent] | [SupportedComponent, (instance: SupportedInstances) => void];
} = {
number: [AgInputNumberField],
+ bigint: [AgInputTextField],
boolean: [AgInputTextField],
object: [AgInputTextField],
text: [AgInputTextField],
@@ -180,7 +181,8 @@ export class InputPillComp extends Component {
private renderValue(): void {
let value: string;
- const { displayValue, eLabel } = this;
+ const { displayValue, eLabel, params } = this;
+ const { type } = params;
const { classList } = eLabel;
classList.remove(
'ag-advanced-filter-builder-value-empty',
@@ -190,7 +192,7 @@ export class InputPillComp extends Component {
if (!_exists(displayValue)) {
value = this.advFilterExpSvc.translate('advancedFilterBuilderEnterValue');
classList.add('ag-advanced-filter-builder-value-empty');
- } else if (this.params.type === 'number') {
+ } else if (type === 'number' || type === 'bigint') {
value = displayValue;
classList.add('ag-advanced-filter-builder-value-number');
} else {
diff --git a/packages/ag-grid-enterprise/src/advancedFilter/colFilterExpressionParser.ts b/packages/ag-grid-enterprise/src/advancedFilter/colFilterExpressionParser.ts
index 54a8cfb2022..5e6fe8640d4 100644
--- a/packages/ag-grid-enterprise/src/advancedFilter/colFilterExpressionParser.ts
+++ b/packages/ag-grid-enterprise/src/advancedFilter/colFilterExpressionParser.ts
@@ -1,4 +1,5 @@
import type { AdvancedFilterModel, AgColumn, BaseCellDataType } from 'ag-grid-community';
+import { _parseBigIntOrNull } from 'ag-grid-community';
import type { ADVANCED_FILTER_LOCALE_TEXT } from './advancedFilterLocaleText';
import type { AutocompleteEntry, AutocompleteListParams } from './autocomplete/autocompleteParams';
@@ -187,13 +188,22 @@ class OperandParser implements Parser {
private modelValue: number | string;
private validationMessage: string | null = null;
- private readonly filterValidationSetters: Record any> = {
+ private readonly filterValidationSetters: Record<
+ BaseCellDataType,
+ (modelValue: string | number | bigint | null) => any
+ > = {
number: () => {
if (this.quotes || isNaN(this.modelValue as number)) {
this.valid = false;
this.validationMessage = this.params.advFilterExpSvc.translate('advancedFilterValidationNotANumber');
}
},
+ bigint: () => {
+ if (this.quotes || _parseBigIntOrNull(this.modelValue) === null) {
+ this.valid = false;
+ this.validationMessage = this.params.advFilterExpSvc.translate('advancedFilterValidationNotABigInt');
+ }
+ },
date: (modelValue) => {
if (modelValue == null) {
this.valid = false;
@@ -295,12 +305,24 @@ export class ColFilterExpressionParser {
private operatorParser: OperatorParser | undefined;
private operandParser: OperandParser | undefined;
- private readonly operandValueGetters: Record any> = {
+ private readonly operandValueGetters: {
+ number: (a: string) => number;
+ bigint: (a: string) => bigint;
+ date: (a: string) => Date;
+ dateString: (a: string) => Date;
+ dateTime: (a: string) => Date;
+ dateTimeString: (a: string) => Date;
+ boolean: (a: string) => string;
+ object: (a: string) => string;
+ text: (a: string) => string;
+ } = {
number: Number,
- date: (operand) => this.params.valueSvc.parseValue(this.columnParser!.column!, null, operand, undefined),
- dateString: (...args) => this.operandValueGetters.date(...args),
- dateTime: (...args) => this.operandValueGetters.date(...args),
- dateTimeString: (...args) => this.operandValueGetters.date(...args),
+ bigint: (operand) => _parseBigIntOrNull(operand)!,
+ date: (operand) =>
+ this.params.valueSvc.parseValue(this.columnParser!.column!, null, operand, undefined) as Date,
+ dateString: (operand) => this.operandValueGetters.date(operand),
+ dateTime: (operand) => this.operandValueGetters.date(operand),
+ dateTimeString: (operand) => this.operandValueGetters.date(operand),
boolean: (operand) => operand,
object: (operand) => operand,
text: (operand) => operand,
@@ -614,7 +636,7 @@ export class ColFilterExpressionParser {
}
private doesOperandNeedQuotes(baseCellDataType?: BaseCellDataType): boolean {
- return baseCellDataType !== 'number';
+ return baseCellDataType !== 'number' && baseCellDataType !== 'bigint';
}
private addToListAndGetIndex(list: T[], value: T): number {
diff --git a/packages/ag-grid-enterprise/src/advancedFilter/filterExpressionOperators.ts b/packages/ag-grid-enterprise/src/advancedFilter/filterExpressionOperators.ts
index 83a46cfb427..b36607561c9 100644
--- a/packages/ag-grid-enterprise/src/advancedFilter/filterExpressionOperators.ts
+++ b/packages/ag-grid-enterprise/src/advancedFilter/filterExpressionOperators.ts
@@ -40,6 +40,7 @@ export abstract class FilterExpressionOperators
dateTimeString: DataTypeFilterExpressionOperators;
text: DataTypeFilterExpressionOperators;
number: DataTypeFilterExpressionOperators;
+ bigint: DataTypeFilterExpressionOperators;
boolean: DataTypeFilterExpressionOperators;
date: DataTypeFilterExpressionOperators;
dateString: DataTypeFilterExpressionOperators;
@@ -177,7 +178,7 @@ interface ScalarFilterExpressionOperatorsParams extends FilterE
equals: (value: ConvertedTValue, operand: ConvertedTValue) => boolean;
}
-export class ScalarFilterExpressionOperators
+export class ScalarFilterExpressionOperators
implements DataTypeFilterExpressionOperators
{
public operators: { [operator: string]: FilterExpressionOperator };
diff --git a/packages/ag-grid-enterprise/src/aiToolkit/features/advancedFilterFeatureSchema.ts b/packages/ag-grid-enterprise/src/aiToolkit/features/advancedFilterFeatureSchema.ts
index 0344eb84af5..7da36009ed9 100644
--- a/packages/ag-grid-enterprise/src/aiToolkit/features/advancedFilterFeatureSchema.ts
+++ b/packages/ag-grid-enterprise/src/aiToolkit/features/advancedFilterFeatureSchema.ts
@@ -18,6 +18,7 @@ export const buildAdvancedFilterFeatureSchema = ({ colModel, dataTypeSvc }: Bean
dateTime: [],
dateTimeString: [],
number: [],
+ bigint: [],
text: [],
};
@@ -200,6 +201,32 @@ const buildNumberFilterSchema = (colIds: string[]) => {
});
};
+const buildBigIntFilterSchema = (colIds: string[]) => {
+ return s.object({
+ filterType: s.literal('bigint', 'Filter type identifier for bigint column filters'),
+ colId: s.enum(colIds, 'Column identifier for the bigint column to filter'),
+ filter: s
+ .string({
+ pattern: '^-?\\d+$',
+ description: 'BigInt value to filter by',
+ })
+ .nullable(),
+ type: s.enum(
+ [
+ 'equals',
+ 'notEqual',
+ 'lessThan',
+ 'lessThanOrEqual',
+ 'greaterThan',
+ 'greaterThanOrEqual',
+ 'blank',
+ 'notBlank',
+ ],
+ 'BigInt filter operation type'
+ ),
+ });
+};
+
const buildTextFilterSchema = (colIds: string[]) => {
return s.object({
filterType: s.literal('text', 'Filter type identifier for text column filters'),
@@ -220,5 +247,6 @@ const DataTypeSchemaBuilders: Record any
dateTime: buildDateTimeFilterSchema,
dateTimeString: buildDateTimeStringFilterSchema,
number: buildNumberFilterSchema,
+ bigint: buildBigIntFilterSchema,
text: buildTextFilterSchema,
};
diff --git a/packages/ag-grid-enterprise/src/pivot/pivotStage.ts b/packages/ag-grid-enterprise/src/pivot/pivotStage.ts
index 9db106d1003..35edc29bb54 100644
--- a/packages/ag-grid-enterprise/src/pivot/pivotStage.ts
+++ b/packages/ag-grid-enterprise/src/pivot/pivotStage.ts
@@ -12,7 +12,7 @@ import type {
ValueService,
_IRowNodePivotStage,
} from 'ag-grid-community';
-import { BeanStub, _missing } from 'ag-grid-community';
+import { BeanStub, _jsonEquals, _missing } from 'ag-grid-community';
import type { PivotColDefService } from './pivotColDefService';
@@ -166,19 +166,14 @@ export class PivotStage extends BeanStub implements NamedBean, _IRowNodePivotSta
}
private setUniqueValues(newValues: Map): boolean {
- const json1 = JSON.stringify(mapToObject(this.uniqueValues));
- const json2 = JSON.stringify(mapToObject(newValues));
-
- const uniqueValuesChanged = json1 !== json2;
-
+ const uniqueValuesChanged = !_jsonEquals(mapToObject(this.uniqueValues), mapToObject(newValues));
// we only continue the below if the unique values are different, as otherwise
// the result will be the same as the last time we did it
if (uniqueValuesChanged) {
this.uniqueValues = newValues;
return true;
- } else {
- return false;
}
+ return false;
}
private currentUniqueCount = 0;
diff --git a/packages/ag-grid-enterprise/src/rowHierarchy/groupEditService.ts b/packages/ag-grid-enterprise/src/rowHierarchy/groupEditService.ts
index 3075f3e76de..7ff599ae7fd 100644
--- a/packages/ag-grid-enterprise/src/rowHierarchy/groupEditService.ts
+++ b/packages/ag-grid-enterprise/src/rowHierarchy/groupEditService.ts
@@ -116,11 +116,13 @@ export class GroupEditService extends BeanStub implements _IGroupEditService {
}
const sourceLevel = rowNode.group ? rowNode.level : currentParent.level ?? -1;
- const targetLevel = target
- ? target.group
- ? target.level
- : target.parent?.level ?? -1
- : comparisonParent?.level ?? -1;
+
+ let targetLevel = -1;
+ if (target) {
+ targetLevel = target.group ? target.level : target.parent?.level ?? -1;
+ } else if (comparisonParent) {
+ targetLevel = comparisonParent.level;
+ }
if (sourceLevel >= 0 && targetLevel >= 0 && targetLevel !== sourceLevel) {
return false;
@@ -148,9 +150,9 @@ export class GroupEditService extends BeanStub implements _IGroupEditService {
const rootNode = rowsDrop.rootNode as IRowNode;
const rowModel = this.beans.rowModel;
- const canStartGroup = target ? this.canDropStartGroup(target) : false;
- this.updateDropTarget(canStartGroup ? target : null, fromNudge, rowsDrop);
+ const canStartGroup = this.canStartGroup(target, treeData);
+ this.updateDropTarget(rowsDrop, fromNudge, canStartGroup);
const lastRowIndex = this.beans.pageBounds?.getLastRow?.() ?? rowModel.getRowCount() - 1;
if (canSetParent) {
@@ -163,16 +165,9 @@ export class GroupEditService extends BeanStub implements _IGroupEditService {
if (!newParent) {
newParent = target?.parent ?? rootNode;
}
+ }
- if (
- !fromNudge &&
- target &&
- canStartGroup &&
- (!newParent || (!target.expanded && !!target.childrenAfterSort?.length))
- ) {
- this.startDropGroupDelay(target);
- }
- } else if (!fromNudge && target && canStartGroup) {
+ if (!fromNudge && target && canStartGroup && !(target.group && target.expanded)) {
this.startDropGroupDelay(target);
}
@@ -209,7 +204,9 @@ export class GroupEditService extends BeanStub implements _IGroupEditService {
}
}
- private updateDropTarget(target: IRowNode | null, canExpand: boolean, rowsDrop: _RowsDrop): void {
+ private updateDropTarget(rowsDrop: _RowsDrop, fromNudge: boolean, canStartGroup: boolean): void {
+ const target = canStartGroup ? rowsDrop.target : null;
+
if (this.dropGroupTarget && this.dropGroupTarget !== target) {
this.resetDragGroup();
}
@@ -218,7 +215,7 @@ export class GroupEditService extends BeanStub implements _IGroupEditService {
return;
}
- if (canExpand && this.dropGroupThrottled && !target.expanded && target.isExpandable?.()) {
+ if (fromNudge && this.dropGroupThrottled && !target.expanded && target.isExpandable?.()) {
target.setExpanded(true, undefined, true);
}
@@ -403,14 +400,16 @@ export class GroupEditService extends BeanStub implements _IGroupEditService {
return true;
}
- public canDropStartGroup(candidate: IRowNode | null | undefined) {
- return (
- !!candidate &&
- candidate.level >= 0 &&
- !candidate.footer &&
- !candidate.detail &&
- (candidate.isExpandable?.() || !!candidate.childrenAfterSort?.length)
- );
+ private canStartGroup(target: IRowNode | null, treeData: boolean): boolean {
+ if (!target || target.level < 0 || target.footer || target.detail) {
+ return false; // cannot group into root, footer, or detail rows
+ }
+
+ if (target.group) {
+ return true;
+ }
+
+ return treeData; // in tree data any leaf can become a group
}
/** Flushes any pending group edits for batch processing */
diff --git a/packages/ag-grid-enterprise/src/serverSideRowModel/listeners/filterListener.ts b/packages/ag-grid-enterprise/src/serverSideRowModel/listeners/filterListener.ts
index d1eb48f4a24..34db9fa4c1c 100644
--- a/packages/ag-grid-enterprise/src/serverSideRowModel/listeners/filterListener.ts
+++ b/packages/ag-grid-enterprise/src/serverSideRowModel/listeners/filterListener.ts
@@ -6,7 +6,7 @@ import type {
NamedBean,
StoreRefreshAfterParams,
} from 'ag-grid-community';
-import { BeanStub, _isServerSideRowModel } from 'ag-grid-community';
+import { BeanStub, _isServerSideRowModel, _jsonEquals } from 'ag-grid-community';
import type { ServerSideRowModel } from '../serverSideRowModel';
import type { ListenerUtils } from './listenerUtils';
@@ -96,9 +96,7 @@ export class FilterListener extends BeanStub implements NamedBean {
const res: string[] = [];
for (const key of Object.keys(allColKeysMap)) {
- const oldJson = JSON.stringify(oldModel[key]);
- const newJson = JSON.stringify(newModel[key]);
- const filterChanged = oldJson != newJson;
+ const filterChanged = !_jsonEquals(oldModel[key], newModel[key]);
if (filterChanged) {
res.push(key);
}
diff --git a/testing/behavioural/src/cell-editing/bigint-value-parser-formatter.test.ts b/testing/behavioural/src/cell-editing/bigint-value-parser-formatter.test.ts
new file mode 100644
index 00000000000..77df979c87c
--- /dev/null
+++ b/testing/behavioural/src/cell-editing/bigint-value-parser-formatter.test.ts
@@ -0,0 +1,61 @@
+import { userEvent } from '@testing-library/user-event';
+
+import { ClientSideRowModelModule, TextEditorModule, getGridElement } from 'ag-grid-community';
+
+import { GridRows, TestGridsManager, waitForEvent, waitForInput } from '../test-utils';
+
+describe('BigInt value parser and formatter', () => {
+ const gridMgr = new TestGridsManager({
+ modules: [ClientSideRowModelModule, TextEditorModule],
+ });
+
+ afterEach(() => {
+ gridMgr.reset();
+ });
+
+ test('parses bigint editor input', async () => {
+ const api = gridMgr.createGrid('bigint-parser', {
+ columnDefs: [{ field: 'value', cellDataType: 'bigint', editable: true }],
+ rowData: [{ id: 'r1', value: 10n }],
+ getRowId: (params) => params.data?.id,
+ });
+
+ const gridDiv = getGridElement(api)! as HTMLElement;
+ const cell = gridDiv.querySelector('[row-index="0"] [col-id="value"]')!;
+
+ const editingStarted = waitForEvent('cellEditingStarted', api);
+ api.startEditingCell({ rowIndex: 0, colKey: 'value' });
+ await editingStarted;
+
+ const input = await waitForInput(gridDiv, cell);
+ const user = userEvent.setup();
+ await user.clear(input);
+ await user.type(input, '500n');
+
+ const editingStopped = waitForEvent('cellEditingStopped', api);
+ api.stopEditing();
+ await editingStopped;
+
+ const rowNode = api.getRowNode('r1')!;
+ expect(rowNode.data.value).toBe(500n);
+ });
+
+ test('uses valueFormatter for bigint display', async () => {
+ const api = gridMgr.createGrid('bigint-formatter', {
+ columnDefs: [
+ {
+ field: 'value',
+ cellDataType: 'bigint',
+ valueFormatter: (params) => (params.value == null ? '' : `formatted-${params.value}`),
+ },
+ ],
+ rowData: [{ id: 'r1', value: 12n }],
+ getRowId: (params) => params.data?.id,
+ });
+
+ await new GridRows(api, 'bigint formatted').check(`
+ ROOT id:ROOT_NODE_ID
+ └── LEAF id:r1 value:"formatted-12"
+ `);
+ });
+});
diff --git a/testing/behavioural/src/cell-editing/examples/full-row-editing-doc.test.ts b/testing/behavioural/src/cell-editing/examples/full-row-editing-doc.test.ts
index 4527123312d..7110e407d6a 100644
--- a/testing/behavioural/src/cell-editing/examples/full-row-editing-doc.test.ts
+++ b/testing/behavioural/src/cell-editing/examples/full-row-editing-doc.test.ts
@@ -233,5 +233,5 @@ describe('Full-row editing documentation examples', () => {
├── LEAF id:1 make-0-0:"Ford" model-1-1:"XYZ" field4-2-2:"S-YY"
└── LEAF id:2 make-0-0:"Porsche" model-1-1:"Boxster 0" field4-2-2:"S-ZZ"
`);
- });
+ }, 15000);
});
diff --git a/testing/behavioural/src/drag-n-drop/grouping/managed-row-group-drag-edit-basic.test.ts b/testing/behavioural/src/drag-n-drop/grouping/managed-row-group-drag-edit-basic.test.ts
index 6228433362c..16e16aba904 100644
--- a/testing/behavioural/src/drag-n-drop/grouping/managed-row-group-drag-edit-basic.test.ts
+++ b/testing/behavioural/src/drag-n-drop/grouping/managed-row-group-drag-edit-basic.test.ts
@@ -432,6 +432,83 @@ describe.each([false, true])('drag refreshAfterGroupEdit basics (suppress move %
expect(api.getRowNode('2')?.data.group).toBe('B');
});
+ test('rowDragInsertDelay does not promote leaf targets in row grouping', async () => {
+ const gridOptions: GridOptions = {
+ animateRows: true,
+ columnDefs: [
+ { field: 'group', rowGroup: true, hide: true },
+ { field: 'value', rowDrag: true },
+ ],
+ autoGroupColumnDef: { headerName: 'Group' },
+ rowData: [
+ { id: '1', group: 'A', value: 'A1' },
+ { id: '2', group: 'B', value: 'B1' },
+ ],
+ rowDragManaged: true,
+ suppressMoveWhenRowDragging,
+ refreshAfterGroupEdit: true,
+ rowDragInsertDelay: 60,
+ groupDefaultExpanded: -1,
+ getRowId: (params) => params.data.id,
+ };
+
+ const api = gridsManager.createGrid('row-group-edit-insert-delay-leaf', gridOptions);
+
+ const dispatcher = new RowDragDispatcher({ api });
+ await dispatcher.start('1');
+ await waitFor(() => expect(dispatcher.getDragGhostLabel()).toBe('A1'));
+ await dispatcher.move('2', { center: true });
+ await asyncSetTimeout(80);
+ await dispatcher.move('2', { center: true });
+
+ const lastMove = dispatcher.rowDragMoveEvents[dispatcher.rowDragMoveEvents.length - 1];
+ expect(lastMove?.rowsDrop?.position).not.toBe('inside');
+ expect(lastMove?.rowsDrop?.newParent?.id).toBe('row-group-group-B');
+
+ if (suppressMoveWhenRowDragging) {
+ const indicator = api.getRowDropPositionIndicator();
+ expect(indicator.dropIndicatorPosition).not.toBe('inside');
+ }
+
+ await dispatcher.finish();
+ });
+
+ test('rowDragInsertDelay skips expanded group targets', async () => {
+ const gridOptions: GridOptions = {
+ animateRows: true,
+ columnDefs: [
+ { field: 'group', rowGroup: true, hide: true },
+ { field: 'value', rowDrag: true },
+ ],
+ autoGroupColumnDef: { headerName: 'Group' },
+ rowData: [
+ { id: '1', group: 'A', value: 'A1' },
+ { id: '2', group: 'A', value: 'A2' },
+ { id: '3', group: 'B', value: 'B1' },
+ ],
+ rowDragManaged: true,
+ suppressMoveWhenRowDragging,
+ refreshAfterGroupEdit: true,
+ rowDragInsertDelay: 10000,
+ groupDefaultExpanded: -1,
+ getRowId: (params) => params.data.id,
+ };
+
+ const api = gridsManager.createGrid('row-group-edit-insert-delay-expanded', gridOptions);
+
+ const dispatcher = new RowDragDispatcher({ api });
+ await dispatcher.start('2');
+ await waitFor(() => expect(dispatcher.getDragGhostLabel()).toBe('A2'));
+ await dispatcher.move('row-group-group-B', { center: true });
+ await dispatcher.finish();
+ await asyncSetTimeout(0);
+
+ const dropInfo = dispatcher.rowDragEndEvents[0]?.rowsDrop;
+ expect(dropInfo?.position).toBe('above');
+ expect(dropInfo?.newParent?.id).toBe('row-group-group-B');
+ expect(api.getRowNode('2')?.data.group).toBe('B');
+ });
+
test.each([0, -0.9, 0.9] as const)('moves a leaf in collapsed sibling group immediately y=%f', async (y) => {
const gridOptions: GridOptions = {
animateRows: true,
diff --git a/testing/behavioural/src/drag-n-drop/tree-data/tree-data-managed-row-drag-multi.test.ts b/testing/behavioural/src/drag-n-drop/tree-data/tree-data-managed-row-drag-multi.test.ts
index 451b8251307..d8cbaad9f9b 100644
--- a/testing/behavioural/src/drag-n-drop/tree-data/tree-data-managed-row-drag-multi.test.ts
+++ b/testing/behavioural/src/drag-n-drop/tree-data/tree-data-managed-row-drag-multi.test.ts
@@ -182,6 +182,14 @@ describe.each([false, true])('tree drag multi flows (suppress move %s)', (suppre
});
}
+ if (suppressMoveWhenRowDragging) {
+ await waitFor(() => {
+ const indicator = api.getRowDropPositionIndicator();
+ expect(indicator.dropIndicatorPosition).not.toBe('none');
+ expect(['root-ops', 'root-ops-logs']).toContain(indicator.row?.id);
+ });
+ }
+
await asyncSetTimeout(10);
await dispatcher.move(targetRowId, { clientX, clientY });
await dispatcher.finish();
@@ -263,4 +271,112 @@ describe.each([false, true])('tree drag multi flows (suppress move %s)', (suppre
expect(dropInfo?.rows?.length ?? 0).toBeGreaterThan(0);
expect(dropInfo?.newParent?.id ?? dropInfo?.overNode?.id).toBe('inbox');
});
+
+ test('rowDragInsertDelay promotes leaf targets without a validator', async () => {
+ const rowData = [
+ {
+ id: 'root',
+ name: 'Root',
+ type: 'folder',
+ children: [
+ { id: 'inbox', name: 'Inbox', type: 'folder', children: [] },
+ { id: 'incoming', name: 'Incoming', type: 'file', children: [] },
+ ],
+ },
+ ];
+
+ const api = createGrid('tree-managed-insert-promote-default', rowData, {
+ rowDragInsertDelay: 60,
+ });
+
+ const initialRows = new GridRows(api, 'insert promote default initial');
+ await initialRows.check(`
+ ROOT id:ROOT_NODE_ID
+ └─┬ root GROUP id:root ag-Grid-AutoColumn:"Root" type:"folder"
+ · ├── inbox LEAF id:inbox ag-Grid-AutoColumn:"Inbox" type:"folder"
+ · └── incoming LEAF id:incoming ag-Grid-AutoColumn:"Incoming" type:"file"
+ `);
+
+ const sourceRowId = 'incoming';
+ const targetRowId = 'inbox';
+ expect(getRowHtmlElement(api, sourceRowId)).toBeTruthy();
+ expect(getRowHtmlElement(api, targetRowId)).toBeTruthy();
+
+ const dispatcher = new RowDragDispatcher({ api });
+ await dispatcher.start(sourceRowId);
+ await waitFor(() => expect(dispatcher.getDragGhostLabel()).toBe('Incoming'));
+ await dispatcher.move(targetRowId, { yOffsetPercent: 0.45 });
+ await asyncSetTimeout(80);
+ await dispatcher.move(targetRowId, { center: true });
+
+ if (suppressMoveWhenRowDragging) {
+ await waitFor(() => {
+ const indicator = api.getRowDropPositionIndicator();
+ expect(indicator.dropIndicatorPosition).toBe('inside');
+ expect(indicator.row?.id).toBe('inbox');
+ });
+ }
+
+ await dispatcher.finish();
+ await asyncSetTimeout(0);
+
+ const dropInfo = dispatcher.rowDragEndEvents[0]?.rowsDrop;
+
+ const finalRows = new GridRows(api, 'insert promote default after');
+ await finalRows.check(`
+ ROOT id:ROOT_NODE_ID
+ └─┬ root GROUP id:root ag-Grid-AutoColumn:"Root" type:"folder"
+ · └─┬ inbox GROUP id:inbox ag-Grid-AutoColumn:"Inbox" type:"folder"
+ · · └── incoming LEAF id:incoming ag-Grid-AutoColumn:"Incoming" type:"file"
+ `);
+
+ expect(api.getRowNode('incoming')?.parent?.id).toBe('inbox');
+ expect(api.getRowNode('inbox')?.childrenAfterSort?.some((node) => node.id === 'incoming')).toBe(true);
+ expect(dropInfo?.newParent?.id ?? dropInfo?.overNode?.id).toBe('inbox');
+ expect(dropInfo?.position).toBe('inside');
+ });
+
+ test('rowDragInsertDelay skips already expanded groups', async () => {
+ const rowData = [
+ {
+ id: 'root',
+ name: 'Root',
+ type: 'folder',
+ children: [
+ {
+ id: 'alpha',
+ name: 'Alpha',
+ type: 'folder',
+ children: [{ id: 'alpha-item', name: 'Alpha Item', type: 'file', children: [] }],
+ },
+ {
+ id: 'beta',
+ name: 'Beta',
+ type: 'folder',
+ children: [{ id: 'beta-item', name: 'Beta Item', type: 'file', children: [] }],
+ },
+ ],
+ },
+ ];
+
+ const api = createGrid('tree-managed-insert-expanded', rowData, {
+ rowDragInsertDelay: 10000,
+ groupDefaultExpanded: -1,
+ });
+
+ await asyncSetTimeout(0);
+ expect(api.getRowNode('beta')?.expanded).toBe(true);
+
+ const dispatcher = new RowDragDispatcher({ api });
+ await dispatcher.start('alpha-item');
+ await waitFor(() => expect(dispatcher.getDragGhostLabel()).toBe('Alpha Item'));
+ await dispatcher.move('beta', { center: true });
+ await dispatcher.finish();
+ await asyncSetTimeout(0);
+
+ const dropInfo = dispatcher.rowDragEndEvents[0]?.rowsDrop;
+ expect(dropInfo?.position).toBe('above');
+ expect(dropInfo?.newParent?.id).toBe('beta');
+ expect(api.getRowNode('alpha-item')?.parent?.id).toBe('beta');
+ });
});
diff --git a/testing/behavioural/src/filters/aggregate-filters.test.ts b/testing/behavioural/src/filters/aggregate-filters.test.ts
index f6cc4214325..1e16cc6280f 100644
--- a/testing/behavioural/src/filters/aggregate-filters.test.ts
+++ b/testing/behavioural/src/filters/aggregate-filters.test.ts
@@ -5,7 +5,14 @@ import { GridRows, TestGridsManager } from '../test-utils';
describe('Aggregate Filters', () => {
const gridsManager = new TestGridsManager({
- modules: [ClientSideRowModelModule, TextFilterModule, NumberFilterModule, RowGroupingModule, PivotModule],
+ modules: [
+ ClientSideRowModelModule,
+ TextFilterModule,
+ PivotModule,
+ NumberFilterModule,
+ RowGroupingModule,
+ PivotModule,
+ ],
});
const rowData = [
diff --git a/testing/behavioural/src/grid-state/grid-state-full.test.ts b/testing/behavioural/src/grid-state/grid-state-full.test.ts
index 0c4a10b6189..ae45a37f50a 100644
--- a/testing/behavioural/src/grid-state/grid-state-full.test.ts
+++ b/testing/behavioural/src/grid-state/grid-state-full.test.ts
@@ -33,7 +33,7 @@ describe('Grid State Full Snapshot', () => {
});
await asyncSetTimeout(1);
- expect({
+ expect(api.getState()).toEqual({
aggregation: undefined,
cellSelection: undefined,
columnGroup: undefined,
@@ -95,7 +95,7 @@ describe('Grid State Full Snapshot', () => {
sort: undefined,
ssrmRowGroupExpansion: undefined,
version: VERSION,
- }).toEqual(api.getState());
+ });
});
test('should get state with multiple features active', async () => {
diff --git a/testing/behavioural/src/grid-state/grid-state.test.ts b/testing/behavioural/src/grid-state/grid-state.test.ts
index 6d4f175c123..e34f8d4fc28 100644
--- a/testing/behavioural/src/grid-state/grid-state.test.ts
+++ b/testing/behavioural/src/grid-state/grid-state.test.ts
@@ -377,6 +377,37 @@ describe('StateService - Grid State Management', () => {
selectableFilters: {},
});
});
+
+ test('should serialise bigint filter state and rehydrate on setState', async () => {
+ const columnDefs = [{ field: 'id', cellDataType: 'bigint', filter: 'agBigIntColumnFilter' }];
+ const rowData = [{ id: 1n }, { id: 2n }, { id: 3n }];
+
+ const api = gridsManager.createGrid('bigIntStateSource', {
+ columnDefs,
+ rowData,
+ });
+
+ api.setFilterModel({
+ id: { filterType: 'bigint', type: 'equals', filter: '2n' },
+ });
+
+ await asyncSetTimeout(20);
+
+ const savedState = api.getState();
+ expect(savedState.filter?.filterModel?.id?.filter).toBe('2n');
+
+ const api2 = gridsManager.createGrid('bigIntStateTarget', {
+ columnDefs,
+ rowData,
+ });
+
+ api2.setState(savedState as GridState);
+
+ await asyncSetTimeout(20);
+
+ const restoredFilterModel = api2.getFilterModel();
+ expect(restoredFilterModel?.id?.filter).toBe('2n');
+ });
});
// ===== CELL STATE TESTS =====
@@ -387,6 +418,8 @@ describe('StateService - Grid State Management', () => {
rowData: defaultRowData,
});
+ await asyncSetTimeout(20);
+
// Focus a cell
api.setFocusedCell(0, 'name');
@@ -667,6 +700,8 @@ describe('StateService - Grid State Management', () => {
rowData: defaultRowData,
});
+ await asyncSetTimeout(20);
+
let eventFired = false;
let eventState: any;
diff --git a/testing/behavioural/src/group-cell-renderer/grouping/groups/csrm/grouping-values-bigint-formatter.test.ts b/testing/behavioural/src/group-cell-renderer/grouping/groups/csrm/grouping-values-bigint-formatter.test.ts
new file mode 100644
index 00000000000..4aae1238bb3
--- /dev/null
+++ b/testing/behavioural/src/group-cell-renderer/grouping/groups/csrm/grouping-values-bigint-formatter.test.ts
@@ -0,0 +1,52 @@
+import type { GridOptions } from 'ag-grid-community';
+import { AllEnterpriseModule } from 'ag-grid-enterprise';
+
+import { TestGridsManager } from '../../../../test-utils';
+
+describe('ag-grid groupCellRenderer', () => {
+ const gridsManager = new TestGridsManager({ modules: [AllEnterpriseModule] });
+
+ beforeEach(() => {
+ gridsManager.reset();
+ });
+
+ afterEach(() => {
+ gridsManager.reset();
+ });
+
+ test('bigint valueFormatter is used for group totals', async () => {
+ const gridOptions: GridOptions = {
+ columnDefs: [
+ { field: 'category', rowGroup: true, hide: true },
+ {
+ field: 'amount',
+ cellDataType: 'bigint',
+ aggFunc: 'sum',
+ valueFormatter: (params) => `formatted-${params.value}`,
+ },
+ ],
+ autoGroupColumnDef: {
+ cellClass: 'ag-cell-group',
+ },
+ rowData: [
+ { category: 'A', amount: 5n },
+ { category: 'A', amount: 7n },
+ ],
+ groupDefaultExpanded: -1,
+ groupTotalRow: 'bottom',
+ };
+
+ const div = document.createElement('div');
+ document.body.appendChild(div);
+ vi.useFakeTimers();
+ const api = gridsManager.createGrid(div, gridOptions);
+ vi.runAllTimers();
+ vi.useRealTimers();
+
+ api.ensureIndexVisible(2);
+ await new Promise((resolve) => setTimeout(resolve, 0));
+
+ const totalValueCell = div.querySelector('.ag-row-footer [col-id="amount"]');
+ expect(totalValueCell?.textContent ?? '').toContain('formatted-12');
+ });
+});
diff --git a/testing/behavioural/src/selection/source-row-index.test.ts b/testing/behavioural/src/selection/source-row-index.test.ts
new file mode 100644
index 00000000000..094a48694b4
--- /dev/null
+++ b/testing/behavioural/src/selection/source-row-index.test.ts
@@ -0,0 +1,70 @@
+import { ClientSideRowModelModule } from 'ag-grid-community';
+import type { GridOptions } from 'ag-grid-community';
+
+import { TestGridsManager } from '../test-utils';
+
+describe('sourceRowIndex in isRowSelectable', () => {
+ const columnDefs = [{ field: 'sport' }];
+ const rowData = [{ sport: 'football' }, { sport: 'rugby' }, { sport: 'tennis' }];
+
+ const gridMgr = new TestGridsManager({
+ modules: [ClientSideRowModelModule],
+ });
+
+ beforeEach(() => {
+ gridMgr.reset();
+ });
+
+ afterEach(() => {
+ gridMgr.reset();
+ });
+
+ test('sourceRowIndex should be populated in isRowSelectable', () => {
+ const nodeLog: { id: string | undefined; sourceRowIndex: number; rowIndex: number | null }[] = [];
+
+ const gridOptions: GridOptions = {
+ columnDefs,
+ rowData,
+ rowSelection: {
+ mode: 'multiRow',
+ isRowSelectable: (node) => {
+ nodeLog.push({
+ id: node.id,
+ sourceRowIndex: node.sourceRowIndex,
+ rowIndex: node.rowIndex,
+ });
+ return true;
+ },
+ },
+ };
+
+ gridMgr.createGrid('myGrid', gridOptions);
+
+ // For 3 rows, we expect isRowSelectable to be called at least 3 times during initial load (once for each node)
+ // Then it should be called again when rowIndex is set.
+ expect(nodeLog.length).toBeGreaterThanOrEqual(3);
+
+ // Group by node ID (or reference if we had it, but ID is fine here as it's set before updateRowSelectable)
+ const nodeMap: Record = {};
+ nodeLog.forEach((log) => {
+ const id = log.id!;
+ if (!nodeMap[id]) {
+ nodeMap[id] = [];
+ }
+ nodeMap[id].push(log);
+ });
+
+ const ids = Object.keys(nodeMap);
+ expect(ids.length).toBe(3);
+
+ ids.forEach((id) => {
+ const logs = nodeMap[id];
+
+ // All calls for this node should have a valid sourceRowIndex (not -1)
+ logs.forEach((log) => {
+ expect(log.sourceRowIndex).toBeGreaterThanOrEqual(0);
+ expect(log.sourceRowIndex).toBeLessThan(3);
+ });
+ });
+ });
+});
diff --git a/testing/behavioural/src/sorting/sorting.test.ts b/testing/behavioural/src/sorting/sorting.test.ts
index 1396a6acc27..674eb80c472 100644
--- a/testing/behavioural/src/sorting/sorting.test.ts
+++ b/testing/behavioural/src/sorting/sorting.test.ts
@@ -159,6 +159,60 @@ describe('Sorting', () => {
`);
});
+ test('sorts bigint values ascending, descending, and absolute', async () => {
+ const api = gridMgr.createGrid('bigintSort', {
+ columnDefs: [
+ {
+ field: 'value',
+ cellDataType: 'bigint',
+ valueFormatter: (params) => (params.value == null ? '' : `${params.value}n`),
+ },
+ ],
+ rowData: [
+ { id: 'a', value: 9007199254740993n },
+ { id: 'b', value: -5n },
+ { id: 'c', value: 10n },
+ ],
+ getRowId: (params) => params.data?.id,
+ });
+
+ await new GridRows(api, 'bigint initial').check(`
+ ROOT id:ROOT_NODE_ID
+ ├── LEAF id:a value:"9007199254740993n"
+ ├── LEAF id:b value:"-5n"
+ └── LEAF id:c value:"10n"
+ `);
+
+ api.applyColumnState({ state: [{ colId: 'value', sort: 'asc' }] });
+
+ await new GridRows(api, 'bigint asc').check(`
+ ROOT id:ROOT_NODE_ID
+ ├── LEAF id:b value:"-5n"
+ ├── LEAF id:c value:"10n"
+ └── LEAF id:a value:"9007199254740993n"
+ `);
+
+ api.applyColumnState({ state: [{ colId: 'value', sort: 'desc' }] });
+
+ await new GridRows(api, 'bigint desc').check(`
+ ROOT id:ROOT_NODE_ID
+ ├── LEAF id:a value:"9007199254740993n"
+ ├── LEAF id:c value:"10n"
+ └── LEAF id:b value:"-5n"
+ `);
+
+ api.applyColumnState({
+ state: [{ colId: 'value', sort: 'asc', sortIndex: 0, sortType: 'absolute' }],
+ });
+
+ await new GridRows(api, 'bigint absolute asc').check(`
+ ROOT id:ROOT_NODE_ID
+ ├── LEAF id:b value:"-5n"
+ ├── LEAF id:c value:"10n"
+ └── LEAF id:a value:"9007199254740993n"
+ `);
+ });
+
test('accentedSort toggles locale aware ordering', async () => {
const namesRowData = [
{ id: 'accent-1', name: 'Zorro' },
diff --git a/testing/behavioural/src/test-utils/gridRows/gridRowsDiagramTree.ts b/testing/behavioural/src/test-utils/gridRows/gridRowsDiagramTree.ts
index eb74bc0b0e3..8b9b047f299 100644
--- a/testing/behavioural/src/test-utils/gridRows/gridRowsDiagramTree.ts
+++ b/testing/behavioural/src/test-utils/gridRows/gridRowsDiagramTree.ts
@@ -341,7 +341,11 @@ export class GridRowsDiagramTree {
const diagramColumnId = isRowNumberCol(columnId) ? 'row-number' : columnId;
if (value !== undefined || formattedValue) {
- result += ' ' + diagramColumnId + ':' + JSON.stringify(formattedValue || value);
+ const serialisedValue =
+ typeof (formattedValue || value) === 'bigint'
+ ? JSON.stringify(`${formattedValue || value}n`)
+ : JSON.stringify(formattedValue || value);
+ result += ' ' + diagramColumnId + ':' + serialisedValue;
} else if (!omitUndefined && row.data != null) {
result += ' ' + diagramColumnId + ':undefined';
}
@@ -352,7 +356,8 @@ export class GridRowsDiagramTree {
if (dataProps?.length) {
for (const prop of dataProps) {
const dataValue = (row.data as any)?.[prop];
- const serialised = JSON.stringify(dataValue ?? '');
+ const serialised =
+ typeof dataValue === 'bigint' ? JSON.stringify(`${dataValue}n`) : JSON.stringify(dataValue ?? '');
result += ` data.${prop}:${serialised}`;
}
}
diff --git a/testing/module-size/moduleDefinitions.ts b/testing/module-size/moduleDefinitions.ts
index b23b6be3795..47d3fddb3e4 100644
--- a/testing/module-size/moduleDefinitions.ts
+++ b/testing/module-size/moduleDefinitions.ts
@@ -6,11 +6,12 @@ import type {
export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, number> = {
AlignedGridsModule: 6.88,
- AllCommunityModule: 501.39,
+ AllCommunityModule: 511.54,
CellApiModule: 0.28,
CellSpanModule: 8.08,
CellStyleModule: 2.24,
CheckboxEditorModule: 69.23,
+ BigIntFilterModule: 131.17,
ClientSideRowModelApiModule: 1.88,
ClientSideRowModelModule: 29.1,
ColumnApiModule: 3.6,
@@ -20,11 +21,11 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, num
CustomEditorModule: 67.95,
CustomFilterModule: 74.17,
DateEditorModule: 74.39,
- DateFilterModule: 132,
+ DateFilterModule: 139.28,
DragAndDropModule: 1,
EventApiModule: 2.64,
ExternalFilterModule: 12.67,
- GridStateModule: 15.84,
+ GridStateModule: 17.38,
HighlightChangesModule: 5.09,
InfiniteRowModelModule: 18,
LargeTextEditorModule: 70.13,
@@ -43,7 +44,7 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, num
ScrollApiModule: 0.7,
SelectEditorModule: 83.87,
TextEditorModule: 71.4,
- TextFilterModule: 124,
+ TextFilterModule: 128.66,
TooltipModule: 25.06,
UndoRedoEditModule: 74.12,
ValidationModule: 74.37,
@@ -51,7 +52,7 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, num
};
export const AllEnterpriseModules: Record<`${EnterpriseModuleName}Module`, number> = {
AdvancedFilterModule: 223.75,
- AllEnterpriseModule: 1606.74,
+ AllEnterpriseModule: 1627.32,
AiToolkitModule: 36,
BatchEditModule: 84.54,
CellSelectionModule: 62.78,
@@ -62,14 +63,14 @@ export const AllEnterpriseModules: Record<`${EnterpriseModuleName}Module`, numbe
ExcelExportModule: 87.14,
FiltersToolPanelModule: 137.67,
FindModule: 31,
- FormulaModule: 88.65,
+ FormulaModule: 92.79,
GridChartsModule: 76.93,
GroupFilterModule: 118.66,
IntegratedChartsModule: 412.18,
MasterDetailModule: 87.16,
MenuModule: 166.7,
MultiFilterModule: 150.56,
- NewFiltersToolPanelModule: 175.32,
+ NewFiltersToolPanelModule: 180.87,
PivotModule: 112.4,
RangeSelectionModule: 62.84,
RichSelectModule: 132.51,
diff --git a/testing/shared/moduleDefinitions.ts b/testing/shared/moduleDefinitions.ts
index 610220ce146..53223a7822c 100644
--- a/testing/shared/moduleDefinitions.ts
+++ b/testing/shared/moduleDefinitions.ts
@@ -6,11 +6,12 @@ import type {
export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, number> = {
AlignedGridsModule: 6.88,
- AllCommunityModule: 501.39,
+ AllCommunityModule: 511.54,
CellApiModule: 0.28,
CellSpanModule: 8.08,
CellStyleModule: 2.24,
CheckboxEditorModule: 69.23,
+ BigIntFilterModule: 131.17,
ClientSideRowModelApiModule: 1.88,
ClientSideRowModelModule: 29.1,
ColumnApiModule: 3.6,
@@ -20,11 +21,11 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, num
CustomEditorModule: 67.95,
CustomFilterModule: 74.17,
DateEditorModule: 74.39,
- DateFilterModule: 132,
+ DateFilterModule: 139.28,
DragAndDropModule: 1,
EventApiModule: 2.64,
ExternalFilterModule: 12.67,
- GridStateModule: 14.7,
+ GridStateModule: 17.38,
HighlightChangesModule: 5.09,
InfiniteRowModelModule: 18,
LargeTextEditorModule: 70.13,
@@ -43,7 +44,7 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, num
ScrollApiModule: 0.7,
SelectEditorModule: 83.87,
TextEditorModule: 71.4,
- TextFilterModule: 124,
+ TextFilterModule: 128.66,
TooltipModule: 25.06,
UndoRedoEditModule: 74.12,
ValidationModule: 74.37,
@@ -51,7 +52,7 @@ export const AllGridCommunityModules: Record<`${CommunityModuleName}Module`, num
};
export const AllEnterpriseModules: Record<`${EnterpriseModuleName}Module`, number> = {
AdvancedFilterModule: 222.75,
- AllEnterpriseModule: 1606.74,
+ AllEnterpriseModule: 1627.32,
AiToolkitModule: 36,
BatchEditModule: 84.54,
CellSelectionModule: 62.78,
@@ -62,14 +63,14 @@ export const AllEnterpriseModules: Record<`${EnterpriseModuleName}Module`, numbe
ExcelExportModule: 87.14,
FiltersToolPanelModule: 137.67,
FindModule: 31,
- FormulaModule: 88.65,
+ FormulaModule: 92.79,
GridChartsModule: 76.93,
IntegratedChartsModule: 412.18,
GroupFilterModule: 118.66,
MasterDetailModule: 87.16,
MenuModule: 165,
MultiFilterModule: 150.24,
- NewFiltersToolPanelModule: 175.32,
+ NewFiltersToolPanelModule: 180.87,
PivotModule: 112.4,
RangeSelectionModule: 62.84,
RichSelectModule: 132.51,