@telus-uds/components-web 2.13.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -2
- package/component-docs.json +46 -19
- package/lib/Badge/Badge.js +10 -1
- package/lib/DatePicker/DatePicker.js +8 -1
- package/lib/QuantitySelector/QuantitySelector.js +67 -66
- package/lib/QuantitySelector/SideButton.js +93 -0
- package/lib/QuantitySelector/styles.js +4 -20
- package/lib/TermsAndConditions/TermsAndConditions.js +21 -4
- package/lib/Testimonial/Testimonial.js +48 -12
- package/lib-module/Badge/Badge.js +10 -1
- package/lib-module/DatePicker/DatePicker.js +7 -1
- package/lib-module/QuantitySelector/QuantitySelector.js +68 -67
- package/lib-module/QuantitySelector/SideButton.js +80 -0
- package/lib-module/QuantitySelector/styles.js +3 -15
- package/lib-module/TermsAndConditions/TermsAndConditions.js +20 -4
- package/lib-module/Testimonial/Testimonial.js +49 -13
- package/package.json +4 -4
- package/src/Badge/Badge.jsx +14 -2
- package/src/DatePicker/DatePicker.jsx +7 -1
- package/src/QuantitySelector/QuantitySelector.jsx +60 -76
- package/src/QuantitySelector/SideButton.jsx +74 -0
- package/src/QuantitySelector/styles.js +4 -70
- package/src/TermsAndConditions/TermsAndConditions.jsx +30 -4
- package/src/Testimonial/Testimonial.jsx +73 -11
package/src/Badge/Badge.jsx
CHANGED
|
@@ -42,7 +42,8 @@ const Badge = ({ children, tokens, variant = {}, ...rest }) => {
|
|
|
42
42
|
paddingTop,
|
|
43
43
|
paddingBottom,
|
|
44
44
|
fontName,
|
|
45
|
-
fontWeight
|
|
45
|
+
fontWeight,
|
|
46
|
+
fontSize
|
|
46
47
|
} = useThemeTokens('Badge', tokens, variant)
|
|
47
48
|
|
|
48
49
|
const semanticGradient = gradient && transformGradient(gradient)
|
|
@@ -56,6 +57,12 @@ const Badge = ({ children, tokens, variant = {}, ...rest }) => {
|
|
|
56
57
|
background = semanticGradient
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
const fontSizeMapping = {
|
|
61
|
+
12: 'micro',
|
|
62
|
+
14: 'small',
|
|
63
|
+
16: 'h6'
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
return (
|
|
60
67
|
<BadgeContainer
|
|
61
68
|
isOutlineOffer={isOutlineOffer}
|
|
@@ -69,7 +76,12 @@ const Badge = ({ children, tokens, variant = {}, ...rest }) => {
|
|
|
69
76
|
border={`${borderWidth}px solid ${borderColor}`}
|
|
70
77
|
{...selectProps(rest)}
|
|
71
78
|
>
|
|
72
|
-
<Typography
|
|
79
|
+
<Typography
|
|
80
|
+
tokens={{ fontName, fontWeight, color }}
|
|
81
|
+
variant={{ size: fontSizeMapping[fontSize] }}
|
|
82
|
+
>
|
|
83
|
+
{children}
|
|
84
|
+
</Typography>
|
|
73
85
|
</BadgeContainer>
|
|
74
86
|
)
|
|
75
87
|
}
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
applyTextStyles
|
|
16
16
|
} from '@telus-uds/components-base'
|
|
17
17
|
import moment from 'moment'
|
|
18
|
+
import { isUndefined } from 'lodash'
|
|
18
19
|
import CalendarContainer from './CalendarContainer'
|
|
19
20
|
import dictionary from './dictionary'
|
|
20
21
|
import { htmlAttrs } from '../utils'
|
|
@@ -106,7 +107,11 @@ const DatePicker = forwardRef(
|
|
|
106
107
|
const [isClickedInside, setIsClickedInside] = useState(false)
|
|
107
108
|
const getCopy = useCopy({ dictionary, copy })
|
|
108
109
|
useEffect(() => {
|
|
109
|
-
|
|
110
|
+
/**
|
|
111
|
+
* `date` could be passed as `null` to reset the value so explicitly
|
|
112
|
+
* checking for not being `undefined`
|
|
113
|
+
*/
|
|
114
|
+
if (!isUndefined(date) && !moment(date).isSame(inputDate)) {
|
|
110
115
|
setInputDate(date)
|
|
111
116
|
setInputText(date instanceof moment ? date.format(dateFormat) : '')
|
|
112
117
|
}
|
|
@@ -139,6 +144,7 @@ const DatePicker = forwardRef(
|
|
|
139
144
|
const onChange = (value) => {
|
|
140
145
|
setInputDate(value)
|
|
141
146
|
setInputText(value.format(dateFormat))
|
|
147
|
+
setIsFocused(false)
|
|
142
148
|
if (onDateChange) onDateChange(value)
|
|
143
149
|
}
|
|
144
150
|
const onChangeInput = (value) => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import {
|
|
4
|
-
getThemeTokens,
|
|
5
4
|
Box,
|
|
6
5
|
TextInput,
|
|
7
6
|
Spacer,
|
|
@@ -9,13 +8,12 @@ import {
|
|
|
9
8
|
InputLabel,
|
|
10
9
|
useInputValue,
|
|
11
10
|
useCopy,
|
|
12
|
-
|
|
13
|
-
useTheme
|
|
11
|
+
useThemeTokensCallback
|
|
14
12
|
} from '@telus-uds/components-base'
|
|
15
13
|
|
|
16
|
-
import
|
|
17
|
-
import { InputField, InputWrapper, LeftButtonWrapper, RightButtonWrapper } from './styles'
|
|
14
|
+
import { InputField, InputWrapper } from './styles'
|
|
18
15
|
import defaultDictionary from './dictionary'
|
|
16
|
+
import SideButton from './SideButton'
|
|
19
17
|
|
|
20
18
|
const { isNaN } = Number
|
|
21
19
|
|
|
@@ -28,6 +26,7 @@ const QuantitySelector = ({
|
|
|
28
26
|
minNumber,
|
|
29
27
|
maxNumber,
|
|
30
28
|
defaultValue,
|
|
29
|
+
value,
|
|
31
30
|
label,
|
|
32
31
|
hint,
|
|
33
32
|
hintPosition,
|
|
@@ -40,13 +39,8 @@ const QuantitySelector = ({
|
|
|
40
39
|
tokens,
|
|
41
40
|
testID
|
|
42
41
|
}) => {
|
|
43
|
-
const {
|
|
44
|
-
components: { QuantitySelector: componentTheme }
|
|
45
|
-
} = useTheme()
|
|
46
|
-
|
|
47
|
-
const { leftIcon, rightIcon, padding } = useThemeTokens('QuantitySelector', tokens, variant)
|
|
42
|
+
const { disabled } = variant
|
|
48
43
|
const [error, setError] = useState('')
|
|
49
|
-
const { alternative } = variant
|
|
50
44
|
const getCopy = useCopy({ dictionary, copy })
|
|
51
45
|
|
|
52
46
|
const getValidatedNumber = (numberToEvaluate) => {
|
|
@@ -58,16 +52,14 @@ const QuantitySelector = ({
|
|
|
58
52
|
return numberToEvaluate
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
const initialValue = getValidatedNumber(defaultValue)
|
|
62
|
-
|
|
63
55
|
const { currentValue: number, setValue: setNumber } = useInputValue({
|
|
64
|
-
value:
|
|
65
|
-
initialValue,
|
|
56
|
+
value: getValidatedNumber(value),
|
|
57
|
+
initialValue: getValidatedNumber(defaultValue),
|
|
66
58
|
onChange
|
|
67
59
|
})
|
|
68
60
|
|
|
69
|
-
const isDecreaseEnabled = !isNumber(minNumber) || number > minNumber
|
|
70
|
-
const isIncreaseEnabled = !isNumber(maxNumber) || number < maxNumber
|
|
61
|
+
const isDecreaseEnabled = (!disabled && !isNumber(minNumber)) || number > minNumber
|
|
62
|
+
const isIncreaseEnabled = (!disabled && !isNumber(maxNumber)) || number < maxNumber
|
|
71
63
|
const inputValue = isNumber(number) ? number.toString() : ''
|
|
72
64
|
|
|
73
65
|
const updateNumber = (newNumber, originalInputEvent) => {
|
|
@@ -101,24 +93,34 @@ const QuantitySelector = ({
|
|
|
101
93
|
/>
|
|
102
94
|
) : null
|
|
103
95
|
|
|
96
|
+
const getTokens = useThemeTokensCallback('QuantitySelector', tokens, variant)
|
|
97
|
+
|
|
104
98
|
const renderTextInput = () => (
|
|
105
99
|
<TextInput
|
|
106
100
|
nativeID={id}
|
|
107
101
|
value={inputValue}
|
|
102
|
+
defaultValue={defaultValue}
|
|
108
103
|
tokens={(textInputState) => {
|
|
109
|
-
const {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
const {
|
|
105
|
+
inputWidth,
|
|
106
|
+
inputBorderWidth,
|
|
107
|
+
inputBorderColor,
|
|
108
|
+
textColor,
|
|
109
|
+
inputBackgroundColor,
|
|
110
|
+
...rest
|
|
111
|
+
} = getTokens({
|
|
112
|
+
...textInputState
|
|
113
|
+
})
|
|
116
114
|
return {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
...rest,
|
|
116
|
+
order: 1,
|
|
117
|
+
borderWidth: inputBorderWidth,
|
|
118
|
+
backgroundColor: inputBackgroundColor,
|
|
119
|
+
color: textColor,
|
|
120
|
+
width: inputWidth,
|
|
120
121
|
borderColor: inputBorderColor,
|
|
121
|
-
|
|
122
|
+
borderRadius: 0,
|
|
123
|
+
outerBorderWidth: 0
|
|
122
124
|
}
|
|
123
125
|
}}
|
|
124
126
|
onChange={inputChangeHandler}
|
|
@@ -133,58 +135,34 @@ const QuantitySelector = ({
|
|
|
133
135
|
/>
|
|
134
136
|
)
|
|
135
137
|
|
|
136
|
-
const getButtonTokens = (isEnabled) => (buttonState) => {
|
|
137
|
-
const disabled = !isEnabled
|
|
138
|
-
const { ...buttonTokens } = getThemeTokens(componentTheme, tokens, variant, {
|
|
139
|
-
...buttonState,
|
|
140
|
-
disabled
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
...buttonTokens,
|
|
145
|
-
outerBorderGap: 0,
|
|
146
|
-
padding
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const renderLeftButton = () => {
|
|
151
|
-
return (
|
|
152
|
-
<IconButton
|
|
153
|
-
icon={leftIcon}
|
|
154
|
-
tokens={getButtonTokens(isDecreaseEnabled)}
|
|
155
|
-
onPress={(event) => updateNumber(number - 1, event)}
|
|
156
|
-
onDoubleClick={(event) => updateNumber(number - 1, event)}
|
|
157
|
-
accessibilityLabel={getCopy('accessibility').decreaseButton}
|
|
158
|
-
accessibilityDisabled={!isDecreaseEnabled}
|
|
159
|
-
/>
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const renderRightButton = () => (
|
|
164
|
-
<IconButton
|
|
165
|
-
icon={rightIcon}
|
|
166
|
-
tokens={getButtonTokens(isIncreaseEnabled)}
|
|
167
|
-
onPress={() => updateNumber(number + 1)}
|
|
168
|
-
onDoubleClick={() => updateNumber(number + 1)}
|
|
169
|
-
accessibilityLabel={getCopy('accessibility').increaseButton}
|
|
170
|
-
accessibilityDisabled={!isIncreaseEnabled}
|
|
171
|
-
/>
|
|
172
|
-
)
|
|
173
|
-
|
|
174
138
|
return (
|
|
175
139
|
<Box space={2} testID={testID}>
|
|
176
140
|
{renderLabel()}
|
|
177
141
|
<Spacer space={2} />
|
|
178
142
|
<InputWrapper>
|
|
179
|
-
<InputField
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
143
|
+
<InputField>{renderTextInput()}</InputField>
|
|
144
|
+
<div style={{ order: 0 }}>
|
|
145
|
+
<SideButton
|
|
146
|
+
isEnabled={isDecreaseEnabled}
|
|
147
|
+
onPress={() => updateNumber(number - 1)}
|
|
148
|
+
onDoubleClick={() => updateNumber(number - 1)}
|
|
149
|
+
tokens={tokens}
|
|
150
|
+
variant={{ decrease: true, ...variant }}
|
|
151
|
+
accessibilityLabel={getCopy('accessibility').decreaseButton}
|
|
152
|
+
accessibilityDisabled={!isDecreaseEnabled}
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
<div style={{ order: 2 }}>
|
|
156
|
+
<SideButton
|
|
157
|
+
isEnabled={isIncreaseEnabled}
|
|
158
|
+
onPress={() => updateNumber(number + 1)}
|
|
159
|
+
onDoubleClick={() => updateNumber(number + 1)}
|
|
160
|
+
accessibilityLabel={getCopy('accessibility').increaseButton}
|
|
161
|
+
accessibilityDisabled={!isIncreaseEnabled}
|
|
162
|
+
tokens={tokens}
|
|
163
|
+
variant={{ increase: true, ...variant }}
|
|
164
|
+
/>
|
|
165
|
+
</div>
|
|
188
166
|
</InputWrapper>
|
|
189
167
|
{error ? (
|
|
190
168
|
<Box vertical={2}>
|
|
@@ -230,6 +208,11 @@ QuantitySelector.propTypes = {
|
|
|
230
208
|
* The default value of the input field
|
|
231
209
|
*/
|
|
232
210
|
defaultValue: PropTypes.number,
|
|
211
|
+
/**
|
|
212
|
+
* If the input's state is to be controlled by a parent component, use this prop
|
|
213
|
+
* together with the `onChange` to pass down and update the lifted state.
|
|
214
|
+
*/
|
|
215
|
+
value: PropTypes.number,
|
|
233
216
|
/**
|
|
234
217
|
* The label of the input field
|
|
235
218
|
*/
|
|
@@ -262,7 +245,8 @@ QuantitySelector.propTypes = {
|
|
|
262
245
|
*/
|
|
263
246
|
copy: PropTypes.oneOfType([PropTypes.oneOf(['en', 'fr'])]),
|
|
264
247
|
variant: PropTypes.exact({
|
|
265
|
-
alternative: PropTypes.bool
|
|
248
|
+
alternative: PropTypes.bool,
|
|
249
|
+
disabled: PropTypes.bool
|
|
266
250
|
}),
|
|
267
251
|
tokens: PropTypes.oneOf([PropTypes.object, PropTypes.func]),
|
|
268
252
|
/**
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { IconButton, useThemeTokensCallback } from '@telus-uds/components-base'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
const SideButton = ({
|
|
6
|
+
isEnabled,
|
|
7
|
+
onPress,
|
|
8
|
+
onDoubleClick,
|
|
9
|
+
accessibilityLabel,
|
|
10
|
+
accessibilityDisabled,
|
|
11
|
+
tokens,
|
|
12
|
+
variant
|
|
13
|
+
}) => {
|
|
14
|
+
const getTokens = useThemeTokensCallback('QuantitySelectorSideButton', tokens, variant)
|
|
15
|
+
const getButtonTokens = ({ buttonState, disabled }) => {
|
|
16
|
+
const {
|
|
17
|
+
borderRadius,
|
|
18
|
+
borderTopLeftRadius,
|
|
19
|
+
borderTopRightRadius,
|
|
20
|
+
borderBottomLeftRadius,
|
|
21
|
+
borderBottomRightRadius,
|
|
22
|
+
...rest
|
|
23
|
+
} = getTokens({ ...buttonState, disabled })
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...rest,
|
|
27
|
+
borderRadius,
|
|
28
|
+
borderTopLeftRadius,
|
|
29
|
+
borderTopRightRadius,
|
|
30
|
+
borderBottomLeftRadius,
|
|
31
|
+
borderBottomRightRadius,
|
|
32
|
+
outerBorderRadius: borderRadius,
|
|
33
|
+
outerBorderTopLeftRadius: borderTopLeftRadius,
|
|
34
|
+
outerBorderTopRightRadius: borderTopRightRadius,
|
|
35
|
+
outerBorderBottomLeftRadius: borderBottomLeftRadius,
|
|
36
|
+
outerBorderBottomRightRadius: borderBottomRightRadius,
|
|
37
|
+
outerBorderGap: 0,
|
|
38
|
+
outerBorderWidth: 0
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<IconButton
|
|
44
|
+
tokens={(buttonState) => getButtonTokens({ disabled: !isEnabled, buttonState })}
|
|
45
|
+
onPress={onPress}
|
|
46
|
+
onDoubleClick={onDoubleClick}
|
|
47
|
+
accessibilityLabel={accessibilityLabel}
|
|
48
|
+
accessibilityDisabled={accessibilityDisabled}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
SideButton.displayName = 'QuantitySelectorSideButton'
|
|
54
|
+
|
|
55
|
+
SideButton.defaultProps = {
|
|
56
|
+
isEnabled: true,
|
|
57
|
+
onPress: () => {},
|
|
58
|
+
onDoubleClick: () => {},
|
|
59
|
+
accessibilityLabel: '',
|
|
60
|
+
accessibilityDisabled: false,
|
|
61
|
+
tokens: {},
|
|
62
|
+
variant: {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
SideButton.propTypes = {
|
|
66
|
+
isEnabled: PropTypes.bool,
|
|
67
|
+
onPress: PropTypes.func,
|
|
68
|
+
onDoubleClick: PropTypes.func,
|
|
69
|
+
accessibilityLabel: PropTypes.string,
|
|
70
|
+
accessibilityDisabled: PropTypes.bool,
|
|
71
|
+
tokens: PropTypes.object,
|
|
72
|
+
variant: PropTypes.object
|
|
73
|
+
}
|
|
74
|
+
export default SideButton
|
|
@@ -1,83 +1,17 @@
|
|
|
1
1
|
import styled from 'styled-components'
|
|
2
2
|
|
|
3
3
|
export const InputField = styled.div`
|
|
4
|
-
order:
|
|
5
|
-
min-width: 3.5rem;
|
|
6
|
-
max-width: 5 rem;
|
|
7
|
-
height: 28px;
|
|
8
|
-
padding: 0;
|
|
9
|
-
width: 64px;
|
|
4
|
+
order: 1;
|
|
10
5
|
text-align: center;
|
|
11
6
|
z-index: 10;
|
|
12
7
|
input {
|
|
13
8
|
text-align: center;
|
|
14
9
|
}
|
|
15
|
-
|
|
16
|
-
&.alternative {
|
|
17
|
-
input {
|
|
18
|
-
height: 40px;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
const ButtonWrapper = styled.div`
|
|
24
|
-
&.alternative {
|
|
25
|
-
div[role='button'] {
|
|
26
|
-
height: 42px;
|
|
27
|
-
> div {
|
|
28
|
-
height: 40px;
|
|
29
|
-
> div {
|
|
30
|
-
padding: 12px 16px;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
export const LeftButtonWrapper = styled(ButtonWrapper)`
|
|
38
|
-
order: 0;
|
|
39
|
-
div[role='button'] {
|
|
40
|
-
border-radius: 4px 0px 0px 4px !important;
|
|
41
|
-
> div {
|
|
42
|
-
border-right: none;
|
|
43
|
-
border-radius: 4px 0px 0px 4px !important;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
&.alternative {
|
|
48
|
-
div[role='button'] {
|
|
49
|
-
border-radius: 36px 0px 0px 36px !important;
|
|
50
|
-
> div {
|
|
51
|
-
border-radius: 24px 0px 0px 24px !important;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
`
|
|
56
|
-
|
|
57
|
-
export const RightButtonWrapper = styled(ButtonWrapper)`
|
|
58
|
-
order: 3;
|
|
59
|
-
div[role='button'] {
|
|
60
|
-
border-radius: 0px 4px 4px 0px !important;
|
|
61
|
-
> div {
|
|
62
|
-
border-left: none;
|
|
63
|
-
border-radius: 0px 4px 4px 0px !important;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
&.alternative {
|
|
68
|
-
div[role='button'] {
|
|
69
|
-
border-radius: 0px 36px 36px 0px !important;
|
|
70
|
-
> div {
|
|
71
|
-
border-radius: 0px 36px 36px 0px !important;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
10
|
`
|
|
76
11
|
|
|
77
12
|
export const InputWrapper = styled.div`
|
|
78
|
-
|
|
13
|
+
text-align: start;
|
|
79
14
|
display: flex;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
justifycontent: center;
|
|
15
|
+
flex-direction: row;
|
|
16
|
+
flex-wrap: nowrap;
|
|
83
17
|
`
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import ExpandCollapse from './ExpandCollapse'
|
|
14
14
|
import OrderedListBase from '../OrderedList/OrderedListBase'
|
|
15
15
|
import { htmlAttrs, media, renderStructuredContent } from '../utils'
|
|
16
|
-
import
|
|
16
|
+
import defaultDictionary from './dictionary'
|
|
17
17
|
|
|
18
18
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
|
|
19
19
|
|
|
@@ -72,7 +72,18 @@ const NonIndexedContentTitle = styled.div(({ tokens }) => ({
|
|
|
72
72
|
* - Use `copy` to set language, ‘en’ for English or ‘fr’ for French
|
|
73
73
|
*/
|
|
74
74
|
const TermsAndConditions = forwardRef(
|
|
75
|
-
(
|
|
75
|
+
(
|
|
76
|
+
{
|
|
77
|
+
copy = 'en',
|
|
78
|
+
indexedContent,
|
|
79
|
+
nonIndexedContent,
|
|
80
|
+
tokens,
|
|
81
|
+
variant = {},
|
|
82
|
+
dictionary = defaultDictionary,
|
|
83
|
+
...rest
|
|
84
|
+
},
|
|
85
|
+
ref
|
|
86
|
+
) => {
|
|
76
87
|
const getCopy = useCopy({ dictionary, copy })
|
|
77
88
|
const hasIndexedContent = indexedContent.length > 0
|
|
78
89
|
const hasNonIndexedContent = nonIndexedContent.length > 0
|
|
@@ -135,6 +146,13 @@ const TermsAndConditions = forwardRef(
|
|
|
135
146
|
|
|
136
147
|
TermsAndConditions.displayName = 'TermsAndConditions'
|
|
137
148
|
|
|
149
|
+
// If a language dictionary entry is provided, it must contain every key
|
|
150
|
+
const dictionaryContentShape = PropTypes.shape({
|
|
151
|
+
headingHide: PropTypes.string.isRequired,
|
|
152
|
+
headingView: PropTypes.string.isRequired,
|
|
153
|
+
nonIndexedTitle: PropTypes.string.isRequired
|
|
154
|
+
})
|
|
155
|
+
|
|
138
156
|
TermsAndConditions.propTypes = {
|
|
139
157
|
...selectedSystemPropTypes,
|
|
140
158
|
/**
|
|
@@ -161,13 +179,21 @@ TermsAndConditions.propTypes = {
|
|
|
161
179
|
*
|
|
162
180
|
* nonIndexedContent do not have a corresponding superscript and instead apply to the page as a whole.
|
|
163
181
|
*/
|
|
164
|
-
nonIndexedContent: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.node, PropTypes.string]))
|
|
182
|
+
nonIndexedContent: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.node, PropTypes.string])),
|
|
183
|
+
/**
|
|
184
|
+
* Custom dictionary containing the labels to use for `TermsAndConditions`
|
|
185
|
+
*/
|
|
186
|
+
dictionary: PropTypes.shape({
|
|
187
|
+
en: dictionaryContentShape,
|
|
188
|
+
fr: dictionaryContentShape
|
|
189
|
+
})
|
|
165
190
|
}
|
|
166
191
|
|
|
167
192
|
TermsAndConditions.defaultProps = {
|
|
168
193
|
copy: 'en',
|
|
169
194
|
indexedContent: [],
|
|
170
|
-
nonIndexedContent: []
|
|
195
|
+
nonIndexedContent: [],
|
|
196
|
+
dictionary: defaultDictionary
|
|
171
197
|
}
|
|
172
198
|
|
|
173
199
|
export default TermsAndConditions
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import styled from 'styled-components'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Icon,
|
|
6
|
+
selectSystemProps,
|
|
7
|
+
Typography,
|
|
8
|
+
useThemeTokens,
|
|
9
|
+
useViewport
|
|
10
|
+
} from '@telus-uds/components-base'
|
|
5
11
|
import Image from '../Image'
|
|
6
12
|
import { htmlAttrs } from '../utils'
|
|
7
13
|
|
|
@@ -48,11 +54,13 @@ const Testimonial = ({
|
|
|
48
54
|
imageSrc,
|
|
49
55
|
image = imageSrc,
|
|
50
56
|
additionalInfo,
|
|
51
|
-
testimonialStyle = '
|
|
57
|
+
testimonialStyle = 'large',
|
|
52
58
|
tokens,
|
|
59
|
+
copy = 'en',
|
|
53
60
|
variant = {},
|
|
54
61
|
...rest
|
|
55
62
|
}) => {
|
|
63
|
+
const viewport = useViewport()
|
|
56
64
|
const {
|
|
57
65
|
testimonialContainerGap,
|
|
58
66
|
quoteContainerGap,
|
|
@@ -61,13 +69,43 @@ const Testimonial = ({
|
|
|
61
69
|
figcaptionGap,
|
|
62
70
|
textColor,
|
|
63
71
|
icon,
|
|
72
|
+
iconFr,
|
|
64
73
|
iconColor,
|
|
65
|
-
imageSize
|
|
66
|
-
|
|
74
|
+
imageSize,
|
|
75
|
+
testimonialFontSizeLarge,
|
|
76
|
+
testimonialLineHeightLarge,
|
|
77
|
+
testimonialFontWeightLarge,
|
|
78
|
+
testimonialFontSizeHeading,
|
|
79
|
+
testimonialLineHeightHeading,
|
|
80
|
+
testimonialFontNameHeading,
|
|
81
|
+
testimonialFontWeightHeading,
|
|
82
|
+
authorFontSize,
|
|
83
|
+
authorLineHeight,
|
|
84
|
+
authorFontName,
|
|
85
|
+
authorFontWeight,
|
|
86
|
+
additionalFontSize,
|
|
87
|
+
additionalLineHeight,
|
|
88
|
+
additionalFontName,
|
|
89
|
+
additionalFontWeight
|
|
90
|
+
} = useThemeTokens('Testimonial', tokens, variant, { viewport })
|
|
91
|
+
|
|
92
|
+
const getQuoteTestimonial = (open) => {
|
|
93
|
+
let quote = ''
|
|
94
|
+
|
|
95
|
+
if (copy === 'en') quote = open ? '\u201C' : '\u201D'
|
|
96
|
+
else quote = open ? '\u00AB ' : ' \u00BB'
|
|
97
|
+
|
|
98
|
+
return quote
|
|
99
|
+
}
|
|
100
|
+
|
|
67
101
|
return (
|
|
68
102
|
<TestimonialContainer testimonialContainerGap={testimonialContainerGap} {...selectProps(rest)}>
|
|
69
103
|
<QuoteContainer quoteContainerGap={quoteContainerGap}>
|
|
70
|
-
<Icon
|
|
104
|
+
<Icon
|
|
105
|
+
tokens={{ color: iconColor }}
|
|
106
|
+
variant={{ size: 'micro' }}
|
|
107
|
+
icon={copy === 'en' ? icon : iconFr}
|
|
108
|
+
/>
|
|
71
109
|
{showDivider && (
|
|
72
110
|
<Divider
|
|
73
111
|
dividerBackgroundColor={dividerBackgroundColor}
|
|
@@ -81,10 +119,22 @@ const Testimonial = ({
|
|
|
81
119
|
variant={{ size: testimonialStyle === 'large' ? 'large' : 'h3' }}
|
|
82
120
|
tokens={{
|
|
83
121
|
color: textColor,
|
|
84
|
-
|
|
122
|
+
fontSize:
|
|
123
|
+
testimonialStyle === 'heading'
|
|
124
|
+
? testimonialFontSizeHeading
|
|
125
|
+
: testimonialFontSizeLarge,
|
|
126
|
+
lineHeight:
|
|
127
|
+
testimonialStyle === 'heading'
|
|
128
|
+
? testimonialLineHeightHeading
|
|
129
|
+
: testimonialLineHeightLarge,
|
|
130
|
+
fontName: testimonialFontNameHeading,
|
|
131
|
+
fontWeight:
|
|
132
|
+
testimonialStyle === 'heading'
|
|
133
|
+
? testimonialFontWeightHeading
|
|
134
|
+
: testimonialFontWeightLarge
|
|
85
135
|
}}
|
|
86
136
|
>
|
|
87
|
-
{
|
|
137
|
+
{`${getQuoteTestimonial(true)}${testimonial}${getQuoteTestimonial()}`}
|
|
88
138
|
</Typography>
|
|
89
139
|
</BlockQuote>
|
|
90
140
|
{(image || title || additionalInfo) && (
|
|
@@ -105,16 +155,28 @@ const Testimonial = ({
|
|
|
105
155
|
<AuthorInfoContainer>
|
|
106
156
|
{title && (
|
|
107
157
|
<Typography
|
|
108
|
-
variant={{ size: 'small'
|
|
109
|
-
tokens={{
|
|
158
|
+
variant={{ size: 'small' }}
|
|
159
|
+
tokens={{
|
|
160
|
+
color: textColor,
|
|
161
|
+
fontSize: authorFontSize,
|
|
162
|
+
lineHeight: authorLineHeight,
|
|
163
|
+
fontName: authorFontName,
|
|
164
|
+
fontWeight: authorFontWeight
|
|
165
|
+
}}
|
|
110
166
|
>
|
|
111
167
|
{title}
|
|
112
168
|
</Typography>
|
|
113
169
|
)}
|
|
114
170
|
{additionalInfo && (
|
|
115
171
|
<Typography
|
|
116
|
-
variant={{ size: '
|
|
117
|
-
tokens={{
|
|
172
|
+
variant={{ size: 'small' }}
|
|
173
|
+
tokens={{
|
|
174
|
+
color: textColor,
|
|
175
|
+
fontSize: additionalFontSize,
|
|
176
|
+
lineHeight: additionalLineHeight,
|
|
177
|
+
fontName: additionalFontName,
|
|
178
|
+
fontWeight: additionalFontWeight
|
|
179
|
+
}}
|
|
118
180
|
>
|
|
119
181
|
{additionalInfo}
|
|
120
182
|
</Typography>
|