@telus-uds/components-base 1.62.0 → 1.63.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/lib/Autocomplete/Autocomplete.js +36 -4
  3. package/lib/Button/ButtonDropdown.js +1 -0
  4. package/lib/Icon/Icon.js +15 -2
  5. package/lib/Link/LinkBase.js +9 -2
  6. package/lib/Listbox/Listbox.js +2 -2
  7. package/lib/Listbox/ListboxItem.js +7 -2
  8. package/lib/MultiSelectFilter/MultiSelectFilter.js +2 -2
  9. package/lib/Tooltip/Tooltip.js +2 -0
  10. package/lib/Tooltip/Tooltip.native.js +2 -0
  11. package/lib/Tooltip/shared.js +5 -0
  12. package/lib/TooltipButton/TooltipButton.js +14 -1
  13. package/lib-module/Autocomplete/Autocomplete.js +37 -5
  14. package/lib-module/Button/ButtonDropdown.js +2 -1
  15. package/lib-module/Icon/Icon.js +15 -2
  16. package/lib-module/Link/LinkBase.js +9 -2
  17. package/lib-module/Listbox/Listbox.js +2 -2
  18. package/lib-module/Listbox/ListboxItem.js +7 -2
  19. package/lib-module/MultiSelectFilter/MultiSelectFilter.js +2 -2
  20. package/lib-module/Tooltip/Tooltip.js +2 -0
  21. package/lib-module/Tooltip/Tooltip.native.js +2 -0
  22. package/lib-module/Tooltip/shared.js +5 -0
  23. package/lib-module/TooltipButton/TooltipButton.js +11 -1
  24. package/package.json +3 -4
  25. package/src/Autocomplete/Autocomplete.jsx +43 -5
  26. package/src/Button/ButtonDropdown.jsx +3 -0
  27. package/src/Icon/Icon.jsx +22 -3
  28. package/src/Link/LinkBase.jsx +20 -2
  29. package/src/Listbox/Listbox.jsx +2 -2
  30. package/src/Listbox/ListboxItem.jsx +14 -2
  31. package/src/MultiSelectFilter/MultiSelectFilter.jsx +2 -2
  32. package/src/Tooltip/Tooltip.jsx +2 -0
  33. package/src/Tooltip/Tooltip.native.jsx +2 -0
  34. package/src/Tooltip/shared.js +4 -0
  35. package/src/TooltipButton/TooltipButton.jsx +13 -2
  36. package/component-docs.json +0 -15853
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
2
  import View from "react-native-web/dist/exports/View";
3
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
4
+ import Platform from "react-native-web/dist/exports/Platform";
3
5
  import PropTypes from 'prop-types';
4
6
  import { useThemeTokens, applyOuterBorder } from '../ThemeProvider';
5
7
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
@@ -53,7 +55,7 @@ const TooltipButton = _ref3 => {
53
55
  return /*#__PURE__*/_jsx(View, {
54
56
  style: [applyOuterBorder(themeTokens), themeTokens.outerBorderWidth && {
55
57
  margin: -themeTokens.outerBorderWidth
56
- }],
58
+ }, staticStyles.bubblePointerEvents],
57
59
  ...selectProps(rest),
58
60
  children: /*#__PURE__*/_jsx(View, {
59
61
  style: selectInnerContainerStyles(themeTokens),
@@ -65,6 +67,14 @@ const TooltipButton = _ref3 => {
65
67
  });
66
68
  };
67
69
 
70
+ const staticStyles = StyleSheet.create({
71
+ bubblePointerEvents: { ...Platform.select({
72
+ web: {
73
+ pointerEvents: 'none'
74
+ }
75
+ })
76
+ }
77
+ });
68
78
  TooltipButton.propTypes = { ...selectedSystemPropTypes,
69
79
 
70
80
  /**
package/package.json CHANGED
@@ -64,15 +64,14 @@
64
64
  "lint": "npm run --prefix ../.. lint:path -- --color packages/components-base",
65
65
  "lint:fix": "npm run --prefix ../.. lint:path -- --fix packages/components-base",
66
66
  "format": "prettier --write .",
67
- "build": "npm run build:code && npm run build:docs",
67
+ "build": "npm run build:code",
68
68
  "build:main": "babel src -d lib",
69
69
  "build:module": "babel src -d lib-module --env-name module",
70
- "build:code": "npm run build:main && npm run build:module",
71
- "build:docs": "babel-node --plugins=@telus-uds/babel-plugin-react-docgen generate-component-docs.js"
70
+ "build:code": "npm run build:main && npm run build:module"
72
71
  },
73
72
  "sideEffects": false,
74
73
  "standard-engine": {
75
74
  "skip": true
76
75
  },
77
- "version": "1.62.0"
76
+ "version": "1.63.0"
78
77
  }
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable react/require-default-props */
2
- import React, { forwardRef, useRef, useState } from 'react'
2
+ import React, { forwardRef, useEffect, useRef, useState } from 'react'
3
3
  import PropTypes from 'prop-types'
4
4
  import { Dimensions, Platform, View, StyleSheet } from 'react-native'
5
5
  import throttle from 'lodash.throttle'
@@ -118,6 +118,8 @@ const Autocomplete = forwardRef(
118
118
  // We need to store current items for uncontrolled usage
119
119
  const [currentItems, setCurrentItems] = useState(initialItems)
120
120
 
121
+ const [otherItems, setOtherItems] = useState(items)
122
+
121
123
  // We need to store the current value as well to be able to highlight it
122
124
  const [currentValue, setCurrentValue] = useState(value ?? initialValue)
123
125
  const inputTokens = { paddingLeft: INPUT_LEFT_PADDING }
@@ -128,6 +130,9 @@ const Autocomplete = forwardRef(
128
130
  const [isFocused, setisFocused] = useState(false)
129
131
  const [sourceLayout, setSourceLayout] = useState(null)
130
132
 
133
+ // When it's nested, selected value
134
+ const [nestedSelectedValue, setNestedSelectedValue] = useState(null)
135
+
131
136
  const { supportsProps, ...selectedProps } = selectProps(rest)
132
137
  const { hint, label: inputLabel } = supportsProps
133
138
  const hintExpansionEnabled = isFocused && helpText && !currentValue
@@ -197,21 +202,49 @@ const Autocomplete = forwardRef(
197
202
  }
198
203
  const handleSelect = (selectedId) => {
199
204
  onSelect?.(selectedId)
200
- const { label: newValue, nested } = (isControlled ? items : currentItems)?.find(
201
- ({ id }) => id === selectedId
202
- )
205
+ const {
206
+ label: newValue,
207
+ nested,
208
+ title
209
+ } = (isControlled ? items : currentItems)?.find(({ id }) => id === selectedId)
210
+ if (title) return
203
211
  if (!nested) {
212
+ setNestedSelectedValue(null)
204
213
  onChange?.(newValue)
205
214
  setIsExpanded(false)
206
215
  }
207
216
  setCurrentValue(newValue)
208
217
  if (!isControlled && inputRef?.current) inputRef.current.value = newValue
218
+
219
+ if (nested) setNestedSelectedValue(newValue)
209
220
  }
210
221
 
222
+ /**
223
+ * When an item that is nested equal "true" is selected this useEffect is executed.
224
+ * The nested item is added to the item list at the top, the if validates it doesn't exist
225
+ * within the list, if doesn't exist the nested item is added to the top of the list,
226
+ * the nested item is added with an id equal "0"
227
+ */
228
+ useEffect(() => {
229
+ if (nestedSelectedValue && !items.find((item) => item.id === 0)) {
230
+ const tmpItems = [...items]
231
+ tmpItems.unshift({ label: nestedSelectedValue, title: true, id: 0 })
232
+ setOtherItems(
233
+ tmpItems.map((item) => {
234
+ return {
235
+ ...item,
236
+ nestedChild: item.id !== 0
237
+ }
238
+ })
239
+ )
240
+ }
241
+ }, [nestedSelectedValue, items])
242
+
211
243
  const handleClose = (event) => {
212
244
  if (event.type === 'keydown') {
213
245
  if (event.key === 'Escape' || event.key === 27) {
214
246
  setIsExpanded(false)
247
+ setNestedSelectedValue(null)
215
248
  } else if (event.key === 'ArrowDown' && isExpanded && !isLoading && targetRef?.current) {
216
249
  targetRef.current.focus()
217
250
  }
@@ -232,6 +265,7 @@ const Autocomplete = forwardRef(
232
265
  } else if (Platform.OS === 'web') {
233
266
  // needed for dropdown to be collapsed when clicking outside on web
234
267
  setIsExpanded(false)
268
+ setNestedSelectedValue(null)
235
269
  }
236
270
  }
237
271
  const itemsToShow = currentValue
@@ -308,7 +342,11 @@ const Autocomplete = forwardRef(
308
342
  <Suggestions
309
343
  hasResults={getCopy('hasResults')}
310
344
  id="autocomplete"
311
- items={itemsToShow}
345
+ items={
346
+ nestedSelectedValue
347
+ ? itemsToSuggest(highlight(otherItems, nestedSelectedValue, resultsTextColor))
348
+ : itemsToShow
349
+ }
312
350
  noResults={helpTextToShow}
313
351
  onClose={handleClose}
314
352
  onSelect={handleSelect}
@@ -6,6 +6,7 @@ import ButtonBase from './ButtonBase'
6
6
  import { useThemeTokensCallback } from '../ThemeProvider'
7
7
  import {
8
8
  a11yProps,
9
+ getTokensPropType,
9
10
  focusHandlerProps,
10
11
  resolvePressableState,
11
12
  selectTokens,
@@ -153,6 +154,8 @@ ButtonDropdown.propTypes = {
153
154
  ...focusHandlerProps.types,
154
155
  ...buttonPropTypes,
155
156
  children: textAndA11yText,
157
+ tokens: getTokensPropType('ButtonDropdown'),
158
+
156
159
  /**
157
160
  * Callback called when a controlled ButtonDropdown gets interacted with.
158
161
  */
package/src/Icon/Icon.jsx CHANGED
@@ -7,7 +7,15 @@ import { getTokensPropType, scaleWithText, variantProp } from '../utils'
7
7
 
8
8
  const Icon = forwardRef(
9
9
  (
10
- { icon: IconComponent, accessibilityLabel, variant, tokens, scalesWithText = false, dataSet },
10
+ {
11
+ icon: IconComponent,
12
+ accessibilityLabel,
13
+ variant,
14
+ tokens,
15
+ scalesWithText = false,
16
+ style = {},
17
+ dataSet
18
+ },
11
19
  ref
12
20
  ) => {
13
21
  const themeTokens = useThemeTokens('Icon', tokens, variant)
@@ -32,7 +40,8 @@ const Icon = forwardRef(
32
40
  themeTokens.translateY ? `translateY(${themeTokens.translateY}px)` : ''
33
41
  ]
34
42
  .filter((exists) => exists)
35
- .join(' ')
43
+ .join(' '),
44
+ ...style
36
45
  }}
37
46
  dataSet={dataSet}
38
47
  >
@@ -55,7 +64,17 @@ export const iconComponentPropTypes = {
55
64
  /**
56
65
  * controls whether the icon size should be proportionate to any accessibility-related font scaling.
57
66
  */
58
- scalesWithText: PropTypes.bool
67
+ scalesWithText: PropTypes.bool,
68
+ /**
69
+ * Custom style object to be applied to the icon component.
70
+ * This is useful for overriding the default icon style but for cases where desires styles are not available as tokens.
71
+ *
72
+ * Note: This prop is only used in web.
73
+ *
74
+ * @example
75
+ * <Icon style={{ color: 'red' }}
76
+ */
77
+ style: PropTypes.object
59
78
  }
60
79
 
61
80
  Icon.propTypes = {
@@ -180,9 +180,20 @@ const LinkBase = forwardRef(
180
180
  icon={IconComponent}
181
181
  iconPosition={iconPosition}
182
182
  space={iconSpace}
183
- iconProps={{ ...iconProps, tokens: iconTokens }}
183
+ iconProps={{
184
+ ...iconProps,
185
+ tokens: iconTokens,
186
+ style: staticStyles.bubblePointerEvents
187
+ }}
184
188
  >
185
- <Text style={[textStyles, blockTextStyles, staticStyles.baseline]}>
189
+ <Text
190
+ style={[
191
+ textStyles,
192
+ blockTextStyles,
193
+ staticStyles.baseline,
194
+ staticStyles.bubblePointerEvents
195
+ ]}
196
+ >
186
197
  {typeof children === 'function' ? children(linkState) : children}
187
198
  </Text>
188
199
  </IconText>
@@ -239,6 +250,13 @@ const staticStyles = StyleSheet.create({
239
250
  },
240
251
  baseline: {
241
252
  alignSelf: 'baseline'
253
+ },
254
+ bubblePointerEvents: {
255
+ ...Platform.select({
256
+ web: {
257
+ pointerEvents: 'none'
258
+ }
259
+ })
242
260
  }
243
261
  })
244
262
 
@@ -136,6 +136,7 @@ const Listbox = ({
136
136
 
137
137
  Listbox.propTypes = {
138
138
  ...withLinkRouter.propTypes,
139
+ tokens: getTokensPropType('Listbox'),
139
140
  /**
140
141
  * Focus will be moved to the item with this ref once within the menu.
141
142
  */
@@ -156,8 +157,7 @@ Listbox.propTypes = {
156
157
  /**
157
158
  * onClose event
158
159
  */
159
- onClose: PropTypes.func,
160
- tokens: getTokensPropType('Listbox')
160
+ onClose: PropTypes.func
161
161
  }
162
162
 
163
163
  Listbox.Overlay = DropdownOverlay
@@ -15,6 +15,9 @@ const styles = StyleSheet.create({
15
15
  },
16
16
  childContainer: {
17
17
  paddingLeft: 16
18
+ },
19
+ nestedChildContainer: {
20
+ paddingLeft: 24
18
21
  }
19
22
  })
20
23
 
@@ -24,6 +27,7 @@ const ListboxItem = forwardRef(
24
27
  href,
25
28
  label,
26
29
  isChild = false,
30
+ nestedChild,
27
31
  onBlur,
28
32
  nextItemRef,
29
33
  prevItemRef,
@@ -41,7 +45,14 @@ const ListboxItem = forwardRef(
41
45
 
42
46
  const getTokens = useThemeTokensCallback('Listbox', tokens, variant, { isChild })
43
47
  return (
44
- <View style={[styles.itemContainer, isChild && styles.childContainer]} role="option">
48
+ <View
49
+ style={[
50
+ styles.itemContainer,
51
+ isChild && styles.childContainer,
52
+ nestedChild && styles.nestedChildContainer
53
+ ]}
54
+ role="option"
55
+ >
45
56
  <PressableItem
46
57
  href={href}
47
58
  isChild={isChild}
@@ -70,7 +81,8 @@ ListboxItem.propTypes = {
70
81
  label: PropTypes.node.isRequired,
71
82
  nextItemRef: PropTypes.object,
72
83
  prevItemRef: PropTypes.object,
73
- onPress: PropTypes.func
84
+ onPress: PropTypes.func,
85
+ nestedChild: PropTypes.bool
74
86
  }
75
87
 
76
88
  export default withLinkRouter(ListboxItem)
@@ -344,9 +344,9 @@ MultiSelectFilter.propTypes = {
344
344
  */
345
345
  variant: variantProp.propType,
346
346
  /**
347
- * Sets the tokens for ButtonDropdown element.
347
+ * Sets the tokens for MultiSelectFilter element.
348
348
  */
349
- tokens: getTokensPropType('ButtonDropdown'),
349
+ tokens: getTokensPropType('MultiSelectFilter'),
350
350
  /**
351
351
  * The options a user may select.
352
352
  */
@@ -92,6 +92,7 @@ const Tooltip = forwardRef(
92
92
  tokens,
93
93
  variant,
94
94
  inline = false,
95
+ nativeID,
95
96
  ...rest
96
97
  },
97
98
  ref
@@ -193,6 +194,7 @@ const Tooltip = forwardRef(
193
194
  hitSlop={pressableHitSlop}
194
195
  accessibilityLabel={getCopy('a11yText')}
195
196
  accessibilityRole="button"
197
+ nativeID={nativeID}
196
198
  >
197
199
  {typeof control === 'function'
198
200
  ? (pressableState) => control(getPressableState(pressableState), variant)
@@ -118,6 +118,7 @@ const Tooltip = forwardRef(
118
118
  tokens,
119
119
  variant,
120
120
  inline = false,
121
+ nativeID,
121
122
  ...rest
122
123
  },
123
124
  ref
@@ -252,6 +253,7 @@ const Tooltip = forwardRef(
252
253
  hitSlop={pressableHitSlop}
253
254
  accessibilityLabel={getCopy('a11yText')}
254
255
  accessibilityRole="button"
256
+ nativeID={nativeID}
255
257
  >
256
258
  {typeof control === 'function'
257
259
  ? (pressableState) => control(getPressableState(pressableState), variant)
@@ -28,6 +28,10 @@ const propTypes = {
28
28
  * Callback function triggered when the tooltip is pressed.
29
29
  */
30
30
  onPress: PropTypes.func,
31
+ /**
32
+ * The `id` of the tooltip button.
33
+ */
34
+ nativeID: PropTypes.string,
31
35
  tokens: getTokensPropType('Tooltip'),
32
36
  variant: variantProp.propType
33
37
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { View } from 'react-native'
2
+ import { View, StyleSheet, Platform } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
  import { useThemeTokens, applyOuterBorder } from '../ThemeProvider'
5
5
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
@@ -35,7 +35,8 @@ const TooltipButton = ({ pressableState, tokens, variant, ...rest }) => {
35
35
  applyOuterBorder(themeTokens),
36
36
  themeTokens.outerBorderWidth && {
37
37
  margin: -themeTokens.outerBorderWidth
38
- }
38
+ },
39
+ staticStyles.bubblePointerEvents
39
40
  ]}
40
41
  {...selectProps(rest)}
41
42
  >
@@ -46,6 +47,16 @@ const TooltipButton = ({ pressableState, tokens, variant, ...rest }) => {
46
47
  )
47
48
  }
48
49
 
50
+ const staticStyles = StyleSheet.create({
51
+ bubblePointerEvents: {
52
+ ...Platform.select({
53
+ web: {
54
+ pointerEvents: 'none'
55
+ }
56
+ })
57
+ }
58
+ })
59
+
49
60
  TooltipButton.propTypes = {
50
61
  ...selectedSystemPropTypes,
51
62
  /**