@telus-uds/components-base 1.10.0 → 1.12.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 +37 -3
- package/component-docs.json +413 -62
- package/lib/BaseProvider/index.js +7 -2
- package/lib/Button/ButtonBase.js +18 -14
- package/lib/Carousel/Carousel.js +92 -71
- package/lib/Carousel/CarouselContext.js +12 -4
- package/lib/Carousel/CarouselItem/CarouselItem.js +24 -9
- package/lib/Carousel/CarouselStepTracker/CarouselStepTracker.js +56 -0
- package/lib/Carousel/CarouselStepTracker/index.js +13 -0
- package/lib/Carousel/dictionary.js +23 -0
- package/lib/Checkbox/Checkbox.js +7 -3
- package/lib/Checkbox/CheckboxGroup.js +1 -1
- package/lib/Feedback/Feedback.js +18 -10
- package/lib/Icon/IconText.js +5 -0
- package/lib/InputLabel/InputLabel.js +11 -5
- package/lib/InputSupports/InputSupports.js +10 -3
- package/lib/InputSupports/useInputSupports.js +3 -2
- package/lib/Link/LinkBase.js +7 -3
- package/lib/List/ListItem.js +7 -3
- package/lib/Modal/Modal.js +4 -0
- package/lib/Notification/Notification.js +7 -2
- package/lib/Pagination/Pagination.js +7 -3
- package/lib/RadioCard/RadioCard.js +6 -1
- package/lib/Select/Select.js +7 -3
- package/lib/Skeleton/Skeleton.js +1 -0
- package/lib/StepTracker/Step.js +8 -4
- package/lib/StepTracker/StepTracker.js +17 -13
- package/lib/Tabs/TabsItem.js +4 -0
- package/lib/TextInput/TextInput.js +3 -1
- package/lib/TextInput/TextInputBase.js +7 -3
- package/lib/ThemeProvider/ThemeProvider.js +20 -3
- package/lib/ThemeProvider/utils/styles.js +8 -1
- package/lib/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib/Typography/Typography.js +6 -2
- package/lib/index.js +9 -0
- package/lib/utils/index.js +9 -0
- package/lib/utils/props/clickProps.js +2 -2
- package/lib/utils/props/handlerProps.js +77 -31
- package/lib/utils/useScrollBlocking.js +66 -0
- package/lib/utils/useScrollBlocking.native.js +11 -0
- package/lib-module/BaseProvider/index.js +7 -2
- package/lib-module/Button/ButtonBase.js +7 -3
- package/lib-module/Carousel/Carousel.js +85 -70
- package/lib-module/Carousel/CarouselContext.js +11 -4
- package/lib-module/Carousel/CarouselItem/CarouselItem.js +25 -10
- package/lib-module/Carousel/CarouselStepTracker/CarouselStepTracker.js +42 -0
- package/lib-module/Carousel/CarouselStepTracker/index.js +2 -0
- package/lib-module/Carousel/dictionary.js +16 -0
- package/lib-module/Checkbox/Checkbox.js +8 -4
- package/lib-module/Checkbox/CheckboxGroup.js +1 -1
- package/lib-module/Feedback/Feedback.js +19 -11
- package/lib-module/Icon/IconText.js +5 -0
- package/lib-module/InputLabel/InputLabel.js +12 -6
- package/lib-module/InputSupports/InputSupports.js +10 -3
- package/lib-module/InputSupports/useInputSupports.js +3 -2
- package/lib-module/Link/LinkBase.js +8 -4
- package/lib-module/List/ListItem.js +8 -4
- package/lib-module/Modal/Modal.js +3 -0
- package/lib-module/Notification/Notification.js +8 -3
- package/lib-module/Pagination/Pagination.js +8 -4
- package/lib-module/RadioCard/RadioCard.js +7 -2
- package/lib-module/Select/Select.js +8 -4
- package/lib-module/Skeleton/Skeleton.js +1 -0
- package/lib-module/StepTracker/Step.js +9 -5
- package/lib-module/StepTracker/StepTracker.js +17 -14
- package/lib-module/Tabs/TabsItem.js +5 -1
- package/lib-module/TextInput/TextInput.js +3 -1
- package/lib-module/TextInput/TextInputBase.js +8 -4
- package/lib-module/ThemeProvider/ThemeProvider.js +20 -3
- package/lib-module/ThemeProvider/utils/styles.js +8 -1
- package/lib-module/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib-module/Typography/Typography.js +7 -3
- package/lib-module/index.js +1 -0
- package/lib-module/utils/index.js +1 -0
- package/lib-module/utils/props/clickProps.js +2 -2
- package/lib-module/utils/props/handlerProps.js +78 -31
- package/lib-module/utils/useScrollBlocking.js +58 -0
- package/lib-module/utils/useScrollBlocking.native.js +2 -0
- package/package.json +3 -3
- package/src/BaseProvider/index.jsx +6 -3
- package/src/Button/ButtonBase.jsx +8 -3
- package/src/Carousel/Carousel.jsx +106 -74
- package/src/Carousel/CarouselContext.jsx +15 -4
- package/src/Carousel/CarouselItem/CarouselItem.jsx +26 -8
- package/src/Carousel/CarouselStepTracker/CarouselStepTracker.jsx +36 -0
- package/src/Carousel/CarouselStepTracker/index.js +3 -0
- package/src/Carousel/dictionary.js +16 -0
- package/src/Checkbox/Checkbox.jsx +14 -11
- package/src/Checkbox/CheckboxGroup.jsx +1 -1
- package/src/Feedback/Feedback.jsx +14 -7
- package/src/Icon/IconText.jsx +2 -0
- package/src/InputLabel/InputLabel.jsx +13 -12
- package/src/InputSupports/InputSupports.jsx +18 -3
- package/src/InputSupports/useInputSupports.js +2 -2
- package/src/Link/LinkBase.jsx +10 -4
- package/src/List/ListItem.jsx +9 -4
- package/src/Modal/Modal.jsx +3 -1
- package/src/Notification/Notification.jsx +5 -3
- package/src/Pagination/Pagination.jsx +6 -4
- package/src/RadioCard/RadioCard.jsx +3 -2
- package/src/Select/Select.jsx +12 -3
- package/src/Skeleton/Skeleton.jsx +1 -0
- package/src/StepTracker/Step.jsx +12 -4
- package/src/StepTracker/StepTracker.jsx +20 -13
- package/src/Tabs/TabsItem.jsx +3 -2
- package/src/TextInput/TextInput.jsx +1 -1
- package/src/TextInput/TextInputBase.jsx +11 -3
- package/src/ThemeProvider/ThemeProvider.jsx +16 -3
- package/src/ThemeProvider/utils/styles.js +9 -1
- package/src/ThemeProvider/utils/theme-tokens.js +1 -1
- package/src/Typography/Typography.jsx +11 -12
- package/src/index.js +1 -0
- package/src/utils/index.js +1 -0
- package/src/utils/props/clickProps.js +2 -2
- package/src/utils/props/handlerProps.js +64 -16
- package/src/utils/useScrollBlocking.js +57 -0
- package/src/utils/useScrollBlocking.native.js +2 -0
|
@@ -7,13 +7,13 @@ 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, variantProp, selectSystemProps, a11yProps, viewProps } from '../utils';
|
|
10
|
+
import { getTokensPropType, getA11yPropsFromHtmlTag, layoutTags, variantProp, selectSystemProps, a11yProps, viewProps, useCopy } from '../utils';
|
|
11
11
|
import { useA11yInfo } from '../A11yInfoProvider';
|
|
12
12
|
import { CarouselProvider } from './CarouselContext';
|
|
13
13
|
import CarouselItem from './CarouselItem';
|
|
14
|
-
import StepTracker from '../StepTracker';
|
|
15
|
-
import StackView from '../StackView';
|
|
16
14
|
import IconButton from '../IconButton';
|
|
15
|
+
import CarouselStepTracker from './CarouselStepTracker/CarouselStepTracker';
|
|
16
|
+
import dictionary from './dictionary';
|
|
17
17
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
18
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
19
|
const staticStyles = StyleSheet.create({
|
|
@@ -26,18 +26,6 @@ const staticStyles = StyleSheet.create({
|
|
|
26
26
|
left: 0
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
|
-
const staticTokens = {
|
|
30
|
-
stackView: {
|
|
31
|
-
justifyContent: 'center'
|
|
32
|
-
},
|
|
33
|
-
stepTracker: {
|
|
34
|
-
showStepLabel: false,
|
|
35
|
-
showStepTrackerLabel: true,
|
|
36
|
-
knobCompletedBackgroundColor: 'none',
|
|
37
|
-
connectorCompletedColor: 'none',
|
|
38
|
-
connectorColor: 'none'
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
29
|
|
|
42
30
|
const selectContainerStyles = width => ({
|
|
43
31
|
backgroundColor: 'transparent',
|
|
@@ -77,14 +65,6 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
|
|
|
77
65
|
return styles;
|
|
78
66
|
};
|
|
79
67
|
|
|
80
|
-
const defaultPanelNavigationDictionary = {
|
|
81
|
-
en: {
|
|
82
|
-
stepTrackerLabel: 'Showing %{stepNumber} of %{stepCount}'
|
|
83
|
-
},
|
|
84
|
-
fr: {
|
|
85
|
-
stepTrackerLabel: 'Étape %{stepNumber} sur %{stepCount}: %{stepLabel}'
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
68
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
89
69
|
/**
|
|
90
70
|
* Carousel is a general-purpose content slider that can be used to render content in terms of slides.
|
|
@@ -146,6 +126,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
146
126
|
tokens,
|
|
147
127
|
variant,
|
|
148
128
|
children,
|
|
129
|
+
itemLabel = 'item',
|
|
149
130
|
previousNextNavigationPosition = 'inside',
|
|
150
131
|
previousNextIconSize = 'default',
|
|
151
132
|
minDistanceToCapture = 5,
|
|
@@ -154,24 +135,38 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
154
135
|
onAnimationEnd,
|
|
155
136
|
onIndexChanged,
|
|
156
137
|
springConfig = undefined,
|
|
157
|
-
|
|
158
|
-
|
|
138
|
+
panelNavigation = /*#__PURE__*/_jsx(CarouselStepTracker, {}),
|
|
139
|
+
tag = 'ul',
|
|
159
140
|
accessibilityRole = 'adjustable',
|
|
160
141
|
accessibilityLabel = 'carousel',
|
|
142
|
+
copy,
|
|
161
143
|
...rest
|
|
162
144
|
} = _ref;
|
|
163
145
|
const viewport = useViewport();
|
|
146
|
+
const themeTokens = useThemeTokens('Carousel', tokens, variant, {
|
|
147
|
+
viewport
|
|
148
|
+
});
|
|
164
149
|
const {
|
|
165
150
|
previousIcon,
|
|
166
151
|
nextIcon,
|
|
167
152
|
showPreviousNextNavigation,
|
|
168
153
|
showPanelNavigation,
|
|
169
|
-
spaceBetweenSlideAndPreviousNextNavigation
|
|
170
|
-
|
|
171
|
-
} = useThemeTokens('Carousel', tokens, variant, {
|
|
172
|
-
viewport
|
|
173
|
-
});
|
|
154
|
+
spaceBetweenSlideAndPreviousNextNavigation
|
|
155
|
+
} = themeTokens;
|
|
174
156
|
const [activeIndex, setActiveIndex] = React.useState(0);
|
|
157
|
+
const [isAnimating, setIsAnimating] = React.useState(false);
|
|
158
|
+
const handleAnimationStart = React.useCallback(function () {
|
|
159
|
+
if (typeof onAnimationStart === 'function') onAnimationStart(...arguments);
|
|
160
|
+
setIsAnimating(true);
|
|
161
|
+
}, [onAnimationStart]);
|
|
162
|
+
const handleAnimationEnd = React.useCallback(function () {
|
|
163
|
+
if (typeof onAnimationEnd === 'function') onAnimationEnd(...arguments);
|
|
164
|
+
setIsAnimating(false);
|
|
165
|
+
}, [onAnimationEnd]);
|
|
166
|
+
const getCopy = useCopy({
|
|
167
|
+
dictionary,
|
|
168
|
+
copy
|
|
169
|
+
});
|
|
175
170
|
const childrenArray = React.Children.toArray(children);
|
|
176
171
|
const systemProps = selectProps({ ...rest,
|
|
177
172
|
accessibilityRole,
|
|
@@ -196,9 +191,6 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
196
191
|
const animatedY = React.useRef(0);
|
|
197
192
|
const isFirstSlide = !activeIndex;
|
|
198
193
|
const isLastSlide = activeIndex + 1 >= children.length;
|
|
199
|
-
const panelNavigationTokens = { ...staticTokens.stepTracker,
|
|
200
|
-
containerPaddingTop: spaceBetweenSlideAndPanelNavigation
|
|
201
|
-
};
|
|
202
194
|
|
|
203
195
|
const onContainerLayout = _ref2 => {
|
|
204
196
|
let {
|
|
@@ -240,20 +232,28 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
240
232
|
y: 0
|
|
241
233
|
});
|
|
242
234
|
}, [activeIndex, containerLayout.width, pan, animatedX]);
|
|
243
|
-
const animate = React.useCallback(toValue => {
|
|
235
|
+
const animate = React.useCallback((toValue, toIndex) => {
|
|
236
|
+
const handleAnimationEndToIndex = function () {
|
|
237
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
238
|
+
args[_key] = arguments[_key];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return handleAnimationEnd(toIndex, ...args);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
244
|
if (reduceMotionEnabled) {
|
|
245
245
|
Animated.timing(pan, {
|
|
246
246
|
toValue,
|
|
247
247
|
duration: 1,
|
|
248
248
|
useNativeDriver: false
|
|
249
|
-
}).start();
|
|
249
|
+
}).start(handleAnimationEndToIndex);
|
|
250
250
|
} else {
|
|
251
251
|
Animated.spring(pan, { ...springConfig,
|
|
252
252
|
toValue,
|
|
253
253
|
useNativeDriver: false
|
|
254
|
-
}).start();
|
|
254
|
+
}).start(handleAnimationEndToIndex);
|
|
255
255
|
}
|
|
256
|
-
}, [pan, springConfig, reduceMotionEnabled]);
|
|
256
|
+
}, [pan, springConfig, reduceMotionEnabled, handleAnimationEnd]);
|
|
257
257
|
const updateIndex = React.useCallback(function () {
|
|
258
258
|
let delta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
|
|
259
259
|
const toValue = {
|
|
@@ -271,24 +271,24 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
271
271
|
calcDelta = -1 * activeIndex + delta - 1;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
const index = activeIndex + calcDelta;
|
|
275
|
+
|
|
274
276
|
if (skipChanges) {
|
|
275
|
-
animate(toValue);
|
|
277
|
+
animate(toValue, index);
|
|
276
278
|
return calcDelta;
|
|
277
279
|
}
|
|
278
280
|
|
|
279
|
-
const index = activeIndex + calcDelta;
|
|
280
281
|
setActiveIndex(index);
|
|
281
282
|
toValue.x = containerLayout.width * -1 * calcDelta;
|
|
282
|
-
animate(toValue);
|
|
283
|
+
animate(toValue, index);
|
|
283
284
|
if (onIndexChanged) onIndexChanged(calcDelta);
|
|
284
|
-
if (onAnimationEnd) onAnimationEnd(index);
|
|
285
285
|
return calcDelta;
|
|
286
|
-
}, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged
|
|
286
|
+
}, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged]);
|
|
287
287
|
const fixOffsetAndGo = React.useCallback(delta => {
|
|
288
288
|
updateOffset();
|
|
289
|
-
|
|
289
|
+
handleAnimationStart(activeIndex);
|
|
290
290
|
updateIndex(delta);
|
|
291
|
-
}, [updateIndex, updateOffset, activeIndex,
|
|
291
|
+
}, [updateIndex, updateOffset, activeIndex, handleAnimationStart]);
|
|
292
292
|
const goToNeighboring = React.useCallback(function () {
|
|
293
293
|
let toPrev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
294
294
|
fixOffsetAndGo(toPrev ? -1 : 1);
|
|
@@ -308,7 +308,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
308
308
|
return false;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
|
|
311
|
+
handleAnimationStart(activeIndex);
|
|
312
312
|
return Math.abs(gestureState.dx) > minDistanceToCapture;
|
|
313
313
|
},
|
|
314
314
|
onPanResponderGrant: () => updateOffset(),
|
|
@@ -324,13 +324,13 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
324
324
|
animate({
|
|
325
325
|
x: 0,
|
|
326
326
|
y: 0
|
|
327
|
-
});
|
|
327
|
+
}, 0);
|
|
328
328
|
} else {
|
|
329
329
|
const delta = correction > 0 ? -1 : 1;
|
|
330
330
|
updateIndex(delta);
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
|
-
}), [containerLayout.width, updateIndex, updateOffset, animate, isSwipeAllowed, activeIndex, minDistanceForAction,
|
|
333
|
+
}), [containerLayout.width, updateIndex, updateOffset, animate, isSwipeAllowed, activeIndex, minDistanceForAction, handleAnimationStart, minDistanceToCapture, pan.x]);
|
|
334
334
|
React.useEffect(() => {
|
|
335
335
|
pan.x.addListener(_ref4 => {
|
|
336
336
|
let {
|
|
@@ -370,11 +370,18 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
370
370
|
size: previousNextIconSize,
|
|
371
371
|
raised: true
|
|
372
372
|
};
|
|
373
|
+
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
|
|
375
|
+
|
|
376
|
+
return "".concat(copyText[0].toUpperCase()).concat(copyText.slice(1));
|
|
377
|
+
}, [activeIndex, childrenArray.length, itemLabel, getCopy]);
|
|
373
378
|
return /*#__PURE__*/_jsxs(CarouselProvider, {
|
|
374
379
|
activeIndex: activeIndex,
|
|
375
380
|
totalItems: childrenArray.length,
|
|
376
381
|
width: containerLayout.width,
|
|
377
382
|
goTo: goTo,
|
|
383
|
+
getCopyWithPlaceholders: getCopyWithPlaceholders,
|
|
384
|
+
themeTokens: themeTokens,
|
|
378
385
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
379
386
|
style: staticStyles.root,
|
|
380
387
|
onLayout: onContainerLayout,
|
|
@@ -388,7 +395,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
388
395
|
icon: previousIcon,
|
|
389
396
|
onPress: goToPrev,
|
|
390
397
|
variant: previousNextIconButtonVariants,
|
|
391
|
-
accessibilityLabel:
|
|
398
|
+
accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex)
|
|
392
399
|
})
|
|
393
400
|
}), /*#__PURE__*/_jsx(View, {
|
|
394
401
|
style: selectContainerStyles(containerLayout.width),
|
|
@@ -401,9 +408,12 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
401
408
|
}]
|
|
402
409
|
}]),
|
|
403
410
|
...panResponder.panHandlers,
|
|
411
|
+
...getA11yPropsFromHtmlTag(tag),
|
|
404
412
|
children: childrenArray.map((element, index) => {
|
|
413
|
+
const hidden = !isAnimating && index !== activeIndex;
|
|
405
414
|
const clonedElement = /*#__PURE__*/React.cloneElement(element, {
|
|
406
|
-
elementIndex: index
|
|
415
|
+
elementIndex: index,
|
|
416
|
+
hidden
|
|
407
417
|
});
|
|
408
418
|
return /*#__PURE__*/_jsx(React.Fragment, {
|
|
409
419
|
children: clonedElement
|
|
@@ -418,22 +428,10 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
418
428
|
icon: nextIcon,
|
|
419
429
|
onPress: goToNext,
|
|
420
430
|
variant: previousNextIconButtonVariants,
|
|
421
|
-
accessibilityLabel:
|
|
431
|
+
accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex + 2)
|
|
422
432
|
})
|
|
423
433
|
})]
|
|
424
|
-
}), showPanelNavigation ?
|
|
425
|
-
direction: "row",
|
|
426
|
-
tokens: staticTokens.stackView,
|
|
427
|
-
children: onRenderPanelNavigation ? onRenderPanelNavigation({
|
|
428
|
-
activeIndex,
|
|
429
|
-
totalItems: childrenArray.length
|
|
430
|
-
}) : /*#__PURE__*/_jsx(StepTracker, {
|
|
431
|
-
current: activeIndex,
|
|
432
|
-
steps: childrenArray.map((_, index) => String(index)),
|
|
433
|
-
dictionary: panelNavigationTextDictionary,
|
|
434
|
-
tokens: panelNavigationTokens
|
|
435
|
-
})
|
|
436
|
-
}) : null]
|
|
434
|
+
}), showPanelNavigation ? panelNavigation : null]
|
|
437
435
|
});
|
|
438
436
|
});
|
|
439
437
|
Carousel.propTypes = { ...selectedSystemPropTypes,
|
|
@@ -445,6 +443,14 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
|
|
|
445
443
|
*/
|
|
446
444
|
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
|
|
447
445
|
|
|
446
|
+
/**
|
|
447
|
+
* Lowercase language-appropriate user-facing description of what each Carousel slide represents.
|
|
448
|
+
* This is used when generating item labels. For example, if a carousel contains offers,
|
|
449
|
+
* pass itemLabel="summer offer" (or copy="fr" and an appropriate French translation) to genereate
|
|
450
|
+
* accessible labels such as "Summer offer 1 of 3" and "Show summer offer 2 of 3".
|
|
451
|
+
*/
|
|
452
|
+
itemLabel: PropTypes.string,
|
|
453
|
+
|
|
448
454
|
/**
|
|
449
455
|
* `inside` renders the previous and next buttons inside the slide
|
|
450
456
|
* `outside` renders the previous and next buttons outside the slide
|
|
@@ -492,20 +498,20 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
|
|
|
492
498
|
onIndexChanged: PropTypes.func,
|
|
493
499
|
|
|
494
500
|
/**
|
|
495
|
-
* Use this to render a custom panel navigation element instead of
|
|
496
|
-
*
|
|
497
|
-
* activeIndex: index of current slide
|
|
498
|
-
* totalItems: total number of slides
|
|
501
|
+
* Use this to render a custom panel navigation element instead of the default StepTracker's based navigation
|
|
502
|
+
* You can make use of `useCarousel` within your custom panel navigation component to hook into various Carousel states such as:
|
|
503
|
+
* - activeIndex: index of current slide
|
|
504
|
+
* - totalItems: total number of slides
|
|
499
505
|
* Use it as follows:
|
|
500
506
|
* ```js
|
|
501
507
|
* <Carousel
|
|
502
|
-
*
|
|
508
|
+
* panelNavigation={<CustomPanelNavigation />}
|
|
503
509
|
* >
|
|
504
510
|
* <Carousel.Item>First Slide</Carousel.Item>
|
|
505
511
|
* </Carousel>
|
|
506
512
|
* ```
|
|
507
513
|
*/
|
|
508
|
-
|
|
514
|
+
panelNavigation: PropTypes.element,
|
|
509
515
|
|
|
510
516
|
/**
|
|
511
517
|
* When slide animation start
|
|
@@ -563,7 +569,16 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
|
|
|
563
569
|
/**
|
|
564
570
|
* Provide custom accessibilityLabel for Carousel container
|
|
565
571
|
*/
|
|
566
|
-
accessibilityLabel: PropTypes.string
|
|
572
|
+
accessibilityLabel: PropTypes.string,
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* HTML tag to use for the Carousel item's immediate parent. Defaults to `'ul'` so that
|
|
576
|
+
* assistive technology tools know to intepret the carousel as a list.
|
|
577
|
+
*
|
|
578
|
+
* Note that if the immediate Carousel children do not all render as `'li'` elements,
|
|
579
|
+
* this should be changed (e.g. pass tag="div") because only 'li' is a valid child of 'ul'.
|
|
580
|
+
*/
|
|
581
|
+
tag: PropTypes.oneOf(layoutTags)
|
|
567
582
|
};
|
|
568
583
|
Carousel.Item = CarouselItem;
|
|
569
584
|
Carousel.displayName = 'Carousel';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import { getTokensPropType } from '../utils';
|
|
3
4
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
5
|
const CarouselContext = /*#__PURE__*/React.createContext();
|
|
5
6
|
|
|
@@ -9,14 +10,18 @@ const CarouselProvider = _ref => {
|
|
|
9
10
|
activeIndex,
|
|
10
11
|
totalItems,
|
|
11
12
|
width,
|
|
12
|
-
goTo
|
|
13
|
+
goTo,
|
|
14
|
+
getCopyWithPlaceholders,
|
|
15
|
+
themeTokens
|
|
13
16
|
} = _ref;
|
|
14
17
|
const value = React.useMemo(() => ({
|
|
15
18
|
activeIndex,
|
|
16
19
|
totalItems,
|
|
17
20
|
width,
|
|
18
|
-
goTo
|
|
19
|
-
|
|
21
|
+
goTo,
|
|
22
|
+
getCopyWithPlaceholders,
|
|
23
|
+
themeTokens
|
|
24
|
+
}), [activeIndex, totalItems, width, goTo, getCopyWithPlaceholders, themeTokens]);
|
|
20
25
|
return /*#__PURE__*/_jsx(CarouselContext.Provider, {
|
|
21
26
|
value: value,
|
|
22
27
|
children: children
|
|
@@ -38,6 +43,8 @@ CarouselProvider.propTypes = {
|
|
|
38
43
|
activeIndex: PropTypes.number.isRequired,
|
|
39
44
|
totalItems: PropTypes.number.isRequired,
|
|
40
45
|
width: PropTypes.number.isRequired,
|
|
41
|
-
goTo: PropTypes.func.isRequired
|
|
46
|
+
goTo: PropTypes.func.isRequired,
|
|
47
|
+
getCopyWithPlaceholders: PropTypes.func.isRequired,
|
|
48
|
+
themeTokens: getTokensPropType('Carousel')
|
|
42
49
|
};
|
|
43
50
|
export { CarouselProvider, useCarousel };
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import View from "react-native-web/dist/exports/View";
|
|
4
4
|
import Platform from "react-native-web/dist/exports/Platform";
|
|
5
|
-
import { selectSystemProps, a11yProps, viewProps } from '../../utils';
|
|
5
|
+
import { layoutTags, getA11yPropsFromHtmlTag, selectSystemProps, a11yProps, viewProps } from '../../utils';
|
|
6
6
|
import { useCarousel } from '../CarouselContext';
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
8
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
@@ -15,23 +15,29 @@ const CarouselItem = _ref => {
|
|
|
15
15
|
let {
|
|
16
16
|
children,
|
|
17
17
|
elementIndex,
|
|
18
|
+
tag = 'li',
|
|
19
|
+
hidden,
|
|
18
20
|
...rest
|
|
19
21
|
} = _ref;
|
|
20
22
|
const {
|
|
21
23
|
width,
|
|
22
|
-
activeIndex
|
|
23
|
-
totalItems
|
|
24
|
+
activeIndex
|
|
24
25
|
} = useCarousel();
|
|
25
26
|
const selectedProps = selectProps({ ...rest,
|
|
26
|
-
|
|
27
|
-
accessibilityRole: Platform.OS === 'android' ? 'none' : 'group',
|
|
28
|
-
accessibilityLabel: "Showing ".concat(elementIndex + 1, " of ").concat(totalItems)
|
|
27
|
+
...getA11yPropsFromHtmlTag(tag, rest.accessibilityRole)
|
|
29
28
|
});
|
|
30
29
|
const focusabilityProps = activeIndex === elementIndex ? {} : a11yProps.nonFocusableProps;
|
|
30
|
+
const style = {
|
|
31
|
+
width
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (hidden && Platform.OS === 'web') {
|
|
35
|
+
// On web, visibility: hidden makes all children non-focusable. It doesn't exist on native.
|
|
36
|
+
style.visibility = 'hidden';
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
return /*#__PURE__*/_jsx(View, {
|
|
32
|
-
style:
|
|
33
|
-
width
|
|
34
|
-
},
|
|
40
|
+
style: style,
|
|
35
41
|
...selectedProps,
|
|
36
42
|
...focusabilityProps,
|
|
37
43
|
children: children
|
|
@@ -54,7 +60,16 @@ CarouselItem.propTypes = { ...selectedSystemPropTypes,
|
|
|
54
60
|
/**
|
|
55
61
|
* Content of the slide
|
|
56
62
|
*/
|
|
57
|
-
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
|
|
63
|
+
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Sets the HTML tag of the outer container. By default `'li'` so that assistive technology sees
|
|
67
|
+
* the Carousel as a list of items.
|
|
68
|
+
*
|
|
69
|
+
* Carousel's innermost container defaults to `'ul'` which can be overridden. If the tag of either
|
|
70
|
+
* `Carousel` or `Carousel.Item` is overriden, the other should be too, to avoid producing invalid HTML.
|
|
71
|
+
*/
|
|
72
|
+
tag: PropTypes.oneOf(layoutTags)
|
|
58
73
|
};
|
|
59
74
|
CarouselItem.displayName = 'Carousel.Item';
|
|
60
75
|
export default CarouselItem;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useCarousel } from '../CarouselContext';
|
|
3
|
+
import StepTracker from '../../StepTracker';
|
|
4
|
+
import StackView from '../../StackView';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
const CarouselStepTracker = () => {
|
|
8
|
+
const {
|
|
9
|
+
activeIndex,
|
|
10
|
+
totalItems,
|
|
11
|
+
getCopyWithPlaceholders,
|
|
12
|
+
themeTokens
|
|
13
|
+
} = useCarousel();
|
|
14
|
+
const stackViewTokens = {
|
|
15
|
+
justifyContent: 'center'
|
|
16
|
+
};
|
|
17
|
+
const stepTrackerTokens = {
|
|
18
|
+
showStepLabel: false,
|
|
19
|
+
showStepTrackerLabel: true,
|
|
20
|
+
knobCompletedBackgroundColor: 'none',
|
|
21
|
+
connectorCompletedColor: 'none',
|
|
22
|
+
connectorColor: 'none',
|
|
23
|
+
containerPaddingTop: themeTokens.spaceBetweenSlideAndPanelNavigation
|
|
24
|
+
};
|
|
25
|
+
const steps = Array.from(Array(totalItems)).map((_, index) => String(index));
|
|
26
|
+
return /*#__PURE__*/_jsx(StackView, {
|
|
27
|
+
direction: "row",
|
|
28
|
+
tokens: stackViewTokens,
|
|
29
|
+
children: /*#__PURE__*/_jsx(StepTracker, {
|
|
30
|
+
current: activeIndex,
|
|
31
|
+
steps: steps,
|
|
32
|
+
copy: {
|
|
33
|
+
// Give StepTracker copy from Carousel's language and dictionary
|
|
34
|
+
stepLabel: getCopyWithPlaceholders('stepLabel'),
|
|
35
|
+
stepTrackerLabel: getCopyWithPlaceholders('stepTrackerLabel')
|
|
36
|
+
},
|
|
37
|
+
tokens: stepTrackerTokens
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default CarouselStepTracker;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// 'stepLabel' and 'stepTrackerLabel' are passed down to StepTracker
|
|
2
|
+
export default {
|
|
3
|
+
en: {
|
|
4
|
+
carouselLabel: '%{stepCount} items',
|
|
5
|
+
iconButtonLabel: 'Show %{itemLabel} %{targetStep} of %{stepCount}',
|
|
6
|
+
stepLabel: '%{itemLabel} %{stepNumber}',
|
|
7
|
+
stepTrackerLabel: '%{itemLabel} %{stepNumber} of %{stepCount}'
|
|
8
|
+
},
|
|
9
|
+
fr: {
|
|
10
|
+
// TODO: French translations here
|
|
11
|
+
carouselLabel: '(fr) %{stepCount} items',
|
|
12
|
+
iconButtonLabel: '(fr) Show %{itemLabel} %{targetStep} of %{stepCount}',
|
|
13
|
+
stepLabel: '(fr) %{itemLabel} %{stepNumber}',
|
|
14
|
+
stepTrackerLabel: '(fr) %{itemLabel} %{stepNumber} of %{stepCount}'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
@@ -9,7 +9,7 @@ import CheckboxInput from './CheckboxInput';
|
|
|
9
9
|
import CheckboxLabel from '../InputLabel/LabelContent';
|
|
10
10
|
import Feedback from '../Feedback';
|
|
11
11
|
import StackView from '../StackView';
|
|
12
|
-
import { applyShadowToken, applyTextStyles, useThemeTokensCallback } from '../ThemeProvider';
|
|
12
|
+
import { applyShadowToken, applyTextStyles, useTheme, useThemeTokensCallback } from '../ThemeProvider';
|
|
13
13
|
import { a11yProps, focusHandlerProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
|
|
14
14
|
import useUniqueId from '../utils/useUniqueId';
|
|
15
15
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -47,7 +47,7 @@ const selectInputStyles = (_ref, isChecked) => {
|
|
|
47
47
|
};
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
const selectLabelStyles = _ref2 => {
|
|
50
|
+
const selectLabelStyles = (_ref2, themeOptions) => {
|
|
51
51
|
let {
|
|
52
52
|
labelColor,
|
|
53
53
|
labelFontName,
|
|
@@ -63,7 +63,8 @@ const selectLabelStyles = _ref2 => {
|
|
|
63
63
|
fontName: labelFontName,
|
|
64
64
|
fontWeight: labelFontWeight,
|
|
65
65
|
fontSize: labelFontSize,
|
|
66
|
-
lineHeight: labelLineHeight
|
|
66
|
+
lineHeight: labelLineHeight,
|
|
67
|
+
themeOptions
|
|
67
68
|
})
|
|
68
69
|
};
|
|
69
70
|
};
|
|
@@ -187,6 +188,9 @@ const Checkbox = /*#__PURE__*/forwardRef((_ref5, ref) => {
|
|
|
187
188
|
|
|
188
189
|
const uniqueId = useUniqueId('checkbox');
|
|
189
190
|
const inputId = id !== null && id !== void 0 ? id : uniqueId;
|
|
191
|
+
const {
|
|
192
|
+
themeOptions
|
|
193
|
+
} = useTheme();
|
|
190
194
|
return /*#__PURE__*/_jsx(View, {
|
|
191
195
|
style: staticStyles.wrapper,
|
|
192
196
|
ref: ref,
|
|
@@ -218,7 +222,7 @@ const Checkbox = /*#__PURE__*/forwardRef((_ref5, ref) => {
|
|
|
218
222
|
pressed
|
|
219
223
|
});
|
|
220
224
|
const iconTokens = selectIconTokens(stateTokens);
|
|
221
|
-
const labelStyles = selectLabelStyles(stateTokens);
|
|
225
|
+
const labelStyles = selectLabelStyles(stateTokens, themeOptions);
|
|
222
226
|
const alignWithLabel = label ? [staticStyles.alignWithLabel, {
|
|
223
227
|
height: labelStyles.lineHeight
|
|
224
228
|
}] : null;
|
|
@@ -46,7 +46,7 @@ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, f
|
|
|
46
46
|
* @example
|
|
47
47
|
* ```jsx
|
|
48
48
|
* <CheckboxGroup
|
|
49
|
-
*
|
|
49
|
+
* initialCheckedIds="check1"
|
|
50
50
|
* items={[
|
|
51
51
|
* { label: 'Checkbox 1', id: 'check1' },
|
|
52
52
|
* { label: 'Checkbox 2', id: 'check2' },
|
|
@@ -3,7 +3,7 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
|
3
3
|
import Text from "react-native-web/dist/exports/Text";
|
|
4
4
|
import View from "react-native-web/dist/exports/View";
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider';
|
|
6
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider';
|
|
7
7
|
import { a11yProps, getTokensPropType, selectSystemProps, selectTokens, variantProp, viewProps } from '../utils';
|
|
8
8
|
import StackView from '../StackView';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -12,24 +12,29 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
12
12
|
|
|
13
13
|
const selectStyles = tokens => selectTokens('Feedback', tokens);
|
|
14
14
|
|
|
15
|
-
const selectTitleTextStyles = _ref => {
|
|
15
|
+
const selectTitleTextStyles = (_ref, themeOptions) => {
|
|
16
16
|
let {
|
|
17
17
|
titleFontSize,
|
|
18
18
|
...tokens
|
|
19
19
|
} = _ref;
|
|
20
|
-
return applyTextStyles(selectTokens('Typography', { ...tokens,
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
return applyTextStyles({ ...selectTokens('Typography', { ...tokens,
|
|
21
|
+
fontSize: titleFontSize,
|
|
22
|
+
themeOptions
|
|
23
|
+
}),
|
|
24
|
+
themeOptions
|
|
25
|
+
});
|
|
23
26
|
};
|
|
24
27
|
|
|
25
|
-
const selectContentTextStyles = _ref2 => {
|
|
28
|
+
const selectContentTextStyles = (_ref2, themeOptions) => {
|
|
26
29
|
let {
|
|
27
30
|
contentFontSize,
|
|
28
31
|
...tokens
|
|
29
32
|
} = _ref2;
|
|
30
|
-
return applyTextStyles(selectTokens('Typography', { ...tokens,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
return applyTextStyles({ ...selectTokens('Typography', { ...tokens,
|
|
34
|
+
fontSize: contentFontSize
|
|
35
|
+
}),
|
|
36
|
+
themeOptions
|
|
37
|
+
});
|
|
33
38
|
};
|
|
34
39
|
|
|
35
40
|
const selectIconTokens = _ref3 => {
|
|
@@ -90,8 +95,11 @@ const Feedback = /*#__PURE__*/forwardRef((_ref5, ref) => {
|
|
|
90
95
|
const {
|
|
91
96
|
icon: IconComponent
|
|
92
97
|
} = themeTokens;
|
|
93
|
-
const
|
|
94
|
-
|
|
98
|
+
const {
|
|
99
|
+
themeOptions
|
|
100
|
+
} = useTheme();
|
|
101
|
+
const titleTextStyles = selectTitleTextStyles(themeTokens, themeOptions);
|
|
102
|
+
const contentTextStyles = selectContentTextStyles(themeTokens, themeOptions);
|
|
95
103
|
const content = typeof children === 'string' ? /*#__PURE__*/_jsx(Text, {
|
|
96
104
|
style: contentTextStyles,
|
|
97
105
|
children: children
|
|
@@ -51,6 +51,9 @@ const IconText = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
|
51
51
|
});
|
|
52
52
|
IconText.displayName = 'IconText';
|
|
53
53
|
IconText.propTypes = {
|
|
54
|
+
/* eslint-disable react/no-unused-prop-types */
|
|
55
|
+
// eslint is having hard time seeing these props through forwardRef
|
|
56
|
+
|
|
54
57
|
/**
|
|
55
58
|
* Amount of space to separate the text content and icon. Uses the themes's spacing scale
|
|
56
59
|
* (see useSpacingScale for more info).
|
|
@@ -79,5 +82,7 @@ IconText.propTypes = {
|
|
|
79
82
|
* `<Typography>` component, or a component that renders `<Text>`.
|
|
80
83
|
*/
|
|
81
84
|
children: PropTypes.node
|
|
85
|
+
/* eslint-enable react/no-unused-prop-types */
|
|
86
|
+
|
|
82
87
|
};
|
|
83
88
|
export default IconText;
|