diff --git a/app/actions/SettingsActions.js b/app/actions/SettingsActions.js index e3814044dc..e02eefc958 100644 --- a/app/actions/SettingsActions.js +++ b/app/actions/SettingsActions.js @@ -181,6 +181,13 @@ export function updateStateSettingsChanged(settings, norestart) { }; } +export const resetSettingsState = () => { + return (dispatch, getState) => { + const { currentSettings } = getState().settings; + dispatch({ tempSettings: currentSettings, type: SETTINGS_UNCHANGED }); + }; +}; + export const updateStateVoteSettingsChanged = (settings) => ( dispatch, getState diff --git a/app/components/buttons/index.js b/app/components/buttons/index.js index 85cd0d1f41..bd09414569 100644 --- a/app/components/buttons/index.js +++ b/app/components/buttons/index.js @@ -118,8 +118,17 @@ export const InfoDocFieldModalButton = mbb( styles.infoFieldModalButton, DocumentationInfoModal ); +export const InfoDocFieldModalInvisibleButton = mbb( + null, + DocumentationInfoModal, + InvisibleButton +); export const DiscoverUsageButton = mbb(null, DiscoverUsageModal); -export const ChangePassphraseButton = mbb(null, ChangePassphraseModal); +export const ChangePassphraseButton = mbb( + null, + ChangePassphraseModal, + PiUiButton +); export const InvisiblePassphraseModalButton = mbb( null, PassphraseModal, diff --git a/app/components/inputs/AccountsSelect/AccountsSelect.jsx b/app/components/inputs/AccountsSelect/AccountsSelect.jsx index 98bf9c365b..45583920b2 100644 --- a/app/components/inputs/AccountsSelect/AccountsSelect.jsx +++ b/app/components/inputs/AccountsSelect/AccountsSelect.jsx @@ -1,24 +1,24 @@ -import Select from "react-select"; import { useAccountsSelect } from "./hooks"; import { Balance } from "shared"; import styles from "./AccountsSelect.module.css"; import { classNames } from "pi-ui"; +import { Select } from "inputs"; import LinkToAccounts from "./LinkToAccounts"; +import { components } from "react-select"; const AccountsSelect = ({ accountsType, className, selectClassName, showAccountsButton, - disabled, hideSpendable, filterAccounts, account: accountProp, + customStyles, + customComponents, onChange, - onKeyDown, - valueRenderer, - optionRenderer, - searchable + selectWithBigFont, + ...props }) => { const { account, accounts, placeholder } = useAccountsSelect({ accountProp, @@ -27,49 +27,54 @@ const AccountsSelect = ({ onChange }); - const selectKeyDown = (e) => { - switch (e.keyCode) { - case 8: - case 46: - e.preventDefault(); - break; - } - onKeyDown?.(e); + const SingleValue = (props) => { + return ( + +
+
{props.data.name}
+ {!hideSpendable && ( +
+ +
+ )} +
+
+ ); }; - if (!valueRenderer) { - valueRenderer = (option) => ( -
-
{option.name}
- {!hideSpendable && ( -
- -
- )} -
+ const Option = (props) => { + return ( + +
+
{props.data.name}
+ {!hideSpendable && ( +
+ +
+ )} +
+
); - } + }; return (
); }; -LanguageSelectInput.propTypes = { - className: PropTypes.string -}; - -export default injectIntl(LanguageSelectInput); +export default LanguageSelectInput; diff --git a/app/components/inputs/LanguageSelectInput/LanguageSelectInput.module.css b/app/components/inputs/LanguageSelectInput/LanguageSelectInput.module.css index 336d84f93d..5c814fad14 100644 --- a/app/components/inputs/LanguageSelectInput/LanguageSelectInput.module.css +++ b/app/components/inputs/LanguageSelectInput/LanguageSelectInput.module.css @@ -1,24 +1,13 @@ -.input { - width: 200px; - margin-right: 0.5em; -} - .label { display: flex; } -.label .flag { - margin: 5px 5px 0 0; -} - .flag { - flex-grow: 2; background-repeat: no-repeat; - background-size: 20px; - width: 20px; - height: 20px; - margin-left: 10px; - margin-top: 2px; + background-size: 20px 13px; + width: 25px; + min-width: 25px; + background-position: left center; } .flag.ar { @@ -61,6 +50,7 @@ background-image: var(--flag-pl); } +.flag.dev, .flag.pt-BR { background-image: var(--flag-ptbr); } @@ -73,9 +63,8 @@ background-image: var(--flag-hk); } -.name { - flex-grow: 4; - width: 100px; +.option, +.singleValue { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; diff --git a/app/components/inputs/ReceiveAccountsSelect.jsx b/app/components/inputs/ReceiveAccountsSelect.jsx index cd2f05e469..b56b8f8399 100644 --- a/app/components/inputs/ReceiveAccountsSelect.jsx +++ b/app/components/inputs/ReceiveAccountsSelect.jsx @@ -6,11 +6,9 @@ import * as sel from "selectors"; function ReceiveAccountsSelect({ onChange, - className, - selectClassName, showAccountsButton, - disabled, - account + account, + ...props }) { const dispatch = useDispatch(); const mixedAccount = useSelector(sel.getMixedAccount); @@ -38,8 +36,6 @@ function ReceiveAccountsSelect({ ); diff --git a/app/components/inputs/Select.jsx b/app/components/inputs/Select.jsx new file mode 100644 index 0000000000..341be7f841 --- /dev/null +++ b/app/components/inputs/Select.jsx @@ -0,0 +1,74 @@ +import { Select as PiUiSelect } from "pi-ui"; + +const Select = ({ styles, selectWithBigFont, ariaLabelledBy, ...props }) => { + const customStyles = { + valueContainer: () => ({ + padding: `0 0 0 ${selectWithBigFont ? 0 : "0.5rem"}` + }), + placeholder: (provided) => ({ + margin: 0, + color: "var(--grey-5)", + fontSize: selectWithBigFont ? "1.6rem" : provided.fontSize, + lineHeight: selectWithBigFont ? "2.1rem" : provided.lineHeight + }), + control: (_, state) => ({ + borderBottomColor: "var(--select-stroke-color)", + borderRadius: "none", + borderLeft: "none", + borderRight: "none", + borderTop: "none", + minHeight: "initial", + "&:hover": { + borderBottomColor: "var(--accent-blue)" + }, + backgroundColor: state.isDisabled + ? "var(--disabled-background-color)" + : "transparent" + }), + container: () => ({ + padding: 0 + }), + singleValue: (provided) => ({ + margin: 0, + fontSize: selectWithBigFont ? "1.6rem" : provided.fontSize, + lineHeight: selectWithBigFont ? "2.1rem" : provided.lineHeight, + color: "var(--main-dark-blue)" + }), + option: (_, state) => ({ + color: "var(--main-dark-blue)", + backgroundColor: state.isFocused + ? "var(--background-hovered)" + : "var(--card-background)" + }), + menu: () => ({ + marginTop: 0 + }), + dropdownIndicator: () => ({ + paddingRight: 0 + }), + input: () => ({ + paddingTop: 0, + paddingBottom: 0, + marginTop: 0, + marginBottom: 0 + }), + ...styles + }; + + return ( + + ); +}; + +Select.propTypes = { + styles: PropTypes.object, + selectWithBigFont: PropTypes.bool, + ariaLabelledBy: PropTypes.string +}; + +export default Select; diff --git a/app/components/inputs/SettingsInput.jsx b/app/components/inputs/SettingsInput.jsx index bb5462276d..d1a029de46 100644 --- a/app/components/inputs/SettingsInput.jsx +++ b/app/components/inputs/SettingsInput.jsx @@ -1,53 +1,44 @@ -import Select from "react-select"; -import { injectIntl } from "react-intl"; -import { useState } from "react"; +import { Select } from "inputs"; +import { isString } from "lodash"; const SettingsInput = ({ - className, value, + options, valueKey, labelKey, - options, - disabled, ariaLabelledBy, - onChange + className, + ...props }) => { - const [inputValue, setInputValue] = useState(value ?? null); - - const selectKeyDown = (e) => { - switch (e.keyCode) { - case 8: - case 46: - e.preventDefault(); - break; - } + const normalizeOption = (option) => { + if (!option) return null; + return { + ...option, + value: option[valueKey], + label: option[labelKey] + }; }; - const onChangeSelect = (value) => { - setInputValue(value); - onChange?.(value); - }; + const normalizedValue = isString(value) + ? normalizeOption( + options.find((option) => option[valueKey]?.toString() === value) + ) + : value; + + const normalizedOptions = options?.map((option) => normalizeOption(option)); return (
; +export default ({ onChange, value, ...props }) => { + const [inputValue, setInputValue] = useState(value); + + const onSubmit = () => { + onChange?.(inputValue); + }; + + return ( + setInputValue(e.target.value)} + onKeyDownSubmit={onSubmit} + onBlur={onSubmit} + {...props} + /> + ); +}; diff --git a/app/components/inputs/VSPSelect/VSPSelect.jsx b/app/components/inputs/VSPSelect/VSPSelect.jsx index f7247d860d..d6d9b13061 100644 --- a/app/components/inputs/VSPSelect/VSPSelect.jsx +++ b/app/components/inputs/VSPSelect/VSPSelect.jsx @@ -1,10 +1,10 @@ -import { Creatable } from "react-select"; import { injectIntl, defineMessages } from "react-intl"; import { useEffect, useState, useMemo } from "react"; import { useVSPSelect } from "./hooks"; import { FormattedMessage as T } from "react-intl"; import { Tooltip } from "pi-ui"; import styles from "./VSPSelect.modules.css"; +import { Select } from "inputs"; const messages = defineMessages({ placeholder: { @@ -30,7 +30,15 @@ const getError = (error) => { return String(error); }; -function VSPSelect({ onChange, options, intl, value, isDisabled, setVspFee }) { +function VSPSelect({ + onChange, + options, + intl, + value, + isDisabled, + setVspFee, + selectWithBigFont +}) { const { send, state, selectedOption, vspInfo, availableVSPs } = useVSPSelect( options, value, @@ -93,13 +101,17 @@ function VSPSelect({ onChange, options, intl, value, isDisabled, setVspFee }) { // push new value if it is a new vsp option. if (value.newOption) { const host = value.host; - newOptions.push({ - host, - label: host, - value: host - }); - - setNewOptions(newOptions); + setNewOptions((opts) => [ + ...opts, + { + value: { + host, + label: host, + value: host + }, + label: host + } + ]); } isRetry ? send({ type: "RETRY", value }) : send({ type: "FETCH", value }); }; @@ -114,21 +126,24 @@ function VSPSelect({ onChange, options, intl, value, isDisabled, setVspFee }) { const getSelect = (isRetry) => { return ( - handleOnChange(option, isRetry)} value={selectedOption} - newOptionCreator={() => { - return { - value: { host: newOption, label: newOption }, - label: newOption, - host: newOption, - newOption: true - }; - }} - disabled={isDisabled} + onCreateOption={(option) => + handleOnChange( + { + value: { host: option, label: option, newOption: true } + }, + isRetry + ) + } + isDisabled={isDisabled} onInputChange={(input) => onSetNewOption(input)} isValidNewOption={() => !!newOption} /> diff --git a/app/components/inputs/index.js b/app/components/inputs/index.js index c89537d391..7f95d9e0f5 100644 --- a/app/components/inputs/index.js +++ b/app/components/inputs/index.js @@ -24,3 +24,4 @@ export { default as InlineField } from "./InlineField"; export { default as SettingsTextInput } from "./SettingsTextInput"; export { default as VSPSelect } from "./VSPSelect"; export { default as SeedHexEntry } from "./SeedHexEntry"; +export { default as Select } from "./Select"; diff --git a/app/components/layout/TabbedPage/TabbedPage.jsx b/app/components/layout/TabbedPage/TabbedPage.jsx index e0ecb70f02..41fabb0bb1 100644 --- a/app/components/layout/TabbedPage/TabbedPage.jsx +++ b/app/components/layout/TabbedPage/TabbedPage.jsx @@ -26,7 +26,9 @@ const TabbedPage = ({ const onSelectTab = (index) => { setActiveTabIndex(index); - history.push(tabs[index].path); + if (tabs[index].path) { + history.push(tabs[index].path); + } }; useEffect(() => { @@ -60,7 +62,7 @@ const TabbedPage = ({ contentAnimation={uiAnimations ? "slide" : "none"}> {tabs .filter(({ disabled }) => !disabled) - .map(({ label, content, path, props }) => { + .map(({ label, content, path, props, key }) => { const element = React.isValidElement(content) ? k(content, { ...props, @@ -70,8 +72,8 @@ const TabbedPage = ({ // before send, otherwise they will be undfined. h(content, { ...props }, null); return ( - -
{element}
+ +
{element}
); })} diff --git a/app/components/layout/TitleHeader/TitleHeader.jsx b/app/components/layout/TitleHeader/TitleHeader.jsx index d1d8375264..a1918dbba7 100644 --- a/app/components/layout/TitleHeader/TitleHeader.jsx +++ b/app/components/layout/TitleHeader/TitleHeader.jsx @@ -4,9 +4,11 @@ import styles from "./TitleHeader.module.css"; const TitleHeader = ({ title, iconType, optionalButton }) => (
-
-
-
+ {iconType && ( +
+
+
+ )}
{title}
diff --git a/app/components/modals/AutoBuyerSettingsModal/AutoBuyerSettingsModal.jsx b/app/components/modals/AutoBuyerSettingsModal/AutoBuyerSettingsModal.jsx index 02f39419ab..932c250080 100644 --- a/app/components/modals/AutoBuyerSettingsModal/AutoBuyerSettingsModal.jsx +++ b/app/components/modals/AutoBuyerSettingsModal/AutoBuyerSettingsModal.jsx @@ -59,15 +59,15 @@ const AutoBuyerSettingsModal = ({ placeholder={intl.formatMessage(messages.balanceToMaintainPlaceholder)} label={intl.formatMessage(messages.balanceToMaintainLabel)} /> -