@telus-uds/components-base 3.21.0 → 3.23.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 (64) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/lib/cjs/Button/Button.js +12 -3
  3. package/lib/cjs/Button/ButtonBase.js +63 -10
  4. package/lib/cjs/Button/ButtonDropdown.js +2 -0
  5. package/lib/cjs/Button/ButtonGroup.js +45 -38
  6. package/lib/cjs/Button/propTypes.js +6 -0
  7. package/lib/cjs/Card/PressableCardBase.js +3 -1
  8. package/lib/cjs/Carousel/Carousel.js +63 -22
  9. package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +23 -3
  10. package/lib/cjs/Icon/Icon.js +8 -11
  11. package/lib/cjs/Icon/IconText.js +0 -1
  12. package/lib/cjs/Listbox/GroupControl.js +33 -39
  13. package/lib/cjs/Listbox/Listbox.js +22 -13
  14. package/lib/cjs/Listbox/ListboxGroup.js +2 -1
  15. package/lib/cjs/Listbox/ListboxOverlay.js +5 -2
  16. package/lib/cjs/Listbox/PressableItem.js +8 -4
  17. package/lib/cjs/TextInput/TextInputBase.js +5 -1
  18. package/lib/cjs/ThemeProvider/index.js +9 -1
  19. package/lib/cjs/ThemeProvider/useResponsiveThemeTokensCallback.js +124 -0
  20. package/lib/cjs/Validator/Validator.js +171 -135
  21. package/lib/cjs/index.js +7 -0
  22. package/lib/esm/Button/Button.js +13 -4
  23. package/lib/esm/Button/ButtonBase.js +64 -11
  24. package/lib/esm/Button/ButtonDropdown.js +2 -0
  25. package/lib/esm/Button/ButtonGroup.js +44 -39
  26. package/lib/esm/Button/propTypes.js +6 -0
  27. package/lib/esm/Card/PressableCardBase.js +3 -1
  28. package/lib/esm/Carousel/Carousel.js +63 -22
  29. package/lib/esm/Carousel/CarouselItem/CarouselItem.js +23 -3
  30. package/lib/esm/Icon/Icon.js +8 -11
  31. package/lib/esm/Icon/IconText.js +0 -1
  32. package/lib/esm/Listbox/GroupControl.js +33 -39
  33. package/lib/esm/Listbox/Listbox.js +23 -14
  34. package/lib/esm/Listbox/ListboxGroup.js +2 -1
  35. package/lib/esm/Listbox/ListboxOverlay.js +5 -2
  36. package/lib/esm/Listbox/PressableItem.js +8 -4
  37. package/lib/esm/TextInput/TextInputBase.js +5 -1
  38. package/lib/esm/ThemeProvider/index.js +1 -0
  39. package/lib/esm/ThemeProvider/useResponsiveThemeTokensCallback.js +117 -0
  40. package/lib/esm/Validator/Validator.js +171 -135
  41. package/lib/esm/index.js +1 -1
  42. package/lib/package.json +2 -2
  43. package/package.json +2 -2
  44. package/src/Button/Button.jsx +26 -5
  45. package/src/Button/ButtonBase.jsx +79 -16
  46. package/src/Button/ButtonDropdown.jsx +2 -0
  47. package/src/Button/ButtonGroup.jsx +62 -45
  48. package/src/Button/propTypes.js +6 -0
  49. package/src/Card/PressableCardBase.jsx +3 -1
  50. package/src/Carousel/Carousel.jsx +71 -7
  51. package/src/Carousel/CarouselItem/CarouselItem.jsx +31 -3
  52. package/src/Icon/Icon.jsx +11 -14
  53. package/src/Icon/IconText.jsx +0 -1
  54. package/src/Listbox/GroupControl.jsx +41 -47
  55. package/src/Listbox/Listbox.jsx +26 -9
  56. package/src/Listbox/ListboxGroup.jsx +2 -1
  57. package/src/Listbox/ListboxOverlay.jsx +7 -2
  58. package/src/Listbox/PressableItem.jsx +8 -4
  59. package/src/PriceLockup/utils/renderPrice.jsx +15 -17
  60. package/src/TextInput/TextInputBase.jsx +5 -1
  61. package/src/ThemeProvider/index.js +1 -0
  62. package/src/ThemeProvider/useResponsiveThemeTokensCallback.js +129 -0
  63. package/src/Validator/Validator.jsx +180 -159
  64. package/src/index.js +2 -1
@@ -1,13 +1,13 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { View, StyleSheet, Text } from 'react-native'
3
+ import { View, Text, StyleSheet } from 'react-native'
4
4
  import { useThemeTokens } from '../ThemeProvider'
5
5
  import Icon from '../Icon'
6
6
  import Spacer from '../Spacer'
7
7
  import { useListboxContext } from './ListboxContext'
8
8
 
9
9
  const styles = StyleSheet.create({
10
- controlWrapper: {
10
+ container: {
11
11
  width: '100%',
12
12
  flex: 1,
13
13
  alignItems: 'center',
@@ -17,6 +17,36 @@ const styles = StyleSheet.create({
17
17
  }
18
18
  })
19
19
 
20
+ const selectTextStyles = (tokens) => ({
21
+ color: tokens.groupColor,
22
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
23
+ fontSize: tokens.groupFontSize,
24
+ fontWeight: tokens.groupFontWeight
25
+ })
26
+
27
+ const selectContainerStyles = (tokens) => ({
28
+ fontFamily: `${tokens.groupFontName}${tokens.groupFontWeight}normal`,
29
+ fontSize: tokens.groupFontSize,
30
+ color: tokens.groupColor,
31
+ textDecoration: tokens.itemTextDecoration,
32
+ backgroundColor: tokens.groupBackgroundColor,
33
+ outline: tokens.itemOutline,
34
+ minHeight: tokens.groupHeight,
35
+ borderRadius: tokens.groupBorderRadius,
36
+ paddingLeft: tokens.groupPaddingLeft - tokens.groupBorderLeftWidth,
37
+ paddingRight: tokens.groupPaddingRight - tokens.groupBorderRightWidth,
38
+ paddingTop: tokens.groupPaddingTop - tokens.groupBorderTopWidth,
39
+ paddingBottom: tokens.groupPaddingBottom - tokens.groupBorderBottomWidth,
40
+ borderLeftWidth: tokens.groupBorderLeftWidth,
41
+ borderLeftColor: tokens.groupBorderLeftColor,
42
+ borderRightWidth: tokens.groupBorderRightWidth,
43
+ borderRightColor: tokens.groupBorderRightColor,
44
+ borderTopWidth: tokens.groupBorderTopWidth,
45
+ borderTopColor: tokens.groupBorderTopColor,
46
+ borderBottomWidth: tokens.groupBorderBottomWidth,
47
+ borderBottomColor: tokens.groupBorderBottomColor
48
+ })
49
+
20
50
  const GroupControl = React.forwardRef(({ expanded, pressed, hover, focus, label, id }, ref) => {
21
51
  const { selectedId, setSelectedId } = useListboxContext()
22
52
  const tokens = useThemeTokens(
@@ -31,58 +61,22 @@ const GroupControl = React.forwardRef(({ expanded, pressed, hover, focus, label,
31
61
  focus
32
62
  }
33
63
  )
34
- const {
35
- groupFontName,
36
- groupFontWeight,
37
- groupFontSize,
38
- groupColor,
39
- groupBackgroundColor,
40
- groupBorderColor,
41
- groupBorderWidth,
42
- groupBorderRadius,
43
- groupPaddingLeft,
44
- groupPaddingRight,
45
- groupPaddingTop,
46
- groupPaddingBottom,
47
- itemTextDecoration,
48
- itemOutline,
49
- groupHeight
50
- } = tokens
51
-
52
- const getTextStyles = () => ({
53
- color: groupColor
54
- })
55
64
 
56
65
  return (
57
66
  <View
58
67
  onPress={() => setSelectedId(id)}
59
- style={[
60
- styles.controlWrapper,
61
- {
62
- fontFamily: `${groupFontName}${groupFontWeight}normal`,
63
- fontSize: groupFontSize,
64
- color: groupColor,
65
- textDecoration: itemTextDecoration,
66
- backgroundColor: groupBackgroundColor,
67
- outline: itemOutline,
68
- height: groupHeight,
69
- border: `${groupBorderWidth}px solid ${groupBorderColor}`,
70
- borderRadius: groupBorderRadius,
71
- paddingLeft: groupPaddingLeft - groupBorderWidth,
72
- paddingRight: groupPaddingRight - groupBorderWidth,
73
- paddingTop: groupPaddingTop - groupBorderWidth,
74
- paddingBottom: groupPaddingBottom - groupBorderWidth
75
- }
76
- ]}
68
+ style={[styles.container, selectContainerStyles(tokens)]}
77
69
  ref={ref}
78
70
  >
79
- <Text style={getTextStyles()}>{label}</Text>
71
+ <Text style={selectTextStyles(tokens)}>{label}</Text>
80
72
  <Spacer space={1} direction="row" />
81
- <Icon
82
- icon={tokens.groupIcon}
83
- tokens={{ color: tokens.groupColor }}
84
- variant={{ size: 'micro' }}
85
- />
73
+ {tokens.groupIcon && (
74
+ <Icon
75
+ icon={tokens.groupIcon}
76
+ tokens={{ color: tokens.groupColor }}
77
+ variant={{ size: 'micro' }}
78
+ />
79
+ )}
86
80
  </View>
87
81
  )
88
82
  })
@@ -1,8 +1,8 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { View, StyleSheet, Platform } from 'react-native'
3
+ import { View, Platform, StyleSheet } from 'react-native'
4
4
  import { useThemeTokens } from '../ThemeProvider'
5
- import { withLinkRouter, getTokensPropType } from '../utils'
5
+ import { withLinkRouter, getTokensPropType, variantProp } from '../utils'
6
6
  import ExpandCollapse from '../ExpandCollapse'
7
7
  import ListboxGroup from './ListboxGroup'
8
8
  import ListboxItem from './ListboxItem'
@@ -10,12 +10,18 @@ import { ListboxContext } from './ListboxContext'
10
10
  import DropdownOverlay from './ListboxOverlay'
11
11
 
12
12
  const styles = StyleSheet.create({
13
- list: {
13
+ container: {
14
14
  padding: 0,
15
15
  margin: 0
16
16
  }
17
17
  })
18
18
 
19
+ const selectContainerStyles = (tokens) => ({
20
+ minHeight: tokens.minHeight,
21
+ minWidth: tokens.minWidth,
22
+ backgroundColor: tokens.containerBackgroundColor
23
+ })
24
+
19
25
  const getInitialOpen = (items, selectedId) =>
20
26
  items
21
27
  .filter(
@@ -36,15 +42,14 @@ const Listbox = React.forwardRef(
36
42
  itemRouterProps,
37
43
  onClose,
38
44
  variant,
39
- tokens
45
+ tokens,
46
+ testID
40
47
  },
41
48
  ref
42
49
  ) => {
43
50
  const initialOpen = getInitialOpen(items, defaultSelectedId)
44
-
45
51
  const [selectedId, setSelectedId] = React.useState(defaultSelectedId)
46
-
47
- const { minHeight, minWidth } = useThemeTokens('Listbox', variant, tokens)
52
+ const listboxTokens = useThemeTokens('Listbox', tokens, variant)
48
53
 
49
54
  // We need to keep track of each item's ref in order to be able to
50
55
  // focus on a specific item via keyboard navigation
@@ -101,7 +106,11 @@ const Listbox = React.forwardRef(
101
106
  <ListboxContext.Provider value={{ selectedId, setSelectedId }}>
102
107
  <ExpandCollapse initialOpen={initialOpen} maxOpen={1} ref={ref}>
103
108
  {(expandProps) => (
104
- <View style={[styles.list, { minHeight, minWidth }]} role="listbox">
109
+ <View
110
+ style={[styles.container, selectContainerStyles(listboxTokens)]}
111
+ accessibilityRole="combobox"
112
+ testID={testID}
113
+ >
105
114
  {items.map((item, index) => {
106
115
  const { id, label, items: nestedItems } = item
107
116
  const itemId = id ?? label
@@ -169,7 +178,15 @@ Listbox.propTypes = {
169
178
  /**
170
179
  * onClose event
171
180
  */
172
- onClose: PropTypes.func
181
+ onClose: PropTypes.func,
182
+ /**
183
+ * Test ID for testing
184
+ */
185
+ testID: PropTypes.string,
186
+ /**
187
+ * Listbox variant
188
+ */
189
+ variant: variantProp.propType
173
190
  }
174
191
 
175
192
  Listbox.Overlay = DropdownOverlay
@@ -74,7 +74,8 @@ const ListboxGroup = React.forwardRef(
74
74
  borderColor: 'transparent',
75
75
  borderRadius: 0,
76
76
  borderWidth: 0,
77
- marginBottom: 0
77
+ marginBottom: 0,
78
+ contentPanelBackgroundColor: 'transparent'
78
79
  }}
79
80
  controlRef={ref}
80
81
  >
@@ -22,13 +22,17 @@ const paddingVertical = 0
22
22
  const paddingHorizontal = 0
23
23
 
24
24
  const DropdownOverlay = React.forwardRef(
25
- ({ children, isReady = false, overlaidPosition, maxWidth, minWidth, onLayout, tokens }, ref) => {
25
+ (
26
+ { children, isReady = false, overlaidPosition, maxWidth, minWidth, onLayout, tokens, testID },
27
+ ref
28
+ ) => {
26
29
  const systemTokens = useThemeTokens('Listbox', {}, {})
27
30
 
28
31
  return (
29
32
  <View
30
33
  ref={ref}
31
34
  onLayout={onLayout}
35
+ testID={testID}
32
36
  style={[
33
37
  overlaidPosition,
34
38
  { maxWidth, minWidth },
@@ -75,7 +79,8 @@ DropdownOverlay.propTypes = {
75
79
  maxWidth: PropTypes.number,
76
80
  minWidth: PropTypes.number,
77
81
  onLayout: PropTypes.func,
78
- tokens: PropTypes.object
82
+ tokens: PropTypes.object,
83
+ testID: PropTypes.string
79
84
  }
80
85
 
81
86
  export default Platform.OS === 'web' ? withPortal(DropdownOverlay) : DropdownOverlay
@@ -39,10 +39,14 @@ const getItemStyles = ({
39
39
  color: itemColor,
40
40
  outline: itemOutline,
41
41
  textDecoration: itemTextDecoration,
42
- borderLeft: `${itemBorderLeftWidth}px solid ${itemBorderLeftColor}`,
43
- borderRight: `${itemBorderRightWidth}px solid ${itemBorderRightColor}`,
44
- borderTop: `${itemBorderTopWidth}px solid ${itemBorderTopColor}`,
45
- borderBottom: `${itemBorderBottomWidth}px solid ${itemBorderBottomColor}`,
42
+ borderLeftWidth: itemBorderLeftWidth,
43
+ borderLeftColor: itemBorderLeftColor,
44
+ borderRightWidth: itemBorderRightWidth,
45
+ borderRightColor: itemBorderRightColor,
46
+ borderTopWidth: itemBorderTopWidth,
47
+ borderTopColor: itemBorderTopColor,
48
+ borderBottomWidth: itemBorderBottomWidth,
49
+ borderBottomColor: itemBorderBottomColor,
46
50
  borderRadius: itemBorderRadius,
47
51
  justifyContent: 'center'
48
52
  })
@@ -102,28 +102,26 @@ const renderPrice = (
102
102
  )}
103
103
  </Text>
104
104
  ) : null}
105
- {
106
- <Text>
107
- {renderAmount(
108
- amount,
109
- amountTypographyTokens,
105
+ <Text>
106
+ {renderAmount(
107
+ amount,
108
+ amountTypographyTokens,
109
+ strikeThrough,
110
+ a11yText,
111
+ fontColor,
112
+ themeTokens
113
+ )}
114
+ {isPriceBaseline &&
115
+ cents &&
116
+ renderAmount(
117
+ `${separator}${cents}`,
118
+ centsTypographyTokens,
110
119
  strikeThrough,
111
120
  a11yText,
112
121
  fontColor,
113
122
  themeTokens
114
123
  )}
115
- {isPriceBaseline &&
116
- cents &&
117
- renderAmount(
118
- `${separator}${cents}`,
119
- centsTypographyTokens,
120
- strikeThrough,
121
- a11yText,
122
- fontColor,
123
- themeTokens
124
- )}
125
- </Text>
126
- }
124
+ </Text>
127
125
  {cents && !isPriceBaseline
128
126
  ? renderTypography(`${separator}${cents}`, centsTypographyTokens, undefined, fontColor)
129
127
  : null}
@@ -263,6 +263,10 @@ const TextInputBase = React.forwardRef(
263
263
  // Add a space every 4 digits starting from the 5th position
264
264
  filteredText = formattedValue.replace(regex, '$1 ').trim()
265
265
  }
266
+ // Apply maxLength if provided
267
+ if (rest.maxLength && filteredText && filteredText.length > rest.maxLength) {
268
+ filteredText = filteredText.substring(0, rest.maxLength)
269
+ }
266
270
  setValue(filteredText, event)
267
271
  if (typeof onChangeText === 'function') onChangeText(filteredText, event)
268
272
  }
@@ -340,7 +344,7 @@ const TextInputBase = React.forwardRef(
340
344
  onMouseOut: handleMouseOut,
341
345
  onChange: handleChangeText,
342
346
  defaultValue: initialValue,
343
- maxLength: type === 'card' ? 19 : undefined,
347
+ maxLength: type === 'card' ? 19 : rest.maxLength,
344
348
  value: isControlled ? currentValue : undefined,
345
349
  onKeyPress
346
350
  }
@@ -3,6 +3,7 @@ import ThemeProvider from './ThemeProvider'
3
3
  export { default as useTheme } from './useTheme'
4
4
  export { default as useSetTheme } from './useSetTheme'
5
5
  export { default as useResponsiveThemeTokens } from './useResponsiveThemeTokens'
6
+ export { default as useResponsiveThemeTokensCallback } from './useResponsiveThemeTokensCallback'
6
7
  export * from './useThemeTokens'
7
8
 
8
9
  export * from './utils'
@@ -0,0 +1,129 @@
1
+ import { useCallback } from 'react'
2
+ import { viewports } from '@telus-uds/system-constants'
3
+ import useTheme from './useTheme'
4
+ import { getComponentTheme, mergeAppearances, resolveThemeTokens } from './utils'
5
+
6
+ const getResponsiveThemeTokens = (
7
+ { rules = [], tokens: defaultThemeTokens = {} },
8
+ tokensProp,
9
+ variants = {},
10
+ states
11
+ ) => {
12
+ const appearances = mergeAppearances(variants, states)
13
+
14
+ const tokensByViewport = Object.fromEntries(
15
+ viewports.keys.map((viewport) => [viewport, { ...defaultThemeTokens }])
16
+ )
17
+
18
+ // Go through each rule and collect them for the corresponding viewport if they apply
19
+ rules.forEach((rule) => {
20
+ if (doesRuleApply(rule, appearances)) {
21
+ // If the rule does not have a viewport specified, we collect it in all viewports
22
+ let targetViewports = rule.if.viewport || viewports.keys
23
+ if (!Array.isArray(targetViewports)) {
24
+ targetViewports = [targetViewports]
25
+ }
26
+ targetViewports.forEach((viewport) => {
27
+ tokensByViewport[viewport] = { ...tokensByViewport[viewport], ...rule.tokens }
28
+ })
29
+ }
30
+ })
31
+
32
+ Object.keys(tokensByViewport).forEach((viewport) => {
33
+ tokensByViewport[viewport] = resolveThemeTokens(
34
+ tokensByViewport[viewport],
35
+ appearances,
36
+ tokensProp
37
+ )
38
+ })
39
+
40
+ return tokensByViewport
41
+ }
42
+
43
+ const doesRuleApply = (rule, appearances) =>
44
+ Object.entries(rule.if).every((condition) => doesConditionApply(condition, appearances))
45
+
46
+ const doesConditionApply = ([key, value], appearances) => {
47
+ if (key === 'viewport') {
48
+ return true
49
+ }
50
+ // use null rather than undefined so we can serialise the value in themes
51
+ const appearanceValue = appearances[key] ?? null
52
+ return Array.isArray(value) ? value.includes(appearanceValue) : value === appearanceValue
53
+ }
54
+
55
+ /**
56
+ * @typedef {import('../utils/props/tokens.js').TokensSet} TokensSet
57
+ * @typedef {import('../utils/props/tokens.js').TokensProp} TokensProp
58
+ * @typedef {import('../utils/props/variantProp').AppearanceSet} AppearanceSet
59
+ */
60
+
61
+ /**
62
+ * Returns a memoised tokens getter function that gets responsive tokens for all viewports,
63
+ * similar to calling useResponsiveThemeTokens but with the callback pattern of useThemeTokensCallback.
64
+ *
65
+ * Scenarios where `useResponsiveThemeTokensCallback` should be used:
66
+ *
67
+ * - Where responsive tokens are to be obtained from state that is accessible only in scopes like callbacks
68
+ * and render functions, where calling useResponsiveThemeTokens directly would be disallowed by React's hook rules.
69
+ * - When using media query stylesheets and need to resolve tokens based on dynamic state (e.g., pressed, hovered)
70
+ * that changes at runtime.
71
+ * - Passing a responsive tokens getter down via a child component's `tokens` prop, applying rules using the
72
+ * child component's current state.
73
+ *
74
+ * The function returned may be called with an object of state appearances to get an object
75
+ * of tokens for each viewport, which can then be passed to createMediaQueryStyles.
76
+ *
77
+ * @example
78
+ * // Resolving responsive tokens inside Pressable's style function, based on Pressable state
79
+ * const PressMe = ({ tokens, variant, children }) => {
80
+ * const getResponsiveTokens = useResponsiveThemeTokensCallback('PressMe', tokens, variant)
81
+ * const getPressableStyle = ({ pressed }) => {
82
+ * const responsiveTokens = getResponsiveTokens({ pressed })
83
+ * const mediaQueryStyles = createMediaQueryStyles(responsiveTokens)
84
+ * return mediaQueryStyles
85
+ * }
86
+ * return <Pressable style={getPressableStyle}>{children}</Pressable>
87
+ * }
88
+ *
89
+ * @example
90
+ * // Setting the theme in a parent and resolving it in a child based on child's state
91
+ * const MenuButton = ({ tokens, variant, ...buttonProps }) => {
92
+ * // Define what theme, variant etc we want in this component...
93
+ * const getResponsiveTokens = useResponsiveThemeTokensCallback('Button', tokens, variant)
94
+ * // ...resolve them in another component based on its state (e.g. press, hover...)
95
+ * return <ButtonBase tokens={getResponsiveTokens} accessibilityRole="menuitem" {...buttonProps} />
96
+ * }
97
+ *
98
+ * @typedef {Object} ResponsiveObject
99
+ * @property {TokensSet} xs
100
+ * @property {TokensSet} sm
101
+ * @property {TokensSet} md
102
+ * @property {TokensSet} lg
103
+ * @property {TokensSet} xl
104
+ *
105
+ * @param {string} componentName - the name as defined in the theme schema of the component whose theme is to be used
106
+ * @param {TokensProp} [tokens] - every themed component should accept a `tokens` prop allowing theme tokens to be overridden
107
+ * @param {AppearanceSet} [variants] - variants passed in as props that don't change dynamically
108
+ * @returns {(states: AppearanceSet, tokenOverrides?: TokensProp) => ResponsiveObject}
109
+ * - callback function that returns an overridable responsive tokens object for current state. Only pass
110
+ * tokenOverrides in rare cases where tokens overrides are also generated outside hook scope.
111
+ */
112
+ const useResponsiveThemeTokensCallback = (componentName, tokens = {}, variants = {}) => {
113
+ const theme = useTheme()
114
+ const componentTheme = getComponentTheme(theme, componentName)
115
+ const getResponsiveThemeTokensCallback = useCallback(
116
+ (states, tokenOverrides) => {
117
+ const resolvedTokens = resolveThemeTokens(
118
+ tokens,
119
+ mergeAppearances(variants, states),
120
+ tokenOverrides
121
+ )
122
+ return getResponsiveThemeTokens(componentTheme, resolvedTokens, variants, states)
123
+ },
124
+ [componentTheme, tokens, variants]
125
+ )
126
+ return getResponsiveThemeTokensCallback
127
+ }
128
+
129
+ export default useResponsiveThemeTokensCallback