@skyscanner/backpack-web 30.1.0 → 30.3.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.
@@ -18,7 +18,7 @@
18
18
 
19
19
  import component, { BADGE_TYPES, type Props } from './src/BpkBadge';
20
20
  import themeAttributes from './src/themeAttributes';
21
-
21
+ import BpkBadgeV2 from './src/BpkBadgeV2/BpkBadge';
22
22
  export type BpkBadgeProps = Props;
23
23
  export default component;
24
- export { BADGE_TYPES, themeAttributes };
24
+ export { BADGE_TYPES, themeAttributes, BpkBadgeV2 };
@@ -18,5 +18,7 @@
18
18
 
19
19
  import component, { BADGE_TYPES } from "./src/BpkBadge";
20
20
  import themeAttributes from "./src/themeAttributes";
21
+ import BpkBadgeV2 from "./src/BpkBadgeV2/BpkBadge";
22
+ ;
21
23
  export default component;
22
- export { BADGE_TYPES, themeAttributes };
24
+ export { BADGE_TYPES, themeAttributes, BpkBadgeV2 };
@@ -0,0 +1,22 @@
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
+ /// <reference types="react" />
20
+ import type { Props } from '../BpkBadge';
21
+ declare const BpkBadgeV2: ({ centered, className, docked, type, ...rest }: Props) => JSX.Element;
22
+ export default BpkBadgeV2;
@@ -0,0 +1,47 @@
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 { cssModules } from "../../../bpk-react-utils";
20
+ import { BADGE_TYPES } from "../BpkBadge";
21
+ import STYLES from "./BpkBadge.module.css";
22
+ import { jsx as _jsx } from "react/jsx-runtime";
23
+ const getClassName = cssModules(STYLES);
24
+ const badgeTypeClassNames = {
25
+ [BADGE_TYPES.warning]: getClassName('bpk-badge--warning'),
26
+ [BADGE_TYPES.success]: getClassName('bpk-badge--success'),
27
+ [BADGE_TYPES.critical]: getClassName('bpk-badge--critical'),
28
+ [BADGE_TYPES.normal]: getClassName('bpk-badge--normal'),
29
+ [BADGE_TYPES.inverse]: getClassName('bpk-badge--inverse'),
30
+ [BADGE_TYPES.outline]: getClassName('bpk-badge--outline'),
31
+ [BADGE_TYPES.strong]: getClassName('bpk-badge--strong'),
32
+ [BADGE_TYPES.brand]: getClassName('bpk-badge--brand')
33
+ };
34
+ const BpkBadgeV2 = ({
35
+ centered = false,
36
+ className = null,
37
+ docked = null,
38
+ type = BADGE_TYPES.normal,
39
+ ...rest
40
+ }) => {
41
+ const classNames = getClassName('bpk-badge', badgeTypeClassNames[type], docked === 'right' && 'bpk-badge--docked-right', docked === 'left' && 'bpk-badge--docked-left', centered && 'bpk-badge--centered', className);
42
+ return /*#__PURE__*/_jsx("span", {
43
+ className: classNames,
44
+ ...rest
45
+ });
46
+ };
47
+ export default BpkBadgeV2;
@@ -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-badge{display:inline-flex;padding:0.25rem 0.5rem;align-items:center;border-radius:.25rem;margin:0;font-size:.875rem;line-height:1.25rem;font-weight:400}.bpk-badge--centered{vertical-align:text-bottom}.bpk-badge--docked-right{position:absolute;top:0;right:0;border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:0}html[dir='rtl'] .bpk-badge--docked-right{right:inherit;left:0;border-bottom-left-radius:0;border-bottom-right-radius:.25rem}.bpk-badge--docked-left{position:absolute;top:0;left:0;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:0}html[dir='rtl'] .bpk-badge--docked-left{right:0;left:inherit;border-bottom-left-radius:.25rem;border-bottom-right-radius:0}.bpk-badge--warning{background-color:#eff1f2;color:#161616;fill:#f55d42}.bpk-badge--success{background-color:#eff1f2;color:#161616;fill:#0c838a}.bpk-badge--critical{background-color:#eff1f2;color:#161616;fill:#e70866}.bpk-badge--normal{background-color:#eff1f2;color:#161616;fill:#161616}.bpk-badge--inverse{background-color:#fff;color:#161616;fill:#161616}.bpk-badge--outline{background-color:transparent;color:#fff;box-shadow:inset 0 0 0 1px #fff;fill:#fff}.bpk-badge--strong{background-color:#05203c;color:#fff;fill:#fff}.bpk-badge--brand{background-color:#0062e3;color:#fff;fill:#fff}
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ declare const _default: ({ styles, ...props }: {
3
+ [x: string]: any;
4
+ styles?: {} | undefined;
5
+ }) => JSX.Element;
6
+ export default _default;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ declare const _default: ({ styles, ...props }: {
3
+ [x: string]: any;
4
+ styles?: {} | undefined;
5
+ }) => JSX.Element;
6
+ export default _default;
@@ -0,0 +1,22 @@
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 BpkSectionHeader, { SECTION_TYPES } from './src/BpkSectionHeader';
20
+
21
+ export default BpkSectionHeader;
22
+ export { SECTION_TYPES };
@@ -0,0 +1,238 @@
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 '../bonds.scss';
20
+ @import 'typography.scss';
21
+ @import 'radii.scss';
22
+ @import 'utils.scss';
23
+
24
+ ////
25
+ /// @group badges
26
+ ////
27
+
28
+ /// Standard badge.
29
+ ///
30
+ /// @example scss
31
+ /// .selector {
32
+ /// @include bpk-badge();
33
+ /// }
34
+
35
+ @mixin bpk-badge {
36
+ display: inline-flex;
37
+ padding: bpk-spacing-sm() bpk-spacing-md();
38
+ align-items: center;
39
+
40
+ @include bpk-border-radius-xs;
41
+ @include bpk-text;
42
+ @include bpk-footnote;
43
+ }
44
+
45
+ /// Centered badge. Modifies the bpk-badge mixin.
46
+ ///
47
+ /// @require {mixin} bpk-badge
48
+ ///
49
+ /// @example scss
50
+ /// .selector {
51
+ /// @include bpk-badge();
52
+ /// @include bpk-badge--centered();
53
+ /// }
54
+
55
+ @mixin bpk-badge--centered {
56
+ vertical-align: text-bottom;
57
+ }
58
+
59
+ /// Right-docked badge. Modifies the bpk-badge mixin.
60
+ ///
61
+ /// @require {mixin} bpk-badge
62
+ ///
63
+ /// @example scss
64
+ /// .selector {
65
+ /// @include bpk-badge();
66
+ /// @include bpk-badge--docked-right();
67
+ /// }
68
+
69
+ @mixin bpk-badge--docked-right {
70
+ position: absolute;
71
+ top: 0;
72
+ right: 0;
73
+ border-top-left-radius: 0;
74
+ border-top-right-radius: 0;
75
+ border-bottom-right-radius: 0;
76
+
77
+ @include bpk-rtl {
78
+ right: inherit;
79
+ left: 0;
80
+ border-bottom-left-radius: 0;
81
+ border-bottom-right-radius: $bpk-border-radius-xs;
82
+ }
83
+ }
84
+
85
+ /// Left-docked badge. Modifies the bpk-badge mixin.
86
+ ///
87
+ /// @require {mixin} bpk-badge
88
+ ///
89
+ /// @example scss
90
+ /// .selector {
91
+ /// @include bpk-badge();
92
+ /// @include bpk-badge--docked-left();
93
+ /// }
94
+
95
+ @mixin bpk-badge--docked-left {
96
+ position: absolute;
97
+ top: 0;
98
+ left: 0;
99
+ border-top-left-radius: 0;
100
+ border-top-right-radius: 0;
101
+ border-bottom-left-radius: 0;
102
+
103
+ @include bpk-rtl {
104
+ right: 0;
105
+ left: inherit;
106
+ border-bottom-left-radius: $bpk-border-radius-xs;
107
+ border-bottom-right-radius: 0;
108
+ }
109
+ }
110
+
111
+ /// Normal badge. Modifies the bpk-badge mixin.
112
+ ///
113
+ /// @require {mixin} bpk-badge
114
+ ///
115
+ /// @example scss
116
+ /// .selector {
117
+ /// @include bpk-badge();
118
+ /// @include bpk-badge--normal();
119
+ /// }
120
+
121
+ @mixin bpk-badge--normal {
122
+ background-color: $bpk-private-badge-background-normal-day;
123
+ color: $bpk-text-primary-day;
124
+ fill: $bpk-text-primary-day;
125
+ }
126
+
127
+ /// Warning badge. Modifies the bpk-badge mixin.
128
+ ///
129
+ /// @require {mixin} bpk-badge
130
+ ///
131
+ /// @example scss
132
+ /// .selector {
133
+ /// @include bpk-badge();
134
+ /// @include bpk-badge--warning();
135
+ /// }
136
+
137
+ @mixin bpk-badge--warning {
138
+ background-color: $bpk-private-badge-background-normal-day;
139
+ color: $bpk-text-on-light-day;
140
+ fill: $bpk-status-warning-spot-day;
141
+ }
142
+
143
+ /// Success badge. Modifies the bpk-badge mixin.
144
+ ///
145
+ /// @require {mixin} bpk-badge
146
+ ///
147
+ /// @example scss
148
+ /// .selector {
149
+ /// @include bpk-badge();
150
+ /// @include bpk-badge--success();
151
+ /// }
152
+
153
+ @mixin bpk-badge--success {
154
+ background-color: $bpk-private-badge-background-normal-day;
155
+ color: $bpk-text-on-light-day;
156
+ fill: $bpk-status-success-spot-day;
157
+ }
158
+
159
+ /// Critical badge. Modifies the bpk-badge mixin.
160
+ ///
161
+ /// @require {mixin} bpk-badge
162
+ ///
163
+ /// @example scss
164
+ /// .selector {
165
+ /// @include bpk-badge();
166
+ /// @include bpk-badge--critical();
167
+ /// }
168
+
169
+ @mixin bpk-badge--critical {
170
+ background-color: $bpk-private-badge-background-normal-day;
171
+ color: $bpk-text-on-light-day;
172
+ fill: $bpk-status-danger-spot-day;
173
+ }
174
+
175
+ /// Inverse badge. Modifies the bpk-badge mixin.
176
+ ///
177
+ /// @require {mixin} bpk-badge
178
+ ///
179
+ /// @example scss
180
+ /// .selector {
181
+ /// @include bpk-badge();
182
+ /// @include bpk-badge--inverse();
183
+ /// }
184
+
185
+ @mixin bpk-badge--inverse {
186
+ background-color: $bpk-surface-default-day;
187
+ color: $bpk-text-primary-day;
188
+ fill: $bpk-text-primary-day;
189
+ }
190
+
191
+ /// Outline badge. Modifies the bpk-badge mixin.
192
+ ///
193
+ /// @require {mixin} bpk-badge
194
+ ///
195
+ /// @example scss
196
+ /// .selector {
197
+ /// @include bpk-badge();
198
+ /// @include bpk-badge--outline();
199
+ /// }
200
+
201
+ @mixin bpk-badge--outline {
202
+ background-color: transparent;
203
+ color: $bpk-text-on-dark-day;
204
+ box-shadow: inset 0 0 0 $bpk-border-size-sm $bpk-text-on-dark-day;
205
+ fill: $bpk-text-on-dark-day;
206
+ }
207
+
208
+ /// Strong badge. Modifies the bpk-badge mixin.
209
+ ///
210
+ /// @require {mixin} bpk-badge
211
+ ///
212
+ /// @example scss
213
+ /// .selector {
214
+ /// @include bpk-badge();
215
+ /// @include bpk-badge--strong();
216
+ /// }
217
+
218
+ @mixin bpk-badge--strong {
219
+ background-color: $bpk-core-primary-day;
220
+ color: $bpk-text-on-dark-day;
221
+ fill: $bpk-text-on-dark-day;
222
+ }
223
+
224
+ /// Brand badge. Modifies the bpk-badge mixin.
225
+ ///
226
+ /// @require {mixin} bpk-badge
227
+ ///
228
+ /// @example scss
229
+ /// .selector {
230
+ /// @include bpk-badge();
231
+ /// @include bpk-badge--brand();
232
+ /// }
233
+
234
+ @mixin bpk-badge--brand {
235
+ background-color: $bpk-core-accent-day;
236
+ color: $bpk-text-primary-inverse-day;
237
+ fill: $bpk-text-primary-inverse-day;
238
+ }
@@ -87,8 +87,8 @@
87
87
  @mixin bpk-input--valid {
88
88
  padding-right: bpk-spacing-xl();
89
89
  background: $bpk-input-background
90
- url(map-get($bpk-icons-sm, tick-circle-green-spot)) no-repeat right
91
- bpk-spacing-md() center;
90
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjMGM4MzhhICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTEyIDIyLjVDNi4yMDEgMjIuNSAxLjUgMTcuNzk5IDEuNSAxMlM2LjIwMSAxLjUgMTIgMS41IDIyLjUgNi4yMDEgMjIuNSAxMiAxNy43OTkgMjIuNSAxMiAyMi41em01LjU2LTEyLjQ0YTEuNSAxLjUgMCAwIDAtMi4xMi0yLjEybC00Ljk0IDQuOTM5LTEuOTQtMS45NGExLjUgMS41IDAgMCAwLTIuMTIgMi4xMjJsMyAzYTEuNSAxLjUgMCAwIDAgMi4xMiAwbDYtNnoiLz48L3N2Zz4=')
91
+ no-repeat right bpk-spacing-md() center;
92
92
  background-size: $bpk-icon-size-sm $bpk-icon-size-sm;
93
93
 
94
94
  @include bpk-rtl {
@@ -111,8 +111,8 @@
111
111
  @mixin bpk-input--invalid {
112
112
  padding-right: bpk-spacing-xl();
113
113
  background: $bpk-input-background
114
- url(map-get($bpk-icons-sm, exclamation-circle-berry)) no-repeat right
115
- bpk-spacing-md() center;
114
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjZTcwODY2ICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTEyIDEuNUExMC41IDEwLjUgMCAxIDAgMjIuNSAxMiAxMC41IDEwLjUgMCAwIDAgMTIgMS41ek0xMiAxOGExLjUgMS41IDAgMSAxIDEuNS0xLjVBMS41IDEuNSAwIDAgMSAxMiAxOHptMS41LTZhMS41IDEuNSAwIDAgMS0zIDBWNy41YTEuNSAxLjUgMCAwIDEgMyAweiIvPjwvc3ZnPg==')
115
+ no-repeat right bpk-spacing-md() center;
116
116
  background-size: $bpk-icon-size-sm $bpk-icon-size-sm;
117
117
 
118
118
  @include bpk-themeable-property(
@@ -337,8 +337,8 @@
337
337
  border: solid $bpk-one-pixel-rem $bpk-line-day;
338
338
  border-radius: $bpk-select-border-radius;
339
339
  background: $bpk-surface-default-day
340
- url(map-get($bpk-icons-sm, arrow-down-charcoal)) no-repeat right
341
- bpk-spacing-md() center;
340
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjMTYxNjE2ICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTE2LjUzNyA4LjI1SDcuNDYzYTEuMzU4IDEuMzU4IDAgMCAwLTEuMTEgMi4yNTFsNC4zNTQgNC43N2ExLjUzIDEuNTMgMCAwIDAgMi4xODQuMDRsNC43MTgtNC43N2ExLjM1NyAxLjM1NyAwIDAgMC0xLjA3Mi0yLjI5MXoiLz48L3N2Zz4=')
341
+ no-repeat right bpk-spacing-md() center;
342
342
  background-size: $bpk-input-height / 2;
343
343
  color: $bpk-text-primary-day;
344
344
  line-height: ($bpk-line-height-base - (2 * $bpk-select-border-width));
@@ -360,8 +360,8 @@
360
360
  &:disabled {
361
361
  border-color: $bpk-surface-highlight-day;
362
362
  background: $bpk-surface-default-day
363
- url(map-get($bpk-icons-sm, arrow-down-black-alpha-20)) no-repeat right
364
- bpk-spacing-md() center;
363
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjMDAwMDAwICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTE2LjUzNyA4LjI1SDcuNDYzYTEuMzU4IDEuMzU4IDAgMCAwLTEuMTEgMi4yNTFsNC4zNTQgNC43N2ExLjUzIDEuNTMgMCAwIDAgMi4xODQuMDRsNC43MTgtNC43N2ExLjM1NyAxLjM1NyAwIDAgMC0xLjA3Mi0yLjI5MXoiLz48L3N2Zz4=')
364
+ no-repeat right bpk-spacing-md() center;
365
365
  background-size: $bpk-input-height / 2;
366
366
  color: $bpk-text-disabled-day;
367
367
  cursor: not-allowed;
@@ -383,8 +383,8 @@
383
383
  padding: bpk-spacing-md() bpk-spacing-base();
384
384
  padding-right: bpk-spacing-xxl();
385
385
  background: $bpk-surface-default-day
386
- url(map-get($bpk-icons-sm, arrow-down-charcoal)) no-repeat right
387
- bpk-spacing-base() center;
386
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjMTYxNjE2ICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTE2LjUzNyA4LjI1SDcuNDYzYTEuMzU4IDEuMzU4IDAgMCAwLTEuMTEgMi4yNTFsNC4zNTQgNC43N2ExLjUzIDEuNTMgMCAwIDAgMi4xODQuMDRsNC43MTgtNC43N2ExLjM1NyAxLjM1NyAwIDAgMC0xLjA3Mi0yLjI5MXoiLz48L3N2Zz4=')
387
+ no-repeat right bpk-spacing-base() center;
388
388
 
389
389
  @include bpk-rtl {
390
390
  padding-right: bpk-spacing-base();
@@ -489,8 +489,8 @@
489
489
  @mixin bpk-select--invalid {
490
490
  padding-right: bpk-spacing-xl();
491
491
  background: $bpk-surface-default-day
492
- url(map-get($bpk-icons-sm, arrow-down-charcoal)) no-repeat right
493
- bpk-spacing-md() center;
492
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjMTYxNjE2ICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTE2LjUzNyA4LjI1SDcuNDYzYTEuMzU4IDEuMzU4IDAgMCAwLTEuMTEgMi4yNTFsNC4zNTQgNC43N2ExLjUzIDEuNTMgMCAwIDAgMi4xODQuMDRsNC43MTgtNC43N2ExLjM1NyAxLjM1NyAwIDAgMC0xLjA3Mi0yLjI5MXoiLz48L3N2Zz4=')
493
+ no-repeat right bpk-spacing-md() center;
494
494
  background-size: $bpk-input-height / 2;
495
495
 
496
496
  @include bpk-themeable-property(
@@ -1003,8 +1003,8 @@
1003
1003
  @mixin bpk-textarea--invalid {
1004
1004
  padding-right: bpk-spacing-xl();
1005
1005
  background: $bpk-input-background
1006
- url(map-get($bpk-icons-sm, exclamation-circle-berry)) no-repeat right
1007
- bpk-spacing-md() center;
1006
+ url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48c3R5bGUgdHlwZT0idGV4dC9jc3MiPmNpcmNsZSwgZWxsaXBzZSwgbGluZSwgcGF0aCwgcG9seWdvbiwgcG9seWxpbmUsIHJlY3QsIHRleHQgeyBmaWxsOiAjZTcwODY2ICFpbXBvcnRhbnQgfTwvc3R5bGU+PHBhdGggZD0iTTEyIDEuNUExMC41IDEwLjUgMCAxIDAgMjIuNSAxMiAxMC41IDEwLjUgMCAwIDAgMTIgMS41ek0xMiAxOGExLjUgMS41IDAgMSAxIDEuNS0xLjVBMS41IDEuNSAwIDAgMSAxMiAxOHptMS41LTZhMS41IDEuNSAwIDAgMS0zIDBWNy41YTEuNSAxLjUgMCAwIDEgMyAweiIvPjwvc3ZnPg==')
1007
+ no-repeat right bpk-spacing-md() center;
1008
1008
 
1009
1009
  @include bpk-themeable-property(
1010
1010
  border-color,
@@ -193,17 +193,10 @@
193
193
  /// @include bpk-spinner(spinner-sky-gray-tint-02);
194
194
  /// }
195
195
 
196
- @mixin bpk-spinner($spinner: '') {
196
+ @mixin bpk-spinner() {
197
197
  width: bpk-spacing-base();
198
198
  height: bpk-spacing-base();
199
199
  animation: bpk-keyframe-spin 600ms linear infinite;
200
-
201
- @if $spinner != '' {
202
- content: '';
203
- display: inline-block;
204
- background: url(map-get($bpk-spinners, $spinner)) no-repeat;
205
- background-size: cover;
206
- }
207
200
  }
208
201
 
209
202
  /// Large spinner. Modifies the bpk-spinner mixin.
@@ -18,230 +18,63 @@
18
18
 
19
19
  /// <reference types="react" />
20
20
  import withScrim from './src/withScrim';
21
- export { withScrim };
21
+ import withScrimmedPortal from './src/withScrimmedPortal';
22
+ export { withScrim, withScrimmedPortal };
22
23
  declare const _default: {
23
24
  withScrim: <P extends object>(WrappedComponent: string | import("react").ComponentType<P>) => {
24
- new (props: ({
25
- [rest: string]: any;
26
- getApplicationElement: () => HTMLElement | null;
27
- onClose?: (() => void | null) | undefined;
28
- isIphone?: boolean | undefined;
29
- isIpad?: boolean | undefined;
30
- containerClassName?: string | undefined;
31
- closeOnScrimClick?: boolean | undefined;
32
- } & Omit<P, "dialogRef">) | Readonly<{
33
- [rest: string]: any;
34
- getApplicationElement: () => HTMLElement | null;
35
- onClose?: (() => void | null) | undefined;
36
- isIphone?: boolean | undefined;
37
- isIpad?: boolean | undefined;
38
- containerClassName?: string | undefined;
39
- closeOnScrimClick?: boolean | undefined;
40
- } & Omit<P, "dialogRef">>): {
25
+ new (props: (import("./src/withScrim").Props & Omit<P, "dialogRef">) | Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>): {
41
26
  dialogElement?: HTMLElement | null | undefined;
42
27
  componentDidMount(): void;
43
28
  componentWillUnmount(): void;
44
29
  dialogRef: (ref: HTMLElement | null | undefined) => void;
45
30
  render(): JSX.Element;
46
31
  context: any;
47
- setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{
48
- [rest: string]: any;
49
- getApplicationElement: () => HTMLElement | null;
50
- onClose?: (() => void | null) | undefined;
51
- isIphone?: boolean | undefined;
52
- isIpad?: boolean | undefined;
53
- containerClassName?: string | undefined;
54
- closeOnScrimClick?: boolean | undefined;
55
- } & Omit<P, "dialogRef">>) => {} | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
32
+ setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>) => {} | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
56
33
  forceUpdate(callback?: (() => void) | undefined): void;
57
- readonly props: Readonly<{
58
- [rest: string]: any;
59
- getApplicationElement: () => HTMLElement | null;
60
- onClose?: (() => void | null) | undefined;
61
- isIphone?: boolean | undefined;
62
- isIpad?: boolean | undefined;
63
- containerClassName?: string | undefined;
64
- closeOnScrimClick?: boolean | undefined;
65
- } & Omit<P, "dialogRef">> & Readonly<{
34
+ readonly props: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">> & Readonly<{
66
35
  children?: import("react").ReactNode;
67
36
  }>;
68
37
  state: Readonly<{}>;
69
38
  refs: {
70
39
  [key: string]: import("react").ReactInstance;
71
40
  };
72
- shouldComponentUpdate?(nextProps: Readonly<{
73
- [rest: string]: any;
74
- getApplicationElement: () => HTMLElement | null;
75
- onClose?: (() => void | null) | undefined;
76
- isIphone?: boolean | undefined;
77
- isIpad?: boolean | undefined;
78
- containerClassName?: string | undefined;
79
- closeOnScrimClick?: boolean | undefined;
80
- } & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): boolean;
41
+ shouldComponentUpdate?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): boolean;
81
42
  componentDidCatch?(error: Error, errorInfo: import("react").ErrorInfo): void;
82
- getSnapshotBeforeUpdate?(prevProps: Readonly<{
83
- [rest: string]: any;
84
- getApplicationElement: () => HTMLElement | null;
85
- onClose?: (() => void | null) | undefined;
86
- isIphone?: boolean | undefined;
87
- isIpad?: boolean | undefined;
88
- containerClassName?: string | undefined;
89
- closeOnScrimClick?: boolean | undefined;
90
- } & Omit<P, "dialogRef">>, prevState: Readonly<{}>): any;
91
- componentDidUpdate?(prevProps: Readonly<{
92
- [rest: string]: any;
93
- getApplicationElement: () => HTMLElement | null;
94
- onClose?: (() => void | null) | undefined;
95
- isIphone?: boolean | undefined;
96
- isIpad?: boolean | undefined;
97
- containerClassName?: string | undefined;
98
- closeOnScrimClick?: boolean | undefined;
99
- } & Omit<P, "dialogRef">>, prevState: Readonly<{}>, snapshot?: any): void;
43
+ getSnapshotBeforeUpdate?(prevProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, prevState: Readonly<{}>): any;
44
+ componentDidUpdate?(prevProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, prevState: Readonly<{}>, snapshot?: any): void;
100
45
  componentWillMount?(): void;
101
46
  UNSAFE_componentWillMount?(): void;
102
- componentWillReceiveProps?(nextProps: Readonly<{
103
- [rest: string]: any;
104
- getApplicationElement: () => HTMLElement | null;
105
- onClose?: (() => void | null) | undefined;
106
- isIphone?: boolean | undefined;
107
- isIpad?: boolean | undefined;
108
- containerClassName?: string | undefined;
109
- closeOnScrimClick?: boolean | undefined;
110
- } & Omit<P, "dialogRef">>, nextContext: any): void;
111
- UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{
112
- [rest: string]: any;
113
- getApplicationElement: () => HTMLElement | null;
114
- onClose?: (() => void | null) | undefined;
115
- isIphone?: boolean | undefined;
116
- isIpad?: boolean | undefined;
117
- containerClassName?: string | undefined;
118
- closeOnScrimClick?: boolean | undefined;
119
- } & Omit<P, "dialogRef">>, nextContext: any): void;
120
- componentWillUpdate?(nextProps: Readonly<{
121
- [rest: string]: any;
122
- getApplicationElement: () => HTMLElement | null;
123
- onClose?: (() => void | null) | undefined;
124
- isIphone?: boolean | undefined;
125
- isIpad?: boolean | undefined;
126
- containerClassName?: string | undefined;
127
- closeOnScrimClick?: boolean | undefined;
128
- } & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
129
- UNSAFE_componentWillUpdate?(nextProps: Readonly<{
130
- [rest: string]: any;
131
- getApplicationElement: () => HTMLElement | null;
132
- onClose?: (() => void | null) | undefined;
133
- isIphone?: boolean | undefined;
134
- isIpad?: boolean | undefined;
135
- containerClassName?: string | undefined;
136
- closeOnScrimClick?: boolean | undefined;
137
- } & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
47
+ componentWillReceiveProps?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextContext: any): void;
48
+ UNSAFE_componentWillReceiveProps?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextContext: any): void;
49
+ componentWillUpdate?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
50
+ UNSAFE_componentWillUpdate?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
138
51
  };
139
- new (props: {
140
- [rest: string]: any;
141
- getApplicationElement: () => HTMLElement | null;
142
- onClose?: (() => void | null) | undefined;
143
- isIphone?: boolean | undefined;
144
- isIpad?: boolean | undefined;
145
- containerClassName?: string | undefined;
146
- closeOnScrimClick?: boolean | undefined;
147
- } & Omit<P, "dialogRef">, context: any): {
52
+ new (props: import("./src/withScrim").Props & Omit<P, "dialogRef">, context: any): {
148
53
  dialogElement?: HTMLElement | null | undefined;
149
54
  componentDidMount(): void;
150
55
  componentWillUnmount(): void;
151
56
  dialogRef: (ref: HTMLElement | null | undefined) => void;
152
57
  render(): JSX.Element;
153
58
  context: any;
154
- setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{
155
- [rest: string]: any;
156
- getApplicationElement: () => HTMLElement | null;
157
- onClose?: (() => void | null) | undefined;
158
- isIphone?: boolean | undefined;
159
- isIpad?: boolean | undefined;
160
- containerClassName?: string | undefined;
161
- closeOnScrimClick?: boolean | undefined;
162
- } & Omit<P, "dialogRef">>) => {} | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
59
+ setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>) => {} | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
163
60
  forceUpdate(callback?: (() => void) | undefined): void;
164
- readonly props: Readonly<{
165
- [rest: string]: any;
166
- getApplicationElement: () => HTMLElement | null;
167
- onClose?: (() => void | null) | undefined;
168
- isIphone?: boolean | undefined;
169
- isIpad?: boolean | undefined;
170
- containerClassName?: string | undefined;
171
- closeOnScrimClick?: boolean | undefined;
172
- } & Omit<P, "dialogRef">> & Readonly<{
61
+ readonly props: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">> & Readonly<{
173
62
  children?: import("react").ReactNode;
174
63
  }>;
175
64
  state: Readonly<{}>;
176
65
  refs: {
177
66
  [key: string]: import("react").ReactInstance;
178
67
  };
179
- shouldComponentUpdate?(nextProps: Readonly<{
180
- [rest: string]: any;
181
- getApplicationElement: () => HTMLElement | null;
182
- onClose?: (() => void | null) | undefined;
183
- isIphone?: boolean | undefined;
184
- isIpad?: boolean | undefined;
185
- containerClassName?: string | undefined;
186
- closeOnScrimClick?: boolean | undefined;
187
- } & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): boolean;
68
+ shouldComponentUpdate?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): boolean;
188
69
  componentDidCatch?(error: Error, errorInfo: import("react").ErrorInfo): void;
189
- getSnapshotBeforeUpdate?(prevProps: Readonly<{
190
- [rest: string]: any;
191
- getApplicationElement: () => HTMLElement | null;
192
- onClose?: (() => void | null) | undefined;
193
- isIphone?: boolean | undefined;
194
- isIpad?: boolean | undefined;
195
- containerClassName?: string | undefined;
196
- closeOnScrimClick?: boolean | undefined;
197
- } & Omit<P, "dialogRef">>, prevState: Readonly<{}>): any;
198
- componentDidUpdate?(prevProps: Readonly<{
199
- [rest: string]: any;
200
- getApplicationElement: () => HTMLElement | null;
201
- onClose?: (() => void | null) | undefined;
202
- isIphone?: boolean | undefined;
203
- isIpad?: boolean | undefined;
204
- containerClassName?: string | undefined;
205
- closeOnScrimClick?: boolean | undefined;
206
- } & Omit<P, "dialogRef">>, prevState: Readonly<{}>, snapshot?: any): void;
70
+ getSnapshotBeforeUpdate?(prevProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, prevState: Readonly<{}>): any;
71
+ componentDidUpdate?(prevProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, prevState: Readonly<{}>, snapshot?: any): void;
207
72
  componentWillMount?(): void;
208
73
  UNSAFE_componentWillMount?(): void;
209
- componentWillReceiveProps?(nextProps: Readonly<{
210
- [rest: string]: any;
211
- getApplicationElement: () => HTMLElement | null;
212
- onClose?: (() => void | null) | undefined;
213
- isIphone?: boolean | undefined;
214
- isIpad?: boolean | undefined;
215
- containerClassName?: string | undefined;
216
- closeOnScrimClick?: boolean | undefined;
217
- } & Omit<P, "dialogRef">>, nextContext: any): void;
218
- UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{
219
- [rest: string]: any;
220
- getApplicationElement: () => HTMLElement | null;
221
- onClose?: (() => void | null) | undefined;
222
- isIphone?: boolean | undefined;
223
- isIpad?: boolean | undefined;
224
- containerClassName?: string | undefined;
225
- closeOnScrimClick?: boolean | undefined;
226
- } & Omit<P, "dialogRef">>, nextContext: any): void;
227
- componentWillUpdate?(nextProps: Readonly<{
228
- [rest: string]: any;
229
- getApplicationElement: () => HTMLElement | null;
230
- onClose?: (() => void | null) | undefined;
231
- isIphone?: boolean | undefined;
232
- isIpad?: boolean | undefined;
233
- containerClassName?: string | undefined;
234
- closeOnScrimClick?: boolean | undefined;
235
- } & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
236
- UNSAFE_componentWillUpdate?(nextProps: Readonly<{
237
- [rest: string]: any;
238
- getApplicationElement: () => HTMLElement | null;
239
- onClose?: (() => void | null) | undefined;
240
- isIphone?: boolean | undefined;
241
- isIpad?: boolean | undefined;
242
- containerClassName?: string | undefined;
243
- closeOnScrimClick?: boolean | undefined;
244
- } & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
74
+ componentWillReceiveProps?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextContext: any): void;
75
+ UNSAFE_componentWillReceiveProps?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextContext: any): void;
76
+ componentWillUpdate?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
77
+ UNSAFE_componentWillUpdate?(nextProps: Readonly<import("./src/withScrim").Props & Omit<P, "dialogRef">>, nextState: Readonly<{}>, nextContext: any): void;
245
78
  };
246
79
  displayName: string;
247
80
  defaultProps: {
@@ -17,7 +17,8 @@
17
17
  */
18
18
 
19
19
  import withScrim from "./src/withScrim";
20
- export { withScrim };
20
+ import withScrimmedPortal from "./src/withScrimmedPortal";
21
+ export { withScrim, withScrimmedPortal };
21
22
  export default {
22
23
  withScrim
23
24
  };
@@ -17,7 +17,7 @@
17
17
  */
18
18
 
19
19
  import type { ComponentType } from 'react';
20
- type Props = {
20
+ export type Props = {
21
21
  getApplicationElement: () => HTMLElement | null;
22
22
  onClose?: () => void | null;
23
23
  isIphone?: boolean;
@@ -0,0 +1,25 @@
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 type { ComponentType } from 'react';
20
+ import type { Props as ScrimProps } from './withScrim';
21
+ type Props = ScrimProps & {
22
+ renderTarget?: (() => HTMLElement | null) | null;
23
+ };
24
+ declare const withScrimmedPortal: (WrappedComponent: ComponentType<ScrimProps>) => ({ renderTarget, ...rest }: Props) => import("react").ReactPortal;
25
+ export default withScrimmedPortal;
@@ -0,0 +1,60 @@
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 { useEffect, useRef } from 'react';
20
+ import { createPortal } from 'react-dom';
21
+ import withScrim from "./withScrim";
22
+ import { jsx as _jsx } from "react/jsx-runtime";
23
+ const getPortalElement = target => {
24
+ const portalElement = target && typeof target === 'function' ? target() : null;
25
+ if (portalElement) {
26
+ return portalElement;
27
+ }
28
+ if (document.body) {
29
+ return document.body;
30
+ }
31
+ throw new Error('Render target and fallback unavailable');
32
+ };
33
+ const withScrimmedPortal = WrappedComponent => {
34
+ const Scrimmed = withScrim(WrappedComponent);
35
+ const ScrimmedComponent = ({
36
+ renderTarget,
37
+ ...rest
38
+ }) => {
39
+ const node = useRef(null);
40
+ if (!node.current) {
41
+ node.current = document.createElement('div');
42
+ }
43
+ useEffect(() => {
44
+ const portalElement = getPortalElement(renderTarget);
45
+ if (node.current) {
46
+ portalElement.appendChild(node.current);
47
+ }
48
+ return () => {
49
+ if (node.current) {
50
+ portalElement.removeChild(node.current);
51
+ }
52
+ };
53
+ }, []);
54
+ return /*#__PURE__*/createPortal( /*#__PURE__*/_jsx(Scrimmed, {
55
+ ...rest
56
+ }), node.current);
57
+ };
58
+ return ScrimmedComponent;
59
+ };
60
+ export default withScrimmedPortal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyscanner/backpack-web",
3
- "version": "30.1.0",
3
+ "version": "30.3.0",
4
4
  "description": "Backpack Design System web library",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "@popperjs/core": "^2.11.5",
26
26
  "@react-google-maps/api": "^2.12.0",
27
- "@skyscanner/bpk-foundations-web": "^17.2.0",
27
+ "@skyscanner/bpk-foundations-web": "^17.4.0",
28
28
  "@skyscanner/bpk-svgs": "^18.1.2",
29
29
  "a11y-focus-scope": "^1.1.3",
30
30
  "a11y-focus-store": "^1.0.0",