diff --git a/packages/devextreme/js/__internal/core/widget/widget.ts b/packages/devextreme/js/__internal/core/widget/widget.ts index 1b3fe71e4dcb..9af6f1b88503 100644 --- a/packages/devextreme/js/__internal/core/widget/widget.ts +++ b/packages/devextreme/js/__internal/core/widget/widget.ts @@ -427,8 +427,7 @@ class Widget< // eslint-disable-next-line @typescript-eslint/no-unsafe-return keyboardListeners.forEach((listener) => listener?._keyboardHandler(options)); - // eslint-disable-next-line @typescript-eslint/no-unused-expressions - onKeyboardHandled && onKeyboardHandled(options); + onKeyboardHandled?.(options); return true; } @@ -570,13 +569,12 @@ class Widget< this.$element().toggleClass('dx-state-independent', ignoreParentReadOnly); } - _setWidgetOption(widgetName: string, args: Record): void { + _setWidgetOption(widgetName: string, args: [string, unknown?] | [Record]): void { if (!this[widgetName]) { return; } if (isPlainObject(args[0])) { - // @ts-expect-error each(args[0], (option, value) => this._setWidgetOption(widgetName, [option, value])); return; diff --git a/packages/devextreme/js/__internal/data/data_controller/data_controller.ts b/packages/devextreme/js/__internal/data/data_controller/data_controller.ts index 0730af1df864..535c78cbcfef 100644 --- a/packages/devextreme/js/__internal/data/data_controller/data_controller.ts +++ b/packages/devextreme/js/__internal/data/data_controller/data_controller.ts @@ -6,7 +6,7 @@ import { normalizeDataSourceOptions } from '../../../common/data/data_source/uti import { extend } from '../../../core/utils/extend'; import { isDefined } from '../../../core/utils/type'; -interface DataSourceType { +export interface DataSourceType { _userData: unknown; _pageSize: number; dispose: () => void; @@ -47,7 +47,6 @@ interface DataControllerOptions extends Record { class DataController { private _isSharedDataSource = false; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error private _dataSource: DataSourceType; @@ -75,7 +74,6 @@ class DataController { } _updateDataSourceByItems(items: unknown[]): void { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment this._dataSource = new DataSource({ store: new ArrayStore({ key: this.key(), @@ -93,7 +91,6 @@ class DataController { this._dataSource.dispose(); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error delete this._dataSource; } @@ -126,9 +123,8 @@ class DataController { } loadNextPage(): Promise { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands + this.pageIndex(1 + this.pageIndex()); return this.load(); @@ -189,7 +185,7 @@ class DataController { } } - updateDataSource(items: unknown[] | DataSourceType, key?: string): void { + updateDataSource(items?: unknown[] | DataSourceType, key?: string): void { const dataSourceOptions = items ?? this.items(); if (key) { diff --git a/packages/devextreme/js/__internal/events/utils/index.ts b/packages/devextreme/js/__internal/events/utils/index.ts index 454fd02018f7..7807a327c7d3 100644 --- a/packages/devextreme/js/__internal/events/utils/index.ts +++ b/packages/devextreme/js/__internal/events/utils/index.ts @@ -98,7 +98,7 @@ export const isPointerEvent = (e) => eventSource(e) === 'pointer'; export const isMouseEvent = (e) => isNativeMouseEvent(e) || ((isPointerEvent(e) || isDxEvent(e)) && e.pointerType === 'mouse'); -export const isDxMouseWheelEvent = (e) => e && e.type === 'dxmousewheel'; +export const isDxMouseWheelEvent = (e) => e?.type === 'dxmousewheel'; export const isTouchEvent = (e) => isNativeTouchEvent(e) || ((isPointerEvent(e) || isDxEvent(e)) && e.pointerType === 'touch'); diff --git a/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_editor.ts b/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_editor.ts index 593c5935cbdb..4d1739806f08 100644 --- a/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_editor.ts +++ b/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_editor.ts @@ -908,7 +908,7 @@ class DropDownEditor< toolbarItems: this._getPopupToolbarItems(), onPositioned: this._popupPositionedHandler.bind(this), fullScreen: false, - // @ts-expect-error should be added on Popup level + // @ts-expect-error Should be updated on public PopupProperties level contentTemplate: null, _hideOnParentScrollTarget: this.$element(), _wrapperClassExternal: DROP_DOWN_EDITOR_OVERLAY, @@ -1040,7 +1040,6 @@ class DropDownEditor< } _setPopupOption(...args: [string, unknown?]): void { - // @ts-expect-error Should be fixed on Widget level this._setWidgetOption('_popup', args); } diff --git a/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_list.ts b/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_list.ts index 2d2f48d7e5ee..901eaf5a0134 100644 --- a/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_list.ts +++ b/packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_list.ts @@ -57,7 +57,6 @@ interface DropDownListProperties extends Omit extends DropDownEditor { @@ -417,7 +416,7 @@ class DropDownList< } _displayValue(item: Item): string { - // @ts-expect-error refactor DataExpressionMixin + // @ts-expect-error DataExpressionMixin must be typed return this._displayGetter(item) as string; } @@ -696,7 +695,6 @@ class DropDownList< ): void; _setListOption(optionName: string, value?: unknown): void; _setListOption(...args: [string, unknown?]): void { - // @ts-expect-error fix on Widget level this._setWidgetOption('_list', args); } @@ -1026,7 +1024,7 @@ class DropDownList< _setSubmitValue(): void { const { value } = this.option(); - // @ts-expect-error refactor DataExpressionMixin + // @ts-expect-error DataExpressionMixin must be typed const submitValue = this._shouldUseDisplayValue(value) ? this._displayGetter(value) : value; this._getSubmitElement().val(submitValue); diff --git a/packages/devextreme/js/__internal/ui/m_autocomplete.ts b/packages/devextreme/js/__internal/ui/m_autocomplete.ts index 6d9f871f3011..d2f13d8008fd 100644 --- a/packages/devextreme/js/__internal/ui/m_autocomplete.ts +++ b/packages/devextreme/js/__internal/ui/m_autocomplete.ts @@ -1,30 +1,39 @@ -import { isCommandKeyPressed } from '@js/common/core/events/utils/index'; -import registerComponent from '@js/core/component_registrator'; +import registerComponent from '@js/core/component_registrator'; // couldn't change import due inconsistent typings for registerComponent +import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; -import { Deferred } from '@js/core/utils/deferred'; -import { extend } from '@js/core/utils/extend'; +import type { DataSourceOptions } from '@js/data/data_source'; +import type { DxEvent, PointerInteractionEvent } from '@js/events/events.types'; import type { Properties } from '@js/ui/autocomplete'; +import type { ItemClickEvent, PageLoadMode } from '@js/ui/list'; +import { Deferred } from '@ts/core/utils/m_deferred'; import { isDefined } from '@ts/core/utils/m_type'; import type { OptionChanged } from '@ts/core/widget/types'; +import { isCommandKeyPressed } from '@ts/events/utils/index'; import DropDownList from '@ts/ui/drop_down_editor/drop_down_list'; +import type { ListBaseProperties } from '@ts/ui/list/list.base'; const AUTOCOMPLETE_CLASS = 'dx-autocomplete'; const AUTOCOMPLETE_POPUP_WRAPPER_CLASS = 'dx-autocomplete-popup-wrapper'; -export interface AutocompleteProperties extends Omit {} +export interface AutocompleteProperties extends Omit< + Properties, 'onItemClick' | 'onSelectionChanged' +> { + +} class Autocomplete extends DropDownList { _supportedKeys(): Record boolean> { - let item = this._list ? this._list.option('focusedElement') : null; + let item: dxElementWrapper | null = null; + if (this._list) { + const { focusedElement } = this._list.option(); + item = focusedElement ? $(focusedElement) : null; + } const parent = super._supportedKeys(); - // @ts-expect-error ts-error - item = item && $(item); return { ...parent, - upArrow(e): boolean { - // @ts-expect-error ts-error - if (parent.upArrow.apply(this, arguments) && !isCommandKeyPressed(e)) { + upArrow: (e): boolean => { + if (parent.upArrow.call(this, e) && !isCommandKeyPressed(e)) { e.preventDefault(); e.stopPropagation(); if (item && !this._calcNextItem(-1)) { @@ -34,9 +43,8 @@ class Autocomplete extends DropDownList { } return true; }, - downArrow(e): boolean { - // @ts-expect-error ts-error - if (parent.downArrow.apply(this, arguments) && !isCommandKeyPressed(e)) { + downArrow: (e): boolean => { + if (parent.downArrow.call(this, e) && !isCommandKeyPressed(e)) { e.preventDefault(); e.stopPropagation(); if (item && !this._calcNextItem(1)) { @@ -46,7 +54,7 @@ class Autocomplete extends DropDownList { } return true; }, - enter(e): boolean { + enter: (e): boolean => { if (!item) { this.close(); } @@ -54,7 +62,7 @@ class Autocomplete extends DropDownList { if (opened) { e.preventDefault(); } - return opened; + return Boolean(opened); }, }; } @@ -78,17 +86,19 @@ class Autocomplete extends DropDownList { _getAriaAutocomplete(): string { const { disabled, readOnly } = this.option(); + // ?? would short-circuit on `false`, missing the other operand // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const isInputEditable = !(readOnly || disabled); return isInputEditable ? 'list' : 'none'; } - _displayGetterExpr() { - return this.option('valueExpr'); + _displayGetterExpr(): undefined | string | ((item: unknown) => string | number | boolean) { + const { valueExpr } = this.option(); + return valueExpr; } - _closeOutsideDropDownHandler({ target }): boolean { + _closeOutsideDropDownHandler({ target }: DxEvent): boolean { return !$(target).closest(this.$element()).length; } @@ -103,18 +113,19 @@ class Autocomplete extends DropDownList { return `${super._popupWrapperClass()} ${AUTOCOMPLETE_POPUP_WRAPPER_CLASS}`; } - _listConfig() { - return extend(super._listConfig(), { - pageLoadMode: 'none', - onSelectionChanged: (e) => { + _listConfig(): ListBaseProperties { + return { + ...super._listConfig(), + pageLoadMode: 'none' as PageLoadMode, + onSelectionChanged: (e): void => { this._setSelectedItem(e.addedItems[0]); }, - }); + }; } - _listItemClickHandler(e) { + _listItemClickHandler(e: ItemClickEvent): void { this._saveValueChangeEvent(e.event); - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const value = this._displayGetter(e.itemData); this.option('value', value); this.close(); @@ -129,20 +140,24 @@ class Autocomplete extends DropDownList { super._setListDataSource(); } - _refreshSelected(): void {} + _refreshSelected(): void { + // Autocomplete has no persistent selection state — suppress parent behavior + // _refreshSelected is called in parent, so we need to override here + // hence we don't need this functionality in Autocomplete + } _searchCanceled(): void { super._searchCanceled(); this.close(); } - _loadItem(value, cache) { - const selectedItem = this._getItemFromPlain(value, cache); + _loadItem(value: unknown, cache: Record): ReturnType { + const selectedItem = this._getItemFromPlain(value, cache) as unknown; - return Deferred().resolve(selectedItem).promise(); + return Deferred().resolve(selectedItem); } - _dataSourceOptions() { + _dataSourceOptions(): DataSourceOptions { const { maxItemCount } = this.option(); return { paginate: true, @@ -150,7 +165,7 @@ class Autocomplete extends DropDownList { }; } - _searchDataSource(searchValue): void { + _searchDataSource(searchValue: string): void { const { maxItemCount } = this.option(); if (isDefined(maxItemCount)) { this._dataSource.pageSize(maxItemCount); @@ -166,12 +181,11 @@ class Autocomplete extends DropDownList { } } - // eslint-disable-next-line class-methods-use-this _renderValueEventName(): string { return 'input keyup'; } - _valueChangeEventHandler(e): void { + _valueChangeEventHandler(e: KeyboardEvent): void { const value = this._input().val() || null; return super._valueChangeEventHandler(e, value); } @@ -184,11 +198,10 @@ class Autocomplete extends DropDownList { this._setDefaultAria(); break; case 'maxItemCount': - // @ts-expect-error ts-error - this._searchDataSource(); + this._searchDataSource(this._searchValue()); break; case 'valueExpr': - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed this._compileDisplayGetter(); this._setListOption('displayExpr', this._displayGetterExpr()); super._optionChanged(args); diff --git a/packages/devextreme/js/__internal/ui/m_drop_down_box.ts b/packages/devextreme/js/__internal/ui/m_drop_down_box.ts index 5271183ede04..39b7a677aaa2 100644 --- a/packages/devextreme/js/__internal/ui/m_drop_down_box.ts +++ b/packages/devextreme/js/__internal/ui/m_drop_down_box.ts @@ -7,8 +7,6 @@ import domAdapter from '@js/core/dom_adapter'; import { getPublicElement } from '@js/core/element'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; -// @ts-expect-error ts-error -import { grep } from '@js/core/utils/common'; import type { DeferredObj } from '@js/core/utils/deferred'; import { Deferred, when } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; @@ -17,8 +15,11 @@ import { isDefined, isObject } from '@js/core/utils/type'; import type { Properties } from '@js/ui/drop_down_box'; import DataExpressionMixin from '@js/ui/editor/ui.data_expression'; import type { Properties as PopupProperties } from '@js/ui/popup'; +import { grep } from '@ts/core/utils/m_common'; import { tabbable } from '@ts/core/utils/m_selectors'; +import type { OptionChanged } from '@ts/core/widget/types'; import DropDownEditor from '@ts/ui/drop_down_editor/drop_down_editor'; +import type { PositioningEvent } from '@ts/ui/overlay/overlay'; import { getElementMaxHeightByWindow } from '@ts/ui/overlay/utils'; const { getActiveElement } = domAdapter; @@ -26,10 +27,18 @@ const { getActiveElement } = domAdapter; const DROP_DOWN_BOX_CLASS = 'dx-dropdownbox'; const ANONYMOUS_TEMPLATE_NAME = 'content'; +interface ItemWithKey { itemKey: unknown; itemDisplayValue: unknown } + export interface DropDownBoxProperties extends Omit { +| 'onCopy' | 'onCut' | 'onEnterKey' +| 'onFocusIn' | 'onFocusOut' +| 'onInput' | 'onKeyDown' +| 'onKeyUp' | 'onPaste' +| 'onValueChanged' +| 'validationMessagePosition' +| 'onContentReady' | 'onDisposing' +| 'onOptionChanged' | 'onInitialized'> { } class DropDownBox< @@ -42,7 +51,8 @@ class DropDownBox< return { ...super._supportedKeys(), tab(e): void { - if (!this.option('opened')) { + const { opened } = this.option(); + if (!opened) { return; } @@ -50,7 +60,7 @@ class DropDownBox< const $focusableElement = e.shiftKey ? $tabbableElements.last() : $tabbableElements.first(); if ($focusableElement) { - // @ts-expect-error ts-error + // @ts-expect-error should be added on EventsEngine level eventsEngine.trigger($focusableElement, 'focus'); } @@ -59,8 +69,8 @@ class DropDownBox< }; } - _getTabbableElements() { - // @ts-expect-error ts-error + _getTabbableElements(): dxElementWrapper { + // @ts-expect-error filter callback overload should be added on dxElementWrapper level return this._getElements().filter(tabbable); } @@ -90,7 +100,7 @@ class DropDownBox< } _initMarkup(): void { - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed this._initDataExpressions(); this.$element().addClass(DROP_DOWN_BOX_CLASS); @@ -98,53 +108,55 @@ class DropDownBox< } _setSubmitValue(): void { - const value = this.option('value'); + const { value } = this.option(); const submitValue = this._shouldUseDisplayValue(value) - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed ? this._displayGetter(value) : value; this._getSubmitElement().val(submitValue); } - _shouldUseDisplayValue(value): boolean { - // @ts-expect-error ts-error - return this.option('valueExpr') === 'this' && isObject(value); + _shouldUseDisplayValue(value: unknown): boolean { + const { valueExpr } = this.option(); + + return valueExpr === 'this' && isObject(value); } - _sortValuesByKeysOrder(orderedKeys, values) { - const sortedValues = values.sort((a, b) => orderedKeys.indexOf(a.itemKey) - orderedKeys.indexOf(b.itemKey)); + _sortValuesByKeysOrder(orderedKeys: unknown[], values: ItemWithKey[]): unknown[] { + const sortedValues = values.sort( + (a, b) => orderedKeys.indexOf(a.itemKey) - orderedKeys.indexOf(b.itemKey), + ); return sortedValues.map((x) => x.itemDisplayValue); } - _renderInputValue({ renderOnly }: { renderOnly?: boolean } = {}) { - // @ts-expect-error ts-error + _renderInputValue({ renderOnly }: { renderOnly?: boolean } = {}): DeferredObj { + // @ts-expect-error DataExpressionMixin must be typed this._rejectValueLoading(); - const values = []; - // @ts-expect-error ts-error + const values: ItemWithKey[] = []; + // @ts-expect-error DataExpressionMixin must be typed if (!this._dataSource) { super._renderInputValue({ renderOnly, value: values }); return Deferred().resolve(); } - // @ts-expect-error ts-error - const currentValue = this._getCurrentValue(); - let keys = currentValue ?? []; - - keys = Array.isArray(keys) ? keys : [keys]; + // @ts-expect-error DataExpressionMixin must be typed + const rawValue = this._getCurrentValue() ?? []; + const keys: unknown[] = Array.isArray(rawValue) ? rawValue : [rawValue]; const itemLoadDeferreds = map(keys, (key) => { const deferred = Deferred(); this ._loadItem(key) .always((item) => { - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const displayValue = this._displayGetter(item); + const { acceptCustomValue } = this.option(); if (isDefined(displayValue)) { - values.push({ itemKey: key, itemDisplayValue: displayValue } as never); - } else if (this.option('acceptCustomValue')) { - values.push({ itemKey: key, itemDisplayValue: key } as never); + values.push({ itemKey: key, itemDisplayValue: displayValue }); + } else if (acceptCustomValue) { + values.push({ itemKey: key, itemDisplayValue: key }); } deferred.resolve(); }); @@ -164,16 +176,19 @@ class DropDownBox< }); } - _loadItem(value): DeferredObj { + _loadItem(value: unknown): DeferredObj { const deferred = Deferred(); - const that = this; - // @ts-expect-error ts-error - const selectedItem = grep(this.option('items') || [], (item) => this._isValueEquals(this._valueGetter(item), value))[0]; + const selectedItem = grep( + this.option('items') || [], + // @ts-expect-error DataExpressionMixin must be typed + (item) => this._isValueEquals(this._valueGetter(item), value), + false, + )[0]; if (selectedItem !== undefined) { deferred.resolve(selectedItem); } else { - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed this._loadValue(value) .done((item) => { deferred.resolve(item); @@ -183,18 +198,17 @@ class DropDownBox< return; } - if (that.option('acceptCustomValue')) { + if (this.option('acceptCustomValue')) { deferred.resolve(value); } else { deferred.reject(); } }); } - // @ts-expect-error - return deferred.promise(); + return deferred; } - _popupTabHandler(e): void { + _popupTabHandler(e: KeyboardEvent): void { if (normalizeKeyName(e) !== 'tab') return; const $firstTabbable = this._getTabbableElements().first().get(0); @@ -205,7 +219,7 @@ class DropDownBox< if (moveBackward || moveForward) { this.close(); - // @ts-expect-error ts-error + // @ts-expect-error should be added on EventsEngine level eventsEngine.trigger(this._input(), 'focus'); if (moveBackward) { @@ -215,14 +229,14 @@ class DropDownBox< } _renderPopupContent(): void { - // @ts-expect-error ts-error - if (this.option('contentTemplate') === ANONYMOUS_TEMPLATE_NAME) { + const { contentTemplate: optionContentTemplate } = this.option(); + if (optionContentTemplate === ANONYMOUS_TEMPLATE_NAME) { return; } const contentTemplate = this._getTemplateByOption('contentTemplate'); - if (!(contentTemplate && this.option('contentTemplate'))) { + if (!(contentTemplate && optionContentTemplate)) { return; } @@ -246,14 +260,12 @@ class DropDownBox< } _canShowVirtualKeyboard(): boolean { - // @ts-expect-error ts-error - return devices.real().mac; // T845484 + return !!(devices.real() as unknown as { mac?: boolean }).mac; // T845484 } _isNestedElementActive(): boolean { const activeElement = getActiveElement(); - // @ts-expect-error ts-error - return activeElement && this._popup.$content().get(0).contains(activeElement); + return !!(activeElement && this._popup?.$content()?.get(0)?.contains(activeElement)); } _shouldHideOnParentScroll(): boolean { @@ -265,7 +277,7 @@ class DropDownBox< this._popupPosition = undefined; } - _popupPositionedHandler(e): void { + _popupPositionedHandler(e: Partial): void { super._popupPositionedHandler(e); this._popupPosition = e.position; } @@ -276,7 +288,7 @@ class DropDownBox< return { my, at, - // @ts-expect-error ts-error + // @ts-expect-error Should be updated on PositionConfig level offset: { v: -1 }, collision: 'flipfit', }; @@ -291,7 +303,7 @@ class DropDownBox< dragEnabled: false, focusStateEnabled, contentTemplate: ANONYMOUS_TEMPLATE_NAME, - // @ts-expect-error ts-error + // @ts-expect-error hideOnParentScroll public overlay.d.ts needs fix hideOnParentScroll: this._shouldHideOnParentScroll.bind(this), position: extend(this.option('popupPosition'), { of: this.$element(), @@ -312,20 +324,18 @@ class DropDownBox< _popupShownHandler(): void { super._popupShownHandler(); const $firstElement = this._getTabbableElements().first(); - // @ts-expect-error ts-error + // @ts-expect-error should be added on EventsEngine level eventsEngine.trigger($firstElement, 'focus'); } - // eslint-disable-next-line class-methods-use-this _setCollectionWidgetOption(): void {} - // eslint-disable-next-line class-methods-use-this _shouldLogFieldTemplateDeprecationWarning(): boolean { return true; } - _optionChanged(args) { - // @ts-expect-error ts-error + _optionChanged(args: OptionChanged): void { + // @ts-expect-error DataExpressionMixin must be typed this._dataExpressionOptionChanged(args); switch (args.name) { case 'dataSource': @@ -346,7 +356,7 @@ class DropDownBox< } } -// @ts-expect-error ts-error +// @ts-expect-error DataExpressionMixin is not typed DropDownBox.include(DataExpressionMixin); registerComponent('dxDropDownBox', DropDownBox); diff --git a/packages/devextreme/js/__internal/ui/m_drop_down_button.ts b/packages/devextreme/js/__internal/ui/m_drop_down_button.ts index b8c34c6bcdd4..6e8431a83a34 100644 --- a/packages/devextreme/js/__internal/ui/m_drop_down_button.ts +++ b/packages/devextreme/js/__internal/ui/m_drop_down_button.ts @@ -1,26 +1,33 @@ -import messageLocalization from '@js/common/core/localization/message'; +import type { template } from '@js/common'; +import type { PositionConfig } from '@js/common/core/animation'; import registerComponent from '@js/core/component_registrator'; -import { getPublicElement } from '@js/core/element'; -import Guid from '@js/core/guid'; +import type { DxElement } from '@js/core/element'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; -import { FunctionTemplate } from '@js/core/templates/function_template'; -import { ensureDefined } from '@js/core/utils/common'; import { compileGetter } from '@js/core/utils/data'; import type { DeferredObj } from '@js/core/utils/deferred'; import { Deferred } from '@js/core/utils/deferred'; import { extend } from '@js/core/utils/extend'; import { getImageContainer } from '@js/core/utils/icon'; -import { isDefined, isObject, isPlainObject } from '@js/core/utils/type'; -import DataController from '@js/data_controller'; +import type { DataSourceLike } from '@js/data/data_source'; import type { Item as ButtonGroupItem, Properties as ButtonGroupProperties, } from '@js/ui/button_group'; import ButtonGroup from '@js/ui/button_group'; import type { Item, Properties } from '@js/ui/drop_down_button'; +import type { ItemClickEvent } from '@js/ui/list'; +import type { PositionAlignment } from '@js/ui/popup'; +import messageLocalization from '@ts/core/localization/message'; +import { getPublicElement } from '@ts/core/m_element'; +import { Guid } from '@ts/core/m_guid'; +import { FunctionTemplate } from '@ts/core/templates/m_function_template'; +import { ensureDefined } from '@ts/core/utils/m_common'; +import { isDefined, isObject, isPlainObject } from '@ts/core/utils/m_type'; import type { OptionChanged } from '@ts/core/widget/types'; import Widget from '@ts/core/widget/widget'; +import type { DataSourceType } from '@ts/data/data_controller/data_controller'; +import DataController from '@ts/data/data_controller/data_controller'; import { getElementWidth } from '@ts/ui/drop_down_editor/utils'; import type { ListBaseProperties } from '@ts/ui/list/list.base'; import List from '@ts/ui/list/list.edit.search'; @@ -48,6 +55,15 @@ export interface DropDownButtonProperties extends Properties { _cached_dropDownOptions?: PopupProperties; } +export interface AriaAttributes { + expanded?: boolean; + haspopup?: string; + label?: string; + owns?: string; +} + +type ItemClickActionType = (event?: Partial) => Partial | boolean; + class DropDownButton extends Widget { _popup?: Popup; @@ -65,15 +81,15 @@ class DropDownButton extends Widget { _selectionChangedAction!: (event?: Record) => void; - _itemClickAction!: (event?: Record) => void; + _itemClickAction!: ItemClickActionType; _actionClickAction!: (event?: Record) => void; _actionItem?: unknown; - _keyGetter?: unknown; + _keyGetter?: (obj: unknown) => unknown; - _displayGetter?: unknown; + _displayGetter?: (obj: unknown) => unknown; _getDefaultOptions(): DropDownButtonProperties { return { @@ -81,7 +97,7 @@ class DropDownButton extends Widget { itemTemplate: 'item', keyExpr: 'this', selectedItem: null, - // @ts-expect-error ts-error + // @ts-expect-error public API needs to be fixed selectedItemKey: null, stylingMode: 'outlined', deferRendering: true, @@ -89,19 +105,15 @@ class DropDownButton extends Widget { useSelectMode: false, splitButton: false, showArrowIcon: true, - // @ts-expect-error ts-error + // @ts-expect-error public API needs to be fixed template: null, text: '', type: 'normal', - // @ts-expect-error ts-error - onButtonClick: null, - // @ts-expect-error ts-error - onSelectionChanged: null, - // @ts-expect-error ts-error - onItemClick: null, + onButtonClick: undefined, + onSelectionChanged: undefined, + onItemClick: undefined, opened: false, - // @ts-expect-error ts-error - items: null, + items: undefined, dataSource: null, focusStateEnabled: true, hoverStateEnabled: true, @@ -140,14 +152,16 @@ class DropDownButton extends Widget { } _initDataController(): void { - const dataSource = this.option('dataSource'); - // @ts-expect-error ts-error - this._dataController = new DataController(dataSource ?? this.option('items'), { key: this.option('keyExpr') }); + const { dataSource, items, keyExpr } = this.option(); + this._dataController = new DataController( + // @ts-expect-error datacontroller constructor typing need to be fixed + dataSource ?? items, + { key: keyExpr }, + ); } _initTemplates(): void { this._templateManager.addDefaultTemplates({ - // @ts-expect-error ts-error content: new FunctionTemplate((options) => { const $popupContent = $(options.container); const $listContainer = $('
').appendTo($popupContent); @@ -164,13 +178,15 @@ class DropDownButton extends Widget { } _compileKeyGetter(): void { - // @ts-expect-error ts-error - this._keyGetter = compileGetter(this._dataController.key()); + const key = this._dataController.key(); + if (key !== undefined) { + this._keyGetter = compileGetter(key) as (obj: unknown) => unknown; + } } _compileDisplayGetter(): void { const { displayExpr } = this.option(); - // @ts-expect-error ts-error + // @ts-expect-error core/utils compileGetter fn typing needs to be fixed this._displayGetter = compileGetter(displayExpr); } @@ -186,6 +202,7 @@ class DropDownButton extends Widget { } // T977758 + _renderFocusTarget(): void {} _render(): void { @@ -196,7 +213,7 @@ class DropDownButton extends Widget { super._render(); } - _renderContentImpl() { + _renderContentImpl(): void | Promise { if (this._popup) { this._renderPopupContent(); } @@ -214,67 +231,80 @@ class DropDownButton extends Widget { } this._lastSelectedItemData = undefined; - const selectedItemKey = this.option('selectedItemKey'); - // @ts-expect-error ts-error - this._dataController.loadSingle(selectedItemKey) - // @ts-expect-error ts-error - .done(d.resolve) - .fail(() => { - d.reject(null); - }); + const { selectedItemKey } = this.option(); + + if (isDefined(selectedItemKey)) { + this._dataController.loadSingle(this._dataController.key() as string, selectedItemKey) + .then((item) => { d.resolve(item); }) + .catch(() => { + d.reject(null); + }); + } else { + d.reject(null); + } this._loadSingleDeferred = d; - // @ts-expect-error ts-error - return d.promise(); + + return d; } - _createActionClickAction() { + _createActionClickAction(): void { this._actionClickAction = this._createActionByOption('onButtonClick'); } - _createSelectionChangedAction() { + _createSelectionChangedAction(): void { this._selectionChangedAction = this._createActionByOption('onSelectionChanged'); } - _createItemClickAction() { - this._itemClickAction = this._createActionByOption('onItemClick'); + _createItemClickAction(): void { + this._itemClickAction = this._createActionByOption('onItemClick') as ItemClickActionType; } - _fireSelectionChangedAction({ previousValue, value }) { + _fireSelectionChangedAction( + { previousValue, value }: { previousValue: unknown; value: unknown }, + ): void { this._selectionChangedAction({ item: value, previousItem: previousValue, }); } - _fireItemClickAction({ event, itemElement, itemData }) { + _fireItemClickAction( + { event, itemElement, itemData }: ItemClickEvent, + ): Partial | boolean { return this._itemClickAction({ event, itemElement, - itemData: this._actionItem || itemData, + itemData: this._actionItem ?? itemData, }); } - _getButtonTemplate() { + _formButtonTemplateFn({ text, icon }: ButtonGroupItem, buttonContent: DxElement): void { + const $firstIcon = getImageContainer(icon); + const $textContainer = text ? $('').text(text).addClass(DX_BUTTON_TEXT_CLASS) : undefined; + const $secondIcon = getImageContainer('spindown'); + if ($secondIcon !== null) { + $secondIcon.addClass(DX_ICON_RIGHT_CLASS); + } + + const $container = $(buttonContent); + if ($firstIcon) $container.append($firstIcon); + if ($textContainer) $container.append($textContainer); + if ($secondIcon) $container.append($secondIcon); + } + + _getButtonTemplate(): template { const { template, splitButton, showArrowIcon } = this.option(); if (template) { return template; } - return splitButton || !showArrowIcon - ? 'content' : ({ text, icon }, buttonContent) => { - const $firstIcon = getImageContainer(icon); - const $textContainer = text ? $('').text(text).addClass(DX_BUTTON_TEXT_CLASS) : undefined; - // @ts-expect-error ts-error - const $secondIcon = getImageContainer('spindown').addClass(DX_ICON_RIGHT_CLASS); - - // @ts-expect-error ts-error - $(buttonContent).append($firstIcon, $textContainer, $secondIcon); - }; + return splitButton || !showArrowIcon ? 'content' + : this._formButtonTemplateFn.bind(this); } - _getActionButtonConfig() { + _getActionButtonConfig(): ButtonGroupItem { const { icon, text, type, splitButton, } = this.option(); @@ -284,18 +314,16 @@ class DropDownButton extends Widget { icon, type, template: this._getButtonTemplate(), - elementAttr: { class: DROP_DOWN_BUTTON_ACTION_CLASS }, + elementAttr: { + class: DROP_DOWN_BUTTON_ACTION_CLASS, + role: splitButton ? 'menuitem' : undefined, + }, }; - if (splitButton) { - // @ts-expect-error ts-error - actionButtonConfig.elementAttr.role = 'menuitem'; - } - return actionButtonConfig; } - _getSpinButtonConfig() { + _getSpinButtonConfig(): ButtonGroupItem { const { type } = this.option(); const config = { @@ -316,18 +344,18 @@ class DropDownButton extends Widget { const items = [this._getActionButtonConfig()]; if (splitButton) { - // @ts-expect-error ts-error items.push(this._getSpinButtonConfig()); } return items; } - _buttonGroupItemClick({ event, itemData }): void { - const isActionButton = itemData.elementAttr.class === DROP_DOWN_BUTTON_ACTION_CLASS; - const isToggleButton = itemData.elementAttr.class === DROP_DOWN_BUTTON_TOGGLE_CLASS; + _buttonGroupItemClick({ event, itemData }: { event: Event; itemData: ButtonGroupItem }): void { + const isActionButton = itemData.elementAttr?.class === DROP_DOWN_BUTTON_ACTION_CLASS; + const isToggleButton = itemData.elementAttr?.class === DROP_DOWN_BUTTON_TOGGLE_CLASS; if (isToggleButton) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.toggle(); } else if (isActionButton) { this._actionClickAction({ @@ -336,6 +364,7 @@ class DropDownButton extends Widget { }); if (!this.option('splitButton')) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.toggle(); } } @@ -351,7 +380,7 @@ class DropDownButton extends Widget { tabIndex, } = this.option(); - const buttonGroupOptions = { + const buttonGroupOptions: ButtonGroupProperties = { items: this._getButtonGroupItems(), width: '100%', height: '100%', @@ -365,15 +394,15 @@ class DropDownButton extends Widget { role: splitButton ? 'menu' : 'group', }, onItemClick: this._buttonGroupItemClick.bind(this), - onKeyboardHandled: (e) => this._keyboardHandler(e), + onKeyboardHandled: (e): boolean => this._keyboardHandler(e), ...this._options.cache('buttonGroupOptions'), }; return buttonGroupOptions; } - _renderPopupContent() { - const $content = this._popup!.$content(); + _renderPopupContent(): unknown { + const $content = this._popup?.$content(); const template = this._getTemplateByOption('dropDownContentTemplate'); $content?.empty(); @@ -389,14 +418,25 @@ class DropDownButton extends Widget { return result; } - _popupOptions() { + _popupOptions(): PopupProperties { const horizontalAlignment = this.option('rtlEnabled') ? 'right' : 'left'; - return extend({ + const { deferRendering, opened } = this.option(); + + const cachedDropDownOptions: PopupProperties = this._options.cache('dropDownOptions'); + + const position: PositionConfig = { + of: getPublicElement(this.$element()), + collision: 'flipfit', + my: `${horizontalAlignment} top` as PositionAlignment, + at: `${horizontalAlignment} bottom` as PositionAlignment, + }; + + return { dragEnabled: false, focusStateEnabled: false, - deferRendering: this.option('deferRendering'), - hideOnOutsideClick: (e) => { + deferRendering, + hideOnOutsideClick: (e): boolean => { const $element = this.$element(); const $buttonClicked = $(e.target).closest(`.${DROP_DOWN_BUTTON_CLASS}`); return !$buttonClicked.is($element); @@ -413,15 +453,13 @@ class DropDownButton extends Widget { width: getElementWidth(this.$element()), height: 'auto', shading: false, - position: { - of: this.$element(), - collision: 'flipfit', - my: `${horizontalAlignment} top`, - at: `${horizontalAlignment} bottom`, - }, + position, _wrapperClassExternal: DROP_DOWN_EDITOR_OVERLAY_CLASS, + // @ts-expect-error public API needs to be fixed contentTemplate: null, - }, this._options.cache('dropDownOptions'), { visible: this.option('opened') }); + ...cachedDropDownOptions, + ...{ visible: opened }, + }; } _listOptions(): ListBaseProperties { @@ -447,7 +485,7 @@ class DropDownButton extends Widget { focusStateEnabled, hoverStateEnabled, useItemTextAsTitle, - // eslint-disable-next-line + // eslint-disable-next-line @typescript-eslint/no-misused-promises onContentReady: () => this._fireContentReadyAction(), selectedItemKeys: isDefined(selectedItemKey) && useSelectMode ? [selectedItemKey] : [], grouped, @@ -457,18 +495,15 @@ class DropDownButton extends Widget { displayExpr, itemTemplate, items, - // @ts-expect-error ts-error - dataSource: this._dataController.getDataSource(), - onItemClick: (e) => { + dataSource: this._dataController.getDataSource() as DataSourceLike | null, + onItemClick: (e): void => { if (!this.option('useSelectMode')) { this._lastSelectedItemData = e.itemData; } - // @ts-expect-error ts-error - this.option('selectedItemKey', this._keyGetter(e.itemData)); - // @ts-expect-error ts-error + this.option('selectedItemKey', this._keyGetter?.(e.itemData)); const actionResult = this._fireItemClickAction(e); - // @ts-expect-error ts-error if (actionResult !== false) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.toggle(false); this._buttonGroup.focus(); } @@ -520,7 +555,7 @@ class DropDownButton extends Widget { this._updateAriaAttributes(false); } - _popupOptionChanged(args): void { + _popupOptionChanged(args: OptionChanged): void { const options = Widget.getOptionsFromContainer(args); this._setPopupOption(options); @@ -539,10 +574,8 @@ class DropDownButton extends Widget { } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _setPopupOption(optionName, value?): void { - // @ts-expect-error ts-error - this._setWidgetOption('_popup', arguments); + _setPopupOption(...args: [string, unknown?] | [Record]): void { + this._setWidgetOption('_popup', args); } _popupShowingHandler(): void { @@ -550,7 +583,7 @@ class DropDownButton extends Widget { this._updateAriaAttributes(true); } - _setElementAria(value): void { + _setElementAria(value: boolean): void { const elementAria = { owns: value ? this._popupContentId : undefined, }; @@ -558,28 +591,28 @@ class DropDownButton extends Widget { this.setAria(elementAria, this.$element()); } - _setButtonsAria(value): void { - const commonButtonAria = { + _setButtonsAria(value: boolean): void { + const commonButtonAria: AriaAttributes = { expanded: value, haspopup: 'listbox', }; - const firstButtonAria = {}; + const firstButtonAria: AriaAttributes = {}; if (!this.option('text')) { - // @ts-expect-error ts-error firstButtonAria.label = 'dropdownbutton'; } - // @ts-expect-error ts-error + this._getButtons().each((index, $button) => { if (index === 0) { this.setAria({ ...firstButtonAria, ...commonButtonAria }, $($button)); } else { this.setAria(commonButtonAria, $($button)); } + return true; }); } - _updateAriaAttributes(value): void { + _updateAriaAttributes(value: boolean): void { this._setElementAria(value); this._setButtonsAria(value); } @@ -607,13 +640,13 @@ class DropDownButton extends Widget { this._buttonGroup.registerKeyHandler('escape', this._escHandler.bind(this)); this._bindInnerWidgetOptions(this._buttonGroup, 'buttonGroupOptions'); - this._updateAriaAttributes(this.option('opened')); + const { opened } = this.option(); + this._updateAriaAttributes(opened ?? false); } _updateArrowClass(): void { const hasArrow = this.option('splitButton') || this.option('showArrowIcon'); - // @ts-expect-error ts-error - this.$element().toggleClass(DROP_DOWN_BUTTON_HAS_ARROW_CLASS, hasArrow); + this.$element().toggleClass(DROP_DOWN_BUTTON_HAS_ARROW_CLASS, Boolean(hasArrow)); } toggle(visible?: boolean): Promise | undefined { @@ -633,28 +666,26 @@ class DropDownButton extends Widget { return this.toggle(false); } - _setListOption(name, value): void { + _setListOption(name: string, value: unknown): void { this._list?.option(name, value); } - _getDisplayValue(item): string { + _getDisplayValue(item: Item): string { const isPrimitiveItem = !isObject(item); - // @ts-expect-error ts-error - const displayValue = isPrimitiveItem ? item : this._displayGetter(item); + const displayValue = isPrimitiveItem ? item : this._displayGetter?.(item); return !isObject(displayValue) ? String(ensureDefined(displayValue, '')) : ''; } - _updateActionButton(selectedItem): void { + _updateActionButton(selectedItem: unknown): void { if (this.option('useSelectMode')) { this.option({ - text: this._getDisplayValue(selectedItem), - icon: isPlainObject(selectedItem) ? selectedItem.icon : undefined, + text: this._getDisplayValue(selectedItem as Item), + icon: isPlainObject(selectedItem) ? (selectedItem as Item).icon : undefined, }); } this._setOptionWithoutOptionChange('selectedItem', selectedItem); - // @ts-expect-error ts-error - this._setOptionWithoutOptionChange('selectedItemKey', this._keyGetter(selectedItem)); + this._setOptionWithoutOptionChange('selectedItemKey', this._keyGetter?.(selectedItem)); } _clean(): void { @@ -662,13 +693,12 @@ class DropDownButton extends Widget { this._popup?.$element().remove(); } - _selectedItemKeyChanged(value): void { + _selectedItemKeyChanged(value: unknown): void { this._setListOption('selectedItemKeys', this.option('useSelectMode') && isDefined(value) ? [value] : []); - const previousItem = this.option('selectedItem'); + const { selectedItem: previousItem } = this.option(); this._loadSelectedItem().always((selectedItem) => { this._updateActionButton(selectedItem); - // @ts-expect-error ts-error - if (this._displayGetter(previousItem) !== this._displayGetter(selectedItem)) { + if (this._displayGetter?.(previousItem) !== this._displayGetter?.(selectedItem)) { this._fireSelectionChangedAction({ previousValue: previousItem, value: selectedItem, @@ -677,19 +707,29 @@ class DropDownButton extends Widget { }); } - _updateButtonGroup(name, value): void { + _updateButtonGroup(name: string, value: unknown): void { this._buttonGroup.option(name, value); - this._updateAriaAttributes(this.option('opened')); + const { opened } = this.option(); + this._updateAriaAttributes(opened ?? false); } - _actionButtonOptionChanged({ name, value }): void { - const newConfig = {}; + _actionButtonOptionChanged({ name, value }: { name: string; value: unknown }): void { + const newConfig: Record = {}; newConfig[name] = value; - this._updateButtonGroup('items[0]', extend({}, this._getActionButtonConfig(), newConfig)); - this._popup && this._popup.repaint(); + this._updateButtonGroup( + 'items[0]', + extend( + {}, + this._getActionButtonConfig(), + newConfig, + ), + ); + if (this._popup) { + this._popup.repaint(); + } } - _selectModeChanged(value): void { + _selectModeChanged(value: unknown): void { if (value) { this._setListOption('selectionMode', 'single'); const selectedItemKey = this.option('selectedItemKey'); @@ -701,15 +741,14 @@ class DropDownButton extends Widget { selectedItemKey: undefined, selectedItem: undefined, }); - // @ts-expect-error ts-error - this._actionButtonOptionChanged({ text: this.option('text') }); + const { text } = this.option(); + this._actionButtonOptionChanged({ name: 'text', value: text }); } } - _updateItemCollection(optionName): void { + _updateItemCollection(optionName: string): void { const { selectedItemKey, useSelectMode } = this.option(); this._setListOption('selectedItem', null); - // @ts-expect-error ts-error this._setWidgetOption('_list', [optionName]); if (isDefined(selectedItemKey)) { @@ -719,17 +758,16 @@ class DropDownButton extends Widget { this._setListOption('selectedItemKeys', [selectedItemKey]); this._setListOption('selectedItem', selectedItem); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - }).fail((error) => { + }).fail(() => { this._setListOption('selectedItemKeys', []); }) .always(this._updateActionButton.bind(this)); } } - _updateDataController(items?): void { - // @ts-expect-error ts-error - this._dataController.updateDataSource(items, this.option('keyExpr')); + _updateDataController(items?: unknown[] | DataSourceType): void { + const { keyExpr } = this.option(); + this._dataController.updateDataSource(items, keyExpr); this._updateKeyExpr(); } @@ -738,7 +776,7 @@ class DropDownButton extends Widget { this._setListOption('keyExpr', this._dataController.key()); } - focus() { + focus(): void { this._buttonGroup.focus(); } @@ -774,6 +812,7 @@ class DropDownButton extends Widget { this._innerWidgetOptionChanged(this._popup, args); break; case 'opened': + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.toggle(value); break; case 'focusStateEnabled': @@ -783,12 +822,13 @@ class DropDownButton extends Widget { super._optionChanged(args); break; case 'items': - this._updateDataController(this.option('items')); + // eslint-disable-next-line no-case-declarations + const { items } = this.option(); + this._updateDataController(items); this._updateItemCollection(name); break; case 'dataSource': - // @ts-expect-error ts-error - this._dataController.updateDataSource(value); + this._dataController.updateDataSource(value as unknown[] | DataSourceType); this._updateKeyExpr(); this._updateItemCollection(name); break; @@ -840,7 +880,7 @@ class DropDownButton extends Widget { break; case 'deferRendering': { const { opened } = this.option(); - + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.toggle(opened); break; } @@ -858,7 +898,7 @@ class DropDownButton extends Widget { } } - getDataSource() { + getDataSource(): DataSourceType | null { return this._dataController.getDataSource(); } } diff --git a/packages/devextreme/js/__internal/ui/m_select_box.ts b/packages/devextreme/js/__internal/ui/m_select_box.ts index e71557681703..fe2869a6522a 100644 --- a/packages/devextreme/js/__internal/ui/m_select_box.ts +++ b/packages/devextreme/js/__internal/ui/m_select_box.ts @@ -449,7 +449,7 @@ class SelectBox< const fieldTemplate = this._getTemplate(fieldTemplateOption); if (!(fieldTemplate && fieldTemplateOption)) { - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const text = this._displayGetter(item); this.option('text', text); @@ -558,8 +558,7 @@ class SelectBox< if (initialSelectedItem === null) { return false; } - - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const value = this._displayGetter(initialSelectedItem); const displayValue = value ? String(value) : ''; const inputText = this._searchValue(); @@ -693,7 +692,7 @@ class SelectBox< _clearTextValue(): void { const selectedItem = this.option('selectedItem'); - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const selectedItemText = this._displayGetter(selectedItem); const shouldRestoreValue = selectedItem && selectedItemText !== ''; @@ -815,10 +814,10 @@ class SelectBox< return this._loadItemDeferred; } - _isCustomItemSelected() { + _isCustomItemSelected(): boolean { const selectedItem = this.option('selectedItem'); const searchValue = this._searchValue(); - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const selectedItemText = this._displayGetter(selectedItem); return !selectedItemText || searchValue !== selectedItemText.toString(); @@ -881,7 +880,7 @@ class SelectBox< this._cancelSearchIfNeed(); // @ts-expect-error ts-error this._setValue(this._valueGetter(item)); - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed this._renderDisplayText(this._displayGetter(item)); this._isValueChanging = false; } @@ -960,7 +959,7 @@ class SelectBox< } const inputElement = $input.get(0) as HTMLInputElement; - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed const displayValue = this._displayGetter(item).toString(); inputElement.value = displayValue; this._caret({ start: valueLength, end: displayValue.length }); diff --git a/packages/devextreme/js/__internal/ui/m_tag_box.ts b/packages/devextreme/js/__internal/ui/m_tag_box.ts index ce929c7f33fb..5bad289e23e7 100644 --- a/packages/devextreme/js/__internal/ui/m_tag_box.ts +++ b/packages/devextreme/js/__internal/ui/m_tag_box.ts @@ -439,7 +439,7 @@ class TagBox< $container.append($tagContent); }, ['text'], this.option('integrationOptions.watchMethod'), { - // @ts-expect-error ts-error + // @ts-expect-error DataExpressionMixin must be typed text: this._displayGetter, }), }); @@ -488,7 +488,7 @@ class TagBox< $options.push( $('