@skyscanner/backpack-web 41.10.0-beta-v1 → 41.11.1

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.
Files changed (55) hide show
  1. package/bpk-component-accordion/src/BpkAccordion.js +2 -1
  2. package/bpk-component-accordion/src/BpkAccordionItem.js +2 -1
  3. package/bpk-component-aria-live/src/BpkAriaLive.js +2 -1
  4. package/bpk-component-autosuggest/src/BpkAutosuggestV2/BpkAutosuggest.js +2 -1
  5. package/bpk-component-bottom-sheet/src/BpkBottomSheet.js +14 -5
  6. package/bpk-component-breakpoint/src/useMediaQuery.js +27 -14
  7. package/bpk-component-bubble/src/BpkBubble.js +2 -1
  8. package/bpk-component-calendar/src/BpkCalendarDate.js +2 -1
  9. package/bpk-component-calendar/src/BpkCalendarGrid.js +2 -1
  10. package/bpk-component-calendar/src/BpkCalendarGridHeader.js +2 -1
  11. package/bpk-component-calendar/src/BpkCalendarGridTransition.js +2 -1
  12. package/bpk-component-calendar/src/BpkCalendarNav.js +2 -1
  13. package/bpk-component-calendar/src/BpkCalendarWeek.js +2 -1
  14. package/bpk-component-chip/src/BpkDismissibleChip.js +3 -2
  15. package/bpk-component-chip/src/BpkDropdownChip.js +2 -0
  16. package/bpk-component-chip/src/BpkIconChip.js +2 -0
  17. package/bpk-component-chip/src/BpkSelectableChip.js +2 -1
  18. package/bpk-component-chip-group/src/BpkMultiSelectChipGroup.js +2 -1
  19. package/bpk-component-chip-group/src/BpkStickyChip.js +2 -1
  20. package/bpk-component-map/src/BpkBasicMapMarker.js +3 -0
  21. package/bpk-component-map/src/BpkPriceMarker.js +2 -0
  22. package/bpk-component-price-range/src/BpkPriceMarker.js +2 -1
  23. package/bpk-component-price-range/src/BpkPriceRange.js +2 -1
  24. package/bpk-component-scrollable-calendar/src/BpkScrollableCalendarGrid.js +2 -1
  25. package/bpk-component-scrollable-calendar/src/BpkScrollableCalendarGridList.js +2 -1
  26. package/bpk-component-tooltip/src/BpkTooltip.js +2 -1
  27. package/package.json +1 -2
  28. package/bpk-component-layout/index.d.ts +0 -18
  29. package/bpk-component-layout/index.js +0 -29
  30. package/bpk-component-layout/src/BpkBox.d.ts +0 -3
  31. package/bpk-component-layout/src/BpkBox.js +0 -33
  32. package/bpk-component-layout/src/BpkFlex.d.ts +0 -3
  33. package/bpk-component-layout/src/BpkFlex.js +0 -51
  34. package/bpk-component-layout/src/BpkGrid.d.ts +0 -3
  35. package/bpk-component-layout/src/BpkGrid.js +0 -57
  36. package/bpk-component-layout/src/BpkGridItem.d.ts +0 -3
  37. package/bpk-component-layout/src/BpkGridItem.js +0 -45
  38. package/bpk-component-layout/src/BpkProvider.d.ts +0 -14
  39. package/bpk-component-layout/src/BpkProvider.js +0 -42
  40. package/bpk-component-layout/src/BpkStack.constant.d.ts +0 -2
  41. package/bpk-component-layout/src/BpkStack.constant.js +0 -22
  42. package/bpk-component-layout/src/BpkStack.d.ts +0 -5
  43. package/bpk-component-layout/src/BpkStack.js +0 -57
  44. package/bpk-component-layout/src/BpkVessel.d.ts +0 -46
  45. package/bpk-component-layout/src/BpkVessel.js +0 -70
  46. package/bpk-component-layout/src/commonProps.d.ts +0 -86
  47. package/bpk-component-layout/src/commonProps.js +0 -1
  48. package/bpk-component-layout/src/theme.d.ts +0 -36
  49. package/bpk-component-layout/src/theme.js +0 -229
  50. package/bpk-component-layout/src/tokenUtils.d.ts +0 -108
  51. package/bpk-component-layout/src/tokenUtils.js +0 -323
  52. package/bpk-component-layout/src/tokens.d.ts +0 -96
  53. package/bpk-component-layout/src/tokens.js +0 -138
  54. package/bpk-component-layout/src/types.d.ts +0 -236
  55. package/bpk-component-layout/src/types.js +0 -1
@@ -1,229 +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 { defineConfig } from '@chakra-ui/react';
20
- // Import tokens from Backpack foundations
21
- // Note: Some tokens may not be in TypeScript definitions but exist at runtime
22
-
23
- const bpkTokens = require('@skyscanner/bpk-foundations-web/tokens/base.es6');
24
-
25
- // NOTE:
26
- // We intentionally do not use the raw breakpoint *values* from foundations here.
27
- // Foundations exports breakpoint values such as `breakpointMobile = "32rem"` which
28
- // are used primarily for max-width queries (e.g. `(max-width: 32rem)`).
29
- //
30
- // Backpack layout responsive values in this package are mobile-first and behave
31
- // like Chakra breakpoints (min-width thresholds). To align with Backpack’s
32
- // intended breakpoint ranges we define lower-bound (min-width) thresholds:
33
- //
34
- // - small-mobile: 320px+
35
- // - mobile: 360px+
36
- // - small-tablet: 513px+
37
- // - tablet: 769px+
38
- // - desktop: 1025px+
39
-
40
- // Note: Spacing tokens are defined as SCSS functions in Backpack foundations,
41
- // not as direct values. We need to use the actual rem values from the SCSS functions.
42
- // Based on @skyscanner/bpk-foundations-web/tokens/base.default.scss:
43
- // - bpk-spacing-sm() returns .25rem
44
- // - bpk-spacing-md() returns .5rem
45
- // - bpk-spacing-lg() returns 1.5rem
46
- // - bpk-spacing-xl() returns 2rem (needs verification)
47
- // - bpk-spacing-xxl() returns 2.5rem
48
- // - bpk-spacing-base() returns 1rem (standard base spacing)
49
- // TODO: CLOV-1021 - will add spacing tokens to Backpack Foundations package and use them here after we ship the PoC
50
- const spacingXs = '.125rem'; // 2px
51
- const spacingSm = '.25rem';
52
- const spacingBase = '1rem'; // Standard base spacing
53
- const spacingMd = '.5rem';
54
- const spacingLg = '1.5rem';
55
- const spacingXl = '2rem';
56
- const spacingXxl = '2.5rem';
57
-
58
- /**
59
- * Backpack Theme Configuration for Chakra UI
60
- *
61
- * This theme maps Backpack design tokens from @skyscanner/bpk-foundations-web
62
- * to Chakra UI's theme structure.
63
- */
64
-
65
- /**
66
- * Maps Backpack spacing tokens to actual rem values.
67
- * These come directly from @skyscanner/bpk-foundations-web.
68
- */
69
- // Spacing tokens - directly imported from foundations
70
- const spacingMap = {
71
- 'bpk-spacing-none': {
72
- value: '0'
73
- },
74
- // Temporary: Foundations does not yet export a 2px spacing token. This will be
75
- // replaced with a foundations value once available.
76
- 'bpk-spacing-xs': {
77
- value: spacingXs
78
- },
79
- 'bpk-spacing-sm': {
80
- value: spacingSm
81
- },
82
- 'bpk-spacing-base': {
83
- value: spacingBase
84
- },
85
- 'bpk-spacing-md': {
86
- value: spacingMd
87
- },
88
- 'bpk-spacing-lg': {
89
- value: spacingLg
90
- },
91
- 'bpk-spacing-xl': {
92
- value: spacingXl
93
- },
94
- 'bpk-spacing-xxl': {
95
- value: spacingXxl
96
- }
97
- };
98
-
99
- /**
100
- * Maps Backpack border size tokens to actual border width values
101
- * These come directly from @skyscanner/bpk-foundations-web
102
- */
103
- const borderSizeMap = {
104
- 'bpk-border-size-sm': bpkTokens.borderSizeSm,
105
- 'bpk-border-size-lg': bpkTokens.borderSizeLg,
106
- 'bpk-border-size-xl': bpkTokens.borderSizeXl
107
- };
108
-
109
- /**
110
- * Maps Backpack border radius tokens to actual radius values.
111
- * These come directly from @skyscanner/bpk-foundations-web.
112
- */
113
- const borderRadiusMap = {
114
- 'bpk-border-radius-none': '0',
115
- 'bpk-border-radius-xs': bpkTokens.borderRadiusXs,
116
- 'bpk-border-radius-sm': bpkTokens.borderRadiusSm,
117
- 'bpk-border-radius-md': bpkTokens.borderRadiusMd,
118
- 'bpk-border-radius-lg': bpkTokens.borderRadiusLg,
119
- 'bpk-border-radius-xl': bpkTokens.borderRadiusXl,
120
- 'bpk-border-radius-full': bpkTokens.borderRadiusFull
121
- };
122
-
123
- /**
124
- * Maps Backpack shadow tokens to actual box-shadow values
125
- * These come directly from @skyscanner/bpk-foundations-web
126
- */
127
- const shadowMap = {
128
- 'bpk-shadow-sm': bpkTokens.boxShadowSm,
129
- 'bpk-shadow-lg': bpkTokens.boxShadowLg,
130
- 'bpk-shadow-xl': bpkTokens.boxShadowXl
131
- };
132
-
133
- /**
134
- * Chakra expects raw width values (e.g. "48rem"), not full media queries.
135
- * The media query construction is handled internally by Chakra's system.
136
- *
137
- * We align Backpack breakpoint tokens to Chakra's keys like this:
138
- * - base: 0 (implicit)
139
- * - sm: small-mobile (>= 320px)
140
- * - md: mobile (>= 360px)
141
- * - lg: small-tablet (>= 513px)
142
- * - xl: tablet (>= 769px)
143
- * - 2xl: desktop (>= 1025px)
144
- */
145
- // TODO: CLOV-1021 - will add breakpoint boundary tokens to Backpack Foundations package and use them here after we ship the PoC
146
- const breakpointMap = {
147
- base: '0rem',
148
- sm: '20rem',
149
- // 320px
150
- md: '22.5rem',
151
- // 360px
152
- lg: '32.0625rem',
153
- // 513px
154
- xl: '48.0625rem',
155
- // 769px
156
- '2xl': '64.0625rem' // 1025px
157
- };
158
-
159
- /**
160
- * Exports spacing map for use in tokenUtils
161
- * This allows tokenUtils to look up actual spacing values
162
- *
163
- * @returns {Record<string, string>} A map of spacing token names to values.
164
- */
165
- export function getSpacingMap() {
166
- // Return simple string values for backward compatibility with utilities
167
- const simpleMap = {};
168
- Object.entries(spacingMap).forEach(([key, obj]) => {
169
- simpleMap[key] = obj.value;
170
- });
171
- return simpleMap;
172
- }
173
-
174
- /**
175
- * Gets the actual spacing value for a Backpack spacing token
176
- *
177
- * @param {string} token - Backpack spacing token name.
178
- * @returns {string | undefined} The actual spacing value.
179
- */
180
- export function getSpacingValue(token) {
181
- return spacingMap[token]?.value;
182
- }
183
-
184
- /**
185
- * Gets the actual border width value for a Backpack border size token
186
- *
187
- * @param {string} token - Backpack border size token name.
188
- * @returns {string | undefined} The actual border width value.
189
- */
190
- export function getBorderSizeValue(token) {
191
- return borderSizeMap[token];
192
- }
193
-
194
- /**
195
- * Gets the actual border radius value for a Backpack border radius token
196
- *
197
- * @param {string} token - Backpack border radius token name.
198
- * @returns {string | undefined} The actual border radius value.
199
- */
200
- export function getBorderRadiusValue(token) {
201
- return borderRadiusMap[token];
202
- }
203
-
204
- /**
205
- * Gets the actual box-shadow value for a Backpack shadow token
206
- *
207
- * @param {string} token - Backpack shadow token name.
208
- * @returns {string | undefined} The actual box-shadow value.
209
- */
210
- export function getShadowValue(token) {
211
- return shadowMap[token];
212
- }
213
- export function createBpkConfig() {
214
- // Convert breakpoint map to Chakra UI format
215
- // Breakpoints in Chakra v3 are typically simple strings in the breakpoints object
216
- const chakraBreakpoints = {};
217
- Object.entries(breakpointMap).forEach(([token, value]) => {
218
- chakraBreakpoints[token] = value;
219
- });
220
- return defineConfig({
221
- cssVarsPrefix: 'bpk',
222
- theme: {
223
- tokens: {
224
- spacing: spacingMap
225
- },
226
- breakpoints: chakraBreakpoints
227
- }
228
- });
229
- }
@@ -1,108 +0,0 @@
1
- export type BpkLayoutComponentName = 'BpkBox' | 'BpkFlex' | 'BpkGrid' | 'BpkStack';
2
- /**
3
- * Allowlisted, component-scoped prop groups that are eligible for Backpack responsive value
4
- * processing (Backpack breakpoint keys -> Chakra breakpoint keys).
5
- *
6
- * NOTE:
7
- * - Spacing/size/position props are processed separately via `processBpkProps` and therefore
8
- * are intentionally NOT included here.
9
- * - These groups are meant to keep the responsive surface predictable per component, while
10
- * avoiding duplicated per-component breakpoint mapping logic.
11
- */
12
- type BpkResponsivePropGroups = {
13
- /**
14
- * Container-level layout props (how children are laid out).
15
- */
16
- container: readonly string[];
17
- /**
18
- * Item-level layout props (how this element participates in a parent layout).
19
- */
20
- item?: readonly string[];
21
- };
22
- export declare const BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT: Record<BpkLayoutComponentName, BpkResponsivePropGroups>;
23
- export declare const BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT: Record<BpkLayoutComponentName, readonly string[]>;
24
- export type ProcessBpkComponentPropsOptions = {
25
- component: BpkLayoutComponentName;
26
- /**
27
- * Optional map of responsive props. When provided, it will be filtered to the
28
- * allowlist for the given component, then breakpoint-normalised.
29
- *
30
- * This is useful for components like `BpkFlex` and `BpkGrid` that expose a
31
- * public API with different prop names.
32
- */
33
- responsiveProps?: Record<string, any>;
34
- /**
35
- * Optional mapping of source prop name -> target prop name.
36
- * Primarily kept for parity with `processResponsiveProps`.
37
- */
38
- propNameMap?: Record<string, string>;
39
- };
40
- /**
41
- * Process a component's props in one place:
42
- * - strip className/style
43
- * - process spacing/size/position props (including breakpoint mapping + token conversion)
44
- * - process allowlisted non-spacing responsive layout props (breakpoint mapping only)
45
- *
46
- * The allowlist is grouped by component via `BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT`.
47
- *
48
- * @param {T} props - The component props to process.
49
- * @param {ProcessBpkComponentPropsOptions} options - Component processing options (allowlist group + mapping).
50
- * @returns {Record<string, any>} The processed props ready to pass to Chakra primitives.
51
- */
52
- export declare function processBpkComponentProps<T extends Record<string, any>>(props: T, options: ProcessBpkComponentPropsOptions): Record<string, any>;
53
- /**
54
- * Converts Backpack spacing token to Chakra UI compatible value
55
- * Returns the actual spacing value from the theme, not a token path
56
- *
57
- * @param {string} value - Backpack spacing token (e.g., 'bpk-spacing-base') or percentage
58
- * @returns {string} The actual spacing value in rem or the percentage string
59
- */
60
- export declare function convertBpkSpacingToChakra(value: string): string;
61
- /**
62
- * Recursively processes responsive values (arrays or objects) to validate and convert tokens
63
- *
64
- * @param {*} value - The value to process (could be string, array, or object)
65
- * @param {Function} converter - Function to convert valid tokens to actual values
66
- * @param {Function} validator - Function to validate if a token is allowed
67
- * @param {string} propName - The name of the prop being processed (for warning messages)
68
- * @returns {*} The processed value with tokens converted, or undefined for invalid tokens
69
- */
70
- export declare function normalizeResponsiveObject<T>(value: Record<string, T>): Record<string, T>;
71
- export declare function processResponsiveValue(value: any, converter: (v: string) => string, validator: (v: string) => boolean, propName: string): any;
72
- /**
73
- * Validates and converts spacing props for Chakra UI
74
- * Handles all spacing-related properties including padding, margin, gap, size, border radius and position
75
- *
76
- * @param {T} props - Component props object
77
- * @returns {Record<string, any>} Processed props with spacing tokens converted to actual values
78
- */
79
- export declare function processSpacingProps<T extends Record<string, any>>(props: T): Record<string, any>;
80
- /**
81
- * Processes all props to convert Backpack tokens to Chakra UI format
82
- * Also explicitly removes className and style to prevent ad-hoc overrides
83
- *
84
- * Processing order:
85
- * 1. Remove className & style
86
- * 2. Process spacing props (includes position)
87
- *
88
- * @param {T} props - Component props object
89
- * @returns {Record<string, any>} Processed props with tokens converted and disallowed props removed
90
- */
91
- export declare function processBpkProps<T extends Record<string, any>>(props: T): Record<string, any>;
92
- /**
93
- * Processes responsive props that are simple string/enum values (non-spacing)
94
- * using Backpack breakpoint keys. Array syntax is rejected as in spacing.
95
- *
96
- * @param {*} value - The value to process
97
- * @param {string} propName - The name of the prop being processed
98
- * @returns {*} The processed value with breakpoint keys mapped to Chakra keys
99
- */
100
- export declare function processResponsiveStringProp(value: any, propName: string): any;
101
- /**
102
- * Processes a collection of responsive props.
103
- * @param {Record<string, any>} props - Object containing prop values.
104
- * @param {Record<string, string>} propNameMap - Map of prop name to CSS/Chakra property name (for error messages and mapping).
105
- * @returns {Record<string, any>} Processed props object.
106
- */
107
- export declare function processResponsiveProps(props: Record<string, any>, propNameMap?: Record<string, string>): Record<string, any>;
108
- export {};
@@ -1,323 +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 StackOptionKeys from "./BpkStack.constant";
20
- import { getSpacingValue } from "./theme";
21
- import { BpkBreakpointToChakraKey, isValidSpacingValue, isValidSizeValue, isValidPositionValue, isPercentage } from "./tokens";
22
-
23
- /**
24
- * Allowlisted, component-scoped prop groups that are eligible for Backpack responsive value
25
- * processing (Backpack breakpoint keys -> Chakra breakpoint keys).
26
- *
27
- * NOTE:
28
- * - Spacing/size/position props are processed separately via `processBpkProps` and therefore
29
- * are intentionally NOT included here.
30
- * - These groups are meant to keep the responsive surface predictable per component, while
31
- * avoiding duplicated per-component breakpoint mapping logic.
32
- */
33
-
34
- export const BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT = {
35
- BpkBox: {
36
- container: [
37
- // Display
38
- 'display',
39
- // Flex container props
40
- 'flexDirection', 'flexWrap', 'justifyContent', 'alignItems', 'alignContent',
41
- // Grid container props
42
- 'gridTemplateColumns', 'gridTemplateRows', 'gridTemplateAreas', 'gridAutoFlow', 'gridAutoRows', 'gridAutoColumns'],
43
- item: [
44
- // Flex item props
45
- 'flex', 'flexGrow', 'flexShrink', 'flexBasis', 'order', 'alignSelf', 'justifySelf',
46
- // Grid item placement props (useful on Box when composing grids)
47
- 'gridColumn', 'gridRow']
48
- },
49
- // Note: BpkFlex maps its public API props to these Chakra keys.
50
- BpkFlex: {
51
- container: ['flexDirection', 'justifyContent', 'alignItems', 'flexWrap'],
52
- item: ['flexGrow', 'flexShrink', 'flexBasis']
53
- },
54
- // Note: BpkGrid maps its public API props to these Chakra keys.
55
- BpkGrid: {
56
- container: ['justifyContent', 'alignItems', 'gridTemplateColumns', 'gridTemplateRows', 'gridTemplateAreas', 'gridAutoFlow', 'gridAutoRows', 'gridAutoColumns'],
57
- item: [
58
- // Used when placing the grid itself within a parent grid.
59
- 'gridColumn', 'gridRow']
60
- },
61
- // Note: BpkStack uses Chakra Stack option prop names directly.
62
- BpkStack: {
63
- container: StackOptionKeys
64
- }
65
- };
66
- export const BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT = {
67
- BpkBox: [...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkBox.container, ...(BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkBox.item ?? [])],
68
- BpkFlex: [...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkFlex.container, ...(BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkFlex.item ?? [])],
69
- BpkGrid: [...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkGrid.container, ...(BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkGrid.item ?? [])],
70
- BpkStack: [...BPK_RESPONSIVE_PROP_GROUPS_BY_COMPONENT.BpkStack.container]
71
- };
72
- function filterToAllowlist(props, allowlist) {
73
- const allowed = new Set(allowlist);
74
- const result = {};
75
- Object.keys(props).forEach(key => {
76
- if (allowed.has(key) && props[key] !== undefined) {
77
- result[key] = props[key];
78
- }
79
- });
80
- return result;
81
- }
82
-
83
- /**
84
- * Process a component's props in one place:
85
- * - strip className/style
86
- * - process spacing/size/position props (including breakpoint mapping + token conversion)
87
- * - process allowlisted non-spacing responsive layout props (breakpoint mapping only)
88
- *
89
- * The allowlist is grouped by component via `BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT`.
90
- *
91
- * @param {T} props - The component props to process.
92
- * @param {ProcessBpkComponentPropsOptions} options - Component processing options (allowlist group + mapping).
93
- * @returns {Record<string, any>} The processed props ready to pass to Chakra primitives.
94
- */
95
- export function processBpkComponentProps(props, options) {
96
- const processed = processBpkProps(props);
97
- const allowlist = BPK_RESPONSIVE_PROP_KEYS_BY_COMPONENT[options.component];
98
- const responsiveSource = options.responsiveProps ? filterToAllowlist(options.responsiveProps, allowlist) : filterToAllowlist(processed, allowlist);
99
- if (Object.keys(responsiveSource).length === 0) {
100
- return processed;
101
- }
102
-
103
- // Ensure allowlisted layout props do NOT fall through unprocessed (e.g. array responsive values).
104
- // These props must be provided via the responsive processing pipeline only.
105
- const cleanedProcessed = {
106
- ...processed
107
- };
108
- allowlist.forEach(key => {
109
- if (key in cleanedProcessed) {
110
- delete cleanedProcessed[key];
111
- }
112
- });
113
- const responsiveProcessed = processResponsiveProps(responsiveSource, options.propNameMap);
114
-
115
- // Remove keys that ended up as `undefined` (e.g. array responsive values are rejected).
116
- Object.keys(responsiveProcessed).forEach(key => {
117
- if (responsiveProcessed[key] === undefined) {
118
- delete responsiveProcessed[key];
119
- }
120
- });
121
- return {
122
- ...cleanedProcessed,
123
- ...responsiveProcessed
124
- };
125
- }
126
-
127
- /**
128
- * Converts Backpack spacing token to Chakra UI compatible value
129
- * Returns the actual spacing value from the theme, not a token path
130
- *
131
- * @param {string} value - Backpack spacing token (e.g., 'bpk-spacing-base') or percentage
132
- * @returns {string} The actual spacing value in rem or the percentage string
133
- */
134
- export function convertBpkSpacingToChakra(value) {
135
- if (isPercentage(value)) {
136
- return value; // Percentages pass through
137
- }
138
-
139
- // Look up the actual spacing value from the theme
140
- const spacingValue = getSpacingValue(value);
141
- if (spacingValue !== undefined) {
142
- return spacingValue;
143
- }
144
-
145
- // Fallback: if token not found, return the value as-is (will cause a warning)
146
- if (process.env.NODE_ENV !== 'production') {
147
- // eslint-disable-next-line no-console
148
- console.warn(`Spacing token "${value}" not found in theme. Returning as-is.`);
149
- }
150
- return value;
151
- }
152
-
153
- /**
154
- * Recursively processes responsive values (arrays or objects) to validate and convert tokens
155
- *
156
- * @param {*} value - The value to process (could be string, array, or object)
157
- * @param {Function} converter - Function to convert valid tokens to actual values
158
- * @param {Function} validator - Function to validate if a token is allowed
159
- * @param {string} propName - The name of the prop being processed (for warning messages)
160
- * @returns {*} The processed value with tokens converted, or undefined for invalid tokens
161
- */
162
- export function normalizeResponsiveObject(value) {
163
- const normalized = {};
164
- Object.entries(value).forEach(([key, val]) => {
165
- if (key === 'base') {
166
- normalized.base = val;
167
- return;
168
- }
169
- const chakraKey = BpkBreakpointToChakraKey[key];
170
- if (chakraKey) {
171
- normalized[chakraKey] = val;
172
- } else if (process.env.NODE_ENV !== 'production') {
173
- // eslint-disable-next-line no-console
174
- console.warn(`Unknown breakpoint "${key}" used in responsive prop. ` + 'Use Backpack breakpoint tokens such as mobile, tablet or desktop.');
175
- }
176
- });
177
- return normalized;
178
- }
179
- export function processResponsiveValue(value, converter, validator, propName) {
180
- if (value === undefined || value === null) {
181
- return value;
182
- }
183
- if (Array.isArray(value)) {
184
- if (process.env.NODE_ENV !== 'production') {
185
- // eslint-disable-next-line no-console
186
- console.warn(`Array-based responsive values are not supported for prop "${propName}". ` + `Please use Backpack breakpoint keys instead.`);
187
- }
188
- return undefined;
189
- }
190
- if (typeof value === 'object') {
191
- const normalized = normalizeResponsiveObject(value);
192
- const result = {};
193
- Object.keys(normalized).forEach(key => {
194
- const processedValue = processResponsiveValue(normalized[key], converter, validator, propName);
195
- if (processedValue !== undefined) {
196
- result[key] = processedValue;
197
- }
198
- });
199
- return Object.keys(result).length > 0 ? result : undefined;
200
- }
201
- const strValue = String(value);
202
- if (!validator(strValue)) {
203
- if (process.env.NODE_ENV !== 'production') {
204
- // eslint-disable-next-line no-console
205
- console.warn(`Invalid value "${strValue}" for prop "${propName}". ` + `Only Backpack tokens are allowed.`);
206
- }
207
- return undefined; // Invalid values are removed
208
- }
209
- return converter(strValue);
210
- }
211
-
212
- /**
213
- * Validates and converts spacing props for Chakra UI
214
- * Handles all spacing-related properties including padding, margin, gap, size, border radius and position
215
- *
216
- * @param {T} props - Component props object
217
- * @returns {Record<string, any>} Processed props with spacing tokens converted to actual values
218
- */
219
- export function processSpacingProps(props) {
220
- const spacingKeys = [
221
- // Padding props
222
- 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingStart', 'paddingEnd', 'paddingInline',
223
- // Margin props
224
- 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginStart', 'marginEnd', 'marginInline',
225
- // Gap and spacing
226
- 'gap', 'spacing', 'rowGap', 'columnGap',
227
- // Size props
228
- 'width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight',
229
- // Position props
230
- 'top', 'right', 'bottom', 'left'];
231
- const processed = {
232
- ...props
233
- };
234
- spacingKeys.forEach(key => {
235
- if (key in processed && processed[key] !== undefined) {
236
- const sizeKeys = ['width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight'];
237
- const positionKeys = ['top', 'right', 'bottom', 'left'];
238
- const isSizeProp = sizeKeys.includes(key);
239
- const isPositionProp = positionKeys.includes(key);
240
- let converter;
241
- if (isSizeProp || isPositionProp) {
242
- converter = v => v;
243
- } else {
244
- converter = convertBpkSpacingToChakra;
245
- }
246
- let validator;
247
- if (isSizeProp) {
248
- validator = isValidSizeValue;
249
- } else if (isPositionProp) {
250
- validator = isValidPositionValue;
251
- } else {
252
- validator = isValidSpacingValue;
253
- }
254
- const processedValue = processResponsiveValue(processed[key], converter, validator, key);
255
- if (processedValue !== undefined) {
256
- processed[key] = processedValue;
257
- } else {
258
- delete processed[key];
259
- }
260
- }
261
- });
262
- return processed;
263
- }
264
-
265
- /**
266
- * Processes all props to convert Backpack tokens to Chakra UI format
267
- * Also explicitly removes className and style to prevent ad-hoc overrides
268
- *
269
- * Processing order:
270
- * 1. Remove className & style
271
- * 2. Process spacing props (includes position)
272
- *
273
- * @param {T} props - Component props object
274
- * @returns {Record<string, any>} Processed props with tokens converted and disallowed props removed
275
- */
276
- export function processBpkProps(props) {
277
- // Explicitly remove className and style to prevent style overrides
278
- const {
279
- className,
280
- style,
281
- ...cleanProps
282
- } = props;
283
- if (className !== undefined && process.env.NODE_ENV !== 'production') {
284
- // eslint-disable-next-line no-console
285
- console.warn('className prop is not allowed on Backpack layout components. ' + 'It has been removed to maintain design system consistency.');
286
- }
287
- if (style !== undefined && process.env.NODE_ENV !== 'production') {
288
- // eslint-disable-next-line no-console
289
- console.warn('style prop is not allowed on Backpack layout components. ' + 'It has been removed to maintain design system consistency.');
290
- }
291
-
292
- // Process spacing props (includes position)
293
- return processSpacingProps(cleanProps);
294
- }
295
-
296
- /**
297
- * Processes responsive props that are simple string/enum values (non-spacing)
298
- * using Backpack breakpoint keys. Array syntax is rejected as in spacing.
299
- *
300
- * @param {*} value - The value to process
301
- * @param {string} propName - The name of the prop being processed
302
- * @returns {*} The processed value with breakpoint keys mapped to Chakra keys
303
- */
304
- export function processResponsiveStringProp(value, propName) {
305
- return processResponsiveValue(value, v => v, () => true, propName);
306
- }
307
-
308
- /**
309
- * Processes a collection of responsive props.
310
- * @param {Record<string, any>} props - Object containing prop values.
311
- * @param {Record<string, string>} propNameMap - Map of prop name to CSS/Chakra property name (for error messages and mapping).
312
- * @returns {Record<string, any>} Processed props object.
313
- */
314
- export function processResponsiveProps(props, propNameMap) {
315
- const processed = {};
316
- Object.keys(props).forEach(key => {
317
- if (props[key] !== undefined) {
318
- const targetPropName = propNameMap ? propNameMap[key] || key : key;
319
- processed[targetPropName] = processResponsiveStringProp(props[key], targetPropName);
320
- }
321
- });
322
- return processed;
323
- }