diff --git a/.eslintrc.json b/.eslintrc.json index 847a599f..9c1d1c8f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -23,6 +23,22 @@ "no-console": "off", "react/jsx-props-no-spreading": "off", "react/require-default-props": "off", - "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }] + "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }], + "no-restricted-imports": ["error", { + "paths": [ + { + // We don't need "import React from 'react'" since React 17 + "name": "react", + "importNames": ["default"], + "message": "Do not import React, use import deconstruction instead" + } + ], + "patterns": [ + { + "group": ["@mui/material/*", "!@mui/material/colors"], + "message": "Please use `import { /*...*/ } from '@mui/material';` instead." + } + ] + }] } } diff --git a/src/components/CustomAGGrid/custom-aggrid.style.ts b/src/components/CustomAGGrid/custom-aggrid.style.ts index bb1613bd..a05b8f75 100644 --- a/src/components/CustomAGGrid/custom-aggrid.style.ts +++ b/src/components/CustomAGGrid/custom-aggrid.style.ts @@ -4,8 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Theme } from '@mui/material/styles/createTheme'; -import { SystemStyleObject } from '@mui/system/styleFunctionSx/styleFunctionSx'; +import { Theme } from '@mui/material'; +import { SystemStyleObject } from '@mui/system'; export const CUSTOM_AGGRID_THEME = 'custom-aggrid-theme'; diff --git a/src/components/CustomAGGrid/custom-aggrid.tsx b/src/components/CustomAGGrid/custom-aggrid.tsx index abb55ee5..1ea41b44 100644 --- a/src/components/CustomAGGrid/custom-aggrid.tsx +++ b/src/components/CustomAGGrid/custom-aggrid.tsx @@ -5,17 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { useCallback } from 'react'; -import { Theme } from '@mui/material/styles/createTheme'; +import { forwardRef, useCallback } from 'react'; +import { SxProps, Theme, useTheme } from '@mui/material'; import { AgGridReact, AgGridReactProps } from 'ag-grid-react'; import { useIntl } from 'react-intl'; import 'ag-grid-community/styles/ag-grid.css'; import 'ag-grid-community/styles/ag-theme-alpine.css'; import { ColumnResizedEvent, GetLocaleTextParams } from 'ag-grid-community'; import { Box } from '@mui/system'; -import { SxProps, useTheme } from '@mui/material'; import { mergeSx } from '../../utils/styles'; -import { styles, CUSTOM_AGGRID_THEME } from './custom-aggrid.style'; +import { CUSTOM_AGGRID_THEME, styles } from './custom-aggrid.style'; interface CustomAGGGridStyleProps { shouldHidePinnedHeaderRightBorder?: boolean; @@ -36,7 +35,7 @@ const onColumnResized = (params: ColumnResizedEvent) => { } }; -const CustomAGGrid = React.forwardRef( +const CustomAGGrid = forwardRef( (props, ref) => { const { shouldHidePinnedHeaderRightBorder = false, diff --git a/src/components/TreeViewFinder/TreeViewFinder.tsx b/src/components/TreeViewFinder/TreeViewFinder.tsx index 08a26057..4972fa2b 100644 --- a/src/components/TreeViewFinder/TreeViewFinder.tsx +++ b/src/components/TreeViewFinder/TreeViewFinder.tsx @@ -5,8 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { +import { ReactElement, + SyntheticEvent, useCallback, useEffect, useRef, @@ -24,8 +25,8 @@ import { DialogContent, DialogContentText, DialogTitle, - Typography, ModalProps, + Typography, } from '@mui/material'; import { TreeItem, TreeView, TreeViewClasses } from '@mui/x-tree-view'; @@ -232,7 +233,7 @@ function TreeViewFinder(props: TreeViewFinderProps) { }); }; - const handleNodeToggle = (_e: React.SyntheticEvent, nodeIds: string[]) => { + const handleNodeToggle = (_e: SyntheticEvent, nodeIds: string[]) => { // onTreeBrowse proc only on last node clicked and only when expanded nodeIds.every((nodeId) => { if (!expanded?.includes(nodeId)) { @@ -298,7 +299,7 @@ function TreeViewFinder(props: TreeViewFinderProps) { /* User Interaction management */ const handleNodeSelect = ( - _e: React.SyntheticEvent, + _e: SyntheticEvent, values: string | string[] ) => { // Default management diff --git a/src/components/dialogs/custom-mui-dialog.tsx b/src/components/dialogs/custom-mui-dialog.tsx index c67a573b..15000c13 100644 --- a/src/components/dialogs/custom-mui-dialog.tsx +++ b/src/components/dialogs/custom-mui-dialog.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React from 'react'; +import { MouseEvent, ReactNode } from 'react'; import { FieldErrors, UseFormReturn } from 'react-hook-form'; import { FormattedMessage } from 'react-intl'; import { @@ -27,14 +27,14 @@ interface ICustomMuiDialog { open: boolean; formSchema: yup.AnySchema; formMethods: UseFormReturn | MergedFormContextProps; - onClose: (event: React.MouseEvent) => void; + onClose: (event: MouseEvent) => void; onSave: (data: any) => void; onValidationError?: (errors: FieldErrors) => void; titleId: string; disabledSave?: boolean; removeOptional?: boolean; onCancel?: () => void; - children: React.ReactNode; + children: ReactNode; isDataFetching?: boolean; language?: string; } @@ -66,12 +66,12 @@ function CustomMuiDialog({ }: ICustomMuiDialog) { const { handleSubmit } = formMethods; - const handleCancel = (event: React.MouseEvent) => { + const handleCancel = (event: MouseEvent) => { onCancel?.(); onClose(event); }; - const handleClose = (event: React.MouseEvent, reason?: string) => { + const handleClose = (event: MouseEvent, reason?: string) => { if (reason === 'backdropClick' && onCancel) { onCancel(); } diff --git a/src/components/dialogs/popup-confirmation-dialog.tsx b/src/components/dialogs/popup-confirmation-dialog.tsx index 26ed036d..0d3c1b84 100644 --- a/src/components/dialogs/popup-confirmation-dialog.tsx +++ b/src/components/dialogs/popup-confirmation-dialog.tsx @@ -5,12 +5,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import Dialog from '@mui/material/Dialog'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import { DialogContentText } from '@mui/material'; -import DialogActions from '@mui/material/DialogActions'; -import Button from '@mui/material/Button'; +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, +} from '@mui/material'; import { FormattedMessage } from 'react-intl'; import CancelButton from '../inputs/react-hook-form/utils/cancel-button'; diff --git a/src/components/filter/criteria-based/criteria-based-filter-form.tsx b/src/components/filter/criteria-based/criteria-based-filter-form.tsx index ab9ca4fa..8a9b65b2 100644 --- a/src/components/filter/criteria-based/criteria-based-filter-form.tsx +++ b/src/components/filter/criteria-based/criteria-based-filter-form.tsx @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import Grid from '@mui/material/Grid'; +import { Grid } from '@mui/material'; import FilterProperties, { filterPropertiesYupSchema, } from './filter-properties'; diff --git a/src/components/filter/criteria-based/filter-properties.tsx b/src/components/filter/criteria-based/filter-properties.tsx index 7bcf089d..d54ec78e 100644 --- a/src/components/filter/criteria-based/filter-properties.tsx +++ b/src/components/filter/criteria-based/filter-properties.tsx @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import Grid from '@mui/material/Grid'; +import { Grid } from '@mui/material'; import { useEffect, useMemo } from 'react'; import { useWatch } from 'react-hook-form'; import { FormattedMessage } from 'react-intl'; diff --git a/src/components/filter/criteria-based/filter-property.tsx b/src/components/filter/criteria-based/filter-property.tsx index 8fce312b..81c5cd3f 100644 --- a/src/components/filter/criteria-based/filter-property.tsx +++ b/src/components/filter/criteria-based/filter-property.tsx @@ -5,14 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { useCallback, useMemo } from 'react'; +import { Grid, IconButton } from '@mui/material'; import DeleteIcon from '@mui/icons-material/Delete'; -import IconButton from '@mui/material/IconButton'; -import Grid from '@mui/material/Grid'; import { useFormContext, useWatch } from 'react-hook-form'; import AutocompleteInput from '../../inputs/react-hook-form/autocomplete-inputs/autocomplete-input'; import MultipleAutocompleteInput from '../../inputs/react-hook-form/autocomplete-inputs/multiple-autocomplete-input'; import FieldConstants from '../../../utils/field-constants'; - import { PredefinedProperties } from '../../../utils/types'; export const PROPERTY_NAME = 'name_property'; diff --git a/src/components/filter/expert/expert-filter-form.tsx b/src/components/filter/expert/expert-filter-form.tsx index 1083dc2c..30ace027 100644 --- a/src/components/filter/expert/expert-filter-form.tsx +++ b/src/components/filter/expert/expert-filter-form.tsx @@ -7,7 +7,7 @@ import { useCallback, useMemo } from 'react'; -import Grid from '@mui/material/Grid'; +import { Grid } from '@mui/material'; import type { RuleGroupTypeAny } from 'react-querybuilder'; import { formatQuery } from 'react-querybuilder'; import './styles-expert-filter.css'; diff --git a/src/components/filter/explicit-naming/explicit-naming-filter-form.tsx b/src/components/filter/explicit-naming/explicit-naming-filter-form.tsx index 129974ad..8b9da0dc 100644 --- a/src/components/filter/explicit-naming/explicit-naming-filter-form.tsx +++ b/src/components/filter/explicit-naming/explicit-naming-filter-form.tsx @@ -7,7 +7,7 @@ import { useCallback, useEffect, useMemo } from 'react'; import { useIntl } from 'react-intl'; import { useFormContext, useWatch } from 'react-hook-form'; -import Grid from '@mui/material/Grid'; +import { Grid } from '@mui/material'; import { ValueParserParams } from 'ag-grid-community'; import { v4 as uuid4 } from 'uuid'; import { UUID } from 'crypto'; diff --git a/src/components/filter/filter-form.tsx b/src/components/filter/filter-form.tsx index 0d15f979..61aa10c2 100644 --- a/src/components/filter/filter-form.tsx +++ b/src/components/filter/filter-form.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { useEffect } from 'react'; +import { ChangeEvent, useEffect } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; import { Grid } from '@mui/material'; import { UUID } from 'crypto'; @@ -43,7 +43,7 @@ function FilterForm(props: FilterFormProps) { // We do this because setValue don't set the field dirty const handleChange = ( - _event: React.ChangeEvent, + _event: ChangeEvent, value: string ) => { setValue(FieldConstants.FILTER_TYPE, value); diff --git a/src/components/inputs/react-hook-form/ag-grid-table/bottom-right-buttons.tsx b/src/components/inputs/react-hook-form/ag-grid-table/bottom-right-buttons.tsx index d661d1f2..6f4579aa 100644 --- a/src/components/inputs/react-hook-form/ag-grid-table/bottom-right-buttons.tsx +++ b/src/components/inputs/react-hook-form/ag-grid-table/bottom-right-buttons.tsx @@ -4,14 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Grid, Tooltip } from '@mui/material'; -import IconButton from '@mui/material/IconButton'; -import { ArrowCircleDown, ArrowCircleUp, Upload } from '@mui/icons-material'; -import AddIcon from '@mui/icons-material/ControlPoint'; -import DeleteIcon from '@mui/icons-material/Delete'; import { useState } from 'react'; +import { Grid, IconButton, styled, Tooltip } from '@mui/material'; +import { + Add as AddIcon, + ArrowCircleDown, + ArrowCircleUp, + Delete as DeleteIcon, + Upload, +} from '@mui/icons-material'; import { useIntl } from 'react-intl'; -import { styled } from '@mui/material/styles'; import { FieldValues, UseFieldArrayReturn } from 'react-hook-form'; import ErrorInput from '../error-management/error-input'; import FieldErrorAlert from '../error-management/field-error-alert'; diff --git a/src/components/inputs/react-hook-form/ag-grid-table/csv-uploader/csv-uploader.tsx b/src/components/inputs/react-hook-form/ag-grid-table/csv-uploader/csv-uploader.tsx index 7b668501..53c555c4 100644 --- a/src/components/inputs/react-hook-form/ag-grid-table/csv-uploader/csv-uploader.tsx +++ b/src/components/inputs/react-hook-form/ag-grid-table/csv-uploader/csv-uploader.tsx @@ -5,18 +5,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import Dialog from '@mui/material/Dialog'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; import { useCSVReader } from 'react-papaparse'; -import Button from '@mui/material/Button'; -import React, { useMemo, useState } from 'react'; -import Grid from '@mui/material/Grid'; +import { useMemo, useState } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; import CsvDownloader from 'react-csv-downloader'; -import Alert from '@mui/material/Alert'; -import { DialogContentText } from '@mui/material'; +import { + Alert, + Button, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, + Grid, +} from '@mui/material'; import { useWatch } from 'react-hook-form'; import { RECORD_SEP, UNIT_SEP } from 'papaparse'; import FieldConstants from '../../../../../utils/field-constants'; @@ -49,7 +51,7 @@ function CsvUploader({ }: CsvUploaderProps) { const watchTableValues = useWatch({ name }); const { append, replace } = useFieldArrayOutput; - const [createError, setCreateError] = React.useState(''); + const [createError, setCreateError] = useState(''); const intl = useIntl(); const { CSVReader } = useCSVReader(); const [importedData, setImportedData] = useState([]); diff --git a/src/components/inputs/react-hook-form/error-management/error-input.tsx b/src/components/inputs/react-hook-form/error-management/error-input.tsx index 195137ea..0346c722 100644 --- a/src/components/inputs/react-hook-form/error-management/error-input.tsx +++ b/src/components/inputs/react-hook-form/error-management/error-input.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { MutableRefObject, useEffect, useRef } from 'react'; +import { MutableRefObject, ReactNode, useEffect, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; import { useController } from 'react-hook-form'; @@ -18,11 +18,7 @@ export type ErrorMessage = export interface ErrorInputProps { name: string; - InputField: ({ - message, - }: { - message: string | React.ReactNode; - }) => React.ReactNode; + InputField: ({ message }: { message: string | ReactNode }) => ReactNode; } function ErrorInput({ name, InputField }: ErrorInputProps) { diff --git a/src/components/inputs/react-hook-form/error-management/field-error-alert.tsx b/src/components/inputs/react-hook-form/error-management/field-error-alert.tsx index 68306601..868b1aaf 100644 --- a/src/components/inputs/react-hook-form/error-management/field-error-alert.tsx +++ b/src/components/inputs/react-hook-form/error-management/field-error-alert.tsx @@ -5,11 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { ReactNode } from 'react'; import { Alert, Grid } from '@mui/material'; -import React from 'react'; interface FieldErrorAlertProps { - message: string | React.ReactNode; + message: string | ReactNode; } // component to display alert when a specific rhf field is in error diff --git a/src/components/inputs/react-hook-form/provider/custom-form-provider.tsx b/src/components/inputs/react-hook-form/provider/custom-form-provider.tsx index a4b6beb8..1d8be5e7 100644 --- a/src/components/inputs/react-hook-form/provider/custom-form-provider.tsx +++ b/src/components/inputs/react-hook-form/provider/custom-form-provider.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { createContext, PropsWithChildren } from 'react'; +import { createContext, PropsWithChildren, useMemo } from 'react'; import { FormProvider, UseFormReturn } from 'react-hook-form'; import * as yup from 'yup'; import { getSystemLanguage } from '../../../../hooks/localized-countries-hook'; @@ -39,7 +39,7 @@ function CustomFormProvider(props: CustomFormProviderProps) { return ( ({ validationSchema, removeOptional, diff --git a/src/components/inputs/react-hook-form/range-input.tsx b/src/components/inputs/react-hook-form/range-input.tsx index 67f91900..dd9d43f5 100644 --- a/src/components/inputs/react-hook-form/range-input.tsx +++ b/src/components/inputs/react-hook-form/range-input.tsx @@ -7,9 +7,7 @@ import { useWatch } from 'react-hook-form'; import { FormattedMessage } from 'react-intl'; import { useMemo } from 'react'; -import InputLabel from '@mui/material/InputLabel'; -import { Grid } from '@mui/material'; -import FormControl from '@mui/material/FormControl'; +import { FormControl, Grid, InputLabel } from '@mui/material'; import FloatInput from './numbers/float-input'; import yup from '../../../utils/yup-config'; import MuiSelectInput from './select-inputs/mui-select-input'; diff --git a/src/components/inputs/react-hook-form/unique-name-input.tsx b/src/components/inputs/react-hook-form/unique-name-input.tsx index bf8434b9..e34ea33c 100644 --- a/src/components/inputs/react-hook-form/unique-name-input.tsx +++ b/src/components/inputs/react-hook-form/unique-name-input.tsx @@ -7,11 +7,14 @@ import { ChangeEvent, useCallback, useEffect } from 'react'; import { FormattedMessage } from 'react-intl'; -import { InputAdornment, TextFieldProps } from '@mui/material'; +import { + CircularProgress, + InputAdornment, + TextField, + TextFieldProps, +} from '@mui/material'; import CheckIcon from '@mui/icons-material/Check'; import { useController, useFormContext } from 'react-hook-form'; -import CircularProgress from '@mui/material/CircularProgress'; -import TextField from '@mui/material/TextField'; import { UUID } from 'crypto'; import useDebounce from '../../../hooks/useDebounce'; import FieldConstants from '../../../utils/field-constants'; diff --git a/src/components/inputs/react-hook-form/utils/cancel-button.tsx b/src/components/inputs/react-hook-form/utils/cancel-button.tsx index f41fc272..0c5acb18 100644 --- a/src/components/inputs/react-hook-form/utils/cancel-button.tsx +++ b/src/components/inputs/react-hook-form/utils/cancel-button.tsx @@ -5,9 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { Button } from '@mui/material'; +import { Button, useThemeProps } from '@mui/material'; import { FormattedMessage } from 'react-intl'; -import { useThemeProps } from '@mui/material/styles'; function CancelButton({ ...inProps }) { const props = useThemeProps({ props: inProps, name: 'CancelButton' }); diff --git a/src/components/inputs/react-query-builder/add-button.tsx b/src/components/inputs/react-query-builder/add-button.tsx index 4fd2ea13..0f7bd73e 100644 --- a/src/components/inputs/react-query-builder/add-button.tsx +++ b/src/components/inputs/react-query-builder/add-button.tsx @@ -7,7 +7,7 @@ import { ActionWithRulesAndAddersProps } from 'react-querybuilder'; import { Button } from '@mui/material'; -import AddIcon from '@mui/icons-material/ControlPoint'; +import ControlPoint from '@mui/icons-material/ControlPoint'; import { FormattedMessage } from 'react-intl'; interface ActionWithRulesAndAddersWithLabelProps @@ -20,7 +20,7 @@ function AddButton(props: ActionWithRulesAndAddersWithLabelProps) { return (