diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2019-07-16 13:12:16 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-07-16 20:21:10 +0200 |
commit | 03bb045cca26245804592602c7ff0c6e477f3b8d (patch) | |
tree | 0d2e536a64eb136b5eafb77955794e0244e5169a /server/sonar-web/src/main/js/components/controls | |
parent | 5ed20116d427b617b04e93bb4f2937ad6692803a (diff) | |
download | sonarqube-03bb045cca26245804592602c7ff0c6e477f3b8d.tar.gz sonarqube-03bb045cca26245804592602c7ff0c6e477f3b8d.zip |
SC-704 Extract more components (#1921)
* Extract BoxedGroupAccordion
* Extract Select and SearchSelect
* Extract Validation controls
* Update sonar-ui-common
Diffstat (limited to 'server/sonar-web/src/main/js/components/controls')
18 files changed, 1 insertions, 1446 deletions
diff --git a/server/sonar-web/src/main/js/components/controls/BoxedGroupAccordion.tsx b/server/sonar-web/src/main/js/components/controls/BoxedGroupAccordion.tsx deleted file mode 100644 index 8e1a4cd99ad..00000000000 --- a/server/sonar-web/src/main/js/components/controls/BoxedGroupAccordion.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import * as classNames from 'classnames'; -import OpenCloseIcon from 'sonar-ui-common/components/icons/OpenCloseIcon'; - -interface Props { - children: React.ReactNode; - className?: string; - data?: string; - onClick: (data?: string) => void; - open: boolean; - renderHeader?: () => React.ReactNode; - title: React.ReactNode; -} - -interface State { - hoveringInner: boolean; -} - -export default class BoxedGroupAccordion extends React.PureComponent<Props, State> { - state: State = { hoveringInner: false }; - - handleClick = () => { - this.props.onClick(this.props.data); - }; - - onDetailEnter = () => { - this.setState({ hoveringInner: true }); - }; - - onDetailLeave = () => { - this.setState({ hoveringInner: false }); - }; - - render() { - const { className, open, renderHeader, title } = this.props; - return ( - <div - className={classNames('boxed-group boxed-group-accordion', className, { - 'no-hover': this.state.hoveringInner - })}> - <div className="boxed-group-header" onClick={this.handleClick} role="listitem"> - <span className="boxed-group-accordion-title"> - <OpenCloseIcon className="little-spacer-right" open={open} /> - {title} - </span> - {renderHeader && renderHeader()} - </div> - {open && ( - <div - className="boxed-group-inner" - onMouseEnter={this.onDetailEnter} - onMouseLeave={this.onDetailLeave}> - {this.props.children} - </div> - )} - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/components/controls/DateInput.tsx b/server/sonar-web/src/main/js/components/controls/DateInput.tsx index dcb777c8573..da7918c9be3 100644 --- a/server/sonar-web/src/main/js/components/controls/DateInput.tsx +++ b/server/sonar-web/src/main/js/components/controls/DateInput.tsx @@ -37,7 +37,7 @@ import { import { ButtonIcon, ClearButton } from 'sonar-ui-common/components/controls/buttons'; import OutsideClickHandler from 'sonar-ui-common/components/controls/OutsideClickHandler'; import { lazyLoad } from 'sonar-ui-common/components/lazyLoad'; -import Select from './Select'; +import Select from 'sonar-ui-common/components/controls/Select'; import './DayPicker.css'; import './styles.css'; diff --git a/server/sonar-web/src/main/js/components/controls/SearchSelect.tsx b/server/sonar-web/src/main/js/components/controls/SearchSelect.tsx deleted file mode 100644 index c4b681624e6..00000000000 --- a/server/sonar-web/src/main/js/components/controls/SearchSelect.tsx +++ /dev/null @@ -1,154 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { debounce } from 'lodash'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import Select, { Creatable } from './Select'; - -interface Props<T> { - autofocus?: boolean; - canCreate?: boolean; - className?: string; - clearable?: boolean; - defaultOptions?: T[]; - minimumQueryLength?: number; - multi?: boolean; - onSearch: (query: string) => Promise<T[]>; - onSelect?: (option: T) => void; - onMultiSelect?: (options: T[]) => void; - promptTextCreator?: (label: string) => string; - renderOption?: (option: T) => JSX.Element; - resetOnBlur?: boolean; - value?: T | T[]; -} - -interface State<T> { - loading: boolean; - options: T[]; - query: string; -} - -export default class SearchSelect<T extends { value: string }> extends React.PureComponent< - Props<T>, - State<T> -> { - mounted = false; - - constructor(props: Props<T>) { - super(props); - this.state = { loading: false, options: props.defaultOptions || [], query: '' }; - this.handleSearch = debounce(this.handleSearch, 250); - } - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - get autofocus() { - return this.props.autofocus !== undefined ? this.props.autofocus : true; - } - - get minimumQueryLength() { - return this.props.minimumQueryLength !== undefined ? this.props.minimumQueryLength : 2; - } - - get resetOnBlur() { - return this.props.resetOnBlur !== undefined ? this.props.resetOnBlur : true; - } - - handleSearch = (query: string) => { - // Ignore the result if the query changed - const currentQuery = query; - this.props.onSearch(currentQuery).then( - options => { - if (this.mounted) { - this.setState(state => ({ - loading: false, - options: state.query === currentQuery ? options : state.options - })); - } - }, - () => { - if (this.mounted) { - this.setState({ loading: false }); - } - } - ); - }; - - handleChange = (option: T | T[]) => { - if (Array.isArray(option)) { - if (this.props.onMultiSelect) { - this.props.onMultiSelect(option); - } - } else if (this.props.onSelect) { - this.props.onSelect(option); - } - }; - - handleInputChange = (query: string) => { - if (query.length >= this.minimumQueryLength) { - this.setState({ loading: true, query }); - this.handleSearch(query); - } else { - // `onInputChange` is called with an empty string after a user selects a value - // in this case we shouldn't reset `options`, because it also resets select value :( - const options = (query.length === 0 && this.props.defaultOptions) || []; - this.setState({ options, query }); - } - }; - - // disable internal filtering - handleFilterOption = () => true; - - render() { - const Component = this.props.canCreate ? Creatable : Select; - return ( - <Component - autoFocus={this.autofocus} - className={this.props.className} - clearable={this.props.clearable} - escapeClearsValue={false} - filterOption={this.handleFilterOption} - isLoading={this.state.loading} - multi={this.props.multi} - noResultsText={ - this.state.query.length < this.minimumQueryLength - ? translateWithParameters('select2.tooShort', this.minimumQueryLength) - : translate('select2.noMatches') - } - onBlurResetsInput={this.resetOnBlur} - onChange={this.handleChange} - onInputChange={this.handleInputChange} - optionRenderer={this.props.renderOption} - options={this.state.options} - placeholder={translate('search_verb')} - promptTextCreator={this.props.promptTextCreator} - searchable={true} - value={this.props.value} - valueRenderer={this.props.renderOption} - /> - ); - } -} diff --git a/server/sonar-web/src/main/js/components/controls/Select.tsx b/server/sonar-web/src/main/js/components/controls/Select.tsx deleted file mode 100644 index 2086716ac0f..00000000000 --- a/server/sonar-web/src/main/js/components/controls/Select.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { ReactSelectProps, ReactCreatableSelectProps, ReactAsyncSelectProps } from 'react-select'; -import { ClearButton } from 'sonar-ui-common/components/controls/buttons'; -import { lazyLoad } from 'sonar-ui-common/components/lazyLoad'; -import './react-select.css'; - -const ReactSelectLib = import('react-select'); -const ReactSelect = lazyLoad(() => ReactSelectLib); -const ReactCreatable = lazyLoad(() => ReactSelectLib.then(lib => ({ default: lib.Creatable }))); -const ReactAsync = lazyLoad(() => ReactSelectLib.then(lib => ({ default: lib.Async }))); - -function renderInput() { - return <ClearButton className="button-tiny spacer-left text-middle" iconProps={{ size: 12 }} />; -} - -interface WithInnerRef { - innerRef?: (element: React.Component) => void; -} - -export default function Select({ innerRef, ...props }: WithInnerRef & ReactSelectProps) { - // TODO try to define good defaults, if any - // ReactSelect doesn't declare `clearRenderer` prop - const ReactSelectAny = ReactSelect as any; - // hide the "x" icon when select is empty - const clearable = props.clearable ? Boolean(props.value) : false; - return ( - <ReactSelectAny {...props} clearRenderer={renderInput} clearable={clearable} ref={innerRef} /> - ); -} - -export function Creatable(props: ReactCreatableSelectProps) { - // ReactSelect doesn't declare `clearRenderer` prop - const ReactCreatableAny = ReactCreatable as any; - return <ReactCreatableAny {...props} clearRenderer={renderInput} />; -} - -// TODO figure out why `ref` prop is incompatible -export function AsyncSelect(props: ReactAsyncSelectProps & { ref?: any }) { - return <ReactAsync {...props} />; -} diff --git a/server/sonar-web/src/main/js/components/controls/ValidationForm.tsx b/server/sonar-web/src/main/js/components/controls/ValidationForm.tsx deleted file mode 100644 index 9f2ca8217ee..00000000000 --- a/server/sonar-web/src/main/js/components/controls/ValidationForm.tsx +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { FormikActions, FormikProps, Formik } from 'formik'; - -export type ChildrenProps<V> = T.Omit<FormikProps<V>, 'handleSubmit'>; - -interface Props<V> { - children: (props: ChildrenProps<V>) => React.ReactNode; - initialValues: V; - isInitialValid?: boolean; - onSubmit: (data: V) => Promise<void>; - validate: (data: V) => { [P in keyof V]?: string } | Promise<{ [P in keyof V]?: string }>; -} - -export default class ValidationForm<V> extends React.Component<Props<V>> { - mounted = false; - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - handleSubmit = (data: V, { setSubmitting }: FormikActions<V>) => { - const result = this.props.onSubmit(data); - const stopSubmitting = () => { - if (this.mounted) { - setSubmitting(false); - } - }; - - if (result) { - result.then(stopSubmitting, stopSubmitting); - } else { - stopSubmitting(); - } - }; - - render() { - return ( - <Formik<V> - initialValues={this.props.initialValues} - isInitialValid={this.props.isInitialValid} - onSubmit={this.handleSubmit} - validate={this.props.validate}> - {({ handleSubmit, ...props }) => ( - <form onSubmit={handleSubmit}>{this.props.children(props)}</form> - )} - </Formik> - ); - } -} diff --git a/server/sonar-web/src/main/js/components/controls/ValidationInput.tsx b/server/sonar-web/src/main/js/components/controls/ValidationInput.tsx deleted file mode 100644 index 3d7a78104a1..00000000000 --- a/server/sonar-web/src/main/js/components/controls/ValidationInput.tsx +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import AlertErrorIcon from 'sonar-ui-common/components/icons/AlertErrorIcon'; -import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon'; -import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; - -interface Props { - description?: string; - children: React.ReactNode; - className?: string; - error: string | undefined; - help?: string; - id: string; - isInvalid: boolean; - isValid: boolean; - label: React.ReactNode; - required?: boolean; -} - -export default function ValidationInput(props: Props) { - const hasError = props.isInvalid && props.error !== undefined; - return ( - <div className={props.className}> - <label htmlFor={props.id}> - <span className="text-middle"> - <strong>{props.label}</strong> - {props.required && <em className="mandatory">*</em>} - </span> - {props.help && <HelpTooltip className="spacer-left" overlay={props.help} />} - </label> - <div className="little-spacer-top spacer-bottom"> - {props.children} - {props.isInvalid && <AlertErrorIcon className="spacer-left text-middle" />} - {hasError && ( - <span className="little-spacer-left text-danger text-middle">{props.error}</span> - )} - {props.isValid && <AlertSuccessIcon className="spacer-left text-middle" />} - </div> - {props.description && <div className="note abs-width-400">{props.description}</div>} - </div> - ); -} diff --git a/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx b/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx deleted file mode 100644 index 841b3592be1..00000000000 --- a/server/sonar-web/src/main/js/components/controls/ValidationModal.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { SubmitButton, ResetButtonLink } from 'sonar-ui-common/components/controls/buttons'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import Modal, { ModalProps } from 'sonar-ui-common/components/controls/Modal'; -import ValidationForm, { ChildrenProps } from './ValidationForm'; - -interface Props<V> extends ModalProps { - children: (props: ChildrenProps<V>) => React.ReactNode; - confirmButtonText: string; - header: string; - initialValues: V; - isDestructive?: boolean; - isInitialValid?: boolean; - onClose: () => void; - onSubmit: (data: V) => Promise<void>; - validate: (data: V) => { [P in keyof V]?: string }; -} - -export default class ValidationModal<V> extends React.PureComponent<Props<V>> { - handleSubmit = (data: V) => { - return this.props.onSubmit(data).then(() => { - this.props.onClose(); - }); - }; - - render() { - return ( - <Modal - contentLabel={this.props.header} - noBackdrop={this.props.noBackdrop} - onRequestClose={this.props.onClose} - size={this.props.size}> - <ValidationForm - initialValues={this.props.initialValues} - isInitialValid={this.props.isInitialValid} - onSubmit={this.handleSubmit} - validate={this.props.validate}> - {props => ( - <> - <header className="modal-head"> - <h2>{this.props.header}</h2> - </header> - - <div className="modal-body">{this.props.children(props)}</div> - - <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={props.isSubmitting} /> - <SubmitButton - className={this.props.isDestructive ? 'button-red' : undefined} - disabled={props.isSubmitting || !props.isValid || !props.dirty}> - {this.props.confirmButtonText} - </SubmitButton> - <ResetButtonLink disabled={props.isSubmitting} onClick={this.props.onClose}> - {translate('cancel')} - </ResetButtonLink> - </footer> - </> - )} - </ValidationForm> - </Modal> - ); - } -} diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/BoxedGroupAccordion-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/BoxedGroupAccordion-test.tsx deleted file mode 100644 index b77c4c5bbcd..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/BoxedGroupAccordion-test.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import { click } from 'sonar-ui-common/helpers/testUtils'; -import BoxedGroupAccordion from '../BoxedGroupAccordion'; - -it('should render correctly', () => { - expect(getWrapper()).toMatchSnapshot(); -}); - -it('should show the inner content after a click', () => { - const onClick = jest.fn(); - const wrapper = getWrapper({ onClick }); - click(wrapper.find('.boxed-group-header')); - - expect(onClick).lastCalledWith('foo'); - wrapper.setProps({ open: true }); - - expect(wrapper.find('.boxed-group-inner').exists()).toBeTruthy(); -}); - -function getWrapper(props = {}) { - return shallow( - <BoxedGroupAccordion - data="foo" - onClick={() => {}} - open={false} - renderHeader={() => <div>header content</div>} - title="Foo" - {...props}> - <div>inner content</div> - </BoxedGroupAccordion> - ); -} diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/SearchSelect-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/SearchSelect-test.tsx deleted file mode 100644 index 340e30c16f2..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/SearchSelect-test.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import SearchSelect from '../SearchSelect'; - -jest.mock('lodash', () => { - const lodash = require.requireActual('lodash'); - lodash.debounce = jest.fn(fn => fn); - return lodash; -}); - -it('should render Select', () => { - expect(shallow(<SearchSelect onSearch={jest.fn()} onSelect={jest.fn()} />)).toMatchSnapshot(); -}); - -it('should call onSelect', () => { - const onSelect = jest.fn(); - const wrapper = shallow(<SearchSelect onSearch={jest.fn()} onSelect={onSelect} />); - wrapper.prop('onChange')({ value: 'foo' }); - expect(onSelect).lastCalledWith({ value: 'foo' }); -}); - -it('should call onSearch', () => { - const onSearch = jest.fn().mockReturnValue(Promise.resolve([])); - const wrapper = shallow( - <SearchSelect minimumQueryLength={2} onSearch={onSearch} onSelect={jest.fn()} /> - ); - wrapper.prop('onInputChange')('f'); - expect(onSearch).not.toHaveBeenCalled(); - wrapper.prop('onInputChange')('foo'); - expect(onSearch).lastCalledWith('foo'); -}); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/ValidationForm-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/ValidationForm-test.tsx deleted file mode 100644 index 3760b02ca81..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/ValidationForm-test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import ValidationForm from '../ValidationForm'; - -it('should render and submit', async () => { - const render = jest.fn(); - const onSubmit = jest.fn(); - const setSubmitting = jest.fn(); - const wrapper = shallow( - <ValidationForm initialValues={{ foo: 'bar' }} onSubmit={onSubmit} validate={jest.fn()}> - {render} - </ValidationForm> - ); - expect(wrapper).toMatchSnapshot(); - wrapper.dive(); - expect(render).toBeCalledWith( - expect.objectContaining({ dirty: false, errors: {}, values: { foo: 'bar' } }) - ); - - wrapper.prop<Function>('onSubmit')({ foo: 'bar' }, { setSubmitting }); - expect(setSubmitting).toBeCalledWith(false); - - onSubmit.mockResolvedValue(undefined).mockClear(); - setSubmitting.mockClear(); - wrapper.prop<Function>('onSubmit')({ foo: 'bar' }, { setSubmitting }); - await new Promise(setImmediate); - expect(setSubmitting).toBeCalledWith(false); -}); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/ValidationInput-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/ValidationInput-test.tsx deleted file mode 100644 index 280d52bec6c..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/ValidationInput-test.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import ValidationInput from '../ValidationInput'; - -it('should render', () => { - expect( - shallow( - <ValidationInput - description="My description" - error={undefined} - help="Help message" - id="field-id" - isInvalid={false} - isValid={false} - label="Field label" - required={true}> - <div /> - </ValidationInput> - ) - ).toMatchSnapshot(); -}); - -it('should render with error', () => { - expect( - shallow( - <ValidationInput - description="My description" - error="Field error message" - id="field-id" - isInvalid={true} - isValid={false} - label="Field label"> - <div /> - </ValidationInput> - ) - ).toMatchSnapshot(); -}); - -it('should render when valid', () => { - expect( - shallow( - <ValidationInput - description="My description" - error={undefined} - id="field-id" - isInvalid={false} - isValid={true} - label="Field label" - required={true}> - <div /> - </ValidationInput> - ) - ).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/ValidationModal-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/ValidationModal-test.tsx deleted file mode 100644 index f4af7f14294..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/ValidationModal-test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { shallow } from 'enzyme'; -import ValidationModal from '../ValidationModal'; - -it('should render correctly', () => { - const wrapper = shallow( - <ValidationModal<{ field: string }> - confirmButtonText="confirm" - header="title" - initialValues={{ field: 'foo' }} - isDestructive={true} - isInitialValid={true} - onClose={jest.fn()} - onSubmit={jest.fn()} - validate={jest.fn()}> - {props => ( - <input - name="field" - onBlur={props.handleBlur} - onChange={props.handleChange} - type="text" - value={props.values.field} - /> - )} - </ValidationModal> - ); - expect(wrapper).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/BoxedGroupAccordion-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/BoxedGroupAccordion-test.tsx.snap deleted file mode 100644 index 0c7b74b79d9..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/BoxedGroupAccordion-test.tsx.snap +++ /dev/null @@ -1,26 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -<div - className="boxed-group boxed-group-accordion" -> - <div - className="boxed-group-header" - onClick={[Function]} - role="listitem" - > - <span - className="boxed-group-accordion-title" - > - <OpenCloseIcon - className="little-spacer-right" - open={false} - /> - Foo - </span> - <div> - header content - </div> - </div> -</div> -`; diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.tsx.snap deleted file mode 100644 index 792343f1a73..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchSelect-test.tsx.snap +++ /dev/null @@ -1,17 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render Select 1`] = ` -<Select - autoFocus={true} - escapeClearsValue={false} - filterOption={[Function]} - isLoading={false} - noResultsText="select2.tooShort.2" - onBlurResetsInput={true} - onChange={[Function]} - onInputChange={[Function]} - options={Array []} - placeholder="search_verb" - searchable={true} -/> -`; diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationForm-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationForm-test.tsx.snap deleted file mode 100644 index e00f009ef2f..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationForm-test.tsx.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render and submit 1`] = ` -<Formik - enableReinitialize={false} - initialValues={ - Object { - "foo": "bar", - } - } - isInitialValid={false} - onSubmit={[Function]} - validate={[MockFunction]} - validateOnBlur={true} - validateOnChange={true} -> - <Component /> -</Formik> -`; diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationInput-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationInput-test.tsx.snap deleted file mode 100644 index e417b038bc6..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationInput-test.tsx.snap +++ /dev/null @@ -1,104 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render 1`] = ` -<div> - <label - htmlFor="field-id" - > - <span - className="text-middle" - > - <strong> - Field label - </strong> - <em - className="mandatory" - > - * - </em> - </span> - <HelpTooltip - className="spacer-left" - overlay="Help message" - /> - </label> - <div - className="little-spacer-top spacer-bottom" - > - <div /> - </div> - <div - className="note abs-width-400" - > - My description - </div> -</div> -`; - -exports[`should render when valid 1`] = ` -<div> - <label - htmlFor="field-id" - > - <span - className="text-middle" - > - <strong> - Field label - </strong> - <em - className="mandatory" - > - * - </em> - </span> - </label> - <div - className="little-spacer-top spacer-bottom" - > - <div /> - <AlertSuccessIcon - className="spacer-left text-middle" - /> - </div> - <div - className="note abs-width-400" - > - My description - </div> -</div> -`; - -exports[`should render with error 1`] = ` -<div> - <label - htmlFor="field-id" - > - <span - className="text-middle" - > - <strong> - Field label - </strong> - </span> - </label> - <div - className="little-spacer-top spacer-bottom" - > - <div /> - <AlertErrorIcon - className="spacer-left text-middle" - /> - <span - className="little-spacer-left text-danger text-middle" - > - Field error message - </span> - </div> - <div - className="note abs-width-400" - > - My description - </div> -</div> -`; diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap deleted file mode 100644 index ecf12ce47b4..00000000000 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ValidationModal-test.tsx.snap +++ /dev/null @@ -1,21 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -<Modal - contentLabel="title" - onRequestClose={[MockFunction]} -> - <ValidationForm - initialValues={ - Object { - "field": "foo", - } - } - isInitialValid={true} - onSubmit={[Function]} - validate={[MockFunction]} - > - <Component /> - </ValidationForm> -</Modal> -`; diff --git a/server/sonar-web/src/main/js/components/controls/react-select.css b/server/sonar-web/src/main/js/components/controls/react-select.css deleted file mode 100644 index 463c0044f47..00000000000 --- a/server/sonar-web/src/main/js/components/controls/react-select.css +++ /dev/null @@ -1,483 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -.Select { - position: relative; - display: inline-block; - vertical-align: middle; - font-size: var(--smallFontSize); - text-align: left; -} - -.Select, -.Select div, -.Select input, -.Select span { - box-sizing: border-box; -} - -.Select.is-disabled > .Select-control { - background-color: var(--disableGrayBg) !important; - border-color: var(--disableGrayBorder) !important; -} - -.Select.is-disabled > .Select-control:hover { - box-shadow: none !important; -} - -.Select.is-disabled .Select-arrow-zone { - cursor: not-allowed !important; - pointer-events: none !important; -} - -.Select.is-disabled .Select-placeholder, -.Select.is-disabled .Select-value { - color: var(--disableGrayText) !important; -} - -.Select-control { - position: relative; - display: table; - width: 100%; - height: var(--controlHeight); - line-height: calc(var(--controlHeight) - 2px); - border: 1px solid var(--gray80); - border-collapse: separate; - border-radius: 2px; - background-color: #fff; - color: var(--baseFontColor); - cursor: default; - outline: none; - overflow: hidden; -} - -.is-searchable.is-open > .Select-control { - cursor: text; -} - -.is-open > .Select-control { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - background: #fff; -} - -.is-open > .Select-control > .Select-arrow { - border-color: transparent transparent #999; - border-width: 0 5px 5px; -} - -.is-searchable.is-focused:not(.is-open) > .Select-control { - cursor: text; -} - -.is-focused:not(.is-open) > .Select-control { - border-color: var(--blue); -} - -.Select-placeholder { - color: var(--secondFontColor); -} - -.Select-placeholder, -:not(.Select--multi) > .Select-control .Select-value { - bottom: 0; - left: 0; - line-height: 23px; - padding-left: 8px; - padding-right: 24px; - position: absolute; - right: 0; - top: 0; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.Select-value [class^='icon-'] { - padding-top: 5px; -} - -.Select-value svg, -.Select-value img { - padding-top: 4px; -} - -.Select-value .outline-badge, -.Select-option .outline-badge { - height: 20px; - line-height: 19px; - margin-top: 1px; -} - -.Select-option svg, -.Select-option img, -.Select-option [class^='icon-'] { - padding-top: 2px; -} - -.has-value:not(.Select--multi) > .Select-control > .Select-value .Select-value-label, -.has-value.is-pseudo-focused:not(.Select--multi) - > .Select-control - > .Select-value - .Select-value-label { - color: var(--baseFontColor); -} - -.has-value:not(.Select--multi) > .Select-control > .Select-value a.Select-value-label, -.has-value.is-pseudo-focused:not(.Select--multi) - > .Select-control - > .Select-value - a.Select-value-label { - cursor: pointer; - text-decoration: none; -} - -.has-value:not(.Select--multi) > .Select-control > .Select-value a.Select-value-label:hover, -.has-value.is-pseudo-focused:not(.Select--multi) - > .Select-control - > .Select-value - a.Select-value-label:hover, -.has-value:not(.Select--multi) > .Select-control > .Select-value a.Select-value-label:focus, -.has-value.is-pseudo-focused:not(.Select--multi) - > .Select-control - > .Select-value - a.Select-value-label:focus { - color: #007eff; - outline: none; - text-decoration: underline; -} - -.Select-input { - vertical-align: top; - height: 22px; - padding-left: 8px; - padding-right: 8px; - outline: none; -} - -.Select-input > input { - background: none transparent; - border: 0 none; - cursor: default; - display: inline-block; - font-family: inherit; - font-size: var(--smallFontSize); - height: 22px; - margin: 0; - outline: none; - padding: 0; - box-shadow: none; - -webkit-appearance: none; -} - -.is-focused .Select-input > input { - cursor: text; -} - -.has-value.is-pseudo-focused .Select-input { - opacity: 0; -} - -.Select-control:not(.is-searchable) > .Select-input { - outline: none; -} - -.Select-loading-zone { - cursor: pointer; - display: table-cell; - position: relative; - text-align: center; - vertical-align: middle; - width: 16px; -} - -.Select-loading { - -webkit-animation: Select-animation-spin 400ms infinite linear; - -o-animation: Select-animation-spin 400ms infinite linear; - animation: Select-animation-spin 400ms infinite linear; - width: 16px; - height: 16px; - box-sizing: border-box; - border-radius: 50%; - border: 2px solid #ccc; - border-right-color: var(--baseFontColor); - display: inline-block; - position: relative; - vertical-align: middle; -} - -.Select-clear-zone { - -webkit-animation: Select-animation-fadeIn 200ms; - -o-animation: Select-animation-fadeIn 200ms; - animation: Select-animation-fadeIn 200ms; - color: #999; - cursor: pointer; - display: table-cell; - position: relative; - text-align: center; - vertical-align: middle; - width: 16px; - height: 16px; - padding-right: 4px; -} - -.Select-clear-zone:hover .Select-clear { - background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxNCAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7Ij4gICAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC4wMjM0Mzc1LDAsMCwwLjAyMzQzNzUsLTUuMDE1NjIsLTUuMDE1NjIpIj4gICAgICAgIDxwYXRoIGQ9Ik04MTAsMjc0TDU3Miw1MTJMODEwLDc1MEw3NTAsODEwTDUxMiw1NzJMMjc0LDgxMEwyMTQsNzUwTDQ1Miw1MTJMMjE0LDI3NEwyNzQsMjE0TDUxMiw0NTJMNzUwLDIxNEw4MTAsMjc0WiIgc3R5bGU9ImZpbGw6cmdiKDIzMSwyMCw1Nik7ZmlsbC1ydWxlOm5vbnplcm87Ii8+ICAgIDwvZz48L3N2Zz4=); -} - -.Select-clear { - display: block; - width: 9px; - height: 9px; - background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxNCAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7Ij4gICAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC4wMjM0Mzc1LDAsMCwwLjAyMzQzNzUsLTUuMDE1NjIsLTUuMDE1NjIpIj4gICAgICAgIDxwYXRoIGQ9Ik04MTAsMjc0TDU3Miw1MTJMODEwLDc1MEw3NTAsODEwTDUxMiw1NzJMMjc0LDgxMEwyMTQsNzUwTDQ1Miw1MTJMMjE0LDI3NEwyNzQsMjE0TDUxMiw0NTJMNzUwLDIxNEw4MTAsMjc0WiIgc3R5bGU9ImZpbGw6cmdiKDE1MywxNTMsMTUzKTtmaWxsLXJ1bGU6bm9uemVybzsiLz4gICAgPC9nPjwvc3ZnPg==); - background-size: 9px 9px; - text-indent: -9999px; -} - -.Select--multi .Select-clear-zone { - width: 17px; -} - -.Select-arrow-zone { - cursor: pointer; - display: table-cell; - position: relative; - text-align: center; - vertical-align: middle; - width: 20px; - padding-right: 5px; -} - -.Select-arrow { - border-color: #999 transparent transparent; - border-style: solid; - border-width: 4px 4px 2px; - display: inline-block; - height: 0; - width: 0; -} - -.is-open .Select-arrow, -.Select-arrow-zone:hover > .Select-arrow { - border-top-color: #666; -} - -@-webkit-keyframes Select-animation-fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@keyframes Select-animation-fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -.Select-menu-outer { - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; - background-color: #fff; - border: 1px solid #ccc; - border-top-color: var(--barBorderColor); - box-sizing: border-box; - margin-top: -1px; - max-height: 200px; - position: absolute; - top: 100%; - width: 100%; - z-index: var(--dropdownMenuZIndex); - -webkit-overflow-scrolling: touch; - box-shadow: var(--defaultShadow); -} - -.Select-menu { - max-height: 198px; - padding: 5px 0; - overflow-y: auto; -} - -.Select-option { - display: block; - line-height: 20px; - padding: 0 8px; - box-sizing: border-box; - color: var(--baseFontColor); - font-size: var(--smallFontSize); - cursor: pointer; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.Select-option:last-child { - border-bottom-right-radius: 2px; - border-bottom-left-radius: 2px; -} - -.Select-option.is-focused { - background-color: var(--barBackgroundColor); -} - -.Select-option.is-disabled { - font-weight: 600; - cursor: default; -} - -.Select-noresults { - box-sizing: border-box; - color: #999; - cursor: default; - display: block; - padding: 8px 10px; -} - -.Select--multi .Select-value { - background-color: rgba(0, 126, 255, 0.08); - border-radius: 2px; - border: 1px solid rgba(0, 126, 255, 0.24); - color: var(--baseFontColor); - display: inline-block; - font-size: var(--smallFontSize); - line-height: 14px; - margin: 1px 4px 1px 1px; - vertical-align: top; -} - -.Select-value-label { - font-size: var(--smallFontSize); -} - -.is-searchable.is-open .Select-value-label { - opacity: 0.5; -} - -.Select-big .Select-control { - padding-top: 4px; - padding-bottom: 4px; -} - -.Select-big .Select-placeholder { - margin-top: 4px; - margin-bottom: 4px; -} - -.Select-big .Select-value-label { - display: inline-block; - margin-top: 7px; - line-height: 16px; -} - -.Select-big .Select-option { - padding: 7px 8px; - line-height: 16px; -} - -.Select-big img, -.Select-big svg { - padding-top: 0; -} - -.Select--multi .Select-value-icon, -.Select--multi .Select-value-label { - display: inline-block; - vertical-align: middle; -} - -.Select--multi .Select-value-label { - display: inline-block; - max-width: 200px; - border-bottom-right-radius: 2px; - border-top-right-radius: 2px; - cursor: default; - padding: 2px 5px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.Select--multi a.Select-value-label { - color: #007eff; - cursor: pointer; - text-decoration: none; -} - -.Select--multi a.Select-value-label:hover { - text-decoration: underline; -} - -.Select--multi .Select-value-icon { - cursor: pointer; - border-bottom-left-radius: 2px; - border-top-left-radius: 2px; - border-right: 1px solid rgba(0, 126, 255, 0.24); - padding: 1px 5px; -} - -.Select--multi .Select-value-icon:hover, -.Select--multi .Select-value-icon:focus { - background-color: rgba(0, 113, 230, 0.08); - color: #0071e6; -} - -.Select--multi .Select-value-icon:active { - background-color: rgba(0, 126, 255, 0.24); -} - -.Select--multi.is-disabled .Select-value { - background-color: #fcfcfc; - border: 1px solid #e3e3e3; - color: var(--baseFontColor); -} - -.Select--multi.is-disabled .Select-value-icon { - cursor: not-allowed; - border-right: 1px solid #e3e3e3; -} - -.Select--multi.is-disabled .Select-value-icon:hover, -.Select--multi.is-disabled .Select-value-icon:focus, -.Select--multi.is-disabled .Select-value-icon:active { - background-color: #fcfcfc; -} - -.Select-aria-only { - display: none; -} - -@keyframes Select-animation-spin { - to { - transform: rotate(1turn); - } -} - -@-webkit-keyframes Select-animation-spin { - to { - -webkit-transform: rotate(1turn); - } -} |