@telus-uds/components-base 1.12.0 → 1.14.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 (132) hide show
  1. package/CHANGELOG.md +41 -2
  2. package/component-docs.json +933 -55
  3. package/lib/BaseProvider/index.js +7 -2
  4. package/lib/Button/ButtonBase.js +52 -19
  5. package/lib/Button/ButtonGroup.js +7 -0
  6. package/lib/Button/propTypes.js +18 -0
  7. package/lib/Carousel/Carousel.js +83 -58
  8. package/lib/Carousel/CarouselContext.js +22 -8
  9. package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +73 -0
  10. package/lib/Carousel/CarouselStepTracker/CarouselStepTracker.js +56 -0
  11. package/lib/Carousel/CarouselStepTracker/index.js +13 -0
  12. package/lib/Carousel/CarouselTabs/CarouselTabs.js +70 -0
  13. package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +95 -0
  14. package/lib/Carousel/CarouselTabs/CarouselTabsPanelItem.js +148 -0
  15. package/lib/Carousel/CarouselTabs/index.js +13 -0
  16. package/lib/Carousel/CarouselThumbnail.js +99 -0
  17. package/lib/Carousel/CarouselThumbnailNavigation.js +87 -0
  18. package/lib/Carousel/dictionary.js +4 -2
  19. package/lib/Carousel/index.js +10 -1
  20. package/lib/Checkbox/Checkbox.js +7 -3
  21. package/lib/Checkbox/CheckboxGroup.js +8 -1
  22. package/lib/Feedback/Feedback.js +18 -10
  23. package/lib/Icon/IconText.js +6 -1
  24. package/lib/InputLabel/InputLabel.js +11 -5
  25. package/lib/Link/InlinePressable.js +1 -8
  26. package/lib/Link/LinkBase.js +13 -10
  27. package/lib/List/ListItem.js +8 -4
  28. package/lib/Notification/Notification.js +44 -24
  29. package/lib/Pagination/Pagination.js +7 -3
  30. package/lib/Radio/RadioGroup.js +8 -0
  31. package/lib/RadioCard/RadioCard.js +6 -1
  32. package/lib/RadioCard/RadioCardGroup.js +7 -0
  33. package/lib/Select/Select.js +7 -3
  34. package/lib/SkipLink/SkipLink.js +216 -0
  35. package/lib/SkipLink/index.js +13 -0
  36. package/lib/StepTracker/Step.js +8 -4
  37. package/lib/StepTracker/StepTracker.js +7 -3
  38. package/lib/Tabs/TabsItem.js +4 -0
  39. package/lib/TextInput/TextInputBase.js +7 -3
  40. package/lib/ThemeProvider/ThemeProvider.js +25 -3
  41. package/lib/ThemeProvider/utils/styles.js +8 -1
  42. package/lib/ThemeProvider/utils/theme-tokens.js +1 -1
  43. package/lib/ToggleSwitch/ToggleSwitchGroup.js +7 -0
  44. package/lib/Typography/Typography.js +6 -2
  45. package/lib/index.js +9 -0
  46. package/lib-module/BaseProvider/index.js +7 -2
  47. package/lib-module/Button/ButtonBase.js +41 -9
  48. package/lib-module/Button/ButtonGroup.js +7 -0
  49. package/lib-module/Button/propTypes.js +17 -0
  50. package/lib-module/Carousel/Carousel.js +80 -57
  51. package/lib-module/Carousel/CarouselContext.js +21 -8
  52. package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +51 -0
  53. package/lib-module/Carousel/CarouselStepTracker/CarouselStepTracker.js +42 -0
  54. package/lib-module/Carousel/CarouselStepTracker/index.js +2 -0
  55. package/lib-module/Carousel/CarouselTabs/CarouselTabs.js +50 -0
  56. package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +76 -0
  57. package/lib-module/Carousel/CarouselTabs/CarouselTabsPanelItem.js +126 -0
  58. package/lib-module/Carousel/CarouselTabs/index.js +2 -0
  59. package/lib-module/Carousel/CarouselThumbnail.js +85 -0
  60. package/lib-module/Carousel/CarouselThumbnailNavigation.js +66 -0
  61. package/lib-module/Carousel/dictionary.js +4 -2
  62. package/lib-module/Carousel/index.js +2 -1
  63. package/lib-module/Checkbox/Checkbox.js +8 -4
  64. package/lib-module/Checkbox/CheckboxGroup.js +8 -1
  65. package/lib-module/Feedback/Feedback.js +19 -11
  66. package/lib-module/Icon/IconText.js +6 -1
  67. package/lib-module/InputLabel/InputLabel.js +12 -6
  68. package/lib-module/Link/InlinePressable.js +1 -8
  69. package/lib-module/Link/LinkBase.js +14 -11
  70. package/lib-module/List/ListItem.js +9 -5
  71. package/lib-module/Notification/Notification.js +46 -26
  72. package/lib-module/Pagination/Pagination.js +8 -4
  73. package/lib-module/Radio/RadioGroup.js +8 -0
  74. package/lib-module/RadioCard/RadioCard.js +7 -2
  75. package/lib-module/RadioCard/RadioCardGroup.js +7 -0
  76. package/lib-module/Select/Select.js +8 -4
  77. package/lib-module/SkipLink/SkipLink.js +188 -0
  78. package/lib-module/SkipLink/index.js +2 -0
  79. package/lib-module/StepTracker/Step.js +9 -5
  80. package/lib-module/StepTracker/StepTracker.js +8 -4
  81. package/lib-module/Tabs/TabsItem.js +5 -1
  82. package/lib-module/TextInput/TextInputBase.js +8 -4
  83. package/lib-module/ThemeProvider/ThemeProvider.js +24 -3
  84. package/lib-module/ThemeProvider/utils/styles.js +8 -1
  85. package/lib-module/ThemeProvider/utils/theme-tokens.js +1 -1
  86. package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +7 -0
  87. package/lib-module/Typography/Typography.js +7 -3
  88. package/lib-module/index.js +1 -0
  89. package/package.json +46 -47
  90. package/src/BaseProvider/index.jsx +6 -3
  91. package/src/Button/ButtonBase.jsx +36 -12
  92. package/src/Button/ButtonGroup.jsx +6 -0
  93. package/src/Button/propTypes.js +14 -0
  94. package/src/Carousel/Carousel.jsx +91 -64
  95. package/src/Carousel/CarouselContext.jsx +29 -5
  96. package/src/Carousel/CarouselFirstFocus/CarouselFirstFocus.jsx +49 -0
  97. package/src/Carousel/CarouselStepTracker/CarouselStepTracker.jsx +36 -0
  98. package/src/Carousel/CarouselStepTracker/index.js +3 -0
  99. package/src/Carousel/CarouselTabs/CarouselTabs.jsx +37 -0
  100. package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +69 -0
  101. package/src/Carousel/CarouselTabs/CarouselTabsPanelItem.jsx +119 -0
  102. package/src/Carousel/CarouselTabs/index.js +3 -0
  103. package/src/Carousel/CarouselThumbnail.jsx +77 -0
  104. package/src/Carousel/CarouselThumbnailNavigation.jsx +53 -0
  105. package/src/Carousel/dictionary.js +4 -2
  106. package/src/Carousel/index.js +1 -0
  107. package/src/Checkbox/Checkbox.jsx +14 -11
  108. package/src/Checkbox/CheckboxGroup.jsx +8 -1
  109. package/src/Feedback/Feedback.jsx +14 -7
  110. package/src/Icon/IconText.jsx +3 -1
  111. package/src/InputLabel/InputLabel.jsx +13 -12
  112. package/src/Link/InlinePressable.jsx +2 -8
  113. package/src/Link/LinkBase.jsx +18 -21
  114. package/src/List/ListItem.jsx +10 -5
  115. package/src/Notification/Notification.jsx +40 -23
  116. package/src/Pagination/Pagination.jsx +6 -4
  117. package/src/Radio/RadioGroup.jsx +7 -0
  118. package/src/RadioCard/RadioCard.jsx +3 -2
  119. package/src/RadioCard/RadioCardGroup.jsx +6 -0
  120. package/src/Select/Select.jsx +12 -3
  121. package/src/SkipLink/SkipLink.jsx +179 -0
  122. package/src/SkipLink/index.js +3 -0
  123. package/src/StepTracker/Step.jsx +12 -4
  124. package/src/StepTracker/StepTracker.jsx +11 -10
  125. package/src/Tabs/TabsItem.jsx +3 -2
  126. package/src/TextInput/TextInputBase.jsx +11 -3
  127. package/src/ThemeProvider/ThemeProvider.jsx +22 -3
  128. package/src/ThemeProvider/utils/styles.js +9 -1
  129. package/src/ThemeProvider/utils/theme-tokens.js +1 -1
  130. package/src/ToggleSwitch/ToggleSwitchGroup.jsx +6 -0
  131. package/src/Typography/Typography.jsx +11 -12
  132. package/src/index.js +1 -0
@@ -24,12 +24,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
24
24
  const BaseProvider = _ref => {
25
25
  let {
26
26
  defaultTheme,
27
- children
27
+ children,
28
+ themeOptions
28
29
  } = _ref;
29
30
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_A11yInfoProvider.default, {
30
31
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ViewportProvider.default, {
31
32
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ThemeProvider.default, {
32
33
  defaultTheme: defaultTheme,
34
+ themeOptions: themeOptions,
33
35
  children: children
34
36
  })
35
37
  })
@@ -37,8 +39,11 @@ const BaseProvider = _ref => {
37
39
  };
38
40
 
39
41
  BaseProvider.propTypes = {
42
+ children: _propTypes.default.node.isRequired,
40
43
  defaultTheme: (_ThemeProvider$propTy = _ThemeProvider.default.propTypes) === null || _ThemeProvider$propTy === void 0 ? void 0 : _ThemeProvider$propTy.defaultTheme,
41
- children: _propTypes.default.node.isRequired
44
+ themeOptions: _propTypes.default.shape({
45
+ forceAbsoluteFontSizing: _propTypes.default.bool
46
+ })
42
47
  };
43
48
  var _default = BaseProvider;
44
49
  exports.default = _default;
@@ -17,11 +17,13 @@ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/expo
17
17
 
18
18
  var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
19
19
 
20
- var _utils = require("../ThemeProvider/utils");
20
+ var _ThemeProvider = require("../ThemeProvider");
21
21
 
22
22
  var _propTypes2 = _interopRequireDefault(require("./propTypes"));
23
23
 
24
- var _utils2 = require("../utils");
24
+ var _utils = require("../utils");
25
+
26
+ var _Icon = require("../Icon");
25
27
 
26
28
  var _jsxRuntime = require("react/jsx-runtime");
27
29
 
@@ -31,7 +33,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
31
33
 
32
34
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
33
35
 
34
- const [selectProps, selectedSystemPropTypes] = (0, _utils2.selectSystemProps)([_utils2.a11yProps, _utils2.focusHandlerProps, _utils2.linkProps, _utils2.viewProps]);
36
+ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.focusHandlerProps, _utils.linkProps, _utils.viewProps]);
35
37
 
36
38
  const getOuterBorderOffset = _ref => {
37
39
  let {
@@ -55,7 +57,7 @@ const selectOuterContainerStyles = _ref2 => {
55
57
  alignSelf,
56
58
  backgroundColor: outerBackgroundColor,
57
59
  opacity,
58
- ...(0, _utils.applyOuterBorder)({
60
+ ...(0, _ThemeProvider.applyOuterBorder)({
59
61
  outerBorderGap,
60
62
  outerBorderWidth,
61
63
  outerBorderColor,
@@ -137,7 +139,7 @@ const selectInnerContainerStyles = _ref4 => {
137
139
  paddingBottom: offsetBorder(paddingBottom),
138
140
  backgroundColor,
139
141
  minWidth,
140
- ...(0, _utils.applyShadowToken)(shadow)
142
+ ...(0, _ThemeProvider.applyShadowToken)(shadow)
141
143
  };
142
144
  };
143
145
 
@@ -154,7 +156,7 @@ const selectBorderStyles = _ref5 => {
154
156
  };
155
157
  };
156
158
 
157
- const selectTextStyles = _ref6 => {
159
+ const selectTextStyles = (_ref6, themeOptions) => {
158
160
  let {
159
161
  fontSize,
160
162
  color,
@@ -163,12 +165,13 @@ const selectTextStyles = _ref6 => {
163
165
  fontWeight,
164
166
  textAlign
165
167
  } = _ref6;
166
- return (0, _utils.applyTextStyles)({
168
+ return (0, _ThemeProvider.applyTextStyles)({
167
169
  fontSize,
168
170
  color,
169
171
  lineHeight,
170
172
  fontName,
171
173
  fontWeight,
174
+ themeOptions,
172
175
  textAlign
173
176
  });
174
177
  };
@@ -183,13 +186,24 @@ const selectWebOnlyStyles = (inactive, themeTokens, _ref7) => {
183
186
  maxWidth: "calc(100% + ".concat(getOuterBorderOffset(themeTokens) * 2, "px)"),
184
187
  outline: 'none',
185
188
  // removes the default browser :focus outline
186
- ...(0, _utils2.getCursorStyle)(inactive, accessibilityRole)
189
+ ...(0, _utils.getCursorStyle)(inactive, accessibilityRole)
187
190
  },
188
191
  default: {}
189
192
  });
190
193
  };
191
194
 
192
- const ButtonBase = /*#__PURE__*/(0, _react.forwardRef)((_ref8, ref) => {
195
+ const selectItemIconTokens = _ref8 => {
196
+ let {
197
+ color,
198
+ iconSize
199
+ } = _ref8;
200
+ return {
201
+ size: iconSize,
202
+ color
203
+ };
204
+ };
205
+
206
+ const ButtonBase = /*#__PURE__*/(0, _react.forwardRef)((_ref9, ref) => {
193
207
  let {
194
208
  id,
195
209
  href,
@@ -200,20 +214,23 @@ const ButtonBase = /*#__PURE__*/(0, _react.forwardRef)((_ref8, ref) => {
200
214
  // alias for inactive
201
215
  inactive = disabled,
202
216
  selected = false,
217
+ icon,
218
+ iconPosition = icon ? 'left' : undefined,
219
+ iconProps,
203
220
  ...rawRest
204
- } = _ref8;
221
+ } = _ref9;
205
222
 
206
223
  const {
207
224
  onPress,
208
225
  ...rest
209
- } = _utils2.clickProps.toPressProps(rawRest);
226
+ } = _utils.clickProps.toPressProps(rawRest);
210
227
 
211
228
  const extraButtonState = {
212
229
  inactive,
213
230
  selected
214
231
  };
215
232
 
216
- const resolveButtonTokens = pressableState => (0, _utils2.resolvePressableTokens)(tokens, pressableState, extraButtonState);
233
+ const resolveButtonTokens = pressableState => (0, _utils.resolvePressableTokens)(tokens, pressableState, extraButtonState);
217
234
 
218
235
  const systemProps = selectProps(rest);
219
236
 
@@ -222,10 +239,13 @@ const ButtonBase = /*#__PURE__*/(0, _react.forwardRef)((_ref8, ref) => {
222
239
  return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens), selectOuterWidthStyles(themeTokens)];
223
240
  };
224
241
 
242
+ const {
243
+ themeOptions
244
+ } = (0, _ThemeProvider.useTheme)();
225
245
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default, {
226
246
  ref: ref,
227
247
  href: href,
228
- onPress: _utils2.linkProps.handleHref({
248
+ onPress: _utils.linkProps.handleHref({
229
249
  href,
230
250
  onPress
231
251
  }),
@@ -237,10 +257,15 @@ const ButtonBase = /*#__PURE__*/(0, _react.forwardRef)((_ref8, ref) => {
237
257
  const themeTokens = resolveButtonTokens(pressableState);
238
258
  const containerStyles = selectInnerContainerStyles(themeTokens);
239
259
  const borderStyles = selectBorderStyles(themeTokens);
240
- const textStyles = [selectTextStyles(themeTokens), staticStyles.text]; // If the container has a width set, fill it instead of sizing from content.
260
+ const textStyles = [selectTextStyles(themeTokens, themeOptions), staticStyles.text];
261
+ const iconTokens = selectItemIconTokens(themeTokens);
262
+ const {
263
+ iconSpace
264
+ } = themeTokens; // If the container has a width set, fill it instead of sizing from content.
241
265
  // If in future we support text alignments other than center, add here.
242
266
 
243
267
  const stretchStyles = themeTokens.width ? staticStyles.stretch : staticStyles.align;
268
+ const IconComponent = icon || themeTokens.icon;
244
269
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
245
270
  id: id,
246
271
  style: [containerStyles, borderStyles, stretchStyles, staticStyles.row, _Platform.default.select({
@@ -251,10 +276,18 @@ const ButtonBase = /*#__PURE__*/(0, _react.forwardRef)((_ref8, ref) => {
251
276
  transition: 'background-color 200ms, border-color 200ms'
252
277
  }
253
278
  })],
254
- children: (0, _utils2.wrapStringsInText)(typeof children === 'function' ? children({ ...(0, _utils2.resolvePressableState)(pressableState, extraButtonState),
255
- textStyles
256
- }) : children, {
257
- style: textStyles
279
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.IconText, {
280
+ icon: IconComponent,
281
+ iconPosition: iconPosition,
282
+ space: iconSpace,
283
+ iconProps: { ...iconProps,
284
+ tokens: iconTokens
285
+ },
286
+ children: (0, _utils.wrapStringsInText)(typeof children === 'function' ? children({ ...(0, _utils.resolvePressableState)(pressableState, extraButtonState),
287
+ textStyles
288
+ }) : children, {
289
+ style: textStyles
290
+ })
258
291
  })
259
292
  });
260
293
  }
@@ -295,6 +328,6 @@ const staticStyles = _StyleSheet.default.create({
295
328
  }
296
329
  });
297
330
 
298
- var _default = (0, _utils2.withLinkRouter)(ButtonBase);
331
+ var _default = (0, _utils.withLinkRouter)(ButtonBase);
299
332
 
300
333
  exports.default = _default;
@@ -51,6 +51,7 @@ const ButtonGroup = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
51
51
  legend,
52
52
  tooltip,
53
53
  hint,
54
+ hintPosition = 'inline',
54
55
  validation,
55
56
  feedback,
56
57
  name: inputGroupName,
@@ -102,6 +103,7 @@ const ButtonGroup = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
102
103
  legend: legend,
103
104
  tooltip: tooltip,
104
105
  hint: hint,
106
+ hintPosition: hintPosition,
105
107
  space: fieldSpace,
106
108
  feedback: feedback,
107
109
  readOnly: readOnly,
@@ -233,6 +235,11 @@ ButtonGroup.propTypes = { ...selectedSystemPropTypes,
233
235
  */
234
236
  hint: _propTypes.default.string,
235
237
 
238
+ /**
239
+ * Position of the hint relative to label. Use `below` to display a larger hint below the label.
240
+ */
241
+ hintPosition: _propTypes.default.oneOf(['inline', 'below']),
242
+
236
243
  /**
237
244
  * Optional tooltip text content to include alongside the legend and hint.
238
245
  */
@@ -13,6 +13,8 @@ var _props = require("../utils/props");
13
13
 
14
14
  var _A11yText = _interopRequireDefault(require("../A11yText"));
15
15
 
16
+ var _Icon = require("../Icon");
17
+
16
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
19
 
18
20
  const textAndA11yText = _airbnbPropTypes.default.childrenOf(_propTypes.default.oneOfType([_airbnbPropTypes.default.elementType(_A11yText.default), _propTypes.default.string]));
@@ -46,6 +48,22 @@ const buttonPropTypes = {
46
48
  * Function called when the button is pressed. Required unless the button has a href.
47
49
  */
48
50
  onPress: _propTypes.default.func,
51
+
52
+ /**
53
+ * Optional variant that may be passed down to the link's icon if there is one
54
+ */
55
+ iconProps: _propTypes.default.exact(_Icon.iconComponentPropTypes),
56
+
57
+ /**
58
+ * When `icon` is provided, use `iconPosition` to place the Icon to the left or right side of the button.
59
+ */
60
+ iconPosition: _propTypes.default.oneOf(['left', 'right']),
61
+
62
+ /**
63
+ * A function component for an SVG icon to render inside the link. Inherits size and color from
64
+ * the link and any Typography the link is nested inside.
65
+ */
66
+ icon: _propTypes.default.func,
49
67
  variant: _props.variantProp.propType
50
68
  };
51
69
  var _default = buttonPropTypes;
@@ -31,11 +31,15 @@ var _CarouselContext = require("./CarouselContext");
31
31
 
32
32
  var _CarouselItem = _interopRequireDefault(require("./CarouselItem"));
33
33
 
34
- var _StepTracker = _interopRequireDefault(require("../StepTracker"));
34
+ var _IconButton = _interopRequireDefault(require("../IconButton"));
35
35
 
36
- var _StackView = _interopRequireDefault(require("../StackView"));
36
+ var _SkipLink = _interopRequireDefault(require("../SkipLink"));
37
37
 
38
- var _IconButton = _interopRequireDefault(require("../IconButton"));
38
+ var _A11yText = _interopRequireDefault(require("../A11yText"));
39
+
40
+ var _CarouselStepTracker = _interopRequireDefault(require("./CarouselStepTracker"));
41
+
42
+ var _CarouselThumbnailNavigation = _interopRequireDefault(require("./CarouselThumbnailNavigation"));
39
43
 
40
44
  var _dictionary = _interopRequireDefault(require("./dictionary"));
41
45
 
@@ -54,19 +58,6 @@ const staticStyles = _StyleSheet.default.create({
54
58
  }
55
59
  });
56
60
 
57
- const staticTokens = {
58
- stackView: {
59
- justifyContent: 'center'
60
- },
61
- stepTracker: {
62
- showStepLabel: false,
63
- showStepTrackerLabel: true,
64
- knobCompletedBackgroundColor: 'none',
65
- connectorCompletedColor: 'none',
66
- connectorColor: 'none'
67
- }
68
- };
69
-
70
61
  const selectContainerStyles = width => ({
71
62
  backgroundColor: 'transparent',
72
63
  overflow: 'hidden',
@@ -174,25 +165,32 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
174
165
  onAnimationStart,
175
166
  onAnimationEnd,
176
167
  onIndexChanged,
168
+ skipLinkHref,
169
+ refocus,
170
+ title = 'carousel',
177
171
  springConfig = undefined,
178
- onRenderPanelNavigation,
172
+ thumbnails = undefined,
173
+ panelNavigation = thumbnails ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CarouselThumbnailNavigation.default, {
174
+ thumbnails: thumbnails
175
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_CarouselStepTracker.default, {}),
179
176
  tag = 'ul',
180
- accessibilityRole = 'adjustable',
181
- accessibilityLabel = 'carousel',
177
+ accessibilityRole,
178
+ accessibilityLabel = title,
179
+ accessibilityLiveRegion = 'polite',
182
180
  copy,
183
181
  ...rest
184
182
  } = _ref;
185
183
  const viewport = (0, _ViewportProvider.useViewport)();
184
+ const themeTokens = (0, _ThemeProvider.useThemeTokens)('Carousel', tokens, variant, {
185
+ viewport
186
+ });
186
187
  const {
187
188
  previousIcon,
188
189
  nextIcon,
189
190
  showPreviousNextNavigation,
190
191
  showPanelNavigation,
191
- spaceBetweenSlideAndPreviousNextNavigation,
192
- spaceBetweenSlideAndPanelNavigation
193
- } = (0, _ThemeProvider.useThemeTokens)('Carousel', tokens, variant, {
194
- viewport
195
- });
192
+ spaceBetweenSlideAndPreviousNextNavigation
193
+ } = themeTokens;
196
194
 
197
195
  const [activeIndex, setActiveIndex] = _react.default.useState(0);
198
196
 
@@ -212,9 +210,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
212
210
  dictionary: _dictionary.default,
213
211
  copy
214
212
  });
215
-
216
- const childrenArray = _react.default.Children.toArray(children);
217
-
213
+ const childrenArray = (0, _utils.unpackFragment)(children);
218
214
  const systemProps = selectProps({ ...rest,
219
215
  accessibilityRole,
220
216
  accessibilityLabel,
@@ -236,6 +232,8 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
236
232
 
237
233
  const [previousNextNavigationButtonWidth, setPreviousNextNavigationButtonWidth] = _react.default.useState(0);
238
234
 
235
+ const firstFocusRef = _react.default.useRef(null);
236
+
239
237
  const pan = _react.default.useRef(new _Animated.default.ValueXY()).current;
240
238
 
241
239
  const animatedX = _react.default.useRef(0);
@@ -244,9 +242,6 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
244
242
 
245
243
  const isFirstSlide = !activeIndex;
246
244
  const isLastSlide = activeIndex + 1 >= children.length;
247
- const panelNavigationTokens = { ...staticTokens.stepTracker,
248
- containerPaddingTop: spaceBetweenSlideAndPanelNavigation
249
- };
250
245
 
251
246
  const onContainerLayout = _ref2 => {
252
247
  let {
@@ -344,10 +339,13 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
344
339
  }, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged]);
345
340
 
346
341
  const fixOffsetAndGo = _react.default.useCallback(delta => {
342
+ var _firstFocusRef$curren;
343
+
347
344
  updateOffset();
348
345
  handleAnimationStart(activeIndex);
349
346
  updateIndex(delta);
350
- }, [updateIndex, updateOffset, activeIndex, handleAnimationStart]);
347
+ if (refocus) (_firstFocusRef$curren = firstFocusRef.current) === null || _firstFocusRef$curren === void 0 ? void 0 : _firstFocusRef$curren.focus();
348
+ }, [updateIndex, updateOffset, activeIndex, handleAnimationStart, refocus]);
351
349
 
352
350
  const goToNeighboring = _react.default.useCallback(function () {
353
351
  let toPrev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
@@ -438,17 +436,22 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
438
436
  raised: true
439
437
  };
440
438
 
441
- const getCopyWithPlaceholders = copyKey => {
442
- const copyText = getCopy(copyKey).replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, activeIndex + 1).replace(/%\{stepCount\}/g, childrenArray.length); // First word might be a lowercase placeholder: capitalize the first letter
439
+ const getCopyWithPlaceholders = _react.default.useCallback(copyKey => {
440
+ const copyText = getCopy(copyKey).replace(/%\{title\}/g, title).replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, activeIndex + 1).replace(/%\{stepCount\}/g, childrenArray.length); // First word might be a lowercase placeholder: capitalize the first letter
443
441
 
444
442
  return "".concat(copyText[0].toUpperCase()).concat(copyText.slice(1));
445
- };
443
+ }, [activeIndex, childrenArray.length, itemLabel, getCopy, title]);
446
444
 
447
445
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_CarouselContext.CarouselProvider, {
448
446
  activeIndex: activeIndex,
447
+ goTo: goTo,
448
+ getCopyWithPlaceholders: getCopyWithPlaceholders,
449
+ itemLabel: itemLabel,
449
450
  totalItems: childrenArray.length,
451
+ themeTokens: themeTokens,
452
+ firstFocusRef: firstFocusRef,
453
+ refocus: refocus,
450
454
  width: containerLayout.width,
451
- goTo: goTo,
452
455
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
453
456
  style: staticStyles.root,
454
457
  onLayout: onContainerLayout,
@@ -464,6 +467,17 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
464
467
  variant: previousNextIconButtonVariants,
465
468
  accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex)
466
469
  })
470
+ }), Boolean(skipLinkHref) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_SkipLink.default, {
471
+ ref: firstFocusRef,
472
+ href: skipLinkHref,
473
+ children: getCopyWithPlaceholders('skipLink')
474
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_A11yText.default // Read the current slide position to screen readers on slide.
475
+ // If it's set to refocus and doesn't have a SkipLink to focus to, focus this.
476
+ , {
477
+ ref: !skipLinkHref && refocus ? firstFocusRef : null,
478
+ accessibilityLiveRegion: !skipLinkHref && refocus ? undefined : 'polite',
479
+ focusable: !skipLinkHref && refocus,
480
+ text: getCopyWithPlaceholders('stepTrackerLabel')
467
481
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
468
482
  style: selectContainerStyles(containerLayout.width),
469
483
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Animated.default.View, {
@@ -476,6 +490,9 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
476
490
  }]),
477
491
  ...panResponder.panHandlers,
478
492
  ...(0, _utils.getA11yPropsFromHtmlTag)(tag),
493
+ // In iframes on Mac (e.g. in Storybook), this content may be misread or read twice.
494
+ // This is a known Voiceover bug: https://github.com/phetsims/a11y-research/issues/132
495
+ accessibilityLiveRegion: accessibilityLiveRegion,
479
496
  children: childrenArray.map((element, index) => {
480
497
  const hidden = !isAnimating && index !== activeIndex;
481
498
 
@@ -500,23 +517,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
500
517
  accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex + 2)
501
518
  })
502
519
  })]
503
- }), showPanelNavigation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_StackView.default, {
504
- direction: "row",
505
- tokens: staticTokens.stackView,
506
- children: onRenderPanelNavigation ? onRenderPanelNavigation({
507
- activeIndex,
508
- totalItems: childrenArray.length
509
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_StepTracker.default, {
510
- current: activeIndex,
511
- steps: childrenArray.map((_, index) => String(index)),
512
- copy: {
513
- // Give StepTracker copy from Carousel's language and dictionary
514
- stepLabel: getCopyWithPlaceholders('stepLabel'),
515
- stepTrackerLabel: getCopyWithPlaceholders('stepTrackerLabel')
516
- },
517
- tokens: panelNavigationTokens
518
- })
519
- }) : null]
520
+ }), showPanelNavigation ? panelNavigation : null]
520
521
  });
521
522
  });
522
523
 
@@ -554,6 +555,15 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
554
555
  */
555
556
  springConfig: _propTypes.default.object,
556
557
 
558
+ /**
559
+ * An array of objects containing information on the thumbnails to be rendered as navigation panel
560
+ */
561
+ thumbnails: _propTypes.default.arrayOf(_propTypes.default.shape({
562
+ accessibilityLabel: _propTypes.default.string,
563
+ alt: _propTypes.default.string,
564
+ src: _propTypes.default.string
565
+ })),
566
+
557
567
  /**
558
568
  * Minimal part of slide width must be swiped for changing index.
559
569
  * Otherwise animation restore current slide. Default value 0.2 means that 20% must be swiped for change index
@@ -584,20 +594,35 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
584
594
  onIndexChanged: _propTypes.default.func,
585
595
 
586
596
  /**
587
- * Use this to render a custom panel navigation element instead of dots navigation
588
- * This function is also provided with an object with the following properties
589
- * activeIndex: index of current slide
590
- * totalItems: total number of slides
597
+ * If this is a complex carousel with a lot of focusable content, pass a href for a skip link. Typically, this will be an anchor link
598
+ * with the ID of a focusable element immediately after the Carousel, e.g. `'#section-2-heading'`.
599
+ */
600
+ skipLinkHref: _propTypes.default.string,
601
+
602
+ /**
603
+ * If true, whenever a new slide comes into view, the focus of the Carousel switches to the start.
604
+ *
605
+ * Pass this as true when using carousel items that contain interactive content, so a user can easily tab into that content.
606
+ *
607
+ * If skipLinkHref is passed, the focus target will be the SkipLink; if not, it'll be an empty element before the slide content.
608
+ */
609
+ refocus: _propTypes.default.bool,
610
+
611
+ /**
612
+ * Use this to render a custom panel navigation element instead of the default StepTracker's based navigation
613
+ * You can make use of `useCarousel` within your custom panel navigation component to hook into various Carousel states such as:
614
+ * - activeIndex: index of current slide
615
+ * - totalItems: total number of slides
591
616
  * Use it as follows:
592
617
  * ```js
593
618
  * <Carousel
594
- * onRenderPanelNavigation={({ totalItems, activeIndex }) => <Text>Showing {activeIndex + 1}</Text>}
619
+ * panelNavigation={<CustomPanelNavigation />}
595
620
  * >
596
621
  * <Carousel.Item>First Slide</Carousel.Item>
597
622
  * </Carousel>
598
623
  * ```
599
624
  */
600
- onRenderPanelNavigation: _propTypes.default.func,
625
+ panelNavigation: _propTypes.default.element,
601
626
 
602
627
  /**
603
628
  * When slide animation start
@@ -10,6 +10,8 @@ var _react = _interopRequireDefault(require("react"));
10
10
 
11
11
  var _propTypes = _interopRequireDefault(require("prop-types"));
12
12
 
13
+ var _utils = require("../utils");
14
+
13
15
  var _jsxRuntime = require("react/jsx-runtime");
14
16
 
15
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -18,19 +20,27 @@ const CarouselContext = /*#__PURE__*/_react.default.createContext();
18
20
 
19
21
  const CarouselProvider = _ref => {
20
22
  let {
21
- children,
22
23
  activeIndex,
24
+ children,
25
+ goTo,
26
+ getCopyWithPlaceholders,
27
+ itemLabel,
28
+ refocus = false,
29
+ themeTokens,
23
30
  totalItems,
24
- width,
25
- goTo
31
+ width
26
32
  } = _ref;
27
33
 
28
34
  const value = _react.default.useMemo(() => ({
29
35
  activeIndex,
36
+ goTo,
37
+ getCopyWithPlaceholders,
38
+ itemLabel,
39
+ refocus,
40
+ themeTokens,
30
41
  totalItems,
31
- width,
32
- goTo
33
- }), [activeIndex, totalItems, width, goTo]);
42
+ width
43
+ }), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width]);
34
44
 
35
45
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(CarouselContext.Provider, {
36
46
  value: value,
@@ -53,7 +63,11 @@ function useCarousel() {
53
63
  CarouselProvider.propTypes = {
54
64
  children: _propTypes.default.arrayOf(_propTypes.default.element).isRequired,
55
65
  activeIndex: _propTypes.default.number.isRequired,
66
+ goTo: _propTypes.default.func.isRequired,
67
+ getCopyWithPlaceholders: _propTypes.default.func.isRequired,
68
+ itemLabel: _propTypes.default.string.isRequired,
69
+ refocus: _propTypes.default.bool,
70
+ themeTokens: (0, _utils.getTokensPropType)('Carousel'),
56
71
  totalItems: _propTypes.default.number.isRequired,
57
- width: _propTypes.default.number.isRequired,
58
- goTo: _propTypes.default.func.isRequired
72
+ width: _propTypes.default.number.isRequired
59
73
  };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireWildcard(require("react"));
9
+
10
+ var _Pressable = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Pressable"));
11
+
12
+ var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
13
+
14
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
15
+
16
+ var _propTypes = require("prop-types");
17
+
18
+ var _CarouselContext = require("../CarouselContext");
19
+
20
+ var _jsxRuntime = require("react/jsx-runtime");
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
24
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
25
+
26
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
27
+
28
+ /**
29
+ * Focus target so that when a new slide is shown, the user can tab into
30
+ * its content using the keyboard.
31
+ *
32
+ * @TODO rework this after integrating with SkipLink when available.
33
+ */
34
+ const CarouselFirstFocus = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
35
+ let {
36
+ title
37
+ } = _ref;
38
+ const {
39
+ getCopyWithPlaceholders
40
+ } = (0, _CarouselContext.useCarousel)(); // TODO: integrate skip link description if behaving as skip link.
41
+ // Consider moving this content to aria-live area while only the skip link is focused.
42
+
43
+ const accessibilityLabel = "".concat(title, ", ").concat(getCopyWithPlaceholders('stepTrackerLabel'));
44
+
45
+ const accessibilityRole = _Platform.default.select({
46
+ web: 'link',
47
+ // The focused item will ultimately be a skip link.
48
+ default: 'button' // 'link' role usually denotes opening browser on Native.
49
+
50
+ });
51
+
52
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default // TODO: integrate skip link functionality, jump focus to after Carousel
53
+ , {
54
+ onPress: undefined,
55
+ ref: ref,
56
+ accessibilityLabel: accessibilityLabel,
57
+ accessibilityRole: accessibilityRole,
58
+ style: _StyleSheet.default.absoluteFill,
59
+ focusable: true
60
+ });
61
+ });
62
+ CarouselFirstFocus.displayName = 'CarouselFirstFocus';
63
+ CarouselFirstFocus.propTypes = {
64
+ /**
65
+ * Simple description of this carousel for screenreaders, to be read before
66
+ * "{itemLabel} {index} of {count}.
67
+ *
68
+ * For example, "Summer offers" in "Summer offers, offer 1 of 3"
69
+ */
70
+ title: _propTypes.PropTypes.string
71
+ };
72
+ var _default = CarouselFirstFocus;
73
+ exports.default = _default;