@telus-uds/components-web 1.9.0 → 1.11.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.
- package/CHANGELOG.md +40 -2
- package/lib/Breadcrumbs/Breadcrumbs.js +8 -3
- package/lib/Breadcrumbs/Item/Item.js +31 -6
- package/lib/Callout/Callout.js +24 -3
- package/lib/Disclaimer/Disclaimer.js +72 -0
- package/lib/Disclaimer/index.js +15 -0
- package/lib/Footnote/Footnote.js +70 -28
- package/lib/Footnote/FootnoteLink.js +11 -13
- package/lib/NavigationBar/NavigationBar.js +231 -0
- package/lib/NavigationBar/NavigationItem.js +111 -0
- package/lib/NavigationBar/NavigationSubMenu.js +179 -0
- package/lib/NavigationBar/collapseItems.js +51 -0
- package/lib/NavigationBar/index.js +13 -0
- package/lib/PriceLockup/PriceLockup.js +40 -17
- package/lib/PriceLockup/tokens.js +49 -116
- package/lib/Progress/ProgressBar.js +100 -0
- package/lib/Progress/index.js +16 -0
- package/lib/Ribbon/Ribbon.js +53 -32
- package/lib/Spinner/Spinner.js +18 -14
- package/lib/Table/Cell.js +15 -1
- package/lib/Toast/Toast.js +15 -8
- package/lib/VideoPicker/VideoPicker.js +177 -0
- package/lib/VideoPicker/VideoPickerPlayer.js +54 -0
- package/lib/VideoPicker/VideoPickerThumbnail.js +201 -0
- package/lib/VideoPicker/VideoSlider.js +100 -0
- package/lib/VideoPicker/index.js +13 -0
- package/lib/VideoPicker/videoPropType.js +25 -0
- package/lib/index.js +37 -1
- package/lib-module/Breadcrumbs/Breadcrumbs.js +8 -3
- package/lib-module/Breadcrumbs/Item/Item.js +32 -7
- package/lib-module/Callout/Callout.js +24 -3
- package/lib-module/Disclaimer/Disclaimer.js +54 -0
- package/lib-module/Disclaimer/index.js +1 -0
- package/lib-module/Footnote/Footnote.js +68 -27
- package/lib-module/Footnote/FootnoteLink.js +12 -14
- package/lib-module/NavigationBar/NavigationBar.js +207 -0
- package/lib-module/NavigationBar/NavigationItem.js +87 -0
- package/lib-module/NavigationBar/NavigationSubMenu.js +161 -0
- package/lib-module/NavigationBar/collapseItems.js +43 -0
- package/lib-module/NavigationBar/index.js +2 -0
- package/lib-module/PriceLockup/PriceLockup.js +42 -19
- package/lib-module/PriceLockup/tokens.js +54 -119
- package/lib-module/Progress/ProgressBar.js +83 -0
- package/lib-module/Progress/index.js +4 -0
- package/lib-module/Ribbon/Ribbon.js +53 -32
- package/lib-module/Spinner/Spinner.js +17 -14
- package/lib-module/Table/Cell.js +15 -1
- package/lib-module/Toast/Toast.js +15 -8
- package/lib-module/VideoPicker/VideoPicker.js +151 -0
- package/lib-module/VideoPicker/VideoPickerPlayer.js +41 -0
- package/lib-module/VideoPicker/VideoPickerThumbnail.js +180 -0
- package/lib-module/VideoPicker/VideoSlider.js +83 -0
- package/lib-module/VideoPicker/index.js +2 -0
- package/lib-module/VideoPicker/videoPropType.js +9 -0
- package/lib-module/index.js +4 -0
- package/package.json +3 -3
- package/src/Breadcrumbs/Breadcrumbs.jsx +4 -3
- package/src/Breadcrumbs/Item/Item.jsx +18 -4
- package/src/Callout/Callout.jsx +27 -3
- package/src/Disclaimer/Disclaimer.jsx +39 -0
- package/src/Disclaimer/index.js +1 -0
- package/src/Footnote/Footnote.jsx +76 -26
- package/src/Footnote/FootnoteLink.jsx +28 -18
- package/src/NavigationBar/NavigationBar.jsx +217 -0
- package/src/NavigationBar/NavigationItem.jsx +83 -0
- package/src/NavigationBar/NavigationSubMenu.jsx +121 -0
- package/src/NavigationBar/collapseItems.js +29 -0
- package/src/NavigationBar/index.js +3 -0
- package/src/PriceLockup/PriceLockup.jsx +47 -21
- package/src/PriceLockup/tokens.js +34 -54
- package/src/Progress/ProgressBar.jsx +67 -0
- package/src/Progress/index.js +6 -0
- package/src/Ribbon/Ribbon.jsx +21 -9
- package/src/Spinner/Spinner.jsx +20 -17
- package/src/Table/Cell.jsx +22 -5
- package/src/Toast/Toast.jsx +12 -5
- package/src/VideoPicker/VideoPicker.jsx +144 -0
- package/src/VideoPicker/VideoPickerPlayer.jsx +21 -0
- package/src/VideoPicker/VideoPickerThumbnail.jsx +182 -0
- package/src/VideoPicker/VideoSlider.jsx +85 -0
- package/src/VideoPicker/index.js +3 -0
- package/src/VideoPicker/videoPropType.js +12 -0
- package/src/index.js +4 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { viewports } from '@telus-uds/system-constants';
|
|
4
|
+
import { selectSystemProps, StackView, useThemeTokens, useViewport } from '@telus-uds/components-base';
|
|
5
|
+
import styled, { css } from 'styled-components';
|
|
6
|
+
import { VideoPropType } from './videoPropType';
|
|
7
|
+
import VideoPickerThumbnail from './VideoPickerThumbnail';
|
|
8
|
+
import VideoPickerPlayer from './VideoPickerPlayer';
|
|
9
|
+
import VideoSlider from './VideoSlider';
|
|
10
|
+
import { htmlAttrs } from '../utils';
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
|
|
14
|
+
|
|
15
|
+
const framedContainerStyles = _ref => {
|
|
16
|
+
let {
|
|
17
|
+
framedContainerBackgroundColor,
|
|
18
|
+
framedContainerBorderWidth,
|
|
19
|
+
framedContainerBorderColor,
|
|
20
|
+
framedContainerBorderRadius,
|
|
21
|
+
framedMaxHeight
|
|
22
|
+
} = _ref;
|
|
23
|
+
return css(["background-color:", ";border:", "px solid ", ";border-radius:", "px;& > div{max-height:", "px;}"], framedContainerBackgroundColor, framedContainerBorderWidth, framedContainerBorderColor, framedContainerBorderRadius, framedMaxHeight);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const VideoPickerContainer = /*#__PURE__*/styled.div.withConfig({
|
|
27
|
+
displayName: "VideoPicker__VideoPickerContainer",
|
|
28
|
+
componentId: "components-web__sc-x6lxp0-0"
|
|
29
|
+
})(["", ""], _ref2 => {
|
|
30
|
+
let {
|
|
31
|
+
isFramed,
|
|
32
|
+
...tokens
|
|
33
|
+
} = _ref2;
|
|
34
|
+
return isFramed && framedContainerStyles(tokens);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const framedPlayerContainerStyles = _ref3 => {
|
|
38
|
+
let {
|
|
39
|
+
framedMaxHeight,
|
|
40
|
+
framedContainerPadding
|
|
41
|
+
} = _ref3;
|
|
42
|
+
return css(["width:66.67%;padding:", "px;max-height:", "px;flex-shrink:0;box-sizing:border-box;"], framedContainerPadding, framedMaxHeight);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const VideoPlayerContainer = /*#__PURE__*/styled.div.withConfig({
|
|
46
|
+
displayName: "VideoPicker__VideoPlayerContainer",
|
|
47
|
+
componentId: "components-web__sc-x6lxp0-1"
|
|
48
|
+
})(["", " overflow:auto;"], _ref4 => {
|
|
49
|
+
let {
|
|
50
|
+
isFramed,
|
|
51
|
+
...tokens
|
|
52
|
+
} = _ref4;
|
|
53
|
+
return isFramed && framedPlayerContainerStyles(tokens);
|
|
54
|
+
});
|
|
55
|
+
const framedVideoListContainerStyle = /*#__PURE__*/css(["max-height:", "px;overflow:auto;flex-direction:column;"], _ref5 => {
|
|
56
|
+
let {
|
|
57
|
+
framedMaxHeight
|
|
58
|
+
} = _ref5;
|
|
59
|
+
return framedMaxHeight;
|
|
60
|
+
});
|
|
61
|
+
const VideoListContainer = /*#__PURE__*/styled.div.withConfig({
|
|
62
|
+
displayName: "VideoPicker__VideoListContainer",
|
|
63
|
+
componentId: "components-web__sc-x6lxp0-2"
|
|
64
|
+
})(["display:flex;justify-content:flex-start;position:relative;flex-grow:1;flex-direction:column;", ""], props => props.isFramed && framedVideoListContainerStyle);
|
|
65
|
+
|
|
66
|
+
const VideoPicker = _ref6 => {
|
|
67
|
+
var _videoList$;
|
|
68
|
+
|
|
69
|
+
let {
|
|
70
|
+
videoList = [],
|
|
71
|
+
selectedVideo = (_videoList$ = videoList[0]) === null || _videoList$ === void 0 ? void 0 : _videoList$.videoId,
|
|
72
|
+
frame,
|
|
73
|
+
...rest
|
|
74
|
+
} = _ref6;
|
|
75
|
+
const viewport = useViewport();
|
|
76
|
+
const {
|
|
77
|
+
stackViewDividerColor,
|
|
78
|
+
...themeTokens
|
|
79
|
+
} = useThemeTokens('VideoPicker');
|
|
80
|
+
const [currentVideoId, setCurrentVideoId] = useState(selectedVideo);
|
|
81
|
+
const videoPlayerRef = useRef(null);
|
|
82
|
+
const currentVideo = videoList.find(video => video.videoId === currentVideoId);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
// Update current video if parent changes which video id it passes down
|
|
85
|
+
setCurrentVideoId(selectedVideo);
|
|
86
|
+
}, [selectedVideo]); // `frame` variant should only work on larger screens
|
|
87
|
+
|
|
88
|
+
const isFramed = frame && [viewports.md, viewports.lg, viewports.xl].includes(viewport);
|
|
89
|
+
const hasSlider = !frame && [viewports.md, viewports.lg, viewports.xl].includes(viewport);
|
|
90
|
+
const listElements = videoList.map((video, index) => /*#__PURE__*/_jsx(VideoPickerThumbnail, {
|
|
91
|
+
video: video,
|
|
92
|
+
videoPlayerRef: videoPlayerRef,
|
|
93
|
+
selectedVideoId: currentVideoId,
|
|
94
|
+
onSelectVideo: current => setCurrentVideoId(current.videoId),
|
|
95
|
+
layout: !hasSlider ? 'horizontal' : 'vertical',
|
|
96
|
+
index: index,
|
|
97
|
+
isFramed: isFramed
|
|
98
|
+
}, video.videoId));
|
|
99
|
+
return /*#__PURE__*/_jsx(VideoPickerContainer, {
|
|
100
|
+
isFramed: isFramed,
|
|
101
|
+
...selectProps(rest),
|
|
102
|
+
...themeTokens,
|
|
103
|
+
children: /*#__PURE__*/_jsxs(StackView, {
|
|
104
|
+
divider: isFramed ? {
|
|
105
|
+
tokens: {
|
|
106
|
+
color: stackViewDividerColor
|
|
107
|
+
}
|
|
108
|
+
} : {
|
|
109
|
+
variant: {
|
|
110
|
+
decorative: true
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
space: isFramed ? 0 : 4 // everything has internal padding in `frame` variant
|
|
114
|
+
,
|
|
115
|
+
direction: isFramed ? 'row' : 'column',
|
|
116
|
+
children: [/*#__PURE__*/_jsx(VideoPlayerContainer, { ...themeTokens,
|
|
117
|
+
isFramed: isFramed,
|
|
118
|
+
children: /*#__PURE__*/_jsx(VideoPickerPlayer, {
|
|
119
|
+
video: currentVideo,
|
|
120
|
+
videoPlayerRef: videoPlayerRef
|
|
121
|
+
})
|
|
122
|
+
}), hasSlider ? /*#__PURE__*/_jsx(VideoSlider, {
|
|
123
|
+
children: listElements
|
|
124
|
+
}) : /*#__PURE__*/_jsx(VideoListContainer, {
|
|
125
|
+
viewport: viewport,
|
|
126
|
+
"data-testid": "video-list-container",
|
|
127
|
+
isFramed: isFramed,
|
|
128
|
+
children: listElements
|
|
129
|
+
})]
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
VideoPicker.propTypes = { ...selectedSystemPropTypes,
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Id of the currently selected video (defaults to the first video if not set).
|
|
138
|
+
*/
|
|
139
|
+
selectedVideo: PropTypes.string,
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* An array of Video objects.
|
|
143
|
+
*/
|
|
144
|
+
videoList: PropTypes.arrayOf(VideoPropType),
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Use to display the picker in a container and the playlist as a sidebar (only available for breakpoints LG and larger)
|
|
148
|
+
*/
|
|
149
|
+
frame: PropTypes.bool
|
|
150
|
+
};
|
|
151
|
+
export default VideoPicker;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StackView, Typography } from '@telus-uds/components-base';
|
|
3
|
+
import WebVideo from '../WebVideo/WebVideo';
|
|
4
|
+
import { VideoPropType, RefPropType } from './videoPropType';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
const VideoPickerPlayer = _ref => {
|
|
9
|
+
let {
|
|
10
|
+
video = {},
|
|
11
|
+
videoPlayerRef
|
|
12
|
+
} = _ref;
|
|
13
|
+
return /*#__PURE__*/_jsxs(StackView, {
|
|
14
|
+
space: 3,
|
|
15
|
+
tokens: {
|
|
16
|
+
flexShrink: 1
|
|
17
|
+
},
|
|
18
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
19
|
+
ref: videoPlayerRef,
|
|
20
|
+
children: video.videoId && /*#__PURE__*/_jsx(WebVideo, { ...video
|
|
21
|
+
})
|
|
22
|
+
}), /*#__PURE__*/_jsxs(StackView, {
|
|
23
|
+
space: 2,
|
|
24
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
25
|
+
variant: {
|
|
26
|
+
size: 'h2',
|
|
27
|
+
colour: 'secondary'
|
|
28
|
+
},
|
|
29
|
+
children: video.title
|
|
30
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
31
|
+
children: video.description
|
|
32
|
+
})]
|
|
33
|
+
})]
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
VideoPickerPlayer.propTypes = {
|
|
38
|
+
video: VideoPropType,
|
|
39
|
+
videoPlayerRef: RefPropType
|
|
40
|
+
};
|
|
41
|
+
export default VideoPickerPlayer;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Pressable from "react-native-web/dist/exports/Pressable";
|
|
3
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import { viewports } from '@telus-uds/system-constants';
|
|
6
|
+
import styled from 'styled-components';
|
|
7
|
+
import { StackView, Typography, useViewport, horizontalScrollUtils, useThemeTokens } from '@telus-uds/components-base';
|
|
8
|
+
import { getTimestamp } from '../shared/VideoSplash/helpers';
|
|
9
|
+
import { VideoPropType, RefPropType } from './videoPropType';
|
|
10
|
+
import VideoSplash from '../shared/VideoSplash/VideoSplash';
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
const {
|
|
14
|
+
getItemPositionLayoutHandler,
|
|
15
|
+
itemPositionsPropType
|
|
16
|
+
} = horizontalScrollUtils; // Use a React Native (web) outer container so it can take an onLayout callback, to
|
|
17
|
+
// access position in VideoSlider's UDS HorizontalScroll and update its itemPositions
|
|
18
|
+
|
|
19
|
+
const createReactNativeStyles = _ref => {
|
|
20
|
+
let {
|
|
21
|
+
pressablePaddingBottom,
|
|
22
|
+
pressablePaddingVertical,
|
|
23
|
+
pressablePaddingHorizontal,
|
|
24
|
+
pressableBorderTopWidth,
|
|
25
|
+
pressableBorderTopColor
|
|
26
|
+
} = _ref;
|
|
27
|
+
return StyleSheet.create({
|
|
28
|
+
container: {
|
|
29
|
+
cursor: 'pointer'
|
|
30
|
+
},
|
|
31
|
+
horizontal: {
|
|
32
|
+
paddingBottom: pressablePaddingBottom
|
|
33
|
+
},
|
|
34
|
+
framed: {
|
|
35
|
+
paddingVertical: pressablePaddingVertical,
|
|
36
|
+
paddingHorizontal: pressablePaddingHorizontal
|
|
37
|
+
},
|
|
38
|
+
framedLine: {
|
|
39
|
+
borderTopWidth: pressableBorderTopWidth,
|
|
40
|
+
borderTopColor: pressableBorderTopColor
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const VideoThumbnail = /*#__PURE__*/styled.div.withConfig({
|
|
46
|
+
displayName: "VideoPickerThumbnail__VideoThumbnail",
|
|
47
|
+
componentId: "components-web__sc-1glxurq-0"
|
|
48
|
+
})(["position:relative;width:", ";flex-shrink:0;* button{display:none;}&::before{content:'';display:block;padding-bottom:56.25%;}&::after{content:'';border:", "px solid;border-color:", ";border-radius:", "px;position:absolute;top:0;left:0;right:0;bottom:0;}& > div{border-radius:", "px;}"], props => props.layout === 'vertical' ? '100%' : '144px', _ref2 => {
|
|
49
|
+
let {
|
|
50
|
+
borderWidth
|
|
51
|
+
} = _ref2;
|
|
52
|
+
return borderWidth;
|
|
53
|
+
}, _ref3 => {
|
|
54
|
+
let {
|
|
55
|
+
isPlaying,
|
|
56
|
+
borderColor
|
|
57
|
+
} = _ref3;
|
|
58
|
+
return isPlaying ? borderColor : 'transparent';
|
|
59
|
+
}, _ref4 => {
|
|
60
|
+
let {
|
|
61
|
+
borderRadius
|
|
62
|
+
} = _ref4;
|
|
63
|
+
return borderRadius;
|
|
64
|
+
}, _ref5 => {
|
|
65
|
+
let {
|
|
66
|
+
borderRadius
|
|
67
|
+
} = _ref5;
|
|
68
|
+
return borderRadius;
|
|
69
|
+
});
|
|
70
|
+
const ThumbnailTitleContainer = /*#__PURE__*/styled.div.withConfig({
|
|
71
|
+
displayName: "VideoPickerThumbnail__ThumbnailTitleContainer",
|
|
72
|
+
componentId: "components-web__sc-1glxurq-1"
|
|
73
|
+
})(["display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;"]);
|
|
74
|
+
|
|
75
|
+
const VideoPickerThumbnail = _ref6 => {
|
|
76
|
+
let {
|
|
77
|
+
videoPlayerRef,
|
|
78
|
+
selectedVideoId,
|
|
79
|
+
video,
|
|
80
|
+
onSelectVideo,
|
|
81
|
+
layout = 'vertical',
|
|
82
|
+
isFramed,
|
|
83
|
+
itemPositions,
|
|
84
|
+
index,
|
|
85
|
+
width = '100%'
|
|
86
|
+
} = _ref6;
|
|
87
|
+
const viewport = useViewport();
|
|
88
|
+
const {
|
|
89
|
+
titleColor,
|
|
90
|
+
subTitleColor,
|
|
91
|
+
...themeTokens
|
|
92
|
+
} = useThemeTokens('VideoPickerThumbnail');
|
|
93
|
+
const rnStyles = createReactNativeStyles(themeTokens);
|
|
94
|
+
const {
|
|
95
|
+
timestamp
|
|
96
|
+
} = getTimestamp(video.videoLength, video.copy);
|
|
97
|
+
const isPlaying = selectedVideoId === video.videoId;
|
|
98
|
+
|
|
99
|
+
const renderThumbnailImage = () => /*#__PURE__*/_jsx(VideoThumbnail, { ...themeTokens,
|
|
100
|
+
isPlaying: isPlaying,
|
|
101
|
+
layout: layout,
|
|
102
|
+
children: /*#__PURE__*/_jsx(VideoSplash, {
|
|
103
|
+
simpleMode: true,
|
|
104
|
+
poster: video.posterSrc || `https://img.youtube.com/vi/${video.videoId}/maxresdefault.jpg`,
|
|
105
|
+
videoLength: video.videoLength,
|
|
106
|
+
copy: video.copy
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const renderThumbnailInfo = () => /*#__PURE__*/_jsxs(StackView, {
|
|
111
|
+
space: 2,
|
|
112
|
+
tokens: {
|
|
113
|
+
flexShrink: 1
|
|
114
|
+
},
|
|
115
|
+
children: [/*#__PURE__*/_jsx(ThumbnailTitleContainer, {
|
|
116
|
+
viewport: viewport,
|
|
117
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
118
|
+
variant: {
|
|
119
|
+
bold: true
|
|
120
|
+
},
|
|
121
|
+
tokens: {
|
|
122
|
+
color: isPlaying ? titleColor : 'none'
|
|
123
|
+
},
|
|
124
|
+
children: video.title
|
|
125
|
+
})
|
|
126
|
+
}), viewport !== viewports.xs && /*#__PURE__*/_jsx(Typography, {
|
|
127
|
+
variant: {
|
|
128
|
+
size: 'micro'
|
|
129
|
+
},
|
|
130
|
+
tokens: {
|
|
131
|
+
color: subTitleColor
|
|
132
|
+
},
|
|
133
|
+
children: timestamp
|
|
134
|
+
})]
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const handleLayout = itemPositions !== undefined ? getItemPositionLayoutHandler(itemPositions.positions, index) : undefined;
|
|
138
|
+
|
|
139
|
+
const onKeyPress = event => {
|
|
140
|
+
if (['Space', 'Enter'].includes(event.key)) {
|
|
141
|
+
var _videoPlayerRef$curre;
|
|
142
|
+
|
|
143
|
+
onSelectVideo(video);
|
|
144
|
+
const splashButton = (_videoPlayerRef$curre = videoPlayerRef.current) === null || _videoPlayerRef$curre === void 0 ? void 0 : _videoPlayerRef$curre.querySelector('button');
|
|
145
|
+
if (splashButton) splashButton.focus();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
return /*#__PURE__*/_jsx(Pressable, {
|
|
150
|
+
onLayout: handleLayout,
|
|
151
|
+
onPress: () => onSelectVideo(video),
|
|
152
|
+
testID: `thumbnail-container-${video.videoId}`,
|
|
153
|
+
onKeyPress: onKeyPress,
|
|
154
|
+
accessibilityRole: "radio",
|
|
155
|
+
accessibilityState: {
|
|
156
|
+
checked: isPlaying
|
|
157
|
+
},
|
|
158
|
+
style: [rnStyles.container, layout === 'horizontal' && rnStyles.horizontal, isFramed && rnStyles.framed, isFramed && index > 0 && rnStyles.framedLine, {
|
|
159
|
+
width
|
|
160
|
+
}],
|
|
161
|
+
children: /*#__PURE__*/_jsxs(StackView, {
|
|
162
|
+
space: layout === 'vertical' ? 2 : 3,
|
|
163
|
+
direction: layout === 'vertical' ? 'column' : 'row',
|
|
164
|
+
children: [renderThumbnailImage(), renderThumbnailInfo()]
|
|
165
|
+
})
|
|
166
|
+
}, video.videoId);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
VideoPickerThumbnail.propTypes = {
|
|
170
|
+
selectedVideoId: PropTypes.string,
|
|
171
|
+
onSelectVideo: PropTypes.func,
|
|
172
|
+
video: VideoPropType,
|
|
173
|
+
videoPlayerRef: RefPropType,
|
|
174
|
+
layout: PropTypes.oneOf(['vertical', 'horizontal']),
|
|
175
|
+
isFramed: PropTypes.bool,
|
|
176
|
+
itemPositions: itemPositionsPropType,
|
|
177
|
+
index: PropTypes.number,
|
|
178
|
+
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
|
|
179
|
+
};
|
|
180
|
+
export default VideoPickerThumbnail;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { cloneElement, useState } from 'react';
|
|
2
|
+
import { HorizontalScroll, HorizontalScrollButton, horizontalScrollUtils, StackView, useThemeTokens, useViewport } from '@telus-uds/components-base';
|
|
3
|
+
import View from "react-native-web/dist/exports/View";
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
const {
|
|
7
|
+
useItemPositions
|
|
8
|
+
} = horizontalScrollUtils;
|
|
9
|
+
|
|
10
|
+
const VideoSlider = _ref => {
|
|
11
|
+
let {
|
|
12
|
+
children
|
|
13
|
+
} = _ref;
|
|
14
|
+
const viewport = useViewport();
|
|
15
|
+
const [itemPositions] = useItemPositions();
|
|
16
|
+
const [containerWidth, setContainerWidth] = useState(null);
|
|
17
|
+
const {
|
|
18
|
+
previousIcon: PreviousIcon,
|
|
19
|
+
nextIcon: NextIcon
|
|
20
|
+
} = useThemeTokens('VideoPickerSlider');
|
|
21
|
+
|
|
22
|
+
const onLayout = _ref2 => {
|
|
23
|
+
let {
|
|
24
|
+
nativeEvent: {
|
|
25
|
+
layout: {
|
|
26
|
+
width
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} = _ref2;
|
|
30
|
+
setContainerWidth(width);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const itemsGap = 24; // '4' on spacing scale
|
|
34
|
+
|
|
35
|
+
const itemsCount = viewport === 'lg' || viewport === 'xl' ? 4 : 3;
|
|
36
|
+
const itemGapPortioned = (itemsCount - 1) * itemsGap / itemsCount;
|
|
37
|
+
const itemWidth = containerWidth === null ? // For first render, we don't know container width, so avoid flicker with static % width
|
|
38
|
+
`calc(${Math.round(100 / itemsCount)}% - ${Math.round(itemGapPortioned)}px)` : // After first render, can't use % widths because parent is > 100% width horizontal scroll area
|
|
39
|
+
Math.max(containerWidth / itemsCount - itemGapPortioned, 0 // Prevent negative width breaking layout on very narrow containers
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const content = /*#__PURE__*/_jsx(StackView, {
|
|
43
|
+
space: 4,
|
|
44
|
+
direction: "row",
|
|
45
|
+
accessibilityRole: "radiogroup",
|
|
46
|
+
tokens: {
|
|
47
|
+
flexGrow: 1
|
|
48
|
+
},
|
|
49
|
+
children: React.Children.map(children, (child, index) => /*#__PURE__*/cloneElement(child, {
|
|
50
|
+
index,
|
|
51
|
+
itemPositions,
|
|
52
|
+
width: itemWidth
|
|
53
|
+
}))
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const overflow = containerWidth === null && {
|
|
57
|
+
overflow: 'hidden'
|
|
58
|
+
};
|
|
59
|
+
const horizontalScrollTokens = {
|
|
60
|
+
nextIcon: NextIcon,
|
|
61
|
+
previousIcon: PreviousIcon,
|
|
62
|
+
gutter: 0,
|
|
63
|
+
borderBottomWidth: 0,
|
|
64
|
+
borderBottomColor: 'transparent',
|
|
65
|
+
buttonClearance: 0
|
|
66
|
+
};
|
|
67
|
+
return /*#__PURE__*/_jsx(View, {
|
|
68
|
+
onLayout: onLayout,
|
|
69
|
+
style: overflow,
|
|
70
|
+
children: containerWidth === null ? // Use a 100% width non-scrollable parent until containerWidth is known, to avoid flicker
|
|
71
|
+
content : /*#__PURE__*/_jsx(HorizontalScroll, {
|
|
72
|
+
ScrollButton: HorizontalScrollButton,
|
|
73
|
+
itemPositions: itemPositions,
|
|
74
|
+
tokens: horizontalScrollTokens,
|
|
75
|
+
children: content
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
VideoSlider.propTypes = {
|
|
81
|
+
children: PropTypes.node
|
|
82
|
+
};
|
|
83
|
+
export default VideoSlider;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import { VideoProps } from '../WebVideo/WebVideo';
|
|
3
|
+
export const VideoPropType = PropTypes.shape({ ...VideoProps,
|
|
4
|
+
title: PropTypes.string,
|
|
5
|
+
description: PropTypes.string
|
|
6
|
+
});
|
|
7
|
+
export const RefPropType = PropTypes.shape({
|
|
8
|
+
current: PropTypes.object
|
|
9
|
+
});
|
package/lib-module/index.js
CHANGED
|
@@ -27,8 +27,12 @@ export { default as WebVideo } from './WebVideo';
|
|
|
27
27
|
export { default as WaffleGrid } from './WaffleGrid';
|
|
28
28
|
export { default as Spinner } from './Spinner';
|
|
29
29
|
export { default as Listbox } from './Listbox';
|
|
30
|
+
export { default as VideoPicker } from './VideoPicker';
|
|
30
31
|
export { default as Video } from './Video';
|
|
31
32
|
export { default as StoryCard } from './StoryCard';
|
|
33
|
+
export { default as Disclaimer } from './Disclaimer';
|
|
32
34
|
export { default as Card } from './Card';
|
|
33
35
|
export { default as TermsAndConditions } from './TermsAndConditions';
|
|
36
|
+
export { default as NavigationBar } from './NavigationBar';
|
|
37
|
+
export { default as Progress } from './Progress';
|
|
34
38
|
export * from './baseExports';
|
package/package.json
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
],
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@gorhom/portal": "^1.0.14",
|
|
8
|
-
"@telus-uds/components-base": "1.
|
|
8
|
+
"@telus-uds/components-base": "1.40.0",
|
|
9
9
|
"@telus-uds/system-constants": "^1.2.0",
|
|
10
10
|
"fscreen": "^1.2.0",
|
|
11
11
|
"lodash.omit": "^4.5.0",
|
|
12
12
|
"react-dates": "^21.8.0",
|
|
13
13
|
"react-helmet-async": "^1.3.0",
|
|
14
14
|
"react-moment-proptypes": "^1.8.1",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^2.25.0",
|
|
16
16
|
"prop-types": "^15.7.2",
|
|
17
17
|
"lodash.throttle": "^4.1.1",
|
|
18
18
|
"react-youtube": "^10.1.0"
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"skip": true
|
|
62
62
|
},
|
|
63
63
|
"types": "types/index.d.ts",
|
|
64
|
-
"version": "1.
|
|
64
|
+
"version": "1.11.0"
|
|
65
65
|
}
|
|
@@ -22,7 +22,8 @@ const StyledList = styled.ol({
|
|
|
22
22
|
listStyle: 'none',
|
|
23
23
|
listStylePosition: 'inside',
|
|
24
24
|
margin: 0,
|
|
25
|
-
padding: 0
|
|
25
|
+
padding: 0,
|
|
26
|
+
alignItems: 'baseline'
|
|
26
27
|
})
|
|
27
28
|
|
|
28
29
|
const omitProps = ({
|
|
@@ -149,7 +150,7 @@ const Breadcrumbs = ({
|
|
|
149
150
|
)
|
|
150
151
|
|
|
151
152
|
return (
|
|
152
|
-
<nav {...selectProps(rest)}>
|
|
153
|
+
<nav aria-label="Breadcrumb" {...selectProps(rest)}>
|
|
153
154
|
<StyledList>
|
|
154
155
|
{items.map(
|
|
155
156
|
({
|
|
@@ -169,7 +170,7 @@ const Breadcrumbs = ({
|
|
|
169
170
|
key={href}
|
|
170
171
|
linkRouterProps={{ ...linkRouterProps, itemLinkRouterProps }}
|
|
171
172
|
reactRouterLinkComponent={linkComponent}
|
|
172
|
-
variant={variant}
|
|
173
|
+
variant={{ ...variant, size: 'micro' }}
|
|
173
174
|
LinkRouter={ItemLinkRouter}
|
|
174
175
|
>
|
|
175
176
|
{breadcrumbName}
|
|
@@ -4,6 +4,7 @@ import styled from 'styled-components'
|
|
|
4
4
|
import {
|
|
5
5
|
Link,
|
|
6
6
|
Typography,
|
|
7
|
+
applyTextStyles,
|
|
7
8
|
clickProps,
|
|
8
9
|
selectSystemProps,
|
|
9
10
|
useThemeTokens,
|
|
@@ -22,7 +23,8 @@ const IconContainer = styled.span({
|
|
|
22
23
|
display: 'inline-flex',
|
|
23
24
|
alignItems: 'center',
|
|
24
25
|
paddingLeft: ({ iconPadding }) => `${iconPadding}px`,
|
|
25
|
-
paddingRight: ({ iconPadding }) => `${iconPadding}px
|
|
26
|
+
paddingRight: ({ iconPadding }) => `${iconPadding}px`,
|
|
27
|
+
fontFamily: ({ fontName, fontWeight }) => applyTextStyles({ fontName, fontWeight }).fontFamily
|
|
26
28
|
})
|
|
27
29
|
|
|
28
30
|
const Item = forwardRef(
|
|
@@ -41,6 +43,10 @@ const Item = forwardRef(
|
|
|
41
43
|
const {
|
|
42
44
|
iconColor,
|
|
43
45
|
icon: ChevronRightIcon,
|
|
46
|
+
currentColor,
|
|
47
|
+
color,
|
|
48
|
+
iconSize,
|
|
49
|
+
fontSize,
|
|
44
50
|
...themeTokens
|
|
45
51
|
} = useThemeTokens('Breadcrumbs', tokens, variant)
|
|
46
52
|
|
|
@@ -55,12 +61,15 @@ const Item = forwardRef(
|
|
|
55
61
|
return (
|
|
56
62
|
<StyledItemContainer {...themeTokens}>
|
|
57
63
|
{current ? (
|
|
58
|
-
<Typography
|
|
64
|
+
<Typography tokens={{ color: currentColor, fontSize }} variant={{ ...variant }}>
|
|
65
|
+
{children}
|
|
66
|
+
</Typography>
|
|
59
67
|
) : (
|
|
60
68
|
<>
|
|
61
69
|
{ReactRouterLink ? (
|
|
62
70
|
<ReactRouterLink
|
|
63
71
|
{...linkOptions}
|
|
72
|
+
tokens={{ color, blockFontSize: fontSize }}
|
|
64
73
|
// TODO refactor
|
|
65
74
|
// eslint-disable-next-line react/no-unstable-nested-components
|
|
66
75
|
component={(props) => {
|
|
@@ -71,12 +80,17 @@ const Item = forwardRef(
|
|
|
71
80
|
{children}
|
|
72
81
|
</ReactRouterLink>
|
|
73
82
|
) : (
|
|
74
|
-
<Link
|
|
83
|
+
<Link
|
|
84
|
+
{...linkOptions}
|
|
85
|
+
tokens={{ color, blockFontSize: fontSize }}
|
|
86
|
+
ref={ref}
|
|
87
|
+
variant={variant}
|
|
88
|
+
>
|
|
75
89
|
{children}
|
|
76
90
|
</Link>
|
|
77
91
|
)}
|
|
78
92
|
<IconContainer {...themeTokens}>
|
|
79
|
-
<ChevronRightIcon size={
|
|
93
|
+
<ChevronRightIcon size={iconSize} color={iconColor} />
|
|
80
94
|
</IconContainer>
|
|
81
95
|
</>
|
|
82
96
|
)}
|
package/src/Callout/Callout.jsx
CHANGED
|
@@ -7,6 +7,20 @@ import { htmlAttrs } from '../utils'
|
|
|
7
7
|
|
|
8
8
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
|
|
9
9
|
|
|
10
|
+
const getAlignment = (rounded, textAlignToFlex) => {
|
|
11
|
+
if (textAlignToFlex) {
|
|
12
|
+
switch (textAlignToFlex) {
|
|
13
|
+
case 'left':
|
|
14
|
+
return 'flex-star'
|
|
15
|
+
case 'center':
|
|
16
|
+
return 'center'
|
|
17
|
+
default:
|
|
18
|
+
return 'flex-start'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return rounded ? 'center' : ' flex-start'
|
|
22
|
+
}
|
|
23
|
+
|
|
10
24
|
const verticalAlignToFlex = (verticalAlign) => {
|
|
11
25
|
switch (verticalAlign) {
|
|
12
26
|
case 'top':
|
|
@@ -21,18 +35,26 @@ const verticalAlignToFlex = (verticalAlign) => {
|
|
|
21
35
|
}
|
|
22
36
|
|
|
23
37
|
const CalloutContainer = styled.div(
|
|
24
|
-
({ rounded, verticalAlign
|
|
38
|
+
({ rounded, verticalAlign, textAlignToFlex, background, gap, borderRadius, padding }) => ({
|
|
25
39
|
background,
|
|
26
40
|
display: 'flex',
|
|
27
41
|
gap,
|
|
28
42
|
borderRadius,
|
|
29
43
|
padding,
|
|
30
|
-
justifyContent:
|
|
44
|
+
justifyContent: getAlignment(rounded, textAlignToFlex),
|
|
31
45
|
alignItems: verticalAlignToFlex(verticalAlign)
|
|
32
46
|
})
|
|
33
47
|
)
|
|
34
48
|
|
|
35
|
-
const Callout = ({
|
|
49
|
+
const Callout = ({
|
|
50
|
+
icon,
|
|
51
|
+
children,
|
|
52
|
+
verticalAlign,
|
|
53
|
+
textAlignToFlex,
|
|
54
|
+
tokens,
|
|
55
|
+
variant = {},
|
|
56
|
+
...rest
|
|
57
|
+
}) => {
|
|
36
58
|
const {
|
|
37
59
|
background,
|
|
38
60
|
gap,
|
|
@@ -52,6 +74,7 @@ const Callout = ({ icon, children, verticalAlign = 'top', tokens, variant = {},
|
|
|
52
74
|
rounded={rounded}
|
|
53
75
|
data-testid="callout-container"
|
|
54
76
|
verticalAlign={verticalAlign}
|
|
77
|
+
textAlignToFlex={textAlignToFlex}
|
|
55
78
|
background={background}
|
|
56
79
|
gap={gap}
|
|
57
80
|
borderRadius={borderRadius}
|
|
@@ -70,6 +93,7 @@ Callout.propTypes = {
|
|
|
70
93
|
...selectedSystemPropTypes,
|
|
71
94
|
icon: PropTypes.elementType,
|
|
72
95
|
children: PropTypes.node.isRequired,
|
|
96
|
+
textAlignToFlex: PropTypes.oneOf(['center', 'left']),
|
|
73
97
|
verticalAlign: PropTypes.oneOf(['top', 'middle', 'bottom'])
|
|
74
98
|
}
|
|
75
99
|
|