Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/ag-grid-community/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export default [
message:
"Prefer unicode characters as they don't have to be parsed into HTML to display correctly.",
},
{
selector: 'PropertyDefinition[static=true]',
message: 'Static class properties prevent tree-shaking. Use an alternative if possible.',
},
],
'no-restricted-properties': [
'warn',
Expand Down
19 changes: 18 additions & 1 deletion packages/ag-grid-community/src/agStack/utils/dom.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { UtilBeanCollection } from '../interfaces/agCoreBeanCollection';
import { _setAriaHidden } from './aria';
import { _getWindow } from './document';
import { _getDocument, _getWindow } from './document';

/**
* This method adds a class to an element and remove that class from all siblings.
Expand Down Expand Up @@ -393,6 +393,23 @@ export function _addOrRemoveAttribute(element: HTMLElement, name: string, value:
}
}

export function _placeCaretAtEnd(beans: UtilBeanCollection, contentElement: HTMLElement): void {
if (!contentElement.isContentEditable) {
return;
}
const selection = _getWindow(beans).getSelection();

if (!selection) {
return;
}

const range = _getDocument(beans).createRange();
range.selectNodeContents(contentElement);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}

export function _observeResize(
beans: UtilBeanCollection,
element: HTMLElement,
Expand Down
37 changes: 21 additions & 16 deletions packages/ag-grid-community/src/columns/dataTypeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { _toStringOrNull } from '../agStack/utils/generic';
import { _getValueUsingField } from '../agStack/utils/value';
import type { NamedBean } from '../context/bean';
import { BeanStub } from '../context/beanStub';
import type { BeanCollection, UserComponentName } from '../context/context';
import type { BeanCollection } from '../context/context';
import type { AgColumn } from '../entities/agColumn';
import type { ColDef, SuppressKeyboardEventParams, ValueFormatterFunc, ValueFormatterParams } from '../entities/colDef';
import type {
Expand Down Expand Up @@ -215,11 +215,14 @@ export class DataTypeService extends BeanStub implements NamedBean {
cellDataType = colDef.cellDataType;
}

const { field, allowFormula } = userColDef;
const { field } = userColDef;

if (cellDataType == null || cellDataType === true) {
cellDataType = this.canInferCellDataType(colDef, userColDef) ? this.inferCellDataType(field, colId) : false;
}

this.addFormulaCellEditorToColDef(colDef, userColDef);

if (!cellDataType) {
colDef.cellDataType = false;
return undefined;
Expand All @@ -231,7 +234,6 @@ export class DataTypeService extends BeanStub implements NamedBean {
}

colDef.cellDataType = cellDataType;
colDef.allowFormula ??= allowFormula;

if (dataTypeDefinition.groupSafeValueFormatter) {
colDef.valueFormatter = dataTypeDefinition.groupSafeValueFormatter;
Expand All @@ -245,6 +247,16 @@ export class DataTypeService extends BeanStub implements NamedBean {
return dataTypeDefinition.columnTypes;
}

private addFormulaCellEditorToColDef(colDef: ColDef, userColDef: ColDef): void {
const allowFormula = userColDef.allowFormula ?? colDef.allowFormula;

if (!allowFormula || userColDef.cellEditor) {
return;
}

colDef.cellEditor = 'agFormulaCellEditor';
}

public addColumnListeners(column: AgColumn): void {
if (!this.isPendingInference) {
return;
Expand Down Expand Up @@ -587,21 +599,14 @@ export class DataTypeService extends BeanStub implements NamedBean {
colId,
formatValue,
});
Object.assign(colDef, partialColDef);

const { cellEditor, allowFormula } = colDef;

if (allowFormula) {
const supportedEditors: UserComponentName[] = [
'agFormulaCellEditor',
'agTextCellEditor',
'agLargeTextCellEditor',
];

if (!supportedEditors.includes(cellEditor)) {
colDef.cellEditor = 'agFormulaCellEditor';
}
// if the user enabled formula and did not manually provide an editor
// we should keep `agFormulaCellEditor` as the default editor.
if (colDef.cellEditor === 'agFormulaCellEditor' && partialColDef.cellEditor !== colDef.cellEditor) {
partialColDef.cellEditor = colDef.cellEditor;
}

Object.assign(colDef, partialColDef);
}

private getDateObjectTypeDef<T extends 'date' | 'dateTime'>(baseDataType: T) {
Expand Down
2 changes: 2 additions & 0 deletions packages/ag-grid-community/src/globalGridOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import type { GridOptions } from './entities/gridOptions';
import { _mergeDeep } from './utils/mergeDeep';

export class GlobalGridOptions {
// eslint-disable-next-line no-restricted-syntax
static gridOptions: GridOptions | undefined = undefined;
// eslint-disable-next-line no-restricted-syntax
static mergeStrategy: GlobalGridOptionsMergeStrategy = 'shallow';

/**
Expand Down
1 change: 1 addition & 0 deletions packages/ag-grid-community/src/interfaces/formulas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export interface IFormulaDataService extends Bean {

export interface IFormulaService extends Bean {
active: boolean;
activeEditor: number | null;
isFormula(value: unknown): value is `=${string}`;
setFormulasActive(cols: ColumnCollections): void;
resolveValue(col: AgColumn, row: RowNode): unknown;
Expand Down
2 changes: 2 additions & 0 deletions packages/ag-grid-community/src/main-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export { MONTHS as _MONTHS, _getDateParts, _parseDateTimeFromString, _serialiseD
export {
_getActiveDomElement,
_getDocument,
_getWindow,
_getPageBody,
_getRootNode,
_isNothingFocused,
Expand All @@ -155,6 +156,7 @@ export {
_setFixedWidth,
_setVisible,
_isFocusableFormField,
_placeCaretAtEnd,
} from './agStack/utils/dom';
export { _anchorElementToMouseMoveEvent, _isElementInEventPath } from './agStack/utils/event';
export {
Expand Down
3 changes: 2 additions & 1 deletion packages/ag-grid-community/src/rendering/cell/cellCtrl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { _setAriaColIndex } from '../../agStack/utils/aria';
import { _getActiveDomElement } from '../../agStack/utils/document';
import { _addOrRemoveAttribute, _requestAnimationFrame } from '../../agStack/utils/dom';
import { _addOrRemoveAttribute, _placeCaretAtEnd, _requestAnimationFrame } from '../../agStack/utils/dom';
import { _findFocusableElements } from '../../agStack/utils/focus';
import { _makeNull } from '../../agStack/utils/generic';
import { AgPromise } from '../../agStack/utils/promise';
Expand Down Expand Up @@ -909,6 +909,7 @@ export class CellCtrl extends BeanStub {
}

focusEl.focus({ preventScroll: !!event.preventScrollOnBrowserFocus });
_placeCaretAtEnd(beans, focusEl);
}

// require event to announce so we only announce
Expand Down
6 changes: 1 addition & 5 deletions packages/ag-grid-community/src/selection/selectionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -758,11 +758,7 @@ export class SelectionService extends BaseSelectionService implements NamedBean,
}

if (!isSelectAll) {
const detailSelected = this.detailSelection.get(node.id!) ?? new Set();
for (const n of detailApi.getSelectedNodes()) {
detailSelected.add(n.id!);
}
this.detailSelection.set(node.id!, detailSelected);
this.detailSelection.set(node.id!, new Set(detailApi.getSelectedNodes().map((n) => n.id!)));
}
}

Expand Down
4 changes: 4 additions & 0 deletions packages/ag-grid-enterprise/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export default [
message:
'Empty imports are not allowed. i.e import "ag-grid-community"; as it will cause warnings about being sideEffect free',
},
{
selector: 'PropertyDefinition[static=true]',
message: 'Static class properties prevent tree-shaking. Use an alternative if possible.',
},
],
'no-restricted-imports': [
'error',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ICellEditorParams } from 'ag-grid-community';
import { AgAbstractCellEditor, KeyCode, RefPlaceholder, _isBrowserSafari } from 'ag-grid-community';
import { AgAbstractCellEditor, KeyCode, RefPlaceholder, _isBrowserSafari, _placeCaretAtEnd } from 'ag-grid-community';

import { AgFormulaInputField } from '../../widgets/agFormulaInputField';

Expand Down Expand Up @@ -55,10 +55,11 @@ export class FormulaCellEditor extends AgAbstractCellEditor<ICellEditorParams> {
return;
}

const { beans, eEditor } = this;
if (!_isBrowserSafari()) {
this.focusIn();
}
this.eEditor.placeCaretAtEnd();
_placeCaretAtEnd(beans, eEditor.getContentElement());
}

public focusIn(): void {
Expand Down
3 changes: 3 additions & 0 deletions packages/ag-grid-enterprise/src/formula/formulaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ export class FormulaService extends BeanStub implements IFormulaService, NamedBe
/** Built-in operations (extendable via gridOptions.formulaFuncs). */
private supportedOperations: Map<string, (params: FormulaFunctionParams) => unknown>;

// Track the active editor instance per grid/cell to avoid overlapping syncs on editor restarts.
public activeEditor: number | null = null;

public active = false;

public setFormulasActive(cols: _ColumnCollections): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ export interface ILicenseManager {
}

export class LicenseManager {
// eslint-disable-next-line no-restricted-syntax
private static readonly RELEASE_INFORMATION: string = 'MTc2NTM1OTQ2ODIzOA==';
// eslint-disable-next-line no-restricted-syntax
private static licenseKey: string;
// eslint-disable-next-line no-restricted-syntax
private static chartsLicenseManager?: ILicenseManager;
private watermarkMessage: string | undefined = undefined;

Expand Down
47 changes: 30 additions & 17 deletions packages/ag-grid-enterprise/src/rangeSelection/rangeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
import {
AutoScrollService,
BeanStub,
KeyCode,
_areCellsEqual,
_areEqual,
_exists,
Expand Down Expand Up @@ -462,15 +463,29 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService,

private isMultiRange(event: MouseEvent): boolean {
const { ctrlKey, metaKey } = event;
const { editSvc, gos } = this.beans;
const editingWithRanges = !!editSvc?.isEditing() && !!editSvc?.isRangeSelectionEnabledWhileEditing();
const { editingWithRanges, allowMulti } = this.getMultiRangeContext();

// ctrlKey for windows, metaKey for Apple
const isMultiKey = ctrlKey || metaKey;
const allowMulti = !_getSuppressMultiRanges(gos);
return editingWithRanges || (allowMulti ? isMultiKey : false);
}

private getMultiRangeContext(): {
editingWithRanges: boolean;
suppressMultiRanges: boolean;
allowMulti: boolean;
} {
const { gos, editSvc } = this.beans;
const editingWithRanges = !!editSvc?.isEditing() && !!editSvc?.isRangeSelectionEnabledWhileEditing();
const suppressMultiRanges = _getSuppressMultiRanges(gos) && !editingWithRanges;

return {
editingWithRanges,
suppressMultiRanges,
allowMulti: !suppressMultiRanges,
};
}

private removeRowFromAllColumnsRange(cell: CellPosition, containingRange: CellRange): void {
const { beans, cellRanges } = this;
const firstRow = _getFirstRow(beans);
Expand Down Expand Up @@ -525,10 +540,10 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService,
return;
}

const suppressMultiRangeSelections = _getSuppressMultiRanges(gos);
const { suppressMultiRanges } = this.getMultiRangeContext();

// if not appending, then clear previous range selections
if (suppressMultiRangeSelections || !appendRange || _missing(this.cellRanges)) {
if (suppressMultiRanges || !appendRange || _missing(this.cellRanges)) {
this.removeAllCellRanges(true);
}

Expand Down Expand Up @@ -1097,18 +1112,11 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService,
// when ranges are created due to a mouse click without drag (happens in cellMouseListener)
// this method will be called with `fromMouseClick=true`.
// Range selection while editing relies on overlapping ranges to preserve editor overlays.
if (this.beans.editSvc?.isRangeSelectionEnabledWhileEditing?.()) {
return;
}
if (fromMouseClick && this.dragging) {
return;
}
if (_getSuppressMultiRanges(this.gos)) {
return;
}
if (this.isEmpty()) {
const { editingWithRanges, suppressMultiRanges } = this.getMultiRangeContext();
if (editingWithRanges || suppressMultiRanges || (fromMouseClick && this.dragging) || this.isEmpty()) {
return;
}

const lastRange = _last(this.cellRanges);
const intersectionStartRow = this.getRangeStartRow(lastRange);
const intersectionEndRow = this.getRangeEndRow(lastRange);
Expand Down Expand Up @@ -1250,7 +1258,8 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService,
}

private verifyCellRanges(gos: GridOptionsService): boolean {
const invalid = _isUsingNewCellSelectionAPI(gos) && _getSuppressMultiRanges(gos) && this.cellRanges.length > 1;
const { suppressMultiRanges } = this.getMultiRangeContext();
const invalid = _isUsingNewCellSelectionAPI(gos) && suppressMultiRanges && this.cellRanges.length > 1;
if (invalid) {
_warn(93);
}
Expand Down Expand Up @@ -1438,7 +1447,7 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService,
return;
}

const suppressMultiRanges = _getSuppressMultiRanges(gos);
const { suppressMultiRanges } = this.getMultiRangeContext();
const hasRanges = cellRanges.length > 0;
const isMeta = event.ctrlKey || event.metaKey;

Expand All @@ -1449,6 +1458,10 @@ export class RangeService extends BeanStub implements NamedBean, IRangeService,
return;
}

if ((event as KeyboardEvent).key === KeyCode.ENTER) {
event.preventDefault();
}

if (event.shiftKey) {
// doing range selection
const root = ctx.root;
Expand Down
Loading
Loading