diff --git a/apps/demos/Demos/Autocomplete/Overview/Angular/app/app.component.ts b/apps/demos/Demos/Autocomplete/Overview/Angular/app/app.component.ts index d3d3a4962975..b85693a66748 100644 --- a/apps/demos/Demos/Autocomplete/Overview/Angular/app/app.component.ts +++ b/apps/demos/Demos/Autocomplete/Overview/Angular/app/app.component.ts @@ -58,7 +58,7 @@ export class AppComponent { this.clientsStore = new CustomStore({ key: 'Value', useDefaultSearch: true, - async load(loadOptions) { + load(loadOptions) { let params: HttpParams = new HttpParams(); [ 'skip', diff --git a/apps/demos/Demos/Chat/AIAndChatbotIntegration/Angular/app/app.service.ts b/apps/demos/Demos/Chat/AIAndChatbotIntegration/Angular/app/app.service.ts index 29b7fdf00957..20c638097558 100644 --- a/apps/demos/Demos/Chat/AIAndChatbotIntegration/Angular/app/app.service.ts +++ b/apps/demos/Demos/Chat/AIAndChatbotIntegration/Angular/app/app.service.ts @@ -90,7 +90,7 @@ export class AppService { }); } - async getAIResponse(messages: AIMessage[]): Promise { + getAIResponse(messages: AIMessage[]): Promise { return this.aiService.getAIResponse(messages) as Promise; } diff --git a/apps/demos/Demos/Chat/FileAttachments/Angular/app/app.service.ts b/apps/demos/Demos/Chat/FileAttachments/Angular/app/app.service.ts index 54b5c307be25..b0642bdf3d92 100644 --- a/apps/demos/Demos/Chat/FileAttachments/Angular/app/app.service.ts +++ b/apps/demos/Demos/Chat/FileAttachments/Angular/app/app.service.ts @@ -80,8 +80,8 @@ export class AppService { initDataSource() { this.customStore = new CustomStore({ key: 'id', - load: async () => this.messages, - insert: async (message) => { + load: () => this.messages, + insert: (message) => { this.messages.push(message); return message; }, diff --git a/apps/demos/Demos/Chat/FileAttachments/React/App.tsx b/apps/demos/Demos/Chat/FileAttachments/React/App.tsx index aebe110e523b..7ad5c5fecf06 100644 --- a/apps/demos/Demos/Chat/FileAttachments/React/App.tsx +++ b/apps/demos/Demos/Chat/FileAttachments/React/App.tsx @@ -11,10 +11,10 @@ const store: ChatTypes.Message[] = [...initialMessages]; const customStore = new CustomStore({ key: 'id', - load: async () => store, - insert: async (message: ChatTypes.Message) => { + load: () => Promise.resolve(store), + insert: (message: ChatTypes.Message) => { store.push(message); - return message; + return Promise.resolve(message); }, }); diff --git a/apps/demos/Demos/Chat/FileAttachments/ReactJs/App.js b/apps/demos/Demos/Chat/FileAttachments/ReactJs/App.js index c4623abfb17e..008779df2787 100644 --- a/apps/demos/Demos/Chat/FileAttachments/ReactJs/App.js +++ b/apps/demos/Demos/Chat/FileAttachments/ReactJs/App.js @@ -7,10 +7,10 @@ import { currentUser, messages as initialMessages } from './data.js'; const store = [...initialMessages]; const customStore = new CustomStore({ key: 'id', - load: async () => store, - insert: async (message) => { + load: () => Promise.resolve(store), + insert: (message) => { store.push(message); - return message; + return Promise.resolve(message); }, }); const dataSource = new DataSource({ diff --git a/apps/demos/Demos/Chat/MessageEditing/Angular/app/app.service.ts b/apps/demos/Demos/Chat/MessageEditing/Angular/app/app.service.ts index 69dcbeb04bd5..13bd85dbfcce 100644 --- a/apps/demos/Demos/Chat/MessageEditing/Angular/app/app.service.ts +++ b/apps/demos/Demos/Chat/MessageEditing/Angular/app/app.service.ts @@ -72,8 +72,8 @@ export class AppService { initDataSource() { this.customStore = new CustomStore({ key: 'id', - load: async () => this.messages, - insert: async (message) => { + load: () => this.messages, + insert: (message) => { this.messages.push(message); return message; }, diff --git a/apps/demos/Demos/Chat/MessageEditing/React/App.tsx b/apps/demos/Demos/Chat/MessageEditing/React/App.tsx index b7e1e9ae9779..f36ae8119fea 100644 --- a/apps/demos/Demos/Chat/MessageEditing/React/App.tsx +++ b/apps/demos/Demos/Chat/MessageEditing/React/App.tsx @@ -33,10 +33,10 @@ const store: ChatTypes.Message[] = [...initialMessages]; const customStore = new CustomStore({ key: 'id', - load: async (): Promise => store, - insert: async (message: ChatTypes.Message): Promise => { + load: (): Promise => Promise.resolve(store), + insert: (message: ChatTypes.Message): Promise => { store.push(message); - return message; + return Promise.resolve(message); }, }); diff --git a/apps/demos/Demos/Chat/MessageEditing/ReactJs/App.js b/apps/demos/Demos/Chat/MessageEditing/ReactJs/App.js index 7a4ff7c353b3..594b0a779944 100644 --- a/apps/demos/Demos/Chat/MessageEditing/ReactJs/App.js +++ b/apps/demos/Demos/Chat/MessageEditing/ReactJs/App.js @@ -26,10 +26,10 @@ const editingStrategy = { const store = [...initialMessages]; const customStore = new CustomStore({ key: 'id', - load: async () => store, - insert: async (message) => { + load: () => Promise.resolve(store), + insert: (message) => { store.push(message); - return message; + return Promise.resolve(message); }, }); const dataSource = new DataSource({ diff --git a/apps/demos/Demos/DataGrid/AIColumns/Angular/app/ai/ai.service.ts b/apps/demos/Demos/DataGrid/AIColumns/Angular/app/ai/ai.service.ts index 5d11318caa39..4d5f9bcb1498 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/Angular/app/ai/ai.service.ts +++ b/apps/demos/Demos/DataGrid/AIColumns/Angular/app/ai/ai.service.ts @@ -42,7 +42,7 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal) { return result; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { diff --git a/apps/demos/Demos/DataGrid/AIColumns/React/service.ts b/apps/demos/Demos/DataGrid/AIColumns/React/service.ts index b3e0121ee93c..f47ec621e906 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/React/service.ts +++ b/apps/demos/Demos/DataGrid/AIColumns/React/service.ts @@ -28,7 +28,7 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal) { return result ?? ''; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { diff --git a/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js b/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js index e8630a16631e..94fccfe26d51 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js +++ b/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js @@ -21,7 +21,7 @@ async function getAIResponse(messages, signal) { const result = response.choices[0].message?.content; return result ?? ''; } -async function getAIResponseRecursive(messages, signal) { +function getAIResponseRecursive(messages, signal) { return getAIResponse(messages, signal).catch(async (error) => { if (!error.message.includes('Connection error')) { return Promise.reject(error); diff --git a/apps/demos/Demos/DataGrid/AIColumns/Vue/service.ts b/apps/demos/Demos/DataGrid/AIColumns/Vue/service.ts index f3cd2e3bf6d1..c1b2b0e75d6b 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/Vue/service.ts +++ b/apps/demos/Demos/DataGrid/AIColumns/Vue/service.ts @@ -41,7 +41,7 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal) { return result; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { diff --git a/apps/demos/Demos/DataGrid/EditStateManagement/Angular/app/app.service.ts b/apps/demos/Demos/DataGrid/EditStateManagement/Angular/app/app.service.ts index 2da6d3bf8aba..b5e6701decca 100644 --- a/apps/demos/Demos/DataGrid/EditStateManagement/Angular/app/app.service.ts +++ b/apps/demos/Demos/DataGrid/EditStateManagement/Angular/app/app.service.ts @@ -84,7 +84,7 @@ export class Service { return data; } - async saveChange(change: Change): Promise { + saveChange(change: Change): Promise { switch (change.type) { case 'insert': return this.insert(change); diff --git a/apps/demos/Demos/DataGrid/EditStateManagement/React/actions.ts b/apps/demos/Demos/DataGrid/EditStateManagement/React/actions.ts index 15b2813b168f..665aadd627c6 100644 --- a/apps/demos/Demos/DataGrid/EditStateManagement/React/actions.ts +++ b/apps/demos/Demos/DataGrid/EditStateManagement/React/actions.ts @@ -64,7 +64,7 @@ export async function saveChange(dispatch: dispatchType, change: DataGridTypes.D } } -async function sendChange(url: string, change: DataGridTypes.DataChange) { +function sendChange(url: string, change: DataGridTypes.DataChange) { switch (change.type) { case 'insert': return sendRequest(`${url}/InsertOrder`, 'POST', { diff --git a/apps/demos/Demos/DataGrid/EditStateManagement/ReactJs/actions.js b/apps/demos/Demos/DataGrid/EditStateManagement/ReactJs/actions.js index ba32231a8b2e..fd61dd7dae3e 100644 --- a/apps/demos/Demos/DataGrid/EditStateManagement/ReactJs/actions.js +++ b/apps/demos/Demos/DataGrid/EditStateManagement/ReactJs/actions.js @@ -48,7 +48,7 @@ export async function saveChange(dispatch, change) { return null; } } -async function sendChange(url, change) { +function sendChange(url, change) { switch (change.type) { case 'insert': return sendRequest(`${url}/InsertOrder`, 'POST', { diff --git a/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx b/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx index 973a79d2fe1f..867bb70c63c1 100644 --- a/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx +++ b/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx @@ -34,7 +34,7 @@ const onExporting = ({ component }: DataGridTypes.ExportingEvent) => { } }, customDrawCell: (e: CustomDrawCellEvent) => { - if (e.gridCell && e.gridCell.rowType === 'data' && e.gridCell.column?.dataField === 'Picture' && e.rect) { + if (e.gridCell?.rowType === 'data' && e.gridCell.column?.dataField === 'Picture' && e.rect) { doc.addImage(e.gridCell.value, 'PNG', e.rect.x, e.rect.y, e.rect.w, e.rect.h); e.cancel = true; } diff --git a/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js b/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js index c8ee1a61d2cb..d460137fa629 100644 --- a/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js @@ -25,12 +25,7 @@ const onExporting = ({ component }) => { } }, customDrawCell: (e) => { - if ( - e.gridCell && - e.gridCell.rowType === 'data' && - e.gridCell.column?.dataField === 'Picture' && - e.rect - ) { + if (e.gridCell?.rowType === 'data' && e.gridCell.column?.dataField === 'Picture' && e.rect) { doc.addImage(e.gridCell.value, 'PNG', e.rect.x, e.rect.y, e.rect.w, e.rect.h); e.cancel = true; } diff --git a/apps/demos/Demos/Localization/UsingIntl/Angular/app/messages.d.ts b/apps/demos/Demos/Localization/UsingIntl/Angular/app/messages.d.ts index 98878ae3059c..56667b8e480b 100644 --- a/apps/demos/Demos/Localization/UsingIntl/Angular/app/messages.d.ts +++ b/apps/demos/Demos/Localization/UsingIntl/Angular/app/messages.d.ts @@ -1,9 +1,9 @@ -declare module 'npm:devextreme/localization/messages/de.json!json'{ +declare module 'npm:devextreme/localization/messages/de.json!json' { const json: object; export = json; } -declare module 'npm:devextreme/localization/messages/ru.json!json'{ +declare module 'npm:devextreme/localization/messages/ru.json!json' { const json: object; export = json; } diff --git a/apps/demos/Demos/PivotGrid/SummaryDisplayModes/Angular/app/app.component.ts b/apps/demos/Demos/PivotGrid/SummaryDisplayModes/Angular/app/app.component.ts index e27e5d961685..8651275365fb 100644 --- a/apps/demos/Demos/PivotGrid/SummaryDisplayModes/Angular/app/app.component.ts +++ b/apps/demos/Demos/PivotGrid/SummaryDisplayModes/Angular/app/app.component.ts @@ -71,7 +71,7 @@ export class AppComponent { } prepareContextMenu(e: DxPivotGridTypes.ContextMenuPreparingEvent) { - if (e.field && e.field.dataField === 'amount') { + if (e.field?.dataField === 'amount') { this.summaryDisplayModes.forEach((mode) => { e.items.push({ text: mode.text, @@ -80,8 +80,7 @@ export class AppComponent { let format: string; const caption = mode.value === 'none' ? 'Total Sales' : 'Relative Sales'; - if (mode.value === 'none' - || mode.value === 'absoluteVariation') { + if (mode.value === 'none' || mode.value === 'absoluteVariation') { format = 'currency'; } this.pivotGridDataSource.field(e.field.index, { diff --git a/apps/demos/Demos/Scheduler/ContextMenu/React/App.tsx b/apps/demos/Demos/Scheduler/ContextMenu/React/App.tsx index daca502ff623..eaa9085a94db 100644 --- a/apps/demos/Demos/Scheduler/ContextMenu/React/App.tsx +++ b/apps/demos/Demos/Scheduler/ContextMenu/React/App.tsx @@ -65,8 +65,7 @@ const App = () => { }, ...resourceItems, ]); - } - , []); + }, []); const onCellContextMenu = useCallback((e: SchedulerTypes.CellContextMenuEvent) => { const scheduler = schedulerRef.current?.instance(); diff --git a/apps/demos/Demos/TreeList/AIColumns/Angular/app/ai/ai.service.ts b/apps/demos/Demos/TreeList/AIColumns/Angular/app/ai/ai.service.ts index 5d11318caa39..4d5f9bcb1498 100644 --- a/apps/demos/Demos/TreeList/AIColumns/Angular/app/ai/ai.service.ts +++ b/apps/demos/Demos/TreeList/AIColumns/Angular/app/ai/ai.service.ts @@ -42,7 +42,7 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal) { return result; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { diff --git a/apps/demos/Demos/TreeList/AIColumns/React/service.ts b/apps/demos/Demos/TreeList/AIColumns/React/service.ts index 7a4b196baeee..be3e939adb1f 100644 --- a/apps/demos/Demos/TreeList/AIColumns/React/service.ts +++ b/apps/demos/Demos/TreeList/AIColumns/React/service.ts @@ -33,7 +33,7 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal): Promis return result ?? ''; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { diff --git a/apps/demos/Demos/TreeList/AIColumns/ReactJs/service.js b/apps/demos/Demos/TreeList/AIColumns/ReactJs/service.js index 5f2d9d9a9b21..85caa8638d1e 100644 --- a/apps/demos/Demos/TreeList/AIColumns/ReactJs/service.js +++ b/apps/demos/Demos/TreeList/AIColumns/ReactJs/service.js @@ -21,7 +21,7 @@ async function getAIResponse(messages, signal) { const result = response.choices[0].message?.content; return result ?? ''; } -async function getAIResponseRecursive(messages, signal) { +function getAIResponseRecursive(messages, signal) { return getAIResponse(messages, signal).catch(async (error) => { if (!error.message.includes('Connection error')) { return Promise.reject(error); diff --git a/apps/demos/Demos/TreeList/AIColumns/Vue/service.ts b/apps/demos/Demos/TreeList/AIColumns/Vue/service.ts index f3cd2e3bf6d1..c1b2b0e75d6b 100644 --- a/apps/demos/Demos/TreeList/AIColumns/Vue/service.ts +++ b/apps/demos/Demos/TreeList/AIColumns/Vue/service.ts @@ -41,7 +41,7 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal) { return result; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { diff --git a/apps/demos/eslint.config.mjs b/apps/demos/eslint.config.mjs index 7f0a3f8908a2..8d2f6762e8c9 100644 --- a/apps/demos/eslint.config.mjs +++ b/apps/demos/eslint.config.mjs @@ -1,6 +1,9 @@ import globals from 'globals'; import babelParser from '@babel/eslint-parser'; -import spellcheckDevextreme from 'eslint-config-devextreme/spell-check.js'; +import spellcheckDevextreme from 'eslint-config-devextreme/spell-check'; +import testcafeConfig from 'eslint-config-devextreme/testcafe'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; +import javascriptConfig from 'eslint-config-devextreme/javascript'; import spellcheckPlugin from 'eslint-plugin-spellcheck'; import noOnlyTests from 'eslint-plugin-no-only-tests'; import deprecation from 'eslint-plugin-deprecation'; @@ -8,6 +11,7 @@ import reactPlugin from 'eslint-plugin-react'; import reactHooks from 'eslint-plugin-react-hooks'; import reactPerf from 'eslint-plugin-react-perf'; import jest from 'eslint-plugin-jest'; +import vuePlugin from 'eslint-plugin-vue'; import vueParser from 'vue-eslint-parser'; import tsParser from '@typescript-eslint/parser'; import tsPlugin from '@typescript-eslint/eslint-plugin'; @@ -28,7 +32,7 @@ const compat = new FlatCompat({ allConfig: js.configs.all }); -const spellcheckRule = spellcheckDevextreme.rules['spellcheck/spell-checker']; +const spellcheckRule = spellcheckDevextreme[0].rules['spellcheck/spell-checker']; export default [ { @@ -76,13 +80,13 @@ export default [ }, }, - ...compat.extends('eslint:recommended', 'devextreme/spell-check'), - - ...compat.extends('devextreme/javascript').map(config => ({ + js.configs.recommended, + ...spellcheckDevextreme, + ...javascriptConfig.map(config => ({ ...config, rules: changeRulesToStylistic(config.rules || {}), })), - ...compat.extends('devextreme/typescript').map(config => ({ + ...typescriptConfig.map(config => ({ ...config, files: ['**/*.ts', '**/*.tsx'], rules: changeRulesToStylistic(config.rules || {}), @@ -257,6 +261,7 @@ export default [ '@typescript-eslint/ban-ts-comment': 0, '@typescript-eslint/no-extraneous-class': 0, '@typescript-eslint/no-floating-promises': 0, + '@typescript-eslint/only-throw-error': 'warn', }, }, @@ -369,7 +374,7 @@ export default [ }, // Vue demos - ...compat.extends('plugin:vue/vue3-recommended').map(config => ({ + ...vuePlugin.configs['flat/recommended'].map(config => ({ ...config, files: [ 'Demos/**/Vue/*.vue', @@ -466,9 +471,13 @@ export default [ }, // testcafe tests - ...compat.extends('devextreme/testcafe').map(config => ({ + ...testcafeConfig.map(config => ({ ...config, - rules: changeRulesToStylistic(config.rules || {}), + rules: { + ...changeRulesToStylistic(config.rules || {}), + 'require-await': 'warn', + + }, files: ['testing/**/*.{js,ts}', 'utils/visual-tests/**/*.*'], })), @@ -501,7 +510,25 @@ export default [ // utils directory { files: [ - 'utils/**/*.{js,ts}', + 'utils/**/*.js', + ], + ignores: [ + 'utils/testing/', + 'utils/visual-tests/', + 'utils/templates/', + ], + rules: { + 'no-console': 0, + 'no-await-in-loop': 0, + 'no-restricted-syntax': 0, + '@typescript-eslint/await-thenable': 0, + 'spellcheck/spell-checker': 0, + 'consistent-return': 0, + }, + }, + { + files: [ + 'utils/**/*.ts', ], ignores: [ 'utils/testing/', @@ -510,7 +537,7 @@ export default [ ], languageOptions: { parserOptions: { - projectService: true, + project: './tsconfig.json', }, }, rules: { diff --git a/apps/demos/package.json b/apps/demos/package.json index 7b63e4552b87..8d57987a4a8a 100644 --- a/apps/demos/package.json +++ b/apps/demos/package.json @@ -125,7 +125,8 @@ "eslint-plugin-no-only-tests": "catalog:", "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "5.2.0", - "eslint-plugin-react-perf": "3.3.2", + "eslint-plugin-react-perf": "3.3.3", + "eslint-plugin-vue": "catalog:", "express": "4.22.0", "glob": "11.1.0", "globals": "catalog:", @@ -152,6 +153,7 @@ "testcafe": "3.7.2", "testcafe-reporter-spec-time": "4.0.0", "ts-node": "10.9.2", + "vue-eslint-parser": "catalog:", "vue-tsc": "3.0.8" }, "scripts": { diff --git a/apps/demos/testing/widgets/fileuploader/CustomDropzone.test.ts b/apps/demos/testing/widgets/fileuploader/CustomDropzone.test.ts index fa910fedb3f6..b23c69e1e6ce 100644 --- a/apps/demos/testing/widgets/fileuploader/CustomDropzone.test.ts +++ b/apps/demos/testing/widgets/fileuploader/CustomDropzone.test.ts @@ -15,11 +15,14 @@ runManualTest('FileUploader', 'CustomDropzone', (test) => { const triggerDragEnter = async (dropZoneSelector, items) => { await ClientFunction(() => { // @ts-expect-error $ is not typed + // eslint-disable-next-line no-undef const $dropZone = $(dropZoneSelector); const { left, top } = $dropZone.offset(); // @ts-expect-error $ is not typed + // eslint-disable-next-line no-undef $dropZone.trigger($.Event('dragenter', { // @ts-expect-error $ is not typed + // eslint-disable-next-line no-undef originalEvent: $.Event('dragenter', { dataTransfer: { items, diff --git a/apps/demos/utils/create-bundles/index.ts b/apps/demos/utils/create-bundles/index.ts index 67b335220bec..9502f0fe54cd 100644 --- a/apps/demos/utils/create-bundles/index.ts +++ b/apps/demos/utils/create-bundles/index.ts @@ -61,6 +61,7 @@ async function processBatch(bundler: ESBundler, demos: Demo[]) { await Promise.all(promises); } +// eslint-disable-next-line require-await async function processDemo(bundler: ESBundler, demo: Demo) { return new Promise((res) => { bundler.buildDemo(demo, res); diff --git a/apps/demos/utils/ts-to-js-converter/converter.ts b/apps/demos/utils/ts-to-js-converter/converter.ts index 4101fe599c6e..b56d1bf6ff4a 100644 --- a/apps/demos/utils/ts-to-js-converter/converter.ts +++ b/apps/demos/utils/ts-to-js-converter/converter.ts @@ -78,6 +78,7 @@ const pipeSource = async ( })); }; +// eslint-disable-next-line require-await const execTsc = async (directory: string, args: string): Promise => new Promise((resolve, reject) => { cps.exec(`tsc ${args}`, (error, stdout, stderr) => { if (error != null) { @@ -140,6 +141,7 @@ const strip = async (resolve: PathResolvers, log: Logger) => { }); }; +// eslint-disable-next-line require-await const replaceInFiles = async (filenamePatterns: string[], replacementCallback: (string) => string, resolvePath: (string) => string, log: Logger) => ( Promise.all( filenamePatterns.map(async (pattern) => { diff --git a/e2e/bundlers/package.json b/e2e/bundlers/package.json index 82e164e2e4c2..f573bb7b1b08 100644 --- a/e2e/bundlers/package.json +++ b/e2e/bundlers/package.json @@ -23,7 +23,7 @@ "@eslint/eslintrc": "catalog:", "@stylistic/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", - "eslint-config-devextreme": "1.1.6", + "eslint-config-devextreme": "catalog:", "eslint-plugin-i18n": "catalog:", "eslint-plugin-import": "catalog:", "eslint-plugin-no-only-tests": "catalog:", diff --git a/e2e/compilation-cases/package.json b/e2e/compilation-cases/package.json index 81aeabde1e02..d6edda098cc7 100644 --- a/e2e/compilation-cases/package.json +++ b/e2e/compilation-cases/package.json @@ -17,7 +17,7 @@ "@stylistic/eslint-plugin": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", - "eslint-config-devextreme": "1.1.6", + "eslint-config-devextreme": "catalog:", "eslint-migration-utils": "workspace:*", "eslint-plugin-i18n": "catalog:", "eslint-plugin-import": "catalog:", diff --git a/e2e/testcafe-devextreme/docker/run-testcafe.js b/e2e/testcafe-devextreme/docker/run-testcafe.js index 47ca78db8acc..a7d9bca09658 100644 --- a/e2e/testcafe-devextreme/docker/run-testcafe.js +++ b/e2e/testcafe-devextreme/docker/run-testcafe.js @@ -30,6 +30,7 @@ const matrix = [ ]; (async() => { + // eslint-disable-next-line no-undef const parsedArgs = parseArgs(process.argv); const componentFolderName = parsedArgs.componentFolder; let testParts = matrix; @@ -45,7 +46,7 @@ const matrix = [ // eslint-disable-next-line no-restricted-syntax for (const { name, ...args } of testParts) { - // eslint-disable-next-line no-console + // eslint-disable-next-line no-console,no-undef console.log(`Started test: ${name}`); const startupParams = Object.entries(args).map(([key, value]) => `--${key}=${value}`); diff --git a/e2e/testcafe-devextreme/eslint.config.mjs b/e2e/testcafe-devextreme/eslint.config.mjs index 719d698b6df2..232738cff5e5 100644 --- a/e2e/testcafe-devextreme/eslint.config.mjs +++ b/e2e/testcafe-devextreme/eslint.config.mjs @@ -9,6 +9,9 @@ import js from '@eslint/js'; import { FlatCompat as FlatCompatibility } from '@eslint/eslintrc'; import stylistic from '@stylistic/eslint-plugin'; import { changeRulesToStylistic } from 'eslint-migration-utils'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; +import testcafeConfig from 'eslint-config-devextreme/testcafe'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -24,8 +27,8 @@ export default [ 'node_modules/**', ], }, - ...compatibility.extends('devextreme/spell-check'), - ...compatibility.extends('devextreme/testcafe'), + ...spellCheckConfig, + ...testcafeConfig, { plugins: { 'no-only-tests': noOnlyTests, @@ -128,7 +131,6 @@ export default [ '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', { @@ -155,7 +157,7 @@ export default [ 'import/no-duplicates': 2, } }, - ...compatibility.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.ts?(x)'], @@ -216,10 +218,11 @@ export default [ 'no-await-in-loop': 'off', '@stylistic/no-extra-parens': 'off', '@typescript-eslint/require-await': 'off', - '@typescript-eslint/no-base-to-string': 'off' + '@typescript-eslint/no-base-to-string': 'off', + 'require-await': 'off', }, }, - ...compatibility.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.d.ts'], diff --git a/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts b/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts index 3bb680d4412b..3bdb4c121002 100644 --- a/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts +++ b/e2e/testcafe-devextreme/helpers/callbackTestHelper.ts @@ -1,7 +1,6 @@ import { ClientFunction } from 'testcafe'; -type WindowCallbackExtended = - Window +type WindowCallbackExtended = Window & typeof globalThis & { clientTesting?: { 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/domUtils.ts b/e2e/testcafe-devextreme/helpers/domUtils.ts index a9660621d922..b0f13add13e0 100644 --- a/e2e/testcafe-devextreme/helpers/domUtils.ts +++ b/e2e/testcafe-devextreme/helpers/domUtils.ts @@ -35,7 +35,7 @@ export const getStyleAttribute = ClientFunction((selector) => { export const setStyleAttribute = ClientFunction((selector, styleValue) => { const element = selector(); - const styles = element.getAttribute('style') || ''; + const styles = element.getAttribute('style') ?? ''; const updatedStyles = `${styles} ${styleValue}`; element.setAttribute('style', updatedStyles); @@ -44,7 +44,7 @@ export const setStyleAttribute = ClientFunction((selector, styleValue) => { export const setClassAttribute = ClientFunction((selector, styleValue) => { const element = selector(); - const styles = element.getAttribute('class') || ''; + const styles = element.getAttribute('class') ?? ''; const updatedClasses = `${styles} ${styleValue}`; element.setAttribute('class', updatedClasses); @@ -53,7 +53,7 @@ export const setClassAttribute = ClientFunction((selector, styleValue) => { export const removeClassAttribute = ClientFunction((selector, styleValue) => { const element = selector(); - const styles = element.getAttribute('class') || ''; + const styles = element.getAttribute('class') ?? ''; const updatedClasses = `${styles.replace(styleValue, '')}`; element.setAttribute('class', updatedClasses); diff --git a/e2e/testcafe-devextreme/helpers/shadowDom/shadowDomExtension.js b/e2e/testcafe-devextreme/helpers/shadowDom/shadowDomExtension.js index 2554f7e65a24..8855aaf57fdf 100644 --- a/e2e/testcafe-devextreme/helpers/shadowDom/shadowDomExtension.js +++ b/e2e/testcafe-devextreme/helpers/shadowDom/shadowDomExtension.js @@ -1,4 +1,4 @@ - +/* eslint-disable no-undef */ function getRoot() { return document.querySelector('#parentContainer').shadowRoot; } diff --git a/e2e/testcafe-devextreme/helpers/widgetTypings.ts b/e2e/testcafe-devextreme/helpers/widgetTypings.ts index 01ee9cacedda..7f62637b0d4b 100644 --- a/e2e/testcafe-devextreme/helpers/widgetTypings.ts +++ b/e2e/testcafe-devextreme/helpers/widgetTypings.ts @@ -1,8 +1,7 @@ import type { Properties as DataGridProperties } from 'devextreme/ui/data_grid'; import type { Properties as FilterBuilderProperties } from 'devextreme/ui/filter_builder'; -export type WidgetName = - 'dxAccordion' +export type WidgetName = 'dxAccordion' | 'dxAutocomplete' | 'dxGallery' | 'dxButtonGroup' diff --git a/e2e/testcafe-devextreme/package.json b/e2e/testcafe-devextreme/package.json index f018c495f599..dc78d1c157d2 100644 --- a/e2e/testcafe-devextreme/package.json +++ b/e2e/testcafe-devextreme/package.json @@ -27,7 +27,7 @@ "@stylistic/eslint-plugin": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", - "eslint-config-devextreme": "1.1.6", + "eslint-config-devextreme": "catalog:", "eslint-migration-utils": "workspace:*", "eslint-plugin-i18n": "catalog:", "eslint-plugin-import": "catalog:", diff --git a/e2e/testcafe-devextreme/runner.ts b/e2e/testcafe-devextreme/runner.ts index a738c017c205..f0745b919cfa 100644 --- a/e2e/testcafe-devextreme/runner.ts +++ b/e2e/testcafe-devextreme/runner.ts @@ -274,7 +274,7 @@ async function main() { await t.hover('html'); - const [width, height] = meta?.browserSize || DEFAULT_BROWSER_SIZE; + const [width, height] = meta?.browserSize ?? DEFAULT_BROWSER_SIZE; await t.resizeWindow(width, height); } else { await loadAxeCore(t); diff --git a/e2e/testcafe-devextreme/tests/common/pivotGrid/contextMenu.ts b/e2e/testcafe-devextreme/tests/common/pivotGrid/contextMenu.ts index 7090b90b9666..54e81eae0b3e 100644 --- a/e2e/testcafe-devextreme/tests/common/pivotGrid/contextMenu.ts +++ b/e2e/testcafe-devextreme/tests/common/pivotGrid/contextMenu.ts @@ -38,7 +38,7 @@ test.meta({ themes: [Themes.genericLight] })('ContextMenu width should be adjust visible: true, }, onContextMenuPreparing(e) { - if (e.field && e.field.dataField === 'amount') { + if (e.field?.dataField === 'amount') { const menuItems = [] as any; e.items.push({ text: 'Summary Type', items: menuItems }); diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/columnReordering.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/columnReordering.ts index 70c9de3bdcf3..2ad83d701712 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/columnReordering.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/columnReordering.ts @@ -15,7 +15,7 @@ const getVisibleColumns = (dataGrid: DataGrid): Promise => { return ClientFunction( () => (getInstance() as any) .getVisibleColumns() - .map((column: any) => column.dataField || column.name), + .map((column: any) => column.dataField ?? column.name), { dependencies: { getInstance } }, )(); }; 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/packages/devextreme-angular/eslint.config.mjs b/packages/devextreme-angular/eslint.config.mjs index 4329f24fda04..f2d90d5ea364 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) diff --git a/packages/devextreme-angular/package.json b/packages/devextreme-angular/package.json index 090c18f9f841..ca18af5e9268 100644 --- a/packages/devextreme-angular/package.json +++ b/packages/devextreme-angular/package.json @@ -49,7 +49,7 @@ "css-loader": "6.10.0", "devextreme-metadata": "workspace:*", "eslint": "catalog:", - "eslint-config-devextreme": "1.1.5", + "eslint-config-devextreme": "catalog:", "eslint-plugin-import": "catalog:", "eslint-migration-utils": "workspace:*", "jasmine": "5.12.0", diff --git a/packages/devextreme-angular/tests/src/server/ssr-components.spec.ts b/packages/devextreme-angular/tests/src/server/ssr-components.spec.ts index f5cc3fa8e576..54060939189b 100644 --- a/packages/devextreme-angular/tests/src/server/ssr-components.spec.ts +++ b/packages/devextreme-angular/tests/src/server/ssr-components.spec.ts @@ -52,6 +52,7 @@ describe('Universal', () => { expect(fixture.detectChanges.bind(fixture)).not.toThrow(); }); + // eslint-disable-next-line require-await it('should not throw error if core/renderer is called (T1255582)', async () => { TestBed.overrideComponent(TestContainerComponent, { set: { diff --git a/packages/devextreme-react/eslint.config.mjs b/packages/devextreme-react/eslint.config.mjs index aaa5789b3f4d..3717f651250d 100644 --- a/packages/devextreme-react/eslint.config.mjs +++ b/packages/devextreme-react/eslint.config.mjs @@ -8,6 +8,8 @@ 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); @@ -24,7 +26,7 @@ export default [ '**/__tests__/**', ], }, - ...compat.extends('devextreme/spell-check').map(config => { + ...spellCheckConfig.map(config => { const newConfig = { ...config @@ -156,7 +158,6 @@ export default [ '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', { @@ -186,7 +187,7 @@ export default [ }, }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.ts?(x)'], @@ -202,9 +203,6 @@ export default [ { files: ['**/*.ts?(x)'], ignores: ['**/*.d.ts'], - plugins: { - '@stylistic': stylistic, - }, languageOptions: { parser: tsParser, ecmaVersion: 6, @@ -239,7 +237,7 @@ export default [ '@typescript-eslint/naming-convention': 'off', }, }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.d.ts'], @@ -253,9 +251,6 @@ export default [ }), { files: ['**/*.d.ts'], - plugins: { - '@stylistic': stylistic, - }, languageOptions: { parser: tsParser, ecmaVersion: 6, diff --git a/packages/devextreme-react/package.json b/packages/devextreme-react/package.json index 265ad622d18a..054e20d939be 100644 --- a/packages/devextreme-react/package.json +++ b/packages/devextreme-react/package.json @@ -83,7 +83,7 @@ "eslint-plugin-import": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", - "eslint-config-devextreme": "1.1.6" + "eslint-config-devextreme": "catalog:" }, "publishConfig": { "directory": "npm", diff --git a/packages/devextreme-react/src/core/configuration/comparer.ts b/packages/devextreme-react/src/core/configuration/comparer.ts index 2ec29c0addf7..9770d81339d4 100644 --- a/packages/devextreme-react/src/core/configuration/comparer.ts +++ b/packages/devextreme-react/src/core/configuration/comparer.ts @@ -134,6 +134,7 @@ function compareCollections( Object.keys(current.configCollections).forEach((key) => { const currentCollection = current.configCollections[key]; const prevCollection = prev.configCollections[key] || []; + // eslint-disable-next-line @typescript-eslint/prefer-optional-chain if (!currentCollection || currentCollection.length !== prevCollection.length) { const updatedCollection: Record[] = []; currentCollection.forEach( diff --git a/packages/devextreme-react/src/core/use-option-scanning.ts b/packages/devextreme-react/src/core/use-option-scanning.ts index 34fcdb8a715d..c112ee720b52 100644 --- a/packages/devextreme-react/src/core/use-option-scanning.ts +++ b/packages/devextreme-react/src/core/use-option-scanning.ts @@ -16,9 +16,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 eeaa9bd53761..8d90e28cd4d2 100644 --- a/packages/devextreme-react/src/core/widget-config.ts +++ b/packages/devextreme-react/src/core/widget-config.ts @@ -15,7 +15,7 @@ const internalProps: InternalProps = { defaults: {}, templateProps: [], expectedChildren: {}, - // eslint-disable-next-line spellcheck/spell-checker + subscribableOptions: [], independentEvents: [], useRequestAnimationFrameFlag: false, @@ -48,10 +48,10 @@ function separateProps( defaultsProps: Record, templateProps: ITemplateMeta[], ): { - options: Record; - defaults: Record; - templates: Record; - } { + options: Record; + defaults: Record; + templates: Record; +} { // eslint-disable-next-line no-param-reassign templateProps = templateProps || []; const defaults: Record = {}; diff --git a/packages/devextreme-themebuilder/package.json b/packages/devextreme-themebuilder/package.json index 96fe881350d8..bf49e43126ce 100644 --- a/packages/devextreme-themebuilder/package.json +++ b/packages/devextreme-themebuilder/package.json @@ -36,7 +36,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..aa995fb4af68 100644 --- a/packages/devextreme-vue/eslint.config.mjs +++ b/packages/devextreme-vue/eslint.config.mjs @@ -1,4 +1,3 @@ -import { FlatCompat } from '@eslint/eslintrc'; import js from "@eslint/js"; import tsParser from "@typescript-eslint/parser"; import babelParser from '@babel/eslint-parser'; @@ -10,10 +9,11 @@ import { rules as stylisticRules } from '@eslint-stylistic/metadata'; import stylistic from '@stylistic/eslint-plugin'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const compat = new FlatCompat({ baseDirectory: __dirname }); const REMOVED_TYPESCRIPT_RULES = ['@typescript-eslint/no-throw-literal', '@typescript-eslint/ban-types']; @@ -34,7 +34,7 @@ const processDevExtremeRules = devExtremeRules => ( ); export default [ - ...compat.extends('devextreme/spell-check'), + ...spellCheckConfig, { ignores: ['metadata/*'], plugins: { @@ -42,7 +42,6 @@ export default [ spellcheck, 'no-only-tests': noOnlyTests, i18n: i18N, - '@stylistic': stylistic, }, }, { @@ -126,7 +125,7 @@ export default [ "import/no-duplicates": "error", }, }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.ts?(x)'], @@ -179,7 +178,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 9f19a6be7b02..f9c5ca72f597 100644 --- a/packages/devextreme-vue/package.json +++ b/packages/devextreme-vue/package.json @@ -66,7 +66,7 @@ "@vue/test-utils": "2.0.0-beta.7", "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", "jest-environment-jsdom": "29.7.0", "ts-jest": "29.1.3", @@ -79,9 +79,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/eslint.config.mjs b/packages/devextreme/eslint.config.mjs index afed54ff8c15..03ba17a3e76b 100644 --- a/packages/devextreme/eslint.config.mjs +++ b/packages/devextreme/eslint.config.mjs @@ -14,6 +14,9 @@ import simpleImportSort from 'eslint-plugin-simple-import-sort'; import { changeRulesToStylistic } from 'eslint-migration-utils'; import unicorn from 'eslint-plugin-unicorn'; import customRules from './eslint_plugins/index.js'; +import spellCheckConfig from 'eslint-config-devextreme/spell-check'; +import typescriptConfig from 'eslint-config-devextreme/typescript'; +import qunitConfig from 'eslint-config-devextreme/qunit'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -43,7 +46,7 @@ export default [ 'js/common/core/localization/default_messages.js', ], }, - ...compat.extends('devextreme/spell-check'), + ...spellCheckConfig, { plugins: { 'no-only-tests': noOnlyTests, @@ -174,7 +177,7 @@ export default [ 'import': importPlugin, } }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.ts?(x)'], @@ -219,9 +222,14 @@ export default [ considerDefaultExhaustiveForUnions: true, }], 'devextreme-custom/no-direct-preact-signals-core-import': 'error', + // TODO Shakhova: remove after fixing issues + '@typescript-eslint/prefer-nullish-coalescing': 'warn', + '@typescript-eslint/only-throw-error': 'warn', + '@typescript-eslint/prefer-optional-chain': 'warn', + 'require-await': 'warn', }, }, - ...compat.extends('devextreme/typescript').map(config => { + ...typescriptConfig.map(config => { const newConfig = { ...config, files: ['**/*.d.ts'], @@ -258,10 +266,11 @@ export default [ 'i18n/no-russian-character': ['error', { includeIdentifier: true, }], + '@typescript-eslint/no-unused-vars': 'off' } }, // Rules for QUnit tests - ...compat.extends('devextreme/qunit').map(config => ({ + ...qunitConfig.map(config => ({ ...config, files: ['testing/tests/**/*.js', 'testing/helpers/**/*.js'], })), 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 f88e49893b47..478b2fb2d047 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/state_manager/dev/types.ts b/packages/devextreme/js/__internal/core/state_manager/dev/types.ts index b852ff4d782c..83666ac6523e 100644 --- a/packages/devextreme/js/__internal/core/state_manager/dev/types.ts +++ b/packages/devextreme/js/__internal/core/state_manager/dev/types.ts @@ -95,8 +95,10 @@ export interface Logger { export type DevToolsActions = 'DISPATCH' | 'JUMP_TO_STATE' | 'JUMP_TO_ACTION' | 'COMMIT' | 'RESET'; -export type DevToolsExternalActionCallback = -(action: DevToolsActions, payload: ComponentState | null) => void; +export type DevToolsExternalActionCallback = ( + action: DevToolsActions, + payload: ComponentState | null +) => void; export interface DevToolsConnector { connect: (options?: Record) => void; 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/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/grids/grid_core/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts index 80b32d88c50e..4c3a60d3cbaa 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 @@ -2484,8 +2484,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 65c8ec627b98..86fb3950b870 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 e00697e998f5..87e0fb450b17 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/m_types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/m_types.ts @@ -24,10 +24,9 @@ export interface ColumnPoint { } // todo: move to upper .d.ts -type OptionsMethod = - (() => TOptions) & - ((options: TOptions) => void) & - ( +type OptionsMethod = (() => TOptions) + & ((options: TOptions) => void) + & ( ( optionName: TPropertyName ) => GridPropertyType @@ -86,24 +85,24 @@ export interface InternalGrid extends GridBaseType { } type TemporarlyOptionsTakenFromDataGrid = Pick; type TemporarlyOptionsTakenFromTreeList = Pick; interface InternalSelection extends SelectionBase { alwaysSelectByShift?: boolean; @@ -132,28 +131,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 6affab895e8e..88a1c4c320d4 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..0ba6ec47991e 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' 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/inferno_wrappers/tree_view.ts b/packages/devextreme/js/__internal/grids/new/grid_core/inferno_wrappers/tree_view.ts index 180abc9bb0f9..d9f1b5c62cd9 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/inferno_wrappers/tree_view.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/inferno_wrappers/tree_view.ts @@ -7,9 +7,9 @@ import { InfernoWrapper } from './widget_wrapper'; export class TreeView< TItem extends TreeViewItemProperties = TreeViewItemProperties, > extends InfernoWrapper< - TreeViewProperties, - dxTreeView -> { + TreeViewProperties, + dxTreeView + > { protected getComponentFabric(): typeof dxTreeView { return dxTreeView; } 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 74e6f67a2962..08c1d9610969 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 @@ -9,18 +9,18 @@ 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; - } - }(extend(true, {}, options)); + return extend(true, {}, baseDefaultOptions, defaultOptions) as TDefaultProps; + } +}(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/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/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/common/shift_intervals.ts b/packages/devextreme/js/__internal/scheduler/view_model/common/shift_intervals.ts index 38c20a02e7a9..cd870799c0cd 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/common/shift_intervals.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/common/shift_intervals.ts @@ -4,7 +4,7 @@ export const shiftIntervals = ( intervals: T[], viewOffset: number, ): T[] => intervals.map((interval) => ({ - ...interval, - min: interval.min + viewOffset, - max: interval.max + viewOffset, - })); + ...interval, + min: interval.min + viewOffset, + max: interval.max + viewOffset, +})); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/filtration/filter_appointments.ts b/packages/devextreme/js/__internal/scheduler/view_model/filtration/filter_appointments.ts index 8f2304ddc979..f15c24f6bab6 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/filtration/filter_appointments.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/filtration/filter_appointments.ts @@ -13,19 +13,19 @@ import { splitByRecurrence } from './utils/split_by_recurrence/split_by_recurren const addDuration = ( entities: T[], ): (T & Duration)[] => entities.map((entity) => ({ - ...entity, - duration: entity.endDateUTC - entity.startDateUTC, - })); + ...entity, + duration: entity.endDateUTC - entity.startDateUTC, +})); const saveDatesBeforeSplit = ( entities: T[], ): (T & UTCDatesBeforeSplit)[] => entities.map((entity) => ({ - ...entity, - datesBeforeSplit: { - startDateUTC: entity.startDateUTC, - endDateUTC: entity.endDateUTC, - }, - })); + ...entity, + datesBeforeSplit: { + startDateUTC: entity.startDateUTC, + endDateUTC: entity.endDateUTC, + }, +})); export const filterAppointments = ( schedulerStore: Scheduler, diff --git a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/add_all_day_panel_occupation.ts b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/add_all_day_panel_occupation.ts index 91eee81d13e5..b2d5d0b884e1 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/add_all_day_panel_occupation.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/add_all_day_panel_occupation.ts @@ -5,17 +5,17 @@ export const addAllDayPanelOccupation = ( entities: T[], { supportAllDayPanel, allDayPanelMode }: FilterOptions, ): (T & AllDayPanelOccupation)[] => entities.map((entity) => { - const isAllDayPanelOccupied = supportAllDayPanel && isAppointmentTakesAllDay( - { - allDay: entity.allDay, - startDate: new Date(entity.source.startDate), - endDate: new Date(entity.source.endDate), - }, - allDayPanelMode, - ); + const isAllDayPanelOccupied = supportAllDayPanel && isAppointmentTakesAllDay( + { + allDay: entity.allDay, + startDate: new Date(entity.source.startDate), + endDate: new Date(entity.source.endDate), + }, + allDayPanelMode, + ); - return { - ...entity, - isAllDayPanelOccupied, - }; - }); + return { + ...entity, + isAllDayPanelOccupied, + }; +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_attributes/filter_by_attributes.ts b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_attributes/filter_by_attributes.ts index 43c49a114b79..87535e76a4ce 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_attributes/filter_by_attributes.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_attributes/filter_by_attributes.ts @@ -5,19 +5,19 @@ export const filterByAttributes = entities.filter((appointment): boolean => { - if (!appointment.visible) { - return false; - } + if (!appointment.visible) { + return false; + } - const allDayPanelAppointmentHidden = Boolean( - supportAllDayPanel + const allDayPanelAppointmentHidden = Boolean( + supportAllDayPanel && !showAllDayPanel && appointment.isAllDayPanelOccupied, - ); - if (allDayPanelAppointmentHidden) { - return false; - } + ); + if (allDayPanelAppointmentHidden) { + return false; + } - const resources = resourceManager.groupResources(); - return isAppointmentMatchedResources(appointment.itemData, resources); - }); + const resources = resourceManager.groupResources(); + return isAppointmentMatchedResources(appointment.itemData, resources); +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_intervals/filter_by_intervals.ts b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_intervals/filter_by_intervals.ts index 6ce6f8d68534..dc8643f71e05 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_intervals/filter_by_intervals.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_intervals/filter_by_intervals.ts @@ -33,15 +33,15 @@ export const filterByIntervals = ( entities: T[], options: FilterOptions, ): T[] => entities.filter((appointment) => { - const intervals = getIntervals(appointment, options); - // NOTE: if all day appointment ends at 00:00 make it longer to occupy next interval - const fixedAppointment = { ...appointment }; - if (appointment.allDay) { - fixedAppointment.endDateUTC += 1; - } + const intervals = getIntervals(appointment, options); + // NOTE: if all day appointment ends at 00:00 make it longer to occupy next interval + const fixedAppointment = { ...appointment }; + if (appointment.allDay) { + fixedAppointment.endDateUTC += 1; + } - return isAppointmentMatchedIntervals( - { startDate: fixedAppointment.startDateUTC, endDate: fixedAppointment.endDateUTC }, - intervals, - ); - }); + return isAppointmentMatchedIntervals( + { startDate: fixedAppointment.startDateUTC, endDate: fixedAppointment.endDateUTC }, + intervals, + ); +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_group_index.ts b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_group_index.ts index 5e9a10a6bf19..df44c85ac1d0 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_group_index.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_group_index.ts @@ -8,24 +8,24 @@ export const splitByGroupIndex = ( entities: T[], { resourceManager }: Pick, ): (T & GroupIndex)[] => entities - .reduce<(T & GroupIndex)[]>((result, entity) => { - if (resourceManager.groupsLeafs.length === 0) { - result.push({ ...entity, groupIndex: 0 }); - return result; - } + .reduce<(T & GroupIndex)[]>((result, entity) => { + if (resourceManager.groupsLeafs.length === 0) { + result.push({ ...entity, groupIndex: 0 }); + return result; + } - const groupValues = getAppointmentGroupValues( - entity.itemData, - resourceManager.resources, - ); - const groupIndexes = getAppointmentGroupIndex( - groupValues, - resourceManager.groupsLeafs, - ); + const groupValues = getAppointmentGroupValues( + entity.itemData, + resourceManager.resources, + ); + const groupIndexes = getAppointmentGroupIndex( + groupValues, + resourceManager.groupsLeafs, + ); - groupIndexes.forEach((groupIndex) => { - result.push({ ...entity, groupIndex }); - }); + groupIndexes.forEach((groupIndex) => { + result.push({ ...entity, groupIndex }); + }); - return result; - }, []); + return result; + }, []); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_recurrence/generate_recurrence_utc_dates.ts b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_recurrence/generate_recurrence_utc_dates.ts index e34697e82e5a..e2587cf09bd5 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_recurrence/generate_recurrence_utc_dates.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_recurrence/generate_recurrence_utc_dates.ts @@ -17,14 +17,14 @@ const WEEK_DAY_NUMBERS = [6, 0, 1, 2, 3, 4, 5]; export const generateRecurrenceUTCDates = < T extends Pick, >( - appointment: T, - { - firstDayOfWeek, - interval, - timeZone, - startDateTimeZone, - }: Options, - ): number[] => { + appointment: T, + { + firstDayOfWeek, + interval, + timeZone, + startDateTimeZone, + }: Options, +): number[] => { if (!appointment.hasRecurrenceRule || !appointment.recurrenceRule) { return [appointment.source.startDate]; } diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_agenda_view_model.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_agenda_view_model.ts index 057bcbd34246..ed11215b5b07 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_agenda_view_model.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/generate_agenda_view_model.ts @@ -13,21 +13,21 @@ import { splitByParts } from './steps/split_by_parts/split_by_parts'; const saveDatesAfterSplit = ( entities: T[], ): (T & UTCDatesAfterSplit)[] => entities.map((entity) => ({ - ...entity, - datesAfterSplit: { - startDateUTC: entity.startDateUTC, - endDateUTC: entity.endDateUTC, - }, - })); + ...entity, + datesAfterSplit: { + startDateUTC: entity.startDateUTC, + endDateUTC: entity.endDateUTC, + }, +})); const addAgendaGeometry = ( entities: T[], height: number, ): (T & AgendaGeometry)[] => entities.map((entity) => ({ - ...entity, - height, - width: '100%', - })); + ...entity, + height, + width: '100%', +})); export const generateAgendaViewModel = ( schedulerStore: Scheduler, diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector.ts index 0f7bb3f1b6a5..4d3c32ee8f91 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector.ts @@ -14,9 +14,9 @@ import type { CollectorOptions } from './types'; export const addCollector = < T extends ListEntity & Position & Duration & AppointmentPart & UTCDatesBeforeSplit, >( - entities: T[], - options: CollectorOptions, - ): (T & Level & AppointmentCollector)[] => { + entities: T[], + options: CollectorOptions, +): (T & Level & AppointmentCollector)[] => { const step1 = addLevel(entities, options); const step2 = addCollectorByLevel(step1, options); return step2; diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector_by_level.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector_by_level.ts index 0d51e46cba7e..07903f7ee03a 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector_by_level.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_collector/add_collector_by_level.ts @@ -11,50 +11,50 @@ import type { CollectorOptions } from './types'; const addEmptyCollector = ( entities: T[], ): (T & AppointmentCollector)[] => entities.map((entity) => ({ - ...entity, - items: [], - isCompact: false, - })); + ...entity, + items: [], + isCompact: false, +})); const groupByStart = ( entities: T[], cellsCount: number, ): T[][] => entities.reduce((result, entity) => { - result[entity.cellIndex].push(entity); - return result; - }, Array.from({ length: cellsCount }, () => [])); + result[entity.cellIndex].push(entity); + return result; +}, Array.from({ length: cellsCount }, () => [])); const groupByOccupation = ( entities: T[], cells: CollectorOptions['cells'], maxLevel: number, ): T[][] => entities.reduce((result, entity) => { - result[entity.cellIndex].push(entity); - for (let i = entity.cellIndex + 1; i <= entity.endCellIndex; i += 1) { - if (entity.level >= maxLevel) { - result[i].push({ - ...entity, - cellIndex: i, - endCellIndex: i, - startDateUTC: cells[i].min, - endDateUTC: cells[i].max, - columnIndex: cells[i].columnIndex, - rowIndex: cells[i].rowIndex, - }); - } + result[entity.cellIndex].push(entity); + for (let i = entity.cellIndex + 1; i <= entity.endCellIndex; i += 1) { + if (entity.level >= maxLevel) { + result[i].push({ + ...entity, + cellIndex: i, + endCellIndex: i, + startDateUTC: cells[i].min, + endDateUTC: cells[i].max, + columnIndex: cells[i].columnIndex, + rowIndex: cells[i].rowIndex, + }); } + } - return result; - }, Array.from({ length: cells.length }, () => [])); + return result; +}, Array.from({ length: cells.length }, () => [])); export const addCollectorByLevel = < T extends ListEntity & Level & Position & AppointmentPart & UTCDatesBeforeSplit, >( - entities: T[], - { - cells, isCompact, maxLevel, collectBy, - }: CollectorOptions, - ): (T & AppointmentCollector)[] => { + entities: T[], + { + cells, isCompact, maxLevel, collectBy, + }: CollectorOptions, +): (T & AppointmentCollector)[] => { if (maxLevel < 0) { return addEmptyCollector(entities); } diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_direction.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_direction.ts index 1726dfb0510f..d75b8175a7ce 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_direction.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_direction.ts @@ -5,6 +5,6 @@ export const addDirection = ( allDayPanelDirection: Direction['direction'], regularPanelDirection: Direction['direction'], ): (T & Direction)[] => entities.map((entity) => ({ - ...entity, - direction: entity.isAllDayPanelOccupied ? allDayPanelDirection : regularPanelDirection, - })); + ...entity, + direction: entity.isAllDayPanelOccupied ? allDayPanelDirection : regularPanelDirection, +})); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_emptiness.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_emptiness.ts index 37acb1c1dc1f..249b011ea7b3 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_emptiness.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_emptiness.ts @@ -12,15 +12,15 @@ export const addEmptiness = entities.map((entity) => { - const minSize = getMinAppointmentSize({ - ...options, - isAllDayAppointment: entity.allDay, - }); - - return { - ...entity, - empty: !entity.isAllDayPanelOccupied && ( - entity.height < minSize.height || entity.width < minSize.width - ), - }; + const minSize = getMinAppointmentSize({ + ...options, + isAllDayAppointment: entity.allDay, }); + + return { + ...entity, + empty: !entity.isAllDayPanelOccupied && ( + entity.height < minSize.height || entity.width < minSize.width + ), + }; +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_geometry/add_geometry.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_geometry/add_geometry.ts index eb96044c7f6c..1c41758d046f 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_geometry/add_geometry.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_geometry/add_geometry.ts @@ -38,13 +38,13 @@ export const addGeometry = ( entities: T[], options: GeometryOptions, ): (T & Geometry & AppointmentCollectorWithGeometry)[] => entities.map((rawEntity) => { - const { isAdaptivityEnabled, maxAppointmentsPerCell } = options; - const entity = isAdaptivityEnabled && maxAppointmentsPerCell === 0 - ? addAdaptivityGeometryInsideInterval(rawEntity, options) - : addGeometryInsideInterval(rawEntity, options); - addPanelOffset(entity, options); - addGroupingOffset(entity, options); - RTLSwap(entity, options); + const { isAdaptivityEnabled, maxAppointmentsPerCell } = options; + const entity = isAdaptivityEnabled && maxAppointmentsPerCell === 0 + ? addAdaptivityGeometryInsideInterval(rawEntity, options) + : addGeometryInsideInterval(rawEntity, options); + addPanelOffset(entity, options); + addGroupingOffset(entity, options); + RTLSwap(entity, options); - return entity; - }); + return entity; +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_position.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_position.ts index bbb0e5ec8a44..e515ea7c311d 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_position.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_position.ts @@ -9,21 +9,21 @@ export const addPosition = entities.map((entity) => { - const cellIndex = binarySearchCellIndex(cells, entity.startDateUTC); - let endCellIndex = cellIndex; - while ( - endCellIndex < cells.length - 1 + const cellIndex = binarySearchCellIndex(cells, entity.startDateUTC); + let endCellIndex = cellIndex; + while ( + endCellIndex < cells.length - 1 && entity.endDateUTC > cells[endCellIndex].max && entity.endDateUTC >= cells[endCellIndex + 1].min - ) { endCellIndex += 1; } + ) { endCellIndex += 1; } - return { - ...entity, - startDateUTC: Math.max(entity.startDateUTC, cells[cellIndex].min), - endDateUTC: Math.min(entity.endDateUTC, cells[endCellIndex].max), - cellIndex, - endCellIndex, - rowIndex: cells[cellIndex].rowIndex, - columnIndex: cells[cellIndex].columnIndex, - }; - }); + return { + ...entity, + startDateUTC: Math.max(entity.startDateUTC, cells[cellIndex].min), + endDateUTC: Math.min(entity.endDateUTC, cells[endCellIndex].max), + cellIndex, + endCellIndex, + rowIndex: cells[cellIndex].rowIndex, + columnIndex: cells[cellIndex].columnIndex, + }; +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_sorted_index.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_sorted_index.ts index 0aef054a2d51..5c1cac9a41aa 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_sorted_index.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/add_sorted_index.ts @@ -3,6 +3,6 @@ import type { SortedIndex } from '../../types'; export const addSortedIndex = ( entities: T[], ): (T & SortedIndex)[] => entities.map((entity, index) => ({ - ...entity, - sortedIndex: index, - })); + ...entity, + sortedIndex: index, +})); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts index de77bee852e5..99c414167557 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/steps/expand_all_day.ts @@ -44,53 +44,53 @@ export const expandAllDayAllDayPanel = entities.map((entity) => { - if (!entity.allDay) { - return entity; - } + if (!entity.allDay) { + return entity; + } - if (viewOffsetMs === 0) { - // NOTE: For case of start date higher than endDayHour: - // (0 hours) [startHour, endHour] (appointment start, end) (24 hours) - const minStartDate = new Date(entity.startDateUTC) - .setUTCHours(endDayHour, 0, 0, 0) + if (viewOffsetMs === 0) { + // NOTE: For case of start date higher than endDayHour: + // (0 hours) [startHour, endHour] (appointment start, end) (24 hours) + const minStartDate = new Date(entity.startDateUTC) + .setUTCHours(endDayHour, 0, 0, 0) - MINUTE_MS; - const maxEndDate = new Date(entity.endDateUTC) - .setUTCHours(endDayHour, 0, 0, 0) + const maxEndDate = new Date(entity.endDateUTC) + .setUTCHours(endDayHour, 0, 0, 0) - MINUTE_MS; - return { - ...entity, - startDateUTC: Math.min(entity.startDateUTC, minStartDate), - endDateUTC: maxEndDate, - }; - } - return { ...entity, - startDateUTC: getShiftedStartDate(entity.startDateUTC, viewOffsetMs), - endDateUTC: getShiftedEndDate(entity.endDateUTC, viewOffsetMs), + startDateUTC: Math.min(entity.startDateUTC, minStartDate), + endDateUTC: maxEndDate, }; - }); + } + + return { + ...entity, + startDateUTC: getShiftedStartDate(entity.startDateUTC, viewOffsetMs), + endDateUTC: getShiftedEndDate(entity.endDateUTC, viewOffsetMs), + }; +}); export const expandAllDayRegularPanel = >( entities: T[], ): T[] => entities.map((entity) => { - if (!entity.allDay) { - return entity; - } + if (!entity.allDay) { + return entity; + } - const startDate = new Date(entity.startDateUTC); - const endDate = new Date(entity.endDateUTC); - endDate.setDate(endDate.getDate() + 1); + const startDate = new Date(entity.startDateUTC); + const endDate = new Date(entity.endDateUTC); + endDate.setDate(endDate.getDate() + 1); - return { - ...entity, - endDateUTC: endDate - .setUTCHours( - startDate.getUTCHours(), - startDate.getUTCMinutes(), - startDate.getUTCSeconds(), - startDate.getUTCMilliseconds(), - ), - }; - }); + return { + ...entity, + endDateUTC: endDate + .setUTCHours( + startDate.getUTCHours(), + startDate.getUTCMinutes(), + startDate.getUTCSeconds(), + startDate.getUTCMilliseconds(), + ), + }; +}); diff --git a/packages/devextreme/js/__internal/scheduler/view_model/types.ts b/packages/devextreme/js/__internal/scheduler/view_model/types.ts index 892cb06dc850..1133b5fc5562 100644 --- a/packages/devextreme/js/__internal/scheduler/view_model/types.ts +++ b/packages/devextreme/js/__internal/scheduler/view_model/types.ts @@ -217,7 +217,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