diff --git a/apps/demos/package.json b/apps/demos/package.json index fc9e420e79f7..595ecc700c86 100644 --- a/apps/demos/package.json +++ b/apps/demos/package.json @@ -120,9 +120,10 @@ "eslint-plugin-import": "catalog:eslint8", "eslint-plugin-no-only-tests": "catalog:eslint8", "eslint-plugin-react": "7.33.2", - "eslint-plugin-react-perf": "3.3.2", + "eslint-plugin-react-perf": "3.3.3", + "eslint-plugin-vue": "catalog:", "express": "4.21.2", - "glob": "10.4.5", + "glob": "11.1.0", "gulp": "4.0.2", "gulp-clean": "0.4.0", "gulp-minify": "3.1.0", @@ -147,6 +148,7 @@ "testcafe-reporter-spec-time": "4.0.0", "ts-node": "10.9.2", "@types/file-saver-es": "^2.0.3", + "vue-eslint-parser": "catalog:", "vue-tsc": "^3.0.6" }, "scripts": { diff --git a/apps/react/package.json b/apps/react/package.json index f00b00c30a2d..471746833ba1 100644 --- a/apps/react/package.json +++ b/apps/react/package.json @@ -22,7 +22,7 @@ "style-loader": "3.3.4", "ts-loader": "9.5.1", "tsconfig-paths-webpack-plugin": "4.1.0", - "webpack": "5.94.0", + "webpack": "5.105.4", "webpack-cli": "5.1.4", "webpack-dev-server": "5.2.1" }, diff --git a/apps/vue/package.json b/apps/vue/package.json index c07665df8651..08bc9f566a8c 100644 --- a/apps/vue/package.json +++ b/apps/vue/package.json @@ -28,7 +28,7 @@ "url-loader": "1.1.2", "vue-loader": "17.4.2", "vue-router": "4.2.5", - "webpack": "5.94.0", + "webpack": "5.105.4", "webpack-cli": "5.1.4", "webpack-dev-server": "5.2.1" }, diff --git a/e2e/bundlers/package.json b/e2e/bundlers/package.json index 333d2dc6fa45..cc2a67421b77 100644 --- a/e2e/bundlers/package.json +++ b/e2e/bundlers/package.json @@ -12,11 +12,12 @@ "cldrjs": "0.5.5", "jquery": "3.7.1", "minimist": "1.2.8", + "@parcel/watcher-linux-x64-glibc": "2.5.0", "parcel": "2.16.1", "rimraf": "3.0.2", "rollup": "4.22.4", "vite": "5.4.19", - "webpack": "5.94.0", + "webpack": "5.105.4", "webpack-cli": "4.10.0", "devextreme": "workspace:*" }, diff --git a/e2e/testcafe-devextreme/docker/run-testcafe.js b/e2e/testcafe-devextreme/docker/run-testcafe.js index bd2a069ec68d..a7d9bca09658 100644 --- a/e2e/testcafe-devextreme/docker/run-testcafe.js +++ b/e2e/testcafe-devextreme/docker/run-testcafe.js @@ -1,3 +1,5 @@ +/* eslint-disable keyword-spacing */ + const { spawnSync } = require('child_process'); const parseArgs = require('minimist'); @@ -26,24 +28,24 @@ const matrix = [ { componentFolder: 'renovation', name: 'renovation (jquery)', platform: 'jquery' }, { componentFolder: 'renovation', name: 'renovation (react)', platform: 'react' }, ]; - (async() => { + // eslint-disable-next-line no-undef const parsedArgs = parseArgs(process.argv); const componentFolderName = parsedArgs.componentFolder; let testParts = matrix; - if(componentFolderName != null) { + if (componentFolderName != null) { testParts = testParts.filter(({ componentFolder }) => componentFolder === componentFolderName); } - if(testParts.length === 0) { + if (testParts.length === 0) { const variants = [...new Set(matrix.map(({ componentFolder }) => componentFolder))]; throw new Error(`componentFolder "${componentFolderName}" was not found. Use one of next variants: ${variants}`); } // eslint-disable-next-line no-restricted-syntax - for(const { name, ...args } of testParts) { + for (const { name, ...args } of testParts) { // eslint-disable-next-line no-console,no-undef console.log(`Started test: ${name}`); diff --git a/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts b/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts index 5e7a3aafb335..ac06246e2b44 100644 --- a/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts +++ b/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts @@ -1,14 +1,13 @@ import { ClientFunction } from 'testcafe'; -type WindowCallbackExtended = - Window - & typeof globalThis - & { - clientTesting?: { - data: Record; - addCallbackResult: (key: string, result: T) => void; - }; +type WindowCallbackExtended = Window +& typeof globalThis +& { + clientTesting?: { + data: Record; + addCallbackResult: (key: string, result: T) => void; }; +}; const initClientTesting = async (keyArray: string[]): Promise => { await ClientFunction( diff --git a/e2e/testcafe-devextreme/helpers/createWidget.ts b/e2e/testcafe-devextreme/helpers/createWidget.ts index 491ccfaeddc7..c078a8d0199f 100644 --- a/e2e/testcafe-devextreme/helpers/createWidget.ts +++ b/e2e/testcafe-devextreme/helpers/createWidget.ts @@ -32,9 +32,9 @@ export const createWidget = async( widgetName: TWidgetName, widgetOptions: TWidgetName extends keyof WidgetOptions ? ( - WidgetOptions[TWidgetName] | + WidgetOptions[TWidgetName] // NOTE: Promise is only for ClientFunction typing - (() => (WidgetOptions[TWidgetName]) | Promise) + | (() => (WidgetOptions[TWidgetName]) | Promise) ) : unknown, selector = DEFAULT_SELECTOR, { disableFxAnimation } = DEFAULT_OPTIONS, diff --git a/e2e/testcafe-devextreme/helpers/widgetTypings.ts b/e2e/testcafe-devextreme/helpers/widgetTypings.ts index 01ee9cacedda..360e9773a78a 100644 --- a/e2e/testcafe-devextreme/helpers/widgetTypings.ts +++ b/e2e/testcafe-devextreme/helpers/widgetTypings.ts @@ -1,61 +1,60 @@ import type { Properties as DataGridProperties } from 'devextreme/ui/data_grid'; import type { Properties as FilterBuilderProperties } from 'devextreme/ui/filter_builder'; -export type WidgetName = - 'dxAccordion' - | 'dxAutocomplete' - | 'dxGallery' - | 'dxButtonGroup' - | 'dxCalendar' - | 'dxCalendarView' - | 'dxCheckBox' - | 'dxColorBox' - | 'dxDropDownButton' - | 'dxDraggable' - | 'dxTabPanel' - | 'dxForm' - | 'dxFilterBuilder' - | 'dxSelectBox' - | 'dxScrollable' - | 'dxScrollView' - | 'dxMultiView' - | 'dxPivotGrid' - | 'dxPivotGridFieldChooser' - | 'dxDataGrid' - | 'dxTreeList' - | 'dxPagination' - | 'dxRadioGroup' - | 'dxScheduler' - | 'dxTabs' - | 'dxTagBox' - | 'dxContextMenu' - | 'dxDropDownMenu' - | 'dxChart' - | 'dxMenu' - | 'dxPopup' - | 'dxPopover' - | 'dxSpeedDialAction' - | 'dxSortable' - | 'dxSplitter' - | 'dxButton' - | 'dxTextBox' - | 'dxTextArea' - | 'dxToolbar' - | 'dxTileView' - | 'dxTreeView' - | 'dxDateBox' - | 'dxDateRangeBox' - | 'dxLookup' - | 'dxOverlay' - | 'dxList' - | 'dxHtmlEditor' - | 'dxNumberBox' - | 'dxValidator' - | 'dxFileUploader' - | 'dxSlider' - | 'dxDropDownBox' - | 'dxFileManager' - | 'dxSwitch'; +export type WidgetName = 'dxAccordion' +| 'dxAutocomplete' +| 'dxGallery' +| 'dxButtonGroup' +| 'dxCalendar' +| 'dxCalendarView' +| 'dxCheckBox' +| 'dxColorBox' +| 'dxDropDownButton' +| 'dxDraggable' +| 'dxTabPanel' +| 'dxForm' +| 'dxFilterBuilder' +| 'dxSelectBox' +| 'dxScrollable' +| 'dxScrollView' +| 'dxMultiView' +| 'dxPivotGrid' +| 'dxPivotGridFieldChooser' +| 'dxDataGrid' +| 'dxTreeList' +| 'dxPagination' +| 'dxRadioGroup' +| 'dxScheduler' +| 'dxTabs' +| 'dxTagBox' +| 'dxContextMenu' +| 'dxDropDownMenu' +| 'dxChart' +| 'dxMenu' +| 'dxPopup' +| 'dxPopover' +| 'dxSpeedDialAction' +| 'dxSortable' +| 'dxSplitter' +| 'dxButton' +| 'dxTextBox' +| 'dxTextArea' +| 'dxToolbar' +| 'dxTileView' +| 'dxTreeView' +| 'dxDateBox' +| 'dxDateRangeBox' +| 'dxLookup' +| 'dxOverlay' +| 'dxList' +| 'dxHtmlEditor' +| 'dxNumberBox' +| 'dxValidator' +| 'dxFileUploader' +| 'dxSlider' +| 'dxDropDownBox' +| 'dxFileManager' +| 'dxSwitch'; export interface WidgetOptions { dxDataGrid: DataGridProperties; diff --git a/e2e/testcafe-devextreme/package.json b/e2e/testcafe-devextreme/package.json index 1d2b5556129d..f0ff0de6e11f 100644 --- a/e2e/testcafe-devextreme/package.json +++ b/e2e/testcafe-devextreme/package.json @@ -11,8 +11,9 @@ "@babel/plugin-transform-runtime": "7.19.6", "@testcafe-community/axe": "3.5.0", "@types/jquery": "3.5.29", - "@typescript-eslint/eslint-plugin": "catalog:eslint8", + "@typescript-eslint/eslint-plugin": "catalog:eslint8", "@typescript-eslint/parser": "catalog:eslint8", + "eslint-config-devextreme": "1.1.6", "axe-core": "catalog:", "devextreme": "workspace:*", "devextreme-screenshot-comparer": "2.0.17", @@ -23,7 +24,7 @@ "eslint-plugin-import": "catalog:eslint8", "eslint-plugin-no-only-tests": "catalog:eslint8", "eslint-plugin-qunit": "catalog:eslint8", - "glob": "10.4.5", + "glob": "11.1.0", "minimist": "1.2.8", "mockdate": "3.0.5", "nconf": "0.12.1", diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/focus/focusEvents/newRows_T1162227.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/focus/focusEvents/newRows_T1162227.ts index 620218dfcab8..98ec140b822a 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/focus/focusEvents/newRows_T1162227.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/focus/focusEvents/newRows_T1162227.ts @@ -9,8 +9,10 @@ import { CallbackTestHelper, WindowCallbackExtended } from '../../../../../helpe fixture`Focused row - new rows T1162227` .page(url(__dirname, '../../../../container.html')); -type FocusCellChangingData = - [[prevRowIdx: number, prevColumnIdx: number], [rowIdx: number, columnIdx: number]]; +type FocusCellChangingData = [ + [prevRowIdx: number, prevColumnIdx: number], + [rowIdx: number, columnIdx: number], +]; type FocusCellChangedData = [rowIdx: number, columnIdx: number]; type FocusRowChangingData = [prevRowIdx: number, rowIdx: number]; type FocusRowChangedData = [rowIdx: number]; diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/keyboardNavigation/keyboardNavigation.functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/keyboardNavigation/keyboardNavigation.functional.ts index b40343483443..0e6a2d109e77 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/keyboardNavigation/keyboardNavigation.functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/keyboardNavigation/keyboardNavigation.functional.ts @@ -106,7 +106,7 @@ test('Changing keyboardNavigation options should not invalidate the entire conte allowUpdating: true, }, onFocusedRowChanging(e) { - if ((e.newRowIndex + 1) % 2 === 0) { + if ((Number(e.newRowIndex) + 1) % 2 === 0) { e.component.option('keyboardNavigation.enterKeyAction', 'moveFocus'); } else { e.component.option('keyboardNavigation.enterKeyAction', 'startEdit'); diff --git a/e2e/testcafe-devextreme/tests/editors/overlays/popup.ts b/e2e/testcafe-devextreme/tests/editors/overlays/popup.ts index 0c8cb01fdd2f..4c9f6204aa16 100644 --- a/e2e/testcafe-devextreme/tests/editors/overlays/popup.ts +++ b/e2e/testcafe-devextreme/tests/editors/overlays/popup.ts @@ -113,8 +113,7 @@ test('Popup should be centered regarding the window after position.boundary is s const initialRect: { bottom: number; top: number; left: number; - right: number; - } = { + right: number; } = { bottom: 0, top: 0, left: 0, diff --git a/e2e/testcafe-devextreme/update_failed_etalons.mjs b/e2e/testcafe-devextreme/update_failed_etalons.mjs index e173c3517c6f..5c9b4b12153e 100644 --- a/e2e/testcafe-devextreme/update_failed_etalons.mjs +++ b/e2e/testcafe-devextreme/update_failed_etalons.mjs @@ -37,10 +37,10 @@ function processEtalonFolder(etalonFolderPath, allEtalons) { const hasFile = allEtalons.has(currentFileName); if (hasFile) { - const dstFileName = join(etalonFolderPath, currentFileName); + const destFileName = join(etalonFolderPath, currentFileName); const srcFileName = join(PATH_TO_CURRENT_ETALONS, currentFileName); - copyFileSync(srcFileName, dstFileName); + copyFileSync(srcFileName, destFileName); allEtalons.delete(currentFileName); if (allEtalons.size === 0) { @@ -53,9 +53,9 @@ function processEtalonFolder(etalonFolderPath, allEtalons) { } function processFolder(currentDir, allEtalons) { - const currentDirrectoryFolders = getAllDirs(currentDir); + const currentDirectoryFolders = getAllDirs(currentDir); - for (let dir of currentDirrectoryFolders) { + for (let dir of currentDirectoryFolders) { const folderName = basename(dir); const continueProcessFolders = folderName === ETALONS_FOLDER_NAME ? processEtalonFolder(dir, allEtalons) diff --git a/package.json b/package.json index bc6cdfc38bfb..ac333ce25a07 100644 --- a/package.json +++ b/package.json @@ -66,18 +66,65 @@ ], "pnpm": { "overrides": { - "@devexpress/callsite-record@^4.1.6": "4.1.6", + "@parcel/watcher": "2.5.0", + "@angular/common@>=19.0.0 <19.2.16": "^19.2.20", + "@angular/compiler@>=19.0.0-next.0 <19.2.20": "^19.2.20", + "@angular/core@>=19.0.0-next.0 <19.2.20": "^19.2.20", + "@angular/platform-server@>=19.0.0-next.0 <19.2.20": "^19.2.20", + "@devexpress/callsite-record@^4.1.6": "4.1.7", + "@hono/node-server@<1.19.10": "^1.19.10", + "@isaacs/brace-expansion@<=5.0.0": "^5.0.1", + "@modelcontextprotocol/sdk@>=1.10.0 <=1.25.3": "^1.26.0", + "@tootallnate/once@<3.0.1": "^3.0.1", + "ajv@>=7.0.0-alpha.0 <8.18.0": "^8.18.0", + "axios@<=1.13.4": "^1.13.5", + "basic-ftp@<5.2.1": "~5.2.1", + "bn.js@<4.12.3": "4.12.3", + "bn.js@>=5.0.0 <5.2.3": "5.2.3", + "brace-expansion@<1.1.13": "1.1.13", + "brace-expansion@>=2.0.0 <2.0.3": "2.0.3", + "braces@<3.0.3": "^3.0.3", + "cookie@<0.7.0": "^0.7.0", + "diff@>=4.0.0 <4.0.4": "4.0.4", + "diff@>=5.0.0 <5.2.2": "5.2.2", + "dompurify@<=3.3.1": "^3.3.2", + "express-rate-limit@>=8.2.0 <8.2.2": "^8.2.2", + "flatted@<3.4.0": "^3.4.0", "form-data@<2.5.4": "2.5.5", "form-data@>=4.0.0 <4.0.4": "^4.0.5", + "glob@>=10.2.0 <10.5.0": "^10.5.0", + "hono@<4.12.4": "^4.12.4", + "immutable@>=4.0.0-rc.1 <4.3.8": "^4.3.8", + "immutable@>=5.0.0 <5.1.5": "^5.1.5", + "json5@<1.0.2": "^2.2.3", + "lodash.template@<4.18.1": "4.18.1", + "lodash@<4.18.1": "4.18.1", + "micromatch@<4.0.8": "^4.0.8", + "minimatch@<3.1.5": "3.1.5", + "minimatch@>=10.0.0 < 10.2.4": "10.2.4", + "minimatch@>=5.0.0 <5.1.8": "5.1.8", + "minimatch@>=9.0.0 < 9.0.7": "9.0.9", + "node-forge@<1.4.0": "1.4.0", + "path-to-regexp@0.1.12": "0.1.13", + "path-to-regexp@>=8.0.0 <8.4.0": "8.4.0", "pbkdf2@<=3.1.2": "^3.1.3", - "sha.js@<=2.4.11": "^2.4.12", + "picomatch@>=2.0.0 <2.3.2": "2.3.2", + "picomatch@>=4.0.0 <4.0.4": "4.0.4", + "qs": ">=6.14.1", + "rollup@< 4.59.0": "^4.59.0", "rollup@<2.79.2": "^4.53.3", - "json5@<1.0.2": "^2.2.3", - "axios@<1.8.2": "^1.13.2", - "braces@<3.0.3": "^3.0.3", "semver@<5.7.2": "^5.7.2", - "glob@>=10.2.0 <10.5.0": "^10.5.0", - "node-forge@<1.3.2": "^1.3.2" + "serialize-javascript@<=7.0.2": "7.0.5", + "sha.js@<=2.4.11": "^2.4.12", + "socket.io-parser@>=4.0.0 <4.2.6": "^4.2.6", + "tar@<=7.5.9": "^7.5.10", + "tmp@<=0.2.3": "^0.2.4", + "tough-cookie@<4.1.3": "^4.1.3", + "underscore@<=1.13.7": "^1.13.8", + "undici@<7.24.0": "^7.24.0", + "vite@>=5.0.0 <=5.4.20": "^5.4.21", + "vite@>=6.0.0 <6.4.1": "^7.3.2", + "vite@>=7.0.0 <=7.3.1": "^7.3.2" } }, "packageManager": "pnpm@9.15.4" diff --git a/packages/devextreme-angular/eslint.config.mjs b/packages/devextreme-angular/eslint.config.mjs index 4329f24fda04..4add61bfeaef 100644 --- a/packages/devextreme-angular/eslint.config.mjs +++ b/packages/devextreme-angular/eslint.config.mjs @@ -1,18 +1,17 @@ /* eslint-disable spellcheck/spell-checker */ import path from 'node:path'; import { fileURLToPath } from 'node:url'; -import { FlatCompat } from '@eslint/eslintrc'; import babelParser from '@babel/eslint-parser'; import tsParser from '@typescript-eslint/parser'; import stylistic from '@stylistic/eslint-plugin'; import importPlugin from 'eslint-plugin-import'; import { changeRulesToStylistic } from 'eslint-migration-utils'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import javascriptConfig from 'eslint-config-devextreme/javascript'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; const filename = fileURLToPath(import.meta.url); const dirname = path.dirname(filename); -const compat = new FlatCompat({ - baseDirectory: dirname, -}); export default [ { @@ -42,15 +41,15 @@ export default [ }, }, }, - ...compat.extends('devextreme/spell-check'), - ...compat.extends('devextreme/javascript').map((config) => ({ + ...spellCheckConfig, + ...javascriptConfig.map((config) => ({ ...config, files: ['**/*.js', '**/*.mjs'], languageOptions: { parser: babelParser, }, })), - ...compat.extends('devextreme/typescript').map((config) => ({ + ...typescriptConfig.map((config) => ({ ...config, rules: config.rules ? changeRulesToStylistic(config.rules) @@ -152,6 +151,7 @@ export default [ '@typescript-eslint/no-useless-constructor': 'warn', '@typescript-eslint/no-empty-function': 'warn', '@typescript-eslint/require-await': 'warn', + 'require-await': 'warn', '@typescript-eslint/no-floating-promises': 'warn', 'import/order': 'warn', 'no-restricted-globals': 'warn', diff --git a/packages/devextreme-angular/package.json b/packages/devextreme-angular/package.json index a724413a8028..61b7f6385a19 100644 --- a/packages/devextreme-angular/package.json +++ b/packages/devextreme-angular/package.json @@ -54,7 +54,7 @@ "del": "2.2.2", "devextreme-metadata": "workspace:*", "eslint": "catalog:", - "eslint-config-devextreme": "1.1.5", + "eslint-config-devextreme": "catalog:", "eslint-plugin-import": "catalog:", "eslint-migration-utils": "workspace:*", "gulp": "4.0.2", @@ -76,7 +76,7 @@ "style-loader": "3.3.4", "tslib": "2.6.3", "typescript": "5.4.5", - "webpack": "5.96.1", + "webpack": "5.105.4", "yargs": "17.7.2", "zone.js": "0.14.10" }, diff --git a/packages/devextreme-angular/tests/src/ui/data-grid.spec.ts b/packages/devextreme-angular/tests/src/ui/data-grid.spec.ts index 3f5dad3dbfc6..36dbe4e2d35a 100644 --- a/packages/devextreme-angular/tests/src/ui/data-grid.spec.ts +++ b/packages/devextreme-angular/tests/src/ui/data-grid.spec.ts @@ -607,6 +607,6 @@ describe('DxDataGrid slow tests', () => { const memoryAfter = await (performance as any).measureUserAgentSpecificMemory(); const memoryDiff = Math.round((memoryAfter.bytes - memoryBefore.bytes) / 1024); - expect(memoryDiff).toBeLessThan(30); + expect(memoryDiff).toBeLessThan(100); }); }); diff --git a/packages/devextreme-react/eslint.config.mjs b/packages/devextreme-react/eslint.config.mjs new file mode 100644 index 000000000000..a3b083a10294 --- /dev/null +++ b/packages/devextreme-react/eslint.config.mjs @@ -0,0 +1,293 @@ +import i18N from 'eslint-plugin-i18n'; +import babelParser from '@babel/eslint-parser'; +import tsParser from '@typescript-eslint/parser'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; +import stylistic from '@stylistic/eslint-plugin'; +import importPlugin from 'eslint-plugin-import'; +import { changeRulesToStylistic } from 'eslint-migration-utils'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [ + { + ignores: [ + 'node_modules/**', + '**/__tests__/**', + ], + }, + ...spellCheckConfig.map(config => { + + const newConfig = { + ...config + } + + if (config.rules) { + newConfig.rules = { + ...changeRulesToStylistic(config.rules), + "spellcheck/spell-checker": [1, { + "skipWords": [ + "unschedule", + "subscribable", + "renderer", + "rerender", + "dx", + "descr", + "params", + "typings", + "wildcard", + "metadata", + "namespace", + "namespaces" + ] + }] + }; + } + + return newConfig + }), + { + plugins: { + i18n: i18N, + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx', '.d.ts'], + }, + }, + }, + }, + ...compat.extends('eslint:recommended', 'plugin:import/recommended').map(config => ({ + ...config, + files: ['**/*.js'] + })), + { + files: ['**/*.js'], + languageOptions: { + globals: { + setInterval: true, + setTimeout: true, + clearInterval: true, + clearTimeout: true, + require: true, + module: true, + exports: true, + }, + parser: babelParser, + parserOptions: { + requireConfigFile: false, + }, + }, + plugins: { + '@stylistic': stylistic, + }, + rules: { + 'i18n/no-russian-character': ['error', { + includeIdentifier: true, + }], + 'block-spacing': 'error', + 'comma-spacing': 'error', + 'computed-property-spacing': 'error', + 'comma-style': ['error', 'last'], + 'eqeqeq': ['error', 'allow-null'], + 'strict': 'error', + 'func-call-spacing': 'error', + 'key-spacing': 'error', + 'keyword-spacing': ['error', { + overrides: { + catch: { + after: false, + }, + + for: { + after: false, + }, + + if: { + after: false, + }, + + switch: { + after: false, + }, + + while: { + after: false, + }, + }, + }], + 'no-multiple-empty-lines': ['error', { + max: 2, + }], + 'no-multi-spaces': 'error', + 'no-trailing-spaces': 'error', + 'no-empty': ['error', { + allowEmptyCatch: true, + }], + 'no-new-func': 'error', + 'no-eval': 'error', + 'no-undef-init': 'error', + 'no-unused-vars': ['error', { + args: 'none', + caughtErrors: 'none', + ignoreRestSiblings: true, + }], + 'no-extend-native': 'error', + 'no-alert': 'error', + 'no-console': 'error', + 'no-restricted-syntax': ['error', 'ForOfStatement'], + 'no-var': 'error', + 'no-whitespace-before-property': 'error', + 'object-curly-spacing': ['error', 'always'], + 'one-var': ['error', 'never'], + 'prefer-const': 'error', + 'semi-spacing': 'error', + 'semi': 'error', + 'space-before-blocks': 'error', + 'space-before-function-paren': ['error', 'never'], + 'space-in-parens': 'error', + 'space-infix-ops': 'error', + 'space-unary-ops': 'error', + '@stylistic/space-infix-ops': 'error', + 'space-unary-ops': 'error', + 'spaced-comment': ['error', 'always', { + exceptions: ['#DEBUG', '#ENDDEBUG'], + markers: ['/'], + }], + '@stylistic/brace-style': ['error', '1tbs', { + allowSingleLine: true, + }], + 'curly': ['error', 'multi-line', 'consistent'], + 'unicode-bom': ['error', 'never'], + 'eol-last': ['error', 'always'], + '@stylistic/indent': ['error', 4, { + SwitchCase: 1, + MemberExpression: 1, + + CallExpression: { + arguments: 1, + }, + }], + 'quotes': ['error', 'single'], + 'import/named': 2, + 'import/default': 2, + 'import/no-duplicates': 2, + "import/extensions": "warn", + "max-len": ["error", { "code": 150 }], + }, + + }, + ...typescriptConfig.map(config => { + const newConfig = { + ...config, + files: ['**/*.ts?(x)'], + ignores: ['**/*.d.ts'], + } + + if (config.rules) { + newConfig.rules = changeRulesToStylistic(config.rules); + } + + return newConfig; + }), + { + files: ['**/*.ts?(x)'], + ignores: ['**/*.d.ts'], + plugins: { + '@stylistic': stylistic, + }, + languageOptions: { + parser: tsParser, + ecmaVersion: 6, + sourceType: 'module', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, + }, + rules: { + 'prefer-regex-literals': 'off', + 'i18n/no-russian-character': ['error', { + includeIdentifier: true, + }], + '@typescript-eslint/no-unused-vars': ['error', { + "ignoreRestSiblings": true, + "caughtErrors": 'none', + }], + '@typescript-eslint/switch-exhaustiveness-check': ['error', { + considerDefaultExhaustiveForUnions: true, + }], + '@typescript-eslint/no-unsafe-function-type': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-throw-literal': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + 'import/extensions': 'off', + '@typescript-eslint/prefer-nullish-coalescing': 'off', + '@typescript-eslint/prefer-optional-chain': 'warn', + '@typescript-eslint/only-throw-error': 'warn', + 'require-await': 'warn', + 'no-underscore-dangle': 'off', + 'no-param-reassign': 'off', + 'class-methods-use-this': 'off', + 'import/no-cycle': 'off', + 'no-restricted-globals': 'off', + '@typescript-eslint/no-dynamic-delete': 'off', + '@stylistic/max-len': 'off', + '@stylistic/no-extra-parens': 'off', + '@typescript-eslint/naming-convention': 'off', + }, + }, + ...typescriptConfig.map(config => { + const newConfig = { + ...config, + files: ['**/*.d.ts'], + }; + + if (config.rules) { + newConfig.rules = changeRulesToStylistic(config.rules); + } + + return newConfig; + }), + { + files: ['**/*.d.ts'], + plugins: { + '@stylistic': stylistic, + }, + languageOptions: { + parser: tsParser, + ecmaVersion: 6, + sourceType: 'module', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + ecmaFeatures: { + globalReturn: true, + jsx: true, + }, + }, + }, + rules: { + 'i18n/no-russian-character': ['error', { + includeIdentifier: true, + }], + '@typescript-eslint/no-unsafe-function-type': 'off', + '@typescript-eslint/no-wrapper-object-types': 'off', + '@typescript-eslint/no-empty-object-type': 'off', + } + }, +]; diff --git a/packages/devextreme-react/package.json b/packages/devextreme-react/package.json index 97ef9a0c5ddd..d85b125ebd70 100644 --- a/packages/devextreme-react/package.json +++ b/packages/devextreme-react/package.json @@ -68,12 +68,17 @@ "devDependencies": { "@testing-library/react": "14.3.1", "@testing-library/user-event": "14.5.2", - "@types/react": "~18.0.0", - "@types/react-dom": "~18.0.0", + "@types/react": "~18.0.38", + "@types/react-dom": "~18.0.11", "del": "3.0.0", "devextreme-metadata": "workspace:*", + "eslint": "catalog:", "eslint-config-airbnb-base": "15.0.0", - "eslint-config-devextreme": "1.1.5", + "eslint-config-airbnb-typescript": "catalog:", + "eslint-config-devextreme": "catalog:", + "eslint-plugin-import": "catalog:", + "@typescript-eslint/eslint-plugin": "catalog:", + "@typescript-eslint/parser": "catalog:", "gulp": "4.0.2", "gulp-header": "2.0.9", "gulp-shell": "0.8.0", @@ -82,12 +87,7 @@ "react": "18.0.0", "react-dom": "18.0.0", "ts-jest": "29.1.3", - "typescript": "4.9.5", - "eslint": "catalog:eslint8", - "eslint-config-airbnb-typescript": "catalog:eslint8", - "eslint-plugin-import": "catalog:eslint8", - "@typescript-eslint/eslint-plugin": "catalog:eslint8", - "@typescript-eslint/parser": "catalog:eslint8" + "typescript": "4.9.5" }, "publishConfig": { "directory": "npm", diff --git a/packages/devextreme-react/src/core/component-base.tsx b/packages/devextreme-react/src/core/component-base.tsx index 0101be60eb09..8e7c04961818 100644 --- a/packages/devextreme-react/src/core/component-base.tsx +++ b/packages/devextreme-react/src/core/component-base.tsx @@ -206,6 +206,7 @@ const ComponentBase = forwardRef( const updateFunc = useDeferUpdateForTemplates.current ? deferUpdate : requestAnimationFrame; + // eslint-disable-next-line @typescript-eslint/no-floating-promises updateFunc(() => { guardsUpdateScheduled.current = false; diff --git a/packages/devextreme-react/src/core/configuration/comparer.ts b/packages/devextreme-react/src/core/configuration/comparer.ts index 687b3bb73891..2bef5aae00d5 100644 --- a/packages/devextreme-react/src/core/configuration/comparer.ts +++ b/packages/devextreme-react/src/core/configuration/comparer.ts @@ -129,7 +129,7 @@ function compareCollections( Object.keys(current.configCollections).forEach((key) => { const currentCollection = current.configCollections[key]; const prevCollection = prev.configCollections[key] || []; - if (!currentCollection || currentCollection.length !== prevCollection.length) { + if (currentCollection?.length !== prevCollection.length) { const updatedCollection: Record[] = []; currentCollection.forEach( (item) => { diff --git a/packages/devextreme-react/src/core/configuration/config-node.ts b/packages/devextreme-react/src/core/configuration/config-node.ts index 7b986e8e88d5..4a6b40c3e83a 100644 --- a/packages/devextreme-react/src/core/configuration/config-node.ts +++ b/packages/devextreme-react/src/core/configuration/config-node.ts @@ -38,7 +38,7 @@ function buildNodeFullName(node: IConfigNode): string { let currentNode: IConfigNode | undefined = node; let fullName = ''; - while (currentNode && currentNode.name) { + while (currentNode?.name) { fullName = currentNode.name.concat( typeof currentNode.index === 'number' ? `[${currentNode.index}]` : '', fullName ? `.${fullName}` : '', diff --git a/packages/devextreme-react/src/core/configuration/react/element.ts b/packages/devextreme-react/src/core/configuration/react/element.ts index ef763c1b76b7..28d45ef8a948 100644 --- a/packages/devextreme-react/src/core/configuration/react/element.ts +++ b/packages/devextreme-react/src/core/configuration/react/element.ts @@ -35,7 +35,7 @@ function getOptionInfo( let name = elementDescriptor.OptionName; let isCollectionItem = elementDescriptor.IsCollectionItem; - const expectation = parentExpectedChildren && parentExpectedChildren[name]; + const expectation = parentExpectedChildren?.[name]; if (expectation) { isCollectionItem = expectation.isCollectionItem; if (expectation.optionName) { @@ -61,7 +61,7 @@ function getElementType( element: React.ReactNode, ): ElementType { const reactElement = element as unknown as React.ReactElement; - if (!reactElement || !reactElement.type) { + if (!reactElement?.type) { return ElementType.Unknown; } diff --git a/packages/devextreme-react/src/core/contexts.ts b/packages/devextreme-react/src/core/contexts.ts index 938063a50515..017bf5f952a0 100644 --- a/packages/devextreme-react/src/core/contexts.ts +++ b/packages/devextreme-react/src/core/contexts.ts @@ -13,7 +13,6 @@ export interface UpdateLocker { export const RemovalLockerContext: Context = createContext(undefined); -// eslint-disable-next-line @typescript-eslint/no-extra-parens export const RestoreTreeContext: Context<(() => void) | undefined> = createContext<(() => void) | undefined>(undefined); export interface NestedOptionContextContent { @@ -24,7 +23,7 @@ export interface NestedOptionContextContent { configNode: IConfigNode, optionDescriptor: IOptionDescriptor, childUpdateToken: symbol, - optionComponentKey: number + optionComponentKey: number, ) => void; onNamedTemplateReady: ( template: ITemplate | null, diff --git a/packages/devextreme-react/src/core/options-manager.ts b/packages/devextreme-react/src/core/options-manager.ts index 1ba6113cf57b..e78b27cfab07 100644 --- a/packages/devextreme-react/src/core/options-manager.ts +++ b/packages/devextreme-react/src/core/options-manager.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-restricted-globals */ import { compareValues, getChanges } from './configuration/comparer'; import { buildConfig, findValue, ValueType } from './configuration/tree'; import { mergeNameParts, shallowEquals } from './configuration/utils'; diff --git a/packages/devextreme-react/src/core/template-manager.tsx b/packages/devextreme-react/src/core/template-manager.tsx index 175abc33178a..b7af1b90e9a6 100644 --- a/packages/devextreme-react/src/core/template-manager.tsx +++ b/packages/devextreme-react/src/core/template-manager.tsx @@ -131,20 +131,20 @@ export const TemplateManager: FC = ({ init, onTemplatesRen function createDXTemplates(templateOptions: Record): DXTemplateCollection { const factories = Object.entries(templateOptions) .reduce>((res, [key, template]) => ( - { - ...res, - [key]: getTemplateFunction(template), - } - ), {}); + { + ...res, + [key]: getTemplateFunction(template), + } + ), {}); templateFactories.current = factories; const dxTemplates = Object.keys(factories) .reduce((templates, templateKey) => { - templates[templateKey] = { render: getRenderFunc(templateKey) }; + templates[templateKey] = { render: getRenderFunc(templateKey) }; - return templates; - }, {}); + return templates; + }, {}); return dxTemplates; } diff --git a/packages/devextreme-react/src/core/use-option-scanning.ts b/packages/devextreme-react/src/core/use-option-scanning.ts index 1b79cff6cda4..98a79202bf72 100644 --- a/packages/devextreme-react/src/core/use-option-scanning.ts +++ b/packages/devextreme-react/src/core/use-option-scanning.ts @@ -15,9 +15,9 @@ export function useOptionScanning( parentUpdateToken: symbol, parentType: 'option' | 'component', ): [ - IConfigNode, - NestedOptionContextContent, - ] { + IConfigNode, + NestedOptionContextContent, +] { const parentContext = useContext(NestedOptionContext); const { diff --git a/packages/devextreme-react/src/core/widget-config.ts b/packages/devextreme-react/src/core/widget-config.ts index 4afc0718ea53..33102c32a3fb 100644 --- a/packages/devextreme-react/src/core/widget-config.ts +++ b/packages/devextreme-react/src/core/widget-config.ts @@ -47,10 +47,10 @@ function separateProps( defaultsProps: Record, templateProps: ITemplateMeta[], ): { - options: Record; - defaults: Record; - templates: Record; - } { + options: Record; + defaults: Record; + templates: Record; +} { templateProps = templateProps || []; const defaults: Record = {}; const options: Record = {}; diff --git a/packages/devextreme-themebuilder/eslint.config.mjs b/packages/devextreme-themebuilder/eslint.config.mjs index e577c676ece2..0dcca30260d5 100644 --- a/packages/devextreme-themebuilder/eslint.config.mjs +++ b/packages/devextreme-themebuilder/eslint.config.mjs @@ -3,6 +3,8 @@ import { fileURLToPath } from 'node:url'; import { FlatCompat } from '@eslint/eslintrc'; import { changeRulesToStylistic } from 'eslint-migration-utils'; import stylistic from '@stylistic/eslint-plugin'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; +import jestConfig from 'eslint-config-devextreme/jest'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -19,7 +21,7 @@ export default [ "jest.config.js", ], }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ["src/**/*.ts"], @@ -57,7 +59,7 @@ export default [ "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off", }, }, - ...compat.extends("devextreme/jest").map((config) => ({ + ...jestConfig.map((config) => ({ ...config, files: ["tests/**/*.ts"], })), diff --git a/packages/devextreme-themebuilder/package.json b/packages/devextreme-themebuilder/package.json index 5fe23e8632fc..9d66c98f528f 100644 --- a/packages/devextreme-themebuilder/package.json +++ b/packages/devextreme-themebuilder/package.json @@ -40,7 +40,7 @@ "@types/fs-extra": "11.0.4", "@types/node": "20.11.17", "eslint-config-airbnb-base": "15.0.0", - "eslint-config-devextreme": "1.1.5", + "eslint-config-devextreme": "catalog:", "eslint": "catalog:", "eslint-plugin-import": "catalog:", "eslint-config-airbnb-typescript": "catalog:", diff --git a/packages/devextreme-vue/eslint.config.mjs b/packages/devextreme-vue/eslint.config.mjs index 06199a35a275..b608c963da66 100644 --- a/packages/devextreme-vue/eslint.config.mjs +++ b/packages/devextreme-vue/eslint.config.mjs @@ -8,6 +8,8 @@ import i18N from "eslint-plugin-i18n"; import noOnlyTests from "eslint-plugin-no-only-tests"; import { rules as stylisticRules } from '@eslint-stylistic/metadata'; import stylistic from '@stylistic/eslint-plugin'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; @@ -34,7 +36,7 @@ const processDevExtremeRules = devExtremeRules => ( ); export default [ - ...compat.extends('devextreme/spell-check'), + ...spellCheckConfig, { ignores: ['metadata/*'], plugins: { @@ -126,7 +128,7 @@ export default [ "import/no-duplicates": "error", }, }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.ts?(x)'], @@ -179,7 +181,7 @@ export default [ "@typescript-eslint/no-unused-vars": "warn", }, }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ["**/*.d.ts"], diff --git a/packages/devextreme-vue/package.json b/packages/devextreme-vue/package.json index 14843bcaa522..f64d6487c00e 100644 --- a/packages/devextreme-vue/package.json +++ b/packages/devextreme-vue/package.json @@ -67,7 +67,7 @@ "del": "3.0.0", "devextreme-metadata": "workspace:*", "eslint-config-airbnb-base": "15.0.0", - "eslint-config-devextreme": "1.1.5", + "eslint-config-devextreme": "catalog:", "eslint-plugin-spellcheck": "0.0.20", "gulp": "4.0.2", "gulp-header": "2.0.9", @@ -84,9 +84,11 @@ "eslint-plugin-i18n": "catalog:", "eslint-plugin-import": "catalog:", "eslint-plugin-no-only-tests": "catalog:", + "eslint-plugin-vue": "catalog:", "@babel/eslint-parser": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:", - "@typescript-eslint/parser": "catalog:" + "@typescript-eslint/parser": "catalog:", + "vue-eslint-parser": "catalog:" }, "publishConfig": { "directory": "npm", diff --git a/packages/devextreme-vue/src/core/component.ts b/packages/devextreme-vue/src/core/component.ts index 4c6ee89c17df..5248be5e0e14 100644 --- a/packages/devextreme-vue/src/core/component.ts +++ b/packages/devextreme-vue/src/core/component.ts @@ -279,7 +279,7 @@ function initBaseComponent() { $_getWatchMethod(): ( valueGetter: () => any, valueChangeCallback: (value: any) => void, - options: { deep: boolean; skipImmediate: boolean } + options: { deep: boolean; skipImmediate: boolean }, ) => any { return (valueGetter, valueChangeCallback, options) => { options = options || {}; diff --git a/packages/devextreme/eslint.config.mjs b/packages/devextreme/eslint.config.mjs index 496937899d26..995954f126e1 100644 --- a/packages/devextreme/eslint.config.mjs +++ b/packages/devextreme/eslint.config.mjs @@ -4,7 +4,6 @@ import i18N from 'eslint-plugin-i18n'; import babelParser from '@babel/eslint-parser'; import tsParser from '@typescript-eslint/parser'; import path from 'node:path'; -import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import js from '@eslint/js'; import { FlatCompat } from '@eslint/eslintrc'; @@ -14,37 +13,20 @@ import globals from 'globals'; import simpleImportSort from 'eslint-plugin-simple-import-sort'; import { changeRulesToStylistic } from 'eslint-migration-utils'; import unicorn from 'eslint-plugin-unicorn'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; +import qunitConfig from 'eslint-config-devextreme/qunit'; import customRules from './eslint_plugins/index.js'; import { schedulerMemberAllowlistRegex } from './eslint-scheduler-allowlist.mjs'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const require = createRequire(import.meta.url); const compat = new FlatCompat({ baseDirectory: __dirname, recommendedConfig: js.configs.recommended, allConfig: js.configs.all }); -function loadDevExtremeConfig(moduleName, legacyName) { - try { - const loadedModule = require(moduleName); - const normalized = loadedModule.default ?? loadedModule; - - if (Array.isArray(normalized)) { - return normalized; - } - - return compat.config(normalized); - } catch { - return compat.extends(legacyName); - } -} - -const spellCheckConfig = loadDevExtremeConfig('eslint-config-devextreme/spell-check', 'devextreme/spell-check'); -const typescriptConfig = loadDevExtremeConfig('eslint-config-devextreme/typescript', 'devextreme/typescript'); -const qunitConfig = loadDevExtremeConfig('eslint-config-devextreme/qunit', 'devextreme/qunit'); - export default [ { ignores: [ @@ -236,6 +218,10 @@ export default [ '@typescript-eslint/ban-types': 'off', '@typescript-eslint/no-empty-object-type': 'off', '@typescript-eslint/no-throw-literal': 'off', + '@typescript-eslint/prefer-nullish-coalescing': 'warn', + '@typescript-eslint/only-throw-error': 'warn', + '@typescript-eslint/prefer-optional-chain': 'warn', + 'require-await': 'warn', '@typescript-eslint/switch-exhaustiveness-check': ['error', { considerDefaultExhaustiveForUnions: true, }], @@ -275,6 +261,7 @@ export default [ '@typescript-eslint/no-unsafe-function-type': 'off', '@typescript-eslint/no-wrapper-object-types': 'off', '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-unused-vars': 'off', 'i18n/no-russian-character': ['error', { includeIdentifier: true, }], diff --git a/packages/devextreme/js/__internal/core/ai_integration/core/prompt_manager.ts b/packages/devextreme/js/__internal/core/ai_integration/core/prompt_manager.ts index 6f72a3100095..ff8327bfe5e6 100644 --- a/packages/devextreme/js/__internal/core/ai_integration/core/prompt_manager.ts +++ b/packages/devextreme/js/__internal/core/ai_integration/core/prompt_manager.ts @@ -11,8 +11,7 @@ export interface PromptTemplate { user?: string; } -export type PromptTemplateName = - | 'changeStyle' +export type PromptTemplateName = | 'changeStyle' | 'changeTone' | 'execute' | 'expand' diff --git a/packages/devextreme/js/__internal/core/r1/template_wrapper.ts b/packages/devextreme/js/__internal/core/r1/template_wrapper.ts index 3336ad8d4f44..350cdc6e3108 100644 --- a/packages/devextreme/js/__internal/core/r1/template_wrapper.ts +++ b/packages/devextreme/js/__internal/core/r1/template_wrapper.ts @@ -30,9 +30,7 @@ export interface TemplateWrapperProps { renovated?: boolean; } -type TemplateModelArgs = - - Required> +type TemplateModelArgs = Required> & Omit; diff --git a/packages/devextreme/js/__internal/core/r1/types.ts b/packages/devextreme/js/__internal/core/r1/types.ts index e9cfba1e7e33..9bdbdd8ed156 100644 --- a/packages/devextreme/js/__internal/core/r1/types.ts +++ b/packages/devextreme/js/__internal/core/r1/types.ts @@ -33,10 +33,10 @@ export interface RefObject { export type JSXTemplate< PropsType = {}, RequiredProps extends keyof PropsType = Exclude< - keyof PropsType, - keyof PropsType + keyof PropsType, + keyof PropsType >, - > = ComponentType< - Partial> & - Required> - >; +> = ComponentType< + Partial> + & Required> +>; diff --git a/packages/devextreme/js/__internal/core/utils/m_callbacks.ts b/packages/devextreme/js/__internal/core/utils/m_callbacks.ts index f404ffb73616..9e4d022c9c23 100644 --- a/packages/devextreme/js/__internal/core/utils/m_callbacks.ts +++ b/packages/devextreme/js/__internal/core/utils/m_callbacks.ts @@ -1,5 +1,4 @@ -type CallbackType - = ((this: TContext, ...args: TArgs) => boolean) +type CallbackType = ((this: TContext, ...args: TArgs) => boolean) | ((this: TContext, ...args: TArgs) => void); export interface CallbackInterface { diff --git a/packages/devextreme/js/__internal/core/widget/component.ts b/packages/devextreme/js/__internal/core/widget/component.ts index 5b8133e5c255..e13f3f9f47af 100644 --- a/packages/devextreme/js/__internal/core/widget/component.ts +++ b/packages/devextreme/js/__internal/core/widget/component.ts @@ -71,7 +71,7 @@ export interface ComponentProperties extends ComponentOptions< onActionCreated?: ( component: TComponent, action: (e) => void, - config: ActionConfig + config: ActionConfig, ) => () => unknown; } @@ -411,7 +411,7 @@ export class Component< // eslint-disable-next-line @typescript-eslint/init-declarations let actionFunc; - let actionConfig = { ...config ?? {} } ; + let actionConfig = { ...config ?? {} }; // eslint-disable-next-line @typescript-eslint/explicit-function-return-type const result = (...args) => { diff --git a/packages/devextreme/js/__internal/core/widget/types.ts b/packages/devextreme/js/__internal/core/widget/types.ts index 72a2f2d4f8a1..5ea5d35fc262 100644 --- a/packages/devextreme/js/__internal/core/widget/types.ts +++ b/packages/devextreme/js/__internal/core/widget/types.ts @@ -7,10 +7,9 @@ type DotPrefix = T extends '' ? '' : `.${T}`; // eslint-disable-next-line spellcheck/spell-checker type DecrementalCounter = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; -type IsObject = -0 extends (1 & T) +type IsObject = 0 extends (1 & T) ? false -// eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any : T extends any[] ? false : string extends keyof T @@ -19,21 +18,20 @@ type IsObject = ? true : false; -type DotNestedKeys = -( - IsObject extends true ? - ( - RLIMIT extends 1 ? keyof T : - { +type DotNestedKeys = ( + IsObject extends true + ? ( + RLIMIT extends 1 ? keyof T + : { // eslint-disable-next-line spellcheck/spell-checker [K in Exclude]: `${K}${DotPrefix>}` | K }[Exclude] - ) : - '' + ) + : '' ) extends infer D ? Extract : never; export type ComponentPropertyType< -T, TProp extends string, + T, TProp extends string, > = PropertyType extends never ? never : PropertyType | undefined; interface OptionChangedArgs { name: TKey extends `${infer TName}.${string}` ? TName : TKey; diff --git a/packages/devextreme/js/__internal/core/widget/widget.ts b/packages/devextreme/js/__internal/core/widget/widget.ts index 57775d9c6cb8..a49bba9f84e0 100644 --- a/packages/devextreme/js/__internal/core/widget/widget.ts +++ b/packages/devextreme/js/__internal/core/widget/widget.ts @@ -41,7 +41,7 @@ const DEFAULT_FEEDBACK_SHOW_TIMEOUT = 30; export type SupportedKeyHandler = ( e: DxEvent, - options?: KeyboardKeyDownEvent + options?: KeyboardKeyDownEvent, // eslint-disable-next-line @typescript-eslint/no-invalid-void-type ) => void | boolean; export type SupportedKeys = Record< diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts index 60a894214034..3531fecd28e1 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts @@ -2518,8 +2518,7 @@ class EditingControllerImpl extends modules.ViewController { } } -export type EditingController = - EditingControllerImpl +export type EditingController = EditingControllerImpl & ICellBasedEditingControllerExtender & IFormBasedEditingControllerExtender; diff --git a/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation_core.ts b/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation_core.ts index d15bfcf7a0e6..b4e43eaf0189 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation_core.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation_core.ts @@ -80,9 +80,9 @@ export class KeyboardNavigationController extends modules.ViewController { private getScrollPadding( $container: dxElementWrapper, ): { - left: number; - right: number; - } { + left: number; + right: number; + } { const containerRect = getBoundingRect($container.get(0)); const containerBoundingRect = this.getContainerBoundingRect($container); diff --git a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts index d70bcda4c6a0..f61df88f05c2 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts @@ -29,17 +29,16 @@ export interface Coordinates { } // todo: move to upper .d.ts -type OptionsMethod = - (() => TOptions) & - ((options: TOptions) => void) & - ( +type OptionsMethod = (() => TOptions) + & ((options: TOptions) => void) + & ( ( - optionName: TPropertyName + optionName: TPropertyName, ) => GridPropertyType ) & ( ( optionName: TPropertyName, - optionValue: GridPropertyType + optionValue: GridPropertyType, ) => void ); @@ -77,7 +76,7 @@ export interface InternalGrid extends GridBaseType { _createComponent: >( $container: dxElementWrapper, component: new (...args) => TComponent, - options?: TComponent extends Component ? TOptions : never + options?: TComponent extends Component ? TOptions : never, ) => TComponent; _createAction: any; @@ -89,24 +88,24 @@ export interface InternalGrid extends GridBaseType { } type TemporarlyOptionsTakenFromDataGrid = Pick; type TemporarlyOptionsTakenFromTreeList = Pick; interface InternalSelection extends SelectionBase { alwaysSelectByShift?: boolean; @@ -135,28 +134,26 @@ type DotPrefix = T extends '' ? '' : `.${T}`; type DecrementalCounter = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; // todo: move to upper .d.ts files -type IsObject = - 0 extends (1 & T) +type IsObject = 0 extends (1 & T) + ? false + : T extends any[] ? false - : T extends any[] + : string extends keyof T ? false - : string extends keyof T - ? false - : T extends object - ? true - : false; + : T extends object + ? true + : false; // todo: move to upper .d.ts files -type DotNestedKeys = -( - IsObject extends true ? - ( - RLIMIT extends 1 ? keyof T : - { +type DotNestedKeys = ( + IsObject extends true + ? ( + RLIMIT extends 1 ? keyof T + : { [K in Exclude]: `${K}${DotPrefix>}` | K }[Exclude] - ) : - '' + ) + : '' ) extends infer D ? Extract : never; // todo: move to upper .d.ts files diff --git a/packages/devextreme/js/__internal/grids/new/card_view/context_menu/options.ts b/packages/devextreme/js/__internal/grids/new/card_view/context_menu/options.ts index 7324cf32f2bd..e937a6d1d7c2 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/context_menu/options.ts +++ b/packages/devextreme/js/__internal/grids/new/card_view/context_menu/options.ts @@ -8,8 +8,7 @@ import type { CardInfo, Column } from '../../grid_core/columns_controller/types' export type ContextMenuTarget = 'toolbar' | 'headerPanel' | 'content'; // eslint-disable-next-line @typescript-eslint/no-unused-vars -export type ContextMenuPreparingEvent -= EventInfo & { +export type ContextMenuPreparingEvent = EventInfo & { items?: any[]; readonly target: ContextMenuTarget; diff --git a/packages/devextreme/js/__internal/grids/new/card_view/options.ts b/packages/devextreme/js/__internal/grids/new/card_view/options.ts index c9c3f0b1fd87..7d37900f904b 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/options.ts +++ b/packages/devextreme/js/__internal/grids/new/card_view/options.ts @@ -7,8 +7,7 @@ import * as HeaderPanel from './header_panel/index'; /** * @interface */ -export type Options = - & GridCore.Options +export type Options = & GridCore.Options & ContentView.Options & HeaderPanel.Options & ContextMenu.Options; diff --git a/packages/devextreme/js/__internal/grids/new/card_view/options_controller.mock.ts b/packages/devextreme/js/__internal/grids/new/card_view/options_controller.mock.ts index d66ec5d1e7c9..9e47493b22a5 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/options_controller.mock.ts +++ b/packages/devextreme/js/__internal/grids/new/card_view/options_controller.mock.ts @@ -6,7 +6,7 @@ import type { Options } from './options'; import { defaultOptions } from './options'; export class OptionsControllerMock extends OptionsControllerBaseMock< -Options, typeof defaultOptions + Options, typeof defaultOptions > { constructor(options: Options) { super(options, defaultOptions); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts index b574a3f0ba21..dd35ed85c907 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/controller.test.ts @@ -79,8 +79,8 @@ describe('ColumnChooser', () => { ); it.each< - { mode: ColumnChooserMode; sortOrder?: SortOrder; result: string[] } - >([ + { mode: ColumnChooserMode; sortOrder?: SortOrder; result: string[] } + >([ { mode: 'dragAndDrop', sortOrder: 'asc', result: ['A', 'B', 'C'] }, { mode: 'dragAndDrop', sortOrder: 'desc', result: ['C', 'B', 'A'] }, { mode: 'dragAndDrop', sortOrder: undefined, result: ['C', 'A', 'B'] }, @@ -110,8 +110,8 @@ describe('ColumnChooser', () => { ); it.each< - { mode: ColumnChooserMode; sortOrder?: SortOrder; result: string[] } - >([ + { mode: ColumnChooserMode; sortOrder?: SortOrder; result: string[] } + >([ { mode: 'dragAndDrop', sortOrder: 'asc', result: ['A', 'C'] }, { mode: 'dragAndDrop', sortOrder: 'desc', result: ['C', 'A'] }, { mode: 'dragAndDrop', sortOrder: undefined, result: ['C', 'A'] }, diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts index 9e5be553fb03..cc8af012931f 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts @@ -52,8 +52,8 @@ export const defaultColumnProperties = { } satisfies Partial; export const defaultColumnPropertiesByDataType: Record< -DataType, -Exclude + DataType, + Exclude > = { boolean: { customizeText({ value }): string { diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts index f81dc089169c..ffaabe986e88 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/types.ts @@ -8,8 +8,7 @@ import type { ComponentType } from 'inferno'; import type { DataObject, Key } from '../data_controller/types'; import type { HighlightedTextItem } from '../search/types'; -type InheritedColumnProps = - | 'alignment' +type InheritedColumnProps = | 'alignment' | 'dataType' | 'visible' | 'visibleIndex' @@ -77,7 +76,7 @@ export type Column = Pick, InheritedColumnProps> & { headerFilter?: HeaderFilterColumnOptions; setFieldValue: ( - this: Column, newData: DeepPartial, value: unknown, currentRowData: DataObject + this: Column, newData: DeepPartial, value: unknown, currentRowData: DataObject, ) => (void | Promise); defaultSetFieldValue: Column['setFieldValue']; diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/utils.ts b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/utils.ts index d639ceb665dc..32a1ecfc4fa8 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/utils.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/utils.ts @@ -15,7 +15,7 @@ import { defaultColumnProperties, defaultColumnPropertiesByDataType } from './op import type { Column, ColumnFromDataOptions, ColumnsConfigurationFromData } from './types'; type TemplateNormalizationFunc = ( - template: Template | undefined + template: Template | undefined, ) => ComponentType | undefined; export function normalizeColumn( diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/options.integration.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/options.integration.test.ts index 2aaeaba29eab..e2bf8f85a7ee 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/options.integration.test.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/options.integration.test.ts @@ -612,53 +612,53 @@ describe('Options', () => { filterType?: HeaderFilterType; filterValues?: string[]; }>([ - { - caseName: 'custom dataSource', - dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], - filterType: undefined, - filterValues: undefined, - }, - { - caseName: 'custom dataSource with exclude filter', - dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], - filterType: 'exclude', - filterValues: undefined, - }, - { - caseName: 'custom dataSource with filter values', - dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], - filterValues: ['B'], - }, - { - caseName: 'custom dataSource with exclude filter and values', - dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], - filterType: 'exclude', - filterValues: ['B'], - }, - ])('dataSource: $caseName', ({ dataSource, filterType, filterValues }) => { - const cardView = setup({ - dataSource: [ - { A: 'A_0', B: 'B_0' }, - { A: 'A_1', B: 'B_1' }, - { A: 'A_2', B: 'B_2' }, - { A: 'A_3', B: 'B_3' }, - { A: 'A_4', B: 'B_4' }, - ], - columns: [{ - dataField: 'A', - headerFilter: { dataSource }, - filterValues, - filterType, - }], - headerFilter: { - visible: true, - }, - }); + { + caseName: 'custom dataSource', + dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], + filterType: undefined, + filterValues: undefined, + }, + { + caseName: 'custom dataSource with exclude filter', + dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], + filterType: 'exclude', + filterValues: undefined, + }, + { + caseName: 'custom dataSource with filter values', + dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], + filterValues: ['B'], + }, + { + caseName: 'custom dataSource with exclude filter and values', + dataSource: [{ text: 'A', value: 'A' }, { text: 'B', value: 'B' }], + filterType: 'exclude', + filterValues: ['B'], + }, + ])('dataSource: $caseName', ({ dataSource, filterType, filterValues }) => { + const cardView = setup({ + dataSource: [ + { A: 'A_0', B: 'B_0' }, + { A: 'A_1', B: 'B_1' }, + { A: 'A_2', B: 'B_2' }, + { A: 'A_3', B: 'B_3' }, + { A: 'A_4', B: 'B_4' }, + ], + columns: [{ + dataField: 'A', + headerFilter: { dataSource }, + filterValues, + filterType, + }], + headerFilter: { + visible: true, + }, + }); - openHeaderFilterPopup(cardView); - const { element: popupContentElement } = getPopup(); + openHeaderFilterPopup(cardView); + const { element: popupContentElement } = getPopup(); - expect(popupContentElement).toMatchSnapshot(); - }); + expect(popupContentElement).toMatchSnapshot(); + }); }); }); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/view_controller.test.ts b/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/view_controller.test.ts index 3b12b71c0b1d..8ba1ca76541f 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/view_controller.test.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/view_controller.test.ts @@ -167,37 +167,37 @@ describe('HeaderFilter', () => { column: Column; checkFn: (group: any) => boolean; }>([ - { - caseName: 'default', - column: { dataField: 'A' } as Column, - checkFn: (group): boolean => typeof group === 'function', - }, - { - caseName: 'groupInterval', - column: { dataField: 'A', headerFilter: { groupInterval: 2 } } as Column, - checkFn: ([group]): boolean => typeof group === 'function', - }, - { - caseName: 'sortingMethod', - column: { dataField: 'A', sortingMethod: () => {} } as unknown as Column, - checkFn: ([{ selector, compare }]): boolean => typeof selector === 'function' && typeof compare === 'function', - }, - ])('$caseName: dataSource options should contains correct group', ({ column, checkFn }) => { - const { viewController } = setup({ - headerFilter: { visible: true }, - columns: [column as any], - }); - - viewController.openPopup( - {} as Element, - column, - ); - - const state = viewController.popupState.peek(); - - expect((state?.options.dataSource as any).group).toBeTruthy(); - expect(checkFn((state?.options.dataSource as any).group)).toBeTruthy(); - }); + { + caseName: 'default', + column: { dataField: 'A' } as Column, + checkFn: (group): boolean => typeof group === 'function', + }, + { + caseName: 'groupInterval', + column: { dataField: 'A', headerFilter: { groupInterval: 2 } } as Column, + checkFn: ([group]): boolean => typeof group === 'function', + }, + { + caseName: 'sortingMethod', + column: { dataField: 'A', sortingMethod: () => {} } as unknown as Column, + checkFn: ([{ selector, compare }]): boolean => typeof selector === 'function' && typeof compare === 'function', + }, + ])('$caseName: dataSource options should contains correct group', ({ column, checkFn }) => { + const { viewController } = setup({ + headerFilter: { visible: true }, + columns: [column as any], + }); + + viewController.openPopup( + {} as Element, + column, + ); + + const state = viewController.popupState.peek(); + + expect((state?.options.dataSource as any).group).toBeTruthy(); + expect(checkFn((state?.options.dataSource as any).group)).toBeTruthy(); + }); }); }); }); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/icon.tsx b/packages/devextreme/js/__internal/grids/new/grid_core/icon.tsx index 49fa767fffef..5be3bfe2555d 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/icon.tsx +++ b/packages/devextreme/js/__internal/grids/new/grid_core/icon.tsx @@ -26,8 +26,7 @@ export function Icon(props: Properties): JSX.Element { ); } -export type IconName = -| 'add' +export type IconName = | 'add' | 'airplane' | 'bookmark' | 'chat' diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/options.ts b/packages/devextreme/js/__internal/grids/new/grid_core/options.ts index 465ec02e81e1..af8492625859 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/options.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/options.ts @@ -22,8 +22,7 @@ import type { GridCoreNew } from './widget'; /** * @interface */ -export type Options = - & WidgetOptions +export type Options = & WidgetOptions & dataController.Options & sortingController.Options & pager.Options diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/component.mock.ts b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/component.mock.ts index 914afd9165d0..359473a1bbd6 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/component.mock.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/component.mock.ts @@ -10,26 +10,26 @@ export const createComponentMock = < TProps extends Record, TDefaultProps extends TProps = TProps, >( - options: TProps, - defaultOptions: TDefaultProps, - isInitialized = true, - ): Component => new class ComponentMock extends Component { - public initialized = signal(isInitialized); + options: TProps, + defaultOptions: TDefaultProps, + isInitialized = true, +): Component => new class ComponentMock extends Component { + public initialized = signal(isInitialized); - // NOTE: Add default option values to base Component for merging them - // with Component's algorithms - public _getDefaultOptions(): TDefaultProps { + // NOTE: Add default option values to base Component for merging them + // with Component's algorithms + public _getDefaultOptions(): TDefaultProps { // @ts-expect-error badly typed base Component class - const baseDefaultOptions = super._getDefaultOptions(); + const baseDefaultOptions = super._getDefaultOptions(); - return extend(true, {}, baseDefaultOptions, defaultOptions) as TDefaultProps; - } + return extend(true, {}, baseDefaultOptions, defaultOptions) as TDefaultProps; + } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public _getTemplate(template: any): any { - if (typeof template === 'function') { - return new FunctionTemplate(template); - } - return template; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public _getTemplate(template: any): any { + if (typeof template === 'function') { + return new FunctionTemplate(template); } - }(extend(true, {}, options)); + return template; + } +}(extend(true, {}, options)); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller.mock.ts b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller.mock.ts index 18dd6d589a37..97262e691979 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller.mock.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller.mock.ts @@ -3,7 +3,7 @@ import { defaultOptions } from '../options'; import { OptionsControllerMock as OptionsControllerBaseMock } from './options_controller_base.mock'; export class OptionsControllerMock extends OptionsControllerBaseMock< -Options, typeof defaultOptions + Options, typeof defaultOptions > { constructor(options: Options) { super(options, defaultOptions); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/types.ts b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/types.ts index 296f061e42c8..2e7c1299f1fc 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/types.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/types.ts @@ -2,35 +2,42 @@ import type { ChangedOptionInfo } from '@js/common/core/events'; import type { Action, Template } from '@ts/grids/new/grid_core/types'; import type { ComponentType } from 'inferno'; -export type OwnProperty = - TPropName extends keyof Required - ? Required[TPropName] - : unknown; - -export type PropertyTypeBase = - TProp extends `${infer TOwnProp}.${infer TNestedProps}` - ? PropertyTypeBase, TNestedProps> - : OwnProperty; - -export type PropertyType = - unknown extends PropertyTypeBase - ? unknown - : PropertyTypeBase | undefined; - -export type PropertyWithDefaults = - unknown extends PropertyType - ? PropertyType - : NonNullable> | PropertyTypeBase; - -export type TemplateProperty = - NonNullable> extends Template - ? ComponentType | undefined - : unknown; - -export type ActionProperty = - NonNullable> extends Action - ? (args: TActionArgs) => void - : unknown; +export type OwnProperty = TPropName extends keyof Required + ? Required[TPropName] + : unknown; + +export type PropertyTypeBase = TProp extends `${infer TOwnProp}.${infer TNestedProps}` + ? PropertyTypeBase, TNestedProps> + : OwnProperty; + +export type PropertyType< + TProps, + TProp extends string, +> = unknown extends PropertyTypeBase + ? unknown + : PropertyTypeBase | undefined; + +export type PropertyWithDefaults< + TProps, + TDefaults, + TProp extends string, +> = unknown extends PropertyType + ? PropertyType + : NonNullable> | PropertyTypeBase; + +export type TemplateProperty< + TProps, + TProp extends string, +> = NonNullable> extends Template + ? ComponentType | undefined + : unknown; + +export type ActionProperty< + TProps, + TProp extends string, +> = NonNullable> extends Action + ? (args: TActionArgs) => void + : unknown; // eslint-disable-next-line @typescript-eslint/no-explicit-any export interface InternalOptionsState> { diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/selection/types.ts b/packages/devextreme/js/__internal/grids/new/grid_core/selection/types.ts index 5b36648c5e79..55b1470fe6dd 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/selection/types.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/selection/types.ts @@ -21,13 +21,17 @@ export interface SelectionEventInfo { readonly isDeselectAll: boolean; } -export type SelectionChangingEvent = - EventInfo & SelectionEventInfo & { - cancel: boolean | PromiseLike | PromiseLike; - }; - -export type SelectionChangedEvent = - EventInfo & SelectionEventInfo; +export type SelectionChangingEvent< + TCardData = unknown, + TKey = unknown, +> = EventInfo & SelectionEventInfo & { + cancel: boolean | PromiseLike | PromiseLike; +}; + +export type SelectionChangedEvent< + TCardData = unknown, + TKey = unknown, +> = EventInfo & SelectionEventInfo; export type { SelectionColumnDisplayMode as ShowCheckBoxesMode }; diff --git a/packages/devextreme/js/__internal/pagination/common/keyboard_action_context.ts b/packages/devextreme/js/__internal/pagination/common/keyboard_action_context.ts index e614cbe1e7a5..b5db25e0fe06 100644 --- a/packages/devextreme/js/__internal/pagination/common/keyboard_action_context.ts +++ b/packages/devextreme/js/__internal/pagination/common/keyboard_action_context.ts @@ -7,5 +7,5 @@ export interface KeyboardActionContextType { registerKeyboardAction: (el: HTMLElement, handler: EventCallback) => DisposeEffectReturn; } -export const KeyboardActionContext = createContext(undefined); +export const KeyboardActionContext = createContext(undefined); diff --git a/packages/devextreme/js/__internal/pagination/editors/common/base_widget_props.ts b/packages/devextreme/js/__internal/pagination/editors/common/base_widget_props.ts index bf56f084f3a9..97a9c17e33b9 100644 --- a/packages/devextreme/js/__internal/pagination/editors/common/base_widget_props.ts +++ b/packages/devextreme/js/__internal/pagination/editors/common/base_widget_props.ts @@ -2,7 +2,7 @@ export interface BaseWidgetProps { className?: string; accessKey?: string; activeStateEnabled?: boolean; - disabled?: boolean ; + disabled?: boolean; focusStateEnabled?: boolean; height?: string | number; hint?: string; diff --git a/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/model/appointment.ts b/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/model/appointment.ts index 97dcf23f4889..06ec245aaac9 100644 --- a/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/model/appointment.ts +++ b/packages/devextreme/js/__internal/scheduler/__tests__/__mock__/model/appointment.ts @@ -41,23 +41,23 @@ const getGeometry = (element: HTMLDivElement | null): Position => { export const createAppointmentModel = ( element: T, ): AppointmentModel => ({ - element, - getText: () => getText(element), - getDisplayDate: () => getDisplayDate(element), - getAriaLabel: () => element?.getAttribute('aria-label') ?? '', - getGeometry: () => getGeometry(element), - getColor(view: string): string | undefined { - if (!element) { - return undefined; - } + element, + getText: () => getText(element), + getDisplayDate: () => getDisplayDate(element), + getAriaLabel: () => element?.getAttribute('aria-label') ?? '', + getGeometry: () => getGeometry(element), + getColor(view: string): string | undefined { + if (!element) { + return undefined; + } - return view === 'agenda' - ? getAgendaColor(element) - : getColor(element); - }, - getSnapshot: (): object => ({ - text: getText(element), - date: getDisplayDate(element), - ...getGeometry(element), - }), - }); + return view === 'agenda' + ? getAgendaColor(element) + : getColor(element); + }, + getSnapshot: (): object => ({ + text: getText(element), + date: getDisplayDate(element), + ...getGeometry(element), + }), +}); diff --git a/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts b/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts index df3bb18e4068..cf36d7ef04c4 100644 --- a/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts +++ b/packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts @@ -764,9 +764,9 @@ describe('Appointment popup form', () => { items: T[], getChildren: (item: T) => T[] | undefined, ): T[] => items.flatMap((item) => { - const children = getChildren(item); - return children?.length ? flattenBy(children, getChildren) : [item]; - }); + const children = getChildren(item); + return children?.length ? flattenBy(children, getChildren) : [item]; + }); const $container = $('
').appendTo(document.body); const editor = ($container as any).dxRecurrenceEditor({ diff --git a/packages/devextreme/js/__internal/scheduler/appointments/utils/get_arrays_diff.ts b/packages/devextreme/js/__internal/scheduler/appointments/utils/get_arrays_diff.ts index 3aaac3902732..10097cbc20fe 100644 --- a/packages/devextreme/js/__internal/scheduler/appointments/utils/get_arrays_diff.ts +++ b/packages/devextreme/js/__internal/scheduler/appointments/utils/get_arrays_diff.ts @@ -2,8 +2,7 @@ interface NoChanges { item: A } interface ToRemove { item: A; needToRemove: true } interface ToAdd { item: B; needToAdd: true } -export type DiffItem = - | NoChanges +export type DiffItem = | NoChanges | ToRemove | ToAdd; diff --git a/packages/devextreme/js/__internal/scheduler/types.ts b/packages/devextreme/js/__internal/scheduler/types.ts index f0a05b920f5b..c56a07698639 100644 --- a/packages/devextreme/js/__internal/scheduler/types.ts +++ b/packages/devextreme/js/__internal/scheduler/types.ts @@ -225,7 +225,7 @@ export interface ViewDataProviderType { rowIndex: number, columnIndex: number, isAllDay?: boolean, - rtlEnabled?: boolean + rtlEnabled?: boolean, ) => ViewCellData; getCellCount: (config: CountGenerationConfig) => number; getRowCount: (config: CountGenerationConfig) => number; @@ -235,7 +235,7 @@ export interface ViewDataProviderType { getVisibleDayDuration: ( startDayHour: number, endDayHour: number, - hoursInterval: number + hoursInterval: number, ) => number; getLastViewDateByEndDayHour: (endDayHour: number) => Date; getIntervalDuration: (intervalCount: number) => number; diff --git a/packages/devextreme/js/__internal/scheduler/utils/options_validator/core/types.ts b/packages/devextreme/js/__internal/scheduler/utils/options_validator/core/types.ts index d4d469834ab9..b64949ab91fd 100644 --- a/packages/devextreme/js/__internal/scheduler/utils/options_validator/core/types.ts +++ b/packages/devextreme/js/__internal/scheduler/utils/options_validator/core/types.ts @@ -7,10 +7,12 @@ export type ValidatorRule = (value: TValue) => ValidatorRuleResult; export type ValidatorErrors = Record; export type ValidatorResult = true | ValidatorErrors; -export type OptionsValidatorErrors = - Partial>; -export type OptionsValidatorResult = - true | OptionsValidatorErrors; +export type OptionsValidatorErrors< + TValidators extends string, +> = Partial>; +export type OptionsValidatorResult< + TValidators extends string, +> = true | OptionsValidatorErrors; export interface GlobalErrorHandler { logError: (errorCode: string, ...args: string[]) => void; diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/types.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/types.ts index 0f529abf912d..b93a789a6fe5 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/types.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/types.ts @@ -108,7 +108,6 @@ export interface AppointmentItemViewModel extends BaseAppointmentViewModel, Appo columnIndex: number; } -export type AppointmentViewModelPlain = - | AppointmentAgendaViewModel +export type AppointmentViewModelPlain = | AppointmentAgendaViewModel | AppointmentItemViewModel | AppointmentCollectorViewModel; diff --git a/packages/devextreme/js/__internal/ui/button_group.ts b/packages/devextreme/js/__internal/ui/button_group.ts index d5f3d4c64dcb..7ee13d621c5e 100644 --- a/packages/devextreme/js/__internal/ui/button_group.ts +++ b/packages/devextreme/js/__internal/ui/button_group.ts @@ -36,7 +36,7 @@ export type ItemRenderedEvent = EventInfo & ItemInfo