@skyscanner/backpack-web 34.11.0 → 34.13.0
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/bpk-component-datepicker/src/BpkDatepicker.d.ts +1 -1
- package/bpk-component-dialog/src/BpkDialog.js +38 -23
- package/bpk-component-drawer/src/BpkDrawer.d.ts +43 -0
- package/bpk-component-drawer/src/BpkDrawer.js +32 -42
- package/bpk-component-drawer/src/BpkDrawerContent.d.ts +21 -0
- package/bpk-component-drawer/src/BpkDrawerContent.js +29 -56
- package/bpk-component-drawer/src/themeAttributes.d.ts +2 -0
- package/bpk-component-drawer/src/themeAttributes.js +4 -1
- package/bpk-component-inset-banner/index.d.ts +4 -0
- package/bpk-component-inset-banner/index.js +21 -0
- package/bpk-component-inset-banner/src/BpkInsetBanner.d.ts +23 -0
- package/bpk-component-inset-banner/src/BpkInsetBanner.js +86 -0
- package/bpk-component-inset-banner/src/BpkInsetBanner.module.css +18 -0
- package/bpk-component-journey-arrow/src/BpkJourneyArrow.module.css +1 -1
- package/bpk-component-modal/src/BpkModal.d.ts +1 -1
- package/bpk-component-modal/src/BpkModal.js +42 -27
- package/bpk-component-segmented-control/src/BpkSegmentedControl.module.css +1 -1
- package/bpk-react-utils/src/Portal.d.ts +4 -0
- package/bpk-react-utils/src/Portal.js +4 -0
- package/package.json +1 -1
|
@@ -40,7 +40,7 @@ type Props = {
|
|
|
40
40
|
onOpenChange?: (arg0: boolean) => void | null;
|
|
41
41
|
selectionConfiguration?: SelectionConfiguration;
|
|
42
42
|
initiallyFocusedDate?: Date;
|
|
43
|
-
renderTarget?:
|
|
43
|
+
renderTarget?: (() => HTMLElement | null) | HTMLElement | null;
|
|
44
44
|
isOpen?: boolean;
|
|
45
45
|
valid?: boolean;
|
|
46
46
|
onClose?: () => void;
|
|
@@ -16,13 +16,16 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { useEffect } from 'react';
|
|
20
|
+
import { FloatingPortal } from '@floating-ui/react';
|
|
21
|
+
|
|
19
22
|
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
|
|
20
23
|
import BpkCloseButton from "../../bpk-component-close-button";
|
|
21
|
-
import { cssModules
|
|
24
|
+
import { cssModules } from "../../bpk-react-utils";
|
|
22
25
|
import BpkDialogInner from "./BpkDialogInner";
|
|
23
26
|
import { HEADER_ICON_TYPES } from "./common-types";
|
|
24
27
|
import STYLES from "./BpkDialog.module.css";
|
|
25
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
28
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
26
29
|
const getClassName = cssModules(STYLES);
|
|
27
30
|
const BpkDialog = ({
|
|
28
31
|
children,
|
|
@@ -41,27 +44,39 @@ const BpkDialog = ({
|
|
|
41
44
|
// eslint-disable-next-line no-console
|
|
42
45
|
console.warn('BpkDialog: dismissible is true but no onClose prop was provided. Dialog will not be dismissible.');
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const handleKeyDown = event => {
|
|
49
|
+
if (event.key === 'Escape' && dismissible && onClose) {
|
|
50
|
+
onClose();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
if (isOpen) {
|
|
54
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
55
|
+
}
|
|
56
|
+
return () => {
|
|
57
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
58
|
+
};
|
|
59
|
+
}, [isOpen, onClose, dismissible]);
|
|
60
|
+
return /*#__PURE__*/_jsx(_Fragment, {
|
|
61
|
+
children: isOpen && /*#__PURE__*/_jsx(FloatingPortal, {
|
|
62
|
+
root: renderTarget(),
|
|
63
|
+
children: /*#__PURE__*/_jsxs(BpkDialogInner, {
|
|
64
|
+
onClose: onClose,
|
|
65
|
+
closeOnScrimClick: dismissible,
|
|
66
|
+
containerClassName: getClassName('bpk-dialog__container'),
|
|
67
|
+
contentClassName: headerIcon ? getClassName('bpk-dialog--with-icon') : undefined,
|
|
68
|
+
...rest,
|
|
69
|
+
children: [headerIcon && /*#__PURE__*/_jsx("div", {
|
|
70
|
+
className: headerIconClassNames,
|
|
71
|
+
children: headerIcon
|
|
72
|
+
}), dismissible && /*#__PURE__*/_jsx("span", {
|
|
73
|
+
className: closeButtonClassNames,
|
|
74
|
+
children: /*#__PURE__*/_jsx(BpkCloseButton, {
|
|
75
|
+
label: closeLabel,
|
|
76
|
+
onClick: onClose
|
|
77
|
+
})
|
|
78
|
+
}), children]
|
|
79
|
+
})
|
|
65
80
|
})
|
|
66
81
|
});
|
|
67
82
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { Component } from 'react';
|
|
3
|
+
export type Props = {
|
|
4
|
+
id: string;
|
|
5
|
+
children: ReactNode | string;
|
|
6
|
+
isOpen: boolean;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
title: string;
|
|
9
|
+
/**
|
|
10
|
+
* **Note:** In order to "hide" your application from screen readers whilst the drawer is open you need to let it know what
|
|
11
|
+
* the root element for your application is by returning it's DOM node via the function passed to the
|
|
12
|
+
* `getApplicationElement` prop (see the example above). The `pagewrap` element id is a convention we use internally at Skyscanner. In most cases it should "just work".
|
|
13
|
+
*/
|
|
14
|
+
getApplicationElement: () => HTMLElement | null;
|
|
15
|
+
renderTarget?: () => HTMLElement | HTMLElement | null;
|
|
16
|
+
dialogRef?: (ref: HTMLElement | null | undefined) => void;
|
|
17
|
+
className?: string | null;
|
|
18
|
+
contentClassName?: string | null;
|
|
19
|
+
closeLabel?: string | null;
|
|
20
|
+
closeText?: string | null;
|
|
21
|
+
hideTitle?: boolean;
|
|
22
|
+
[rest: string]: any;
|
|
23
|
+
};
|
|
24
|
+
type State = {
|
|
25
|
+
isDrawerShown: boolean;
|
|
26
|
+
};
|
|
27
|
+
declare class BpkDrawer extends Component<Props, State> {
|
|
28
|
+
static defaultProps: {
|
|
29
|
+
renderTarget: () => null;
|
|
30
|
+
className: null;
|
|
31
|
+
contentClassName: null;
|
|
32
|
+
closeLabel: null;
|
|
33
|
+
closeText: null;
|
|
34
|
+
hideTitle: boolean;
|
|
35
|
+
};
|
|
36
|
+
constructor(props: Props);
|
|
37
|
+
UNSAFE_componentWillReceiveProps(nextProps: Props): void;
|
|
38
|
+
onCloseAnimationComplete: () => void;
|
|
39
|
+
handleKeyDown: (event: KeyboardEvent) => void;
|
|
40
|
+
hide: () => void;
|
|
41
|
+
render(): JSX.Element;
|
|
42
|
+
}
|
|
43
|
+
export default BpkDrawer;
|
|
@@ -14,16 +14,25 @@
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/
|
|
17
|
+
*/
|
|
18
|
+
|
|
18
19
|
import { Component } from 'react';
|
|
19
|
-
import {
|
|
20
|
+
import { FloatingPortal } from '@floating-ui/react';
|
|
20
21
|
import { withScrim } from "../../bpk-scrim-utils";
|
|
21
22
|
import BpkDrawerContent from "./BpkDrawerContent";
|
|
22
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
23
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
23
24
|
const BpkScrimDrawerContent = withScrim(BpkDrawerContent);
|
|
24
25
|
class BpkDrawer extends Component {
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
static defaultProps = {
|
|
27
|
+
renderTarget: () => null,
|
|
28
|
+
className: null,
|
|
29
|
+
contentClassName: null,
|
|
30
|
+
closeLabel: null,
|
|
31
|
+
closeText: null,
|
|
32
|
+
hideTitle: false
|
|
33
|
+
};
|
|
34
|
+
constructor(props) {
|
|
35
|
+
super(props);
|
|
27
36
|
this.state = {
|
|
28
37
|
isDrawerShown: true
|
|
29
38
|
};
|
|
@@ -33,11 +42,19 @@ class BpkDrawer extends Component {
|
|
|
33
42
|
this.setState({
|
|
34
43
|
isDrawerShown: true
|
|
35
44
|
});
|
|
45
|
+
window.addEventListener('keydown', this.handleKeyDown);
|
|
46
|
+
} else {
|
|
47
|
+
window.removeEventListener('keydown', this.handleKeyDown);
|
|
36
48
|
}
|
|
37
49
|
}
|
|
38
50
|
onCloseAnimationComplete = () => {
|
|
39
51
|
this.props.onClose();
|
|
40
52
|
};
|
|
53
|
+
handleKeyDown = event => {
|
|
54
|
+
if (event.key === 'Escape' && this.props.onClose) {
|
|
55
|
+
this.props.onClose();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
41
58
|
hide = () => {
|
|
42
59
|
this.setState({
|
|
43
60
|
isDrawerShown: false
|
|
@@ -53,45 +70,18 @@ class BpkDrawer extends Component {
|
|
|
53
70
|
const {
|
|
54
71
|
isDrawerShown
|
|
55
72
|
} = this.state;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
73
|
+
const renTarget = typeof renderTarget === 'function' ? renderTarget() : renderTarget;
|
|
74
|
+
return /*#__PURE__*/_jsx(_Fragment, {
|
|
75
|
+
children: isOpen && /*#__PURE__*/_jsx(FloatingPortal, {
|
|
76
|
+
root: renTarget,
|
|
77
|
+
children: /*#__PURE__*/_jsx(BpkScrimDrawerContent, {
|
|
78
|
+
isDrawerShown: isDrawerShown,
|
|
79
|
+
onClose: this.hide,
|
|
80
|
+
onCloseAnimationComplete: this.onCloseAnimationComplete,
|
|
81
|
+
...rest
|
|
82
|
+
})
|
|
65
83
|
})
|
|
66
84
|
});
|
|
67
85
|
}
|
|
68
86
|
}
|
|
69
|
-
BpkDrawer.propTypes = {
|
|
70
|
-
id: PropTypes.string.isRequired,
|
|
71
|
-
children: PropTypes.node.isRequired,
|
|
72
|
-
isOpen: PropTypes.bool.isRequired,
|
|
73
|
-
onClose: PropTypes.func.isRequired,
|
|
74
|
-
title: PropTypes.string.isRequired,
|
|
75
|
-
/**
|
|
76
|
-
* **Note:** In order to "hide" your application from screen readers whilst the drawer is open you need to let it know what
|
|
77
|
-
* the root element for your application is by returning it's DOM node via the function passed to the
|
|
78
|
-
* `getApplicationElement` prop (see the example above). The `pagewrap` element id is a convention we use internally at Skyscanner. In most cases it should "just work".
|
|
79
|
-
*/
|
|
80
|
-
getApplicationElement: PropTypes.func.isRequired,
|
|
81
|
-
renderTarget: PropTypes.func,
|
|
82
|
-
dialogRef: PropTypes.func,
|
|
83
|
-
className: PropTypes.string,
|
|
84
|
-
contentClassName: PropTypes.string,
|
|
85
|
-
closeLabel: PropTypes.string,
|
|
86
|
-
closeText: PropTypes.string,
|
|
87
|
-
hideTitle: PropTypes.bool
|
|
88
|
-
};
|
|
89
|
-
BpkDrawer.defaultProps = {
|
|
90
|
-
renderTarget: null,
|
|
91
|
-
className: null,
|
|
92
|
-
contentClassName: null,
|
|
93
|
-
closeLabel: null,
|
|
94
|
-
closeText: null,
|
|
95
|
-
hideTitle: false
|
|
96
|
-
};
|
|
97
87
|
export default BpkDrawer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export type Props = {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
dialogRef: () => void;
|
|
5
|
+
onCloseAnimationComplete: () => void;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
className?: string | null;
|
|
10
|
+
contentClassName?: string | null;
|
|
11
|
+
closeLabel?: string | null;
|
|
12
|
+
closeText?: string | null;
|
|
13
|
+
isDrawerShown?: boolean;
|
|
14
|
+
hideTitle?: boolean;
|
|
15
|
+
closeOnScrimClick?: boolean;
|
|
16
|
+
isIphone?: boolean;
|
|
17
|
+
isIpad?: boolean;
|
|
18
|
+
[rest: string]: any;
|
|
19
|
+
};
|
|
20
|
+
declare const BpkDrawerContent: ({ children, className, closeLabel, closeOnScrimClick, closeText, contentClassName, dialogRef, hideTitle, id, isDrawerShown, isIpad, isIphone, onClose, onCloseAnimationComplete, title, ...rest }: Props) => JSX.Element;
|
|
21
|
+
export default BpkDrawerContent;
|
|
@@ -14,37 +14,41 @@
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
|
|
18
20
|
import Transition from 'react-transition-group/Transition';
|
|
19
21
|
import { animations } from '@skyscanner/bpk-foundations-web/tokens/base.es6';
|
|
22
|
+
|
|
23
|
+
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
|
|
20
24
|
import BpkCloseButton from "../../bpk-component-close-button";
|
|
25
|
+
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
|
|
21
26
|
import { BpkButtonLink } from "../../bpk-component-link";
|
|
22
27
|
import { cssModules } from "../../bpk-react-utils";
|
|
23
28
|
import STYLES from "./BpkDrawerContent.module.css";
|
|
24
29
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
25
30
|
const getClassName = cssModules(STYLES);
|
|
26
|
-
const BpkDrawerContent =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} = props;
|
|
31
|
+
const BpkDrawerContent = ({
|
|
32
|
+
children,
|
|
33
|
+
className = null,
|
|
34
|
+
closeLabel = null,
|
|
35
|
+
closeOnScrimClick = true,
|
|
36
|
+
// Unused from withScrim scrim HOC
|
|
37
|
+
closeText = null,
|
|
38
|
+
contentClassName = null,
|
|
39
|
+
dialogRef,
|
|
40
|
+
hideTitle = false,
|
|
41
|
+
id,
|
|
42
|
+
isDrawerShown = true,
|
|
43
|
+
isIpad = false,
|
|
44
|
+
// Unused from withScrim scrim HOC
|
|
45
|
+
isIphone = false,
|
|
46
|
+
// Unused from withScrim scrim HOC
|
|
47
|
+
onClose,
|
|
48
|
+
onCloseAnimationComplete,
|
|
49
|
+
title,
|
|
50
|
+
...rest
|
|
51
|
+
}) => {
|
|
48
52
|
const drawerClassNames = [getClassName('bpk-drawer')];
|
|
49
53
|
const headerClassNames = [getClassName('bpk-drawer__heading')];
|
|
50
54
|
const contentClassNames = [getClassName('bpk-drawer__content')];
|
|
@@ -68,12 +72,9 @@ const BpkDrawerContent = props => {
|
|
|
68
72
|
exit: true,
|
|
69
73
|
in: isDrawerShown,
|
|
70
74
|
onExited: onCloseAnimationComplete,
|
|
71
|
-
children: status =>
|
|
72
|
-
/*#__PURE__*/
|
|
73
|
-
// $FlowFixMe[cannot-spread-inexact] - inexact rest. See decisions/flowfixme.md
|
|
74
|
-
_jsxs("section", {
|
|
75
|
+
children: status => /*#__PURE__*/_jsxs("section", {
|
|
75
76
|
id: id,
|
|
76
|
-
tabIndex:
|
|
77
|
+
tabIndex: -1,
|
|
77
78
|
role: "dialog",
|
|
78
79
|
"aria-labelledby": headingId,
|
|
79
80
|
className: [drawerClassNames.join(' '), getClassName(`bpk-drawer--${status}`)].join(' '),
|
|
@@ -102,32 +103,4 @@ const BpkDrawerContent = props => {
|
|
|
102
103
|
}, "dialog")
|
|
103
104
|
});
|
|
104
105
|
};
|
|
105
|
-
BpkDrawerContent.propTypes = {
|
|
106
|
-
children: PropTypes.node.isRequired,
|
|
107
|
-
dialogRef: PropTypes.func.isRequired,
|
|
108
|
-
onCloseAnimationComplete: PropTypes.func.isRequired,
|
|
109
|
-
onClose: PropTypes.func.isRequired,
|
|
110
|
-
id: PropTypes.string.isRequired,
|
|
111
|
-
title: PropTypes.string.isRequired,
|
|
112
|
-
className: PropTypes.string,
|
|
113
|
-
contentClassName: PropTypes.string,
|
|
114
|
-
closeLabel: PropTypes.string,
|
|
115
|
-
closeText: PropTypes.string,
|
|
116
|
-
isDrawerShown: PropTypes.bool,
|
|
117
|
-
hideTitle: PropTypes.bool,
|
|
118
|
-
closeOnScrimClick: PropTypes.bool,
|
|
119
|
-
isIphone: PropTypes.bool,
|
|
120
|
-
isIpad: PropTypes.bool
|
|
121
|
-
};
|
|
122
|
-
BpkDrawerContent.defaultProps = {
|
|
123
|
-
className: null,
|
|
124
|
-
contentClassName: null,
|
|
125
|
-
closeLabel: null,
|
|
126
|
-
closeText: null,
|
|
127
|
-
isDrawerShown: true,
|
|
128
|
-
hideTitle: false,
|
|
129
|
-
closeOnScrimClick: true,
|
|
130
|
-
isIphone: false,
|
|
131
|
-
isIpad: false
|
|
132
|
-
};
|
|
133
106
|
export default BpkDrawerContent;
|
|
@@ -14,5 +14,8 @@
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
|
|
20
|
+
import { themeAttributes as linkAttributes } from "../../bpk-component-link";
|
|
18
21
|
export default [...linkAttributes];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import BpkInsetBanner, { VARIANT } from "./src/BpkInsetBanner";
|
|
20
|
+
export { VARIANT };
|
|
21
|
+
export default BpkInsetBanner;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare const VARIANT: {
|
|
3
|
+
onLight: string;
|
|
4
|
+
onDark: string;
|
|
5
|
+
};
|
|
6
|
+
export type Props = {
|
|
7
|
+
accessibilityLabel?: string;
|
|
8
|
+
backgroundColor?: string;
|
|
9
|
+
body?: {
|
|
10
|
+
text: string;
|
|
11
|
+
link?: string;
|
|
12
|
+
linkText?: string;
|
|
13
|
+
};
|
|
14
|
+
callToAction?: {
|
|
15
|
+
text?: string;
|
|
16
|
+
};
|
|
17
|
+
logo?: string;
|
|
18
|
+
subheadline?: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
variant?: (typeof VARIANT)[keyof typeof VARIANT];
|
|
21
|
+
};
|
|
22
|
+
declare const BpkInsetBanner: ({ accessibilityLabel, backgroundColor, body, callToAction, logo, subheadline, title, variant, }: Props) => JSX.Element;
|
|
23
|
+
export default BpkInsetBanner;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
import { surfaceHighlightDay } from '@skyscanner/bpk-foundations-web/tokens/base.es6';
|
|
19
|
+
import BpkText, { TEXT_STYLES } from "../../bpk-component-text/src/BpkText";
|
|
20
|
+
import { cssModules } from "../../bpk-react-utils";
|
|
21
|
+
import STYLES from "./BpkInsetBanner.module.css";
|
|
22
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
23
|
+
const getClassName = cssModules(STYLES);
|
|
24
|
+
export const VARIANT = {
|
|
25
|
+
onLight: 'on-light',
|
|
26
|
+
onDark: 'on-dark'
|
|
27
|
+
};
|
|
28
|
+
const BpkInsetBanner = ({
|
|
29
|
+
accessibilityLabel,
|
|
30
|
+
backgroundColor = surfaceHighlightDay,
|
|
31
|
+
body,
|
|
32
|
+
callToAction,
|
|
33
|
+
logo,
|
|
34
|
+
subheadline,
|
|
35
|
+
title,
|
|
36
|
+
variant = VARIANT.onLight
|
|
37
|
+
}) => {
|
|
38
|
+
const classNames = getClassName('bpk-inset-banner', `bpk-inset-banner--${variant}`, body && 'bpk-inset-banner--with-body');
|
|
39
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
40
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
41
|
+
"aria-label": accessibilityLabel,
|
|
42
|
+
className: classNames,
|
|
43
|
+
style: {
|
|
44
|
+
backgroundColor
|
|
45
|
+
},
|
|
46
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
47
|
+
className: getClassName('bpk-inset-banner--content-container'),
|
|
48
|
+
children: [logo && /*#__PURE__*/_jsx("img", {
|
|
49
|
+
className: getClassName('bpk-inset-banner--image'),
|
|
50
|
+
src: logo,
|
|
51
|
+
alt: "",
|
|
52
|
+
"aria-hidden": true
|
|
53
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
54
|
+
className: getClassName('bpk-inset-banner--text-container'),
|
|
55
|
+
children: [/*#__PURE__*/_jsx(BpkText, {
|
|
56
|
+
textStyle: TEXT_STYLES.label2,
|
|
57
|
+
children: title
|
|
58
|
+
}), /*#__PURE__*/_jsx(BpkText, {
|
|
59
|
+
textStyle: TEXT_STYLES.caption,
|
|
60
|
+
children: subheadline
|
|
61
|
+
})]
|
|
62
|
+
})]
|
|
63
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
64
|
+
className: getClassName('bpk-inset-banner--cta-container'),
|
|
65
|
+
children: callToAction?.text && /*#__PURE__*/_jsx(BpkText, {
|
|
66
|
+
textStyle: TEXT_STYLES.caption,
|
|
67
|
+
children: callToAction.text
|
|
68
|
+
})
|
|
69
|
+
})]
|
|
70
|
+
}), body && /*#__PURE__*/_jsxs("div", {
|
|
71
|
+
className: getClassName('bpk-inset-banner-body-container'),
|
|
72
|
+
children: [/*#__PURE__*/_jsx(BpkText, {
|
|
73
|
+
textStyle: TEXT_STYLES.caption,
|
|
74
|
+
children: body.text
|
|
75
|
+
}), body.link && body.linkText && /*#__PURE__*/_jsx("a", {
|
|
76
|
+
href: body.link,
|
|
77
|
+
className: getClassName('bpk-inset-banner-body-container--link-text'),
|
|
78
|
+
children: /*#__PURE__*/_jsx(BpkText, {
|
|
79
|
+
textStyle: TEXT_STYLES.caption,
|
|
80
|
+
children: body.linkText
|
|
81
|
+
})
|
|
82
|
+
})]
|
|
83
|
+
})]
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
export default BpkInsetBanner;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Backpack - Skyscanner's Design System
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2016 Skyscanner Ltd
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
.bpk-inset-banner{display:flex;padding:.5rem 1rem;justify-content:space-between;border-radius:.5rem}.bpk-inset-banner--with-body{border-radius:.5rem .5rem 0 0}.bpk-inset-banner--on-light{color:#161616;fill:#161616}.bpk-inset-banner--on-dark{color:#fff;fill:#fff}.bpk-inset-banner--content-container{display:flex;align-items:center}.bpk-inset-banner--image{max-height:2rem;object-fit:contain;padding-inline-end:1rem}@media(max-width: 32rem){.bpk-inset-banner--image{max-height:1.5rem}}.bpk-inset-banner--text-container{display:flex;flex-direction:column}.bpk-inset-banner--cta-container{display:flex;align-items:center}.bpk-inset-banner-body-container{display:flex;padding:1rem;flex-direction:column;border-radius:0 0 .5rem .5rem;background-color:#eff3f8;color:#161616}.bpk-inset-banner-body-container--link-text{color:#0062e3;text-decoration:none}.bpk-no-touch-support .bpk-inset-banner-body-container--link-text:hover:not(:active):not(:disabled){color:#024daf}:global(.bpk-no-touch-support) .bpk-inset-banner-body-container--link-text:hover:not(:active):not(:disabled){color:#024daf}
|
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
.bpk-journey-arrow{display:flex;width:100%;
|
|
18
|
+
.bpk-journey-arrow{display:flex;width:100%;height:.5rem;margin:0 .5rem;justify-content:center;border-width:0 .3125rem 0 .125rem;border-style:solid;border-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="8" fill="none" viewBox="0 0 16 8"><path fill="%23C1C7CF" d="M15.69 4.35a.5.5 0 0 0 0-.7L12.51.46a.5.5 0 1 0-.7.71L14.62 4 11.8 6.83a.5.5 0 0 0 .7.7l3.2-3.17m-.7.14v-1H.5a.5.5 0 0 0 0 1Z"/></svg>') 0 5 0 2 fill/1/0 stretch}html[dir=rtl] .bpk-journey-arrow{transform:scaleX(-1)}.bpk-journey-arrow__stop{width:.5rem;height:.5rem;border:.125rem solid #fff;border-radius:.25rem;background-color:#e70866}
|
|
@@ -7,7 +7,7 @@ export type Props = Partial<ModalDialogProps> & {
|
|
|
7
7
|
isOpen: boolean;
|
|
8
8
|
closeOnScrimClick?: boolean;
|
|
9
9
|
closeOnEscPressed?: boolean;
|
|
10
|
-
renderTarget?:
|
|
10
|
+
renderTarget?: (() => HTMLElement | null) | HTMLElement | null;
|
|
11
11
|
modalStyle?: ModalStyle;
|
|
12
12
|
onClose?: (arg0?: TouchEvent | MouseEvent | KeyboardEvent, arg1?: {
|
|
13
13
|
source: 'ESCAPE' | 'DOCUMENT_CLICK';
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { useEffect } from 'react';
|
|
20
|
+
import { FloatingPortal } from '@floating-ui/react';
|
|
21
|
+
import { cssModules, isDeviceIphone } from "../../bpk-react-utils";
|
|
20
22
|
import { withScrim } from "../../bpk-scrim-utils";
|
|
21
23
|
import BpkModalInner, { MODAL_STYLING } from "./BpkModalInner";
|
|
22
24
|
import STYLES from "./BpkModal.module.css";
|
|
23
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
25
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
24
26
|
const getClassName = cssModules(STYLES);
|
|
25
27
|
const ScrimBpkModalInner = withScrim(BpkModalInner);
|
|
26
28
|
const BpkModal = ({
|
|
@@ -39,42 +41,55 @@ const BpkModal = ({
|
|
|
39
41
|
modalStyle = MODAL_STYLING.default,
|
|
40
42
|
onClose = () => null,
|
|
41
43
|
padded = true,
|
|
42
|
-
renderTarget = null,
|
|
44
|
+
renderTarget = () => null,
|
|
43
45
|
showHeader = true,
|
|
44
46
|
title = null,
|
|
45
47
|
wide = false,
|
|
46
48
|
...rest
|
|
47
49
|
}) => {
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const handleKeyDown = event => {
|
|
52
|
+
if (event.key === 'Escape' && onClose) {
|
|
53
|
+
onClose();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
if (isOpen) {
|
|
57
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
58
|
+
}
|
|
59
|
+
return () => {
|
|
60
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
61
|
+
};
|
|
62
|
+
}, [isOpen, onClose]);
|
|
48
63
|
const containerClass = [getClassName('bpk-modal__container')];
|
|
49
64
|
if (fullScreen || isIphone) {
|
|
50
65
|
containerClass.push(getClassName('bpk-modal__container--full-screen'));
|
|
51
66
|
} else if (fullScreenOnMobile) {
|
|
52
67
|
containerClass.push(getClassName('bpk-modal__container--full-screen-mobile'));
|
|
53
68
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
const renTarget = typeof renderTarget === 'function' ? renderTarget() : renderTarget;
|
|
70
|
+
return /*#__PURE__*/_jsx(_Fragment, {
|
|
71
|
+
children: isOpen && /*#__PURE__*/_jsx(FloatingPortal, {
|
|
72
|
+
root: renTarget,
|
|
73
|
+
children: /*#__PURE__*/_jsx(ScrimBpkModalInner, {
|
|
74
|
+
onClose: onClose,
|
|
75
|
+
fullScreenOnMobile: fullScreenOnMobile,
|
|
76
|
+
fullScreen: fullScreen,
|
|
77
|
+
closeOnScrimClick: closeOnScrimClick,
|
|
78
|
+
containerClassName: containerClass.join(' '),
|
|
79
|
+
isIphone: isIphone,
|
|
80
|
+
title: title,
|
|
81
|
+
className: className,
|
|
82
|
+
contentClassName: contentClassName,
|
|
83
|
+
closeLabel: closeLabel,
|
|
84
|
+
closeText: closeText,
|
|
85
|
+
wide: wide,
|
|
86
|
+
showHeader: showHeader,
|
|
87
|
+
padded: padded,
|
|
88
|
+
accessoryView: accessoryView,
|
|
89
|
+
dialogRef: dialogRef,
|
|
90
|
+
modalStyle: modalStyle,
|
|
91
|
+
...rest
|
|
92
|
+
})
|
|
78
93
|
})
|
|
79
94
|
});
|
|
80
95
|
};
|
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
.bpk-segmented-control-group{display:flex;flex-wrap:nowrap;overflow:hidden;border-radius:.5rem}.bpk-segmented-control-group-shadow{box-shadow:0px 1px 3px 0px rgba(37,32,31,.3)}.bpk-segmented-control{min-height:2rem;padding:.5rem 1rem;flex:1;border:none;text-overflow:ellipsis;cursor:pointer;overflow:hidden;font-size:.875rem;line-height:1.25rem;font-weight:700}.bpk-segmented-control--canvas-default{background-color:#eff3f8;color:#161616}.bpk-segmented-control--canvas-default-selected{background-color:#05203c;color:#fff}.bpk-segmented-control--canvas-contrast{background-color:#fff;color:#161616}.bpk-segmented-control--canvas-contrast-selected{background-color:#05203c;color:#fff}.bpk-segmented-control--surface-default{background-color:#eff3f8;color:#161616}.bpk-segmented-control--surface-default-selected{background-color:#05203c;color:#fff}.bpk-segmented-control--surface-contrast{background-color:rgba(255,255,255,.1);color:#fff}.bpk-segmented-control--surface-contrast-selected{background-color:#024daf;color:#fff}.bpk-segmented-control:not(:first-of-type,[class*=selected]){border-
|
|
18
|
+
.bpk-segmented-control-group{display:flex;flex-wrap:nowrap;overflow:hidden;border-radius:.5rem}.bpk-segmented-control-group-shadow{box-shadow:0px 1px 3px 0px rgba(37,32,31,.3)}.bpk-segmented-control{min-height:2rem;padding:.5rem 1rem;flex:1;border:none;text-overflow:ellipsis;cursor:pointer;overflow:hidden;font-size:.875rem;line-height:1.25rem;font-weight:700}.bpk-segmented-control--canvas-default{background-color:#eff3f8;color:#161616}.bpk-segmented-control--canvas-default-selected{background-color:#05203c;color:#fff}.bpk-segmented-control--canvas-contrast{background-color:#fff;color:#161616}.bpk-segmented-control--canvas-contrast-selected{background-color:#05203c;color:#fff}.bpk-segmented-control--surface-default{background-color:#eff3f8;color:#161616}.bpk-segmented-control--surface-default-selected{background-color:#05203c;color:#fff}.bpk-segmented-control--surface-contrast{background-color:rgba(255,255,255,.1);color:#fff}.bpk-segmented-control--surface-contrast-selected{background-color:#024daf;color:#fff}.bpk-segmented-control:not(:first-of-type,[class*=selected]){border-inline-start:.0625rem solid #c1c7cf}.bpk-segmented-control--surface-contrast:not(:first-of-type,[class*=selected]){border-inline-start:.0625rem solid rgba(255,255,255,.5)}.bpk-segmented-control[class*=rightOfOption]{border-inline-start:none}.bpk-segmented-control:first-child{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.bpk-segmented-control:last-child{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.bpk-segmented-control:focus{border:.125rem solid #0062e3;outline:none}
|
|
@@ -20,6 +20,10 @@ type Props = {
|
|
|
20
20
|
type State = {
|
|
21
21
|
isVisible: boolean;
|
|
22
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated the portal is deprecated and will be removed in a future release. Please read [](https://github.com/Skyscanner/backpack/blob/main/packages/bpk-react-utils/docs/portal-migration.md) for further information
|
|
25
|
+
* @returns{Component} used to render children into a new component tree. For use with Modals, popovers, tooltips.
|
|
26
|
+
*/
|
|
23
27
|
declare class Portal extends Component<Props, State> {
|
|
24
28
|
portalElement: null | HTMLDivElement;
|
|
25
29
|
shouldClose: boolean;
|
|
@@ -25,6 +25,10 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
25
25
|
const KEYCODES = {
|
|
26
26
|
ESCAPE: 'Escape'
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated the portal is deprecated and will be removed in a future release. Please read [](https://github.com/Skyscanner/backpack/blob/main/packages/bpk-react-utils/docs/portal-migration.md) for further information
|
|
30
|
+
* @returns{Component} used to render children into a new component tree. For use with Modals, popovers, tooltips.
|
|
31
|
+
*/
|
|
28
32
|
class Portal extends Component {
|
|
29
33
|
static defaultProps = {
|
|
30
34
|
beforeClose: null,
|