@telus-uds/components-base 3.31.0 → 3.32.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.
@@ -1,11 +1,12 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- import { View, Pressable, Platform } from 'react-native'
4
+ import { View, Pressable, Platform, StyleSheet } from 'react-native'
5
5
  import { resolvePressableTokens } from '../utils/pressability'
6
6
  import { applyShadowToken } from '../ThemeProvider'
7
7
  import { getTokensPropType } from '../utils'
8
8
  import Tooltip from '../Tooltip'
9
+ import { UNAVAILABLE_VARIANT } from './constants'
9
10
 
10
11
  const selectGeneralBubbleTokens = ({
11
12
  outerBubbleHeight,
@@ -52,13 +53,41 @@ const selectBorderBubbleTokens = ({
52
53
  borderRadius: bubbleBorderRadius
53
54
  })
54
55
 
56
+ const selectOverlayStyles = ({ overlayColor, innerBubbleBorderRadius }) => ({
57
+ borderRadius: innerBubbleBorderRadius,
58
+ backgroundColor: overlayColor
59
+ })
60
+
61
+ const selectSlashStyles = (
62
+ { slashLightColor, slashDarkColor, slashWidth, slashOffset },
63
+ unavailable
64
+ ) => ({
65
+ width: slashWidth,
66
+ backgroundColor: unavailable === UNAVAILABLE_VARIANT.DARK ? slashDarkColor : slashLightColor,
67
+ marginLeft: slashOffset
68
+ })
69
+
55
70
  const ColourBubble = React.forwardRef(
56
- ({ tokens = {}, id, colourHexCode, colourName, isSelected, onPress, showTooltip }, ref) => {
71
+ (
72
+ {
73
+ tokens = () => ({}),
74
+ id,
75
+ colourHexCode,
76
+ colourName,
77
+ isSelected,
78
+ onPress,
79
+ showTooltip,
80
+ unavailable,
81
+ isDisabled
82
+ },
83
+ ref
84
+ ) => {
57
85
  const defaultTokens = tokens({ selected: isSelected })
58
86
 
59
- const resolveColourBubbleTokens = (pressState) => resolvePressableTokens(tokens, pressState, {})
87
+ const resolveColourBubbleTokens = (pressState) =>
88
+ resolvePressableTokens(tokens, isDisabled ? {} : pressState, {})
60
89
 
61
- const themeTokens = React.useMemo(() => tokens(), [tokens])
90
+ const themeTokens = tokens()
62
91
 
63
92
  const pressable = (
64
93
  <Pressable
@@ -67,14 +96,23 @@ const ColourBubble = React.forwardRef(
67
96
  isSelected && selectBorderBubbleTokens(defaultTokens)
68
97
  ]}
69
98
  onPress={onPress}
99
+ disabled={isDisabled}
100
+ focusable={!isDisabled}
70
101
  accessible
71
102
  accessibilityRole="radio"
72
103
  accessibilityLabel={colourName}
73
- accessibilityState={{ checked: isSelected }}
104
+ accessibilityState={{ checked: isSelected, disabled: isDisabled }}
74
105
  ref={ref}
75
106
  testID={id}
76
107
  >
77
- <View style={[selectInnerBubbleTokens(themeTokens), { backgroundColor: colourHexCode }]} />
108
+ <View style={[selectInnerBubbleTokens(themeTokens), { backgroundColor: colourHexCode }]}>
109
+ {unavailable && (
110
+ <View style={[StyleSheet.absoluteFillObject, selectOverlayStyles(themeTokens)]} />
111
+ )}
112
+ </View>
113
+ {unavailable && (
114
+ <View style={[staticStyles.indicator, selectSlashStyles(themeTokens, unavailable)]} />
115
+ )}
78
116
  </Pressable>
79
117
  )
80
118
 
@@ -121,7 +159,24 @@ ColourBubble.propTypes = {
121
159
  /**
122
160
  * When true, wraps the bubble in a Tooltip that displays the colourName on hover (web only).
123
161
  */
124
- showTooltip: PropTypes.bool
162
+ showTooltip: PropTypes.bool,
163
+ /**
164
+ * When set, renders a diagonal indicator over the bubble. Accepts either 'dark' or 'light' to determine the colour of the indicator.
165
+ */
166
+ unavailable: PropTypes.oneOf(Object.values(UNAVAILABLE_VARIANT)),
167
+ /**
168
+ * When true, disables interaction on the bubble.
169
+ */
170
+ isDisabled: PropTypes.bool
125
171
  }
126
172
 
173
+ const staticStyles = StyleSheet.create({
174
+ indicator: {
175
+ position: 'absolute',
176
+ top: '50%',
177
+ height: 2,
178
+ transform: [{ rotate: '-45deg' }]
179
+ }
180
+ })
181
+
127
182
  export default ColourBubble
@@ -3,32 +3,57 @@ import { View } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
 
5
5
  import { useThemeTokensCallback } from '../ThemeProvider'
6
- import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
6
+ import {
7
+ a11yProps,
8
+ getTokensPropType,
9
+ selectSystemProps,
10
+ useCopy,
11
+ variantProp,
12
+ viewProps
13
+ } from '../utils'
7
14
  import { StackWrap } from '../StackView'
8
15
  import Typography from '../Typography'
9
16
  import ColourBubble from './ColourBubble'
17
+ import { UNAVAILABLE_VARIANT, DICTIONARY_CONTENT_SHAPE } from './constants'
18
+ import DEFAULT_COLOUR_TOGGLE_DICTIONARY from './dictionary'
10
19
 
11
20
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
12
21
 
13
22
  const ColourToggle = React.forwardRef(
14
- ({ tokens, variant, defaultColourId, items, onChange, showTooltips, ...rest }, ref) => {
23
+ (
24
+ {
25
+ tokens,
26
+ variant,
27
+ defaultColourId,
28
+ items,
29
+ onChange,
30
+ showTooltips,
31
+ copy = 'en',
32
+ dictionary = DEFAULT_COLOUR_TOGGLE_DICTIONARY,
33
+ ...rest
34
+ },
35
+ ref
36
+ ) => {
15
37
  const [currentColourId, setCurrentColourId] = React.useState(defaultColourId)
16
38
  const getTokens = useThemeTokensCallback('ColourToggle', tokens, variant)
17
-
39
+ const getCopy = useCopy({ dictionary, copy })
18
40
  const { space } = getTokens()
19
- const { colourName: currentColourName = '' } =
20
- items.find((item) => item.id === currentColourId) || ''
41
+ const currentItem = items.find(({ id }) => id === currentColourId)
21
42
 
22
43
  return (
23
44
  <View ref={ref} {...selectProps(rest)}>
24
- <Typography>{currentColourName}</Typography>
45
+ <Typography>
46
+ {currentItem?.unavailable
47
+ ? `${currentItem.colourName} ${getCopy('unavailable')}`
48
+ : currentItem?.colourName ?? ''}
49
+ </Typography>
25
50
  <StackWrap space={space} accessibilityRole="radiogroup">
26
- {items.map(({ id, colourHexCode, colourName }, index) => {
51
+ {items.map(({ id, colourHexCode, colourName, unavailable, disabled }, index) => {
27
52
  const colourBubbleId = id || `ColourBubble[${index}]`
28
53
 
29
54
  const handleChangeColour = (event) => {
30
55
  setCurrentColourId(id)
31
- onChange?.(event, { id, colourHexCode, colourName })
56
+ onChange?.(event, { id, colourHexCode, colourName, unavailable })
32
57
  }
33
58
 
34
59
  return (
@@ -41,6 +66,8 @@ const ColourToggle = React.forwardRef(
41
66
  colourName={colourName}
42
67
  onPress={handleChangeColour}
43
68
  showTooltip={showTooltips}
69
+ unavailable={unavailable}
70
+ isDisabled={!!disabled}
44
71
  />
45
72
  )
46
73
  })}
@@ -72,7 +99,9 @@ ColourToggle.propTypes = {
72
99
  PropTypes.exact({
73
100
  colourHexCode: PropTypes.string,
74
101
  colourName: PropTypes.string,
75
- id: PropTypes.string
102
+ id: PropTypes.string,
103
+ unavailable: PropTypes.oneOf(Object.values(UNAVAILABLE_VARIANT)),
104
+ disabled: PropTypes.bool
76
105
  })
77
106
  ),
78
107
  /**
@@ -82,7 +111,18 @@ ColourToggle.propTypes = {
82
111
  /**
83
112
  * When true, displays each colour's name as a tooltip on hover (web only).
84
113
  */
85
- showTooltips: PropTypes.bool
114
+ showTooltips: PropTypes.bool,
115
+ /**
116
+ * Select English or French copy.
117
+ */
118
+ copy: PropTypes.oneOf(['en', 'fr']),
119
+ /**
120
+ * Override default labels.
121
+ */
122
+ dictionary: PropTypes.shape({
123
+ en: DICTIONARY_CONTENT_SHAPE,
124
+ fr: DICTIONARY_CONTENT_SHAPE
125
+ })
86
126
  }
87
127
 
88
128
  export default ColourToggle
@@ -0,0 +1,10 @@
1
+ import PropTypes from 'prop-types'
2
+
3
+ export const UNAVAILABLE_VARIANT = {
4
+ DARK: 'dark',
5
+ LIGHT: 'light'
6
+ }
7
+
8
+ export const DICTIONARY_CONTENT_SHAPE = PropTypes.shape({
9
+ unavailable: PropTypes.string
10
+ })
@@ -0,0 +1,6 @@
1
+ const DEFAULT_COLOUR_TOGGLE_DICTIONARY = {
2
+ en: { unavailable: '(Out of stock)' },
3
+ fr: { unavailable: '(En rupture de stock)' }
4
+ }
5
+
6
+ export default DEFAULT_COLOUR_TOGGLE_DICTIONARY
@@ -204,7 +204,11 @@ const Validator = React.forwardRef(
204
204
 
205
205
  // Sync external value prop to internal state
206
206
  React.useEffect(() => {
207
- if (value && Number(value).toString() !== 'NaN') {
207
+ if (value === '') {
208
+ setCodes(Array(validatorsLength).fill(''))
209
+ return
210
+ }
211
+ if (Number(value).toString() !== 'NaN') {
208
212
  const digits = value.split('').slice(0, validatorsLength)
209
213
  const newCodes = Array(validatorsLength).fill('')
210
214
  digits.forEach((digit, i) => {