@skyscanner/backpack-web 41.8.0 → 41.9.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.
Files changed (27) hide show
  1. package/bpk-component-badge/src/BpkBadge.js +2 -1
  2. package/bpk-component-blockquote/src/BpkBlockquote.js +2 -1
  3. package/bpk-component-boilerplate/src/BpkBoilerplate.js +2 -1
  4. package/bpk-component-card-list/src/BpkCardListRowRail/BpkCardListCarousel.js +11 -7
  5. package/bpk-component-card-list/src/BpkCardListRowRail/BpkCardListCarousel.module.css +1 -1
  6. package/bpk-component-close-button/src/BpkCloseButton.js +2 -1
  7. package/bpk-component-code/src/BpkCode.js +2 -1
  8. package/bpk-component-code/src/BpkCodeBlock.js +2 -1
  9. package/bpk-component-journey-arrow/src/BpkJourneyArrow.js +2 -1
  10. package/bpk-component-label/src/BpkLabel.js +2 -1
  11. package/bpk-component-page-indicator/src/BpkPageIndicator.js +2 -1
  12. package/bpk-component-price-range/index.d.ts +2 -3
  13. package/bpk-component-price-range/index.js +2 -2
  14. package/bpk-component-price-range/src/BpkPriceRange.d.ts +14 -6
  15. package/bpk-component-price-range/src/BpkPriceRange.js +34 -14
  16. package/bpk-component-price-range/src/common-types.d.ts +5 -0
  17. package/bpk-component-price-range/src/common-types.js +4 -0
  18. package/bpk-component-snippet/src/BpkSnippet.js +2 -1
  19. package/bpk-component-text/src/BpkText.js +2 -1
  20. package/bpk-component-visually-hidden/src/BpkVisuallyHidden.js +2 -1
  21. package/bpk-react-utils/index.d.ts +5 -1
  22. package/bpk-react-utils/index.js +4 -2
  23. package/bpk-react-utils/src/BpkDialogWrapper/BpkDialogWrapper.js +2 -0
  24. package/bpk-react-utils/src/getDataComponentAttribute.d.ts +20 -0
  25. package/bpk-react-utils/src/getDataComponentAttribute.js +38 -0
  26. package/bpk-scrim-utils/src/BpkScrim.js +2 -1
  27. package/package.json +1 -1
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkBadge.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  export const BADGE_TYPES = {
@@ -50,6 +50,7 @@ const BpkBadge = ({
50
50
  const classNames = getClassName('bpk-badge', badgeTypeClassNames[type], docked === 'right' && 'bpk-badge--docked-right', docked === 'left' && 'bpk-badge--docked-left', centered && 'bpk-badge--centered', className);
51
51
  return /*#__PURE__*/_jsx("span", {
52
52
  className: classNames,
53
+ ...getDataComponentAttribute('Badge'),
53
54
  ...rest
54
55
  });
55
56
  };
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkBlockquote.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -30,6 +30,7 @@ const BpkBlockquote = ({
30
30
  }
31
31
  return /*#__PURE__*/_jsx("blockquote", {
32
32
  className: classNames.join(' '),
33
+ ...getDataComponentAttribute('Blockquote'),
33
34
  children: children
34
35
  });
35
36
  };
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkBoilerplate.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -27,6 +27,7 @@ const BpkBoilerplate = ({
27
27
  delete rest.className;
28
28
  return /*#__PURE__*/_jsx("div", {
29
29
  className: getClassName('bpk-boilerplate'),
30
+ ...getDataComponentAttribute('Boilerplate'),
30
31
  ...rest,
31
32
  children: "I am an example component."
32
33
  });
@@ -150,12 +150,9 @@ const BpkCardListCarousel = props => {
150
150
  }
151
151
  const commonProps = {
152
152
  className: getClassName(`bpk-card-list-row-rail__${layout}__card`),
153
- style: {
154
- ...shownNumberStyle,
155
- ...cardDimensionStyle
156
- },
153
+ style: shownNumberStyle,
157
154
  key: `carousel-card-${index.toString()}`,
158
- role: "group"
155
+ role: 'group'
159
156
  };
160
157
 
161
158
  // Only render cards that are within the renderList range or have been visible before
@@ -165,18 +162,25 @@ const BpkCardListCarousel = props => {
165
162
  ...commonProps,
166
163
  style: {
167
164
  ...commonProps.style,
165
+ ...cardDimensionStyle,
168
166
  contain: 'paint'
169
167
  },
170
168
  "data-testid": "bpk-card-list-carousel--placeholder",
171
169
  "aria-hidden": "true",
172
- children: card
170
+ children: /*#__PURE__*/_jsx("div", {
171
+ className: getClassName('bpk-card-list-row-rail__card-slot'),
172
+ children: card
173
+ })
173
174
  });
174
175
  }
175
176
  return /*#__PURE__*/_jsx("div", {
176
177
  ...commonProps,
177
178
  ref: cardRefFns[index],
178
179
  "aria-label": slideLabel(index, childrenLength),
179
- children: card
180
+ children: /*#__PURE__*/_jsx("div", {
181
+ className: getClassName('bpk-card-list-row-rail__card-slot'),
182
+ children: card
183
+ })
180
184
  });
181
185
  })
182
186
  });
@@ -15,4 +15,4 @@
15
15
  * See the License for the specific language governing permissions and
16
16
  * limitations under the License.
17
17
  */
18
- .bpk-card-list-row-rail__row,.bpk-card-list-row-rail__rail{--spacing-offset: 0.5rem;--carousel-card-gap: 1.25rem;display:flex;overflow-x:hidden;box-sizing:border-box;gap:var(--carousel-card-gap);margin-block:-1.5rem;margin-inline:-0.5rem;padding-block:1.5rem;padding-inline:.5rem;scroll-snap-stop:always;scroll-snap-type:x mandatory;scrollbar-width:none}@media(max-width: 32rem){.bpk-card-list-row-rail__row,.bpk-card-list-row-rail__rail{--spacing-offset: 1rem;--carousel-card-gap: 1rem;overflow-x:scroll}}.bpk-card-list-row-rail__row::-webkit-scrollbar,.bpk-card-list-row-rail__rail::-webkit-scrollbar{display:none}.bpk-card-list-row-rail__row__card,.bpk-card-list-row-rail__rail__card{position:relative;flex:0 0 calc((100% - (var(--carousel-card-gap)*(var(--initially-shown-cards, 3) - 1) + var(--spacing-offset)*2/var(--initially-shown-cards, 3)))/var(--initially-shown-cards, 3));overflow:visible;box-sizing:border-box;scroll-margin-inline:var(--spacing-offset);scroll-snap-align:start}@media(max-width: 32rem){.bpk-card-list-row-rail__row__card,.bpk-card-list-row-rail__rail__card{flex:0 0 calc((100% - var(--carousel-card-gap)*(var(--initially-shown-cards, 3) - 1))/max(1,var(--initially-shown-cards, 3) - .8))}}.bpk-card-list-row-rail__rail{-webkit-overflow-scrolling:touch}@media(max-width: 32rem){.bpk-card-list-row-rail__rail{margin-inline:calc(-1*var(--spacing-offset));padding-inline:var(--spacing-offset)}}
18
+ .bpk-card-list-row-rail__row,.bpk-card-list-row-rail__rail{--spacing-offset: 0.5rem;--carousel-card-gap: 1.25rem;display:flex;overflow-x:hidden;box-sizing:border-box;gap:var(--carousel-card-gap);margin-block:-1.5rem;margin-inline:-0.5rem;padding-block:1.5rem;padding-inline:.5rem;scroll-snap-stop:always;scroll-snap-type:x mandatory;scrollbar-width:none}@media(max-width: 32rem){.bpk-card-list-row-rail__row,.bpk-card-list-row-rail__rail{--spacing-offset: 1rem;--carousel-card-gap: 1rem;overflow-x:scroll}}.bpk-card-list-row-rail__row::-webkit-scrollbar,.bpk-card-list-row-rail__rail::-webkit-scrollbar{display:none}.bpk-card-list-row-rail__row__card,.bpk-card-list-row-rail__rail__card{position:relative;flex:0 0 calc((100% - (var(--carousel-card-gap)*(var(--initially-shown-cards, 3) - 1) + var(--spacing-offset)*2/var(--initially-shown-cards, 3)))/var(--initially-shown-cards, 3));overflow:visible;box-sizing:border-box;scroll-margin-inline:var(--spacing-offset);scroll-snap-align:start}@media(max-width: 32rem){.bpk-card-list-row-rail__row__card,.bpk-card-list-row-rail__rail__card{flex:0 0 calc((100% - var(--carousel-card-gap)*(var(--initially-shown-cards, 3) - 1))/max(1,var(--initially-shown-cards, 3) - .8))}}.bpk-card-list-row-rail__rail{-webkit-overflow-scrolling:touch}@media(max-width: 32rem){.bpk-card-list-row-rail__rail{margin-inline:calc(-1*var(--spacing-offset));padding-inline:var(--spacing-offset)}}.bpk-card-list-row-rail__card-slot{display:grid;height:100%}
@@ -17,7 +17,7 @@
17
17
  */
18
18
 
19
19
  import CloseIcon from "../../bpk-component-icon/sm/close";
20
- import { cssModules } from "../../bpk-react-utils";
20
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
21
21
  import STYLES from "./BpkCloseButton.module.css";
22
22
  import { jsx as _jsx } from "react/jsx-runtime";
23
23
  const getClassName = cssModules(STYLES);
@@ -40,6 +40,7 @@ const BpkCloseButton = ({
40
40
  onClick: onClick,
41
41
  "aria-label": label,
42
42
  className: classNames.join(' '),
43
+ ...getDataComponentAttribute('CloseButton'),
43
44
  ...rest,
44
45
  children: /*#__PURE__*/_jsx("span", {
45
46
  className: getClassName('bpk-close-button-icon'),
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkCode.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -29,6 +29,7 @@ const BpkCode = ({
29
29
  const classNames = getClassName('bpk-code', alternate && 'bpk-code--alternate', className);
30
30
  return /*#__PURE__*/_jsx("code", {
31
31
  className: classNames,
32
+ ...getDataComponentAttribute('Code'),
32
33
  ...rest,
33
34
  children: children
34
35
  });
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkCodeBlock.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -30,6 +30,7 @@ const BpkCodeBlock = ({
30
30
  const codeClassNames = getClassName('bpk-code', 'bpk-code--block');
31
31
  return /*#__PURE__*/_jsx("pre", {
32
32
  className: preClassNames,
33
+ ...getDataComponentAttribute('CodeBlock'),
33
34
  ...rest,
34
35
  children: /*#__PURE__*/_jsx("code", {
35
36
  className: codeClassNames,
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkJourneyArrow.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -28,6 +28,7 @@ const BpkJourneyArrow = ({
28
28
  const dotCount = Math.min(3, Math.max(0, stops));
29
29
  return /*#__PURE__*/_jsx("div", {
30
30
  className: getClassName("bpk-journey-arrow"),
31
+ ...getDataComponentAttribute('JourneyArrow'),
31
32
  ...rest,
32
33
  children: Array.from({
33
34
  length: dotCount
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkLabel.module.css";
21
21
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -33,6 +33,7 @@ const BpkLabel = ({
33
33
  const classNames = getClassName('bpk-label', white && 'bpk-label--white', invalid && 'bpk-label--invalid', disabled && 'bpk-label--disabled', white && disabled && 'bpk-label--disabled--white', className);
34
34
  return /*#__PURE__*/_jsxs("label", {
35
35
  className: classNames,
36
+ ...getDataComponentAttribute('Label'),
36
37
  ...rest,
37
38
  children: [children, !disabled && required && /*#__PURE__*/_jsx("span", {
38
39
  className: getClassName('bpk-label__asterisk'),
@@ -17,7 +17,7 @@
17
17
  */
18
18
 
19
19
  import { BUTTON_TYPES } from "../../bpk-component-button";
20
- import { cssModules } from "../../bpk-react-utils";
20
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
21
21
  import NavButton, { DIRECTIONS } from "./NavButton";
22
22
  import STYLES from "./BpkPageIndicator.module.css";
23
23
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -55,6 +55,7 @@ const BpkPageIndicator = ({
55
55
  "data-testid": "indicator-container",
56
56
  children: /*#__PURE__*/_jsxs("div", {
57
57
  className: getClassName('bpk-page-indicator', showNav && 'bpk-page-indicator__showNav'),
58
+ ...getDataComponentAttribute('PageIndicator'),
58
59
  children: [showNav && /*#__PURE__*/_jsx(NavButton, {
59
60
  currentIndex: currentIndex,
60
61
  onClick: onClick,
@@ -1,3 +1,2 @@
1
- import BpkPriceRange, { type Props as BpkPriceRangeProps } from './src/BpkPriceRange';
2
- export type { BpkPriceRangeProps };
3
- export default BpkPriceRange;
1
+ export { default, type BpkPriceRangeProps } from './src/BpkPriceRange';
2
+ export { MARKER_DISPLAY_TYPES, type MarkerDisplayType, } from './src/common-types';
@@ -16,5 +16,5 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import BpkPriceRange from "./src/BpkPriceRange";
20
- export default BpkPriceRange;
19
+ export { default } from "./src/BpkPriceRange";
20
+ export { MARKER_DISPLAY_TYPES } from "./src/common-types";
@@ -1,16 +1,24 @@
1
- type Marker = {
1
+ import type { MarkerDisplayType } from './common-types';
2
+ type PriceRangePosition = {
2
3
  price: string;
3
4
  percentage: number;
4
5
  };
5
- export type Props = {
6
+ type MarkerPriceRangePosition = PriceRangePosition & {
7
+ type?: MarkerDisplayType;
8
+ };
9
+ export type BpkPriceRangeProps = {
6
10
  min?: number;
7
11
  max?: number;
12
+ /**
13
+ * @deprecated Use `marker.type` with `MARKER_DISPLAY_TYPES.DOT` instead to hide boundary prices.
14
+ * This prop will be removed in a future major release.
15
+ */
8
16
  showPriceIndicator?: boolean;
9
- marker: Marker;
17
+ marker?: MarkerPriceRangePosition;
10
18
  segments: {
11
- low: Marker;
12
- high: Marker;
19
+ low: PriceRangePosition;
20
+ high: PriceRangePosition;
13
21
  };
14
22
  };
15
- declare const BpkPriceRange: ({ marker, max, min, segments, showPriceIndicator, }: Props) => import("react/jsx-runtime").JSX.Element;
23
+ declare const BpkPriceRange: ({ marker, max, min, segments, showPriceIndicator, }: BpkPriceRangeProps) => import("react/jsx-runtime").JSX.Element;
16
24
  export default BpkPriceRange;
@@ -21,27 +21,39 @@ import clamp from 'lodash/clamp';
21
21
  import BpkText, { TEXT_STYLES } from "../../bpk-component-text/src/BpkText";
22
22
  import { cssModules } from "../../bpk-react-utils";
23
23
  import BpkPriceMarker from "./BpkPriceMarker";
24
- import { MARKER_TYPES } from "./common-types";
24
+ import { MARKER_DISPLAY_TYPES, MARKER_TYPES } from "./common-types";
25
25
  import STYLES from "./BpkPriceRange.module.css";
26
26
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
27
27
  const getClassName = cssModules(STYLES);
28
+ const getShouldShowPriceOnBoundaries = (markerType, showPriceIndicator) => {
29
+ switch (markerType) {
30
+ case MARKER_DISPLAY_TYPES.DOT:
31
+ return false;
32
+ case MARKER_DISPLAY_TYPES.BUBBLE:
33
+ return true;
34
+ case undefined:
35
+ default:
36
+ // TODO: LUNA-3184 return `true` when deprecating `showPriceIndicator`
37
+ return showPriceIndicator ?? true;
38
+ }
39
+ };
28
40
  const BpkPriceRange = ({
29
41
  marker,
30
42
  max = 100,
31
43
  min = 0,
32
44
  segments,
33
- showPriceIndicator = true
45
+ showPriceIndicator
34
46
  }) => {
47
+ const shouldShowPriceOnBoundaries = getShouldShowPriceOnBoundaries(marker?.type, showPriceIndicator);
35
48
  const linesRef = useRef(null);
36
49
  const indicatorRef = useRef(null);
37
50
  const [linesWidth, setLinesWidth] = useState(0);
38
51
  const [prefilledWidth, setPrefilledWidth] = useState(0);
39
52
  const calcPercentage = current => (clamp(current, min, max) - min) / (max - min);
40
- const indicatorPercent = calcPercentage(marker.percentage);
41
53
  let type;
42
- if (marker.percentage < segments.low.percentage) {
54
+ if (marker && marker.percentage < segments.low.percentage) {
43
55
  type = MARKER_TYPES.LOW;
44
- } else if (marker.percentage > segments.high.percentage) {
56
+ } else if (marker && marker.percentage > segments.high.percentage) {
45
57
  type = MARKER_TYPES.HIGH;
46
58
  } else {
47
59
  type = MARKER_TYPES.MEDIUM;
@@ -62,17 +74,25 @@ const BpkPriceRange = ({
62
74
  }, []);
63
75
  useEffect(() => {
64
76
  // to calculate the spacing ahead of the price indicator
65
- if (indicatorRef.current && linesWidth) {
77
+ if (marker && indicatorRef.current && linesWidth) {
78
+ const indicatorPercent = calcPercentage(marker.percentage);
66
79
  const estimatedWidth = indicatorPercent * linesWidth - indicatorRef.current.scrollWidth / 2;
67
80
  const maxPrefilledWidth = linesWidth - indicatorRef.current.scrollWidth;
68
81
  const actualPrefilledWidth = clamp(estimatedWidth, 0, maxPrefilledWidth);
69
82
  setPrefilledWidth(actualPrefilledWidth);
70
83
  }
71
- }, [indicatorPercent, linesWidth]);
72
- const linesClassName = getClassName('bpk-price-range__lines', showPriceIndicator && 'bpk-price-range__lines--large');
73
- const lowClassName = getClassName('bpk-price-range__line--low', showPriceIndicator && 'bpk-price-range__line--lowLarge');
74
- const highClassName = getClassName('bpk-price-range__line--high', showPriceIndicator && 'bpk-price-range__line--highLarge');
84
+ }, [marker?.percentage, linesWidth]);
85
+ const linesClassName = getClassName('bpk-price-range__lines', shouldShowPriceOnBoundaries && 'bpk-price-range__lines--large');
86
+ const lowClassName = getClassName('bpk-price-range__line--low', shouldShowPriceOnBoundaries && 'bpk-price-range__line--lowLarge');
87
+ const highClassName = getClassName('bpk-price-range__line--high', shouldShowPriceOnBoundaries && 'bpk-price-range__line--highLarge');
75
88
  const mediumClassName = getClassName('bpk-price-range__line--medium');
89
+
90
+ // TODO: LUNA-3184 set default to BUBBLE when deprecating `showPriceIndicator`
91
+ const defaultMarkerType = showPriceIndicator ?? true ? MARKER_DISPLAY_TYPES.BUBBLE : MARKER_DISPLAY_TYPES.DOT;
92
+ const markerType = marker?.type || defaultMarkerType;
93
+ const shouldShowMarker = !!marker;
94
+ const shouldShowBubble = shouldShowMarker && markerType === MARKER_DISPLAY_TYPES.BUBBLE;
95
+ const shouldShowDot = shouldShowMarker && markerType === MARKER_DISPLAY_TYPES.DOT;
76
96
  const dotClassName = getClassName(`bpk-price-range__line--${type}`, 'bpk-price-range__line--dot');
77
97
  return /*#__PURE__*/_jsxs("div", {
78
98
  style: {
@@ -80,9 +100,9 @@ const BpkPriceRange = ({
80
100
  '--high': calcPercentage(segments.high.percentage),
81
101
  '--prefilled-width': `${prefilledWidth}px`
82
102
  },
83
- className: getClassName('bpk-price-range', showPriceIndicator && 'bpk-price-range--large'),
103
+ className: getClassName('bpk-price-range', shouldShowPriceOnBoundaries && 'bpk-price-range--large'),
84
104
  ref: linesRef,
85
- children: [showPriceIndicator && /*#__PURE__*/_jsx("div", {
105
+ children: [shouldShowBubble && /*#__PURE__*/_jsx("div", {
86
106
  className: getClassName('bpk-price-range__marker'),
87
107
  children: /*#__PURE__*/_jsx(BpkPriceMarker, {
88
108
  ref: indicatorRef,
@@ -97,11 +117,11 @@ const BpkPriceRange = ({
97
117
  className: mediumClassName
98
118
  }), /*#__PURE__*/_jsx("div", {
99
119
  className: highClassName
100
- }), !showPriceIndicator && /*#__PURE__*/_jsx("div", {
120
+ }), shouldShowDot && /*#__PURE__*/_jsx("div", {
101
121
  className: dotClassName,
102
122
  ref: indicatorRef
103
123
  })]
104
- }), showPriceIndicator && /*#__PURE__*/_jsxs("div", {
124
+ }), shouldShowPriceOnBoundaries && /*#__PURE__*/_jsxs("div", {
105
125
  className: getClassName('bpk-price-range__ranges'),
106
126
  children: [/*#__PURE__*/_jsx(BpkText, {
107
127
  textStyle: TEXT_STYLES.footnote,
@@ -4,3 +4,8 @@ export declare const MARKER_TYPES: {
4
4
  readonly HIGH: "high";
5
5
  };
6
6
  export type MarkerType = (typeof MARKER_TYPES)[keyof typeof MARKER_TYPES];
7
+ export declare const MARKER_DISPLAY_TYPES: {
8
+ readonly BUBBLE: "bubble";
9
+ readonly DOT: "dot";
10
+ };
11
+ export type MarkerDisplayType = (typeof MARKER_DISPLAY_TYPES)[keyof typeof MARKER_DISPLAY_TYPES];
@@ -20,4 +20,8 @@ export const MARKER_TYPES = {
20
20
  LOW: 'low',
21
21
  MEDIUM: 'medium',
22
22
  HIGH: 'high'
23
+ };
24
+ export const MARKER_DISPLAY_TYPES = {
25
+ BUBBLE: 'bubble',
26
+ DOT: 'dot'
23
27
  };
@@ -20,7 +20,7 @@ import BpkBreakpoint, { BREAKPOINTS } from "../../bpk-component-breakpoint";
20
20
  import BpkButton, { BUTTON_TYPES } from "../../bpk-component-button";
21
21
  import BpkImage, { BORDER_RADIUS_STYLES, withLazyLoading } from "../../bpk-component-image";
22
22
  import BpkText, { TEXT_STYLES } from "../../bpk-component-text/src/BpkText";
23
- import { cssModules } from "../../bpk-react-utils";
23
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
24
24
  import STYLES from "./BpkSnippet.module.css";
25
25
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
26
26
  const getClassName = cssModules(STYLES);
@@ -92,6 +92,7 @@ const BpkSnippet = ({
92
92
  query: BREAKPOINTS.MOBILE,
93
93
  children: isMobile => /*#__PURE__*/_jsxs("div", {
94
94
  className: getClassName('bpk-snippet', desktopLayout === 'imageRight' && 'bpk-snippet--row-reverse', desktopLayout === 'vertical' && 'bpk-snippet--vertical'),
95
+ ...getDataComponentAttribute('Snippet'),
95
96
  children: [/*#__PURE__*/_jsx("div", {
96
97
  className: getClassName('bpk-snippet--image', desktopLayout === 'vertical' ? 'bpk-snippet--vertical--container' : 'bpk-snippet--container'),
97
98
  children: /*#__PURE__*/_jsx(LazyLoadedImage, {
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkText.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -81,6 +81,7 @@ const BpkText = ({
81
81
  // eslint-disable-next-line @skyscanner/rules/forbid-component-props
82
82
  _jsx(TagName, {
83
83
  className: classNames,
84
+ ...getDataComponentAttribute('Text'),
84
85
  ...rest,
85
86
  children: children
86
87
  })
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { cssModules } from "../../bpk-react-utils";
19
+ import { cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./BpkVisuallyHidden.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -31,6 +31,7 @@ const BpkVisuallyHidden = ({
31
31
  // eslint-disable-next-line @skyscanner/rules/forbid-component-props
32
32
  _jsx(Element, {
33
33
  className: classNames,
34
+ ...getDataComponentAttribute('VisuallyHidden'),
34
35
  children: children
35
36
  })
36
37
  );
@@ -4,11 +4,12 @@ import TransitionInitialMount from './src/TransitionInitialMount';
4
4
  import cssModules from './src/cssModules';
5
5
  import deprecated from './src/deprecated';
6
6
  import { isDeviceIphone, isDeviceIpad, isDeviceIos } from './src/deviceDetection';
7
+ import { getDataComponentAttribute } from './src/getDataComponentAttribute';
7
8
  import isRTL from './src/isRTL';
8
9
  import { setNativeValue } from './src/nativeEventHandler';
9
10
  import withDefaultProps from './src/withDefaultProps';
10
11
  import wrapDisplayName from './src/wrapDisplayName';
11
- export { Portal, TransitionInitialMount, cssModules, deprecated, withDefaultProps, wrapDisplayName, isDeviceIphone, isDeviceIpad, isDeviceIos, isRTL, BpkDialogWrapper, setNativeValue, };
12
+ export { Portal, TransitionInitialMount, cssModules, deprecated, withDefaultProps, wrapDisplayName, isDeviceIphone, isDeviceIpad, isDeviceIos, isRTL, BpkDialogWrapper, setNativeValue, getDataComponentAttribute, };
12
13
  declare const _default: {
13
14
  Portal: typeof Portal;
14
15
  TransitionInitialMount: ({ appearActiveClassName, appearClassName, children, transitionTimeout, }: {
@@ -39,5 +40,8 @@ declare const _default: {
39
40
  isRTL: () => boolean;
40
41
  BpkDialogWrapper: ({ children, closeOnEscPressed, closeOnScrimClick, dialogClassName, exiting, id, isOpen, onClose, timeout, transitionClassNames, ...ariaProps }: import("./src/BpkDialogWrapper/BpkDialogWrapper").Props) => import("react/jsx-runtime").JSX.Element | null;
41
42
  setNativeValue: typeof setNativeValue;
43
+ getDataComponentAttribute: (componentName: string) => {
44
+ "data-backpack-ds-component": string;
45
+ };
42
46
  };
43
47
  export default _default;
@@ -23,11 +23,12 @@ import cssModules from "./src/cssModules";
23
23
  // @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
24
24
  import deprecated from "./src/deprecated";
25
25
  import { isDeviceIphone, isDeviceIpad, isDeviceIos } from "./src/deviceDetection";
26
+ import { getDataComponentAttribute } from "./src/getDataComponentAttribute";
26
27
  import isRTL from "./src/isRTL";
27
28
  import { setNativeValue } from "./src/nativeEventHandler";
28
29
  import withDefaultProps from "./src/withDefaultProps";
29
30
  import wrapDisplayName from "./src/wrapDisplayName";
30
- export { Portal, TransitionInitialMount, cssModules, deprecated, withDefaultProps, wrapDisplayName, isDeviceIphone, isDeviceIpad, isDeviceIos, isRTL, BpkDialogWrapper, setNativeValue };
31
+ export { Portal, TransitionInitialMount, cssModules, deprecated, withDefaultProps, wrapDisplayName, isDeviceIphone, isDeviceIpad, isDeviceIos, isRTL, BpkDialogWrapper, setNativeValue, getDataComponentAttribute };
31
32
  export default {
32
33
  Portal,
33
34
  TransitionInitialMount,
@@ -40,5 +41,6 @@ export default {
40
41
  isDeviceIos,
41
42
  isRTL,
42
43
  BpkDialogWrapper,
43
- setNativeValue
44
+ setNativeValue,
45
+ getDataComponentAttribute
44
46
  };
@@ -19,6 +19,7 @@
19
19
  import { useEffect, useRef, useState } from 'react';
20
20
  import CSSTransition from 'react-transition-group/CSSTransition';
21
21
  import cssModules from "../cssModules";
22
+ import { getDataComponentAttribute } from "../getDataComponentAttribute";
22
23
  import STYLES from "./BpkDialogWrapper.module.css";
23
24
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
25
  const getClassName = cssModules(STYLES);
@@ -121,6 +122,7 @@ export const BpkDialogWrapper = ({
121
122
  };
122
123
  return isOpen ? /*#__PURE__*/_jsxs("div", {
123
124
  className: getClassName('bpk-dialog-wrapper', !dialogSupported && 'bpk-dialog-wrapper--polyfill'),
125
+ ...getDataComponentAttribute('DialogWrapper'),
124
126
  children: [!dialogSupported && /*#__PURE__*/_jsx("div", {
125
127
  id: `${id}-polyfill`,
126
128
  className: getClassName('bpk-dialog-wrapper--backdrop'),
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Returns an object containing the data-backpack-ds-component attribute.
3
+ * Use this to ensure consistent naming and placement across all components.
4
+ *
5
+ * @param {string} componentName - The component name without the "Bpk" prefix (e.g., "Button", "Card")
6
+ * @returns {{Object}} An object with the data-backpack-ds-component attribute
7
+ *
8
+ * @example
9
+ * // In a component:
10
+ * <button {...getDataComponentAttribute('Button')} {...rest}>
11
+ * Click me
12
+ * </button>
13
+ *
14
+ * // Renders:
15
+ * // <button data-backpack-ds-component="Button" ...>Click me</button>
16
+ */
17
+ export declare const getDataComponentAttribute: (componentName: string) => {
18
+ "data-backpack-ds-component": string;
19
+ };
20
+ export default getDataComponentAttribute;
@@ -0,0 +1,38 @@
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
+ * Returns an object containing the data-backpack-ds-component attribute.
21
+ * Use this to ensure consistent naming and placement across all components.
22
+ *
23
+ * @param {string} componentName - The component name without the "Bpk" prefix (e.g., "Button", "Card")
24
+ * @returns {{Object}} An object with the data-backpack-ds-component attribute
25
+ *
26
+ * @example
27
+ * // In a component:
28
+ * <button {...getDataComponentAttribute('Button')} {...rest}>
29
+ * Click me
30
+ * </button>
31
+ *
32
+ * // Renders:
33
+ * // <button data-backpack-ds-component="Button" ...>Click me</button>
34
+ */
35
+ export const getDataComponentAttribute = componentName => ({
36
+ 'data-backpack-ds-component': componentName
37
+ });
38
+ export default getDataComponentAttribute;
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { TransitionInitialMount, cssModules } from "../../bpk-react-utils";
19
+ import { TransitionInitialMount, cssModules, getDataComponentAttribute } from "../../bpk-react-utils";
20
20
  import STYLES from "./bpk-scrim.module.css";
21
21
  import { jsx as _jsx } from "react/jsx-runtime";
22
22
  const getClassName = cssModules(STYLES);
@@ -29,6 +29,7 @@ const BpkScrim = ({
29
29
  children: /*#__PURE__*/_jsx("div", {
30
30
  role: "presentation",
31
31
  className: getClassName('bpk-scrim'),
32
+ ...getDataComponentAttribute('Scrim'),
32
33
  onMouseDown: onClose,
33
34
  onTouchStart: onClose
34
35
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyscanner/backpack-web",
3
- "version": "41.8.0",
3
+ "version": "41.9.0",
4
4
  "description": "Backpack Design System web library",
5
5
  "repository": {
6
6
  "type": "git",