diff --git a/.eslintrc.js b/.eslintrc.js index 8faebfa40b..236febff3e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,6 +8,7 @@ const config = { 'algolia/react', 'algolia/typescript', 'plugin:react-hooks/recommended', + 'plugin:de-morgan/recommended-legacy', ], plugins: ['react-hooks', 'deprecation'], globals: { diff --git a/package.json b/package.json index ab7bf01dd6..7296b665b6 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@babel/preset-typescript": "7.26.0", "@googlemaps/jest-mocks": "2.7.5", "@microsoft/api-extractor": "7.45.1", + "@rollup/plugin-terser": "0.4.4", "@storybook/addon-actions": "5.3.9", "@storybook/addon-knobs": "5.3.9", "@storybook/addon-options": "5.3.9", @@ -104,6 +105,7 @@ "eslint-config-prettier": "6.15.0", "eslint-import-resolver-typescript": "2.5.0", "eslint-plugin-compat": "6.0.1", + "eslint-plugin-de-morgan": "1.2.0", "eslint-plugin-deprecation": "1.3.2", "eslint-plugin-eslint-comments": "3.2.0", "eslint-plugin-import": "2.24.2", @@ -137,7 +139,6 @@ "rollup-plugin-node-globals": "1.4.0", "rollup-plugin-node-resolve": "5.2.0", "rollup-plugin-replace": "2.2.0", - "@rollup/plugin-terser": "0.4.4", "shelljs": "0.8.5", "shipjs": "0.26.0", "ts-jest": "27", diff --git a/packages/algoliasearch-helper/src/SearchResults/index.js b/packages/algoliasearch-helper/src/SearchResults/index.js index b52e01ffca..b7081d38d1 100644 --- a/packages/algoliasearch-helper/src/SearchResults/index.js +++ b/packages/algoliasearch-helper/src/SearchResults/index.js @@ -877,7 +877,7 @@ SearchResults.prototype.getFacetValues = function (attribute, opts) { sortBy: SearchResults.DEFAULT_SORT, // if no sortBy is given, attempt to sort based on facetOrdering // if it is given, we still allow to sort via facet ordering first - facetOrdering: !(opts && opts.sortBy), + facetOrdering: !opts || !opts.sortBy, }); // eslint-disable-next-line consistent-this diff --git a/packages/instantsearch-core/src/connectors/connectDynamicWidgets.ts b/packages/instantsearch-core/src/connectors/connectDynamicWidgets.ts index 36d271fcb7..8e34cf92fe 100644 --- a/packages/instantsearch-core/src/connectors/connectDynamicWidgets.ts +++ b/packages/instantsearch-core/src/connectors/connectDynamicWidgets.ts @@ -104,11 +104,9 @@ export const connectDynamicWidgets: DynamicWidgetsConnector = } = widgetParams; if ( - !( - widgets && - Array.isArray(widgets) && - widgets.every((widget) => typeof widget === 'object') - ) + !widgets || + !Array.isArray(widgets) || + !widgets.every((widget) => typeof widget === 'object') ) { throw new Error( withUsage('The `widgets` option expects an array of widgets.') diff --git a/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts b/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts index 13b43c02b5..5f69f75774 100644 --- a/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts +++ b/packages/instantsearch-core/src/connectors/connectInfiniteHits.ts @@ -401,7 +401,7 @@ export const connectInfiniteHits = function connectInfiniteHits< cachedItems[page] === undefined && !results.__isArtificial && instantSearchInstance.status === 'idle' && - !(hasDynamicWidgets && hasNoFacets) + (!hasDynamicWidgets || !hasNoFacets) ) { cachedItems[page] = transformedHits; cache.write({ state: normalizeState(state), items: cachedItems }); diff --git a/packages/instantsearch-core/src/connectors/connectNumericMenu.ts b/packages/instantsearch-core/src/connectors/connectNumericMenu.ts index e0b91e896c..740078a108 100644 --- a/packages/instantsearch-core/src/connectors/connectNumericMenu.ts +++ b/packages/instantsearch-core/src/connectors/connectNumericMenu.ts @@ -334,7 +334,7 @@ export const connectNumericMenu: NumericMenuConnector = return { createURL: connectorState.createURL(state), items: transformItems(preparedItems, { results }), - canRefine: !(hasNoResults && allIsSelected), + canRefine: !hasNoResults || !allIsSelected, refine: connectorState.refine, sendEvent: connectorState.sendEvent, widgetParams, diff --git a/packages/instantsearch-core/src/routing/historyRouter.ts b/packages/instantsearch-core/src/routing/historyRouter.ts index 52da910c76..e1017a6bd1 100644 --- a/packages/instantsearch-core/src/routing/historyRouter.ts +++ b/packages/instantsearch-core/src/routing/historyRouter.ts @@ -106,9 +106,9 @@ export function historyRouter({ // OR // - the last write was from InstantSearch.js // (unlike a SPA, where it would have last written) - const lastPushWasByISAfterDispose = !( - router.isDisposed && latestAcknowledgedHistory !== window.history.length - ); + const lastPushWasByISAfterDispose = + !router.isDisposed || + latestAcknowledgedHistory === window.history.length; return ( // When the last state change was through popstate, the IS.js state changes, diff --git a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx index e5d5267644..a7c63a4d0b 100644 --- a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx +++ b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx @@ -299,7 +299,7 @@ class RefinementList extends Component< public render() { const showMoreButtonClassName = cx( this.props.cssClasses.showMore, - !(this.props.showMore === true && this.props.canToggleShowMore) && + (this.props.showMore !== true || !this.props.canToggleShowMore) && this.props.cssClasses.disabledShowMore ); @@ -321,7 +321,8 @@ class RefinementList extends Component< const shouldDisableSearchBox = this.props.searchIsAlwaysActive !== true && - !(this.props.isFromSearch || !this.props.hasExhaustiveItems); + !this.props.isFromSearch && + this.props.hasExhaustiveItems; const searchBox = this.props.searchFacetValues && (
diff --git a/packages/instantsearch.js/src/components/SearchBox/SearchBox.tsx b/packages/instantsearch.js/src/components/SearchBox/SearchBox.tsx index e3b3d69151..9cd9eff68f 100644 --- a/packages/instantsearch.js/src/components/SearchBox/SearchBox.tsx +++ b/packages/instantsearch.js/src/components/SearchBox/SearchBox.tsx @@ -90,10 +90,8 @@ class SearchBox extends Component< const query = (event.target as HTMLInputElement).value; if ( - !( - this.props.ignoreCompositionEvents && - (event as KeyboardEvent).isComposing - ) + !this.props.ignoreCompositionEvents || + !(event as KeyboardEvent).isComposing ) { if (searchAsYouType) { refine(query); diff --git a/packages/instantsearch.js/src/widgets/dynamic-widgets/dynamic-widgets.ts b/packages/instantsearch.js/src/widgets/dynamic-widgets/dynamic-widgets.ts index a7f07258f0..afb0f5e1d6 100644 --- a/packages/instantsearch.js/src/widgets/dynamic-widgets/dynamic-widgets.ts +++ b/packages/instantsearch.js/src/widgets/dynamic-widgets/dynamic-widgets.ts @@ -71,11 +71,9 @@ const dynamicWidgets: DynamicWidgetsWidget = function dynamicWidgets( } if ( - !( - widgets && - Array.isArray(widgets) && - widgets.every((widget) => typeof widget === 'function') - ) + !widgets || + !Array.isArray(widgets) || + !widgets.every((widget) => typeof widget === 'function') ) { throw new Error( withUsage('The `widgets` option expects an array of callbacks.') diff --git a/packages/instantsearch.js/src/widgets/panel/panel.tsx b/packages/instantsearch.js/src/widgets/panel/panel.tsx index 47413c6071..85992620a0 100644 --- a/packages/instantsearch.js/src/widgets/panel/panel.tsx +++ b/packages/instantsearch.js/src/widgets/panel/panel.tsx @@ -242,7 +242,7 @@ const panel: PanelWidget = (panelWidgetParams) => { }; return (widgetFactory) => (widgetParams) => { - if (!(widgetParams && widgetParams.container)) { + if (!widgetParams || !widgetParams.container) { throw new Error( withUsage( `The \`container\` option is required in the widget within the panel.` diff --git a/packages/react-instantsearch/src/widgets/SearchBox.tsx b/packages/react-instantsearch/src/widgets/SearchBox.tsx index f33d81a342..09d1326ac7 100644 --- a/packages/react-instantsearch/src/widgets/SearchBox.tsx +++ b/packages/react-instantsearch/src/widgets/SearchBox.tsx @@ -55,7 +55,7 @@ export function SearchBox({ function setQuery(newQuery: string, isComposing = false) { setInputValue(newQuery); - if (searchAsYouType && !(ignoreCompositionEvents && isComposing)) { + if (searchAsYouType && (!ignoreCompositionEvents || !isComposing)) { refine(newQuery); } } diff --git a/packages/vue-instantsearch/src/components/SearchInput.vue b/packages/vue-instantsearch/src/components/SearchInput.vue index b2ca8a3ba6..f7524cee53 100644 --- a/packages/vue-instantsearch/src/components/SearchInput.vue +++ b/packages/vue-instantsearch/src/components/SearchInput.vue @@ -164,7 +164,7 @@ export default { return document.activeElement === this.$refs.input; }, onInput(event) { - if (!(this.ignoreCompositionEvents && event.isComposing)) { + if (!this.ignoreCompositionEvents || !event.isComposing) { this.$emit('input', event.target.value); this.$emit('update:modelValue', event.target.value); } diff --git a/yarn.lock b/yarn.lock index 7bfbd1359f..e34666d336 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14049,6 +14049,11 @@ eslint-plugin-compat@6.0.1: lodash.memoize "^4.1.2" semver "^7.6.2" +eslint-plugin-de-morgan@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-de-morgan/-/eslint-plugin-de-morgan-1.2.0.tgz#bf3aaa68e82835beee6010179fbf7019bca9ff1d" + integrity sha512-XOZxiOMHchXn425a1DS/NOXVkGqKiTOCvVGIPru/l/bfF4Ant7u8d4+rXOqVFEN5Z8K+I/AO19U074gqnnBsJw== + eslint-plugin-deprecation@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/eslint-plugin-deprecation/-/eslint-plugin-deprecation-1.3.2.tgz#a8125d28c56158cdfa1a685197e6be8ed86f189e"