diff --git a/packages/devextreme/js/__internal/core/localization/date.ts b/packages/devextreme/js/__internal/core/localization/date.ts index c1444ce21bfc..076a0c56eb3b 100644 --- a/packages/devextreme/js/__internal/core/localization/date.ts +++ b/packages/devextreme/js/__internal/core/localization/date.ts @@ -155,7 +155,7 @@ const dateLocalization = dependencyInjector({ return formatter(date); }, - parse(text: string, format: FormatObject | string): Date | null | undefined { + parse(text: string, format?: FormatObject | string): Date | null | undefined { // eslint-disable-next-line @typescript-eslint/no-this-alias const that = this; // eslint-disable-next-line @typescript-eslint/init-declarations diff --git a/packages/devextreme/js/__internal/events/m_visibility_change.ts b/packages/devextreme/js/__internal/events/m_visibility_change.ts index 278bc4047a3d..57a7325cf93f 100644 --- a/packages/devextreme/js/__internal/events/m_visibility_change.ts +++ b/packages/devextreme/js/__internal/events/m_visibility_change.ts @@ -8,7 +8,6 @@ const triggerVisibilityChangeEvent = function (eventName) { const $element = $(element || 'body'); const changeHandlers = $element.filter(VISIBILITY_CHANGE_SELECTOR) - // @ts-expect-error .add($element.find(VISIBILITY_CHANGE_SELECTOR)); for (let i = 0; i < changeHandlers.length; i++) { diff --git a/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts index 6865e1370a0c..7969b5fd22c0 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts @@ -1703,7 +1703,6 @@ export class ColumnsController extends modules.Controller { result = false; } } else if (gridCoreUtils.isDateType(column.dataType)) { - // @ts-expect-error parsedValue = dateLocalization.parse(text, column.format); if (parsedValue) { result = parsedValue; diff --git a/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts b/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts index fb317c2fe834..3866c6dcdf8b 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/views/m_columns_view.ts @@ -371,7 +371,6 @@ export class ColumnsView extends ColumnStateMixin(modules.View) { if (browser.safari) { // T198380, T809552 - // @ts-expect-error $table.append($('').append('')); } diff --git a/packages/devextreme/js/__internal/ui/calendar/calendar.views.ts b/packages/devextreme/js/__internal/ui/calendar/calendar.views.ts index 2f8803b52e83..e5496da8f518 100644 --- a/packages/devextreme/js/__internal/ui/calendar/calendar.views.ts +++ b/packages/devextreme/js/__internal/ui/calendar/calendar.views.ts @@ -149,7 +149,6 @@ export class MonthView extends BaseView { const { weekNumberRule = 'auto', firstDayOfWeek } = this.option(); if (weekNumberRule === 'auto') { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.getWeekNumber( date, firstDayOfWeek, @@ -157,7 +156,6 @@ export class MonthView extends BaseView { ); } - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.getWeekNumber(date, firstDayOfWeek, weekNumberRule); } @@ -170,7 +168,6 @@ export class MonthView extends BaseView { _isTodayCell(cellDate: Date): boolean { const { _todayDate: today } = this.option(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameDate(cellDate, today()); } @@ -188,12 +185,10 @@ export class MonthView extends BaseView { } _isStartDayOfMonth(cellDate: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameDate(cellDate, dateUtils.getFirstMonthDate(this.option('date'))); } _isEndDayOfMonth(cellDate: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameDate(cellDate, dateUtils.getLastMonthDate(this.option('date'))); } @@ -237,7 +232,6 @@ export class MonthView extends BaseView { } isBoundary(date: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameMonthAndYear(date, this.option('min')) || dateUtils.sameMonthAndYear(date, this.option('max')); } @@ -260,7 +254,6 @@ export class YearView extends BaseView { _isTodayCell(cellDate: Date): boolean { const { _todayDate: today } = this.option(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameMonthAndYear(cellDate, today()); } @@ -315,7 +308,6 @@ export class YearView extends BaseView { } isBoundary(date: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameYear(date, this.option('min')) || dateUtils.sameYear(date, this.option('max')); } @@ -330,7 +322,6 @@ export class DecadeView extends BaseView { _isTodayCell(cellDate: Date): boolean { const { _todayDate: today } = this.option(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameYear(cellDate, today()); } @@ -384,7 +375,6 @@ export class DecadeView extends BaseView { } _isValueOnCurrentView(currentDate: Date, value: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameDecade(currentDate, value); } @@ -397,7 +387,6 @@ export class DecadeView extends BaseView { } isBoundary(date: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameDecade(date, this.option('min')) || dateUtils.sameDecade(date, this.option('max')); } @@ -412,7 +401,6 @@ export class CenturyView extends BaseView { _isTodayCell(cellDate: Date): boolean { const { _todayDate: today } = this.option(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameDecade(cellDate, today()); } @@ -482,7 +470,6 @@ export class CenturyView extends BaseView { } isBoundary(date: Date): boolean { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return dateUtils.sameCentury(date, this.option('min')) || dateUtils.sameCentury(date, this.option('max')); } diff --git a/packages/devextreme/js/__internal/ui/date_box/date_view.ts b/packages/devextreme/js/__internal/ui/date_box/date_view.ts index 7de4caa9a176..40a12e104b1e 100644 --- a/packages/devextreme/js/__internal/ui/date_box/date_view.ts +++ b/packages/devextreme/js/__internal/ui/date_box/date_view.ts @@ -137,9 +137,7 @@ class DateView extends Editor { } _renderRollers(): void { - if (!this._$rollersContainer) { - this._$rollersContainer = $('
').addClass(DATEVIEW_ROLLER_CONTAINER_CLASS); - } + this._$rollersContainer ??= $('
').addClass(DATEVIEW_ROLLER_CONTAINER_CLASS); this._$rollersContainer.empty(); this._createRollerConfigs(); @@ -157,22 +155,20 @@ class DateView extends Editor { selectedIndex: this._rollerConfigs[name].selectedIndex, showScrollbar: 'never', scrollByContent: true, - // TODO Add event type once m_date_view_roller types is refactored - onStart: (e) => { + onStart: (e): void => { const { component } = e; const rollerConfig = this._rollerConfigs[name]; component._toggleActive(true); this._setActiveRoller(rollerConfig); }, - // TODO Add event type once m_date_view_roller types is refactored - onEnd: (e) => { + onEnd: (e): void => { e.component._toggleActive(false); }, - // TODO Add event type once m_date_view_roller types is refactored - onClick: (e) => { + + onClick: (e): void => { const { component } = e; - const { selectedIndex } = component.option(); + const { selectedIndex = 0 } = component.option(); const rollerConfig = this._rollerConfigs[name]; component._toggleActive(true); @@ -180,10 +176,9 @@ class DateView extends Editor { this._setRollerState(rollerConfig, selectedIndex); component._toggleActive(false); }, - // TODO Add event type once m_date_view_roller types is refactored onSelectedIndexChanged: (e) => { const { component } = e; - const { selectedIndex } = component.option(); + const { selectedIndex = 0 } = component.option(); const rollerConfig = this._rollerConfigs[name]; this._setRollerState(rollerConfig, selectedIndex); @@ -211,7 +206,6 @@ class DateView extends Editor { } _createRollerConfig(componentName: string): void { - // @ts-expect-error TODO remove once m_date_utils is refactored const componentInfo = uiDateUtils.DATE_COMPONENTS_INFO[componentName]; const valueRange = this._calculateRollerConfigValueRange(componentName); @@ -282,6 +276,7 @@ class DateView extends Editor { currentValue[setValue](rollerValue); const normalizedDate = dateUtils.normalizeDate(currentValue, minDate, maxDate); + // @ts-expect-error ts-error currentValue = uiDateUtils.mergeDates(normalizedDate, currentValue, 'time'); currentValue = dateUtils.normalizeDate(currentValue, minDate, maxDate); @@ -304,8 +299,7 @@ class DateView extends Editor { const roller = this._rollers[rollerType]; if (roller) { - // @ts-expect-error TODO Remove once m_date_view_roller is reworked - const { items } = roller.option(); + const { items = [] } = roller.option(); this._createRollerConfig(rollerType); const rollerConfig = this._rollerConfigs[rollerType]; @@ -339,7 +333,6 @@ class DateView extends Editor { const maxMonth = maxYear && curDate.getMonth() === maxDate.getMonth(); const minHour = minMonth && curDate.getDate() === minDate.getDate(); const maxHour = maxMonth && curDate.getDate() === maxDate.getDate(); - // @ts-expect-error TODO remove once m_date_utils is refactored const componentInfo = uiDateUtils.DATE_COMPONENTS_INFO[componentName]; let { startValue } = componentInfo; let { endValue } = componentInfo; diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.base.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.base.ts index 89d1b798a577..089ffd830cad 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.base.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.base.ts @@ -1,3 +1,4 @@ +/* eslint-disable class-methods-use-this */ import dateLocalization from '@js/common/core/localization/date'; import messageLocalization from '@js/common/core/localization/message'; import config from '@js/core/config'; @@ -6,18 +7,24 @@ import type { DefaultOptionsRule } from '@js/core/options/utils'; import browser from '@js/core/utils/browser'; import dateUtils from '@js/core/utils/date'; import dateSerialization from '@js/core/utils/date_serialization'; +import type { DeferredObj } from '@js/core/utils/deferred'; import { createTextElementHiddenCopy } from '@js/core/utils/dom'; import { extend } from '@js/core/utils/extend'; -import { each } from '@js/core/utils/iterator'; import { inputType } from '@js/core/utils/support'; import { isDate as isDateType, isNumeric, isString } from '@js/core/utils/type'; import { getWindow, hasWindow } from '@js/core/utils/window'; +import type { DxEvent } from '@js/events'; import type { - DatePickerType, DateType, Properties, + DateLike, + DatePickerType, + DateType, + Properties, } from '@js/ui/date_box'; +import type { ToolbarItem } from '@js/ui/popup'; import type { OptionChanged } from '@ts/core/widget/types'; import DropDownEditor from '@ts/ui/drop_down_editor/m_drop_down_editor'; +import type { ValueChangedEvent } from '../editor/editor'; import type { PopupProperties } from '../popup/m_popup'; import Calendar from './m_date_box.strategy.calendar'; import CalendarWithTime from './m_date_box.strategy.calendar_with_time'; @@ -65,6 +72,7 @@ const STRATEGY_CLASSES = { }; export interface DateBoxBaseProperties extends Omit { + emptyDateValue?: Date; _showValidationIcon?: boolean; } @@ -77,8 +85,7 @@ class DateBox extends DropDownEditor { _userOptions?: DateBoxBaseProperties; - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - _supportedKeys(): Record boolean | void> { + _supportedKeys(): Record void> { return { ...super._supportedKeys(), ...this._strategy.supportedKeys(), @@ -86,8 +93,7 @@ class DateBox extends DropDownEditor { } _renderButtonContainers(): void { - // @ts-expect-error ts-error - super._renderButtonContainers.apply(this, arguments); + super._renderButtonContainers(); this._strategy.customizeButtons(); } @@ -194,7 +200,6 @@ class DateBox extends DropDownEditor { super._init(); } - // eslint-disable-next-line class-methods-use-this _toLowerCaseFirstLetter(string: string): string { return string.charAt(0).toLowerCase() + string.substr(1); } @@ -209,26 +214,23 @@ class DateBox extends DropDownEditor { } } - _getFormatType() { - const currentType = this.option('type'); - // @ts-expect-error ts-error - const isTime = /h|m|s/g.test(currentType); - // @ts-expect-error ts-error - const isDate = /d|M|Y/g.test(currentType); - let type = ''; + _getFormatType(): DateType { + const { type = 'date' } = this.option(); + const isTime = /h|m|s/g.test(type); + const isDate = /d|M|Y/g.test(type); - if (isDate) { - type += TYPE.date; + if (isDate && isTime) { + return TYPE.datetime; } if (isTime) { - type += TYPE.time; + return TYPE.time; } - return type; + return TYPE.date; } - _getStrategyName(type) { + _getStrategyName(type: DateType): string { const pickerType = this._pickerType; if (pickerType === PICKER_TYPE.rollers) { @@ -267,7 +269,8 @@ class DateBox extends DropDownEditor { _renderDimensions(): void { super._renderDimensions(); - this.$element().toggleClass(DX_AUTO_WIDTH_CLASS, !this.option('width')); + const { width } = this.option(); + this.$element().toggleClass(DX_AUTO_WIDTH_CLASS, !width); this._updatePopupWidth(); this._updatePopupHeight(); @@ -280,16 +283,16 @@ class DateBox extends DropDownEditor { } _updatePopupHeight(): void { - if (this._popup) { - // @ts-expect-error ts-error - this._strategy._updatePopupHeight?.(); + if (this._popup && this._strategy instanceof List) { + this._strategy._updatePopupHeight(); } } _refreshFormatClass(): void { const $element = this.$element(); + const types = Object.values(TYPE); - each(TYPE, (_, item) => { + types.forEach((item) => { $element.removeClass(`${DATEBOX_CLASS}-${item}`); }); @@ -300,8 +303,9 @@ class DateBox extends DropDownEditor { _refreshPickerTypeClass(): void { const $element = this.$element(); + const pickerTypes = Object.values(PICKER_TYPE); - each(PICKER_TYPE, (_, item) => { + pickerTypes.forEach((item) => { $element.removeClass(`${DATEBOX_CLASS}-${item}`); }); @@ -313,33 +317,40 @@ class DateBox extends DropDownEditor { return; } - const inputElement = this._input().get(0); - const isRtlEnabled = this.option('rtlEnabled'); + const inputElement = this._input().get(0) as HTMLElement; + const { rtlEnabled } = this.option(); const clearButtonWidth = this._getClearButtonWidth(); const longestElementDimensions = this._getLongestElementDimensions(); const curWidth = parseFloat(window.getComputedStyle(inputElement).width) - clearButtonWidth; const shouldHideValidationIcon = longestElementDimensions.width > curWidth; - // @ts-expect-error ts-error const { style } = inputElement; const { _showValidationIcon: showValidationIcon } = this.option(); - this.$element().toggleClass(DX_INVALID_BADGE_CLASS, !shouldHideValidationIcon && showValidationIcon); + this.$element() + .toggleClass(DX_INVALID_BADGE_CLASS, !shouldHideValidationIcon && showValidationIcon); if (shouldHideValidationIcon) { - if (this._storedPadding === undefined) { - this._storedPadding = isRtlEnabled ? longestElementDimensions.leftPadding : longestElementDimensions.rightPadding; + this._storedPadding ??= rtlEnabled + ? longestElementDimensions.leftPadding + : longestElementDimensions.rightPadding; + if (rtlEnabled) { + style.paddingLeft = '0'; + } else { + style.paddingRight = '0'; } - isRtlEnabled ? style.paddingLeft = 0 : style.paddingRight = 0; + } else if (rtlEnabled) { + style.paddingLeft = `${this._storedPadding}px`; } else { - isRtlEnabled ? style.paddingLeft = `${this._storedPadding}px` : style.paddingRight = `${this._storedPadding}px`; + style.paddingRight = `${this._storedPadding}px`; } } - _getClearButtonWidth() { + _getClearButtonWidth(): number { let clearButtonWidth = 0; - // @ts-expect-error ts-error - if (this._isClearButtonVisible() && this._input().val() === '') { + const input = this._input().get(0) as HTMLInputElement; + + if (this._isClearButtonVisible() && input.value === '') { const clearButtonElement = this.$element().find(`.${DX_CLEAR_BUTTON_CLASS}`).get(0); clearButtonWidth = parseFloat(window.getComputedStyle(clearButtonElement).width); } @@ -347,20 +358,30 @@ class DateBox extends DropDownEditor { return clearButtonWidth; } - _getLongestElementDimensions() { - const format = this._strategy.getDisplayFormat(this.option('displayFormat')); - const longestValue = dateLocalization.format(uiDateUtils.getLongestDate(format, dateLocalization.getMonthNames(), dateLocalization.getDayNames()), format); + _getLongestElementDimensions(): { + width: number; + leftPadding: number; + rightPadding: number; + } { + const { displayFormat } = this.option(); + const format = this._strategy.getDisplayFormat(displayFormat); + const longestValue = dateLocalization.format( + uiDateUtils.getLongestDate( + format, + dateLocalization.getMonthNames(), + dateLocalization.getDayNames(), + ), + format, + ); const $input = this._input(); const inputElement = $input.get(0); const $longestValueElement = createTextElementHiddenCopy($input, longestValue); - const isPaddingStored = this._storedPadding !== undefined; - const storedPadding = !isPaddingStored ? 0 : this._storedPadding; + const storedPadding = this._storedPadding ?? 0; $longestValueElement.appendTo(this.$element()); const elementWidth = parseFloat(window.getComputedStyle($longestValueElement.get(0)).width); const rightPadding = parseFloat(window.getComputedStyle(inputElement).paddingRight); const leftPadding = parseFloat(window.getComputedStyle(inputElement).paddingLeft); - // @ts-expect-error ts-error const necessaryWidth = elementWidth + leftPadding + rightPadding + storedPadding; $longestValueElement.remove(); @@ -371,7 +392,8 @@ class DateBox extends DropDownEditor { }; } - _getKeyboardListeners() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _getKeyboardListeners(): any[] { return super._getKeyboardListeners().concat([this._strategy?.getKeyboardListener()]); } @@ -381,10 +403,10 @@ class DateBox extends DropDownEditor { this._renderPopupWrapper(); } - _getPopupToolbarItems() { + _getPopupToolbarItems(): ToolbarItem[] { const defaultItems = super._getPopupToolbarItems(); - // @ts-expect-error ts-error - return this._strategy._getPopupToolbarItems?.(defaultItems) ?? defaultItems; + + return this._strategy._getPopupToolbarItems(defaultItems); } _popupConfig(): PopupProperties { @@ -402,9 +424,9 @@ class DateBox extends DropDownEditor { } const $element = this.$element(); - const classPostfixes = extend({}, TYPE, PICKER_TYPE); + const classPostfixes = [...Object.values(TYPE), ...Object.values(PICKER_TYPE)]; - each(classPostfixes, (_, item) => { + classPostfixes.forEach((item) => { $element.removeClass(`${DATEBOX_WRAPPER_CLASS}-${item}`); }); @@ -437,13 +459,13 @@ class DateBox extends DropDownEditor { this._strategy.popupHiddenHandler(); } - _visibilityChanged(visible): void { + _visibilityChanged(visible: boolean): void { if (visible) { this._formatValidationIcon(); } } - _clearValueHandler(e): void { + _clearValueHandler(e: DxEvent): void { this.option('text', ''); super._clearValueHandler(e); } @@ -457,8 +479,8 @@ class DateBox extends DropDownEditor { const isCustomValueDisabled = this._isNativeType() && (platform === 'ios' || platform === 'android'); if (isCustomValueDisabled) { - const { readOnly } = this.option(); - // @ts-expect-error ts-error + const { readOnly = false } = this.option(); + return readOnly; } @@ -469,8 +491,8 @@ class DateBox extends DropDownEditor { return super._isClearButtonVisible() && !this._isNativeType(); } - _renderValue() { - const value = this.dateOption('value'); + _renderValue(): DeferredObj { + const value = this.getDateOption('value'); this.option('text', this._getDisplayedText(value)); this._strategy.renderValue(); @@ -478,43 +500,41 @@ class DateBox extends DropDownEditor { return super._renderValue(); } - _setSubmitValue() { - const value = this.dateOption('value'); - const { type, dateSerializationFormat } = this.option(); - // @ts-expect-error ts-error + _setSubmitValue(): void { + const value = this.getDateOption('value'); + const { type = 'date', dateSerializationFormat } = this.option(); const submitFormat = uiDateUtils.SUBMIT_FORMATS_MAP[type]; - const submitValue = dateSerializationFormat ? dateSerialization.serializeDate(value, dateSerializationFormat) : uiDateUtils.toStandardDateFormat(value, submitFormat); + const submitValue = dateSerializationFormat + ? dateSerialization.serializeDate(value, dateSerializationFormat) + : uiDateUtils.toStandardDateFormat(value, submitFormat); this._getSubmitElement().val(submitValue); } - _getDisplayedText(value) { - const { mode } = this.option(); - let displayedText; + _getDisplayedText(value?: DateLike): string { + const { mode = 'text', displayFormat: displayFormatOption } = this.option(); if (mode === 'text') { - const displayFormat = this._strategy.getDisplayFormat(this.option('displayFormat')); - displayedText = dateLocalization.format(value, displayFormat); - } else { - const format = this._getFormatByMode(mode); - - if (format) { - displayedText = dateLocalization.format(value, format); - } else { - displayedText = uiDateUtils.toStandardDateFormat(value, mode); - } + const displayFormat = this._strategy.getDisplayFormat(displayFormatOption); + return dateLocalization.format(value, displayFormat) as string; } + const format = this._getFormatByMode(mode); - return displayedText; + if (format) { + return dateLocalization.format(value, format) as string; + } + return uiDateUtils.toStandardDateFormat(value, mode); } - _getFormatByMode(mode) { - return inputType(mode) ? null : uiDateUtils.FORMATS_MAP[mode]; + _getFormatByMode(mode: string): string | null { + return inputType(mode) + ? null + : uiDateUtils.FORMATS_MAP[mode] as string | null; } - _valueChangeEventHandler(e) { - const { text, type, validationError } = this.option(); - const currentValue = this.dateOption('value'); + _valueChangeEventHandler(e: ValueChangedEvent): void { + const { text, type = 'date', validationError } = this.option(); + const currentValue = this.getDateOption('value'); if (text === this._getDisplayedText(currentValue)) { this._recallInternalValidation(currentValue, validationError); @@ -537,39 +557,50 @@ class DateBox extends DropDownEditor { } } - _recallInternalValidation(value, validationError) { + _recallInternalValidation( + value: Date | null, + validationError: { editorSpecific?: boolean }, + ): void { if (!validationError || validationError.editorSpecific) { this._applyInternalValidation(value); this._applyCustomValidation(value); } } - _getDateByDefault() { - return this._strategy.useCurrentDateByDefault() && this._strategy.getDefaultDate(); + _getDateByDefault(): Date | undefined { + if (this._strategy.useCurrentDateByDefault()) { + return this._strategy.getDefaultDate(); + } + + return undefined; } - _getParsedDate(text) { - const displayFormat = this._strategy.getDisplayFormat(this.option('displayFormat')); - const parsedText = this._strategy.getParsedText(text, displayFormat); + _getParsedDate(text?: string): Date | undefined { + const { displayFormat } = this.option(); + const strategyDisplayFormat = this._strategy.getDisplayFormat(displayFormat); + const parsedText = this._strategy.getParsedText(text, strategyDisplayFormat); return parsedText ?? undefined; } - _applyInternalValidation(value) { - const text = this.option('text'); + _applyInternalValidation(value?: Date | null): { isValid: boolean; isDate: boolean } { + const { text, type } = this.option(); const hasText = !!text && value !== null; const isDate = !!value && isDateType(value) && !isNaN(value.getTime()); - const isDateInRange = isDate && dateUtils.dateInRange(value, this.dateOption('min'), this.dateOption('max'), this.option('type')); - const isValid = !hasText && !value || isDateInRange; + const isDateInRange = isDate && dateUtils.dateInRange( + value, + this.getDateOption('min'), + this.getDateOption('max'), + type, + ); + const isValid = (!hasText && !value) || isDateInRange; let validationMessage = ''; - const { invalidDateMessage, dateOutOfRangeMessage } = this.option(); + const { invalidDateMessage = '', dateOutOfRangeMessage = '' } = this.option(); if (!isDate) { - // @ts-expect-error ts-error validationMessage = invalidDateMessage; } else if (!isDateInRange) { - // @ts-expect-error ts-error validationMessage = dateOutOfRangeMessage; } @@ -581,7 +612,7 @@ class DateBox extends DropDownEditor { }; } - _updateInternalValidationState(isValid, validationMessage): void { + _updateInternalValidationState(isValid: boolean, validationMessage: string): void { this.option({ isValid, validationError: isValid ? null : { @@ -591,15 +622,15 @@ class DateBox extends DropDownEditor { }); } - _applyCustomValidation(value): void { + _applyCustomValidation(value: DateLike): void { this.validationRequest.fire({ editor: this, value: this._serializeDate(value), }); } - _isValueChanged(newValue): boolean { - const oldValue = this.dateOption('value'); + _isValueChanged(newValue: Date | null): boolean { + const oldValue = this.getDateOption('value'); const oldTime = oldValue && oldValue.getTime(); const newTime = newValue && newValue.getTime(); @@ -607,9 +638,9 @@ class DateBox extends DropDownEditor { return oldTime !== newTime; } - _isTextChanged(newValue): boolean { - const oldText = this.option('text'); - const newText = newValue && this._getDisplayedText(newValue) || ''; + _isTextChanged(newValue: DateLike): boolean { + const { text: oldText } = this.option(); + const newText = (newValue && this._getDisplayedText(newValue)) ?? ''; return oldText !== newText; } @@ -656,7 +687,7 @@ class DateBox extends DropDownEditor { this._refresh(); } - _applyButtonHandler(e): void { + _applyButtonHandler(e: { event: ValueChangedEvent }): void { const value = this._strategy.getValue(); this.dateValue(value, e.event); @@ -680,8 +711,7 @@ class DateBox extends DropDownEditor { switch (args.name) { case 'showClearButton': case 'buttons': - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + super._optionChanged(args); this._formatValidationIcon(); break; case 'pickerType': @@ -699,16 +729,15 @@ class DateBox extends DropDownEditor { this._updateValue(); break; case 'placeholder': - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + super._optionChanged(args); this._updatePopupTitle(); break; case 'min': case 'max': { const isValid = this.option('isValid'); - this._applyInternalValidation(this.dateOption('value')); + this._applyInternalValidation(this.getDateOption('value')); if (!isValid) { - this._applyCustomValidation(this.dateOption('value')); + this._applyCustomValidation(this.getDateOption('value')); } this._invalidate(); break; @@ -721,28 +750,23 @@ class DateBox extends DropDownEditor { this._invalidate(); break; case 'displayFormat': - this.option('text', this._getDisplayedText(this.dateOption('value'))); + this.option('text', this._getDisplayedText(this.getDateOption('value'))); this._renderInputValue(); break; case 'text': - // @ts-expect-error ts-error - this._strategy.textChangedHandler(args.value); - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + this._strategy.textChangedHandler(); + super._optionChanged(args); break; case 'isValid': - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + super._optionChanged(args); this._formatValidationIcon(); break; case 'showDropDownButton': this._formatValidationIcon(); - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + super._optionChanged(args); break; case 'readOnly': - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + super._optionChanged(args); this._formatValidationIcon(); break; case 'invalidDateMessage': @@ -752,16 +776,15 @@ class DateBox extends DropDownEditor { case '_showValidationIcon': break; default: - // @ts-expect-error ts-error - super._optionChanged.apply(this, arguments); + super._optionChanged(args); } } - _getSerializationFormat() { - const { value } = this.option(); + _getSerializationFormat(): string | undefined { + const { value, dateSerializationFormat } = this.option(); - if (this.option('dateSerializationFormat') && config().forceIsoDateParsing) { - return this.option('dateSerializationFormat'); + if (dateSerializationFormat && config().forceIsoDateParsing) { + return dateSerializationFormat; } if (isNumeric(value)) { @@ -769,18 +792,18 @@ class DateBox extends DropDownEditor { } if (!isString(value) || value === '') { - return; + return undefined; } - return dateSerialization.getDateSerializationFormat(value); + return dateSerialization.getDateSerializationFormat(value) as string | undefined; } - _updateValue(value?) { + _updateValue(value?: Date | null): void { super._updateValue(); - this._applyInternalValidation(value ?? this.dateOption('value')); + this._applyInternalValidation(value ?? this.getDateOption('value')); } - dateValue(value, dxEvent) { + dateValue(value: Date | null, dxEvent?: ValueChangedEvent): void { const isValueChanged = this._isValueChanged(value); if (isValueChanged && dxEvent) { @@ -797,24 +820,27 @@ class DateBox extends DropDownEditor { } } - return this.dateOption('value', value); + this.setDateOption('value', value); } - dateOption(optionName, value?) { - if (arguments.length === 1) { - return dateSerialization.deserializeDate(this.option(optionName)); - } + getDateOption(optionName: 'value' | 'min' | 'max'): Date | null { + const { [optionName]: optionValue } = this.option(); + + return dateSerialization.deserializeDate(optionValue) as Date | null; + } + setDateOption(optionName: 'value' | 'min' | 'max', value: DateLike | undefined): void { this.option(optionName, this._serializeDate(value)); } - _serializeDate(date) { + _serializeDate(date?: DateLike): Date | string | null { const serializationFormat = this._getSerializationFormat(); - return dateSerialization.serializeDate(date, serializationFormat); + + return dateSerialization.serializeDate(date, serializationFormat) as Date | string | null; } _clearValue(): void { - const value = this.option('value'); + const { value } = this.option(); super._clearValue(); if (value === null) { @@ -823,7 +849,7 @@ class DateBox extends DropDownEditor { } clear(): void { - const value = this.option('value'); + const { value } = this.option(); super.clear(); if (value === null) { diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts index f22389d2aeec..48c4b729c261 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts @@ -3,17 +3,41 @@ import { noop } from '@js/core/utils/common'; import { extend } from '@js/core/utils/extend'; import { fitIntoRange } from '@js/core/utils/math'; -const monthGetter = (date) => date.getMonth() + 1; +const getLimits = ( + pattern: string, + date: Date, + forcedPattern?: string, +): { min: number; max: number } => { + const limits: Record = { + y: { min: 0, max: 9999 }, + M: { min: 1, max: 12 }, + L: { min: 1, max: 12 }, + d: { min: 1, max: 31 }, + dM: { + min: 1, + max: new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(), + }, + E: { min: 0, max: 6 }, + H: { min: 0, max: 23 }, + h: { min: 1, max: 12 }, + m: { min: 0, max: 59 }, + s: { min: 0, max: 59 }, + S: { min: 0, max: 999 }, + a: { min: 0, max: 1 }, + x: { min: 0, max: 0 }, // NOTE: Timezone part is read only. + }; + return limits[forcedPattern ?? pattern] ?? { min: 0, max: 0 }; +}; -const monthSetter = (date, value) => { +const monthGetter = (date: Date): number => date.getMonth() + 1; + +const monthSetter = (date: Date, value: number | string): void => { const day = date.getDate(); - // @ts-expect-error const monthLimits = getLimits('M', date); - // eslint-disable-next-line radix - const newValue = fitIntoRange(parseInt(value), monthLimits.min, monthLimits.max); + const newValue = fitIntoRange(+value, monthLimits.min, monthLimits.max); date.setMonth(newValue - 1, 1); - // @ts-expect-error + const { min, max } = getLimits('dM', date); const newDay = fitIntoRange(day, min, max); @@ -21,7 +45,7 @@ const monthSetter = (date, value) => { }; const PATTERN_GETTERS = { - a: (date) => (date.getHours() < 12 ? 0 : 1), + a: (date: Date): number => (date.getHours() < 12 ? 0 : 1), E: 'getDay', y: 'getFullYear', M: monthGetter, @@ -36,82 +60,92 @@ const PATTERN_GETTERS = { }; const PATTERN_SETTERS = extend({}, getPatternSetters(), { - a: (date, value) => { + a: (date: Date, value: number | string): void => { const hours = date.getHours(); const current = hours >= 12; - // eslint-disable-next-line radix - if (current === !!parseInt(value)) { + if (current === !!+value) { return; } date.setHours((hours + 12) % 24); }, - d: (date, value) => { - // @ts-expect-error + d: (date: Date, value: number | string): void => { const lastDayInMonth = getLimits('dM', date).max; - if (value > lastDayInMonth) { + if (+value > lastDayInMonth) { date.setMonth(date.getMonth() + 1); } - date.setDate(value); + date.setDate(+value); }, - h: (date, value) => { + h: (date: Date, value: number | string): void => { const isPM = date.getHours() >= 12; date.setHours((+value % 12) + (isPM ? 12 : 0)); }, M: monthSetter, L: monthSetter, - E: (date, value) => { - if (value < 0) { + E: (date: Date, value: number | string): void => { + if (+value < 0) { return; } - // eslint-disable-next-line radix - date.setDate(date.getDate() - date.getDay() + parseInt(value)); + + date.setDate(date.getDate() - date.getDay() + +value); }, - y: (date, value) => { + y: (date: Date, value: number | string): void => { const currentYear = date.getFullYear(); const valueLength = String(value).length; - // @ts-expect-error const maxLimitLength = String(getLimits('y', date).max).length; - // eslint-disable-next-line radix - const newValue = parseInt(String(currentYear).substr(0, maxLimitLength - valueLength) + value); + const yearPrefix = String(currentYear).substr(0, maxLimitLength - valueLength); + const newValue = parseInt(yearPrefix + value, 10); date.setFullYear(newValue); }, - x: (date) => date, + x: (date: Date): Date => date, }); -const getPatternGetter = (patternChar) => { - const unsupportedCharGetter = () => patternChar; - return PATTERN_GETTERS[patternChar] || unsupportedCharGetter; +const getPatternGetter = (patternChar: string): string | ((date: Date) => number | Date) => { + const unsupportedCharGetter = (): string => patternChar; + return (PATTERN_GETTERS[patternChar] + ?? unsupportedCharGetter) as string | ((date: Date) => number | Date); }; -export const renderDateParts = (text, regExpInfo) => { - const result = regExpInfo.regexp.exec(text); +interface Section { + index: number; + isStub: boolean; + caret: { start: number; end: number }; + pattern: string; + text: string; + limits: (date: Date, forcedPattern?: string) => { min: number; max: number }; + setter: (date: Date, value: number | string) => void; + getter: string | ((date: Date) => Date | number); +} + +export const renderDateParts = ( + text: string, + regExpInfo: { regexp: RegExp; patterns: string[] }, +): Section[] => { + const result = regExpInfo.regexp.exec(text) ?? []; let start = 0; let end = 0; - const sections = []; + const sections: Section[] = []; - for (let i = 1; i < result.length; i++) { + for (let i = 1; i < result.length; i += 1) { start = end; end = start + result[i].length; const pattern = regExpInfo.patterns[i - 1].replace(/^'|'$/g, ''); const getter = getPatternGetter(pattern[0]); - // @ts-expect-error sections.push({ index: i - 1, isStub: pattern === result[i], caret: { start, end }, pattern, text: result[i], - // @ts-expect-error - limits: (...args) => getLimits(pattern[0], ...args), - setter: PATTERN_SETTERS[pattern[0]] || noop, + limits: (date: Date, forcedPattern?: string) => getLimits(pattern[0], date, forcedPattern), + setter: PATTERN_SETTERS[pattern[0]] ?? noop, getter, }); } @@ -119,31 +153,11 @@ export const renderDateParts = (text, regExpInfo) => { return sections; }; -const getLimits = (pattern, date, forcedPattern) => { - const limits = { - y: { min: 0, max: 9999 }, - M: { min: 1, max: 12 }, - L: { min: 1, max: 12 }, - d: { min: 1, max: 31 }, - dM: { - min: 1, - max: new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(), - }, - E: { min: 0, max: 6 }, - H: { min: 0, max: 23 }, - h: { min: 1, max: 12 }, - m: { min: 0, max: 59 }, - s: { min: 0, max: 59 }, - S: { min: 0, max: 999 }, - a: { min: 0, max: 1 }, - x: { min: 0, max: 0 }, // NOTE: Timezone part is read only. - }; - // @ts-expect-error - return limits[forcedPattern || pattern] || limits.getAmPm; -}; - -export const getDatePartIndexByPosition = (dateParts, position) => { - for (let i = 0; i < dateParts.length; i++) { +export const getDatePartIndexByPosition = ( + dateParts: { caret: { start: number; end: number }; isStub: boolean }[], + position: number, +): number | null => { + for (let i = 0; i < dateParts.length; i += 1) { const caretInGroup = dateParts[i].caret.end >= position; if (!dateParts[i].isStub && caretInGroup) { diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.ts index ced4a0def4c2..a69cf7a348b5 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.ts @@ -1,3 +1,4 @@ +/* eslint-disable class-methods-use-this */ import eventsEngine from '@js/common/core/events/core/events_engine'; import { addNamespace, isCommandKeyPressed, normalizeKeyName } from '@js/common/core/events/utils/index'; import defaultDateNames from '@js/common/core/localization/default_date_names'; @@ -12,9 +13,14 @@ import { isDate, isDefined, isFunction, isString, } from '@js/core/utils/type'; import type { DxEvent } from '@js/events'; -import type { Properties } from '@js/ui/date_box'; +import type { DateLike, Properties } from '@js/ui/date_box'; import dateLocalization from '@ts/core/localization/date'; +import type { OptionChanged } from '@ts/core/widget/types'; +import type { KeyboardKeyDownEvent } from '@ts/events/core/m_keyboard_processor'; +import type { ValueChangedEvent } from '../editor/editor'; +import type { DxMouseWheelEvent } from '../scroll_view/types'; +import type { DateBoxBaseProperties } from './m_date_box.base'; import DateBoxBase from './m_date_box.base'; import { getDatePartIndexByPosition, renderDateParts } from './m_date_box.mask.parts'; @@ -30,26 +36,26 @@ class DateBoxMask extends DateBoxBase { _maskValue?: Date | null; - _dateParts!: Record[]; + _dateParts!: { caret: { start: number; end: number }; isStub: boolean }[]; _maskInputHandler?: (() => void) | null; - _initialMaskValue?: Date; + _initialMaskValue?: Date | null; _searchValue!: string; - _regExpInfo?: Record; + _regExpInfo!: { regexp: RegExp; patterns: string[] }; - _formatPattern?: unknown; + _formatPattern?: string | null; - _supportedKeys(): Record boolean> { + _supportedKeys(): Record unknown> { const originalHandlers = super._supportedKeys(); - const callOriginalHandler = (e) => { - // @ts-expect-error ts-error - const originalHandler = originalHandlers[normalizeKeyName(e)]; + const callOriginalHandler = (e: KeyboardEvent): unknown => { + const normalizedKeyName = normalizeKeyName(e); + const originalHandler = normalizedKeyName ? originalHandlers[normalizedKeyName] : undefined; return originalHandler?.apply(this, [e]); }; - const applyHandler = (e, maskHandler) => { + const applyHandler = (e: KeyboardEvent, maskHandler: (e: KeyboardEvent) => void): unknown => { if (this._shouldUseOriginalHandler(e)) { return callOriginalHandler.apply(this, [e]); } @@ -60,17 +66,21 @@ class DateBoxMask extends DateBoxBase { ...originalHandlers, del: (e) => applyHandler(e, (event) => { this._revertPart(FORWARD); - this._isAllSelected() || event.preventDefault(); + if (!this._isAllSelected()) { + event.preventDefault(); + } }), backspace: (e) => applyHandler(e, (event) => { this._revertPart(BACKWARD); - this._isAllSelected() || event.preventDefault(); + if (!this._isAllSelected()) { + event.preventDefault(); + } }), - home: (e) => applyHandler(e, (event) => { + home: (e) => applyHandler(e, (event): void => { this._selectFirstPart(); event.preventDefault(); }), - end: (e) => applyHandler(e, (event) => { + end: (e) => applyHandler(e, (event): void => { this._selectLastPart(); event.preventDefault(); }), @@ -99,15 +109,15 @@ class DateBoxMask extends DateBoxBase { }; } - _shouldUseOriginalHandler(e) { + _shouldUseOriginalHandler(e: KeyboardEvent): boolean { const keysToHandleByMask = ['backspace', 'del']; - // @ts-expect-error - const isNotDeletingInCalendar = this.option('opened') && e && !keysToHandleByMask.includes(normalizeKeyName(e)); + const { opened = false } = this.option(); + const isNotDeletingInCalendar = opened && e && !keysToHandleByMask.includes(normalizeKeyName(e) ?? ''); return !this._useMaskBehavior() || isNotDeletingInCalendar || (e && e.altKey); } - _upDownArrowHandler(step): void { + _upDownArrowHandler(step: number): void { this._setNewDateIfEmpty(); const originalValue = this._getActivePartValue(this._initialMaskValue); @@ -119,7 +129,7 @@ class DateBoxMask extends DateBoxBase { this._changePartValue(delta + step, true); } - _changePartValue(step, lockOtherParts?) { + _changePartValue(step: number, lockOtherParts?: boolean): void { const activePartPattern = this._getActivePartProp('pattern'); const isAmPmPartActive = /^a{1,5}$/.test(activePartPattern); @@ -132,8 +142,11 @@ class DateBoxMask extends DateBoxBase { _toggleAmPm(): void { const currentValue = this._getActivePartProp('text'); - // @ts-expect-error ts-error - const indexOfCurrentValue = defaultDateNames.getPeriodNames().indexOf(currentValue); + const indexOfCurrentValue = defaultDateNames + // @ts-expect-error getPeriodNames type should be fixed + .getPeriodNames(this._formatPattern) + .indexOf(currentValue); + // eslint-disable-next-line no-bitwise const newValue = indexOfCurrentValue ^ 1; this._setActivePartValue(newValue); } @@ -146,30 +159,40 @@ class DateBoxMask extends DateBoxBase { }; } - _isSingleCharKey({ originalEvent, alt }) { - const key = originalEvent.data || originalEvent.key; + _isSingleCharKey( + { originalEvent, alt }: { + originalEvent: { data: string, key: string, ctrlKey: boolean, metaKey: boolean }; + alt?: boolean + }, + ): boolean { + const key = originalEvent.data ?? originalEvent.key; return typeof key === 'string' && key.length === 1 && !alt && !isCommandKeyPressed(originalEvent); } - _isSingleDigitKey(e) { + _isSingleDigitKey(e: { + originalEvent: InputEvent; + alt?: boolean; + }): boolean { const data = e.originalEvent?.data; - return data?.length === 1 && parseInt(data, 10); + return data?.length === 1 && Boolean(parseInt(data, 10)); } - _useBeforeInputEvent() { - return devices.real().android; + _useBeforeInputEvent(): boolean { + return Boolean(devices.real().android); } - _keyInputHandler(e, key): void { + _keyInputHandler(e: DxEvent, key: string): void { const oldInputValue = this._input().val(); this._processInputKey(key); e.preventDefault(); const isValueChanged = oldInputValue !== this._input().val(); - // @ts-expect-error ts-error - isValueChanged && eventsEngine.trigger(this._input(), 'input'); + + if (isValueChanged) { + eventsEngine.triggerHandler(this._input(), { type: 'input' }); + } } - _keyboardHandler(e) { + _keyboardHandler(e: KeyboardKeyDownEvent): boolean { let { key } = e.originalEvent; const result = super._keyboardHandler(e); @@ -178,10 +201,10 @@ class DateBoxMask extends DateBoxBase { return result; } - if (browser.chrome && e.key === 'Process' && e.code.indexOf('Digit') === 0) { + if (browser.chrome && e.key === 'Process' && e.code.startsWith('Digit')) { key = e.code.replace('Digit', ''); this._processInputKey(key); - this._maskInputHandler = () => { + this._maskInputHandler = (): void => { this._renderSelectedPart(); }; } else if (this._isSingleCharKey(e)) { @@ -191,13 +214,13 @@ class DateBoxMask extends DateBoxBase { return result; } - _maskBeforeInputHandler(e) { + _maskBeforeInputHandler(e: DxEvent): boolean { this._maskInputHandler = null; const { inputType } = e.originalEvent; if (inputType === 'insertCompositionText') { - this._maskInputHandler = () => { + this._maskInputHandler = (): void => { this._renderSelectedPart(); }; } @@ -206,26 +229,26 @@ class DateBoxMask extends DateBoxBase { const isForwardDeletion = inputType === 'deleteContentForward'; if (isBackwardDeletion || isForwardDeletion) { const direction = isBackwardDeletion ? BACKWARD : FORWARD; - this._maskInputHandler = () => { + this._maskInputHandler = (): void => { this._revertPart(); this._selectNextPart(direction); }; } if (!this._useMaskBehavior() || !this._isSingleCharKey(e)) { - return; + return false; } - const key = e.originalEvent.data; + const key = e.originalEvent.data ?? ''; this._keyInputHandler(e, key); return true; } - _keyPressHandler(e) { + _keyPressHandler(e: { originalEvent: InputEvent & KeyboardEvent }): void { const { originalEvent: event } = e; if (event?.inputType === 'insertCompositionText' && this._isSingleDigitKey(e)) { - this._processInputKey(event.data); + this._processInputKey(event.data ?? ''); this._renderDisplayText(this._getDisplayedText(this._maskValue)); this._selectNextPart(); } @@ -245,8 +268,8 @@ class DateBoxMask extends DateBoxBase { this._clearSearchValue(); } this._setNewDateIfEmpty(); - // eslint-disable-next-line radix - if (isNaN(parseInt(key))) { + + if (isNaN(parseInt(key, 10))) { this._searchString(key); } else { this._searchNumber(key); @@ -255,58 +278,59 @@ class DateBoxMask extends DateBoxBase { _isAllSelected(): boolean { const caret = this._caret(); - const { text } = this.option(); - // @ts-expect-error ts-error + const { text = '' } = this.option(); + return caret.end - caret.start === text.length; } - _getFormatPattern() { + _getFormatPattern(): string { if (this._formatPattern) { return this._formatPattern; } - const format = this._strategy.getDisplayFormat(this.option('displayFormat')); + const { displayFormat } = this.option(); + const format = this._strategy.getDisplayFormat(displayFormat); const isLDMLPattern = isString(format) && !dateLocalization._getPatternByFormat(format); if (isLDMLPattern) { this._formatPattern = format; } else { - this._formatPattern = getFormat((value) => dateLocalization.format(value, format)); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + this._formatPattern = getFormat((value) => dateLocalization.format(value, format)) as string; } return this._formatPattern; } - _setNewDateIfEmpty() { + _setNewDateIfEmpty(): void { if (!this._maskValue) { const { type } = this.option(); - // @ts-expect-error ts-error - const value = type === 'time' ? new Date(null) : new Date(); + const value = type === 'time' ? new Date(0) : new Date(); + this._maskValue = value; this._initialMaskValue = value; this._renderDateParts(); } } - _partLimitsReached(max) { + _partLimitsReached(max: number): boolean { const maxLimitLength = String(max).length; const formatLength = this._getActivePartProp('pattern').length; const isShortFormat = formatLength === 1; const maxSearchLength = isShortFormat ? maxLimitLength : Math.min(formatLength, maxLimitLength); const isLengthExceeded = this._searchValue.length === maxSearchLength; - // eslint-disable-next-line radix - const isValueOverflowed = parseInt(`${this._searchValue}0`) > max; + const isValueOverflowed = parseInt(`${this._searchValue}0`, 10) > max; return isLengthExceeded || isValueOverflowed; } - _searchNumber(char): void { + _searchNumber(char: string): void { const { max } = this._getActivePartLimits(); const maxLimitLength = String(max).length; this._searchValue = (this._searchValue + char).substr(-maxLimitLength); - // @ts-expect-error ts-error - if (isNaN(this._searchValue)) { + + if (isNaN(parseInt(this._searchValue, 10))) { this._searchValue = char; } @@ -317,7 +341,7 @@ class DateBoxMask extends DateBoxBase { } } - _searchString(char) { + _searchString(char: string): void { const text = this._getActivePartProp('text'); const convertedText = numberLocalization.convertDigits(text, true); @@ -325,16 +349,16 @@ class DateBoxMask extends DateBoxBase { return; } - const limits = this._getActivePartProp('limits')(this._maskValue); + const limits = this._getActivePartProp('limits')(this._maskValue as Date); const startString = this._searchValue + char.toLowerCase(); const endLimit = limits.max - limits.min; - for (let i = 0; i <= endLimit; i++) { + for (let i = 0; i <= endLimit; i += 1) { this._loadMaskValue(this._initialMaskValue); this._changePartValue(i + 1); - if (this._getActivePartProp('text').toLowerCase().indexOf(startString) === 0) { + if (this._getActivePartProp('text').toLowerCase().startsWith(startString)) { this._searchValue = startString; return; } @@ -352,9 +376,10 @@ class DateBoxMask extends DateBoxBase { this._searchValue = ''; } - _revertPart(direction?): void { + _revertPart(direction?: number): void { if (!this._isAllSelected()) { - const actual = this._getActivePartValue(this.option('emptyDateValue')); + const { emptyDateValue } = this.option(); + const actual = this._getActivePartValue(emptyDateValue); this._setActivePartValue(actual); this._selectNextPart(direction); @@ -368,12 +393,9 @@ class DateBoxMask extends DateBoxBase { } _prepareRegExpInfo(): void { - // @ts-expect-error ts-error this._regExpInfo = getRegExpInfo(this._getFormatPattern(), dateLocalization); const { regexp } = this._regExpInfo; - // @ts-expect-error ts-error const { source } = regexp; - // @ts-expect-error ts-error const { flags } = regexp; const quantifierRegexp = new RegExp(/(\{[0-9]+,?[0-9]*\})/); @@ -381,7 +403,7 @@ class DateBoxMask extends DateBoxBase { .split(quantifierRegexp) .map((sourcePart) => (quantifierRegexp.test(sourcePart) ? sourcePart - : numberLocalization.convertDigits(sourcePart, false))) + : numberLocalization.convertDigits(sourcePart, false)) as string) .join(''); this._regExpInfo.regexp = new RegExp(convertedSource, flags); } @@ -410,10 +432,12 @@ class DateBoxMask extends DateBoxBase { return; } - const text = this.option('text') || this._getDisplayedText(this._maskValue); + const { text } = this.option(); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const newText = text || this._getDisplayedText(this._maskValue); - if (text) { - this._dateParts = renderDateParts(text, this._regExpInfo); + if (newText) { + this._dateParts = renderDateParts(newText, this._regExpInfo); if (!this._input().is(':hidden')) { this._selectNextPart(); } @@ -461,9 +485,9 @@ class DateBoxMask extends DateBoxBase { return true; } - _onMouseWheel(e): void { + _onMouseWheel(e: DxMouseWheelEvent): void { if (this._useMaskBehavior()) { - this._partIncrease(e.delta > 0 ? FORWARD : BACKWARD, e); + this._partIncrease(e.delta > 0 ? FORWARD : BACKWARD, Boolean(e)); } } @@ -473,22 +497,23 @@ class DateBoxMask extends DateBoxBase { } if (step) { - // @ts-expect-error ts-error - this._initialMaskValue = new Date(this._maskValue); + this._initialMaskValue = new Date(this._maskValue as Date); } - // @ts-expect-error ts-error - let index = fitIntoRange(this._activePartIndex + step, 0, this._dateParts.length - 1); + + const activePartIndex = this._activePartIndex ?? 0; + let index = fitIntoRange(activePartIndex + step, 0, this._dateParts.length - 1); if (this._dateParts[index].isStub) { - const isBoundaryIndex = index === 0 && step < 0 || index === this._dateParts.length - 1 && step > 0; + const isBoundaryIndex = (index === 0 && step < 0) + || (index === this._dateParts.length - 1 && step > 0); if (!isBoundaryIndex) { this._selectNextPart(step >= 0 ? step + 1 : step - 1); return; } - // @ts-expect-error ts-error - index = this._activePartIndex; + + index = activePartIndex; } - if (this._activePartIndex !== index) { + if (activePartIndex !== index) { this._clearSearchValue(); } @@ -496,60 +521,77 @@ class DateBoxMask extends DateBoxBase { this._caret(this._getActivePartProp('caret')); } - // @ts-expect-error - _getRealLimitsPattern() { - if (this._getActivePartProp('pattern')[0] === 'd') { + _getRealLimitsPattern(): string | undefined { + if (this._getActivePartProp('pattern').startsWith('d')) { return 'dM'; } + + return undefined; } - _getActivePartLimits(lockOtherParts?) { + _getActivePartLimits(lockOtherParts = false): { min: number; max: number } { const limitFunction = this._getActivePartProp('limits'); - return limitFunction(this._maskValue, lockOtherParts && this._getRealLimitsPattern()); + return limitFunction( + this._maskValue as Date, + lockOtherParts ? this._getRealLimitsPattern() : undefined, + ); } - _getActivePartValue(dateValue?) { - dateValue = dateValue || this._maskValue; + _getActivePartValue(dateValue?: Date | null): number { + const date = dateValue ?? this._maskValue as Date; const getter = this._getActivePartProp('getter'); - return isFunction(getter) ? getter(dateValue) : dateValue[getter](); + + return isFunction(getter) ? getter(date) : date[getter]() as number; } - _addLeadingZeroes(value) { + _addLeadingZeroes(value: number): string { const zeroes = /^0+/.exec(this._searchValue); const limits = this._getActivePartLimits(); const maxLimitLength = String(limits.max).length; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - return ((zeroes && zeroes[0] || '') + String(value)).substr(-maxLimitLength); + return (((zeroes?.[0]) ?? '') + String(value)).substr(-maxLimitLength); } - _setActivePartValue(value, dateValue?) { - dateValue = dateValue || this._maskValue; + _setActivePartValue(value: number | string, dateValue?: Date): void { + let newValue: number | string = +value; + const newDateValue = dateValue ?? this._maskValue as Date; const setter = this._getActivePartProp('setter'); const limits = this._getActivePartLimits(); - value = inRange(value, limits.min, limits.max) ? value : value % 10; - value = this._addLeadingZeroes(fitIntoRange(value, limits.min, limits.max)); + newValue = inRange(newValue, limits.min, limits.max) ? newValue : newValue % 10; + newValue = this._addLeadingZeroes(fitIntoRange(newValue, limits.min, limits.max)); - isFunction(setter) ? setter(dateValue, value) : dateValue[setter](value); - this._renderDisplayText(this._getDisplayedText(dateValue)); + if (isFunction(setter)) { + setter(newDateValue, newValue); + } else { + newDateValue[setter](newValue); + } + this._renderDisplayText(this._getDisplayedText(newDateValue)); this._renderDateParts(); } - _getActivePartProp(property) { - // @ts-expect-error ts-error + _getActivePartProp(property: 'caret'): { start: number; end: number }; + _getActivePartProp(property: 'isStub'): boolean; + _getActivePartProp(property: 'pattern' | 'text'): string; + _getActivePartProp(property: 'limits'): (date: Date, forcedPattern?: string) => { min: number; max: number }; + _getActivePartProp(property: 'setter'): string | ((date: Date, value: number | string) => void); + _getActivePartProp(property: 'getter'): string | ((date: Date) => number); + _getActivePartProp(property: 'caret' | 'isStub' | 'pattern' | 'text' | 'limits' | 'setter' | 'getter'): unknown { + if (!isDefined(this._activePartIndex)) { + return undefined; + } - if (!this._dateParts || !this._dateParts[this._activePartIndex]) { + if (!this._dateParts?.[this._activePartIndex]) { return undefined; } - // @ts-expect-error ts-error - return this._dateParts[this._activePartIndex][property]; + + return this._dateParts[this._activePartIndex][property] as unknown; } - _loadMaskValue(value = this.dateOption('value')) { - this._maskValue = value && new Date(value); - this._initialMaskValue = value && new Date(value); + _loadMaskValue(value: Date | null | string = this.getDateOption('value')): void { + this._maskValue = value ? new Date(value) : null; + this._initialMaskValue = value ? new Date(value) : null; } _saveMaskValue(): void { @@ -563,7 +605,7 @@ class DateBoxMask extends DateBoxBase { this._initialMaskValue = new Date(value); if (this._applyInternalValidation(value).isValid) { - this.dateOption('value', value); + this.setDateOption('value', value); } } @@ -573,14 +615,14 @@ class DateBoxMask extends DateBoxBase { this._renderDateParts(); } - _renderDisplayText(text): void { + _renderDisplayText(text?: string): void { super._renderDisplayText(text); if (this._useMaskBehavior()) { this.option('text', text); } } - _partIncrease(step, lockOtherParts): void { + _partIncrease(step: number, lockOtherParts?: boolean): void { this._setNewDateIfEmpty(); const { max, min } = this._getActivePartLimits(lockOtherParts); @@ -596,14 +638,18 @@ class DateBoxMask extends DateBoxBase { this._setActivePartValue(newValue); } - _applyLimits(newValue, { limitBase, limitClosest, max }) { + _applyLimits( + newValue: number, + { limitBase, limitClosest, max }: { limitBase: number, limitClosest: number, max: number }, + ): number { const delta = (newValue - limitClosest) % max; return delta ? limitBase + delta - 1 * sign(delta) : limitClosest; } - _maskClickHandler() { + _maskClickHandler(): void { this._loadMaskValue(this._maskValue); - if (this.option('text')) { + const { text } = this.option(); + if (text) { this._activePartIndex = getDatePartIndexByPosition(this._dateParts, this._caret().start); if (!this._isAllSelected()) { @@ -618,18 +664,18 @@ class DateBoxMask extends DateBoxBase { } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _maskCompositionEndHandler(e): void { + _maskCompositionEndHandler(): void { this._input().val(this._getDisplayedText(this._maskValue)); this._selectNextPart(); - this._maskInputHandler = () => { + this._maskInputHandler = (): void => { this._renderSelectedPart(); }; } - _maskPasteHandler(e): void { - const newText = this._replaceSelectedText(this.option('text'), this._caret(), clipboardText(e)); + _maskPasteHandler(e: DxEvent): void { + const { text } = this.option(); + const newText = this._replaceSelectedText(text, this._caret(), clipboardText(e)); const date = dateLocalization.parse(newText, this._getFormatPattern()); if (date && this._isDateValid(date)) { @@ -642,23 +688,21 @@ class DateBoxMask extends DateBoxBase { e.preventDefault(); } - _isDateValid(date): boolean { - // @ts-expect-error ts-error - return isDate(date) && !isNaN(date); + _isDateValid(date: DateLike): boolean { + return isDate(date) && !isNaN(date.getTime()); } - _isValueDirty() { - const value = this.dateOption('value'); + _isValueDirty(): boolean { + const value = this.getDateOption('value'); - return (this._maskValue && this._maskValue.getTime()) !== (value && value.getTime()); + return this._maskValue?.getTime() !== value?.getTime(); } - _fireChangeEvent() { + _fireChangeEvent(): void { this._clearSearchValue(); if (this._isValueDirty()) { - // @ts-expect-error - eventsEngine.trigger(this._input(), 'change'); + eventsEngine.triggerHandler(this._input(), { type: 'change' }); } } @@ -683,8 +727,8 @@ class DateBoxMask extends DateBoxBase { } } - _valueChangeEventHandler(e) { - const text = this.option('text'); + _valueChangeEventHandler(e: ValueChangedEvent): void { + const { text } = this.option(); if (this._useMaskBehavior()) { this._saveValueChangeEvent(e); @@ -699,7 +743,7 @@ class DateBoxMask extends DateBoxBase { } } - _optionChanged(args): void { + _optionChanged(args: OptionChanged): void { switch (args.name) { case 'useMaskBehavior': this._renderMask(); diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar.ts index d675e614b359..6f824314b905 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar.ts @@ -1,12 +1,14 @@ +/* eslint-disable class-methods-use-this */ import messageLocalization from '@js/common/core/localization/message'; -// @ts-expect-error -import { splitPair } from '@js/core/utils/common'; import dateUtils from '@js/core/utils/date'; import { extend } from '@js/core/utils/extend'; import { isEmptyObject, isFunction } from '@js/core/utils/type'; import Calendar from '@js/ui/calendar'; +import type { ToolbarItem } from '@js/ui/popup'; import { isMaterial } from '@js/ui/themes'; +import { splitPair } from '@ts/core/utils/m_common'; +import type { PopupProperties } from '../popup/m_popup'; import DateBoxStrategy from './m_date_box.strategy'; const TODAY_BUTTON_CLASS = 'dx-button-today'; @@ -27,8 +29,7 @@ class CalendarStrategy extends DateBoxStrategy { }; } - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type - supportedKeys(): Record boolean | void> { + supportedKeys(): Record void> { const homeEndHandler = function (e) { if (this.option('opened')) { e.preventDefault(); @@ -131,7 +132,7 @@ class CalendarStrategy extends DateBoxStrategy { this.dateBox.setAria('activedescendant', e.actionValue); } - _getTodayButtonConfig() { + _getTodayButtonConfig(): ToolbarItem { const buttonsLocation = this.dateBox.option('buttonsLocation'); const isButtonsLocationDefault = buttonsLocation === 'default'; const position = isButtonsLocationDefault ? ['bottom', 'center'] : splitPair(buttonsLocation); @@ -157,7 +158,7 @@ class CalendarStrategy extends DateBoxStrategy { return isEmptyObject(calendarOptions) || calendarOptions.visible !== false; } - _getPopupToolbarItems(toolbarItems) { + _getPopupToolbarItems(toolbarItems: ToolbarItem[]): ToolbarItem[] { const useButtons = this.dateBox.option('applyValueMode') === 'useButtons'; const shouldRenderTodayButton = useButtons && this._isCalendarVisible(); @@ -173,11 +174,11 @@ class CalendarStrategy extends DateBoxStrategy { return toolbarItems; } - popupConfig(popupConfig) { + popupConfig(popupConfig: PopupProperties): PopupProperties { return extend(true, popupConfig, { position: { collision: 'flipfit flip' }, width: 'auto', - }); + }) as PopupProperties; } _valueChangedHandler(e) { @@ -193,8 +194,7 @@ class CalendarStrategy extends DateBoxStrategy { } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _updateValue(preventDefaultValue?: boolean) { + _updateValue() { if (!this._widget) { return; } @@ -206,7 +206,7 @@ class CalendarStrategy extends DateBoxStrategy { this._lastActionElement = 'input'; if (this.dateBox.option('opened') && this._widget) { - this._updateValue(true); + this._updateValue(); } } diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar_with_time.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar_with_time.ts index b165920b68d4..162eea2bdc9e 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar_with_time.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.calendar_with_time.ts @@ -7,6 +7,8 @@ import { getWindow } from '@js/core/utils/window'; import Box from '@ts/ui/box'; import TimeView from '@ts/ui/date_box/time_view'; +import type { PopupProperties } from '../popup/m_popup'; +import type DateBox from './m_date_box.base'; import CalendarStrategy from './m_date_box.strategy.calendar'; import uiDateUtils from './m_date_utils'; @@ -19,15 +21,17 @@ const DATEBOX_TIMEVIEW_SIDE_CLASS = 'dx-datebox-datetime-time-side'; class CalendarWithTimeStrategy extends CalendarStrategy { _timeView!: TimeView; + // eslint-disable-next-line no-restricted-globals _repaintTimer?: ReturnType; + // eslint-disable-next-line no-restricted-globals _removeMinWidthTimer?: ReturnType; _currentAdaptiveMode?: boolean; _box?: Box; - ctor(dateBox): void { + ctor(dateBox: DateBox): void { super.ctor(dateBox); this.NAME = 'CalendarWithTime'; @@ -99,7 +103,7 @@ class CalendarWithTimeStrategy extends CalendarStrategy { return super.isAdaptivityChanged(); } - _updateValue(preventDefaultValue) { + _updateValue(preventDefaultValue?: boolean): void { let date = this.dateBoxValue(); if (!date && !preventDefaultValue) { @@ -170,9 +174,9 @@ class CalendarWithTimeStrategy extends CalendarStrategy { }); } - popupConfig(popupConfig) { + popupConfig(popupConfig: PopupProperties): PopupProperties { const calendarPopupConfig = super.popupConfig(popupConfig); - return extend(calendarPopupConfig, { width: 'auto' }); + return extend(calendarPopupConfig, { width: 'auto' }) as PopupProperties; } _preventFocusOnPopup(e): void { diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.date_view.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.date_view.ts index b3e3eae25f26..caf2f1fc2cac 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.date_view.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.date_view.ts @@ -122,8 +122,8 @@ class DateViewStrategy extends DateBoxStrategy { return { value: this.dateBoxValue() || new Date(), type: this.dateBox.option('type'), - minDate: this.dateBox.dateOption('min') || new Date(1900, 0, 1), - maxDate: this.dateBox.dateOption('max') || new Date(Date.now() + 50 * dateUtils.ONE_YEAR), + minDate: this.dateBox.getDateOption('min') || new Date(1900, 0, 1), + maxDate: this.dateBox.getDateOption('max') || new Date(Date.now() + 50 * dateUtils.ONE_YEAR), onDisposing: function () { this._widget = null; }.bind(this), diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.list.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.list.ts index 173e9c582dc1..401151670d2f 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.list.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.list.ts @@ -1,3 +1,4 @@ +/* eslint-disable class-methods-use-this */ import '@ts/ui/list/modules/selection'; import dateLocalization from '@js/common/core/localization/date'; @@ -9,6 +10,7 @@ import { getWindow } from '@js/core/utils/window'; import { getSizeValue } from '@ts/ui/drop_down_editor/m_utils'; import List from '@ts/ui/list/list.edit.search'; +import type { PopupProperties } from '../popup/m_popup'; import DateBoxStrategy from './m_date_box.strategy'; import dateUtils from './m_date_utils'; @@ -51,7 +53,7 @@ class ListStrategy extends DateBoxStrategy { return displayFormat || 'shorttime'; } - popupConfig(popupConfig) { + popupConfig(popupConfig: PopupProperties): PopupProperties { return popupConfig; } @@ -174,9 +176,9 @@ class ListStrategy extends DateBoxStrategy { } _getTimeListItems() { - let min = this.dateBox.dateOption('min') || this._getBoundaryDate('min'); - const max = this.dateBox.dateOption('max') || this._getBoundaryDate('max'); - const value = this.dateBox.dateOption('value') || null; + let min = this.dateBox.getDateOption('min') || this._getBoundaryDate('min'); + const max = this.dateBox.getDateOption('max') || this._getBoundaryDate('max'); + const value = this.dateBox.getDateOption('value') || null; let delta = max - min; const minutes = min.getMinutes() % this.dateBox.option('interval'); @@ -217,7 +219,7 @@ class ListStrategy extends DateBoxStrategy { _getBoundaryDate(boundary) { const boundaryValue = BOUNDARY_VALUES[boundary]; - const currentValue = new Date(ensureDefined(this.dateBox.dateOption('value'), 0)); + const currentValue = new Date(ensureDefined(this.dateBox.getDateOption('value'), 0)); return new Date( currentValue.getFullYear(), diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.native.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.native.ts index 5da622c926a4..24faf41268c6 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.native.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.native.ts @@ -82,8 +82,8 @@ class NativeStrategy extends DateBoxStrategy { }[type] ?? defaultFormat; $input.attr({ - min: dateSerialization.serializeDate(this.dateBox.dateOption('min'), format), - max: dateSerialization.serializeDate(this.dateBox.dateOption('max'), format), + min: dateSerialization.serializeDate(this.dateBox.getDateOption('min'), format), + max: dateSerialization.serializeDate(this.dateBox.getDateOption('max'), format), }); } } diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.ts index 3a2ca29b1e45..1332349c2449 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.ts @@ -1,7 +1,9 @@ +/* eslint-disable class-methods-use-this */ import eventsEngine from '@js/common/core/events/core/events_engine'; import dateLocalization from '@js/common/core/localization/date'; import Class from '@js/core/class'; import $ from '@js/core/renderer'; +import type { ToolbarItem } from '@js/ui/popup'; import type { PopupProperties } from '../popup/m_popup'; @@ -59,10 +61,8 @@ class DateBoxStrategy extends (Class.inherit({}) as new() => {}) { customizeButtons() {} getParsedText(text, format) { - // @ts-expect-error const value = dateLocalization.parse(text, format); - // @ts-expect-error - return value || dateLocalization.parse(text); + return value ?? dateLocalization.parse(text); } renderInputMinMax(): void {} @@ -71,17 +71,15 @@ class DateBoxStrategy extends (Class.inherit({}) as new() => {}) { this._updateValue(); } - // @ts-expect-error ts-error - // eslint-disable-next-line @typescript-eslint/no-unused-vars popupConfig(popupConfig: PopupProperties): PopupProperties { - Class.abstract(); + return popupConfig; } _dimensionChanged(): void { this._getPopup()?.repaint(); } - renderPopupContent() { + renderPopupContent(): void { const popup = this._getPopup(); this._renderWidget(); @@ -106,14 +104,19 @@ class DateBoxStrategy extends (Class.inherit({}) as new() => {}) { popupHiddenHandler() {} - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _updateValue(preventDefaultValue?: boolean) { + _updateValue() { this._widget?.option('value', this.dateBoxValue()); } - useCurrentDateByDefault() {} + _getPopupToolbarItems(toolbarItems: ToolbarItem[]): ToolbarItem[] { + return toolbarItems; + } + + useCurrentDateByDefault(): boolean { + return false; + } - getDefaultDate() { + getDefaultDate(): Date { return new Date(); } @@ -146,7 +149,7 @@ class DateBoxStrategy extends (Class.inherit({}) as new() => {}) { if (arguments.length) { return this.dateBox.dateValue.apply(this.dateBox, arguments); } - return this.dateBox.dateOption.apply(this.dateBox, ['value']); + return this.dateBox.getDateOption.apply(this.dateBox, ['value']); } } diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_utils.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_utils.ts index 28429841f8b0..679486ff562a 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_utils.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_utils.ts @@ -1,8 +1,8 @@ import dateLocalization from '@js/common/core/localization/date'; import $ from '@js/core/renderer'; import dateSerialization from '@js/core/utils/date_serialization'; -import { each } from '@js/core/utils/iterator'; import { isDate } from '@js/core/utils/type'; +import type { DateLike, DateType } from '@js/ui/date_box'; const DATE_COMPONENTS = ['year', 'day', 'month', 'day']; const TIME_COMPONENTS = ['hours', 'minutes', 'seconds', 'milliseconds']; @@ -11,14 +11,23 @@ const ONE_MINUTE = 1000 * 60; const ONE_DAY = ONE_MINUTE * 60 * 24; const ONE_YEAR = ONE_DAY * 365; -const getStringFormat = function (format) { +type FormatKey = DateType | 'datetime-local'; +type DateComponentKey = 'year' | 'day' | 'month' | 'hours' | 'minutes' | 'seconds' | 'milliseconds'; +type ShortFormat = 'shortdate' | 'shorttime' | 'shortdateshorttime'; + +interface FormatInfo { + getStandardPattern: () => string; + components: DateComponentKey[]; +} + +const getStringFormat = (format: string | { type: string }): string | null => { const formatType = typeof format; if (formatType === 'string') { return 'format'; } - if (formatType === 'object' && format.type !== undefined) { + if (typeof format === 'object' && format.type !== undefined) { return format.type; } @@ -33,29 +42,29 @@ const dateUtils = { ONE_YEAR, MIN_DATEVIEW_DEFAULT_DATE: new Date(1900, 0, 1), - MAX_DATEVIEW_DEFAULT_DATE: (function () { + MAX_DATEVIEW_DEFAULT_DATE: ((): Date => { const newDate = new Date(); return new Date(newDate.getFullYear() + 50, newDate.getMonth(), newDate.getDate(), 23, 59, 59); - }()), + })(), FORMATS_INFO: { date: { - getStandardPattern() { + getStandardPattern(): string { return 'yyyy-MM-dd'; }, components: DATE_COMPONENTS, }, time: { - getStandardPattern() { + getStandardPattern(): string { return 'HH:mm'; }, components: TIME_COMPONENTS, }, datetime: { - getStandardPattern() { - let standardPattern; + getStandardPattern(): string { + let standardPattern = 'yyyy-MM-ddTHH:mm:ssZ'; - (function androidFormatDetection() { + (function androidFormatDetection(): void { const androidFormatPattern = 'yyyy-MM-ddTHH:mmZ'; const testDateString = '2000-01-01T01:01Z'; @@ -67,13 +76,9 @@ const dateUtils = { } }()); - if (!standardPattern) { - standardPattern = 'yyyy-MM-ddTHH:mm:ssZ'; - } + standardPattern ??= 'yyyy-MM-ddTHH:mm:ssZ'; - dateUtils.FORMATS_INFO.datetime.getStandardPattern = function () { - return standardPattern; - }; + dateUtils.FORMATS_INFO.datetime.getStandardPattern = (): string => standardPattern; return standardPattern; }, @@ -85,62 +90,65 @@ const dateUtils = { }, components: [...DATE_COMPONENTS, 'hours', 'minutes', 'seconds'], }, - }, + } as Record, FORMATS_MAP: { date: 'shortdate', time: 'shorttime', datetime: 'shortdateshorttime', - }, + } as Record, SUBMIT_FORMATS_MAP: { date: 'date', time: 'time', datetime: 'datetime-local', - }, + } as Record, - toStandardDateFormat(date, type) { + toStandardDateFormat(date: DateLike | undefined, type: string): string { const pattern = dateUtils.FORMATS_INFO[type].getStandardPattern(); - return dateSerialization.serializeDate(date, pattern); + return dateSerialization.serializeDate(date, pattern) as string; }, - fromStandardDateFormat(text) { + fromStandardDateFormat(text: string): Date | undefined { const date = dateSerialization.dateParser(text); return isDate(date) ? date : undefined; }, - getMaxMonthDay(year, month) { + getMaxMonthDay(year: number, month: number): number { return new Date(year, month + 1, 0).getDate(); }, - mergeDates(oldValue, newValue, format) { + mergeDates( + oldValue: Date | null | undefined, + newValue: Date | null | undefined, + format: FormatKey, + ): Date | null { + let oldDate = oldValue; if (!newValue) { - return newValue || null; + return newValue ?? null; } - if (!oldValue || isNaN(oldValue.getTime())) { - // @ts-expect-error - const now = new Date(null); - oldValue = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + if (!oldDate || isNaN(oldDate.getTime())) { + const now = new Date(0); + oldDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()); } - const result = new Date(oldValue.valueOf()); + const result = new Date(oldDate.valueOf()); const formatInfo = dateUtils.FORMATS_INFO[format]; - each(formatInfo.components, function () { - // @ts-expect-error - const componentInfo = dateUtils.DATE_COMPONENTS_INFO[this]; + formatInfo.components.forEach((component: DateComponentKey) => { + const componentInfo = dateUtils.DATE_COMPONENTS_INFO[component]; result[componentInfo.setter](newValue[componentInfo.getter]()); }); return result; }, - getLongestCaptionIndex(captionArray) { + getLongestCaptionIndex(captionArray: string[]): number { let longestIndex = 0; let longestCaptionLength = 0; - let i; - for (i = 0; i < captionArray.length; ++i) { + + for (let i = 0; i < captionArray.length; i += 1) { if (captionArray[i].length > longestCaptionLength) { longestIndex = i; longestCaptionLength = captionArray[i].length; @@ -149,17 +157,15 @@ const dateUtils = { return longestIndex; }, - formatUsesMonthName(format) { - // @ts-expect-error + formatUsesMonthName(format: string): boolean { return dateLocalization.formatUsesMonthName(format); }, - formatUsesDayName(format) { - // @ts-expect-error + formatUsesDayName(format: string): boolean { return dateLocalization.formatUsesDayName(format); }, - getLongestDate(format, monthNames, dayNames) { + getLongestDate(format: string, monthNames: string[], dayNames: string[]): Date { const stringFormat = getStringFormat(format); let month = 9; @@ -170,93 +176,100 @@ const dateUtils = { const longestDate = new Date(1888, month, 21, 23, 59, 59, 999); if (!stringFormat || dateUtils.formatUsesDayName(stringFormat)) { - const date = longestDate.getDate() - longestDate.getDay() + dateUtils.getLongestCaptionIndex(dayNames); + const date = longestDate.getDate() + - longestDate.getDay() + dateUtils.getLongestCaptionIndex(dayNames); longestDate.setDate(date); } return longestDate; }, - normalizeTime(date) { + normalizeTime(date: Date): void { date.setSeconds(0); date.setMilliseconds(0); }, -}; -// @ts-expect-error -dateUtils.DATE_COMPONENTS_INFO = { - year: { - getter: 'getFullYear', - setter: 'setFullYear', - formatter(value, date) { - const formatDate = new Date(date.getTime()); - formatDate.setFullYear(value); - return dateLocalization.format(formatDate, 'yyyy'); + + DATE_COMPONENTS_INFO: { + year: { + getter: 'getFullYear', + setter: 'setFullYear', + formatter(value: number, date: Date) { + const formatDate = new Date(date.getTime()); + formatDate.setFullYear(value); + return dateLocalization.format(formatDate, 'yyyy'); + }, + startValue: undefined, + endValue: undefined, }, - startValue: undefined, - endValue: undefined, - }, - day: { - getter: 'getDate', - setter: 'setDate', - formatter(value, date) { - const formatDate = new Date(date.getTime()); - formatDate.setDate(value); - return dateLocalization.format(formatDate, 'd'); + day: { + getter: 'getDate', + setter: 'setDate', + formatter(value: number, date: Date) { + const formatDate = new Date(date.getTime()); + formatDate.setDate(value); + return dateLocalization.format(formatDate, 'd'); + }, + startValue: 1, + endValue: undefined, }, - startValue: 1, - endValue: undefined, - }, - month: { - getter: 'getMonth', - setter: 'setMonth', - formatter(value) { - return dateLocalization.getMonthNames()[value]; + month: { + getter: 'getMonth', + setter: 'setMonth', + formatter(value: number) { + return dateLocalization.getMonthNames()[value]; + }, + startValue: 0, + endValue: 11, }, - startValue: 0, - endValue: 11, - }, - hours: { - getter: 'getHours', - setter: 'setHours', - formatter(value) { - return dateLocalization.format(new Date(0, 0, 0, value), 'hour'); + hours: { + getter: 'getHours', + setter: 'setHours', + formatter(value: number) { + return dateLocalization.format(new Date(0, 0, 0, value), 'hour'); + }, + startValue: 0, + endValue: 23, }, - startValue: 0, - endValue: 23, - }, - minutes: { - getter: 'getMinutes', - setter: 'setMinutes', - formatter(value) { - return dateLocalization.format(new Date(0, 0, 0, 0, value), 'minute'); + minutes: { + getter: 'getMinutes', + setter: 'setMinutes', + formatter(value: number) { + return dateLocalization.format(new Date(0, 0, 0, 0, value), 'minute'); + }, + startValue: 0, + endValue: 59, }, - startValue: 0, - endValue: 59, - }, - seconds: { - getter: 'getSeconds', - setter: 'setSeconds', - formatter(value) { - return dateLocalization.format(new Date(0, 0, 0, 0, 0, value), 'second'); + seconds: { + getter: 'getSeconds', + setter: 'setSeconds', + formatter(value: number) { + return dateLocalization.format(new Date(0, 0, 0, 0, 0, value), 'second'); + }, + startValue: 0, + endValue: 59, }, - startValue: 0, - endValue: 59, - }, - milliseconds: { - getter: 'getMilliseconds', - setter: 'setMilliseconds', - formatter(value) { - return dateLocalization.format(new Date(0, 0, 0, 0, 0, 0, value), 'millisecond'); + milliseconds: { + getter: 'getMilliseconds', + setter: 'setMilliseconds', + formatter(value: number) { + return dateLocalization.format(new Date(0, 0, 0, 0, 0, 0, value), 'millisecond'); + }, + startValue: 0, + endValue: 999, }, - startValue: 0, - endValue: 999, - }, + } as Record string; + startValue: number | undefined; + endValue: number | undefined; + }>, }; export default dateUtils; diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts index a901b6a9b076..c23e68c64f04 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_view_roller.ts @@ -1,3 +1,4 @@ +/* eslint-disable class-methods-use-this */ import { fx } from '@js/common/core/animation'; import { resetPosition } from '@js/common/core/animation/translator'; import { name as clickEventName } from '@js/common/core/events/click'; @@ -7,13 +8,14 @@ import registerComponent from '@js/core/component_registrator'; import devices from '@js/core/devices'; import type { dxElementWrapper } from '@js/core/renderer'; import $ from '@js/core/renderer'; -import { each } from '@js/core/utils/iterator'; import { getHeight } from '@js/core/utils/size'; +import type { ScrollEventInfo } from '@js/ui/scroll_view/ui.scrollable'; import type { OptionChanged } from '@ts/core/widget/types'; import { convertToLocation } from '@ts/ui/scroll_view/utils/convert_location'; import type { ScrollableProperties } from '../scroll_view/scrollable'; import Scrollable from '../scroll_view/scrollable'; +import type { DxMouseEvent } from '../scroll_view/types'; const DATEVIEW_ROLLER_CLASS = 'dx-dateviewroller'; const DATEVIEW_ROLLER_ACTIVE_CLASS = 'dx-state-active'; @@ -27,14 +29,23 @@ const DATEVIEW_ROLLER_ITEM_SELECTED_BORDER_CLASS = 'dx-dateview-item-selected-bo export interface DateViewRollerProperties extends ScrollableProperties { selectedIndex?: number; - items?: any[]; + items?: string[]; showOnClick?: boolean; - onClick?: () => void; + onClick?: ((e: { event: DxMouseEvent; component: DateViewRoller }) => void) | null; + + onStart?: ((e: ScrollEventInfo) => void) | null; + + onEnd?: ((e: ScrollEventInfo) => void) | null; + + onSelectedIndexChanged?: (( + e: { component: DateViewRoller; previousValue: number; value: number } + ) => void) | null; } -class DateViewRoller extends Scrollable { +class DateViewRoller extends Scrollable { + // eslint-disable-next-line no-restricted-globals _visibilityTimer?: ReturnType; _selectedIndexChanged?: (e?: Record) => void; @@ -54,7 +65,6 @@ class DateViewRoller extends Scrollable { bounceEnabled: false, items: [], showOnClick: false, - // @ts-expect-error ts-error onClick: null, onSelectedIndexChanged: null, scrollByContent: true, @@ -77,7 +87,6 @@ class DateViewRoller extends Scrollable { this._renderContainerClick(); this._renderItems(); - // @ts-expect-error ts-error this._renderSelectedValue(); this._renderItemsClick(); this._renderWheelEvent(); @@ -86,13 +95,11 @@ class DateViewRoller extends Scrollable { } _renderSelectedIndexChanged(): void { - // @ts-expect-error ts-error this._selectedIndexChanged = this._createActionByOption('onSelectedIndexChanged'); } _renderWheelEvent(): void { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - eventsEngine.on($(this.container()), 'dxmousewheel', (e) => { + eventsEngine.on($(this.container()), 'dxmousewheel', () => { this._isWheelScrolled = true; }); } @@ -103,7 +110,6 @@ class DateViewRoller extends Scrollable { } // @ts-expect-error ts-error const eventName = addNamespace(clickEventName, this.NAME); - // @ts-expect-error ts-error const clickAction = this._createActionByOption('onClick'); eventsEngine.off($(this.container()), eventName); @@ -112,16 +118,14 @@ class DateViewRoller extends Scrollable { }); } - _renderItems() { - const items = this.option('items') || []; + _renderItems(): void { + const { items = [] } = this.option(); let $items = $(); $(this.content()).empty(); // NOTE: rendering ~166+30+12+24+60
s >> 50mc - // @ts-expect-error ts-error items.forEach((item) => { $items = $items.add( - // @ts-expect-error $('
') .addClass(DATEVIEW_ROLLER_ITEM_CLASS) .append(item), @@ -133,23 +137,23 @@ class DateViewRoller extends Scrollable { this.update(); } - _renderSelectedItemFrame() { + _renderSelectedItemFrame(): void { $('
') .addClass(DATEVIEW_ROLLER_ITEM_SELECTED_FRAME_CLASS) .append($('
').addClass(DATEVIEW_ROLLER_ITEM_SELECTED_BORDER_CLASS)) .appendTo($(this.container())); } - _renderSelectedValue(selectedIndex) { - const index = this._fitIndex(selectedIndex ?? this.option('selectedIndex')); + _renderSelectedValue(selectedIndex?: number): void { + const { selectedIndex: oldSelectedIndex = 0 } = this.option(); + const index = this._fitIndex(selectedIndex ?? oldSelectedIndex); this._moveTo({ top: this._getItemPosition(index) }); this._renderActiveStateItem(); } - _fitIndex(index) { - const items = this.option('items') || []; - // @ts-expect-error ts-error + _fitIndex(index: number): number { + const { items = [] } = this.option(); const itemCount = items.length; if (index >= itemCount) { @@ -163,7 +167,7 @@ class DateViewRoller extends Scrollable { return index; } - _getItemPosition(index): number { + _getItemPosition(index: number): number { return Math.round(this._itemHeight() * index); } @@ -180,39 +184,38 @@ class DateViewRoller extends Scrollable { return `.${DATEVIEW_ROLLER_ITEM_CLASS}`; } - _itemClickHandler(e): void { + _itemClickHandler(e: { currentTarget: dxElementWrapper }): void { this.option('selectedIndex', this._itemElementIndex(e.currentTarget)); } - _itemElementIndex(itemElement) { + _itemElementIndex(itemElement: dxElementWrapper): number { return this._itemElements().index(itemElement); } - _itemElements() { + _itemElements(): dxElementWrapper { return this.$element().find(this._getItemSelector()); } - _renderActiveStateItem() { - const selectedIndex = this.option('selectedIndex'); - each(this._$items, function (index) { - $(this).toggleClass(DATEVIEW_ROLLER_ITEM_SELECTED_CLASS, selectedIndex === index); + _renderActiveStateItem(): void { + const { selectedIndex } = this.option(); + + this._$items.each((index, element) => { + $(element).toggleClass(DATEVIEW_ROLLER_ITEM_SELECTED_CLASS, selectedIndex === index); + return true; }); } - _shouldScrollToNeighborItem() { - return devices.real().deviceType === 'desktop' - && this._isWheelScrolled; + _shouldScrollToNeighborItem(): boolean { + return Boolean(devices.real().deviceType === 'desktop' && this._isWheelScrolled); } - _moveTo(targetLocation): void { - // @ts-expect-error - const { top, left } = convertToLocation(targetLocation); + _moveTo(targetLocation: { top: number; }): void { + // @ts-expect-error scrollable types should be extended + const { top = 0, left = 0 } = convertToLocation(targetLocation); const location = this.scrollOffset(); const delta = { - // @ts-expect-error x: location.left - left, - // @ts-expect-error y: location.top - top, }; @@ -220,45 +223,42 @@ class DateViewRoller extends Scrollable { this._prepareDirections(true); if (this._animation && !this._shouldScrollToNeighborItem()) { - const that = this; - - // @ts-expect-error - fx.stop($(this.content())); - // @ts-expect-error - fx.animate($(this.content()), { + fx.stop($(this.content()).get(0), false); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + fx.animate($(this.content()).get(0), { duration: 200, type: 'slide', to: { top: Math.floor(delta.y) }, - complete() { - resetPosition($(that.content())); - // @ts-expect-error - that.handleMove({ delta }); + complete: () => { + resetPosition($(this.content())); + // @ts-expect-error scrollable types should be extended + this.handleMove({ delta }); }, }); delete this._animation; } else { - // @ts-expect-error + // @ts-expect-error scrollable types should be extended this.handleMove({ delta }); } } } - _validate(e) { + _validate(e: DxMouseEvent): boolean { return this._moveIsAllowed(e); } - _fitSelectedIndexInRange(index) { - // @ts-expect-error ts-error - const itemsCount = this.option('items').length; + _fitSelectedIndexInRange(index: number): number { + const { items = [] } = this.option(); + const itemsCount = items.length; return Math.max(Math.min(index, itemsCount - 1), 0); } - _isInNullNeighborhood(x) { + _isInNullNeighborhood(x: number): boolean { const EPS = 0.1; return -EPS <= x && x <= EPS; } - _getSelectedIndexAfterScroll(currentSelectedIndex): number { + _getSelectedIndexAfterScroll(currentSelectedIndex: number): number { const locationTop = this.scrollOffset().top; const currentSelectedIndexPosition = currentSelectedIndex * this._itemHeight(); @@ -274,7 +274,7 @@ class DateViewRoller extends Scrollable { return newSelectedIndex; } - _getNewSelectedIndex(currentSelectedIndex): number { + _getNewSelectedIndex(currentSelectedIndex: number): number { if (this._shouldScrollToNeighborItem()) { return this._getSelectedIndexAfterScroll(currentSelectedIndex); } @@ -285,7 +285,7 @@ class DateViewRoller extends Scrollable { } _endActionHandler(): void { - const currentSelectedIndex = this.option('selectedIndex'); + const { selectedIndex: currentSelectedIndex = 0 } = this.option(); const newSelectedIndex = this._getNewSelectedIndex(currentSelectedIndex); if (newSelectedIndex === currentSelectedIndex) { @@ -300,7 +300,7 @@ class DateViewRoller extends Scrollable { _itemHeight(): number { const $item = this._$items.first(); - return getHeight($item); + return getHeight($item) as number; } _toggleActive(state: boolean): void { @@ -311,7 +311,7 @@ class DateViewRoller extends Scrollable { return $(this.container()).is(':visible'); } - _fireSelectedIndexChanged(value, previousValue): void { + _fireSelectedIndexChanged(value?: number, previousValue?: number): void { this._selectedIndexChanged?.({ value, previousValue, @@ -319,16 +319,18 @@ class DateViewRoller extends Scrollable { }); } - _visibilityChanged(visible): void { + _visibilityChanged(visible: boolean): void { super._visibilityChanged(visible); this._visibilityChangedHandler(visible); } - _visibilityChangedHandler(visible): void { + _visibilityChangedHandler(visible: boolean): void { if (visible) { // uses for purposes of renovated scrollable widget + // eslint-disable-next-line no-restricted-globals this._visibilityTimer = setTimeout(() => { - this._renderSelectedValue(this.option('selectedIndex')); + const { selectedIndex } = this.option(); + this._renderSelectedValue(selectedIndex); }); } this.toggleActiveState(false); @@ -339,7 +341,7 @@ class DateViewRoller extends Scrollable { } _refreshSelectedIndex(): void { - const selectedIndex = this.option('selectedIndex'); + const { selectedIndex = 0 } = this.option(); const fitIndex = this._fitIndex(selectedIndex); if (fitIndex === selectedIndex) { @@ -363,7 +365,6 @@ class DateViewRoller extends Scrollable { case 'showOnClick': this._renderContainerClick(); break; - // @ts-expect-error ts-error case 'onSelectedIndexChanged': this._renderSelectedIndexChanged(); break; diff --git a/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts b/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts index 179a411b42c1..70a417c14323 100644 --- a/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts +++ b/packages/devextreme/js/__internal/ui/date_range_box/strategy/m_rangeCalendar.ts @@ -66,11 +66,11 @@ class RangeCalendarStrategy extends CalendarStrategy { enter: (e) => { if (dateRangeBox.option('opened')) { // @ts-expect-error - const dateBoxValue = this.dateBox.dateOption('value'); + const dateBoxValue = this.dateBox.getDateOption('value'); // @ts-expect-error this.dateBox._valueChangeEventHandler(e); // @ts-expect-error - const newDateBoxValue = this.dateBox.dateOption('value'); + const newDateBoxValue = this.dateBox.getDateOption('value'); const dateBoxValueChanged = !isSameDates(dateBoxValue, newDateBoxValue); if (dateBoxValueChanged) { @@ -253,10 +253,10 @@ class RangeCalendarStrategy extends CalendarStrategy { if (arguments.length) { // @ts-expect-error - return dateBox.dateValue.apply(dateBox, arguments); + return dateBox.setDateOption.apply(dateBox, arguments); } // @ts-expect-error - return dateBox.dateOption.apply(dateBox, ['value']); + return dateBox.getDateOption.apply(dateBox, ['value']); } _cellClickHandler(): void { } diff --git a/packages/devextreme/js/__internal/ui/diagram/ui.diagram.menu_helper.ts b/packages/devextreme/js/__internal/ui/diagram/ui.diagram.menu_helper.ts index 2b771f027188..b54e0035f107 100644 --- a/packages/devextreme/js/__internal/ui/diagram/ui.diagram.menu_helper.ts +++ b/packages/devextreme/js/__internal/ui/diagram/ui.diagram.menu_helper.ts @@ -16,8 +16,7 @@ const DiagramMenuHelper = { $itemElement.append($iconElement); } } else if ( - contextMenu._menuHasCheckedItems - && contextMenu._menuHasCheckedItems[itemKey] === true + contextMenu._menuHasCheckedItems?.[itemKey] === true ) { const $checkElement = getImageContainer('check'); if ($checkElement) { @@ -26,12 +25,10 @@ const DiagramMenuHelper = { } } $itemElement.append( - // @ts-expect-error ts-error `${itemData.text}`, ); if (Array.isArray(itemData.items) && itemData.items.length > 0) { $itemElement.append( - // @ts-expect-error ts-error '
', ); } diff --git a/packages/devextreme/js/__internal/ui/menu/menu.ts b/packages/devextreme/js/__internal/ui/menu/menu.ts index af2c7df19163..3ea2e78dc175 100644 --- a/packages/devextreme/js/__internal/ui/menu/menu.ts +++ b/packages/devextreme/js/__internal/ui/menu/menu.ts @@ -194,7 +194,6 @@ class Menu extends MenuBase { const rootMenuElements = super._itemElements(); const submenuElements = this._submenuItemElements(); - // @ts-expect-error ts-error return rootMenuElements.add(submenuElements); } diff --git a/packages/devextreme/js/__internal/ui/scroll_view/scrollable.ts b/packages/devextreme/js/__internal/ui/scroll_view/scrollable.ts index bd13318e3c5d..4b4531303c1f 100644 --- a/packages/devextreme/js/__internal/ui/scroll_view/scrollable.ts +++ b/packages/devextreme/js/__internal/ui/scroll_view/scrollable.ts @@ -58,9 +58,9 @@ export interface ScrollableProperties extends DOMComponentProperties, Omit< useKeyboard?: boolean; updateManually?: boolean; inertiaEnabled?: boolean; - onStart?: (() => void) | null; - onEnd?: (() => void) | null; - onBounce?: (() => void) | null; + onStart?: ((e) => void) | null; + onEnd?: ((e) => void) | null; + onBounce?: ((e) => void) | null; } class Scrollable< diff --git a/packages/devextreme/js/common/core/localization/date.d.ts b/packages/devextreme/js/common/core/localization/date.d.ts index 8668641dfbc3..ae932a6ef308 100644 --- a/packages/devextreme/js/common/core/localization/date.d.ts +++ b/packages/devextreme/js/common/core/localization/date.d.ts @@ -1,12 +1,16 @@ +import { DateLike } from '../../../common'; import { Format as LocalizationFormat } from '../localization'; type Format = 'abbreviated' | 'short' | 'narrow'; interface DateLocalization { firstDayOfWeekIndex(): number; - format(date?: Date, format?: LocalizationFormat): string | Date | undefined; + format(date?: DateLike, format?: LocalizationFormat): string | Date | undefined; + formatUsesDayName(format: string): boolean; + formatUsesMonthName(format: string): boolean; getDayNames(format?: Format): string[]; getMonthNames(format?: Format): string[]; + parse(text: string, format?: Format | string): Date | null | undefined } declare const dateLocalization: DateLocalization; export default dateLocalization; diff --git a/packages/devextreme/js/core/renderer.d.ts b/packages/devextreme/js/core/renderer.d.ts index a0aa24a04cdb..4e7e938930c1 100644 --- a/packages/devextreme/js/core/renderer.d.ts +++ b/packages/devextreme/js/core/renderer.d.ts @@ -5,13 +5,13 @@ export interface Coordinates { export interface dxElementWrapper { - add(selector: string): this; + add(selector: string | dxElementWrapper): this; addClass(className: string): this; after(element: Element | dxElementWrapper): this; - append(element: Element | dxElementWrapper): this; + append(element: Element | dxElementWrapper | string): this; appendTo(element: Element | dxElementWrapper): this; diff --git a/packages/devextreme/ts/dx.all.d.ts b/packages/devextreme/ts/dx.all.d.ts index 3eeb5dac2c5b..e97662540532 100644 --- a/packages/devextreme/ts/dx.all.d.ts +++ b/packages/devextreme/ts/dx.all.d.ts @@ -6988,13 +6988,13 @@ declare module DevExpress.core { * @deprecated Attention! This type is for internal purposes only. If you used it previously, please submit a ticket to our {@link https://supportcenter.devexpress.com/ticket/create Support Center}. We will check if there is an alternative solution. */ export interface dxElementWrapper { - add(selector: string): this; + add(selector: string | dxElementWrapper): this; addClass(className: string): this; after(element: Element | dxElementWrapper): this; - append(element: Element | dxElementWrapper): this; + append(element: Element | dxElementWrapper | string): this; appendTo(element: Element | dxElementWrapper): this;