@shopgate/pwa-ui-shared 7.30.0-alpha.7 → 7.30.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AccordionContainer/index.js +39 -5
- package/AccordionContainer/spec.js +25 -2
- package/ActionButton/index.js +63 -7
- package/ActionButton/spec.js +63 -2
- package/ActionButton/style.js +22 -1
- package/AddToCartButton/index.js +184 -27
- package/AddToCartButton/mock.js +18 -4
- package/AddToCartButton/spec.js +65 -2
- package/AddToCartButton/style.js +127 -11
- package/Availability/index.js +34 -2
- package/Availability/spec.js +41 -1
- package/Availability/style.js +19 -1
- package/Button/index.js +76 -5
- package/Button/spec.js +33 -1
- package/Button/style.js +130 -21
- package/ButtonLink/connector.js +11 -2
- package/ButtonLink/index.js +44 -6
- package/ButtonLink/spec.js +23 -1
- package/Card/index.js +19 -2
- package/Card/style.js +11 -1
- package/CardList/components/Item/index.js +26 -2
- package/CardList/components/Item/style.js +7 -1
- package/CardList/index.js +34 -3
- package/CartTotalLine/components/Amount/index.js +28 -2
- package/CartTotalLine/components/Amount/style.js +8 -1
- package/CartTotalLine/components/Hint/index.js +23 -2
- package/CartTotalLine/components/Hint/style.js +12 -1
- package/CartTotalLine/components/Label/index.js +36 -2
- package/CartTotalLine/components/Label/style.js +17 -1
- package/CartTotalLine/components/Spacer/index.js +16 -2
- package/CartTotalLine/index.js +39 -2
- package/CartTotalLine/style.js +31 -1
- package/Checkbox/index.js +31 -2
- package/Checkbox/style.js +18 -1
- package/Chip/index.js +61 -2
- package/Chip/spec.js +24 -1
- package/Chip/style.js +71 -3
- package/ContextMenu/ContextMenu.hooks.js +6 -2
- package/ContextMenu/ContextMenuProvider.context.js +9 -3
- package/ContextMenu/ContextMenuProvider.js +21 -2
- package/ContextMenu/components/Item/index.js +67 -5
- package/ContextMenu/components/Item/style.js +32 -3
- package/ContextMenu/components/Position/index.js +61 -10
- package/ContextMenu/components/Position/style.js +11 -1
- package/ContextMenu/index.js +124 -3
- package/ContextMenu/spec.js +101 -2
- package/ContextMenu/style.js +45 -1
- package/Dialog/components/BasicDialog/index.js +5 -1
- package/Dialog/components/HtmlContentDialog/index.js +22 -2
- package/Dialog/components/HtmlContentDialog/spec.js +59 -1
- package/Dialog/components/PipelineErrorDialog/index.js +114 -25
- package/Dialog/components/PipelineErrorDialog/spec.js +92 -12
- package/Dialog/components/TextMessageDialog/index.js +28 -2
- package/Dialog/components/TextMessageDialog/spec.js +59 -1
- package/Dialog/components/VariantSelectModal/connector.js +11 -2
- package/Dialog/components/VariantSelectModal/index.js +65 -6
- package/Dialog/components/VariantSelectModal/spec.js +51 -2
- package/Dialog/constants.js +6 -1
- package/Dialog/index.js +114 -7
- package/Dialog/spec.js +81 -3
- package/DiscountBadge/index.js +30 -2
- package/DiscountBadge/spec.js +19 -1
- package/DiscountBadge/style.js +34 -2
- package/FavoritesButton/connector.js +18 -3
- package/FavoritesButton/index.js +118 -15
- package/FavoritesButton/mock.js +50 -4
- package/FavoritesButton/spec.js +120 -2
- package/FavoritesButton/style.js +26 -1
- package/Form/Builder/builders/buildCountryList.js +40 -6
- package/Form/Builder/builders/buildFormDefaults.js +35 -6
- package/Form/Builder/builders/buildFormElements.js +68 -10
- package/Form/Builder/builders/buildProvinceList.js +19 -2
- package/Form/Builder/builders/buildValidationErrorList.js +7 -2
- package/Form/Builder/classes/ActionListener/constants.js +22 -2
- package/Form/Builder/classes/ActionListener/index.js +441 -93
- package/Form/Builder/classes/ActionListener/spec.js +321 -19
- package/Form/Builder/components/CheckboxElement.js +35 -3
- package/Form/Builder/components/CountryElement.js +40 -3
- package/Form/Builder/components/ProvinceElement.js +40 -3
- package/Form/Builder/components/RadioElement.js +41 -3
- package/Form/Builder/components/SelectElement.js +39 -3
- package/Form/Builder/components/TextElement.js +49 -4
- package/Form/Builder/elementTypes.js +11 -1
- package/Form/Builder/index.js +298 -52
- package/Form/Builder/iso-3166-2.js +4943 -1
- package/Form/Builder/spec.js +308 -16
- package/Form/Checkbox/index.js +66 -4
- package/Form/Checkbox/style.js +25 -2
- package/Form/InfoField/index.js +50 -2
- package/Form/InfoField/spec.js +9 -1
- package/Form/InfoField/style.js +11 -1
- package/Form/Password/index.js +51 -6
- package/Form/Password/spec.js +34 -1
- package/Form/Password/style.js +11 -1
- package/Form/RadioGroup/components/Item/index.js +59 -3
- package/Form/RadioGroup/components/Item/style.js +32 -2
- package/Form/RadioGroup/index.js +101 -9
- package/Form/RadioGroup/spec.js +83 -3
- package/Form/RadioGroup/style.js +18 -2
- package/Form/Select/index.js +158 -10
- package/Form/Select/spec.js +36 -5
- package/Form/Select/style.js +27 -1
- package/Form/SelectContextChoices/index.js +77 -3
- package/Form/SelectContextChoices/spec.js +33 -4
- package/Form/SelectContextChoices/style.js +23 -1
- package/Form/TextField/index.js +92 -8
- package/Form/TextField/spec.js +110 -1
- package/Form/TextField/style.js +66 -8
- package/Form/index.js +54 -13
- package/FormElement/components/ErrorText/index.js +31 -2
- package/FormElement/components/ErrorText/style.js +13 -1
- package/FormElement/components/Label/index.js +35 -2
- package/FormElement/components/Label/style.js +76 -8
- package/FormElement/components/Placeholder/index.js +26 -2
- package/FormElement/components/Placeholder/style.js +48 -6
- package/FormElement/components/Underline/index.js +18 -2
- package/FormElement/components/Underline/style.js +51 -4
- package/FormElement/index.js +91 -6
- package/FormElement/spec.js +67 -2
- package/FormElement/style.js +13 -2
- package/Glow/index.js +90 -7
- package/Glow/spec.js +9 -1
- package/Glow/style.js +18 -1
- package/IndicatorCircle/index.js +33 -3
- package/IndicatorCircle/spec.js +28 -1
- package/IndicatorCircle/style.js +57 -3
- package/LoadingIndicator/index.js +29 -2
- package/LoadingIndicator/style.js +20 -1
- package/Manufacturer/index.js +20 -2
- package/Manufacturer/style.js +5 -1
- package/MessageBar/index.js +36 -2
- package/MessageBar/spec.js +79 -1
- package/MessageBar/style.js +38 -1
- package/NoResults/components/Icon/index.js +130 -2
- package/NoResults/components/Icon/style.js +17 -1
- package/NoResults/index.js +46 -2
- package/NoResults/style.js +31 -1
- package/Placeholder/index.js +25 -3
- package/Placeholder/style.js +11 -1
- package/PlaceholderLabel/index.js +27 -2
- package/PlaceholderLabel/spec.js +19 -1
- package/PlaceholderLabel/style.js +12 -1
- package/PlaceholderParagraph/index.js +36 -2
- package/PlaceholderParagraph/spec.js +19 -1
- package/Price/index.js +88 -7
- package/Price/style.js +22 -1
- package/PriceInfo/index.js +20 -2
- package/PriceInfo/style.js +5 -1
- package/PriceStriked/index.js +83 -12
- package/PriceStriked/style.js +33 -3
- package/ProductProperties/index.js +32 -2
- package/ProgressBar/index.js +101 -13
- package/ProgressBar/spec.js +13 -1
- package/ProgressBar/style.js +83 -2
- package/RadioButton/index.js +18 -2
- package/RadioButton/spec.js +21 -1
- package/RadioButton/style.js +21 -1
- package/RatingNumber/index.js +29 -2
- package/RatingStars/constants.js +2 -1
- package/RatingStars/index.js +130 -12
- package/RatingStars/spec.js +90 -3
- package/RatingStars/style.js +51 -2
- package/Ripple/components/RippleAnimation/index.js +88 -6
- package/Ripple/index.js +218 -40
- package/Ripple/style.js +18 -1
- package/RippleButton/index.js +52 -5
- package/RippleButton/spec.js +45 -1
- package/ScannerOverlay/components/CameraOverlay/index.js +13 -2
- package/ScannerOverlay/components/CameraOverlay/style.js +40 -1
- package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/index.js +34 -2
- package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/style.js +28 -1
- package/ScannerOverlay/components/ScannerBar/components/ScannerInstructions/index.js +11 -2
- package/ScannerOverlay/components/ScannerBar/index.js +31 -2
- package/ScannerOverlay/components/ScannerBar/style.js +20 -1
- package/ScannerOverlay/index.js +47 -7
- package/Sheet/components/Header/components/SearchBar/index.js +46 -2
- package/Sheet/components/Header/components/SearchBar/spec.js +21 -3
- package/Sheet/components/Header/components/SearchBar/style.js +47 -1
- package/Sheet/components/Header/index.js +75 -7
- package/Sheet/components/Header/spec.js +14 -1
- package/Sheet/components/Header/style.js +50 -1
- package/Sheet/index.js +170 -17
- package/Sheet/spec.js +85 -5
- package/Sheet/style.js +143 -2
- package/TaxDisclaimer/index.js +34 -4
- package/TaxDisclaimer/spec.js +31 -3
- package/TaxDisclaimer/style.js +9 -1
- package/TextField/components/ErrorText/index.js +33 -2
- package/TextField/components/ErrorText/style.js +25 -3
- package/TextField/components/FormElement/index.js +19 -2
- package/TextField/components/FormElement/style.js +32 -4
- package/TextField/components/Hint/index.js +21 -2
- package/TextField/components/Hint/style.js +40 -5
- package/TextField/components/Label/index.js +32 -3
- package/TextField/components/Label/style.js +68 -8
- package/TextField/components/Underline/index.js +19 -2
- package/TextField/components/Underline/style.js +51 -4
- package/TextField/index.js +189 -27
- package/TextField/spec.js +128 -3
- package/TextField/style.js +34 -4
- package/ToggleIcon/index.js +58 -8
- package/ToggleIcon/spec.js +35 -1
- package/icons/AccountBoxIcon.js +11 -2
- package/icons/AddMoreIcon.js +11 -2
- package/icons/ArrowDropIcon.js +11 -2
- package/icons/ArrowIcon.js +21 -2
- package/icons/BarcodeScannerIcon.js +11 -2
- package/icons/BoxIcon.js +11 -2
- package/icons/BrowseIcon.js +11 -2
- package/icons/BurgerIcon.js +11 -2
- package/icons/CalendarIcon.js +15 -3
- package/icons/CartCouponIcon.js +72 -2
- package/icons/CartIcon.js +11 -2
- package/icons/CartPlusIcon.js +11 -2
- package/icons/CheckIcon.js +11 -2
- package/icons/CheckedIcon.js +11 -2
- package/icons/ChevronIcon.js +11 -2
- package/icons/CreditCardIcon.js +11 -2
- package/icons/CrossIcon.js +11 -2
- package/icons/DescriptionIcon.js +11 -2
- package/icons/FilterIcon.js +11 -2
- package/icons/FlashDisabledIcon.js +11 -2
- package/icons/FlashEnabledIcon.js +11 -2
- package/icons/GridIcon.js +11 -2
- package/icons/HeartIcon.js +11 -2
- package/icons/HeartOutlineIcon.js +11 -2
- package/icons/HeartPlusIcon.js +12 -2
- package/icons/HeartPlusOutlineIcon.js +12 -2
- package/icons/HomeIcon.js +11 -2
- package/icons/InfoIcon.js +11 -2
- package/icons/InfoOutlineIcon.js +11 -2
- package/icons/ListIcon.js +11 -2
- package/icons/LocalShippingIcon.js +11 -2
- package/icons/LocationIcon.js +13 -3
- package/icons/LocatorIcon.js +11 -2
- package/icons/LockIcon.js +11 -2
- package/icons/LogoutIcon.js +11 -2
- package/icons/MagnifierIcon.js +11 -2
- package/icons/MapMarkerIcon.js +24 -3
- package/icons/MoreIcon.js +11 -2
- package/icons/MoreVertIcon.js +11 -2
- package/icons/NotificationIcon.js +14 -3
- package/icons/PersonIcon.js +12 -2
- package/icons/PhoneIcon.js +13 -3
- package/icons/PlaceholderIcon.js +11 -2
- package/icons/RadioCheckedIcon.js +11 -2
- package/icons/RadioUncheckedIcon.js +11 -2
- package/icons/SecurityIcon.js +11 -2
- package/icons/ShippingMethodIcon.js +18 -3
- package/icons/ShoppingCartIcon.js +11 -2
- package/icons/SortIcon.js +11 -2
- package/icons/StarHalfIcon.js +18 -2
- package/icons/StarIcon.js +18 -2
- package/icons/StarOutlineIcon.js +11 -2
- package/icons/StopIcon.js +11 -2
- package/icons/TickIcon.js +11 -2
- package/icons/TimeIcon.js +14 -3
- package/icons/TrashIcon.js +11 -2
- package/icons/TrashOutlineIcon.js +12 -2
- package/icons/UncheckedIcon.js +11 -2
- package/icons/ViewListIcon.js +11 -2
- package/icons/VisibilityIcon.js +11 -2
- package/icons/VisibilityOffIcon.js +11 -2
- package/icons/WarningIcon.js +11 -2
- package/index.js +13 -1
- package/package.json +5 -5
|
@@ -1,5 +1,79 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { useState, useCallback, Fragment } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import pick from 'lodash/pick';
|
|
4
|
+
import { i18n } from '@shopgate/engage/core';
|
|
5
|
+
import Chevron from "../../icons/ChevronIcon";
|
|
6
|
+
import InfoField from "../InfoField";
|
|
7
|
+
import ContextMenu from "../../ContextMenu";
|
|
8
|
+
import styles from "./style";
|
|
9
|
+
|
|
10
|
+
/**
|
|
2
11
|
* @param {Object} props .
|
|
3
12
|
* @returns {JSX}
|
|
4
|
-
*/
|
|
5
|
-
|
|
13
|
+
*/
|
|
14
|
+
const SelectContextChoices = ({
|
|
15
|
+
options,
|
|
16
|
+
onChange,
|
|
17
|
+
value,
|
|
18
|
+
placeholder,
|
|
19
|
+
className,
|
|
20
|
+
label,
|
|
21
|
+
errorText,
|
|
22
|
+
showErrorText
|
|
23
|
+
}) => {
|
|
24
|
+
const [opened, setOpened] = useState(false);
|
|
25
|
+
const onMenuChange = useCallback(({
|
|
26
|
+
active
|
|
27
|
+
}) => {
|
|
28
|
+
setOpened(active);
|
|
29
|
+
}, []);
|
|
30
|
+
const onItemClick = useCallback(key => {
|
|
31
|
+
if (key === '') {
|
|
32
|
+
onChange([]);
|
|
33
|
+
} else if (value.includes(key)) {
|
|
34
|
+
// Eliminate value
|
|
35
|
+
onChange(value.filter(v => v !== key));
|
|
36
|
+
} else {
|
|
37
|
+
onChange([...value, key]);
|
|
38
|
+
}
|
|
39
|
+
}, [onChange, value]);
|
|
40
|
+
const hasValue = !!value && !!value.length;
|
|
41
|
+
const values = hasValue ? Object.values(pick(options, value)) : [];
|
|
42
|
+
return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(InfoField, {
|
|
43
|
+
className: className,
|
|
44
|
+
label: label,
|
|
45
|
+
errorText: errorText,
|
|
46
|
+
showErrorText: showErrorText,
|
|
47
|
+
hasValue: true,
|
|
48
|
+
rightElement: /*#__PURE__*/React.createElement(Chevron, {
|
|
49
|
+
className: styles.chevron
|
|
50
|
+
})
|
|
51
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
52
|
+
role: "button",
|
|
53
|
+
onClick: () => setOpened(true),
|
|
54
|
+
"aria-hidden": true,
|
|
55
|
+
tabIndex: "0",
|
|
56
|
+
className: styles.toggle
|
|
57
|
+
}, !hasValue && (placeholder || i18n.text('common.please_choose')), hasValue && values.join(', ')), /*#__PURE__*/React.createElement(ContextMenu, {
|
|
58
|
+
isOpened: opened,
|
|
59
|
+
onStateChange: onMenuChange,
|
|
60
|
+
showToggle: false,
|
|
61
|
+
scroll: true
|
|
62
|
+
}, Object.keys(options).map(key => /*#__PURE__*/React.createElement(ContextMenu.Item, {
|
|
63
|
+
key: key,
|
|
64
|
+
autoClose: false,
|
|
65
|
+
onClick: () => onItemClick(key),
|
|
66
|
+
className: hasValue && value.includes(key) ? styles.itemSelected : ''
|
|
67
|
+
}, options[key])))));
|
|
68
|
+
};
|
|
69
|
+
SelectContextChoices.defaultProps = {
|
|
70
|
+
className: '',
|
|
71
|
+
errorText: '',
|
|
72
|
+
placeholder: '',
|
|
73
|
+
label: '',
|
|
74
|
+
onChange: () => {},
|
|
75
|
+
options: {},
|
|
76
|
+
value: [],
|
|
77
|
+
showErrorText: true
|
|
78
|
+
};
|
|
79
|
+
export default SelectContextChoices;
|
|
@@ -1,4 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
'
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import SelectContextChoices from "./index";
|
|
4
|
+
jest.mock('@shopgate/engage/a11y/components');
|
|
5
|
+
jest.mock('@shopgate/engage/components');
|
|
6
|
+
describe('<SelectContextChoices />', () => {
|
|
7
|
+
// Simple tests for snapshots
|
|
8
|
+
const tests = {
|
|
9
|
+
'should render select with no options': {},
|
|
10
|
+
// eslint-disable-next-line extra-rules/no-single-line-objects
|
|
11
|
+
'should render select with 2 options': {
|
|
12
|
+
options: {
|
|
13
|
+
DE: 'Germany',
|
|
14
|
+
US: 'United states'
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
// eslint-disable-next-line extra-rules/no-single-line-objects
|
|
18
|
+
'should render select with 1 selected option': {
|
|
19
|
+
options: {
|
|
20
|
+
DE: 'Germany',
|
|
21
|
+
US: 'United states'
|
|
22
|
+
},
|
|
23
|
+
value: ['DE']
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
Object.keys(tests).forEach(test => {
|
|
27
|
+
it(test, () => {
|
|
28
|
+
const testFixtures = tests[test];
|
|
29
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(SelectContextChoices, testFixtures));
|
|
30
|
+
expect(wrapper).toMatchSnapshot();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -1 +1,23 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import { themeConfig } from '@shopgate/pwa-common/helpers/config';
|
|
3
|
+
const chevron = css({
|
|
4
|
+
position: 'absolute',
|
|
5
|
+
top: '50%',
|
|
6
|
+
right: 0,
|
|
7
|
+
transform: 'translateY(-50%) rotateZ(-90deg)',
|
|
8
|
+
fontSize: '1.3em !important',
|
|
9
|
+
marginTop: -3
|
|
10
|
+
}).toString();
|
|
11
|
+
const toggle = css({
|
|
12
|
+
fontSize: '1rem',
|
|
13
|
+
paddingRight: '2rem'
|
|
14
|
+
});
|
|
15
|
+
const itemSelected = css({
|
|
16
|
+
backgroundColor: themeConfig.colors.shade8,
|
|
17
|
+
fontWeight: 500
|
|
18
|
+
}).toString();
|
|
19
|
+
export default {
|
|
20
|
+
chevron,
|
|
21
|
+
toggle,
|
|
22
|
+
itemSelected
|
|
23
|
+
};
|
package/Form/TextField/index.js
CHANGED
|
@@ -1,14 +1,98 @@
|
|
|
1
|
-
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { Component } from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import Input from '@shopgate/pwa-common/components/Input';
|
|
5
|
+
import Grid from '@shopgate/pwa-common/components/Grid';
|
|
6
|
+
import FormElement from '@shopgate/pwa-ui-shared/FormElement';
|
|
7
|
+
import style from "./style";
|
|
8
|
+
|
|
9
|
+
/**
|
|
2
10
|
* No operational
|
|
3
|
-
*/
|
|
11
|
+
*/
|
|
12
|
+
const noop = () => {};
|
|
13
|
+
|
|
14
|
+
/**
|
|
4
15
|
* TextField component
|
|
5
|
-
*/
|
|
16
|
+
*/
|
|
17
|
+
class TextField extends Component {
|
|
18
|
+
/**
|
|
6
19
|
* Creates a new text field component.
|
|
7
20
|
* @param {Object} props The component properties.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
*/
|
|
22
|
+
constructor(props) {
|
|
23
|
+
super(props);
|
|
24
|
+
/**
|
|
25
|
+
* Internal focus event handler.
|
|
26
|
+
* @param {boolean} isFocused Whether the input component is focused.
|
|
27
|
+
*/
|
|
28
|
+
this.handleFocusChange = isFocused => {
|
|
29
|
+
this.setState({
|
|
30
|
+
isFocused
|
|
31
|
+
});
|
|
32
|
+
this.props.onFocusChange(isFocused);
|
|
33
|
+
};
|
|
34
|
+
this.state = {
|
|
35
|
+
isFocused: false
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
12
39
|
* Renders the text field.
|
|
13
40
|
* @return {JSX.Element}
|
|
14
|
-
*/
|
|
41
|
+
*/
|
|
42
|
+
render() {
|
|
43
|
+
const {
|
|
44
|
+
className,
|
|
45
|
+
placeholder,
|
|
46
|
+
label,
|
|
47
|
+
errorText,
|
|
48
|
+
leftElement,
|
|
49
|
+
rightElement,
|
|
50
|
+
hasUnderline,
|
|
51
|
+
...props
|
|
52
|
+
} = this.props;
|
|
53
|
+
return /*#__PURE__*/React.createElement(FormElement, {
|
|
54
|
+
className: `${className} ui-shared__form__text-field`,
|
|
55
|
+
htmlFor: props.name,
|
|
56
|
+
placeholder: placeholder,
|
|
57
|
+
label: label,
|
|
58
|
+
errorText: errorText,
|
|
59
|
+
hasLeftElement: !!leftElement,
|
|
60
|
+
hasUnderline: hasUnderline,
|
|
61
|
+
hasValue: !!props.value,
|
|
62
|
+
isFocused: this.state.isFocused
|
|
63
|
+
}, /*#__PURE__*/React.createElement(Grid, null, leftElement && /*#__PURE__*/React.createElement(Grid.Item, {
|
|
64
|
+
grow: 0,
|
|
65
|
+
className: style.element
|
|
66
|
+
}, leftElement), /*#__PURE__*/React.createElement(Grid.Item, {
|
|
67
|
+
grow: 1,
|
|
68
|
+
className: style.container
|
|
69
|
+
}, /*#__PURE__*/React.createElement(Input, _extends({}, props, {
|
|
70
|
+
onFocusChange: this.handleFocusChange,
|
|
71
|
+
className: `
|
|
72
|
+
${style[props.multiLine ? 'multiLine' : 'input']}
|
|
73
|
+
${leftElement ? style.leftOffset : ''}
|
|
74
|
+
`,
|
|
75
|
+
validateOnBlur: true
|
|
76
|
+
}))), rightElement && /*#__PURE__*/React.createElement(Grid.Item, {
|
|
77
|
+
grow: 0,
|
|
78
|
+
className: style.element
|
|
79
|
+
}, rightElement)));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
TextField.defaultProps = {
|
|
83
|
+
attributes: null,
|
|
84
|
+
className: '',
|
|
85
|
+
errorText: '',
|
|
86
|
+
hasUnderline: true,
|
|
87
|
+
label: '',
|
|
88
|
+
leftElement: null,
|
|
89
|
+
onChange: noop,
|
|
90
|
+
onFocusChange: noop,
|
|
91
|
+
placeholder: '',
|
|
92
|
+
multiLine: false,
|
|
93
|
+
rightElement: null,
|
|
94
|
+
value: '',
|
|
95
|
+
type: 'text',
|
|
96
|
+
maxLength: ''
|
|
97
|
+
};
|
|
98
|
+
export default TextField;
|
package/Form/TextField/spec.js
CHANGED
|
@@ -1 +1,110 @@
|
|
|
1
|
-
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { mount } from 'enzyme';
|
|
4
|
+
import TextField from "./index";
|
|
5
|
+
const inputProps = {
|
|
6
|
+
name: 'test-input'
|
|
7
|
+
};
|
|
8
|
+
describe('<TextField>', () => {
|
|
9
|
+
it('should render a simple text field', () => {
|
|
10
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, inputProps));
|
|
11
|
+
expect(wrapper).toMatchSnapshot();
|
|
12
|
+
expect(wrapper.find('input').length).toBe(1);
|
|
13
|
+
});
|
|
14
|
+
it('should render the text field as password', () => {
|
|
15
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
16
|
+
password: true
|
|
17
|
+
})));
|
|
18
|
+
expect(wrapper).toMatchSnapshot();
|
|
19
|
+
expect(wrapper.find('input[type="password"]').length).toBe(1);
|
|
20
|
+
});
|
|
21
|
+
it('should render the text field with a default value', () => {
|
|
22
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
23
|
+
value: "FooBar"
|
|
24
|
+
})));
|
|
25
|
+
expect(wrapper).toMatchSnapshot();
|
|
26
|
+
expect(wrapper.find('input[value="FooBar"]').length).toBe(1);
|
|
27
|
+
});
|
|
28
|
+
it('should trigger the onChange callback', () => {
|
|
29
|
+
const onChangeMock = jest.fn();
|
|
30
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
31
|
+
onChange: onChangeMock
|
|
32
|
+
})));
|
|
33
|
+
wrapper.find('input').simulate('change', {
|
|
34
|
+
target: {
|
|
35
|
+
value: 'a'
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
expect(onChangeMock).toHaveBeenCalledTimes(2);
|
|
39
|
+
expect(wrapper.find('input').props().value).toEqual('a');
|
|
40
|
+
});
|
|
41
|
+
it('should receive the correct value while typing', () => {
|
|
42
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, inputProps));
|
|
43
|
+
const input = wrapper.find('input');
|
|
44
|
+
input.simulate('change', {
|
|
45
|
+
target: {
|
|
46
|
+
value: 'foobar'
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
expect(wrapper).toMatchSnapshot();
|
|
50
|
+
expect(input.instance().value).toBe('foobar');
|
|
51
|
+
});
|
|
52
|
+
it('should sanitize the input', () => {
|
|
53
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
54
|
+
onSanitize: value => value.toUpperCase()
|
|
55
|
+
})));
|
|
56
|
+
const input = wrapper.find('input');
|
|
57
|
+
input.simulate('change', {
|
|
58
|
+
target: {
|
|
59
|
+
value: 'foobar'
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
expect(wrapper).toMatchSnapshot();
|
|
63
|
+
expect(input.instance().value).toBe('FOOBAR');
|
|
64
|
+
});
|
|
65
|
+
it('should trigger the validation callback', () => {
|
|
66
|
+
const onValidateMock = jest.fn();
|
|
67
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
68
|
+
onValidate: onValidateMock
|
|
69
|
+
})));
|
|
70
|
+
expect(wrapper).toMatchSnapshot();
|
|
71
|
+
expect(onValidateMock).toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
it('should focus the input', () => {
|
|
74
|
+
const onFocusMock = jest.fn();
|
|
75
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
76
|
+
onFocusChange: onFocusMock
|
|
77
|
+
})));
|
|
78
|
+
const input = wrapper.find('SimpleInput');
|
|
79
|
+
expect(wrapper).toMatchSnapshot();
|
|
80
|
+
expect(input.instance().isFocused).toBe(false);
|
|
81
|
+
input.simulate('focus');
|
|
82
|
+
expect(input.instance().isFocused).toBe(true);
|
|
83
|
+
input.simulate('blur');
|
|
84
|
+
expect(input.instance().isFocused).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
it('should show the error message', () => {
|
|
87
|
+
const errorText = 'This is an error here';
|
|
88
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
89
|
+
errorText: errorText
|
|
90
|
+
})));
|
|
91
|
+
expect(wrapper).toMatchSnapshot();
|
|
92
|
+
expect(wrapper.find('ErrorText').find('Translate').at(0).props().string).toEqual(errorText);
|
|
93
|
+
});
|
|
94
|
+
it('should show the label', () => {
|
|
95
|
+
const label = 'This is the label';
|
|
96
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
97
|
+
label: label
|
|
98
|
+
})));
|
|
99
|
+
expect(wrapper).toMatchSnapshot();
|
|
100
|
+
expect(wrapper.find('Label').find('Translate').props().string).toEqual(label);
|
|
101
|
+
});
|
|
102
|
+
it('should show the placeholder text', () => {
|
|
103
|
+
const placeholder = 'This is the placeholder text';
|
|
104
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(TextField, _extends({}, inputProps, {
|
|
105
|
+
placeholder: placeholder
|
|
106
|
+
})));
|
|
107
|
+
expect(wrapper).toMatchSnapshot();
|
|
108
|
+
expect(wrapper.find('Placeholder').find('Translate').at(0).props().string).toEqual(placeholder);
|
|
109
|
+
});
|
|
110
|
+
});
|
package/Form/TextField/style.js
CHANGED
|
@@ -1,12 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
|
|
3
|
+
// Selects a date input that is not focused.
|
|
4
|
+
const bluredDateSelector = 'input[type="date"]:in-range:not(:focus)';
|
|
5
|
+
|
|
6
|
+
/**
|
|
3
7
|
* The styles for the container element.
|
|
4
|
-
*/
|
|
5
|
-
|
|
8
|
+
*/
|
|
9
|
+
const container = css({
|
|
10
|
+
// Fixes layout issue with webkit. Height is 0 in some webkit browsers.
|
|
11
|
+
'& input[type="date"]': {
|
|
12
|
+
minHeight: '1.3rem',
|
|
13
|
+
appearance: 'none',
|
|
14
|
+
paddingLeft: 0,
|
|
15
|
+
marginLeft: 0
|
|
16
|
+
},
|
|
17
|
+
// Removes placeholder texts on chrome when input is not focused.
|
|
18
|
+
[`& ${bluredDateSelector}::-webkit-datetime-edit-year-field, ` + `${bluredDateSelector}::-webkit-datetime-edit-month-field, ` + `${bluredDateSelector}::-webkit-datetime-edit-day-field, ` + `${bluredDateSelector}::-webkit-datetime-edit-text`]: {
|
|
19
|
+
padding: 0,
|
|
20
|
+
color: 'transparent'
|
|
21
|
+
}
|
|
22
|
+
}).toString();
|
|
23
|
+
|
|
24
|
+
/**
|
|
6
25
|
* The styles for the input field.
|
|
7
|
-
*/
|
|
26
|
+
*/
|
|
27
|
+
const input = css({
|
|
28
|
+
position: 'relative',
|
|
29
|
+
padding: 0,
|
|
30
|
+
width: '100%',
|
|
31
|
+
marginTop: 24,
|
|
32
|
+
outline: 0,
|
|
33
|
+
fontSize: 16,
|
|
34
|
+
lineHeight: '19px'
|
|
35
|
+
}).toString();
|
|
36
|
+
|
|
37
|
+
/**
|
|
8
38
|
* The styles for the multiLine.
|
|
9
|
-
*/
|
|
10
|
-
|
|
39
|
+
*/
|
|
40
|
+
const multiLine = css({
|
|
41
|
+
position: 'relative',
|
|
42
|
+
marginTop: 24,
|
|
43
|
+
marginBottom: 3,
|
|
44
|
+
padding: 0,
|
|
45
|
+
width: '100%',
|
|
46
|
+
outline: 0,
|
|
47
|
+
height: 19,
|
|
48
|
+
minHeight: 19,
|
|
49
|
+
lineHeight: '19px',
|
|
50
|
+
verticalAlign: 'top' // Important to avoid bottom whitespace.
|
|
51
|
+
}).toString();
|
|
52
|
+
const element = css({
|
|
53
|
+
marginTop: 16,
|
|
54
|
+
display: 'flex',
|
|
55
|
+
alignItems: 'flex-end'
|
|
56
|
+
}).toString();
|
|
57
|
+
|
|
58
|
+
/**
|
|
11
59
|
* Additional left spacing when a left element is present
|
|
12
|
-
*/
|
|
60
|
+
*/
|
|
61
|
+
const leftOffset = css({
|
|
62
|
+
marginLeft: 2
|
|
63
|
+
}).toString();
|
|
64
|
+
export default {
|
|
65
|
+
container,
|
|
66
|
+
input,
|
|
67
|
+
multiLine,
|
|
68
|
+
element,
|
|
69
|
+
leftOffset
|
|
70
|
+
};
|
package/Form/index.js
CHANGED
|
@@ -1,17 +1,58 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { PureComponent } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
2
5
|
* Form component that handles keyboard submit, next buttons, ...
|
|
3
6
|
* @deprecated Use `@shopgate/engage/components/Form` instead.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/_defineProperty(_this2,"handleSubmit",function(event){event.preventDefault();var inputFocused=[].concat(_this2.formElement.current.querySelectorAll('input')).some(function(input){return document.activeElement===input;});if(inputFocused){document.activeElement.blur();}_this2.props.onSubmit();});/**
|
|
8
|
-
* Handles form submits by key.
|
|
9
|
-
* @param {Object} event The event that caused the keypress.
|
|
10
|
-
*/_defineProperty(_this2,"handleKeyPress",function(event){// Enter key and on iOS also the "Done" button.
|
|
11
|
-
if(event.which===13){_this2.handleSubmit(event);}});_this2.formElement=React.createRef();return _this2;}_inherits(Form,_PureComponent);return _createClass(Form,[{key:"render",value:/**
|
|
12
|
-
* Renders the component.
|
|
13
|
-
* @returns {JSX}
|
|
14
|
-
*/function render(){/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */return React.createElement("form",{action:"#",onSubmit:this.handleSubmit,onKeyPress:this.handleKeyPress,ref:this.formElement,className:"ui-shared__form"},this.props.children);/* eslint-enable jsx-a11y/no-noninteractive-element-interactions */}}]);}(PureComponent);_defineProperty(Form,"defaultProps",{onSubmit:function onSubmit(){}/**
|
|
7
|
+
*/
|
|
8
|
+
class Form extends PureComponent {
|
|
9
|
+
/**
|
|
15
10
|
* Initializes the form component.
|
|
16
11
|
* @param {Object} props The components props.
|
|
17
|
-
*/
|
|
12
|
+
*/
|
|
13
|
+
constructor(props) {
|
|
14
|
+
super(props);
|
|
15
|
+
/**
|
|
16
|
+
* Handles the form submit.
|
|
17
|
+
* @param {Object} event The event that caused the submit.
|
|
18
|
+
*/
|
|
19
|
+
this.handleSubmit = event => {
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
const inputFocused = [...this.formElement.current.querySelectorAll('input')].some(input => document.activeElement === input);
|
|
22
|
+
if (inputFocused) {
|
|
23
|
+
document.activeElement.blur();
|
|
24
|
+
}
|
|
25
|
+
this.props.onSubmit();
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Handles form submits by key.
|
|
29
|
+
* @param {Object} event The event that caused the keypress.
|
|
30
|
+
*/
|
|
31
|
+
this.handleKeyPress = event => {
|
|
32
|
+
// Enter key and on iOS also the "Done" button.
|
|
33
|
+
if (event.which === 13) {
|
|
34
|
+
this.handleSubmit(event);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
this.formElement = /*#__PURE__*/React.createRef();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Renders the component.
|
|
41
|
+
* @returns {JSX}
|
|
42
|
+
*/
|
|
43
|
+
render() {
|
|
44
|
+
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
|
|
45
|
+
return /*#__PURE__*/React.createElement("form", {
|
|
46
|
+
action: "#",
|
|
47
|
+
onSubmit: this.handleSubmit,
|
|
48
|
+
onKeyPress: this.handleKeyPress,
|
|
49
|
+
ref: this.formElement,
|
|
50
|
+
className: "ui-shared__form"
|
|
51
|
+
}, this.props.children);
|
|
52
|
+
/* eslint-enable jsx-a11y/no-noninteractive-element-interactions */
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
Form.defaultProps = {
|
|
56
|
+
onSubmit: () => {}
|
|
57
|
+
};
|
|
58
|
+
export default Form;
|
|
@@ -1,5 +1,34 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import I18n from '@shopgate/pwa-common/components/I18n';
|
|
5
|
+
import styles from "./style";
|
|
6
|
+
|
|
7
|
+
/**
|
|
2
8
|
* Error message component.
|
|
3
9
|
* @param {Object} props The component props.
|
|
4
10
|
* @returns {JSX.Element}
|
|
5
|
-
*/
|
|
11
|
+
*/
|
|
12
|
+
const ErrorText = ({
|
|
13
|
+
className,
|
|
14
|
+
errorText,
|
|
15
|
+
translate,
|
|
16
|
+
elementName,
|
|
17
|
+
ariaHidden
|
|
18
|
+
}) => /*#__PURE__*/React.createElement("div", {
|
|
19
|
+
id: `ariaError-${elementName}`,
|
|
20
|
+
className: classNames(className, styles, 'errorText'),
|
|
21
|
+
"aria-live": "assertive",
|
|
22
|
+
"aria-atomic": "true",
|
|
23
|
+
"aria-hidden": ariaHidden
|
|
24
|
+
}, translate && /*#__PURE__*/React.createElement(I18n.Text, {
|
|
25
|
+
string: errorText
|
|
26
|
+
}), !translate && errorText);
|
|
27
|
+
ErrorText.defaultProps = {
|
|
28
|
+
className: null,
|
|
29
|
+
errorText: null,
|
|
30
|
+
elementName: null,
|
|
31
|
+
translate: true,
|
|
32
|
+
ariaHidden: false
|
|
33
|
+
};
|
|
34
|
+
export default ErrorText;
|
|
@@ -1 +1,13 @@
|
|
|
1
|
-
import{css}from'glamor';
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import { themeConfig } from '@shopgate/pwa-common/helpers/config';
|
|
3
|
+
export default css({
|
|
4
|
+
bottom: 2,
|
|
5
|
+
color: `var(--color-state-alert, ${themeConfig.colors.error})`,
|
|
6
|
+
fontSize: 12,
|
|
7
|
+
lineHeight: '14px',
|
|
8
|
+
overflow: 'hidden',
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
textOverflow: 'ellipsis',
|
|
11
|
+
whiteSpace: 'nowrap',
|
|
12
|
+
width: '100%'
|
|
13
|
+
}).toString();
|
|
@@ -1,5 +1,38 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import I18n from '@shopgate/pwa-common/components/I18n';
|
|
5
|
+
import styles from "./style";
|
|
6
|
+
|
|
7
|
+
/**
|
|
2
8
|
* Renders the label element.
|
|
3
9
|
* @param {Object} props The component props.
|
|
4
10
|
* @return {JSX}
|
|
5
|
-
*/
|
|
11
|
+
*/
|
|
12
|
+
const Label = ({
|
|
13
|
+
hasErrorMessage,
|
|
14
|
+
htmlFor,
|
|
15
|
+
isFloating,
|
|
16
|
+
isFocused,
|
|
17
|
+
label,
|
|
18
|
+
labelStatic
|
|
19
|
+
}) => {
|
|
20
|
+
const labelStyles = styles.labelStyles(isFocused, isFloating, hasErrorMessage, labelStatic);
|
|
21
|
+
return /*#__PURE__*/ /* eslint-disable-next-line jsx-a11y/label-has-associated-control */React.createElement("label", {
|
|
22
|
+
htmlFor: htmlFor,
|
|
23
|
+
className: classNames(labelStyles, 'label', {
|
|
24
|
+
floating: isFloating
|
|
25
|
+
})
|
|
26
|
+
}, /*#__PURE__*/React.createElement(I18n.Text, {
|
|
27
|
+
string: label
|
|
28
|
+
}));
|
|
29
|
+
};
|
|
30
|
+
Label.defaultProps = {
|
|
31
|
+
htmlFor: '',
|
|
32
|
+
isFocused: false,
|
|
33
|
+
isFloating: false,
|
|
34
|
+
hasErrorMessage: false,
|
|
35
|
+
label: '',
|
|
36
|
+
labelStatic: false
|
|
37
|
+
};
|
|
38
|
+
export default Label;
|