@telus-uds/components-base 3.18.0 → 3.20.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 (52) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/jest.config.cjs +10 -2
  3. package/lib/cjs/Box/Box.js +114 -62
  4. package/lib/cjs/Box/backgroundImageStylesMap.js +136 -28
  5. package/lib/cjs/Button/ButtonDropdown.js +1 -0
  6. package/lib/cjs/Carousel/Carousel.js +1 -1
  7. package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +8 -21
  8. package/lib/cjs/Link/LinkBase.js +8 -9
  9. package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +10 -10
  10. package/lib/cjs/Spacer/Spacer.js +65 -5
  11. package/lib/cjs/StepTracker/Step.js +12 -1
  12. package/lib/cjs/StepTracker/StepTracker.js +15 -4
  13. package/lib/cjs/TabBar/TabBar.js +4 -2
  14. package/lib/cjs/TabBar/index.js +2 -0
  15. package/lib/cjs/Tooltip/Backdrop.js +1 -1
  16. package/lib/cjs/utils/index.js +17 -1
  17. package/lib/cjs/utils/isTouchDevice.js +34 -0
  18. package/lib/cjs/utils/useMediaQuerySpacing.js +121 -0
  19. package/lib/esm/Box/Box.js +113 -63
  20. package/lib/esm/Box/backgroundImageStylesMap.js +134 -27
  21. package/lib/esm/Button/ButtonDropdown.js +1 -0
  22. package/lib/esm/Carousel/Carousel.js +2 -2
  23. package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +8 -21
  24. package/lib/esm/Link/LinkBase.js +8 -9
  25. package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +10 -10
  26. package/lib/esm/Spacer/Spacer.js +66 -6
  27. package/lib/esm/StepTracker/Step.js +12 -1
  28. package/lib/esm/StepTracker/StepTracker.js +15 -4
  29. package/lib/esm/TabBar/TabBar.js +4 -2
  30. package/lib/esm/TabBar/index.js +2 -0
  31. package/lib/esm/Tooltip/Backdrop.js +1 -1
  32. package/lib/esm/utils/index.js +3 -1
  33. package/lib/esm/utils/isTouchDevice.js +27 -0
  34. package/lib/esm/utils/useMediaQuerySpacing.js +116 -0
  35. package/lib/package.json +2 -2
  36. package/package.json +2 -2
  37. package/src/Box/Box.jsx +97 -55
  38. package/src/Box/backgroundImageStylesMap.js +48 -15
  39. package/src/Button/ButtonDropdown.jsx +1 -0
  40. package/src/Carousel/Carousel.jsx +3 -2
  41. package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +9 -16
  42. package/src/Link/LinkBase.jsx +11 -9
  43. package/src/MultiSelectFilter/MultiSelectFilter.jsx +11 -10
  44. package/src/Spacer/Spacer.jsx +54 -7
  45. package/src/StepTracker/Step.jsx +47 -27
  46. package/src/StepTracker/StepTracker.jsx +9 -1
  47. package/src/TabBar/TabBar.jsx +3 -1
  48. package/src/TabBar/index.js +3 -0
  49. package/src/Tooltip/Backdrop.jsx +1 -1
  50. package/src/utils/index.js +2 -0
  51. package/src/utils/isTouchDevice.js +34 -0
  52. package/src/utils/useMediaQuerySpacing.js +124 -0
@@ -0,0 +1,124 @@
1
+ import { useThemeTokens } from '../ThemeProvider'
2
+ import { resolveResponsiveProp } from './useResponsiveProp'
3
+
4
+ /**
5
+ * @typedef {import('@telus-uds/system-constants/viewports').Viewport} Viewport
6
+ * @typedef {import('./props/spacingProps.js').SpacingValue} SpacingValue
7
+ * @typedef {import('./props/spacingProps.js').SpacingIndex} SpacingIndex
8
+ * @typedef {import('./props/spacingProps.js').SpacingObject} SpacingObject
9
+ */
10
+
11
+ /**
12
+ * A utility hook that simplifies implementing media query-based responsive spacing.
13
+ *
14
+ * This hook handles the complexity of:
15
+ * - Detecting if a space value is responsive (has viewport keys)
16
+ * - Fetching theme tokens for each viewport
17
+ * - Resolving the correct space index for each viewport
18
+ * - Extracting actual pixel values from theme tokens
19
+ *
20
+ * ## Usage
21
+ *
22
+ * ```jsx
23
+ * const { sizeByViewport } = useMediaQuerySpacing(space, 'spacingScale')
24
+ *
25
+ * // Use sizeByViewport to create media query styles
26
+ * const stylesByViewport = {
27
+ * xs: { padding: sizeByViewport.xs },
28
+ * sm: { padding: sizeByViewport.sm },
29
+ * md: { padding: sizeByViewport.md },
30
+ * lg: { padding: sizeByViewport.lg },
31
+ * xl: { padding: sizeByViewport.xl }
32
+ * }
33
+ * const mediaQueryStyles = createMediaQueryStyles(stylesByViewport)
34
+ * ```
35
+ *
36
+ * ## Parameters
37
+ *
38
+ * @param {SpacingValue} spaceValue - A spacing value (number or responsive object with viewport keys)
39
+ * @param {string} tokenKey - The theme token key to use (e.g., 'spacingScale', 'Typography')
40
+ * @param {object} [tokens={}] - Additional tokens to pass to useThemeTokens
41
+ * @param {object} [variant={}] - Variant to pass to useThemeTokens
42
+ *
43
+ * ## Returns
44
+ *
45
+ * @returns {{
46
+ * spaceIndexByViewport: { xs: number, sm: number, md: number, lg: number, xl: number },
47
+ * sizeByViewport: { xs: number, sm: number, md: number, lg: number, xl: number },
48
+ * tokensByViewport: { xs: object, sm: object, md: object, lg: object, xl: object }
49
+ * }}
50
+ *
51
+ * - `spaceIndexByViewport`: The resolved space index for each viewport
52
+ * - `sizeByViewport`: The actual pixel/number values for each viewport
53
+ * - `tokensByViewport`: The full theme tokens for each viewport (for advanced use cases)
54
+ */
55
+ const useMediaQuerySpacing = (spaceValue, tokenKey = 'spacingScale', tokens = {}, variant = {}) => {
56
+ const isResponsive =
57
+ typeof spaceValue === 'object' &&
58
+ spaceValue !== null &&
59
+ !spaceValue.space &&
60
+ !spaceValue.options
61
+
62
+ const getSpaceIndex = (viewport) => {
63
+ if (isResponsive) {
64
+ return resolveResponsiveProp(spaceValue, viewport)
65
+ }
66
+ if (typeof spaceValue === 'number') {
67
+ return spaceValue
68
+ }
69
+ return spaceValue?.space ?? 1
70
+ }
71
+
72
+ const spaceIndexByViewport = {
73
+ xs: getSpaceIndex('xs'),
74
+ sm: getSpaceIndex('sm'),
75
+ md: getSpaceIndex('md'),
76
+ lg: getSpaceIndex('lg'),
77
+ xl: getSpaceIndex('xl')
78
+ }
79
+
80
+ const tokensXs = useThemeTokens(tokenKey, tokens, variant, {
81
+ space: spaceIndexByViewport.xs,
82
+ viewport: 'xs'
83
+ })
84
+ const tokensSm = useThemeTokens(tokenKey, tokens, variant, {
85
+ space: spaceIndexByViewport.sm,
86
+ viewport: 'sm'
87
+ })
88
+ const tokensMd = useThemeTokens(tokenKey, tokens, variant, {
89
+ space: spaceIndexByViewport.md,
90
+ viewport: 'md'
91
+ })
92
+ const tokensLg = useThemeTokens(tokenKey, tokens, variant, {
93
+ space: spaceIndexByViewport.lg,
94
+ viewport: 'lg'
95
+ })
96
+ const tokensXl = useThemeTokens(tokenKey, tokens, variant, {
97
+ space: spaceIndexByViewport.xl,
98
+ viewport: 'xl'
99
+ })
100
+
101
+ const sizeByViewport = {
102
+ xs: tokensXs.size ?? 0,
103
+ sm: tokensSm.size ?? 0,
104
+ md: tokensMd.size ?? 0,
105
+ lg: tokensLg.size ?? 0,
106
+ xl: tokensXl.size ?? 0
107
+ }
108
+
109
+ const tokensByViewport = {
110
+ xs: tokensXs,
111
+ sm: tokensSm,
112
+ md: tokensMd,
113
+ lg: tokensLg,
114
+ xl: tokensXl
115
+ }
116
+
117
+ return {
118
+ spaceIndexByViewport,
119
+ sizeByViewport,
120
+ tokensByViewport
121
+ }
122
+ }
123
+
124
+ export default useMediaQuerySpacing