@telus-uds/components-base 1.12.1 → 1.14.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.
- package/CHANGELOG.md +41 -2
- package/component-docs.json +888 -66
- package/lib/Button/ButtonBase.js +36 -7
- package/lib/Button/ButtonGroup.js +7 -0
- package/lib/Button/propTypes.js +18 -0
- package/lib/Carousel/Carousel.js +69 -12
- package/lib/Carousel/CarouselContext.js +17 -11
- package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +73 -0
- package/lib/Carousel/CarouselTabs/CarouselTabs.js +70 -0
- package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +95 -0
- package/lib/Carousel/CarouselTabs/CarouselTabsPanelItem.js +148 -0
- package/lib/Carousel/CarouselTabs/index.js +13 -0
- package/lib/Carousel/CarouselThumbnail.js +99 -0
- package/lib/Carousel/CarouselThumbnailNavigation.js +87 -0
- package/lib/Carousel/dictionary.js +4 -2
- package/lib/Carousel/index.js +10 -1
- package/lib/Checkbox/CheckboxGroup.js +7 -0
- package/lib/Icon/IconText.js +1 -1
- package/lib/Link/InlinePressable.js +1 -8
- package/lib/Link/LinkBase.js +6 -7
- package/lib/List/ListItem.js +1 -1
- package/lib/Notification/Notification.js +37 -22
- package/lib/Radio/RadioGroup.js +8 -0
- package/lib/RadioCard/RadioCardGroup.js +7 -0
- package/lib/SkipLink/SkipLink.js +216 -0
- package/lib/SkipLink/index.js +13 -0
- package/lib/ThemeProvider/ThemeProvider.js +6 -1
- package/lib/ToggleSwitch/ToggleSwitchGroup.js +7 -0
- package/lib/index.js +9 -0
- package/lib-module/Button/ButtonBase.js +35 -7
- package/lib-module/Button/ButtonGroup.js +7 -0
- package/lib-module/Button/propTypes.js +17 -0
- package/lib-module/Carousel/Carousel.js +66 -11
- package/lib-module/Carousel/CarouselContext.js +17 -11
- package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +51 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabs.js +50 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +76 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanelItem.js +126 -0
- package/lib-module/Carousel/CarouselTabs/index.js +2 -0
- package/lib-module/Carousel/CarouselThumbnail.js +85 -0
- package/lib-module/Carousel/CarouselThumbnailNavigation.js +66 -0
- package/lib-module/Carousel/dictionary.js +4 -2
- package/lib-module/Carousel/index.js +2 -1
- package/lib-module/Checkbox/CheckboxGroup.js +7 -0
- package/lib-module/Icon/IconText.js +1 -1
- package/lib-module/Link/InlinePressable.js +1 -8
- package/lib-module/Link/LinkBase.js +6 -7
- package/lib-module/List/ListItem.js +1 -1
- package/lib-module/Notification/Notification.js +38 -23
- package/lib-module/Radio/RadioGroup.js +8 -0
- package/lib-module/RadioCard/RadioCardGroup.js +7 -0
- package/lib-module/SkipLink/SkipLink.js +188 -0
- package/lib-module/SkipLink/index.js +2 -0
- package/lib-module/ThemeProvider/ThemeProvider.js +5 -1
- package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +7 -0
- package/lib-module/index.js +1 -0
- package/package.json +46 -47
- package/src/Button/ButtonBase.jsx +28 -9
- package/src/Button/ButtonGroup.jsx +6 -0
- package/src/Button/propTypes.js +14 -0
- package/src/Carousel/Carousel.jsx +68 -10
- package/src/Carousel/CarouselContext.jsx +22 -9
- package/src/Carousel/CarouselFirstFocus/CarouselFirstFocus.jsx +49 -0
- package/src/Carousel/CarouselTabs/CarouselTabs.jsx +37 -0
- package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +69 -0
- package/src/Carousel/CarouselTabs/CarouselTabsPanelItem.jsx +119 -0
- package/src/Carousel/CarouselTabs/index.js +3 -0
- package/src/Carousel/CarouselThumbnail.jsx +77 -0
- package/src/Carousel/CarouselThumbnailNavigation.jsx +53 -0
- package/src/Carousel/dictionary.js +4 -2
- package/src/Carousel/index.js +1 -0
- package/src/Checkbox/CheckboxGroup.jsx +7 -0
- package/src/Icon/IconText.jsx +1 -1
- package/src/Link/InlinePressable.jsx +2 -8
- package/src/Link/LinkBase.jsx +8 -17
- package/src/List/ListItem.jsx +1 -1
- package/src/Notification/Notification.jsx +35 -20
- package/src/Radio/RadioGroup.jsx +7 -0
- package/src/RadioCard/RadioCardGroup.jsx +6 -0
- package/src/SkipLink/SkipLink.jsx +179 -0
- package/src/SkipLink/index.js +3 -0
- package/src/ThemeProvider/ThemeProvider.jsx +7 -1
- package/src/ToggleSwitch/ToggleSwitchGroup.jsx +6 -0
- package/src/index.js +1 -0
|
@@ -92,6 +92,7 @@ const RadioCardGroup = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
|
92
92
|
legend,
|
|
93
93
|
tooltip,
|
|
94
94
|
hint,
|
|
95
|
+
hintPosition = 'inline',
|
|
95
96
|
validation,
|
|
96
97
|
feedback,
|
|
97
98
|
initialCheckedId,
|
|
@@ -136,6 +137,7 @@ const RadioCardGroup = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
|
136
137
|
legend: legend,
|
|
137
138
|
tooltip: tooltip,
|
|
138
139
|
hint: hint,
|
|
140
|
+
hintPosition: hintPosition,
|
|
139
141
|
space: fieldSpace,
|
|
140
142
|
feedback: feedback,
|
|
141
143
|
inactive: inactive || readOnly,
|
|
@@ -221,6 +223,11 @@ RadioCardGroup.propTypes = { ...selectedSystemPropTypes,
|
|
|
221
223
|
*/
|
|
222
224
|
hint: _propTypes.default.string,
|
|
223
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
228
|
+
*/
|
|
229
|
+
hintPosition: _propTypes.default.oneOf(['inline', 'below']),
|
|
230
|
+
|
|
224
231
|
/**
|
|
225
232
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
226
233
|
*/
|
|
@@ -0,0 +1,216 @@
|
|
|
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 _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
|
|
11
|
+
|
|
12
|
+
var _Pressable = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Pressable"));
|
|
13
|
+
|
|
14
|
+
var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
|
|
15
|
+
|
|
16
|
+
var _Text = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Text"));
|
|
17
|
+
|
|
18
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
19
|
+
|
|
20
|
+
var _ThemeProvider = require("../ThemeProvider");
|
|
21
|
+
|
|
22
|
+
var _utils = require("../utils");
|
|
23
|
+
|
|
24
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
|
+
|
|
26
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
|
+
|
|
28
|
+
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); }
|
|
29
|
+
|
|
30
|
+
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; }
|
|
31
|
+
|
|
32
|
+
const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.linkProps]); // ensure explicit selection of tokens
|
|
33
|
+
|
|
34
|
+
const selectStyles = _ref => {
|
|
35
|
+
let {
|
|
36
|
+
backgroundColor,
|
|
37
|
+
outlineColor,
|
|
38
|
+
outlineOffset,
|
|
39
|
+
outlineStyle,
|
|
40
|
+
outlineWidth,
|
|
41
|
+
paddingHorizontal,
|
|
42
|
+
paddingVertical,
|
|
43
|
+
borderRadius
|
|
44
|
+
} = _ref;
|
|
45
|
+
return {
|
|
46
|
+
backgroundColor,
|
|
47
|
+
outlineColor,
|
|
48
|
+
outlineOffset,
|
|
49
|
+
outlineStyle,
|
|
50
|
+
outlineWidth,
|
|
51
|
+
paddingHorizontal,
|
|
52
|
+
paddingVertical,
|
|
53
|
+
borderRadius
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const selectTextStyles = _ref2 => {
|
|
58
|
+
let {
|
|
59
|
+
color
|
|
60
|
+
} = _ref2;
|
|
61
|
+
return {
|
|
62
|
+
color
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* A generic Skip link component, unstyled by default.
|
|
67
|
+
* A Skip link component help keyboard-only users, screen reader users to skip
|
|
68
|
+
* sections and navigate to the content they want.
|
|
69
|
+
*
|
|
70
|
+
* ## Component API
|
|
71
|
+
*
|
|
72
|
+
* For common uses, pass a `href` that is a # link to a DOM id that can be skipped to (web only).
|
|
73
|
+
*
|
|
74
|
+
* The element with this ID should be focusable, e.g. `<Box nativeID="skip-target" focusable>`.
|
|
75
|
+
*
|
|
76
|
+
* Other custom behaviour may be set by passing an `onPress` function, and routers may be integrated
|
|
77
|
+
* in the same way as other navigation-related components by passing a `LinkRouter`; but a # anchor
|
|
78
|
+
* href on web and/or a `targetRef` for cross-platform applications is the recommended approach.
|
|
79
|
+
*
|
|
80
|
+
* ## Visible styling
|
|
81
|
+
*
|
|
82
|
+
* When focused, the skip link shows as a visible element similar to a simplified ButtonLink using
|
|
83
|
+
* UDS theming. The `tokens` prop may be used to override these styles.
|
|
84
|
+
*
|
|
85
|
+
* To control the background of a skip link, the following tokens can be used:
|
|
86
|
+
*
|
|
87
|
+
* - `backgroundColor`
|
|
88
|
+
* *
|
|
89
|
+
* In order to control the color of the skip link text, the following tokens can be used:
|
|
90
|
+
*
|
|
91
|
+
* - `color`
|
|
92
|
+
*
|
|
93
|
+
* ### Padding
|
|
94
|
+
*
|
|
95
|
+
* The following padding tokens can be used:
|
|
96
|
+
*
|
|
97
|
+
* - `paddingHorizontal`
|
|
98
|
+
* - `paddingVertical`
|
|
99
|
+
*
|
|
100
|
+
* ### Outline
|
|
101
|
+
*
|
|
102
|
+
* The following tokens to control the outline:
|
|
103
|
+
*
|
|
104
|
+
* - `outlineColor`
|
|
105
|
+
* - `outlineOffset`
|
|
106
|
+
* - `outlineStyle`
|
|
107
|
+
* - `outlineWidth`
|
|
108
|
+
*
|
|
109
|
+
* ## Usability and A11y guidelines
|
|
110
|
+
*
|
|
111
|
+
* - The skip link component is visually hidden until a keyboard press activates it.
|
|
112
|
+
* - Usually, you should place the skip link immediately after the opening <body> tag.
|
|
113
|
+
* - This lets users bypass top-level navigation links and jump to the main content on a page.
|
|
114
|
+
* - Also consider using SkipLink before a complex feature containing many focusable elements.
|
|
115
|
+
*
|
|
116
|
+
* ## Accessibility
|
|
117
|
+
*
|
|
118
|
+
* Skip link supports all the common a11y and link props.
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
const SkipLink = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
|
|
123
|
+
let {
|
|
124
|
+
tokens,
|
|
125
|
+
variant,
|
|
126
|
+
href,
|
|
127
|
+
children,
|
|
128
|
+
...rawRest
|
|
129
|
+
} = _ref3;
|
|
130
|
+
|
|
131
|
+
const {
|
|
132
|
+
onPress,
|
|
133
|
+
...rest
|
|
134
|
+
} = _utils.clickProps.toPressProps(rawRest);
|
|
135
|
+
|
|
136
|
+
const getTokens = (0, _ThemeProvider.useThemeTokensCallback)('SkipLink', tokens, variant);
|
|
137
|
+
const defaultTokens = getTokens();
|
|
138
|
+
|
|
139
|
+
const resolveLinkTokens = pressState => (0, _utils.resolvePressableTokens)(defaultTokens, pressState);
|
|
140
|
+
|
|
141
|
+
const handlePress = event => {
|
|
142
|
+
if (typeof onPress === 'function') onPress(event); // TODO - support native apps with something based on refs and/or setAccessibilityFocus
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pressable.default, {
|
|
146
|
+
ref: ref,
|
|
147
|
+
accessibilityRole: "link",
|
|
148
|
+
onPress: handlePress,
|
|
149
|
+
href: href,
|
|
150
|
+
style: _ref4 => {
|
|
151
|
+
let {
|
|
152
|
+
focused: focus
|
|
153
|
+
} = _ref4;
|
|
154
|
+
const themeTokens = getTokens({
|
|
155
|
+
focus
|
|
156
|
+
});
|
|
157
|
+
const skipLinkStyle = selectStyles(themeTokens);
|
|
158
|
+
return [staticStyles.absolute, skipLinkStyle, !focus && staticStyles.hidden];
|
|
159
|
+
},
|
|
160
|
+
...selectProps(rest),
|
|
161
|
+
children: pressState => {
|
|
162
|
+
const themeTokens = resolveLinkTokens(pressState);
|
|
163
|
+
const textStyles = selectTextStyles(themeTokens);
|
|
164
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
|
|
165
|
+
style: [textStyles, staticStyles.baseline],
|
|
166
|
+
children: children
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
SkipLink.displayName = 'SkipLink';
|
|
172
|
+
SkipLink.propTypes = { ...selectedSystemPropTypes,
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* The text content shown or read out when the SkipLink is focused, usually a string.
|
|
176
|
+
*/
|
|
177
|
+
children: _propTypes.default.node,
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* The target to skip to. Usually an anchor link to a section id (e.g. href="#main-section").
|
|
181
|
+
*/
|
|
182
|
+
href: _propTypes.default.string,
|
|
183
|
+
tokens: (0, _utils.getTokensPropType)('SkipLink'),
|
|
184
|
+
variant: _utils.variantProp.propType
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const staticStyles = _StyleSheet.default.create({
|
|
188
|
+
baseline: {
|
|
189
|
+
alignSelf: 'baseline'
|
|
190
|
+
},
|
|
191
|
+
absolute: {
|
|
192
|
+
margin: 0,
|
|
193
|
+
position: 'absolute',
|
|
194
|
+
top: 0,
|
|
195
|
+
left: 0
|
|
196
|
+
},
|
|
197
|
+
hidden: {
|
|
198
|
+
overflow: 'hidden',
|
|
199
|
+
..._Platform.default.select({
|
|
200
|
+
web: {
|
|
201
|
+
clip: 'rect(0 0 0 0)',
|
|
202
|
+
clipPath: 'inset(50%)'
|
|
203
|
+
},
|
|
204
|
+
default: {
|
|
205
|
+
// width / height of 0 would make it non-focusable
|
|
206
|
+
height: 1,
|
|
207
|
+
width: 1,
|
|
208
|
+
opacity: 0
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
var _default = (0, _utils.withLinkRouter)(SkipLink);
|
|
215
|
+
|
|
216
|
+
exports.default = _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _SkipLink = _interopRequireDefault(require("./SkipLink"));
|
|
9
|
+
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
|
|
12
|
+
var _default = _SkipLink.default;
|
|
13
|
+
exports.default = _default;
|
|
@@ -11,6 +11,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
11
11
|
|
|
12
12
|
var _utils = require("./utils");
|
|
13
13
|
|
|
14
|
+
var _responsiveProps = _interopRequireDefault(require("../utils/props/responsiveProps"));
|
|
15
|
+
|
|
14
16
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
17
|
|
|
16
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -65,9 +67,12 @@ ThemeProvider.propTypes = {
|
|
|
65
67
|
* - `forceAbsoluteFontSizing`: available on web only; when set to true, allows
|
|
66
68
|
* using absolute font sizing (in pixels, doesn't scale) instead of the
|
|
67
69
|
* relative sizing (in `rem`, scales depending on the browser settings)
|
|
70
|
+
* - `contentMaxWidth`: allows configuration of the content max width to be used in components
|
|
71
|
+
* such as Footnote and Notification to avoid content to stretch width more then the page's width
|
|
68
72
|
*/
|
|
69
73
|
themeOptions: _propTypes.default.shape({
|
|
70
|
-
forceAbsoluteFontSizing: _propTypes.default.bool
|
|
74
|
+
forceAbsoluteFontSizing: _propTypes.default.bool,
|
|
75
|
+
contentMaxWidth: _responsiveProps.default.getTypeOptionallyByViewport(_propTypes.default.number)
|
|
71
76
|
})
|
|
72
77
|
};
|
|
73
78
|
var _default = ThemeProvider;
|
|
@@ -49,6 +49,7 @@ const ToggleSwitchGroup = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
|
49
49
|
inactive = false,
|
|
50
50
|
feedback,
|
|
51
51
|
hint,
|
|
52
|
+
hintPosition = 'inline',
|
|
52
53
|
tooltip,
|
|
53
54
|
legend,
|
|
54
55
|
name: inputGroupName,
|
|
@@ -134,6 +135,7 @@ const ToggleSwitchGroup = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
|
134
135
|
legend: legend,
|
|
135
136
|
tooltip: tooltip,
|
|
136
137
|
hint: hint,
|
|
138
|
+
hintPosition: hintPosition,
|
|
137
139
|
space: fieldSpace,
|
|
138
140
|
feedback: feedback,
|
|
139
141
|
inactive: inactive,
|
|
@@ -216,6 +218,11 @@ ToggleSwitchGroup.propTypes = { ...selectedSystemPropTypes,
|
|
|
216
218
|
*/
|
|
217
219
|
hint: _propTypes.default.string,
|
|
218
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
223
|
+
*/
|
|
224
|
+
hintPosition: _propTypes.default.oneOf(['inline', 'below']),
|
|
225
|
+
|
|
219
226
|
/**
|
|
220
227
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
221
228
|
*/
|
package/lib/index.js
CHANGED
|
@@ -34,6 +34,7 @@ var _exportNames = {
|
|
|
34
34
|
Select: true,
|
|
35
35
|
SideNav: true,
|
|
36
36
|
Skeleton: true,
|
|
37
|
+
SkipLink: true,
|
|
37
38
|
Spacer: true,
|
|
38
39
|
StackView: true,
|
|
39
40
|
StepTracker: true,
|
|
@@ -249,6 +250,12 @@ Object.defineProperty(exports, "Skeleton", {
|
|
|
249
250
|
return _Skeleton.default;
|
|
250
251
|
}
|
|
251
252
|
});
|
|
253
|
+
Object.defineProperty(exports, "SkipLink", {
|
|
254
|
+
enumerable: true,
|
|
255
|
+
get: function () {
|
|
256
|
+
return _SkipLink.default;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
252
259
|
Object.defineProperty(exports, "Spacer", {
|
|
253
260
|
enumerable: true,
|
|
254
261
|
get: function () {
|
|
@@ -524,6 +531,8 @@ var _SideNav = _interopRequireDefault(require("./SideNav"));
|
|
|
524
531
|
|
|
525
532
|
var _Skeleton = _interopRequireDefault(require("./Skeleton"));
|
|
526
533
|
|
|
534
|
+
var _SkipLink = _interopRequireDefault(require("./SkipLink"));
|
|
535
|
+
|
|
527
536
|
var _Spacer = _interopRequireDefault(require("./Spacer"));
|
|
528
537
|
|
|
529
538
|
var _StackView = _interopRequireWildcard(require("./StackView"));
|
|
@@ -7,6 +7,7 @@ import Platform from "react-native-web/dist/exports/Platform";
|
|
|
7
7
|
import { applyTextStyles, applyShadowToken, applyOuterBorder, useTheme } from '../ThemeProvider';
|
|
8
8
|
import buttonPropTypes from './propTypes';
|
|
9
9
|
import { a11yProps, clickProps, focusHandlerProps, getCursorStyle, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, viewProps, wrapStringsInText, withLinkRouter } from '../utils';
|
|
10
|
+
import { IconText } from '../Icon';
|
|
10
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, linkProps, viewProps]);
|
|
12
13
|
|
|
@@ -167,7 +168,18 @@ const selectWebOnlyStyles = (inactive, themeTokens, _ref7) => {
|
|
|
167
168
|
});
|
|
168
169
|
};
|
|
169
170
|
|
|
170
|
-
const
|
|
171
|
+
const selectItemIconTokens = _ref8 => {
|
|
172
|
+
let {
|
|
173
|
+
color,
|
|
174
|
+
iconSize
|
|
175
|
+
} = _ref8;
|
|
176
|
+
return {
|
|
177
|
+
size: iconSize,
|
|
178
|
+
color
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const ButtonBase = /*#__PURE__*/forwardRef((_ref9, ref) => {
|
|
171
183
|
let {
|
|
172
184
|
id,
|
|
173
185
|
href,
|
|
@@ -178,8 +190,11 @@ const ButtonBase = /*#__PURE__*/forwardRef((_ref8, ref) => {
|
|
|
178
190
|
// alias for inactive
|
|
179
191
|
inactive = disabled,
|
|
180
192
|
selected = false,
|
|
193
|
+
icon,
|
|
194
|
+
iconPosition = icon ? 'left' : undefined,
|
|
195
|
+
iconProps,
|
|
181
196
|
...rawRest
|
|
182
|
-
} =
|
|
197
|
+
} = _ref9;
|
|
183
198
|
const {
|
|
184
199
|
onPress,
|
|
185
200
|
...rest
|
|
@@ -216,10 +231,15 @@ const ButtonBase = /*#__PURE__*/forwardRef((_ref8, ref) => {
|
|
|
216
231
|
const themeTokens = resolveButtonTokens(pressableState);
|
|
217
232
|
const containerStyles = selectInnerContainerStyles(themeTokens);
|
|
218
233
|
const borderStyles = selectBorderStyles(themeTokens);
|
|
219
|
-
const textStyles = [selectTextStyles(themeTokens, themeOptions), staticStyles.text];
|
|
234
|
+
const textStyles = [selectTextStyles(themeTokens, themeOptions), staticStyles.text];
|
|
235
|
+
const iconTokens = selectItemIconTokens(themeTokens);
|
|
236
|
+
const {
|
|
237
|
+
iconSpace
|
|
238
|
+
} = themeTokens; // If the container has a width set, fill it instead of sizing from content.
|
|
220
239
|
// If in future we support text alignments other than center, add here.
|
|
221
240
|
|
|
222
241
|
const stretchStyles = themeTokens.width ? staticStyles.stretch : staticStyles.align;
|
|
242
|
+
const IconComponent = icon || themeTokens.icon;
|
|
223
243
|
return /*#__PURE__*/_jsx(View, {
|
|
224
244
|
id: id,
|
|
225
245
|
style: [containerStyles, borderStyles, stretchStyles, staticStyles.row, Platform.select({
|
|
@@ -230,10 +250,18 @@ const ButtonBase = /*#__PURE__*/forwardRef((_ref8, ref) => {
|
|
|
230
250
|
transition: 'background-color 200ms, border-color 200ms'
|
|
231
251
|
}
|
|
232
252
|
})],
|
|
233
|
-
children:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
253
|
+
children: /*#__PURE__*/_jsx(IconText, {
|
|
254
|
+
icon: IconComponent,
|
|
255
|
+
iconPosition: iconPosition,
|
|
256
|
+
space: iconSpace,
|
|
257
|
+
iconProps: { ...iconProps,
|
|
258
|
+
tokens: iconTokens
|
|
259
|
+
},
|
|
260
|
+
children: wrapStringsInText(typeof children === 'function' ? children({ ...resolvePressableState(pressableState, extraButtonState),
|
|
261
|
+
textStyles
|
|
262
|
+
}) : children, {
|
|
263
|
+
style: textStyles
|
|
264
|
+
})
|
|
237
265
|
})
|
|
238
266
|
});
|
|
239
267
|
}
|
|
@@ -26,6 +26,7 @@ const ButtonGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
|
26
26
|
legend,
|
|
27
27
|
tooltip,
|
|
28
28
|
hint,
|
|
29
|
+
hintPosition = 'inline',
|
|
29
30
|
validation,
|
|
30
31
|
feedback,
|
|
31
32
|
name: inputGroupName,
|
|
@@ -77,6 +78,7 @@ const ButtonGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
|
77
78
|
legend: legend,
|
|
78
79
|
tooltip: tooltip,
|
|
79
80
|
hint: hint,
|
|
81
|
+
hintPosition: hintPosition,
|
|
80
82
|
space: fieldSpace,
|
|
81
83
|
feedback: feedback,
|
|
82
84
|
readOnly: readOnly,
|
|
@@ -208,6 +210,11 @@ ButtonGroup.propTypes = { ...selectedSystemPropTypes,
|
|
|
208
210
|
*/
|
|
209
211
|
hint: PropTypes.string,
|
|
210
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
215
|
+
*/
|
|
216
|
+
hintPosition: PropTypes.oneOf(['inline', 'below']),
|
|
217
|
+
|
|
211
218
|
/**
|
|
212
219
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
213
220
|
*/
|
|
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
|
|
2
2
|
import ABBPropTypes from 'airbnb-prop-types';
|
|
3
3
|
import { variantProp, getTokensPropType } from '../utils/props';
|
|
4
4
|
import A11yText from '../A11yText';
|
|
5
|
+
import { iconComponentPropTypes } from '../Icon';
|
|
5
6
|
export const textAndA11yText = ABBPropTypes.childrenOf(PropTypes.oneOfType([ABBPropTypes.elementType(A11yText), PropTypes.string]));
|
|
6
7
|
const buttonPropTypes = {
|
|
7
8
|
tokens: getTokensPropType('Button'),
|
|
@@ -31,6 +32,22 @@ const buttonPropTypes = {
|
|
|
31
32
|
* Function called when the button is pressed. Required unless the button has a href.
|
|
32
33
|
*/
|
|
33
34
|
onPress: PropTypes.func,
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Optional variant that may be passed down to the link's icon if there is one
|
|
38
|
+
*/
|
|
39
|
+
iconProps: PropTypes.exact(iconComponentPropTypes),
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* When `icon` is provided, use `iconPosition` to place the Icon to the left or right side of the button.
|
|
43
|
+
*/
|
|
44
|
+
iconPosition: PropTypes.oneOf(['left', 'right']),
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A function component for an SVG icon to render inside the link. Inherits size and color from
|
|
48
|
+
* the link and any Typography the link is nested inside.
|
|
49
|
+
*/
|
|
50
|
+
icon: PropTypes.func,
|
|
34
51
|
variant: variantProp.propType
|
|
35
52
|
};
|
|
36
53
|
export default buttonPropTypes;
|
|
@@ -7,12 +7,15 @@ import Platform from "react-native-web/dist/exports/Platform";
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { useThemeTokens } from '../ThemeProvider';
|
|
9
9
|
import { useViewport } from '../ViewportProvider';
|
|
10
|
-
import { getTokensPropType, getA11yPropsFromHtmlTag, layoutTags, variantProp, selectSystemProps, a11yProps, viewProps, useCopy } from '../utils';
|
|
10
|
+
import { getTokensPropType, getA11yPropsFromHtmlTag, layoutTags, variantProp, selectSystemProps, a11yProps, viewProps, useCopy, unpackFragment } from '../utils';
|
|
11
11
|
import { useA11yInfo } from '../A11yInfoProvider';
|
|
12
12
|
import { CarouselProvider } from './CarouselContext';
|
|
13
13
|
import CarouselItem from './CarouselItem';
|
|
14
14
|
import IconButton from '../IconButton';
|
|
15
|
-
import
|
|
15
|
+
import SkipLink from '../SkipLink';
|
|
16
|
+
import A11yText from '../A11yText';
|
|
17
|
+
import CarouselStepTracker from './CarouselStepTracker';
|
|
18
|
+
import CarouselThumbnailNavigation from './CarouselThumbnailNavigation';
|
|
16
19
|
import dictionary from './dictionary';
|
|
17
20
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
21
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -134,11 +137,18 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
134
137
|
onAnimationStart,
|
|
135
138
|
onAnimationEnd,
|
|
136
139
|
onIndexChanged,
|
|
140
|
+
skipLinkHref,
|
|
141
|
+
refocus,
|
|
142
|
+
title = 'carousel',
|
|
137
143
|
springConfig = undefined,
|
|
138
|
-
|
|
144
|
+
thumbnails = undefined,
|
|
145
|
+
panelNavigation = thumbnails ? /*#__PURE__*/_jsx(CarouselThumbnailNavigation, {
|
|
146
|
+
thumbnails: thumbnails
|
|
147
|
+
}) : /*#__PURE__*/_jsx(CarouselStepTracker, {}),
|
|
139
148
|
tag = 'ul',
|
|
140
|
-
accessibilityRole
|
|
141
|
-
accessibilityLabel =
|
|
149
|
+
accessibilityRole,
|
|
150
|
+
accessibilityLabel = title,
|
|
151
|
+
accessibilityLiveRegion = 'polite',
|
|
142
152
|
copy,
|
|
143
153
|
...rest
|
|
144
154
|
} = _ref;
|
|
@@ -167,7 +177,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
167
177
|
dictionary,
|
|
168
178
|
copy
|
|
169
179
|
});
|
|
170
|
-
const childrenArray =
|
|
180
|
+
const childrenArray = unpackFragment(children);
|
|
171
181
|
const systemProps = selectProps({ ...rest,
|
|
172
182
|
accessibilityRole,
|
|
173
183
|
accessibilityLabel,
|
|
@@ -186,6 +196,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
186
196
|
width: 0
|
|
187
197
|
});
|
|
188
198
|
const [previousNextNavigationButtonWidth, setPreviousNextNavigationButtonWidth] = React.useState(0);
|
|
199
|
+
const firstFocusRef = React.useRef(null);
|
|
189
200
|
const pan = React.useRef(new Animated.ValueXY()).current;
|
|
190
201
|
const animatedX = React.useRef(0);
|
|
191
202
|
const animatedY = React.useRef(0);
|
|
@@ -285,10 +296,13 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
285
296
|
return calcDelta;
|
|
286
297
|
}, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged]);
|
|
287
298
|
const fixOffsetAndGo = React.useCallback(delta => {
|
|
299
|
+
var _firstFocusRef$curren;
|
|
300
|
+
|
|
288
301
|
updateOffset();
|
|
289
302
|
handleAnimationStart(activeIndex);
|
|
290
303
|
updateIndex(delta);
|
|
291
|
-
|
|
304
|
+
if (refocus) (_firstFocusRef$curren = firstFocusRef.current) === null || _firstFocusRef$curren === void 0 ? void 0 : _firstFocusRef$curren.focus();
|
|
305
|
+
}, [updateIndex, updateOffset, activeIndex, handleAnimationStart, refocus]);
|
|
292
306
|
const goToNeighboring = React.useCallback(function () {
|
|
293
307
|
let toPrev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
294
308
|
fixOffsetAndGo(toPrev ? -1 : 1);
|
|
@@ -371,17 +385,20 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
371
385
|
raised: true
|
|
372
386
|
};
|
|
373
387
|
const getCopyWithPlaceholders = React.useCallback(copyKey => {
|
|
374
|
-
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
|
|
388
|
+
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
|
|
375
389
|
|
|
376
390
|
return "".concat(copyText[0].toUpperCase()).concat(copyText.slice(1));
|
|
377
|
-
}, [activeIndex, childrenArray.length, itemLabel, getCopy]);
|
|
391
|
+
}, [activeIndex, childrenArray.length, itemLabel, getCopy, title]);
|
|
378
392
|
return /*#__PURE__*/_jsxs(CarouselProvider, {
|
|
379
393
|
activeIndex: activeIndex,
|
|
380
|
-
totalItems: childrenArray.length,
|
|
381
|
-
width: containerLayout.width,
|
|
382
394
|
goTo: goTo,
|
|
383
395
|
getCopyWithPlaceholders: getCopyWithPlaceholders,
|
|
396
|
+
itemLabel: itemLabel,
|
|
397
|
+
totalItems: childrenArray.length,
|
|
384
398
|
themeTokens: themeTokens,
|
|
399
|
+
firstFocusRef: firstFocusRef,
|
|
400
|
+
refocus: refocus,
|
|
401
|
+
width: containerLayout.width,
|
|
385
402
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
386
403
|
style: staticStyles.root,
|
|
387
404
|
onLayout: onContainerLayout,
|
|
@@ -397,6 +414,17 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
397
414
|
variant: previousNextIconButtonVariants,
|
|
398
415
|
accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex)
|
|
399
416
|
})
|
|
417
|
+
}), Boolean(skipLinkHref) && /*#__PURE__*/_jsx(SkipLink, {
|
|
418
|
+
ref: firstFocusRef,
|
|
419
|
+
href: skipLinkHref,
|
|
420
|
+
children: getCopyWithPlaceholders('skipLink')
|
|
421
|
+
}), /*#__PURE__*/_jsx(A11yText // Read the current slide position to screen readers on slide.
|
|
422
|
+
// If it's set to refocus and doesn't have a SkipLink to focus to, focus this.
|
|
423
|
+
, {
|
|
424
|
+
ref: !skipLinkHref && refocus ? firstFocusRef : null,
|
|
425
|
+
accessibilityLiveRegion: !skipLinkHref && refocus ? undefined : 'polite',
|
|
426
|
+
focusable: !skipLinkHref && refocus,
|
|
427
|
+
text: getCopyWithPlaceholders('stepTrackerLabel')
|
|
400
428
|
}), /*#__PURE__*/_jsx(View, {
|
|
401
429
|
style: selectContainerStyles(containerLayout.width),
|
|
402
430
|
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
@@ -409,6 +437,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
409
437
|
}]),
|
|
410
438
|
...panResponder.panHandlers,
|
|
411
439
|
...getA11yPropsFromHtmlTag(tag),
|
|
440
|
+
// In iframes on Mac (e.g. in Storybook), this content may be misread or read twice.
|
|
441
|
+
// This is a known Voiceover bug: https://github.com/phetsims/a11y-research/issues/132
|
|
442
|
+
accessibilityLiveRegion: accessibilityLiveRegion,
|
|
412
443
|
children: childrenArray.map((element, index) => {
|
|
413
444
|
const hidden = !isAnimating && index !== activeIndex;
|
|
414
445
|
const clonedElement = /*#__PURE__*/React.cloneElement(element, {
|
|
@@ -468,6 +499,15 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
|
|
|
468
499
|
*/
|
|
469
500
|
springConfig: PropTypes.object,
|
|
470
501
|
|
|
502
|
+
/**
|
|
503
|
+
* An array of objects containing information on the thumbnails to be rendered as navigation panel
|
|
504
|
+
*/
|
|
505
|
+
thumbnails: PropTypes.arrayOf(PropTypes.shape({
|
|
506
|
+
accessibilityLabel: PropTypes.string,
|
|
507
|
+
alt: PropTypes.string,
|
|
508
|
+
src: PropTypes.string
|
|
509
|
+
})),
|
|
510
|
+
|
|
471
511
|
/**
|
|
472
512
|
* Minimal part of slide width must be swiped for changing index.
|
|
473
513
|
* Otherwise animation restore current slide. Default value 0.2 means that 20% must be swiped for change index
|
|
@@ -497,6 +537,21 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
|
|
|
497
537
|
*/
|
|
498
538
|
onIndexChanged: PropTypes.func,
|
|
499
539
|
|
|
540
|
+
/**
|
|
541
|
+
* 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
|
|
542
|
+
* with the ID of a focusable element immediately after the Carousel, e.g. `'#section-2-heading'`.
|
|
543
|
+
*/
|
|
544
|
+
skipLinkHref: PropTypes.string,
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* If true, whenever a new slide comes into view, the focus of the Carousel switches to the start.
|
|
548
|
+
*
|
|
549
|
+
* Pass this as true when using carousel items that contain interactive content, so a user can easily tab into that content.
|
|
550
|
+
*
|
|
551
|
+
* If skipLinkHref is passed, the focus target will be the SkipLink; if not, it'll be an empty element before the slide content.
|
|
552
|
+
*/
|
|
553
|
+
refocus: PropTypes.bool,
|
|
554
|
+
|
|
500
555
|
/**
|
|
501
556
|
* Use this to render a custom panel navigation element instead of the default StepTracker's based navigation
|
|
502
557
|
* You can make use of `useCarousel` within your custom panel navigation component to hook into various Carousel states such as:
|