diff --git a/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts b/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts index 1d389d3cb56f..7a925478016b 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts @@ -2,6 +2,7 @@ import dataQuery from '@js/common/data/query'; import storeHelper from '@js/common/data/store_helper'; import { normalizeSortingInfo } from '@js/common/data/utils'; +import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; import { extend } from '@js/core/utils/extend'; import { each } from '@js/core/utils/iterator'; @@ -14,6 +15,7 @@ import type { RawItemData, RemoteOperationsOptions } from '@ts/grids/grid_core/d import type { ModuleType } from '@ts/grids/grid_core/types'; import { ColumnsView } from '@ts/grids/grid_core/views/columns_view'; import { CLASSES as VIEW_CLASSES } from '@ts/grids/grid_core/views/const'; +import type { RowRenderOptions, SummaryRowsViewExtension } from '@ts/grids/grid_core/views/types'; import type { EditingController } from '../../grid_core/editing/editing'; import type { RowsView } from '../../grid_core/views/rows_view'; @@ -485,7 +487,7 @@ export const summaryEditingControllerExtender = ( export const summaryRowsViewExtender = ( Base: ModuleType, -): ModuleType => class SummaryRowsViewExtender extends Base { +): ModuleType => class SummaryRowsViewExtender extends Base { protected _createRow(row) { // @ts-expect-error const $row = super._createRow.apply(this, arguments); @@ -530,10 +532,15 @@ export const summaryRowsViewExtender = ( const groupCellColSpan = Number($groupCell.attr('colSpan')) || 1; const alignByColumnCellCount = this._getAlignByColumnCellCount(groupCellColSpan, options); - this._renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount); + this.renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount); } - private _renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount) { + public renderGroupSummaryCellsCore( + $groupCell: dxElementWrapper, + options: RowRenderOptions, + groupCellColSpan: number, + alignByColumnCellCount: number, + ): void { if (alignByColumnCellCount > 0) { $groupCell.attr('colSpan', groupCellColSpan - alignByColumnCellCount); diff --git a/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts b/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts index a8d463540568..af9b495574af 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/column_fixing/m_column_fixing.ts @@ -34,7 +34,7 @@ import gridCoreUtils from '../utils'; import type { ColumnsView } from '../views/columns_view'; import { normalizeWidth } from '../views/columns_view'; import type { RowsView } from '../views/rows_view'; -import type { RowsViewScrollEvent } from '../views/types'; +import type { RowsViewScrollEvent, SummaryRowsViewExtension } from '../views/types'; import { CLASSES } from './const'; const FIRST_CELL_CLASS = 'dx-first-cell'; @@ -681,7 +681,9 @@ const columnHeadersView = (Base: ModuleType) => class ColumnH } }; -const rowsView = (Base: ModuleType) => class RowsViewFixedColumnsExtender extends baseFixedColumns(Base) { +const rowsView = ( + Base: ModuleType, +) => class RowsViewFixedColumnsExtender extends baseFixedColumns(Base) { protected _fixedScrollTimeout: any; public dispose() { @@ -856,7 +858,7 @@ const rowsView = (Base: ModuleType) => class RowsViewFixedColumnsExten return result && (!this._isFixedColumns || !column.fixed); } - private _renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount) { + public renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount) { let alignByFixedColumnCellCount; if (this._isFixedTableRendering) { @@ -878,8 +880,7 @@ const rowsView = (Base: ModuleType) => class RowsViewFixedColumnsExten alignByColumnCellCount = alignByFixedColumnCellCount; } - // @ts-expect-error DataGrid's method - super._renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount); + super.renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount); } private _getSummaryCellIndex(columnIndex, columns) { diff --git a/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts b/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts index f9b551c0f9f2..cee083c896c0 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/columns_resizing_reordering/m_columns_resizing_reordering.ts @@ -28,7 +28,7 @@ import { CLASSES as COLUMN_HEADERS_CLASSES } from '@ts/grids/grid_core/column_he import { getDraggingPanelBoundingRects } from '@ts/grids/grid_core/columns_resizing_reordering/utils'; import type { EditorFactory } from '@ts/grids/grid_core/editor_factory/editor_factory'; import type { - ColumnPoint, InternalGrid, ModuleType, OptionChanged, + ColumnPoint, ColumnPointProps, InternalGrid, ModuleType, OptionChanged, } from '@ts/grids/grid_core/types'; import type { RowsView } from '@ts/grids/grid_core/views/rows_view'; import type { ScrollPosition } from '@ts/grids/grid_core/views/types'; @@ -799,7 +799,7 @@ export class ColumnsResizerViewController extends modules.ViewController { } protected _correctColumnIndexForPoint( - point: ColumnPoint, + point: ColumnPointProps, correctionValue: number, // eslint-disable-next-line @typescript-eslint/no-unused-vars -- overrides use the param columns: Column[], @@ -811,7 +811,7 @@ export class ColumnsResizerViewController extends modules.ViewController { * @extended: adaptivity */ protected _pointCreated( - point: ColumnPoint, + point: ColumnPointProps, columns: Column[], cells?: dxElementWrapper, ): boolean { @@ -1082,7 +1082,7 @@ export class ColumnsResizerViewController extends modules.ViewController { const topYMap = this._generateColumnsTopYIndex(needToCheckPrevPoint); const columns = this._columnsController ? this._columnsController.getVisibleColumns() : []; const cells = this._columnHeadersView.getColumnElements(); - const correctColumnY = (point: ColumnPoint): ColumnPoint => { + const correctColumnY = (point: ColumnPointProps): ColumnPointProps => { const x = Math.ceil(point.x); if (topYMap[x]) { diff --git a/packages/devextreme/js/__internal/grids/grid_core/grid_view/grid_view.ts b/packages/devextreme/js/__internal/grids/grid_core/grid_view/grid_view.ts index 3f69eca3fee7..d19363c8e7b5 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/grid_view/grid_view.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/grid_view/grid_view.ts @@ -63,7 +63,7 @@ export class ResizingController extends modules.ViewController { protected _rowsView!: RowsView; - private _columnHeadersView!: ColumnHeadersView; + protected _columnHeadersView!: ColumnHeadersView; public _columnsController!: ColumnsController; diff --git a/packages/devextreme/js/__internal/grids/grid_core/master_detail/m_master_detail.ts b/packages/devextreme/js/__internal/grids/grid_core/master_detail/m_master_detail.ts index 057322634867..a261e61e98ed 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/master_detail/m_master_detail.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/master_detail/m_master_detail.ts @@ -24,6 +24,7 @@ import type { import type { RawItemData } from '../data_source_adapter/types'; import gridCoreUtils from '../utils'; import { CLASSES } from './const'; +import type { MasterDetailRowsViewExtension } from './types'; import { isDetailRow } from './utils'; const columns = (Base: ModuleType) => class ColumnsMasterDetailExtender extends Base { @@ -353,7 +354,11 @@ const resizing = (Base: ModuleType) => class ResizingMasterD } }; -const rowsView = (Base: ModuleType) => class RowsViewMasterDetailExtender extends Base { +const rowsView = ( + Base: ModuleType, +): ModuleType< + RowsView & MasterDetailRowsViewExtension +> => class RowsViewMasterDetailExtender extends Base { protected _getCellTemplate(options) { const that = this; const { column } = options; @@ -394,14 +399,14 @@ const rowsView = (Base: ModuleType) => class RowsViewMasterDetailExten if (isDetailRowResult) { if (this._needRenderCell(0, options.columnIndices)) { - this._renderMasterDetailCell($row, row, options); + this.renderMasterDetailCell($row, row, options); } } else { super._renderCells.apply(this, arguments as any); } } - protected _renderMasterDetailCell($row, row, options): dxElementWrapper { + public renderMasterDetailCell($row, row, options): dxElementWrapper { const visibleColumns = this._columnsController.getVisibleColumns(); const $detailCell = this._renderCell($row, { diff --git a/packages/devextreme/js/__internal/grids/grid_core/master_detail/types.ts b/packages/devextreme/js/__internal/grids/grid_core/master_detail/types.ts new file mode 100644 index 000000000000..7538ae05813e --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/master_detail/types.ts @@ -0,0 +1,12 @@ +import type { dxElementWrapper } from '@js/core/renderer'; + +import type { RowRenderOptions, ViewRow } from '../views/types'; + +export interface MasterDetailRowsViewExtension { + // eslint-disable-next-line @typescript-eslint/method-signature-style -- overridden by methods + renderMasterDetailCell( + $row: dxElementWrapper, + row: ViewRow, + options: RowRenderOptions, + ): dxElementWrapper; +} diff --git a/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/dom.ts b/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/dom.ts index 2ee97638e210..8346aa615bbc 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/dom.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/dom.ts @@ -3,6 +3,7 @@ import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; import { getBoundingRect } from '@js/core/utils/position'; import { isDefined } from '@js/core/utils/type'; +import type { ColumnPointProps } from '@ts/grids/grid_core/types'; import type { ColumnHeadersView } from '../column_headers/m_column_headers'; import { CLASSES, StickyPosition } from './const'; @@ -196,13 +197,7 @@ const noNeedToCreateResizingPoint = ( nextColumn, cells, }: { - point: { - x: number; - index: number; - item: HTMLElement; - isLeftBoundary: boolean | undefined; - isRightBoundary: boolean | undefined; - }; + point: ColumnPointProps; column; nextColumn; cells: dxElementWrapper | undefined; diff --git a/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/m_sticky_columns.ts b/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/m_sticky_columns.ts index 172187eaf827..944b0f11ca18 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/m_sticky_columns.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/m_sticky_columns.ts @@ -4,10 +4,21 @@ import $ from '@js/core/renderer'; import type { DeferredObj } from '@js/core/utils/deferred'; import { getBoundingRect } from '@js/core/utils/position'; import { getWidth, setWidth } from '@js/core/utils/size'; +import type { ItemClickEvent } from '@js/ui/context_menu'; +import type { KeyboardKeyDownEvent } from '@ts/events/core/keyboard_processor'; +import type { + DraggingPointCreatedOptions, + DraggingPointsOptions, +} from '@ts/grids/grid_core/columns_resizing_reordering/types'; import type { DataChange } from '@ts/grids/grid_core/data_controller/types'; import type { EditorFactory } from '@ts/grids/grid_core/editor_factory/editor_factory'; import type { ResizingController } from '@ts/grids/grid_core/grid_view/grid_view'; +import type { HorizontalBounds } from '@ts/grids/grid_core/keyboard_navigation/types'; +import type { MasterDetailRowsViewExtension } from '@ts/grids/grid_core/master_detail/types'; +import type { ValidatingEditorFactoryExtension } from '@ts/grids/grid_core/validating/types'; import { CLASSES as VIEW_CLASSES } from '@ts/grids/grid_core/views/const'; +import type { VirtualScrollingResizingControllerExtension } from '@ts/grids/grid_core/virtual_scrolling/types'; +import type { ElementOffset } from '@ts/ui/scroll_view/types'; import { HIDDEN_COLUMNS_WIDTH } from '../adaptivity/const'; import type { ColumnHeadersView } from '../column_headers/m_column_headers'; @@ -24,14 +35,30 @@ import { } from '../keyboard_navigation/utils'; import { CLASSES as MASTER_DETAIL_CLASSES } from '../master_detail/const'; import { isDetailRow } from '../master_detail/utils'; -import type { ModuleType } from '../types'; +import type { ColumnPoint, ColumnPointProps, ModuleType } from '../types'; import gridCoreUtils from '../utils'; import type { ColumnsView } from '../views/columns_view'; import type { RowsView } from '../views/rows_view'; import { isGroupRow } from '../views/rows_view'; -import type { RowsViewScrollEvent } from '../views/types'; +import type { + CellRenderOptions, + ColumnWidthsOptions, + ContextMenuItemsOptions, + GridContextMenuItem, + RowRenderOptions, + RowsViewScrollEvent, + SummaryRowsViewExtension, + ViewCellOptions, + ViewRow, +} from '../views/types'; import { CLASSES, StickyPosition } from './const'; import { GridCoreStickyColumnsDom } from './dom'; +import type { + StickyColumnHeadersView, + StickyColumnsColumnsViewExtension, + StickyOffsets, + StickyRowsView, +} from './types'; import { getColumnFixedPosition, getStickyOffset, @@ -44,11 +71,15 @@ import { processFixedColumns, } from './utils'; -const baseStickyColumns = >(Base: T) => class BaseStickyColumnsExtender extends Base { +const baseStickyColumns = >( + Base: T, +): T & ModuleType< + ColumnsView & StickyColumnsColumnsViewExtension +> => class BaseStickyColumnsExtender extends Base { private _addStickyColumnBorderLeftClass( $cell: dxElementWrapper, - column, - rowIndex: number, + column: Column, + rowIndex: number | null, onlyWithinBandColumn = false, fixedPosition?: StickyPosition, ): void { @@ -68,8 +99,8 @@ const baseStickyColumns = >(Base: T) => class private _addStickyColumnBorderRightClass( $cell: dxElementWrapper, - column, - rowIndex: number, + column: Column, + rowIndex: number | null, onlyWithinBandColumn = false, fixedPosition?: StickyPosition, ): void { @@ -147,64 +178,69 @@ const baseStickyColumns = >(Base: T) => class return deferred; } - protected _createCell(options) { - const { column } = options; - const { rowType } = options; + protected _createCell(options: ViewCellOptions): dxElementWrapper { + const { column, rowType } = options; const $cell = super._createCell(options); const hasStickyColumns = this.hasStickyColumns(); - const rowIndex = rowType === 'header' ? options.rowIndex : null; + const rowIndex = rowType === 'header' ? options.rowIndex ?? null : null; const isSummary = rowType === 'groupFooter' || rowType === 'totalFooter' || rowType === 'group'; - const isExpandColumn = column.command && column.command === 'expand'; + const isExpandColumn = column.command === 'expand'; + + if (!hasStickyColumns || needToDisableStickyColumn(this._columnsController, column)) { + return $cell; + } - if (hasStickyColumns && !needToDisableStickyColumn(this._columnsController, column)) { - this.toggleColumnNoBorderClass($cell, column, rowIndex); + this.toggleColumnNoBorderClass($cell, column, rowIndex); - if (column.fixed) { - const fixedPosition = getColumnFixedPosition(this._columnsController, column); + if (!column.fixed) { + return $cell; + } - GridCoreStickyColumnsDom.addStickyColumnClass( + const fixedPosition = getColumnFixedPosition(this._columnsController, column); + + GridCoreStickyColumnsDom.addStickyColumnClass( + $cell, + fixedPosition, + this.addWidgetPrefix.bind(this), + ); + + if (isSummary || isExpandColumn) { + return $cell; + } + + switch (fixedPosition) { + case StickyPosition.Right: { + this._addStickyColumnBorderLeftClass( $cell, - fixedPosition, - this.addWidgetPrefix.bind(this), + column, + rowIndex, + false, + StickyPosition.Right, + ); + break; + } + case StickyPosition.Sticky: { + this._addStickyColumnBorderLeftClass($cell, column, rowIndex, true); + this._addStickyColumnBorderRightClass($cell, column, rowIndex, true); + break; + } + default: { + this._addStickyColumnBorderRightClass( + $cell, + column, + rowIndex, + false, + StickyPosition.Left, ); - - if (!isSummary && !isExpandColumn) { - switch (fixedPosition) { - case StickyPosition.Right: { - this._addStickyColumnBorderLeftClass( - $cell, - column, - rowIndex, - false, - StickyPosition.Right, - ); - break; - } - case StickyPosition.Sticky: { - this._addStickyColumnBorderLeftClass($cell, column, rowIndex, true); - this._addStickyColumnBorderRightClass($cell, column, rowIndex, true); - break; - } - default: { - this._addStickyColumnBorderRightClass( - $cell, - column, - rowIndex, - false, - StickyPosition.Left, - ); - } - } - } } } return $cell; } - protected setStickyOffsets(rowIndex?: number, offsets?: Record>): void { + public setStickyOffsets(rowIndex?: number, offsets?: StickyOffsets): void { const columnsController = this._columnsController; - const rtlEnabled = this.option('rtlEnabled') as boolean; + const rtlEnabled = this.option('rtlEnabled'); const showColumnHeaders = this.option('showColumnHeaders'); let widths = this.getColumnWidths(undefined, rowIndex); let columns = this.getColumns(showColumnHeaders ? rowIndex : undefined); @@ -212,8 +248,8 @@ const baseStickyColumns = >(Base: T) => class columns = processFixedColumns(this._columnsController, columns); if (rtlEnabled) { - columns = rtlEnabled ? [...columns].reverse() : columns; - widths = rtlEnabled ? [...widths].reverse() : widths; + columns = [...columns].reverse(); + widths = [...widths].reverse(); } columns.forEach((column, columnIndex) => { @@ -232,7 +268,7 @@ const baseStickyColumns = >(Base: T) => class }); } - protected setColumnWidths(options): void { + protected setColumnWidths(options: ColumnWidthsOptions): void { const hasStickyColumns = this.hasStickyColumns(); const columnsResizerController = this.getController('columnsResizer'); const isColumnResizing = columnsResizerController?.isResizing(); @@ -249,7 +285,7 @@ const baseStickyColumns = >(Base: T) => class const hasHidingColumnsQueue = !!this.adaptiveColumnsController ?.getHidingColumnsQueue()?.length; - super._resizeCore.apply(this); + super._resizeCore(); if (!hasStickyColumns) { return; @@ -262,7 +298,8 @@ const baseStickyColumns = >(Base: T) => class } } - // TODO: Need to rename this method to hasFixedColumns after removing old fixed columns implementation + // TODO: Need to rename this method to hasFixedColumns + // after removing old fixed columns implementation public hasStickyColumns(): boolean { const stickyColumns = this._columnsController?.getStickyColumns(); @@ -272,27 +309,30 @@ const baseStickyColumns = >(Base: T) => class const columnHeadersView = ( Base: ModuleType, -) => class ColumnHeadersViewStickyColumnsExtender extends baseStickyColumns(Base) { - protected setStickyOffsets() { - const offsets: Record> = {}; +): ModuleType => class ColumnHeadersViewStickyColumnsExtender + extends baseStickyColumns(Base) { + public setStickyOffsets(): void { + const offsets: StickyOffsets = {}; const rows = this._getRows(); - for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) { + for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) { const isFilterRow = rows?.[rowIndex]?.rowType === 'filter'; super.setStickyOffsets(rowIndex, isFilterRow ? undefined : offsets); } } - public getContextMenuItems(options) { + public getContextMenuItems( + options: ContextMenuItemsOptions, + ): GridContextMenuItem[] | undefined { const { column } = options; const columnsController = this._columnsController; - const columnFixingOptions: any = this.option('columnFixing'); - let items: any = super.getContextMenuItems(options); + const columnFixingOptions = this.option('columnFixing'); + let items = super.getContextMenuItems(options); - if (options.row && options.row.rowType === 'header') { - if (columnFixingOptions.enabled === true && column && column.allowFixing) { - const onItemClick = (params) => { + if (options.row?.rowType === 'header') { + if (columnFixingOptions?.enabled === true && column && column.allowFixing) { + const onItemClick = (params: ItemClickEvent): void => { // eslint-disable-next-line default-case switch (params.itemData.value) { case 'none': @@ -318,17 +358,17 @@ const columnHeadersView = ( break; } }; - const fixedPositionItems = [ + const fixedPositionItems: GridContextMenuItem[] = [ { - text: columnFixingOptions.texts.leftPosition, - icon: columnFixingOptions.icons.leftPosition, + text: columnFixingOptions.texts?.leftPosition, + icon: columnFixingOptions.icons?.leftPosition, value: 'left', disabled: column.fixed && (!column.fixedPosition || column.fixedPosition === 'left'), onItemClick, }, { - text: columnFixingOptions.texts.rightPosition, - icon: columnFixingOptions.icons.rightPosition, + text: columnFixingOptions.texts?.rightPosition, + icon: columnFixingOptions.icons?.rightPosition, value: 'right', disabled: column.fixed && column.fixedPosition === 'right', onItemClick, @@ -337,25 +377,25 @@ const columnHeadersView = ( if (this.option('columnFixing.legacyMode') !== true && !columnsController.isVirtualMode()) { fixedPositionItems.push({ - text: columnFixingOptions.texts.stickyPosition, - icon: columnFixingOptions.icons.stickyPosition, + text: columnFixingOptions.texts?.stickyPosition, + icon: columnFixingOptions.icons?.stickyPosition, value: 'sticky', disabled: column.fixed && column.fixedPosition === StickyPosition.Sticky, onItemClick, }); } - items = items || []; + items ??= []; items.push( { - text: columnFixingOptions.texts.fix, - icon: columnFixingOptions.icons.fix, + text: columnFixingOptions.texts?.fix, + icon: columnFixingOptions.icons?.fix, beginGroup: true, items: fixedPositionItems, }, { - text: columnFixingOptions.texts.unfix, - icon: columnFixingOptions.icons.unfix, + text: columnFixingOptions.texts?.unfix, + icon: columnFixingOptions.icons?.unfix, value: 'none', disabled: !column.fixed, onItemClick, @@ -368,8 +408,9 @@ const columnHeadersView = ( }; const rowsView = ( - Base: ModuleType, -) => class RowsViewStickyColumnsExtender extends baseStickyColumns(Base) { + Base: ModuleType, +): ModuleType => class RowsViewStickyColumnsExtender + extends baseStickyColumns(Base) { private _getMasterDetailWidth(): number { const componentWidth = getWidth(this.component.$element().get(0)) ?? 0; const borderWidth = gridCoreUtils.getComponentBorderWidth(this, this._$element); @@ -377,9 +418,12 @@ const rowsView = ( return componentWidth - borderWidth - this.getScrollbarWidth(); } - protected _renderMasterDetailCell($row, row, options): dxElementWrapper { - // @ts-expect-error - const $detailCell: dxElementWrapper = super._renderMasterDetailCell($row, row, options); + public renderMasterDetailCell( + $row: dxElementWrapper, + row: ViewRow, + options: RowRenderOptions, + ): dxElementWrapper { + const $detailCell = super.renderMasterDetailCell($row, row, options); if (this.hasStickyColumns()) { const detailContainerSelector = `.${this.addWidgetPrefix(MASTER_DETAIL_CLASSES.detailContainer)}`; @@ -393,7 +437,7 @@ const rowsView = ( return $detailCell; } - private _updateMasterDetailWidths() { + private _updateMasterDetailWidths(): void { const $detailContainers = this._getRowElements() .children(`.${MASTER_DETAIL_CLASSES.detailCell}`) .children(`.${this.addWidgetPrefix(MASTER_DETAIL_CLASSES.detailContainer)}`); @@ -406,12 +450,12 @@ const rowsView = ( ); } - protected setStickyOffsets(rowIndex?: number, offsets?: Record>) { + public setStickyOffsets(rowIndex?: number, offsets?: StickyOffsets): void { super.setStickyOffsets(rowIndex, offsets); this.setStickyOffsetsForGroupCells(); } - private setStickyOffsetsForGroupCells() { + private setStickyOffsetsForGroupCells(): void { const groupColumns = this._columnsController.getGroupColumns(); let columns = this.getColumns(); let widths = this.getColumnWidths(); @@ -420,11 +464,15 @@ const rowsView = ( const rtlEnabled = this.option('rtlEnabled'); if (rtlEnabled) { - columns = rtlEnabled ? [...columns].reverse() : columns; - widths = rtlEnabled ? [...widths].reverse() : widths; + columns = [...columns].reverse(); + widths = [...widths].reverse(); } - const $tableElement = this.getTableElement()!; + const $tableElement = this.getTableElement(); + + if (!$tableElement?.length) { + return; + } groupColumns.forEach((column) => { const columnIndex = columnsCountBeforeGroups + column.groupIndex + 1; @@ -445,17 +493,21 @@ const rowsView = ( }); } - protected _resizeCore() { + protected _resizeCore(): void { const hasStickyColumns = this.hasStickyColumns(); - super._resizeCore.apply(this, arguments as any); + super._resizeCore(); if (hasStickyColumns) { this._updateMasterDetailWidths(); } } - protected _renderCellContent($cell, options, renderOptions) { + protected _renderCellContent( + $cell: dxElementWrapper, + options: ViewCellOptions, + renderOptions: CellRenderOptions, + ): void { const hasStickyColumns = this.hasStickyColumns(); const isGroupRowResult = isGroupRow(options); const isDetailRowResult = isDetailRow(options); @@ -473,9 +525,18 @@ const rowsView = ( return super._renderCellContent($container, options, renderOptions); } - protected _renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount) { - // @ts-expect-error - super._renderGroupSummaryCellsCore($groupCell, options, groupCellColSpan, alignByColumnCellCount); + public renderGroupSummaryCellsCore( + $groupCell: dxElementWrapper, + options: RowRenderOptions, + groupCellColSpan: number, + alignByColumnCellCount: number, + ): void { + super.renderGroupSummaryCellsCore( + $groupCell, + options, + groupCellColSpan, + alignByColumnCellCount, + ); const stickySummarySelector = `.${this.addWidgetPrefix(CLASSES.stickyColumn)}`; if ( @@ -504,7 +565,7 @@ const rowsView = ( } } - public _scrollToElement($element, offset?) { + public _scrollToElement($element: dxElementWrapper, offset?: ElementOffset): void { let scrollOffset = offset; const scrollable = this.getScrollable(); const hasStickyColumns = this.hasStickyColumns(); @@ -528,11 +589,16 @@ const rowsView = ( } }; -const footerView = ( - Base: ModuleType, -) => class FooterViewStickyColumnsExtender extends baseStickyColumns(Base) {}; +const footerView = >( + Base: T, +): T => class FooterViewStickyColumnsExtender extends baseStickyColumns(Base) {}; + +const columnsResizer = ( + Base: ModuleType, +): ModuleType => class ColumnResizerStickyColumnsExtender + extends Base { + protected declare _columnHeadersView: StickyColumnHeadersView; -const columnsResizer = (Base: ModuleType) => class ColumnResizerStickyColumnsExtender extends Base { private isNextCellPinned($nextCell: dxElementWrapper, $container: dxElementWrapper): boolean { const addWidgetPrefix = this.addWidgetPrefix.bind(this); @@ -542,7 +608,6 @@ const columnsResizer = (Base: ModuleType) => class } protected getSeparatorOffsetX($cell: dxElementWrapper, $nextCell: dxElementWrapper): number { - // @ts-expect-error const hasStickyColumns = this._columnHeadersView?.hasStickyColumns(); if (hasStickyColumns) { @@ -569,7 +634,11 @@ const columnsResizer = (Base: ModuleType) => class return super.getSeparatorOffsetX($cell, $nextCell); } - protected _correctColumnIndexForPoint(point, correctionValue: number, columns): void { + protected _correctColumnIndexForPoint( + point: ColumnPointProps, + correctionValue: number, + columns: Column[], + ): void { const rtlEnabled = this.option('rtlEnabled'); const isWidgetResizingMode = this.option('columnResizingMode') === 'widget'; const columnIndex = Math.max(point.index - 1, 0); @@ -613,14 +682,16 @@ const columnsResizer = (Base: ModuleType) => class } protected _generatePointsByColumns(): void { - // @ts-expect-error const hasStickyColumns = this._columnHeadersView?.hasStickyColumns(); super._generatePointsByColumns(hasStickyColumns); } - protected _pointCreated(point, columns, cells?: dxElementWrapper) { - // @ts-expect-error + protected _pointCreated( + point: ColumnPointProps, + columns: Column[], + cells?: dxElementWrapper, + ): boolean { const hasStickyColumns = this._columnHeadersView?.hasStickyColumns(); const result = super._pointCreated(point, columns, cells); const cellsLength = cells?.length ?? columns.length; @@ -647,9 +718,13 @@ const columnsResizer = (Base: ModuleType) => class } }; -const draggingHeader = (Base: ModuleType) => class DraggingHeaderStickyColumnsExtender extends Base { - public _generatePointsByColumns(options): any[] { - // @ts-expect-error +const draggingHeader = ( + Base: ModuleType, +): ModuleType => class DraggingHeaderStickyColumnsExtender + extends Base { + protected declare _columnHeadersView: StickyColumnHeadersView; + + public _generatePointsByColumns(options: DraggingPointsOptions): ColumnPoint[] { const hasStickyColumns = this._columnHeadersView?.hasStickyColumns(); const { sourceLocation, sourceColumn, targetDraggingPanel } = options; const isDraggingBetweenHeaders = sourceLocation === 'headers' && targetDraggingPanel?.getName() === 'headers'; @@ -686,11 +761,10 @@ const draggingHeader = (Base: ModuleType) => class protected _pointCreated({ point, columns, location, sourceColumn, cells, - }) { - // @ts-expect-error + }: DraggingPointCreatedOptions): boolean { const hasStickyColumns = this._columnHeadersView.hasStickyColumns(); const needToCheckPoint = hasStickyColumns && location === 'headers' && cells?.length - && (!sourceColumn.fixed || sourceColumn.fixedPosition === StickyPosition.Sticky); + && (!sourceColumn?.fixed || sourceColumn.fixedPosition === StickyPosition.Sticky); const result = super._pointCreated({ point, columns, location, sourceColumn, }); @@ -708,9 +782,12 @@ const draggingHeader = (Base: ModuleType) => class } }; -const editorFactory = (Base: ModuleType) => class EditorFactoryStickyColumnsExtender extends Base { +const editorFactory = ( + Base: ModuleType, +): ModuleType => class EditorFactoryStickyColumnsExtender extends Base { + protected declare _rowsView: StickyRowsView; + private getOverlayContainerIfNeeded($cell: dxElementWrapper): dxElementWrapper | undefined { - // @ts-expect-error const hasFixedColumns = this._rowsView.hasStickyColumns(); const isFixedCell = GridCoreStickyColumnsDom.isFixedCell( $cell, @@ -724,8 +801,7 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt return undefined; } - protected updateFocusOverlaySize($element, position): void { - // @ts-expect-error + protected updateFocusOverlaySize($element: dxElementWrapper, position: object): void { const hasFixedColumns = this._rowsView.hasStickyColumns(); if (!hasFixedColumns) { @@ -734,7 +810,6 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt } protected getFocusOverlaySize($element: dxElementWrapper): { width: number; height: number } { - // @ts-expect-error const hasFixedColumns = this._rowsView.hasStickyColumns(); if (hasFixedColumns) { @@ -744,9 +819,9 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt $element, this.addWidgetPrefix.bind(this), ); - const isGroupRow = isGroupRowElement($element); + const isGroupElement = isGroupRowElement($element); const isGroupFooter = isGroupFooterRow($element); - const noExtraWidth = isLastCell || isFixedCell || isGroupRow || isGroupFooter; + const noExtraWidth = isLastCell || isFixedCell || isGroupElement || isGroupFooter; return { width: elementRect.right - elementRect.left + (noExtraWidth ? 0 : 1), @@ -757,21 +832,17 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt return super.getFocusOverlaySize($element); } - protected getValidationMessageContainer($cell: dxElementWrapper): dxElementWrapper { - // @ts-expect-error + public getValidationMessageContainer($cell: dxElementWrapper): dxElementWrapper { return this.getOverlayContainerIfNeeded($cell) ?? super.getValidationMessageContainer($cell); } - protected getRevertButtonContainer($cell: dxElementWrapper): dxElementWrapper { - // @ts-expect-error + public getRevertButtonContainer($cell: dxElementWrapper): dxElementWrapper { return this.getOverlayContainerIfNeeded($cell) ?? super.getRevertButtonContainer($cell); } - protected overlayPositionedHandler(e, isOverlayVisible: boolean): void { - const columnHeaders = this.getView('columnHeadersView'); - // @ts-expect-error + public overlayPositionedHandler(e, isOverlayVisible: boolean): void { + const columnHeaders = this.getView('columnHeadersView') as StickyColumnHeadersView; const hasStickyColumns = columnHeaders.hasStickyColumns(); - // @ts-expect-error super.overlayPositionedHandler(e, isOverlayVisible); if (hasStickyColumns) { @@ -788,8 +859,7 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt this.addWidgetPrefix.bind(this), ); - // @ts-expect-error - $wrapper.css('zIndex', isOutsideVisibleArea ? 1 : this?.getOverlayBaseZIndex() ?? 0); + $wrapper.css('zIndex', isOutsideVisibleArea ? 1 : this.getOverlayBaseZIndex() ?? 0); } } } @@ -798,15 +868,13 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt if (!isHideBorder) { const isFixedCell = GridCoreStickyColumnsDom .isFixedCell($element, this.addWidgetPrefix.bind(this)); - // @ts-expect-error renderFocusOverlay creates the focus overlay first - this._$focusOverlay.toggleClass(CLASSES.focusedFixedElement, isFixedCell); + this._$focusOverlay?.toggleClass(CLASSES.focusedFixedElement, isFixedCell); const isGroupElement = isGroupRowElement($element); const isGroupFooterRowElement = isGroupFooterRow($element); const isAdaptiveElement = isAdaptiveItem($element); if (isFixedCell || isGroupElement || isGroupFooterRowElement || isAdaptiveElement) { - // @ts-expect-error renderFocusOverlay creates the focus overlay first - this._$focusOverlay.toggleClass(CLASSES.focusedFixedElement, true); + this._$focusOverlay?.toggleClass(CLASSES.focusedFixedElement, true); } } @@ -814,15 +882,18 @@ const editorFactory = (Base: ModuleType) => class EditorFactorySt } }; -const resizing = (Base: ModuleType) => class ResizingStickyColumnsExtender extends Base { +const resizing = ( + Base: ModuleType, +): ModuleType => class ResizingStickyColumnsExtender extends Base { + protected declare _columnHeadersView: StickyColumnHeadersView; + + protected declare _rowsView: StickyRowsView; + public resize(): DeferredObj { const result = super.resize(); - // @ts-expect-error ColumnHeadersView's method const hasStickyColumns = this._columnHeadersView.hasStickyColumns(); - // @ts-expect-error Resizing's method - if (hasStickyColumns && this?.hasResizeTimeout()) { - // @ts-expect-error RowsView's method + if (hasStickyColumns && this.hasResizeTimeout()) { this._rowsView.setStickyOffsets(); } @@ -830,9 +901,14 @@ const resizing = (Base: ModuleType) => class ResizingStickyC } }; -const headersKeyboardNavigation = (Base: ModuleType) => class HeadersKeyboardNavigationStickyColumnsExtender extends Base { - protected getContainerBoundingRect($container: dxElementWrapper) { - // @ts-expect-error columnHeadersView's method +const headersKeyboardNavigation = ( + Base: ModuleType, +): ModuleType< + HeadersKeyboardNavigationController +> => class HeadersKeyboardNavigationStickyColumnsExtender extends Base { + protected declare _columnHeadersView: StickyColumnHeadersView; + + protected getContainerBoundingRect($container: dxElementWrapper): HorizontalBounds { const hasStickyColumns = this._columnHeadersView?.hasStickyColumns(); if (hasStickyColumns) { @@ -852,8 +928,7 @@ const headersKeyboardNavigation = (Base: ModuleType>; + +export interface StickyColumnsColumnsViewExtension { + hasStickyColumns: () => boolean; + + // eslint-disable-next-line @typescript-eslint/method-signature-style -- overridden by methods + setStickyOffsets(rowIndex?: number, offsets?: StickyOffsets): void; +} + +export type StickyColumnHeadersView = ColumnHeadersView & StickyColumnsColumnsViewExtension; + +export type StickyRowsView = RowsView & StickyColumnsColumnsViewExtension; diff --git a/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/utils.ts b/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/utils.ts index c344289d88d2..c2acc5d35758 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/utils.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/sticky_columns/utils.ts @@ -4,6 +4,7 @@ import gridCoreUtils from '@ts/grids/grid_core/utils'; import { HIDDEN_COLUMNS_WIDTH } from '../adaptivity/const'; import type { ColumnsController } from '../columns_controller/columns_controller'; import { STICKY_BORDER_WIDTH, StickyPosition } from './const'; +import type { StickyOffsets } from './types'; export const getColumnFixedPosition = ( that: ColumnsController, @@ -69,7 +70,7 @@ const getStickyOffsetCore = function ( widths: number[], columnIndex: number, fixedPosition: StickyPosition, - offsets?: Record>, + offsets?: StickyOffsets, ): number { const column = columns[columnIndex]; const isChildColumn = isDefined(column.ownerBand); @@ -115,9 +116,8 @@ const getStickyOffsetCore = function ( const isFirstOrLastColumn = function ( that: ColumnsController, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types column, - rowIndex: number, + rowIndex: number | null, onlyWithinBandColumn = false, isLast = false, fixedPosition?: StickyPosition, @@ -156,7 +156,7 @@ export const getStickyOffset = function ( columns: any[], widths: number[], columnIndex: number, - offsets?: Record>, + offsets?: StickyOffsets, ): Record { const result: Record = {}; const column = columns[columnIndex]; @@ -274,7 +274,7 @@ export const isFirstFixedColumn = function ( that: ColumnsController, // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types column, - rowIndex: number, + rowIndex: number | null, onlyWithinBandColumn = false, fixedPosition?: StickyPosition, ): boolean { @@ -285,7 +285,7 @@ export const isLastFixedColumn = function ( that: ColumnsController, // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types column, - rowIndex: number, + rowIndex: number | null, onlyWithinBandColumn = false, fixedPosition?: StickyPosition, ): boolean { diff --git a/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts b/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts index 740bfe442790..c0011b72f9e3 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts @@ -49,6 +49,7 @@ import { VALIDATION_STATUS, validationResultIsValid, } from './const'; +import type { ValidatingEditorFactoryExtension } from './types'; const REVERT_TOOLTIP_CLASS = 'revert-tooltip'; const INVALID_MESSAGE_CLASS = 'dx-invalid-message'; @@ -1131,7 +1132,11 @@ const getBoundaryNonFixedColumnsInfo = function (fixedColumns) { }; }; -export const validatingEditorFactoryExtender = (Base: ModuleType) => class ValidatingEditorFactoryExtender extends Base { +export const validatingEditorFactoryExtender = ( + Base: ModuleType, +): ModuleType< + EditorFactory & ValidatingEditorFactoryExtension +> => class ValidatingEditorFactoryExtender extends Base { private _revertTooltip: any; private _showRevertButton($container) { @@ -1353,11 +1358,11 @@ export const validatingEditorFactoryExtender = (Base: ModuleType) } } - protected getOverlayBaseZIndex(): number { + public getOverlayBaseZIndex(): number { return Overlay.baseZIndex(); } - protected overlayPositionedHandler(e, isOverlayVisible) { + public overlayPositionedHandler(e, isOverlayVisible) { if (!e.component.__skipPositionProcessing) { const isRevertButton = $(e.element).hasClass(this.addWidgetPrefix(REVERT_TOOLTIP_CLASS)); const needRepaint = !isRevertButton && this._rowsView.updateFreeSpaceRowHeight(); @@ -1511,11 +1516,11 @@ export const validatingEditorFactoryExtender = (Base: ModuleType) return gridCoreUtils.getWidgetInstance($editor); } - protected getValidationMessageContainer($cell: dxElementWrapper): dxElementWrapper { + public getValidationMessageContainer($cell: dxElementWrapper): dxElementWrapper { return $cell.closest(`.${this.addWidgetPrefix(VIEW_CLASSES.content)}`); } - protected getRevertButtonContainer($cell: dxElementWrapper): dxElementWrapper { + public getRevertButtonContainer($cell: dxElementWrapper): dxElementWrapper { return $cell.closest(`.${this.addWidgetPrefix(VIEW_CLASSES.content)}`).parent(); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/validating/types.ts b/packages/devextreme/js/__internal/grids/grid_core/validating/types.ts new file mode 100644 index 000000000000..22cdb2243b3d --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/validating/types.ts @@ -0,0 +1,15 @@ +import type { dxElementWrapper } from '@js/core/renderer'; +import type { PositioningEvent } from '@ts/ui/overlay/overlay'; + +export interface ValidatingEditorFactoryExtension { + getOverlayBaseZIndex: () => number; + + // eslint-disable-next-line @typescript-eslint/method-signature-style -- overridden by methods + overlayPositionedHandler(e: PositioningEvent, isOverlayVisible: boolean): void; + + // eslint-disable-next-line @typescript-eslint/method-signature-style -- overridden by methods + getValidationMessageContainer($cell: dxElementWrapper): dxElementWrapper; + + // eslint-disable-next-line @typescript-eslint/method-signature-style -- overridden by methods + getRevertButtonContainer($cell: dxElementWrapper): dxElementWrapper; +} diff --git a/packages/devextreme/js/__internal/grids/grid_core/views/types.ts b/packages/devextreme/js/__internal/grids/grid_core/views/types.ts index 72b4e9d0f3ab..ddd467dd858f 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/views/types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/views/types.ts @@ -216,6 +216,17 @@ export interface GroupContinuationData { /** @architectureLeak data_grid: group cells show the grouping continuation texts */ export type RowsViewOptions = InternalGridOptions & Pick; +/** @architectureLeak data_grid/summary: core extenders adjust the group summary cells */ +export interface SummaryRowsViewExtension { + // eslint-disable-next-line @typescript-eslint/method-signature-style -- overridden by methods + renderGroupSummaryCellsCore( + $groupCell: dxElementWrapper, + options: RowRenderOptions, + groupCellColSpan: number, + alignByColumnCellCount: number, + ): void; +} + // the grid passes loadPanel options to the LoadPanel widget, so its animation applies too export type RowsViewLoadPanelOptions = LoadPanel & Pick; diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts index eb7770d2faf1..c0c0618fa731 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts @@ -33,6 +33,7 @@ import { VIRTUAL_ROW_CLASS, } from './const'; import { subscribeToExternalScrollers, VirtualScrollController } from './m_virtual_scrolling_core'; +import type { VirtualScrollingResizingControllerExtension } from './types'; import { isItemCountableByDataSource } from './utils/items'; import { isInfiniteMode, isVirtualMode, isVirtualPaging } from './utils/scrolling_mode'; @@ -428,7 +429,11 @@ export const dataSourceAdapterExtender = (Base: ModuleType) = } }; -export const resizing = (Base: ModuleType) => class VirtualScrollingResizingControllerExtender extends Base { +export const resizing = ( + Base: ModuleType, +): ModuleType< + ResizingController & VirtualScrollingResizingControllerExtension +> => class VirtualScrollingResizingControllerExtender extends Base { private _resizeTimeout: any; private _lastTime: any; @@ -453,7 +458,7 @@ export const resizing = (Base: ModuleType) => class VirtualS }); } - private hasResizeTimeout() { + public hasResizeTimeout(): boolean { return isDefined(this._resizeTimeout); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/types.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/types.ts index 31cc0ab1e819..41560464b0c8 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/types.ts @@ -2,3 +2,7 @@ export interface ChangedLoadParams { pageIndex: number; loadPageCount: number; } + +export interface VirtualScrollingResizingControllerExtension { + hasResizeTimeout: () => boolean; +}