@skyscanner/backpack-web 42.10.0-dev-v24496611676.1 → 42.11.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-bottom-sheet/src/BpkBottomSheet.js +1 -0
- package/bpk-component-layout/index.d.ts +0 -4
- package/bpk-component-layout/index.js +0 -2
- package/bpk-component-layout/src/BpkBox.js +13 -16
- package/bpk-component-layout/src/BpkFlex.js +9 -20
- package/bpk-component-layout/src/BpkGrid.js +9 -20
- package/bpk-component-layout/src/BpkGridItem.js +15 -23
- package/bpk-component-layout/src/BpkProvider.d.ts +10 -7
- package/bpk-component-layout/src/BpkProvider.js +98 -12
- package/bpk-component-layout/src/BpkStack.constant.js +2 -3
- package/bpk-component-layout/src/BpkStack.js +40 -89
- package/bpk-component-layout/src/commonProps.d.ts +1 -8
- package/bpk-component-layout/src/theme.d.ts +1 -0
- package/bpk-component-layout/src/theme.js +301 -27
- package/bpk-component-layout/src/tokenUtils.js +11 -34
- package/bpk-component-layout/src/types.d.ts +147 -84
- package/bpk-component-navigation-bar/src/BpkNavigationBar.d.ts +3 -0
- package/bpk-component-navigation-bar/src/BpkNavigationBar.js +2 -1
- package/bpk-component-navigation-bar/src/BpkNavigationBar.module.css +1 -1
- package/bpk-component-page-indicator/src/NavButton.js +3 -3
- package/package.json +3 -2
- package/bpk-component-layout/src/BpkArkProvider.d.ts +0 -20
- package/bpk-component-layout/src/BpkArkProvider.js +0 -112
- package/bpk-component-layout/src/BpkLayoutProvider.d.ts +0 -18
- package/bpk-component-layout/src/BpkLayoutProvider.js +0 -36
- package/bpk-component-layout/src/resolveTextStyle.d.ts +0 -13
- package/bpk-component-layout/src/resolveTextStyle.js +0 -265
- package/bpk-component-layout/src/responsiveStyleBuilder.d.ts +0 -22
- package/bpk-component-layout/src/responsiveStyleBuilder.js +0 -152
- package/bpk-component-layout/src/useCurrentBreakpoint.d.ts +0 -9
- package/bpk-component-layout/src/useCurrentBreakpoint.js +0 -89
|
@@ -1,265 +0,0 @@
|
|
|
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 only the specific tokens needed for text styles, rather than the
|
|
20
|
-
// entire foundations module. This avoids pulling unused tokens (colors,
|
|
21
|
-
// shadows, borders, etc.) into the layout bundle.
|
|
22
|
-
import { fontSizeXs, fontSizeSm, fontSizeBase, fontSizeLg, fontSizeXl, fontSizeXxl, fontSizeXxxl, fontSizeXxxxl, fontSizeXxxxxl, fontSize6Xl, fontSize7Xl, fontSize8Xl, lineHeightXs, lineHeightSm, lineHeightBase, lineHeightBaseTight, lineHeightLg, lineHeightLgTight, lineHeightXl, lineHeightXlTight, lineHeightXxl, lineHeightXxxl, lineHeightXxxxl, lineHeightXxxxxl, lineHeight6Xl, lineHeight7Xl, lineHeight8Xl, fontWeightBook, fontWeightBold, fontWeightBlack, fontWeightLight, letterSpacingTight, letterSpacingHero, fontFamilyLarken } from '@skyscanner/bpk-foundations-web/tokens/base.es6';
|
|
23
|
-
import { BpkBreakpointToChakraKey } from "./tokens";
|
|
24
|
-
/**
|
|
25
|
-
* Maps Backpack text style tokens to concrete CSS properties.
|
|
26
|
-
*
|
|
27
|
-
* This map is intentionally kept outside the Chakra theme config so that
|
|
28
|
-
* layout-only consumers (who never use textStyle) do not pay for it.
|
|
29
|
-
* Components that use textStyle expand it inline via `expandTextStyleProps`.
|
|
30
|
-
*/
|
|
31
|
-
const TEXT_STYLE_MAP = {
|
|
32
|
-
xs: {
|
|
33
|
-
fontSize: fontSizeXs,
|
|
34
|
-
lineHeight: lineHeightXs,
|
|
35
|
-
fontWeight: fontWeightBook
|
|
36
|
-
},
|
|
37
|
-
sm: {
|
|
38
|
-
fontSize: fontSizeSm,
|
|
39
|
-
lineHeight: lineHeightSm,
|
|
40
|
-
fontWeight: fontWeightBook
|
|
41
|
-
},
|
|
42
|
-
base: {
|
|
43
|
-
fontSize: fontSizeBase,
|
|
44
|
-
lineHeight: lineHeightBase,
|
|
45
|
-
fontWeight: fontWeightBook
|
|
46
|
-
},
|
|
47
|
-
lg: {
|
|
48
|
-
fontSize: fontSizeLg,
|
|
49
|
-
lineHeight: lineHeightLg,
|
|
50
|
-
fontWeight: fontWeightBook
|
|
51
|
-
},
|
|
52
|
-
xl: {
|
|
53
|
-
fontSize: fontSizeXl,
|
|
54
|
-
lineHeight: lineHeightXl,
|
|
55
|
-
fontWeight: fontWeightBook
|
|
56
|
-
},
|
|
57
|
-
xxl: {
|
|
58
|
-
fontSize: fontSizeXxl,
|
|
59
|
-
lineHeight: lineHeightXxl,
|
|
60
|
-
fontWeight: fontWeightBold
|
|
61
|
-
},
|
|
62
|
-
xxxl: {
|
|
63
|
-
fontSize: fontSizeXxxl,
|
|
64
|
-
lineHeight: lineHeightXxxl,
|
|
65
|
-
fontWeight: fontWeightBold
|
|
66
|
-
},
|
|
67
|
-
xxxxl: {
|
|
68
|
-
fontSize: fontSizeXxxxl,
|
|
69
|
-
lineHeight: lineHeightXxxxl,
|
|
70
|
-
fontWeight: fontWeightBold,
|
|
71
|
-
letterSpacing: letterSpacingTight
|
|
72
|
-
},
|
|
73
|
-
xxxxxl: {
|
|
74
|
-
fontSize: fontSizeXxxxxl,
|
|
75
|
-
lineHeight: lineHeightXxxxxl,
|
|
76
|
-
fontWeight: fontWeightBold,
|
|
77
|
-
letterSpacing: letterSpacingTight
|
|
78
|
-
},
|
|
79
|
-
caption: {
|
|
80
|
-
fontSize: fontSizeXs,
|
|
81
|
-
lineHeight: lineHeightXs,
|
|
82
|
-
fontWeight: fontWeightBook
|
|
83
|
-
},
|
|
84
|
-
footnote: {
|
|
85
|
-
fontSize: fontSizeSm,
|
|
86
|
-
lineHeight: lineHeightSm,
|
|
87
|
-
fontWeight: fontWeightBook
|
|
88
|
-
},
|
|
89
|
-
'label-1': {
|
|
90
|
-
fontSize: fontSizeBase,
|
|
91
|
-
lineHeight: lineHeightBase,
|
|
92
|
-
fontWeight: fontWeightBold
|
|
93
|
-
},
|
|
94
|
-
'label-2': {
|
|
95
|
-
fontSize: fontSizeSm,
|
|
96
|
-
lineHeight: lineHeightSm,
|
|
97
|
-
fontWeight: fontWeightBold
|
|
98
|
-
},
|
|
99
|
-
'label-3': {
|
|
100
|
-
fontSize: fontSizeXs,
|
|
101
|
-
lineHeight: lineHeightXs,
|
|
102
|
-
fontWeight: fontWeightBold
|
|
103
|
-
},
|
|
104
|
-
'body-default': {
|
|
105
|
-
fontSize: fontSizeBase,
|
|
106
|
-
lineHeight: lineHeightBase,
|
|
107
|
-
fontWeight: fontWeightBook
|
|
108
|
-
},
|
|
109
|
-
'body-longform': {
|
|
110
|
-
fontSize: fontSizeLg,
|
|
111
|
-
lineHeight: lineHeightLg,
|
|
112
|
-
fontWeight: fontWeightBook
|
|
113
|
-
},
|
|
114
|
-
subheading: {
|
|
115
|
-
fontSize: fontSizeXl,
|
|
116
|
-
lineHeight: lineHeightXl,
|
|
117
|
-
fontWeight: fontWeightBook
|
|
118
|
-
},
|
|
119
|
-
'heading-1': {
|
|
120
|
-
fontSize: fontSizeXxxl,
|
|
121
|
-
lineHeight: lineHeightXxxl,
|
|
122
|
-
fontWeight: fontWeightBold
|
|
123
|
-
},
|
|
124
|
-
'heading-2': {
|
|
125
|
-
fontSize: fontSizeXxl,
|
|
126
|
-
lineHeight: lineHeightXxl,
|
|
127
|
-
fontWeight: fontWeightBold
|
|
128
|
-
},
|
|
129
|
-
'heading-3': {
|
|
130
|
-
fontSize: fontSizeXl,
|
|
131
|
-
lineHeight: lineHeightXlTight,
|
|
132
|
-
fontWeight: fontWeightBold
|
|
133
|
-
},
|
|
134
|
-
'heading-4': {
|
|
135
|
-
fontSize: fontSizeLg,
|
|
136
|
-
lineHeight: lineHeightLgTight,
|
|
137
|
-
fontWeight: fontWeightBold
|
|
138
|
-
},
|
|
139
|
-
'heading-5': {
|
|
140
|
-
fontSize: fontSizeBase,
|
|
141
|
-
lineHeight: lineHeightBaseTight,
|
|
142
|
-
fontWeight: fontWeightBold
|
|
143
|
-
},
|
|
144
|
-
'hero-1': {
|
|
145
|
-
fontSize: fontSize8Xl,
|
|
146
|
-
lineHeight: lineHeight8Xl,
|
|
147
|
-
fontWeight: fontWeightBlack,
|
|
148
|
-
letterSpacing: letterSpacingHero
|
|
149
|
-
},
|
|
150
|
-
'hero-2': {
|
|
151
|
-
fontSize: fontSize7Xl,
|
|
152
|
-
lineHeight: lineHeight7Xl,
|
|
153
|
-
fontWeight: fontWeightBlack,
|
|
154
|
-
letterSpacing: letterSpacingHero
|
|
155
|
-
},
|
|
156
|
-
'hero-3': {
|
|
157
|
-
fontSize: fontSize6Xl,
|
|
158
|
-
lineHeight: lineHeight6Xl,
|
|
159
|
-
fontWeight: fontWeightBlack,
|
|
160
|
-
letterSpacing: letterSpacingHero
|
|
161
|
-
},
|
|
162
|
-
'hero-4': {
|
|
163
|
-
fontSize: fontSizeXxxxxl,
|
|
164
|
-
lineHeight: lineHeightXxxxxl,
|
|
165
|
-
fontWeight: fontWeightBlack,
|
|
166
|
-
letterSpacing: letterSpacingHero
|
|
167
|
-
},
|
|
168
|
-
'hero-5': {
|
|
169
|
-
fontSize: fontSizeXxxxl,
|
|
170
|
-
lineHeight: lineHeightXxxl,
|
|
171
|
-
fontWeight: fontWeightBlack,
|
|
172
|
-
letterSpacing: letterSpacingHero
|
|
173
|
-
},
|
|
174
|
-
'hero-6': {
|
|
175
|
-
fontSize: fontSizeXxxl,
|
|
176
|
-
lineHeight: lineHeightXxl,
|
|
177
|
-
fontWeight: fontWeightBlack,
|
|
178
|
-
letterSpacing: letterSpacingHero
|
|
179
|
-
},
|
|
180
|
-
'editorial-1': {
|
|
181
|
-
fontFamily: `var(--bpk-larken-font-stack, ${fontFamilyLarken})`,
|
|
182
|
-
fontSize: fontSizeXxxxl,
|
|
183
|
-
lineHeight: lineHeightXxxxl,
|
|
184
|
-
fontWeight: fontWeightLight
|
|
185
|
-
},
|
|
186
|
-
'editorial-2': {
|
|
187
|
-
fontFamily: `var(--bpk-larken-font-stack, ${fontFamilyLarken})`,
|
|
188
|
-
fontSize: fontSizeXxl,
|
|
189
|
-
lineHeight: lineHeightXxl,
|
|
190
|
-
fontWeight: fontWeightLight
|
|
191
|
-
},
|
|
192
|
-
'editorial-3': {
|
|
193
|
-
fontFamily: `var(--bpk-larken-font-stack, ${fontFamilyLarken})`,
|
|
194
|
-
fontSize: fontSizeLg,
|
|
195
|
-
lineHeight: lineHeightLg,
|
|
196
|
-
fontWeight: fontWeightBook
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Expands a textStyle token (or responsive object of tokens) into concrete
|
|
202
|
-
* CSS property values that can be spread directly onto a Chakra component.
|
|
203
|
-
*
|
|
204
|
-
* Supports:
|
|
205
|
-
* - Static values: `textStyle="heading-3"` → `{ fontSize, lineHeight, fontWeight }`
|
|
206
|
-
* - Responsive objects: `textStyle={{ mobile: 'heading-5', desktop: 'heading-3' }}`
|
|
207
|
-
* → `{ fontSize: { md: '...', '2xl': '...' }, lineHeight: { ... }, ... }`
|
|
208
|
-
*
|
|
209
|
-
* @param {any} value - A textStyle token string, responsive object, or undefined/null.
|
|
210
|
-
* @returns {Record<string, any>} An object of CSS props to spread, or an empty object if no match.
|
|
211
|
-
*/
|
|
212
|
-
// eslint-disable-next-line import/prefer-default-export
|
|
213
|
-
export function expandTextStyleProps(value) {
|
|
214
|
-
if (value == null) return {};
|
|
215
|
-
|
|
216
|
-
// Responsive object: { mobile: 'heading-5', desktop: 'heading-3' }
|
|
217
|
-
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
218
|
-
// Normalise Backpack breakpoint keys to Chakra keys inline (avoids
|
|
219
|
-
// circular dependency on tokenUtils).
|
|
220
|
-
const normalized = {};
|
|
221
|
-
Object.entries(value).forEach(([key, val]) => {
|
|
222
|
-
if (key === 'base') {
|
|
223
|
-
normalized.base = val;
|
|
224
|
-
} else {
|
|
225
|
-
const chakraKey = BpkBreakpointToChakraKey[key];
|
|
226
|
-
if (chakraKey) {
|
|
227
|
-
normalized[chakraKey] = val;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
// Pivot from { bp -> token } to { cssProp -> { bp -> cssValue } }
|
|
233
|
-
const result = {};
|
|
234
|
-
Object.entries(normalized).forEach(([bp, token]) => {
|
|
235
|
-
const style = TEXT_STYLE_MAP[String(token)];
|
|
236
|
-
if (!style) {
|
|
237
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
238
|
-
// eslint-disable-next-line no-console
|
|
239
|
-
console.warn(`Unknown textStyle token "${String(token)}" at breakpoint "${bp}".`);
|
|
240
|
-
}
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
Object.entries(style).forEach(([cssProp, cssValue]) => {
|
|
244
|
-
if (!result[cssProp]) {
|
|
245
|
-
result[cssProp] = {};
|
|
246
|
-
}
|
|
247
|
-
result[cssProp][bp] = cssValue;
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
return result;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Static string value
|
|
254
|
-
const style = TEXT_STYLE_MAP[String(value)];
|
|
255
|
-
if (!style) {
|
|
256
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
257
|
-
// eslint-disable-next-line no-console
|
|
258
|
-
console.warn(`Unknown textStyle token "${String(value)}".`);
|
|
259
|
-
}
|
|
260
|
-
return {};
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
...style
|
|
264
|
-
};
|
|
265
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties } from 'react';
|
|
2
|
-
export type LayoutStyleOutput = {
|
|
3
|
-
/** Inline styles (all values resolved for the current breakpoint) */
|
|
4
|
-
style: CSSProperties & Record<string, string>;
|
|
5
|
-
/** Non-style props to spread on the DOM element */
|
|
6
|
-
passthrough: Record<string, any>;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Converts processed layout props into an output suitable for a plain DOM element.
|
|
10
|
-
*
|
|
11
|
-
* - Scalar values → inline `style` properties
|
|
12
|
-
* - Responsive objects → resolved to the current breakpoint's value via fill-forward,
|
|
13
|
-
* then set as inline `style` properties
|
|
14
|
-
* - Non-style props (id, role, aria-*, data-*, event handlers) → `passthrough`
|
|
15
|
-
*
|
|
16
|
-
* @param {Record<string, any>} processedProps - Props after token conversion and validation
|
|
17
|
-
* by `processBpkComponentProps`. Values are already resolved to CSS values (e.g. '.5rem').
|
|
18
|
-
* Responsive values are objects keyed by Chakra breakpoint keys (base, sm, md, lg, xl, 2xl).
|
|
19
|
-
* @param {string} currentBreakpoint - The currently active breakpoint key from useCurrentBreakpoint
|
|
20
|
-
* @returns {LayoutStyleOutput} Style and passthrough props.
|
|
21
|
-
*/
|
|
22
|
-
export declare function buildLayoutOutput(processedProps: Record<string, any>, currentBreakpoint: string): LayoutStyleOutput;
|
|
@@ -1,152 +0,0 @@
|
|
|
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
|
-
/**
|
|
20
|
-
* All style props that participate in the layout system.
|
|
21
|
-
* These are recognised as CSS-settable properties and will be
|
|
22
|
-
* placed into the inline `style` object.
|
|
23
|
-
*/
|
|
24
|
-
const STYLE_PROPS = new Set([
|
|
25
|
-
// Spacing
|
|
26
|
-
'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingStart', 'paddingEnd', 'paddingInline', 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginStart', 'marginEnd', 'marginInline', 'gap', 'spacing', 'rowGap', 'columnGap',
|
|
27
|
-
// Size
|
|
28
|
-
'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
|
|
29
|
-
// Position offsets
|
|
30
|
-
'top', 'right', 'bottom', 'left',
|
|
31
|
-
// Display & position
|
|
32
|
-
'display', 'position', 'overflow', 'overflowX', 'overflowY',
|
|
33
|
-
// Flex container
|
|
34
|
-
'flexDirection', 'flexWrap', 'justifyContent', 'alignItems', 'alignContent',
|
|
35
|
-
// Flex item
|
|
36
|
-
'flex', 'flexGrow', 'flexShrink', 'flexBasis', 'order', 'alignSelf', 'justifySelf',
|
|
37
|
-
// Grid container
|
|
38
|
-
'gridTemplateColumns', 'gridTemplateRows', 'gridTemplateAreas', 'gridAutoFlow', 'gridAutoRows', 'gridAutoColumns',
|
|
39
|
-
// Grid item
|
|
40
|
-
'gridColumn', 'gridRow',
|
|
41
|
-
// Typography
|
|
42
|
-
'fontSize', 'lineHeight', 'fontWeight', 'letterSpacing', 'fontFamily', 'textAlign', 'whiteSpace',
|
|
43
|
-
// Visual
|
|
44
|
-
'cursor', 'opacity', 'visibility', 'pointerEvents', 'userSelect']);
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Maps camelCase JS prop names to their CSS property equivalents.
|
|
48
|
-
* Used for setting inline styles on props whose JS name differs from CSS.
|
|
49
|
-
*/
|
|
50
|
-
const PROP_TO_CSS_PROPERTY = {
|
|
51
|
-
paddingStart: 'paddingInlineStart',
|
|
52
|
-
paddingEnd: 'paddingInlineEnd',
|
|
53
|
-
marginStart: 'marginInlineStart',
|
|
54
|
-
marginEnd: 'marginInlineEnd',
|
|
55
|
-
spacing: 'gap' // Chakra Stack alias
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Props that are passed through to the DOM element as-is (not style props).
|
|
60
|
-
*/
|
|
61
|
-
const PASSTHROUGH_KEYS = new Set(['id', 'role', 'tabIndex', 'onClick', 'onKeyDown', 'onFocus', 'onBlur', 'onMouseEnter', 'onMouseLeave', 'onMouseOver', 'onMouseOut', 'onMouseDown', 'onMouseUp', 'onKeyUp', 'onKeyPress', 'children']);
|
|
62
|
-
const PASSTHROUGH_PREFIXES = ['aria-', 'data-'];
|
|
63
|
-
function isPassthroughProp(key) {
|
|
64
|
-
if (PASSTHROUGH_KEYS.has(key)) return true;
|
|
65
|
-
return PASSTHROUGH_PREFIXES.some(prefix => key.startsWith(prefix));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Props that are handled separately by components (not style, not passthrough).
|
|
70
|
-
* These are stripped from the style output and handled in the component layer.
|
|
71
|
-
*/
|
|
72
|
-
const COMPONENT_HANDLED_KEYS = new Set(['color', 'backgroundColor', 'className', 'style', 'zIndex']);
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Breakpoint order (ascending, mobile-first).
|
|
76
|
-
* Used by the fill-forward resolution to determine which value applies
|
|
77
|
-
* at the current breakpoint.
|
|
78
|
-
*/
|
|
79
|
-
const BP_ORDER = ['sm', 'md', 'lg', 'xl', '2xl'];
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Resolves a responsive value object to the effective value for a given breakpoint.
|
|
83
|
-
* Uses fill-forward: the most recently specified value at or below the current
|
|
84
|
-
* breakpoint wins.
|
|
85
|
-
*
|
|
86
|
-
* @param {Record<string, string>} responsive - Object keyed by breakpoint (base, sm, md, lg, xl, 2xl)
|
|
87
|
-
* @param {string} currentBp - The currently active breakpoint key
|
|
88
|
-
* @returns {string | undefined} The resolved value, or undefined if no value applies
|
|
89
|
-
*/
|
|
90
|
-
function resolveResponsive(responsive, currentBp) {
|
|
91
|
-
let result = responsive.base !== undefined ? String(responsive.base) : undefined;
|
|
92
|
-
for (const bp of BP_ORDER) {
|
|
93
|
-
if (responsive[bp] !== undefined) {
|
|
94
|
-
result = String(responsive[bp]);
|
|
95
|
-
}
|
|
96
|
-
if (bp === currentBp) break;
|
|
97
|
-
}
|
|
98
|
-
return result;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Converts processed layout props into an output suitable for a plain DOM element.
|
|
102
|
-
*
|
|
103
|
-
* - Scalar values → inline `style` properties
|
|
104
|
-
* - Responsive objects → resolved to the current breakpoint's value via fill-forward,
|
|
105
|
-
* then set as inline `style` properties
|
|
106
|
-
* - Non-style props (id, role, aria-*, data-*, event handlers) → `passthrough`
|
|
107
|
-
*
|
|
108
|
-
* @param {Record<string, any>} processedProps - Props after token conversion and validation
|
|
109
|
-
* by `processBpkComponentProps`. Values are already resolved to CSS values (e.g. '.5rem').
|
|
110
|
-
* Responsive values are objects keyed by Chakra breakpoint keys (base, sm, md, lg, xl, 2xl).
|
|
111
|
-
* @param {string} currentBreakpoint - The currently active breakpoint key from useCurrentBreakpoint
|
|
112
|
-
* @returns {LayoutStyleOutput} Style and passthrough props.
|
|
113
|
-
*/
|
|
114
|
-
export function buildLayoutOutput(processedProps, currentBreakpoint) {
|
|
115
|
-
const style = {};
|
|
116
|
-
const passthrough = {};
|
|
117
|
-
Object.entries(processedProps).forEach(([key, value]) => {
|
|
118
|
-
if (value === undefined || value === null) return;
|
|
119
|
-
|
|
120
|
-
// Passthrough props go directly to the DOM element
|
|
121
|
-
if (isPassthroughProp(key)) {
|
|
122
|
-
passthrough[key] = value;
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Component-handled props are skipped (handled by the component)
|
|
127
|
-
if (COMPONENT_HANDLED_KEYS.has(key)) return;
|
|
128
|
-
|
|
129
|
-
// Not a known style prop — pass through
|
|
130
|
-
if (!STYLE_PROPS.has(key)) {
|
|
131
|
-
passthrough[key] = value;
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const cssPropName = PROP_TO_CSS_PROPERTY[key] || key;
|
|
135
|
-
|
|
136
|
-
// Responsive object → resolve to current breakpoint value
|
|
137
|
-
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
138
|
-
const resolved = resolveResponsive(value, currentBreakpoint);
|
|
139
|
-
if (resolved !== undefined) {
|
|
140
|
-
style[cssPropName] = resolved;
|
|
141
|
-
}
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Scalar value → inline style
|
|
146
|
-
style[cssPropName] = String(value);
|
|
147
|
-
});
|
|
148
|
-
return {
|
|
149
|
-
style: style,
|
|
150
|
-
passthrough
|
|
151
|
-
};
|
|
152
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns the current active breakpoint key based on viewport width.
|
|
3
|
-
* Uses `window.matchMedia` listeners to re-render when breakpoints change.
|
|
4
|
-
* SSR-safe: returns `'base'` when `window` is unavailable.
|
|
5
|
-
*
|
|
6
|
-
* @returns {string} The active breakpoint key ('base' | 'sm' | 'md' | 'lg' | 'xl' | '2xl')
|
|
7
|
-
*/
|
|
8
|
-
declare const useCurrentBreakpoint: () => string;
|
|
9
|
-
export default useCurrentBreakpoint;
|
|
@@ -1,89 +0,0 @@
|
|
|
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, useState } from 'react';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Breakpoint min-widths in ascending order (mobile-first).
|
|
23
|
-
* Must match the breakpoint definitions in tokens.ts
|
|
24
|
-
* and the breakpoint mapping in tokens.ts.
|
|
25
|
-
*/
|
|
26
|
-
const BREAKPOINTS = [{
|
|
27
|
-
key: 'sm',
|
|
28
|
-
query: '(min-width: 20rem)'
|
|
29
|
-
},
|
|
30
|
-
// 320px — small-mobile
|
|
31
|
-
{
|
|
32
|
-
key: 'md',
|
|
33
|
-
query: '(min-width: 22.5rem)'
|
|
34
|
-
},
|
|
35
|
-
// 360px — mobile
|
|
36
|
-
{
|
|
37
|
-
key: 'lg',
|
|
38
|
-
query: '(min-width: 32.0625rem)'
|
|
39
|
-
},
|
|
40
|
-
// 513px — small-tablet
|
|
41
|
-
{
|
|
42
|
-
key: 'xl',
|
|
43
|
-
query: '(min-width: 48.0625rem)'
|
|
44
|
-
},
|
|
45
|
-
// 769px — tablet
|
|
46
|
-
{
|
|
47
|
-
key: '2xl',
|
|
48
|
-
query: '(min-width: 64.0625rem)'
|
|
49
|
-
} // 1025px — desktop
|
|
50
|
-
];
|
|
51
|
-
function getCurrentBreakpoint() {
|
|
52
|
-
if (typeof window === 'undefined' || !window.matchMedia) return 'base';
|
|
53
|
-
let active = 'base';
|
|
54
|
-
for (const {
|
|
55
|
-
key,
|
|
56
|
-
query
|
|
57
|
-
} of BREAKPOINTS) {
|
|
58
|
-
if (window.matchMedia(query).matches) active = key;
|
|
59
|
-
}
|
|
60
|
-
return active;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Returns the current active breakpoint key based on viewport width.
|
|
65
|
-
* Uses `window.matchMedia` listeners to re-render when breakpoints change.
|
|
66
|
-
* SSR-safe: returns `'base'` when `window` is unavailable.
|
|
67
|
-
*
|
|
68
|
-
* @returns {string} The active breakpoint key ('base' | 'sm' | 'md' | 'lg' | 'xl' | '2xl')
|
|
69
|
-
*/
|
|
70
|
-
const useCurrentBreakpoint = () => {
|
|
71
|
-
const [breakpoint, setBreakpoint] = useState(getCurrentBreakpoint);
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
const mqls = BREAKPOINTS.map(({
|
|
77
|
-
query
|
|
78
|
-
}) => window.matchMedia(query));
|
|
79
|
-
const update = () => {
|
|
80
|
-
setBreakpoint(getCurrentBreakpoint());
|
|
81
|
-
};
|
|
82
|
-
mqls.forEach(mql => mql.addEventListener('change', update));
|
|
83
|
-
return () => {
|
|
84
|
-
mqls.forEach(mql => mql.removeEventListener('change', update));
|
|
85
|
-
};
|
|
86
|
-
}, []);
|
|
87
|
-
return breakpoint;
|
|
88
|
-
};
|
|
89
|
-
export default useCurrentBreakpoint;
|