diff --git a/package.json b/package.json index a155762..0e479fa 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "css-loader": "3.2.0", "date-fns": "2.7.0", "detect-secrets": "1.0.5", - "emotion": "9.2.12", + "emotion": "10.0.23", "enzyme": "3.10.0", "enzyme-adapter-react-16": "1.15.1", "enzyme-to-json": "3.4.3", @@ -90,7 +90,6 @@ "react": "16.12.0", "react-autosuggest": "9.4.3", "react-dom": "16.12.0", - "react-emotion": "9.2.12", "react-hot-loader": "4.12.17", "react-router-dom": "5.1.2", "request": "2.88.0", @@ -216,6 +215,8 @@ "logo": "https://opencollective.com/verdaccio/logo.txt" }, "dependencies": { + "@emotion/core": "10.0.22", + "@emotion/styled": "10.0.23", "@material-ui/lab": "4.0.0-alpha.31" } } diff --git a/src/components/ActionBar/styles.ts b/src/components/ActionBar/styles.ts index a1691b2..108eca2 100644 --- a/src/components/ActionBar/styles.ts +++ b/src/components/ActionBar/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import colors from '../../utils/styles/colors'; import ListItem from '../../muiComponents/ListItem'; diff --git a/src/components/Author/styles.ts b/src/components/Author/styles.ts index d713489..27c11df 100644 --- a/src/components/Author/styles.ts +++ b/src/components/Author/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { fontWeight } from '../../utils/styles/sizes'; import ListItem from '../../muiComponents/ListItem'; diff --git a/src/components/AutoComplete/AutoComplete.tsx b/src/components/AutoComplete/AutoComplete.tsx index 7c78a79..e551b41 100644 --- a/src/components/AutoComplete/AutoComplete.tsx +++ b/src/components/AutoComplete/AutoComplete.tsx @@ -1,5 +1,4 @@ import React, { KeyboardEvent } from 'react'; -import { css } from 'emotion'; import Autosuggest, { SuggestionSelectedEventData, InputProps, ChangeEvent } from 'react-autosuggest'; import match from 'autosuggest-highlight/match'; import parse from 'autosuggest-highlight/parse'; @@ -140,12 +139,7 @@ const AutoComplete = ({ return ( - + ); }; diff --git a/src/components/AutoComplete/styles.tsx b/src/components/AutoComplete/styles.tsx index 21e4504..52057bd 100644 --- a/src/components/AutoComplete/styles.tsx +++ b/src/components/AutoComplete/styles.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import styled, { css } from 'react-emotion'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; import TextField from '../../muiComponents/TextField'; import Paper from '../../muiComponents/Paper'; diff --git a/src/components/CopyToClipBoard/styles.ts b/src/components/CopyToClipBoard/styles.ts index 2f70378..60c775f 100644 --- a/src/components/CopyToClipBoard/styles.ts +++ b/src/components/CopyToClipBoard/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import IconButton from '../../muiComponents/IconButton'; diff --git a/src/components/Dependencies/styles.ts b/src/components/Dependencies/styles.ts index 7db712c..2996b00 100644 --- a/src/components/Dependencies/styles.ts +++ b/src/components/Dependencies/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { fontWeight } from '../../utils/styles/sizes'; import Text from '../../muiComponents/Text'; diff --git a/src/components/DetailContainer/DetailContainerTabs.tsx b/src/components/DetailContainer/DetailContainerTabs.tsx index 23b19fc..fdaa009 100644 --- a/src/components/DetailContainer/DetailContainerTabs.tsx +++ b/src/components/DetailContainer/DetailContainerTabs.tsx @@ -1,5 +1,5 @@ import React, { ChangeEvent, useState, useEffect } from 'react'; -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { default as MuiTabs } from '../../muiComponents/Tabs'; import Tab from '../../muiComponents/Tab'; diff --git a/src/components/DetailSidebar/styles.ts b/src/components/DetailSidebar/styles.ts index 131100e..da9fc5f 100644 --- a/src/components/DetailSidebar/styles.ts +++ b/src/components/DetailSidebar/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import ListItem from '../../muiComponents/ListItem'; import ListItemText from '../../muiComponents/ListItemText'; diff --git a/src/components/Developers/styles.ts b/src/components/Developers/styles.ts index 15ab694..07d41b5 100644 --- a/src/components/Developers/styles.ts +++ b/src/components/Developers/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import colors from '../../utils/styles/colors'; import { fontWeight } from '../../utils/styles/sizes'; diff --git a/src/components/Dist/styles.ts b/src/components/Dist/styles.ts index 30da4e7..46e4cbd 100644 --- a/src/components/Dist/styles.ts +++ b/src/components/Dist/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import colors from '../../utils/styles/colors'; import { fontWeight } from '../../utils/styles/sizes'; diff --git a/src/components/Engines/styles.ts b/src/components/Engines/styles.ts index f44af79..8bdd9d1 100644 --- a/src/components/Engines/styles.ts +++ b/src/components/Engines/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { fontWeight } from '../../utils/styles/sizes'; import ListItem from '../../muiComponents/ListItem'; diff --git a/src/components/Footer/styles.ts b/src/components/Footer/styles.ts index 3cff8b3..5ef38f6 100644 --- a/src/components/Footer/styles.ts +++ b/src/components/Footer/styles.ts @@ -1,4 +1,5 @@ -import styled, { css } from 'react-emotion'; +import { css } from '@emotion/core'; +import styled from '@emotion/styled'; import mq from '../../utils/styles/media'; import Icon from '../Icon/Icon'; diff --git a/src/components/Header/styles.ts b/src/components/Header/styles.ts index 733bfb4..3de0b4b 100644 --- a/src/components/Header/styles.ts +++ b/src/components/Header/styles.ts @@ -1,4 +1,5 @@ -import styled, { css } from 'react-emotion'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; import colors from '../../utils/styles/colors'; import mq from '../../utils/styles/media'; @@ -48,7 +49,7 @@ export const IconSearchButton = styled(IconButton)({ }); export const SearchWrapper = styled('div')({ - display: 'none', + // display: 'none', maxWidth: '393px', width: '100%', }); diff --git a/src/components/Help/styles.ts b/src/components/Help/styles.ts index c8cd753..86d3ec3 100644 --- a/src/components/Help/styles.ts +++ b/src/components/Help/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { default as Typography } from '../../muiComponents/Heading'; import Card from '../../muiComponents/Card'; diff --git a/src/components/Icon/styles.ts b/src/components/Icon/styles.ts index b17243c..bf60394 100644 --- a/src/components/Icon/styles.ts +++ b/src/components/Icon/styles.ts @@ -1,6 +1,6 @@ -import styled, { css } from 'react-emotion'; +import { css } from '@emotion/core'; +import styled from '@emotion/styled'; import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; -import { StyledOtherComponent } from 'create-emotion-styled'; import { DetailedHTMLProps, HTMLAttributes } from 'react'; const getSize = (size: Breakpoint): string => { @@ -18,7 +18,7 @@ const getSize = (size: Breakpoint): string => { } }; -const commonStyle = ({ size = 'sm' as Breakpoint, pointer, modifiers = null }): string => css` +const commonStyle = ({ size = 'sm' as Breakpoint, pointer, modifiers = null }) => css` && { display: inline-block; cursor: ${pointer ? 'pointer' : 'Developers'}; @@ -32,16 +32,7 @@ export const Svg = styled('svg')` box-sizing: initial; `; -export const ImgWrapper: StyledOtherComponent< - { - size?: Breakpoint; - pointer: boolean; - modifiers?: null | undefined; - name?: string | unknown; - }, - DetailedHTMLProps, HTMLSpanElement>, - {} -> = styled('span')` +export const ImgWrapper = styled('span')` ${commonStyle}; box-sizing: initial; `; diff --git a/src/components/Install/Install.tsx b/src/components/Install/Install.tsx index 3daa01c..9f10ee3 100644 --- a/src/components/Install/Install.tsx +++ b/src/components/Install/Install.tsx @@ -1,5 +1,5 @@ import React, { useContext } from 'react'; -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { DetailContext } from '../../pages/Version'; import { fontWeight } from '../../utils/styles/sizes'; diff --git a/src/components/Install/InstallListItem.tsx b/src/components/Install/InstallListItem.tsx index 2f198b5..3845874 100644 --- a/src/components/Install/InstallListItem.tsx +++ b/src/components/Install/InstallListItem.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import CopyToClipBoard from '../CopyToClipBoard'; import Avatar from '../../muiComponents/Avatar'; diff --git a/src/components/Label/Label.tsx b/src/components/Label/Label.tsx index 6ab5f05..6bb653c 100644 --- a/src/components/Label/Label.tsx +++ b/src/components/Label/Label.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { fontWeight } from '../../utils/styles/sizes'; @@ -15,7 +15,6 @@ interface WrapperProps { weight: string; modifiers?: null; } - const Wrapper = styled('div')` font-weight: ${({ weight }: WrapperProps) => fontWeight[weight]}; text-transform: ${({ capitalize }: WrapperProps) => (capitalize ? 'capitalize' : 'none')}; diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx index b1aeea4..19ec264 100644 --- a/src/components/Layout/Layout.tsx +++ b/src/components/Layout/Layout.tsx @@ -1,4 +1,5 @@ -import styled, { css } from 'react-emotion'; +import { css } from '@emotion/core'; +import styled from '@emotion/styled'; import colors from '../../utils/styles/colors'; diff --git a/src/components/Loading/styles.ts b/src/components/Loading/styles.ts index 3227eee..abe45ce 100644 --- a/src/components/Loading/styles.ts +++ b/src/components/Loading/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; export const Wrapper = styled('div')` && { diff --git a/src/components/Logo/Logo.tsx b/src/components/Logo/Logo.tsx index d4b9031..16f4a01 100644 --- a/src/components/Logo/Logo.tsx +++ b/src/components/Logo/Logo.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import logo from './img/logo.svg'; diff --git a/src/components/NotFound/NotFound.tsx b/src/components/NotFound/NotFound.tsx index 4b01515..aba294c 100644 --- a/src/components/NotFound/NotFound.tsx +++ b/src/components/NotFound/NotFound.tsx @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import React, { useCallback } from 'react'; import { useHistory } from 'react-router-dom'; diff --git a/src/components/NotFound/styles.ts b/src/components/NotFound/styles.ts index 6c85990..b479e6e 100644 --- a/src/components/NotFound/styles.ts +++ b/src/components/NotFound/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { default as Typography } from '../../muiComponents/Heading'; import List from '../../muiComponents/List'; diff --git a/src/components/Package/styles.ts b/src/components/Package/styles.ts index dfd685a..8cdf8b2 100644 --- a/src/components/Package/styles.ts +++ b/src/components/Package/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { Link } from 'react-router-dom'; import { breakpoints } from '../../utils/styles/media'; diff --git a/src/components/PackageList/styles.ts b/src/components/PackageList/styles.ts index b5268c1..8ef61d0 100644 --- a/src/components/PackageList/styles.ts +++ b/src/components/PackageList/styles.ts @@ -1,4 +1,4 @@ -import { css } from 'emotion'; +import { css } from '@emotion/core'; import { fontWeight, fontSize } from '../../utils/styles/sizes'; diff --git a/src/components/RegistryInfoContent/RegistryInfoContent.tsx b/src/components/RegistryInfoContent/RegistryInfoContent.tsx index af7824c..944069c 100644 --- a/src/components/RegistryInfoContent/RegistryInfoContent.tsx +++ b/src/components/RegistryInfoContent/RegistryInfoContent.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { css } from 'emotion'; +import { css } from '@emotion/core'; import CopyToClipBoard from '../CopyToClipBoard'; import { getCLISetRegistry, getCLIChangePassword, getCLISetConfigRegistry } from '../../utils/cli-utils'; @@ -47,13 +47,7 @@ const RegistryInfoContent: React.FC = props => { return ( <> - + diff --git a/src/components/RegistryInfoContent/styles.ts b/src/components/RegistryInfoContent/styles.ts index 08d82d8..695fd18 100644 --- a/src/components/RegistryInfoContent/styles.ts +++ b/src/components/RegistryInfoContent/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; export const CommandContainer = styled('div')({ '&&': { diff --git a/src/components/RegistryInfoDialog/styles.ts b/src/components/RegistryInfoDialog/styles.ts index 8bdc1b6..c6fd04d 100644 --- a/src/components/RegistryInfoDialog/styles.ts +++ b/src/components/RegistryInfoDialog/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import colors from '../../utils/styles/colors'; import { fontSize } from '../../utils/styles/sizes'; diff --git a/src/components/Repository/styles.ts b/src/components/Repository/styles.ts index 5ea2a4c..262eae4 100644 --- a/src/components/Repository/styles.ts +++ b/src/components/Repository/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import Github from '../../icons/GitHub'; import colors from '../../utils/styles/colors'; diff --git a/src/components/Search/Search.tsx b/src/components/Search/Search.tsx index 568a654..3d8c2a1 100644 --- a/src/components/Search/Search.tsx +++ b/src/components/Search/Search.tsx @@ -1,200 +1,80 @@ -import React, { KeyboardEvent, Component, ReactElement } from 'react'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { SuggestionSelectedEventData, ChangeEvent } from 'react-autosuggest'; -import { css } from 'emotion'; -import { default as IconSearch } from '@material-ui/icons/Search'; -// import debounce from 'lodash/debounce'; +import React from 'react'; +import debounce from 'lodash/debounce'; -import InputAdornment from '../../muiComponents/InputAdornment'; import AutoComplete from '../../muiComponents/AutoComplete'; -import colors from '../../utils/styles/colors'; import { callSearch } from '../../utils/calls'; -export interface State { - search: string; - suggestions: unknown[]; - loading: boolean; - loaded: boolean; - error: boolean; -} - -export type cancelAllSearchRequests = () => void; -export type handlePackagesClearRequested = () => void; -export type handleSearch = (event: React.FormEvent, { newValue, method }: ChangeEvent) => void; -export type handleClickSearch = (event: KeyboardEvent, { suggestionValue, method }: { suggestionValue: object[]; method: string }) => void; -export type handleFetchPackages = ({ value: string }) => Promise; -export type onBlur = (event: React.FormEvent) => void; - const CONSTANTS = { API_DELAY: 300, PLACEHOLDER_TEXT: 'Search Packages', ABORT_ERROR: 'AbortError', }; -export class Search extends Component, State> { - constructor(props: RouteComponentProps<{}>) { - super(props); - this.state = { - search: '', - suggestions: [], - // loading: A boolean value to indicate that request is in pending state. - loading: false, - // loaded: A boolean value to indicate that result has been loaded. - loaded: false, - // error: A boolean value to indicate API error. - error: false, - }; - this.requestList = []; - } +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +const Search: React.FC = () => { + const [suggestions, setSuggestions] = React.useState([]); + const [isLoading, setIsLoading] = React.useState(); + const [hasBeenLoaded, setHasBeenLoaded] = React.useState(); + const [error, setError] = React.useState(); - public render(): ReactElement { - const { suggestions, search, loaded, loading, error } = this.state; - - return ( - - ); - } - - /** - * Cancel all the requests which are in pending state. - */ - private cancelAllSearchRequests: cancelAllSearchRequests = () => { - this.requestList.forEach(request => request.abort()); - this.requestList = []; - }; - - /** - * Cancel all the request from list and make request list empty. - */ - private handlePackagesClearRequested: handlePackagesClearRequested = () => { - this.setState({ - suggestions: [], - }); - }; - - /** - * onChange method for the input element. - */ - private handleSearch: handleSearch = (event: ChangeEvent) => { - // stops event bubbling - event.stopPropagation(); - if (method === 'type') { - const value = newValue.trim(); - this.setState( - { - search: value, - loading: true, - loaded: false, - error: false, - }, - () => { - /** - * A use case where User keeps adding and removing value in input field, - * so we cancel all the existing requests when input is empty. - */ - if (value.length === 0) { - this.cancelAllSearchRequests(); - } - } - ); - } - }; - - /** - * When an user select any package by clicking or pressing return key. - */ - private handleClickSearch = ( - event: React.FormEvent, - { suggestionValue, method }: SuggestionSelectedEventData - ): void | undefined => { - const { history } = this.props; - // stops event bubbling - event.stopPropagation(); - switch (method) { - case 'click': - case 'enter': - this.setState({ search: '' }); - history.push(`/-/web/detail/${suggestionValue}`); - break; - } - }; - - /** - * Fetch packages from API. - * For AbortController see: https://developer.mozilla.org/en-US/docs/Web/API/AbortController - */ - private handleFetchPackages: handleFetchPackages = async ({ value }) => { + const handleFetchPackages = debounce(async (value: string) => { try { const controller = new window.AbortController(); const signal = controller.signal; // Keep track of search requests. - this.requestList.push(controller); + // this.requestList.push(controller); const suggestions = await callSearch(value, signal); - // @ts-ignore - this.setState({ - suggestions, - loaded: true, - }); + setSuggestions( + // @ts-ignore + suggestions.map(suggestion => ({ + ...suggestion, + id: suggestion._id, + label: suggestion.name, + })) + ); + setHasBeenLoaded(true); } catch (error) { /** * AbortError is not the API error. * It means browser has cancelled the API request. */ if (error.name === CONSTANTS.ABORT_ERROR) { - this.setState({ error: false, loaded: false }); + setError(false); + setHasBeenLoaded(false); } else { - this.setState({ error: true, loaded: false }); + setError(true); + setHasBeenLoaded(false); } } finally { - this.setState({ loading: false }); + setIsLoading(false); } - }; + }, CONSTANTS.API_DELAY); - private requestList: AbortController[]; - - public getAdorment(): JSX.Element { - return ( - - - - ); - } - - /** - * As user focuses out from input, we cancel all the request from requestList - * and set the API state parameters to default boolean values. - */ - private handleOnBlur: onBlur = event => { + const handleChange = (event: React.ChangeEvent) => { // stops event bubbling event.stopPropagation(); - this.setState( - { - loaded: false, - loading: false, - error: false, - }, - () => this.cancelAllSearchRequests() - ); + setIsLoading(true); + setHasBeenLoaded(false); + setError(undefined); + handleFetchPackages(event.target.value); }; -} -export default withRouter(Search); + return ( + + ); +}; + +export default Search; diff --git a/src/components/Spinner/styles.ts b/src/components/Spinner/styles.ts index 9b48aaf..7f476ef 100644 --- a/src/components/Spinner/styles.ts +++ b/src/components/Spinner/styles.ts @@ -1,4 +1,5 @@ -import styled, { css } from 'react-emotion'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; import colors from '../../utils/styles/colors'; import CircularProgress from '../../muiComponents/CircularProgress'; diff --git a/src/components/Tag/styles.ts b/src/components/Tag/styles.ts index f41dbad..f6e1240 100644 --- a/src/components/Tag/styles.ts +++ b/src/components/Tag/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; export const Wrapper = styled('span')({ '&&': { diff --git a/src/components/UpLinks/styles.ts b/src/components/UpLinks/styles.ts index 7f52cf0..d4940d4 100644 --- a/src/components/UpLinks/styles.ts +++ b/src/components/UpLinks/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import Text from '../../muiComponents/Text'; import { default as MuiListItemText } from '../../muiComponents/ListItemText'; diff --git a/src/components/Versions/styles.ts b/src/components/Versions/styles.ts index 9c1b2a3..8cbc8f1 100644 --- a/src/components/Versions/styles.ts +++ b/src/components/Versions/styles.ts @@ -1,4 +1,4 @@ -import styled from 'react-emotion'; +import styled from '@emotion/styled'; import { fontWeight } from '../../utils/styles/sizes'; import Text from '../../muiComponents/Text'; diff --git a/src/muiComponents/AutoComplete/AutoComplete.tsx b/src/muiComponents/AutoComplete/AutoComplete.tsx index 26dbce6..d8f532c 100644 --- a/src/muiComponents/AutoComplete/AutoComplete.tsx +++ b/src/muiComponents/AutoComplete/AutoComplete.tsx @@ -1,93 +1,93 @@ -import React, { FC, ChangeEvent, useState } from 'react'; +import React, { forwardRef, ChangeEvent, useState } from 'react'; import { default as MuiAutoComplete, AutocompleteProps } from '@material-ui/lab/Autocomplete'; -import styled from 'react-emotion'; +import TextField from '@material-ui/core/TextField'; +import styled from '@emotion/styled'; +import Search from '@material-ui/icons/Search'; import CircularProgress from '../CircularProgress'; -import TextField from '../TextField'; + +import AutoCompleteTextField from './AutoCompleteTextField'; const StyledAutoComplete = styled(MuiAutoComplete)({ width: '100%', + color: 'white', }); -interface Props extends Pick { +const StyledSearch = styled(Search)({ + color: 'white', + marginRight: 10, +}); + +const StyledTextField = styled(TextField)({ + '& .MuiInputBase-root': { + color: 'white', + }, + '& .MuiInput-underline': { + ':before': { + content: "''", + border: 'none', + }, + ':after': { + borderColor: 'white', + }, + ':hover:before': { + content: 'none', + }, + }, +}); + +interface Props { placeholder?: string; onChange: (event: ChangeEvent) => void; + options: Array