Skip to content
Open
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
264 changes: 163 additions & 101 deletions packages/devextreme/js/__internal/common/core/animation/m_position.ts

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions packages/devextreme/js/__internal/common/core/animation/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { dxElementWrapper } from '@js/core/renderer';
import type { DxEvent } from '@js/events';

export type PositionTarget = string | EventTarget | dxElementWrapper | null | undefined;

export type CollisionSide = 'left' | 'right' | 'top' | 'bottom' | 'none';

export interface AxisPositionResult {
location: number;
flip: boolean;
fit: boolean;
oversize: number;
collisionSide?: CollisionSide;
}

export interface PositionResult {
h: AxisPositionResult;
v: AxisPositionResult;
precise?: boolean;
}

export interface PositionOptions {
my?: unknown;
at?: unknown;
of?: PositionTarget | DxEvent;
offset?: unknown;
collision?: unknown;
boundary?: PositionTarget | 0;
boundaryOffset?: unknown;
precise?: boolean;
h?: undefined;
v?: undefined;
}

export interface AxisPositionData {
mySize: number;
myAlign: string;
atAlign: string;
offset: number;
collision: string;
boundaryOffset: number;
atLocation: number;
atSize: number;
myLocation: number;
oversize: number;
collisionSide?: CollisionSide;
fit?: boolean;
flip?: boolean;
}

export interface AxisBounds {
min: number;
max: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ class CollectionWidget<
}

_getCombinedFilter(): unknown {
// @ts-expect-error arguments
return this._dataController.filter();
}

Expand Down Expand Up @@ -272,7 +271,7 @@ class CollectionWidget<
options.userData = dataController.userData();

if (dataController.store()) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
// @ts-expect-error the store is typed for StoreLoadOptions and unknown items
return dataController.loadFromStore(options).done((loadResult) => {
if (that._disposed) {
return;
Expand All @@ -284,8 +283,7 @@ class CollectionWidget<
}
return Deferred<TItem[]>().resolve(this.plainItems());
},
// eslint-disable-next-line @stylistic/max-len
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/explicit-function-return-type
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
dataFields: () => this._dataController.select(),
plainItems: itemsGetter.bind(this._editStrategy),
});
Expand Down Expand Up @@ -816,7 +814,6 @@ class CollectionWidget<
_refreshLastPage(): DeferredObj<unknown> {
this._expectLastItemLoading();

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return this._dataController.load();
}

Expand Down
104 changes: 62 additions & 42 deletions packages/devextreme/js/__internal/ui/collection/m_data_controller.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { noop } from '@js/core/utils/common';
import type { DeferredObj } from '@js/core/utils/deferred';
import { Deferred } from '@js/core/utils/deferred';
import type Store from '@ts/data/abstract_store';
import type { StoreKey } from '@ts/data/abstract_store';
import type { DataSource } from '@ts/data/data_source/data_source';
import type { DataSourceEventName, StoreLoadOptions } from '@ts/data/data_source/types';

const DataControllerMock = {
load: () => Deferred().reject(),
loadSingle: () => Deferred().reject(),
loadFromStore: () => Deferred().reject(),
loadNextPage: () => Deferred().reject(),
load: (): DeferredObj<unknown> => Deferred().reject(),
loadSingle: (): DeferredObj<unknown> => Deferred().reject(),
loadFromStore: (): DeferredObj<unknown> => Deferred().reject(),
loadNextPage: (): DeferredObj<unknown> => Deferred().reject(),
loadOptions: noop,
userData: noop,
cancel: noop,
Expand Down Expand Up @@ -37,160 +42,175 @@ const DataControllerMock = {
};

class DataController {
_dataSource: any;
private readonly _dataSource!: DataSource;

constructor(dataSource) {
constructor(dataSource: DataSource | null | undefined) {
if (!dataSource) {
// @ts-expect-error
// @ts-expect-error the mock has the same methods, all of them no-ops
// eslint-disable-next-line no-constructor-return
return DataControllerMock;
}
this._dataSource = dataSource;
}

load() {
load(): DeferredObj<unknown> {
return this._dataSource.load();
}

loadSingle(propName, propValue) {
loadSingle(propName: unknown, propValue?: unknown): DeferredObj<unknown> {
if (arguments.length < 2) {
propValue = propName;
propName = this.key();
return this._dataSource.loadSingle(this.key(), propName);
}

return this._dataSource.loadSingle(propName, propValue);
}

loadFromStore(loadOptions) {
loadFromStore(loadOptions?: StoreLoadOptions): DeferredObj<unknown[]> {
return this.store().load(loadOptions);
}

loadNextPage() {
loadNextPage(): DeferredObj<unknown> {
this.pageIndex(1 + this.pageIndex());

return this.load();
}

loadOptions() {
loadOptions(): StoreLoadOptions {
return this._dataSource.loadOptions();
}

userData() {
userData(): Record<string, unknown> {
return this._dataSource._userData;
}

cancel(operationId) {
cancel(operationId: number): void {
this._dataSource.cancel(operationId);
}

cancelAll() {
cancelAll(): void {
this._dataSource.cancelAll();
}

filter(filter) {
filter(filter?: undefined): StoreLoadOptions['filter'];
filter(filter: NonNullable<StoreLoadOptions['filter']>): void;
filter(filter?: StoreLoadOptions['filter']): StoreLoadOptions['filter'] {
return this._dataSource.filter(filter);
}

addSearchFilter(storeLoadOptions) {
addSearchFilter(storeLoadOptions: StoreLoadOptions): void {
this._dataSource._addSearchFilter(storeLoadOptions);
}

group(group?) {
group(group?: undefined): StoreLoadOptions['group'];
group(group: NonNullable<StoreLoadOptions['group']>): void;
group(group?: StoreLoadOptions['group']): StoreLoadOptions['group'] {
// @ts-expect-error DataSource accessors are typed without the undefined getter argument
return this._dataSource.group(group);
}

paginate() {
paginate(): boolean | undefined {
return this._dataSource.paginate();
}

pageSize() {
pageSize(): number {
return this._dataSource._pageSize;
}

pageIndex(pageIndex?: number) {
pageIndex(): number;
pageIndex(pageIndex: number): void;
pageIndex(pageIndex?: number): number | undefined {
// @ts-expect-error DataSource accessors are typed without the undefined getter argument
return this._dataSource.pageIndex(pageIndex);
}

resetDataSourcePageIndex() {
resetDataSourcePageIndex(): void {
if (this.pageIndex()) {
this.pageIndex(0);
this.load();
}
}

totalCount() {
totalCount(): number {
return this._dataSource.totalCount();
}

isLastPage() {
isLastPage(): boolean {
return this._dataSource.isLastPage() || !this._dataSource._pageSize;
}

isLoading() {
isLoading(): boolean {
return this._dataSource.isLoading();
}

isLoaded() {
isLoaded(): boolean {
return this._dataSource.isLoaded();
}

searchValue(value) {
searchValue(): StoreLoadOptions['searchValue'];
searchValue(value: StoreLoadOptions['searchValue']): void;
searchValue(value?: StoreLoadOptions['searchValue']): StoreLoadOptions['searchValue'] {
if (!arguments.length) {
return this._dataSource.searchValue();
}

return this._dataSource.searchValue(value);
}

searchOperation(operation) {
searchOperation(operation?: unknown): StoreLoadOptions['searchOperation'] {
// @ts-expect-error DataSource.searchOperation() treats a non-string argument as the getter
return this._dataSource.searchOperation(operation);
}

searchExpr(expr) {
searchExpr(): StoreLoadOptions['searchExpr'];
searchExpr(expr: NonNullable<StoreLoadOptions['searchExpr']>): void;
searchExpr(expr?: StoreLoadOptions['searchExpr']): StoreLoadOptions['searchExpr'] {
if (!arguments.length) {
return this._dataSource.searchExpr();
}

// @ts-expect-error DataSource.searchExpr() is typed without an array or undefined argument
return this._dataSource.searchExpr(expr);
}

select() {
return this._dataSource.select(...arguments);
select(): StoreLoadOptions['select'];
select(...selectExpr: NonNullable<StoreLoadOptions['select']>[]): void;
select(...selectExpr: NonNullable<StoreLoadOptions['select']>[]): unknown {
return this._dataSource.select(...selectExpr);
}

key() {
key(): StoreKey | undefined {
return this._dataSource.key();
}

keyOf(item) {
keyOf(item: unknown): unknown {
return this.store().keyOf(item);
}

store() {
store(): Store {
return this._dataSource.store();
}

items() {
items(): unknown[] {
return this._dataSource.items();
}

applyMapFunction(data) {
applyMapFunction(data: unknown[]): unknown[] {
return this._dataSource._applyMapFunction(data);
}

getDataSource() {
getDataSource(): DataSource | null {
return this._dataSource || null;
}

reload() {
reload(): DeferredObj<unknown> {
return this._dataSource.reload();
}

on(event, handler): void {
on(event: DataSourceEventName, handler: Function): void {
this._dataSource.on(event, handler);
}

off(event, handler): void {
off(event: DataSourceEventName, handler?: Function): void {
this._dataSource.off(event, handler);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1001,12 +1001,15 @@ class DropDownEditor<
let positionSide = 'bottom';

if (this._popup?.option('visible')) {
const { top: myTop } = animationPosition.setup(this.$element());
const myOffset = animationPosition.setup(this.$element());

const { top: popupTop } = animationPosition.setup(this._popup.$content());
const { popupPosition } = this.option();
// @ts-expect-error Should be updated on PositionConfig level
positionSide = (myTop + popupPosition.offset.v) > popupTop ? 'bottom' : 'top';
const popupOffset = animationPosition.setup(this._popup.$content());

if (myOffset && popupOffset) {
const { popupPosition } = this.option();
// @ts-expect-error Should be updated on PositionConfig level
positionSide = (myOffset.top + popupPosition.offset.v) > popupOffset.top ? 'bottom' : 'top';
}
}

return positionSide;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ class DropDownList<
const isMinSearchLengthExceeded = this._isMinSearchLengthExceeded();
const { showDataBeforeSearch, minSearchLength } = this.option();

return this._dataController.isLoaded() as boolean
return this._dataController.isLoaded()
&& Boolean(showDataBeforeSearch)
&& Boolean(minSearchLength)
&& !isMinSearchLengthExceeded
Expand Down Expand Up @@ -877,7 +877,6 @@ class DropDownList<
_clearFilter(): void {
const dataController = this._dataController;

// @ts-expect-error fix argument type in m_data_controller.ts
if (dataController.searchValue()) {
dataController.searchValue(null);
}
Expand Down Expand Up @@ -963,7 +962,7 @@ class DropDownList<
const dataController = this._dataController;
const currentPageIndex = dataController.pageIndex();
const needRepaint = (isDefined(this._pageIndex) && currentPageIndex <= this._pageIndex)
|| (dataController.isLastPage() as boolean && !this._list?._scrollViewIsFull());
|| (dataController.isLastPage() && !this._list?._scrollViewIsFull());

this._pageIndex = currentPageIndex;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class ListSearch extends ListEdit {
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types
_getCombinedFilter() {
const dataController = this._dataController;
// @ts-expect-error ts-error
const storeLoadOptions = { filter: dataController.filter() };
dataController.addSearchFilter(storeLoadOptions);
const { filter } = storeLoadOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
DxEvent,
PointerInteractionEvent,
} from '@js/events';
import type { PositionResult } from '@ts/common/core/animation/types';
import swatch from '@ts/core/utils/swatch_container';
import windowUtils from '@ts/core/utils/window';
import type {
Expand Down Expand Up @@ -142,7 +143,7 @@ export class OverlayPositionController<

_visualPosition?: Coordinates;

_initialPosition?: OverlayPosition;
_initialPosition?: Coordinates | PositionResult;

_previousVisualPosition?: Coordinates;

Expand Down
Loading
Loading