@shopgate/pwa-common 7.30.0-alpha.7 → 7.30.0-alpha.8
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/App.js +48 -6
- package/action-creators/app/index.js +75 -12
- package/action-creators/app/spec.js +96 -1
- package/action-creators/client/index.js +27 -5
- package/action-creators/client/spec.js +44 -1
- package/action-creators/error/index.js +15 -3
- package/action-creators/index.js +9 -1
- package/action-creators/menu/index.js +23 -4
- package/action-creators/menu/spec.js +37 -1
- package/action-creators/modal/index.js +15 -3
- package/action-creators/modal/spec.js +26 -1
- package/action-creators/page/index.js +24 -4
- package/action-creators/page/spec.js +38 -1
- package/action-creators/router/index.js +48 -7
- package/action-creators/url/index.js +24 -4
- package/action-creators/url/spec.js +45 -1
- package/action-creators/user/index.js +90 -13
- package/action-creators/user/spec.js +186 -2
- package/actions/app/handleDeepLink.js +11 -2
- package/actions/app/handleLink.js +62 -6
- package/actions/app/handlePushNotification.js +32 -4
- package/actions/app/handleUniversalLink.js +11 -2
- package/actions/app/registerLinkEvents.js +24 -3
- package/actions/client/fetchClientInformation.js +26 -2
- package/actions/menu/fetchMenu.js +23 -2
- package/actions/modal/closeModal.js +18 -2
- package/actions/modal/promiseMap.js +3 -1
- package/actions/modal/showModal.js +54 -8
- package/actions/page/fetchPageConfig.js +69 -2
- package/actions/page/getPageConfig.js +6 -2
- package/actions/page/index.js +1 -1
- package/actions/router/historyPop.js +12 -2
- package/actions/router/historyPopToRoute.js +27 -2
- package/actions/router/historyPush.js +12 -2
- package/actions/router/historyRedirect.js +21 -2
- package/actions/router/historyReplace.js +20 -3
- package/actions/router/historyReset.js +11 -2
- package/actions/router/historyResetTo.js +12 -2
- package/actions/router/index.js +17 -1
- package/actions/router/routeDidPop.js +11 -2
- package/actions/router/routeDidPush.js +13 -2
- package/actions/router/routeDidReplace.js +11 -2
- package/actions/router/routeDidReset.js +11 -2
- package/actions/router/routeDidUpdate.js +10 -2
- package/actions/router/routeWillPop.js +11 -2
- package/actions/router/routeWillPush.js +13 -2
- package/actions/router/routeWillReplace.js +11 -2
- package/actions/router/routeWillReset.js +11 -2
- package/actions/router/windowOpenOverride.js +10 -2
- package/actions/user/fetchRegisterUrl.js +36 -2
- package/actions/user/fetchUser.js +29 -3
- package/actions/user/getUser.js +6 -2
- package/actions/user/index.js +1 -1
- package/actions/user/login.js +76 -9
- package/actions/user/logout.js +30 -2
- package/collections/AuthRoutes.js +73 -14
- package/collections/Configuration.js +54 -7
- package/collections/EmbeddedMedia.js +84 -11
- package/collections/PersistedReducers.js +41 -6
- package/collections/Redirects.js +103 -17
- package/collections/index.js +5 -1
- package/collections/media-providers/MediaProvider.js +151 -26
- package/collections/media-providers/Vimeo.js +113 -19
- package/collections/media-providers/YouTube.js +74 -14
- package/collections/media-providers/index.js +3 -1
- package/collections/media-providers/style.js +52 -2
- package/components/Backdrop/index.js +95 -6
- package/components/Backdrop/spec.js +23 -1
- package/components/Backdrop/style.js +11 -2
- package/components/Button/index.js +47 -5
- package/components/Button/spec.js +36 -1
- package/components/Button/style.js +6 -1
- package/components/Checkbox/index.js +126 -32
- package/components/Checkbox/spec.js +94 -3
- package/components/Consume/helpers/buildParams.js +13 -2
- package/components/Consume/index.js +14 -2
- package/components/CountdownTimer/index.js +115 -17
- package/components/CountdownTimer/spec.js +126 -12
- package/components/Drawer/index.js +131 -16
- package/components/Drawer/spec.js +76 -1
- package/components/Drawer/style.js +37 -1
- package/components/Dropdown/index.js +65 -6
- package/components/Dropdown/style.js +4 -1
- package/components/Dropdown/transitions.js +34 -1
- package/components/Ellipsis/index.js +16 -2
- package/components/Ellipsis/spec.js +13 -1
- package/components/EmbeddedMedia/index.js +56 -6
- package/components/EmbeddedMedia/spec.js +52 -3
- package/components/ErrorBoundary/connector.js +9 -2
- package/components/ErrorBoundary/index.js +43 -7
- package/components/Grid/components/Item/index.js +40 -4
- package/components/Grid/components/Item/spec.js +23 -1
- package/components/Grid/components/Item/style.js +17 -3
- package/components/Grid/index.js +36 -4
- package/components/Grid/spec.js +23 -1
- package/components/Grid/style.js +11 -2
- package/components/HtmlSanitizer/connector.js +24 -3
- package/components/HtmlSanitizer/index.js +104 -12
- package/components/HtmlSanitizer/spec.js +207 -6
- package/components/I18n/components/FormatDate/index.js +26 -2
- package/components/I18n/components/FormatDate/spec.js +46 -1
- package/components/I18n/components/FormatNumber/index.js +34 -2
- package/components/I18n/components/FormatNumber/spec.js +41 -2
- package/components/I18n/components/FormatPrice/index.js +32 -2
- package/components/I18n/components/FormatPrice/spec.js +46 -1
- package/components/I18n/components/FormatTime/index.js +26 -2
- package/components/I18n/components/FormatTime/spec.js +43 -2
- package/components/I18n/components/I18nProvider/index.js +52 -9
- package/components/I18n/components/I18nProvider/spec.js +39 -1
- package/components/I18n/components/Placeholder/index.js +8 -2
- package/components/I18n/components/Placeholder/spec.js +30 -1
- package/components/I18n/components/Translate/index.js +68 -7
- package/components/I18n/components/Translate/spec.js +30 -1
- package/components/I18n/index.js +16 -1
- package/components/Icon/index.js +25 -2
- package/components/Icon/style.js +6 -1
- package/components/Image/Image.js +176 -19
- package/components/Image/ImageInner.js +48 -2
- package/components/Image/index.js +1 -1
- package/components/Image/style.js +29 -2
- package/components/InfiniteContainer/index.js +381 -49
- package/components/InfiniteContainer/spec.js +199 -10
- package/components/Input/components/DateInput.js +262 -6
- package/components/Input/components/MultiLineInput.js +98 -12
- package/components/Input/components/SimpleInput.js +207 -31
- package/components/Input/index.js +32 -3
- package/components/Input/spec.js +122 -1
- package/components/KeyboardConsumer/index.js +48 -7
- package/components/Link/connector.js +7 -1
- package/components/Link/index.js +96 -11
- package/components/Link/spec.js +56 -1
- package/components/Link/style.js +10 -1
- package/components/List/components/Item/index.js +35 -3
- package/components/List/components/Item/style.js +16 -1
- package/components/List/index.js +20 -2
- package/components/List/spec.js +31 -1
- package/components/Loading/index.js +6 -2
- package/components/Modal/index.js +38 -3
- package/components/Modal/style.js +36 -1
- package/components/ModalContainer/connector.js +17 -3
- package/components/ModalContainer/index.js +36 -3
- package/components/ModalContainer/spec.js +105 -5
- package/components/Picker/components/Button/index.js +34 -2
- package/components/Picker/components/Button/style.js +19 -1
- package/components/Picker/components/List/index.js +33 -2
- package/components/Picker/components/List/style.js +17 -1
- package/components/Picker/components/Modal/index.js +60 -7
- package/components/Picker/components/Modal/style.js +78 -1
- package/components/Picker/index.js +167 -21
- package/components/Picker/spec.js +83 -2
- package/components/Portal/index.js +130 -19
- package/components/ProductCharacteristics/connector.js +33 -4
- package/components/ProductCharacteristics/context.js +2 -1
- package/components/ProductCharacteristics/helpers/index.js +135 -21
- package/components/ProductCharacteristics/index.js +266 -31
- package/components/RangeSlider/components/Handle/index.js +25 -2
- package/components/RangeSlider/components/Handle/style.js +14 -1
- package/components/RangeSlider/helper.js +43 -8
- package/components/RangeSlider/index.js +228 -38
- package/components/RangeSlider/style.js +14 -1
- package/components/Route/RouteNotFound.js +46 -3
- package/components/Route/index.js +78 -10
- package/components/Router/connector.js +9 -2
- package/components/Router/index.js +237 -31
- package/components/ScannerContainer/connector.js +9 -2
- package/components/ScannerContainer/index.js +42 -6
- package/components/Select/components/Item/index.js +20 -4
- package/components/Select/components/Item/style.js +4 -1
- package/components/Select/index.js +149 -28
- package/components/Select/spec.js +86 -2
- package/components/Select/style.js +17 -1
- package/components/SelectBox/components/Item/index.js +47 -5
- package/components/SelectBox/components/Item/style.js +7 -1
- package/components/SelectBox/index.js +173 -17
- package/components/SelectBox/spec.js +59 -3
- package/components/SelectBox/style.js +18 -1
- package/components/Slider/index.js +6 -2
- package/components/SurroundPortals/index.js +26 -2
- package/components/Swiper/components/SwiperItem/index.js +28 -4
- package/components/Swiper/components/SwiperItem/spec.js +17 -1
- package/components/Swiper/components/SwiperItem/styles.js +5 -1
- package/components/Swiper/index.js +210 -18
- package/components/Swiper/styles.js +75 -7
- package/components/Toaster/index.js +10 -2
- package/components/Transition/index.js +89 -13
- package/components/Widgets/components/Widget/index.js +52 -4
- package/components/Widgets/components/Widget/spec.js +68 -3
- package/components/Widgets/components/Widget/style.js +21 -3
- package/components/Widgets/components/WidgetGrid/index.js +52 -7
- package/components/Widgets/components/WidgetGrid/spec.js +46 -2
- package/components/Widgets/components/WidgetGrid/style.js +8 -1
- package/components/Widgets/helpers/shouldShowWidget.js +44 -7
- package/components/Widgets/index.js +127 -15
- package/components/Widgets/spec.js +213 -6
- package/components/index.js +9 -1
- package/constants/ActionTypes.js +97 -19
- package/constants/Configuration.js +12 -2
- package/constants/Device.js +29 -2
- package/constants/DisplayOptions.js +8 -1
- package/constants/MenuIDs.js +2 -1
- package/constants/ModalTypes.js +1 -1
- package/constants/PageIDs.js +1 -1
- package/constants/Pipelines.js +7 -1
- package/constants/Portals.js +136 -3
- package/constants/Registration.js +3 -1
- package/constants/RoutePaths.js +13 -2
- package/constants/Tracking.js +3 -1
- package/constants/client.js +6 -1
- package/constants/ui.js +2 -1
- package/constants/user.js +6 -2
- package/context/index.js +33 -3
- package/helpers/config/index.js +139 -21
- package/helpers/config/mock.js +200 -8
- package/helpers/config/theme.js +50 -4
- package/helpers/data/index.js +204 -29
- package/helpers/data/spec.js +187 -7
- package/helpers/date/index.js +58 -6
- package/helpers/date/spec.js +92 -1
- package/helpers/dom/index.js +48 -11
- package/helpers/environment/index.js +14 -2
- package/helpers/html/decodeHTML.js +7 -1
- package/helpers/html/handleDOM.js +172 -21
- package/helpers/html/parseHTML.js +67 -12
- package/helpers/i18n/getDateFormatter.js +23 -4
- package/helpers/i18n/getNumberFormatter.js +32 -4
- package/helpers/i18n/getPriceFormatter.js +38 -4
- package/helpers/i18n/getTimeFormatter.js +23 -4
- package/helpers/i18n/getTranslator.js +62 -8
- package/helpers/i18n/index.js +5 -1
- package/helpers/i18n/mergeTranslations.js +36 -9
- package/helpers/i18n/messageCache.js +3 -1
- package/helpers/legacy/index.js +47 -9
- package/helpers/modal/withShowModal.js +13 -2
- package/helpers/portals/portalCollection.js +28 -6
- package/helpers/portals/routePortals.js +12 -1
- package/helpers/redux/compareObjects.js +7 -2
- package/helpers/redux/generateResultHash.js +36 -3
- package/helpers/redux/generateSortedHash.js +7 -2
- package/helpers/redux/hasExpired.js +10 -2
- package/helpers/redux/index.js +7 -1
- package/helpers/redux/mutable.js +143 -24
- package/helpers/redux/shouldFetchData.js +46 -10
- package/helpers/redux/shouldFetchFilters.js +17 -4
- package/helpers/router/index.js +49 -5
- package/helpers/style/index.js +43 -4
- package/helpers/style/spec.js +108 -2
- package/helpers/tracking/index.js +52 -9
- package/helpers/validation/index.js +39 -12
- package/helpers/validation/spec.js +10 -1
- package/package.json +3 -3
- package/providers/index.js +4 -1
- package/providers/loading/context.js +2 -1
- package/providers/loading/index.js +137 -22
- package/providers/toast/context.js +2 -1
- package/providers/toast/index.js +105 -11
- package/reducers/client/connectivity.js +22 -2
- package/reducers/client/index.js +7 -1
- package/reducers/client/info.js +27 -2
- package/reducers/index.js +23 -4
- package/reducers/menu/index.js +5 -1
- package/reducers/menu/menusById.js +41 -2
- package/reducers/modal/index.js +14 -2
- package/reducers/page/index.js +68 -5
- package/reducers/router/index.js +48 -2
- package/reducers/url/index.js +42 -3
- package/reducers/user/data.js +27 -2
- package/reducers/user/index.js +7 -1
- package/reducers/user/login.js +65 -2
- package/selectors/client.js +138 -21
- package/selectors/history.js +49 -11
- package/selectors/menu.js +34 -6
- package/selectors/modal.js +15 -4
- package/selectors/page.js +25 -4
- package/selectors/router.js +154 -30
- package/selectors/url.js +25 -4
- package/selectors/user.js +90 -13
- package/store/index.js +60 -6
- package/store/middelwares/logger.js +7 -1
- package/store/middelwares/streams.js +19 -2
- package/streams/app.js +60 -8
- package/streams/client.js +8 -2
- package/streams/error.js +14 -3
- package/streams/index.js +6 -1
- package/streams/interval.js +6 -2
- package/streams/main.js +27 -2
- package/streams/router.js +45 -8
- package/streams/user.js +89 -15
- package/streams/view.js +97 -25
- package/styles/reset/form.js +57 -5
- package/styles/reset/index.js +6 -1
- package/styles/reset/media.js +22 -1
- package/styles/reset/root.js +33 -1
- package/styles/reset/table.js +10 -1
- package/styles/reset/typography.js +26 -1
- package/subscriptions/app.js +148 -17
- package/subscriptions/error.js +292 -13
- package/subscriptions/helpers/buildRegisterUrl.js +25 -6
- package/subscriptions/helpers/clearUpInAppBrowser.js +14 -3
- package/subscriptions/helpers/handleLinks.js +267 -25
- package/subscriptions/helpers/pipeline.js +12 -1
- package/subscriptions/history.js +34 -6
- package/subscriptions/index.js +25 -4
- package/subscriptions/menu.js +22 -5
- package/subscriptions/mock.js +39 -7
- package/subscriptions/router.js +336 -23
- package/subscriptions/user.js +93 -3
|
@@ -1,31 +1,91 @@
|
|
|
1
|
-
|
|
1
|
+
import URLSearchParams from 'url-search-params';
|
|
2
|
+
import MediaProvider from "./MediaProvider";
|
|
3
|
+
|
|
4
|
+
/* eslint-disable class-methods-use-this */
|
|
5
|
+
|
|
6
|
+
/**
|
|
2
7
|
* The YouTube media provider class.
|
|
3
|
-
*/
|
|
8
|
+
*/
|
|
9
|
+
class YouTubeMediaProvider extends MediaProvider {
|
|
10
|
+
/**
|
|
4
11
|
* Retrieves a list of media containers for YouTube.
|
|
5
12
|
* @param {ParentNode} container A DOM container that may contain YouTube iframes.
|
|
6
13
|
* @returns {NodeListOf<Element>}
|
|
7
|
-
*/
|
|
14
|
+
*/
|
|
15
|
+
getMediaContainers(container) {
|
|
16
|
+
return container.querySelectorAll('iframe[src*="youtube.com"], iframe[src*="youtube-nocookie.com"]');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
8
20
|
* Add a DOM container with embedded videos.
|
|
9
21
|
* @override
|
|
10
22
|
* @param {ParentNode} container A DOM container.
|
|
11
23
|
* @returns {YouTubeMediaProvider}
|
|
12
|
-
*/
|
|
24
|
+
*/
|
|
25
|
+
add(container) {
|
|
26
|
+
const iframes = this.getMediaContainers(container);
|
|
27
|
+
if (!iframes.length) {
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
this.containers.set(container, iframes);
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
13
35
|
* Applies optimizations to embedded media iframes within the given container.
|
|
14
36
|
* Common enhancements include adding responsive wrappers and appropriate
|
|
15
37
|
* sandbox attributes to improve security and layout behavior.
|
|
16
38
|
*
|
|
17
39
|
* @param {Document} document - The DOM document containing iframes to optimize.
|
|
18
40
|
* @returns {YouTubeMediaProvider}
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
iframes
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
*/
|
|
42
|
+
applyIframeOptimizations(document) {
|
|
43
|
+
const iframes = this.getMediaContainers(document);
|
|
44
|
+
if (!iframes.length) {
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Update the video urls to enable stopping videos via the event API.
|
|
49
|
+
iframes.forEach((iframe, index) => {
|
|
50
|
+
// Block clicks on YouTube icon
|
|
51
|
+
iframes[index].setAttribute('sandbox', 'allow-forms allow-scripts allow-pointer-lock allow-same-origin allow-top-navigation');
|
|
52
|
+
this.responsify(iframe);
|
|
53
|
+
const src = iframe.getAttribute('src');
|
|
54
|
+
const [url, query] = src.split('?');
|
|
55
|
+
const urlParams = new URLSearchParams(query);
|
|
56
|
+
|
|
57
|
+
// Enable the js api to allow sending events to the iframe.
|
|
58
|
+
urlParams.set('enablejsapi', 1);
|
|
59
|
+
// Enable controls to avoid the iframe not being resumable because of controls=0 param on ios.
|
|
60
|
+
urlParams.set('controls', 1);
|
|
61
|
+
iframes[index].setAttribute('src', `${url}?${urlParams.toString()}`);
|
|
62
|
+
});
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
24
67
|
* Stops all playing videos within the DOM containers.
|
|
25
68
|
* @override
|
|
26
69
|
* @returns {YouTubeMediaProvider}
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
70
|
+
*/
|
|
71
|
+
stop() {
|
|
72
|
+
// Select all iframes in the document. Actually this should be done via the iframes
|
|
73
|
+
// registered in this.containers, but that doesn't seem to work reliably anymore.
|
|
74
|
+
// Since we had to find a quick fix for CURB-5033 we now select all iframes in the document
|
|
75
|
+
// via the media container selector and then stop the videos.
|
|
76
|
+
const iframes = this.getMediaContainers(document);
|
|
77
|
+
iframes.forEach(iframe => {
|
|
78
|
+
if (typeof iframe?.contentWindow?.postMessage === 'function') {
|
|
79
|
+
iframe.contentWindow.postMessage(JSON.stringify({
|
|
80
|
+
event: 'command',
|
|
81
|
+
func: 'stopVideo',
|
|
82
|
+
args: []
|
|
83
|
+
}), '*');
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export default YouTubeMediaProvider;
|
|
90
|
+
|
|
91
|
+
/* eslint-enable class-methods-use-this */
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
export{default as MediaProvider}
|
|
1
|
+
export { default as MediaProvider } from "./MediaProvider";
|
|
2
|
+
export { default as Vimeo } from "./Vimeo";
|
|
3
|
+
export { default as YouTube } from "./YouTube";
|
|
@@ -1,2 +1,52 @@
|
|
|
1
|
-
import{
|
|
2
|
-
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import { themeConfig } from '@shopgate/pwa-common/helpers/config';
|
|
3
|
+
const {
|
|
4
|
+
colors
|
|
5
|
+
} = themeConfig;
|
|
6
|
+
const responsiveContainer = css({
|
|
7
|
+
position: 'relative',
|
|
8
|
+
height: 0,
|
|
9
|
+
overflow: 'hidden',
|
|
10
|
+
padding: '56.25% 0 0 0',
|
|
11
|
+
fontSize: '0.875rem',
|
|
12
|
+
' iframe, object, embed': {
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
top: 0,
|
|
15
|
+
left: 0,
|
|
16
|
+
width: '100%',
|
|
17
|
+
height: '100%',
|
|
18
|
+
border: 0
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const consentContainer = css({
|
|
22
|
+
position: 'absolute',
|
|
23
|
+
height: '100%',
|
|
24
|
+
width: '100%',
|
|
25
|
+
padding: 16,
|
|
26
|
+
lineHeight: '1.2rem',
|
|
27
|
+
display: 'flex',
|
|
28
|
+
flexDirection: 'column',
|
|
29
|
+
justifyContent: 'center',
|
|
30
|
+
textAlign: 'center',
|
|
31
|
+
gap: 16,
|
|
32
|
+
background: colors.shade10,
|
|
33
|
+
border: `1px solid ${colors.shade5}`,
|
|
34
|
+
// Add a tiny little border radius to make the message container look nice with padding
|
|
35
|
+
borderRadius: 4,
|
|
36
|
+
top: 0
|
|
37
|
+
});
|
|
38
|
+
const consentLink = css({
|
|
39
|
+
textAlign: 'center',
|
|
40
|
+
color: colors.primary,
|
|
41
|
+
fontWeight: 500
|
|
42
|
+
}).toString();
|
|
43
|
+
const consentIcon = css({
|
|
44
|
+
fill: colors.shade5,
|
|
45
|
+
height: 40
|
|
46
|
+
});
|
|
47
|
+
export default {
|
|
48
|
+
responsiveContainer,
|
|
49
|
+
consentContainer,
|
|
50
|
+
consentLink,
|
|
51
|
+
consentIcon
|
|
52
|
+
};
|
|
@@ -1,9 +1,98 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Transition } from 'react-transition-group';
|
|
4
|
+
import { toggleBodyScroll } from '@shopgate/engage/styles/helpers';
|
|
5
|
+
import style from "./style";
|
|
6
|
+
|
|
7
|
+
/**
|
|
2
8
|
* Backdrop component
|
|
3
9
|
* @param {Object} props The component props.
|
|
4
10
|
* @returns {JSX.Element}
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
*/
|
|
12
|
+
function Backdrop({
|
|
13
|
+
className,
|
|
14
|
+
color,
|
|
15
|
+
duration,
|
|
16
|
+
isVisible,
|
|
17
|
+
level,
|
|
18
|
+
lockBodyScroll,
|
|
19
|
+
onClick,
|
|
20
|
+
opacity
|
|
21
|
+
}) {
|
|
22
|
+
// Stable id for body scroll lock
|
|
23
|
+
const bodyScrollRef = useRef(Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2));
|
|
24
|
+
const nodeRef = useRef(null);
|
|
25
|
+
|
|
26
|
+
// Lock / unlock body scroll based on visibility
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!lockBodyScroll) return undefined;
|
|
29
|
+
const refId = bodyScrollRef.current;
|
|
30
|
+
toggleBodyScroll(isVisible, refId);
|
|
31
|
+
return () => {
|
|
32
|
+
toggleBodyScroll(false, refId);
|
|
33
|
+
};
|
|
34
|
+
}, [isVisible, lockBodyScroll]);
|
|
35
|
+
const baseStyle = useMemo(() => ({
|
|
36
|
+
background: color,
|
|
37
|
+
zIndex: level,
|
|
38
|
+
transition: `opacity ${duration}ms ease-out`,
|
|
39
|
+
// start hidden by default; pointer events only when shown
|
|
40
|
+
opacity: 0,
|
|
41
|
+
pointerEvents: 'none'
|
|
42
|
+
}), [color, level, duration]);
|
|
43
|
+
const targetOpacity = useMemo(() => opacity / 100, [opacity]);
|
|
44
|
+
|
|
45
|
+
// Map Transition states to inline styles
|
|
46
|
+
const transitionStyles = useMemo(() => ({
|
|
47
|
+
entering: {
|
|
48
|
+
opacity: targetOpacity,
|
|
49
|
+
pointerEvents: 'auto'
|
|
50
|
+
},
|
|
51
|
+
entered: {
|
|
52
|
+
opacity: targetOpacity,
|
|
53
|
+
pointerEvents: 'auto'
|
|
54
|
+
},
|
|
55
|
+
exiting: {
|
|
56
|
+
opacity: 0,
|
|
57
|
+
pointerEvents: 'none'
|
|
58
|
+
},
|
|
59
|
+
exited: {
|
|
60
|
+
opacity: 0,
|
|
61
|
+
pointerEvents: 'none'
|
|
62
|
+
},
|
|
63
|
+
unmounted: {
|
|
64
|
+
opacity: 0,
|
|
65
|
+
pointerEvents: 'none'
|
|
66
|
+
}
|
|
67
|
+
}), [targetOpacity]);
|
|
68
|
+
const combinedClassName = `${style} ${className} common__backdrop`;
|
|
69
|
+
return /*#__PURE__*/React.createElement(Transition, {
|
|
70
|
+
in: isVisible,
|
|
71
|
+
timeout: duration,
|
|
72
|
+
mountOnEnter: true,
|
|
73
|
+
unmountOnExit: true,
|
|
74
|
+
appear: true,
|
|
75
|
+
nodeRef: nodeRef
|
|
76
|
+
}, state => /*#__PURE__*/React.createElement("div", {
|
|
77
|
+
ref: nodeRef,
|
|
78
|
+
"data-test-id": "Backdrop",
|
|
79
|
+
"aria-hidden": true,
|
|
80
|
+
className: combinedClassName,
|
|
81
|
+
onClick: onClick,
|
|
82
|
+
style: {
|
|
83
|
+
...baseStyle,
|
|
84
|
+
...transitionStyles[state]
|
|
85
|
+
}
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
Backdrop.defaultProps = {
|
|
89
|
+
className: '',
|
|
90
|
+
color: '#000',
|
|
91
|
+
duration: 200,
|
|
92
|
+
isVisible: false,
|
|
93
|
+
level: 2,
|
|
94
|
+
onClick: () => {},
|
|
95
|
+
opacity: 50,
|
|
96
|
+
lockBodyScroll: true
|
|
97
|
+
};
|
|
98
|
+
export default /*#__PURE__*/React.memo(Backdrop, (prev, next) => prev.isVisible === next.isVisible && prev.className === next.className && prev.color === next.color && prev.duration === next.duration && prev.level === next.level && prev.lockBodyScroll === next.lockBodyScroll && prev.opacity === next.opacity && prev.onClick === next.onClick);
|
|
@@ -1 +1,23 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow, mount } from 'enzyme';
|
|
3
|
+
import Backdrop from "./index";
|
|
4
|
+
describe('<Backdrop />', () => {
|
|
5
|
+
let mockOpen;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
mockOpen = jest.fn();
|
|
8
|
+
});
|
|
9
|
+
it('should render', () => {
|
|
10
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(Backdrop, {
|
|
11
|
+
isVisible: true
|
|
12
|
+
}));
|
|
13
|
+
expect(wrapper).toMatchSnapshot();
|
|
14
|
+
});
|
|
15
|
+
it('should execute callback when Backdrop is clicked', () => {
|
|
16
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(Backdrop, {
|
|
17
|
+
isVisible: true,
|
|
18
|
+
onClick: mockOpen
|
|
19
|
+
}));
|
|
20
|
+
wrapper.find('div').simulate('click');
|
|
21
|
+
expect(mockOpen).toBeCalled();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
import{css}from'glamor';
|
|
2
|
-
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
export default css({
|
|
3
|
+
position: 'fixed',
|
|
4
|
+
top: 0,
|
|
5
|
+
right: 0,
|
|
6
|
+
bottom: 0,
|
|
7
|
+
left: 0,
|
|
8
|
+
// Prevents that content behind the backdrop is clickable
|
|
9
|
+
pointerEvents: 'all',
|
|
10
|
+
touchAction: 'none'
|
|
11
|
+
});
|
|
@@ -1,10 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { Component } from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import style from "./style";
|
|
5
|
+
|
|
6
|
+
/**
|
|
2
7
|
* The button component.
|
|
3
|
-
*/
|
|
8
|
+
*/
|
|
9
|
+
class Button extends Component {
|
|
10
|
+
/**
|
|
4
11
|
* Getter for the calculated button props.
|
|
5
12
|
* @returns {Object}
|
|
6
|
-
*/
|
|
13
|
+
*/
|
|
14
|
+
get buttonProps() {
|
|
15
|
+
const {
|
|
16
|
+
children,
|
|
17
|
+
testId,
|
|
18
|
+
className,
|
|
19
|
+
disabled,
|
|
20
|
+
onClick,
|
|
21
|
+
...props
|
|
22
|
+
} = this.props;
|
|
23
|
+
const buttonProps = {
|
|
24
|
+
className: `${className} ${style} common__button`,
|
|
25
|
+
disabled,
|
|
26
|
+
onClick: disabled ? null : onClick,
|
|
27
|
+
...props
|
|
28
|
+
};
|
|
29
|
+
return buttonProps;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
7
33
|
* Renders the component.
|
|
8
34
|
* @returns {JSX.Element}
|
|
9
|
-
*/
|
|
10
|
-
|
|
35
|
+
*/
|
|
36
|
+
render() {
|
|
37
|
+
return (
|
|
38
|
+
/*#__PURE__*/
|
|
39
|
+
// eslint-disable-next-line react/button-has-type
|
|
40
|
+
React.createElement("button", _extends({
|
|
41
|
+
"data-test-id": this.props.testId
|
|
42
|
+
}, this.buttonProps), this.props.children)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
Button.defaultProps = {
|
|
47
|
+
className: '',
|
|
48
|
+
disabled: false,
|
|
49
|
+
onClick: null,
|
|
50
|
+
testId: 'Button'
|
|
51
|
+
};
|
|
52
|
+
export default Button;
|
|
@@ -1 +1,36 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import Button from "./index";
|
|
4
|
+
describe('<Button />', () => {
|
|
5
|
+
it('should render the button', () => {
|
|
6
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(Button, null, "My content"));
|
|
7
|
+
expect(wrapper).toMatchSnapshot();
|
|
8
|
+
expect(wrapper.find('button').length).toBe(1);
|
|
9
|
+
});
|
|
10
|
+
it('should render the button in disabled state', () => {
|
|
11
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(Button, {
|
|
12
|
+
disabled: true
|
|
13
|
+
}, "My content"));
|
|
14
|
+
expect(wrapper).toMatchSnapshot();
|
|
15
|
+
expect(wrapper.find('button[disabled]').length).toBe(1);
|
|
16
|
+
});
|
|
17
|
+
it('should trigger the click event', () => {
|
|
18
|
+
const callback = jest.fn();
|
|
19
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(Button, {
|
|
20
|
+
onClick: callback
|
|
21
|
+
}, "My content"));
|
|
22
|
+
wrapper.simulate('click');
|
|
23
|
+
expect(wrapper).toMatchSnapshot();
|
|
24
|
+
expect(callback).toHaveBeenCalled();
|
|
25
|
+
});
|
|
26
|
+
it('should not trigger the click event when disabled', () => {
|
|
27
|
+
const callback = jest.fn();
|
|
28
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(Button, {
|
|
29
|
+
disabled: true,
|
|
30
|
+
onClick: callback
|
|
31
|
+
}, "My content"));
|
|
32
|
+
wrapper.simulate('click');
|
|
33
|
+
expect(wrapper).toMatchSnapshot();
|
|
34
|
+
expect(callback).not.toHaveBeenCalled();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
|
|
5
|
+
/**
|
|
2
6
|
* @typedef {Object} CheckboxProps
|
|
3
7
|
* @property {React.ReactNode} checkedIcon React component used as icon for the checked state
|
|
4
8
|
* @property {React.ReactNode} uncheckedIcon React component used as icon for the unchecked state
|
|
@@ -10,45 +14,135 @@ function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="s
|
|
|
10
14
|
* @property {"left"|"right"} [labelPosition] Position for the lable (default `"left"`)
|
|
11
15
|
* @property {string} [name] Name for the hidden input tag
|
|
12
16
|
* @property {Function} [onCheck] Callback invoked when checkbox is toggled
|
|
13
|
-
*/
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
14
20
|
* Base checkbox component.
|
|
15
21
|
* @extends {React.Component<CheckboxProps>}
|
|
16
22
|
* @returns {JSX.Element}
|
|
17
|
-
*/
|
|
23
|
+
*/
|
|
24
|
+
class Checkbox extends Component {
|
|
25
|
+
/**
|
|
18
26
|
* The checkbox component constructor.
|
|
19
27
|
* It checks if the checkbox is a controlled or uncontrolled input and sets an internal state if
|
|
20
28
|
* uncontrolled to keep track of th checked-state.
|
|
21
29
|
* @param {Object} props The Checkbox properties.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
30
|
+
*/
|
|
31
|
+
constructor(props) {
|
|
32
|
+
super(props);
|
|
33
|
+
/**
|
|
34
|
+
* Returns if the checkbox is checked or not.
|
|
35
|
+
* @return {boolean} Is the checkbox checked?
|
|
36
|
+
*/
|
|
37
|
+
this.isChecked = () => typeof this.props.defaultChecked === 'undefined' ? this.props.checked // Controlled.
|
|
38
|
+
: this.state.checked // Uncontrolled.
|
|
39
|
+
;
|
|
40
|
+
/**
|
|
41
|
+
* Inverts the current "checked" value and calls the callback function with it.
|
|
42
|
+
* If the checkbox is uncontrolled, it keeps track of the value.
|
|
43
|
+
*/
|
|
44
|
+
this.handleCheck = () => {
|
|
45
|
+
if (this.props.disabled) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const checked = !this.isChecked();
|
|
49
|
+
if (typeof this.props.defaultChecked !== 'undefined') {
|
|
50
|
+
// Uncontrolled.
|
|
51
|
+
this.setState({
|
|
52
|
+
checked
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
this.props.onCheck(checked);
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Handler for keyDown events of the checkbox
|
|
59
|
+
* @param {Object} e The keyDown event payload
|
|
60
|
+
*/
|
|
61
|
+
this.handleKeyDown = e => {
|
|
62
|
+
if (e.key === ' ') {
|
|
63
|
+
// Toggle checkbox on "space" - mocks behavior of native checkboxes
|
|
64
|
+
this.handleCheck();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Renders the checked/unchecked icon.
|
|
69
|
+
* @returns {JSX}
|
|
70
|
+
*/
|
|
71
|
+
this.renderIcon = () => this.isChecked() ? this.props.checkedIcon : this.props.uncheckedIcon;
|
|
72
|
+
/**
|
|
73
|
+
* Renders an input if a "name" prop is provided.
|
|
74
|
+
* @returns {JSX}
|
|
75
|
+
*/
|
|
76
|
+
this.renderInput = () => {
|
|
77
|
+
const {
|
|
78
|
+
props: {
|
|
79
|
+
name
|
|
80
|
+
},
|
|
81
|
+
isChecked
|
|
82
|
+
} = this;
|
|
83
|
+
return this.props.name ? /*#__PURE__*/React.createElement("input", {
|
|
84
|
+
className: "input",
|
|
85
|
+
type: "hidden",
|
|
86
|
+
name: name,
|
|
87
|
+
value: isChecked() ? 1 : 0
|
|
88
|
+
}) : null;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Renders the label if "side" matches he labelPosition prop.
|
|
92
|
+
* @param {string} side Used to check against which side to render the label on.
|
|
93
|
+
* @returns {JSX}
|
|
94
|
+
*/
|
|
95
|
+
this.renderLabelIfItIsOnThe = side => this.props.labelPosition === side ? this.props.label : null;
|
|
96
|
+
if (typeof props.defaultChecked !== 'undefined') {
|
|
97
|
+
// Uncontrolled input.
|
|
98
|
+
this.state = {
|
|
99
|
+
checked: props.defaultChecked
|
|
100
|
+
};
|
|
101
|
+
} else {
|
|
102
|
+
// Controlled input
|
|
103
|
+
this.state = {
|
|
104
|
+
checked: props.checked
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
48
110
|
* Make sure state is updated with new checked value when input is controlled
|
|
49
111
|
* @param {Object} nextProps Contains the new "checked" status
|
|
50
|
-
*/
|
|
51
|
-
|
|
112
|
+
*/
|
|
113
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
114
|
+
// Update only for controlled input
|
|
115
|
+
if (typeof this.props.defaultChecked === 'undefined') {
|
|
116
|
+
if (this.state.checked !== nextProps.checked) {
|
|
117
|
+
this.setState({
|
|
118
|
+
checked: nextProps.checked
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
52
124
|
* Renders the checkbox component.
|
|
53
125
|
* @returns {JSX}
|
|
54
|
-
*/
|
|
126
|
+
*/
|
|
127
|
+
render() {
|
|
128
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
129
|
+
className: classNames(this.props.className, 'checkbox', 'common__checkbox'),
|
|
130
|
+
onClick: this.handleCheck,
|
|
131
|
+
onKeyDown: this.handleKeyDown,
|
|
132
|
+
role: "checkbox",
|
|
133
|
+
"aria-checked": this.props.checked,
|
|
134
|
+
tabIndex: 0
|
|
135
|
+
}, this.renderInput(), this.renderLabelIfItIsOnThe('left'), this.renderIcon(), this.renderLabelIfItIsOnThe('right'));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
Checkbox.defaultProps = {
|
|
139
|
+
checked: undefined,
|
|
140
|
+
className: undefined,
|
|
141
|
+
defaultChecked: undefined,
|
|
142
|
+
disabled: false,
|
|
143
|
+
label: null,
|
|
144
|
+
labelPosition: 'left',
|
|
145
|
+
name: undefined,
|
|
146
|
+
onCheck: () => {}
|
|
147
|
+
};
|
|
148
|
+
export default Checkbox;
|