@telus-uds/components-base 4.0.0-alpha.2 → 4.0.0-beta.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 (120) hide show
  1. package/CHANGELOG.md +47 -1
  2. package/lib/cjs/Autocomplete/Autocomplete.js +13 -1
  3. package/lib/cjs/Autocomplete/constants.js +1 -1
  4. package/lib/cjs/Button/ButtonGroup.js +91 -23
  5. package/lib/cjs/Card/CardBase.js +75 -47
  6. package/lib/cjs/ColourToggle/ColourBubble.js +66 -13
  7. package/lib/cjs/ColourToggle/ColourToggle.js +41 -11
  8. package/lib/cjs/ColourToggle/constants.js +15 -0
  9. package/lib/cjs/ColourToggle/dictionary.js +14 -0
  10. package/lib/cjs/Listbox/ListboxOverlay.js +7 -1
  11. package/lib/cjs/MultiSelectFilter/ModalOverlay.js +7 -1
  12. package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +2 -28
  13. package/lib/cjs/TextInput/TextInputBase.js +2 -1
  14. package/lib/cjs/Validator/Validator.js +5 -1
  15. package/lib/cjs/utils/useOverlaidPosition.js +83 -42
  16. package/lib/esm/Autocomplete/Autocomplete.js +13 -1
  17. package/lib/esm/Autocomplete/constants.js +1 -1
  18. package/lib/esm/Button/ButtonGroup.js +91 -23
  19. package/lib/esm/Card/CardBase.js +75 -47
  20. package/lib/esm/ColourToggle/ColourBubble.js +67 -14
  21. package/lib/esm/ColourToggle/ColourToggle.js +41 -11
  22. package/lib/esm/ColourToggle/constants.js +8 -0
  23. package/lib/esm/ColourToggle/dictionary.js +8 -0
  24. package/lib/esm/Listbox/ListboxOverlay.js +7 -1
  25. package/lib/esm/MultiSelectFilter/ModalOverlay.js +8 -2
  26. package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +2 -28
  27. package/lib/esm/TextInput/TextInputBase.js +2 -1
  28. package/lib/esm/Validator/Validator.js +5 -1
  29. package/lib/esm/utils/useOverlaidPosition.js +83 -42
  30. package/lib/package.json +3 -3
  31. package/package.json +3 -3
  32. package/src/Autocomplete/Autocomplete.jsx +11 -2
  33. package/src/Autocomplete/constants.js +1 -1
  34. package/src/Button/ButtonGroup.jsx +93 -24
  35. package/src/Card/CardBase.jsx +94 -75
  36. package/src/ColourToggle/ColourBubble.jsx +62 -7
  37. package/src/ColourToggle/ColourToggle.jsx +43 -9
  38. package/src/ColourToggle/constants.js +10 -0
  39. package/src/ColourToggle/dictionary.js +4 -0
  40. package/src/Listbox/ListboxOverlay.jsx +6 -2
  41. package/src/MultiSelectFilter/ModalOverlay.jsx +9 -3
  42. package/src/MultiSelectFilter/MultiSelectFilter.jsx +1 -31
  43. package/src/TextInput/TextInputBase.jsx +2 -1
  44. package/src/Validator/Validator.jsx +5 -1
  45. package/src/utils/useOverlaidPosition.js +84 -34
  46. package/types/A11yInfoProvider.d.ts +9 -0
  47. package/types/A11yText.d.ts +13 -0
  48. package/types/ActionCard.d.ts +19 -0
  49. package/types/ActivityIndicator.d.ts +13 -0
  50. package/types/Autocomplete.d.ts +27 -0
  51. package/types/Badge.d.ts +15 -4
  52. package/types/BaseProvider.d.ts +26 -0
  53. package/types/Box.d.ts +13 -3
  54. package/types/Button.d.ts +35 -0
  55. package/types/Card.d.ts +19 -0
  56. package/types/CardGroup.d.ts +23 -0
  57. package/types/Carousel.d.ts +25 -0
  58. package/types/Checkbox.d.ts +15 -2
  59. package/types/CheckboxCard.d.ts +20 -0
  60. package/types/CheckboxCardGroup.d.ts +10 -4
  61. package/types/ChevronLink.d.ts +9 -2
  62. package/types/ColourToggle.d.ts +16 -0
  63. package/types/Common.d.ts +7 -3
  64. package/types/Divider.d.ts +13 -1
  65. package/types/DownloadApp.d.ts +19 -0
  66. package/types/ExpandCollapse.d.ts +16 -9
  67. package/types/ExpandCollapseMini.d.ts +16 -0
  68. package/types/Feedback.d.ts +16 -0
  69. package/types/Fieldset.d.ts +17 -0
  70. package/types/FileUpload.d.ts +6 -0
  71. package/types/FlexGrid.d.ts +57 -0
  72. package/types/Footnote.d.ts +18 -0
  73. package/types/HorizontalScroll.d.ts +15 -0
  74. package/types/HorizontalScrollButton.d.ts +17 -1
  75. package/types/Icon.d.ts +13 -2
  76. package/types/IconButton.d.ts +19 -0
  77. package/types/InputLabel.d.ts +12 -0
  78. package/types/InputSupports.d.ts +19 -0
  79. package/types/Link.d.ts +20 -4
  80. package/types/List.d.ts +11 -4
  81. package/types/Listbox.d.ts +13 -3
  82. package/types/Modal.d.ts +25 -0
  83. package/types/MultiSelectFilter.d.ts +24 -0
  84. package/types/Notification.d.ts +19 -0
  85. package/types/OrderedList.d.ts +17 -0
  86. package/types/Pagination.d.ts +25 -0
  87. package/types/Portal.d.ts +5 -1
  88. package/types/PriceLockup.d.ts +28 -0
  89. package/types/ProductCard.d.ts +20 -0
  90. package/types/ProductCardGroup.d.ts +21 -0
  91. package/types/Progress.d.ts +22 -0
  92. package/types/QuickLinks.d.ts +27 -0
  93. package/types/QuickLinksFeature.d.ts +27 -0
  94. package/types/Radio.d.ts +22 -0
  95. package/types/RadioCard.d.ts +21 -0
  96. package/types/Responsive.d.ts +14 -0
  97. package/types/Scroll.d.ts +2 -2
  98. package/types/Search.d.ts +15 -2
  99. package/types/Select.d.ts +12 -4
  100. package/types/SideNav.d.ts +38 -0
  101. package/types/Skeleton.d.ts +17 -0
  102. package/types/SkipLink.d.ts +14 -0
  103. package/types/Spacer.d.ts +8 -1
  104. package/types/StackView.d.ts +8 -2
  105. package/types/Status.d.ts +2 -3
  106. package/types/StepTracker.d.ts +16 -0
  107. package/types/TabBar.d.ts +25 -0
  108. package/types/Tabs.d.ts +12 -3
  109. package/types/Tags.d.ts +24 -0
  110. package/types/TextButton.d.ts +11 -4
  111. package/types/TextInput.d.ts +38 -0
  112. package/types/ThemeProvider.d.ts +29 -0
  113. package/types/Timeline.d.ts +16 -0
  114. package/types/ToggleSwitch.d.ts +11 -2
  115. package/types/ToolTip.d.ts +7 -3
  116. package/types/TooltipButton.d.ts +20 -0
  117. package/types/Typography.d.ts +8 -2
  118. package/types/Validator.d.ts +16 -0
  119. package/types/ViewportProvider.d.ts +12 -0
  120. package/types/index.d.ts +197 -50
package/CHANGELOG.md CHANGED
@@ -1,9 +1,55 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 17 Apr 2026 23:54:32 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 29 May 2026 17:27:59 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 4.0.0-beta.1
8
+
9
+ Fri, 29 May 2026 17:27:59 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `Card`: Add testID to CardBase and its subcomponents (david.melara1@telus.com)
14
+ - `ColourToggle`: Add crossedOut variant (david.melara1@telus.com)
15
+ - Bump @telus-uds/system-constants to v4.0.0-beta.0
16
+ - Bump @telus-uds/system-theme-tokens to v5.0.0-beta.0
17
+
18
+ ### Patches
19
+
20
+ - `Validator`: Fix guard skipping code reset on empty string value prop (david.melara1@telus.com)
21
+ - `ButtonGroup`: Fixed a bug where it wasn't displaying correctly for the `responsive` width variant on web-mobile, Android, and iOS (kevin.ruiz@telus.com)
22
+ - `Card`: preserve `style` gradient border and custom `backgroundColor` tokens when `backgroundImage` is set (josue.higueroscalderon@telus.com)
23
+
24
+ ## 3.31.0
25
+
26
+ Fri, 22 May 2026 05:09:10 GMT
27
+
28
+ ### Minor changes
29
+
30
+ - `Autocomplete`: Add scroll to overlay in mobile (david.melara1@telus.com)
31
+
32
+ ### Patches
33
+
34
+ - `MultiSelectFilter`: position issues fixed in MFE (josue.higueroscalderon@telus.com)
35
+ - `TextInput`: Fix `onChangeText` returning `undefined` instead of an empty string when `isNumeric` is set and no text is provided (david.melara1@telus.com)
36
+ - `Autocomplete`: inside modal story fixed to show the close button properly (josue.higueroscalderon@telus.com)
37
+
38
+ ## 4.0.0-beta.0
39
+
40
+ Thu, 21 May 2026 03:01:22 GMT
41
+
42
+ ### Minor changes
43
+
44
+ - `Autocomplete`: Add scroll to overlay in mobile (david.melara1@telus.com)
45
+
46
+ ### Patches
47
+
48
+ - `TextInput`: Fix `onChangeText` returning `undefined` instead of an empty string when `isNumeric` is set and no text is provided (david.melara1@telus.com)
49
+ - `Autocomplete`: inside modal story fixed to show the close button properly (josue.higueroscalderon@telus.com)
50
+ - `TypeScript`: fix types (guillermo.peitzner@telus.com)
51
+ - `MultiSelectFilter`: position issues fixed in MFE (josue.higueroscalderon@telus.com)
52
+
7
53
  ## 4.0.0-alpha.2
8
54
 
9
55
  Fri, 17 Apr 2026 23:54:32 GMT
@@ -134,6 +134,7 @@ const Autocomplete = exports.Autocomplete = /*#__PURE__*/_react.default.forwardR
134
134
  value,
135
135
  helpText = '',
136
136
  loadingLabel,
137
+ dropdownPosition = 'bottom',
137
138
  tokens,
138
139
  ...rest
139
140
  } = _ref2;
@@ -189,6 +190,13 @@ const Autocomplete = exports.Autocomplete = /*#__PURE__*/_react.default.forwardR
189
190
  isShown: isExpanded || hintExpansionEnabled,
190
191
  offsets: {
191
192
  vertical: _Platform.default.OS !== 'web' && (hint || inputLabel) ? 28 : 4
193
+ },
194
+ align: dropdownPosition === 'top' ? {
195
+ center: 'center',
196
+ bottom: 'top'
197
+ } : {
198
+ center: 'center',
199
+ top: 'bottom'
192
200
  }
193
201
  });
194
202
  const targetRef = _react.default.useRef(null);
@@ -541,5 +549,9 @@ Autocomplete.propTypes = {
541
549
  /**
542
550
  * Input value for controlled usage
543
551
  */
544
- value: _propTypes.default.string
552
+ value: _propTypes.default.string,
553
+ /**
554
+ * Controls whether the dropdown renders above or below the input. Defaults to 'bottom'.
555
+ */
556
+ dropdownPosition: _propTypes.default.oneOf(['top', 'bottom'])
545
557
  };
@@ -6,6 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.MIN_LISTBOX_WIDTH = exports.INPUT_LEFT_PADDING = exports.DEFAULT_MIN_TO_SUGGESTION = exports.DEFAULT_MAX_SUGGESTIONS = exports.DEFAULT_MAX_DROPDOWN_HEIGHT = void 0;
7
7
  const DEFAULT_MIN_TO_SUGGESTION = exports.DEFAULT_MIN_TO_SUGGESTION = 1;
8
8
  const DEFAULT_MAX_SUGGESTIONS = exports.DEFAULT_MAX_SUGGESTIONS = 5;
9
- const DEFAULT_MAX_DROPDOWN_HEIGHT = exports.DEFAULT_MAX_DROPDOWN_HEIGHT = 336; // Approximately 7 items (48px each)
9
+ const DEFAULT_MAX_DROPDOWN_HEIGHT = exports.DEFAULT_MAX_DROPDOWN_HEIGHT = 500;
10
10
  const INPUT_LEFT_PADDING = exports.INPUT_LEFT_PADDING = 16;
11
11
  const MIN_LISTBOX_WIDTH = exports.MIN_LISTBOX_WIDTH = 288;
@@ -29,6 +29,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
29
29
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
30
30
  const [selectProps, selectedSystemPropTypes] = (0, _selectSystemProps.selectSystemProps)([_a11yProps.a11yProps, _viewProps.viewProps]);
31
31
  const [selectItemProps, selectedItemPropTypes] = (0, _selectSystemProps.selectSystemProps)([_a11yProps.a11yProps, _handlerProps.focusHandlerProps, _pressProps.pressProps, _viewProps.viewProps]);
32
+ const EQUAL_WIDTH = 'equal';
33
+ const RESPONSIVE_WIDTH = 'responsive';
32
34
  const ButtonGroup = exports.ButtonGroup = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
33
35
  let {
34
36
  variant,
@@ -73,31 +75,90 @@ const ButtonGroup = exports.ButtonGroup = /*#__PURE__*/_react.default.forwardRef
73
75
  const isMobileNonContained = _Platform.default.OS !== 'web' && (!variant || variant?.style !== 'contained');
74
76
  const themeButtonTokensCallback = (0, _useThemeTokens.useThemeTokensCallback)('ButtonGroupItem', tokens, variant);
75
77
  const gapValue = (0, _useSpacingScale.useSpacingScale)(gap || space);
78
+ const isWeb = _Platform.default.OS === 'web';
79
+ const buttonWidthVariant = variant?.width;
76
80
  const getButtonTokens = (0, _react.useCallback)(state => {
77
81
  const themeButtonTokens = themeButtonTokensCallback(state);
78
82
  const shouldUseTransparentBackground = isMobileNonContained && !state.selected && !state.pressed && !state.hover && !state.focus;
83
+ let widthStyle;
84
+ switch (buttonWidthVariant) {
85
+ case EQUAL_WIDTH:
86
+ widthStyle = staticStyles.equalWidth;
87
+ break;
88
+ case RESPONSIVE_WIDTH:
89
+ widthStyle = staticStyles.responsiveWidth;
90
+ break;
91
+ // no default
92
+ }
79
93
  return {
80
94
  ...themeButtonTokens,
81
- ...(variant?.width === 'equal' && staticStyles.equalWidth),
95
+ ...widthStyle,
82
96
  ...(shouldUseTransparentBackground && {
83
97
  backgroundColor: 'transparent'
84
98
  }),
85
99
  alignSelf: themeButtonTokens.width ? 'flex-start' : 'center'
86
100
  };
87
- }, [themeButtonTokensCallback, isMobileNonContained, variant?.width]);
88
- const fieldsetStyles = (0, _react.useMemo)(() => ({
89
- ...staticStyles.fieldsetBase,
90
- borderRadius,
91
- backgroundColor: isMobileNonContained ? 'transparent' : backgroundColor || 'transparent',
92
- padding,
93
- width: variant?.width === 'equal' ? '100%' : 'auto'
94
- }), [borderRadius, backgroundColor, padding, variant?.width, isMobileNonContained]);
95
- const viewStyles = (0, _react.useMemo)(() => ({
96
- ...staticStyles.viewBase,
97
- flexDirection: direction === 'column' ? 'column' : 'row',
98
- gap: gapValue || 0,
99
- justifyContent: variant?.width === 'equal' ? 'space-evenly' : 'flex-start'
100
- }), [direction, gapValue, variant?.width]);
101
+ }, [themeButtonTokensCallback, isMobileNonContained, buttonWidthVariant]);
102
+ const fieldsetStyles = (0, _react.useMemo)(() => {
103
+ let fieldSetBase;
104
+ switch (buttonWidthVariant) {
105
+ case EQUAL_WIDTH:
106
+ case RESPONSIVE_WIDTH:
107
+ fieldSetBase = staticStyles.fieldSetResponsive;
108
+ break;
109
+ default:
110
+ fieldSetBase = staticStyles.fieldsetBase;
111
+ break;
112
+ }
113
+ return {
114
+ ...fieldSetBase,
115
+ borderRadius,
116
+ backgroundColor: isMobileNonContained ? 'transparent' : backgroundColor || 'transparent',
117
+ padding
118
+ };
119
+ }, [borderRadius, backgroundColor, padding, isMobileNonContained, buttonWidthVariant]);
120
+ const buttonsContainerStyles = (0, _react.useMemo)(() => {
121
+ let flexWrap;
122
+ if (isWeb) {
123
+ flexWrap = 'wrap';
124
+ } else {
125
+ switch (buttonWidthVariant) {
126
+ case EQUAL_WIDTH:
127
+ case RESPONSIVE_WIDTH:
128
+ flexWrap = 'nowrap';
129
+ break;
130
+ default:
131
+ flexWrap = 'wrap';
132
+ break;
133
+ }
134
+ }
135
+ let justifyContent;
136
+ switch (buttonWidthVariant) {
137
+ case EQUAL_WIDTH:
138
+ justifyContent = 'space-evenly';
139
+ break;
140
+ default:
141
+ justifyContent = 'flex-start';
142
+ break;
143
+ }
144
+ let viewBaseStyle;
145
+ switch (buttonWidthVariant) {
146
+ case EQUAL_WIDTH:
147
+ case RESPONSIVE_WIDTH:
148
+ viewBaseStyle = {};
149
+ break;
150
+ default:
151
+ viewBaseStyle = staticStyles.viewBase;
152
+ break;
153
+ }
154
+ return {
155
+ ...viewBaseStyle,
156
+ flexWrap,
157
+ flexDirection: direction === 'column' ? 'column' : 'row',
158
+ gap: gapValue || 0,
159
+ justifyContent
160
+ };
161
+ }, [direction, gapValue, buttonWidthVariant, isWeb]);
101
162
  const {
102
163
  currentValues,
103
164
  toggleOneValue
@@ -119,7 +180,7 @@ const ButtonGroup = exports.ButtonGroup = /*#__PURE__*/_react.default.forwardRef
119
180
  }
120
181
 
121
182
  // Some web screenreaders e.g. MacOS Voiceover don't handle radiogroups properly unless radio is direct child of radiogroup
122
- const innerRole = _Platform.default.OS === 'web' && accessibilityRole === 'radiogroup' ? accessibilityRole : undefined;
183
+ const buttonsWrapperRole = _Platform.default.OS === 'web' && accessibilityRole === 'radiogroup' ? accessibilityRole : undefined;
123
184
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Fieldset.Fieldset, {
124
185
  ...systemProps,
125
186
  ref: ref,
@@ -137,8 +198,8 @@ const ButtonGroup = exports.ButtonGroup = /*#__PURE__*/_react.default.forwardRef
137
198
  style: fieldsetStyles,
138
199
  ...selectProps(rest),
139
200
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
140
- accessibilityRole: innerRole,
141
- style: viewStyles,
201
+ accessibilityRole: buttonsWrapperRole,
202
+ style: buttonsContainerStyles,
142
203
  children: items.map((_ref2, index) => {
143
204
  let {
144
205
  label,
@@ -308,17 +369,24 @@ ButtonGroup.propTypes = {
308
369
  copy: _propTypes.default.oneOf(['en', 'fr'])
309
370
  };
310
371
  const staticStyles = _StyleSheet.default.create({
372
+ equalWidth: {
373
+ width: '100%',
374
+ flex: 1
375
+ },
376
+ responsiveWidth: {
377
+ width: 'auto'
378
+ },
311
379
  fieldsetBase: {
312
380
  alignSelf: 'flex-start',
313
- display: 'inline'
381
+ display: 'inline',
382
+ width: 'auto'
383
+ },
384
+ fieldSetResponsive: {
385
+ width: '100%'
314
386
  },
315
387
  viewBase: {
316
388
  flexWrap: 'wrap',
317
389
  alignContent: 'stretch',
318
390
  alignItems: 'center'
319
- },
320
- equalWidth: {
321
- width: '100%',
322
- flex: 1
323
391
  }
324
392
  });
@@ -27,9 +27,7 @@ var _jsxRuntime = require("react/jsx-runtime");
27
27
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
28
28
  const [selectProps, selectedSystemPropTypes] = (0, _selectSystemProps.selectSystemProps)([_a11yProps.a11yProps, _viewProps.viewProps]);
29
29
  const GRID_COLUMNS = 12;
30
- const isOverlayColor = color => {
31
- return color && typeof color === 'string' && color.startsWith('rgba(');
32
- };
30
+ const isOverlayColor = color => color && typeof color === 'string' && color.startsWith('rgba(');
33
31
  const setBackgroundImage = _ref => {
34
32
  let {
35
33
  src,
@@ -38,7 +36,8 @@ const setBackgroundImage = _ref => {
38
36
  backgroundImagePosition,
39
37
  backgroundImageAlign,
40
38
  content,
41
- cardStyle
39
+ cardStyle,
40
+ testID
42
41
  } = _ref;
43
42
  const borderRadius = cardStyle?.borderRadius || 0;
44
43
  const borderWidth = cardStyle?.borderWidth || 0;
@@ -98,6 +97,7 @@ const setBackgroundImage = _ref => {
98
97
  style: [staticStyles.imageBackground, backgroundImageStyle],
99
98
  role: "img",
100
99
  "aria-label": alt,
100
+ testID: testID,
101
101
  children: content
102
102
  });
103
103
  }
@@ -112,7 +112,8 @@ const setBackgroundImage = _ref => {
112
112
  style: [staticStyles.containImage, positionStyles],
113
113
  accessible: true,
114
114
  accessibilityLabel: alt,
115
- accessibilityIgnoresInvertColors: true
115
+ accessibilityIgnoresInvertColors: true,
116
+ testID: testID
116
117
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
117
118
  style: staticStyles.contentOverlay,
118
119
  children: content
@@ -128,6 +129,7 @@ const setBackgroundImage = _ref => {
128
129
  style: staticStyles.imageBackground,
129
130
  accessible: true,
130
131
  accessibilityLabel: alt,
132
+ testID: testID,
131
133
  children: content
132
134
  });
133
135
  };
@@ -136,22 +138,13 @@ const selectPaddedContentStyles = _ref2 => {
136
138
  paddingTop,
137
139
  paddingBottom,
138
140
  paddingLeft,
139
- paddingRight,
140
- borderWidth,
141
- borderColor,
142
- borderRadius,
143
- hasInteractiveBorder
141
+ paddingRight
144
142
  } = _ref2;
145
143
  return {
146
144
  paddingTop,
147
145
  paddingBottom,
148
146
  paddingLeft,
149
- paddingRight,
150
- ...(hasInteractiveBorder ? {
151
- borderWidth,
152
- borderColor,
153
- borderRadius
154
- } : {})
147
+ paddingRight
155
148
  };
156
149
  };
157
150
  const selectInteractiveOverlayStyles = _ref3 => {
@@ -170,12 +163,31 @@ const selectInteractiveOverlayStyles = _ref3 => {
170
163
  backgroundColor,
171
164
  borderRadius: adjustedBorderRadius,
172
165
  pointerEvents: 'none',
173
- zIndex: 1
166
+ zIndex: 3
167
+ };
168
+ };
169
+ const selectOuterContainerStyles = _ref4 => {
170
+ let {
171
+ containerStyle,
172
+ backgroundColor,
173
+ borderRadius,
174
+ borderColor,
175
+ borderWidth,
176
+ hasGradientToken
177
+ } = _ref4;
178
+ return {
179
+ ...containerStyle,
180
+ backgroundColor,
181
+ borderRadius,
182
+ ...(hasGradientToken ? {} : {
183
+ borderColor,
184
+ borderWidth
185
+ })
174
186
  };
175
187
  };
176
188
 
177
189
  // Ensure explicit selection of tokens
178
- const selectStyles = _ref4 => {
190
+ const selectStyles = function (_ref5) {
179
191
  let {
180
192
  flex,
181
193
  backgroundColor,
@@ -196,7 +208,10 @@ const selectStyles = _ref4 => {
196
208
  gradient,
197
209
  maxHeight,
198
210
  overflowY
199
- } = _ref4;
211
+ } = _ref5;
212
+ let {
213
+ hasBgImage = false
214
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
200
215
  const hasGradient = (gradient || backgroundGradient) && _Platform.default.OS === 'web';
201
216
  let backgroundImageValue = null;
202
217
  if (hasGradient) {
@@ -225,7 +240,11 @@ const selectStyles = _ref4 => {
225
240
  ...(gradient && _Platform.default.OS === 'web' ? {
226
241
  backgroundImage: backgroundImageValue,
227
242
  backgroundOrigin: `border-box`,
228
- boxShadow: `inset 0 1000px ${boxShadowColor}`,
243
+ // bgImage child fills the content-box and replaces what the inset shadow
244
+ // used to cover, so we omit it to avoid hiding the image.
245
+ ...(hasBgImage ? {} : {
246
+ boxShadow: `inset 0 1000px ${boxShadowColor}`
247
+ }),
229
248
  border: `${borderWidth}px solid transparent`
230
249
  } : {}),
231
250
  ...(backgroundGradient && _Platform.default.OS === 'web' ? {
@@ -243,7 +262,7 @@ const selectStyles = _ref4 => {
243
262
  * intended to be used in apps or sites directly: build themed components on top of this.
244
263
  */
245
264
  exports.selectStyles = selectStyles;
246
- const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
265
+ const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
247
266
  let {
248
267
  children,
249
268
  tokens,
@@ -251,15 +270,14 @@ const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref
251
270
  backgroundImage,
252
271
  fullBleedContent,
253
272
  cardState,
273
+ testID,
254
274
  ...rest
255
- } = _ref5;
275
+ } = _ref6;
256
276
  const resolvedTokens = typeof tokens === 'function' ? tokens(cardState) : tokens;
257
- const tokensToUse = backgroundImage && backgroundImage.src ? {
258
- ...resolvedTokens,
259
- gradient: undefined,
260
- backgroundGradient: undefined
261
- } : resolvedTokens;
262
- const cardStyle = selectStyles(tokensToUse);
277
+ const hasBgImage = Boolean(backgroundImage && backgroundImage.src);
278
+ const cardStyle = selectStyles(resolvedTokens, {
279
+ hasBgImage
280
+ });
263
281
  const props = selectProps(rest);
264
282
  let content = children;
265
283
  const {
@@ -292,31 +310,29 @@ const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref
292
310
  ...containerStyle
293
311
  } = cardStyle;
294
312
  const hasPadding = paddingTop || paddingBottom || paddingLeft || paddingRight;
295
- const hasInteractiveBorder = borderWidth && borderWidth > 0;
296
313
  const hasInteractiveOverlay = isOverlayColor(backgroundColor);
297
- const paddedContent = hasPadding || hasInteractiveBorder ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
314
+ const outerBackgroundColor = hasInteractiveOverlay ? undefined : backgroundColor;
315
+ const hasGradientToken = Boolean(resolvedTokens.gradient) && _Platform.default.OS === 'web';
316
+ const paddedContent = hasPadding ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
298
317
  style: selectPaddedContentStyles({
299
318
  paddingTop,
300
319
  paddingBottom,
301
320
  paddingLeft,
302
- paddingRight,
303
- borderWidth,
304
- borderColor,
305
- borderRadius,
306
- hasInteractiveBorder
321
+ paddingRight
307
322
  }),
308
323
  children: children
309
324
  }) : children;
310
325
  const contentWithOverlay = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
311
- children: [hasInteractiveOverlay && _Platform.default.OS === 'web' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
326
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
327
+ style: staticStyles.contentOverlay,
328
+ children: paddedContent
329
+ }), hasInteractiveOverlay && _Platform.default.OS === 'web' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
312
330
  style: selectInteractiveOverlayStyles({
313
331
  backgroundColor,
314
332
  borderRadius,
315
333
  borderWidth
316
- })
317
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
318
- style: staticStyles.contentOverlay,
319
- children: paddedContent
334
+ }),
335
+ testID: testID && `${testID}-card-base-bg-overlay`
320
336
  })]
321
337
  });
322
338
  content = setBackgroundImage({
@@ -327,17 +343,23 @@ const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref
327
343
  backgroundImageAlign,
328
344
  content: contentWithOverlay,
329
345
  cardStyle: {
330
- ...containerStyle,
331
- borderRadius
332
- }
346
+ borderRadius,
347
+ borderWidth
348
+ },
349
+ testID: testID && `${testID}-card-base-bg-image`
333
350
  });
334
351
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
335
- style: {
336
- ...containerStyle,
337
- borderRadius
338
- },
352
+ style: selectOuterContainerStyles({
353
+ containerStyle,
354
+ backgroundColor: outerBackgroundColor,
355
+ borderRadius,
356
+ borderColor,
357
+ borderWidth,
358
+ hasGradientToken
359
+ }),
339
360
  dataSet: dataSet,
340
361
  ref: ref,
362
+ testID: testID,
341
363
  ...props,
342
364
  children: content
343
365
  });
@@ -377,6 +399,7 @@ const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref
377
399
  style: containerStyle,
378
400
  dataSet: dataSet,
379
401
  ref: ref,
402
+ testID: testID,
380
403
  ...props,
381
404
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FlexGrid.FlexGrid, {
382
405
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FlexGridRow.FlexGridRow, {
@@ -393,6 +416,7 @@ const CardBase = exports.CardBase = /*#__PURE__*/_react.default.forwardRef((_ref
393
416
  style: cardStyle,
394
417
  dataSet: dataSet,
395
418
  ref: ref,
419
+ testID: testID,
396
420
  ...props,
397
421
  children: content
398
422
  });
@@ -435,6 +459,10 @@ CardBase.propTypes = {
435
459
  ...selectedSystemPropTypes,
436
460
  children: _propTypes.default.node,
437
461
  tokens: (0, _tokens.getTokensPropType)('Card'),
462
+ /**
463
+ * Identifier for testing purposes.
464
+ */
465
+ testID: _propTypes.default.string,
438
466
  /**
439
467
  * Apply background image to the card.
440
468
  */
@@ -9,10 +9,12 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
10
10
  var _Pressable = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Pressable"));
11
11
  var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
12
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
12
13
  var _pressability = require("../utils/pressability");
13
14
  var _styles = require("../ThemeProvider/utils/styles");
14
15
  var _tokens = require("../utils/props/tokens");
15
16
  var _Tooltip = require("../Tooltip/Tooltip.native");
17
+ var _constants = require("./constants");
16
18
  var _jsxRuntime = require("react/jsx-runtime");
17
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
20
  const selectGeneralBubbleTokens = _ref => {
@@ -70,37 +72,70 @@ const selectBorderBubbleTokens = _ref3 => {
70
72
  borderRadius: bubbleBorderRadius
71
73
  };
72
74
  };
73
- const ColourBubble = exports.ColourBubble = /*#__PURE__*/_react.default.forwardRef((_ref4, ref) => {
75
+ const selectOverlayStyles = _ref4 => {
74
76
  let {
75
- tokens = {},
77
+ overlayColor,
78
+ innerBubbleBorderRadius
79
+ } = _ref4;
80
+ return {
81
+ borderRadius: innerBubbleBorderRadius,
82
+ backgroundColor: overlayColor
83
+ };
84
+ };
85
+ const selectSlashStyles = (_ref5, unavailable) => {
86
+ let {
87
+ slashLightColor,
88
+ slashDarkColor,
89
+ slashWidth,
90
+ slashOffset
91
+ } = _ref5;
92
+ return {
93
+ width: slashWidth,
94
+ backgroundColor: unavailable === _constants.UNAVAILABLE_VARIANT.DARK ? slashDarkColor : slashLightColor,
95
+ marginLeft: slashOffset
96
+ };
97
+ };
98
+ const ColourBubble = exports.ColourBubble = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
99
+ let {
100
+ tokens = () => ({}),
76
101
  id,
77
102
  colourHexCode,
78
103
  colourName,
79
104
  isSelected,
80
105
  onPress,
81
- showTooltip
82
- } = _ref4;
106
+ showTooltip,
107
+ unavailable,
108
+ isDisabled
109
+ } = _ref6;
83
110
  const defaultTokens = tokens({
84
111
  selected: isSelected
85
112
  });
86
- const resolveColourBubbleTokens = pressState => (0, _pressability.resolvePressableTokens)(tokens, pressState, {});
87
- const themeTokens = _react.default.useMemo(() => tokens(), [tokens]);
88
- const pressable = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default, {
113
+ const resolveColourBubbleTokens = pressState => (0, _pressability.resolvePressableTokens)(tokens, isDisabled ? {} : pressState, {});
114
+ const themeTokens = tokens();
115
+ const pressable = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Pressable.default, {
89
116
  style: state => [selectGeneralBubbleTokens(resolveColourBubbleTokens(state)), isSelected && selectBorderBubbleTokens(defaultTokens)],
90
117
  onPress: onPress,
118
+ disabled: isDisabled,
119
+ focusable: !isDisabled,
91
120
  accessible: true,
92
121
  accessibilityRole: "radio",
93
122
  accessibilityLabel: colourName,
94
123
  accessibilityState: {
95
- checked: isSelected
124
+ checked: isSelected,
125
+ disabled: isDisabled
96
126
  },
97
127
  ref: ref,
98
128
  testID: id,
99
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
129
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
100
130
  style: [selectInnerBubbleTokens(themeTokens), {
101
131
  backgroundColor: colourHexCode
102
- }]
103
- })
132
+ }],
133
+ children: unavailable && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
134
+ style: [_StyleSheet.default.absoluteFillObject, selectOverlayStyles(themeTokens)]
135
+ })
136
+ }), unavailable && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
137
+ style: [staticStyles.indicator, selectSlashStyles(themeTokens, unavailable)]
138
+ })]
104
139
  });
105
140
  if (showTooltip) {
106
141
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.Tooltip, {
@@ -142,5 +177,23 @@ ColourBubble.propTypes = {
142
177
  /**
143
178
  * When true, wraps the bubble in a Tooltip that displays the colourName on hover (web only).
144
179
  */
145
- showTooltip: _propTypes.default.bool
146
- };
180
+ showTooltip: _propTypes.default.bool,
181
+ /**
182
+ * When set, renders a diagonal indicator over the bubble. Accepts either 'dark' or 'light' to determine the colour of the indicator.
183
+ */
184
+ unavailable: _propTypes.default.oneOf(Object.values(_constants.UNAVAILABLE_VARIANT)),
185
+ /**
186
+ * When true, disables interaction on the bubble.
187
+ */
188
+ isDisabled: _propTypes.default.bool
189
+ };
190
+ const staticStyles = _StyleSheet.default.create({
191
+ indicator: {
192
+ position: 'absolute',
193
+ top: '50%',
194
+ height: 2,
195
+ transform: [{
196
+ rotate: '-45deg'
197
+ }]
198
+ }
199
+ });