@telus-uds/components-base 1.71.0 → 1.73.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 (115) hide show
  1. package/CHANGELOG.md +37 -2
  2. package/lib/Box/Box.js +17 -6
  3. package/lib/ColourToggle/ColourBubble.js +135 -0
  4. package/lib/ColourToggle/ColourToggle.js +101 -0
  5. package/lib/ColourToggle/index.js +10 -0
  6. package/lib/FlexGrid/Col/Col.js +42 -19
  7. package/lib/FlexGrid/FlexGrid.js +40 -17
  8. package/lib/FlexGrid/Row/Row.js +45 -22
  9. package/lib/Listbox/ListboxGroup.js +7 -1
  10. package/lib/Modal/ModalContent.js +4 -6
  11. package/lib/MultiSelectFilter/MultiSelectFilter.js +1 -0
  12. package/lib/Notification/Notification.js +13 -5
  13. package/lib/OrderedList/Item.js +180 -0
  14. package/lib/OrderedList/ItemBase.js +54 -0
  15. package/lib/OrderedList/OrderedList.js +71 -0
  16. package/lib/OrderedList/OrderedListBase.js +47 -0
  17. package/lib/OrderedList/index.js +10 -0
  18. package/lib/Responsive/Responsive.js +24 -14
  19. package/lib/Responsive/ResponsiveProp.js +46 -0
  20. package/lib/Responsive/ResponsiveWithMediaQueryStyleSheet.js +72 -0
  21. package/lib/ThemeProvider/ThemeProvider.js +5 -2
  22. package/lib/ThemeProvider/index.js +9 -1
  23. package/lib/ThemeProvider/useResponsiveThemeTokens.js +89 -0
  24. package/lib/Typography/Typography.js +48 -22
  25. package/lib/index.js +16 -0
  26. package/lib/server.js +40 -0
  27. package/lib/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +56 -0
  28. package/lib/utils/ssr-media-query/create-stylesheet/index.android.js +10 -0
  29. package/lib/utils/ssr-media-query/create-stylesheet/index.ios.js +10 -0
  30. package/lib/utils/ssr-media-query/create-stylesheet/index.js +44 -0
  31. package/lib/utils/ssr-media-query/utils/create-media-query-styles.js +39 -6
  32. package/lib-module/Box/Box.js +17 -6
  33. package/lib-module/ColourToggle/ColourBubble.js +125 -0
  34. package/lib-module/ColourToggle/ColourToggle.js +92 -0
  35. package/lib-module/ColourToggle/index.js +2 -0
  36. package/lib-module/FlexGrid/Col/Col.js +42 -19
  37. package/lib-module/FlexGrid/FlexGrid.js +40 -17
  38. package/lib-module/FlexGrid/Row/Row.js +45 -22
  39. package/lib-module/Listbox/ListboxGroup.js +7 -1
  40. package/lib-module/Modal/ModalContent.js +4 -6
  41. package/lib-module/MultiSelectFilter/MultiSelectFilter.js +1 -0
  42. package/lib-module/Notification/Notification.js +13 -5
  43. package/lib-module/OrderedList/Item.js +171 -0
  44. package/lib-module/OrderedList/ItemBase.js +43 -0
  45. package/lib-module/OrderedList/OrderedList.js +61 -0
  46. package/lib-module/OrderedList/OrderedListBase.js +36 -0
  47. package/lib-module/OrderedList/index.js +2 -0
  48. package/lib-module/Responsive/Responsive.js +24 -15
  49. package/lib-module/Responsive/ResponsiveProp.js +39 -0
  50. package/lib-module/Responsive/ResponsiveWithMediaQueryStyleSheet.js +64 -0
  51. package/lib-module/ThemeProvider/ThemeProvider.js +5 -2
  52. package/lib-module/ThemeProvider/index.js +1 -0
  53. package/lib-module/ThemeProvider/useResponsiveThemeTokens.js +81 -0
  54. package/lib-module/Typography/Typography.js +50 -24
  55. package/lib-module/index.js +2 -0
  56. package/lib-module/server.js +4 -0
  57. package/lib-module/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +48 -0
  58. package/lib-module/utils/ssr-media-query/create-stylesheet/index.android.js +2 -0
  59. package/lib-module/utils/ssr-media-query/create-stylesheet/index.ios.js +2 -0
  60. package/lib-module/utils/ssr-media-query/create-stylesheet/index.js +36 -0
  61. package/lib-module/utils/ssr-media-query/utils/create-media-query-styles.js +36 -6
  62. package/package.json +13 -2
  63. package/src/Box/Box.jsx +35 -17
  64. package/src/ColourToggle/ColourBubble.jsx +111 -0
  65. package/src/ColourToggle/ColourToggle.jsx +83 -0
  66. package/src/ColourToggle/index.js +3 -0
  67. package/src/FlexGrid/Col/Col.jsx +42 -13
  68. package/src/FlexGrid/FlexGrid.jsx +40 -11
  69. package/src/FlexGrid/Row/Row.jsx +40 -16
  70. package/src/Listbox/ListboxGroup.jsx +9 -2
  71. package/src/Modal/ModalContent.jsx +4 -6
  72. package/src/MultiSelectFilter/MultiSelectFilter.jsx +2 -0
  73. package/src/Notification/Notification.jsx +15 -3
  74. package/src/OrderedList/Item.jsx +152 -0
  75. package/src/OrderedList/ItemBase.jsx +43 -0
  76. package/src/OrderedList/OrderedList.jsx +61 -0
  77. package/src/OrderedList/OrderedListBase.jsx +33 -0
  78. package/src/OrderedList/index.js +3 -0
  79. package/src/Responsive/Responsive.jsx +24 -11
  80. package/src/Responsive/ResponsiveProp.jsx +33 -0
  81. package/src/Responsive/ResponsiveWithMediaQueryStyleSheet.jsx +58 -0
  82. package/src/ThemeProvider/ThemeProvider.jsx +5 -2
  83. package/src/ThemeProvider/index.js +1 -0
  84. package/src/ThemeProvider/useResponsiveThemeTokens.js +85 -0
  85. package/src/Typography/Typography.jsx +72 -24
  86. package/src/index.js +2 -0
  87. package/src/server.js +4 -0
  88. package/src/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +41 -0
  89. package/src/utils/ssr-media-query/create-stylesheet/index.android.js +3 -0
  90. package/src/utils/ssr-media-query/create-stylesheet/index.ios.js +3 -0
  91. package/src/utils/ssr-media-query/create-stylesheet/index.js +33 -0
  92. package/src/utils/ssr-media-query/utils/create-media-query-styles.js +21 -6
  93. package/types/Badge.d.ts +28 -0
  94. package/types/Box.d.ts +52 -0
  95. package/types/ChevronLink.d.ts +47 -0
  96. package/types/Common.d.ts +106 -0
  97. package/types/Divider.d.ts +19 -0
  98. package/types/ExpandCollapse.d.ts +65 -0
  99. package/types/HorizontalScrollButton.d.ts +16 -0
  100. package/types/Icon.d.ts +21 -0
  101. package/types/Link.d.ts +48 -0
  102. package/types/List.d.ts +48 -0
  103. package/types/Search.d.ts +38 -0
  104. package/types/Select.d.ts +57 -0
  105. package/types/Spacer.d.ts +5 -0
  106. package/types/StackView.d.ts +28 -0
  107. package/types/Tabs.d.ts +46 -0
  108. package/types/TextButton.d.ts +11 -0
  109. package/types/ToggleSwitch.d.ts +54 -0
  110. package/types/ToolTip.d.ts +40 -0
  111. package/types/Typography.d.ts +39 -0
  112. package/types/index.d.ts +62 -0
  113. package/lib/utils/ssr-media-query/create-stylesheet.js +0 -76
  114. package/lib-module/utils/ssr-media-query/create-stylesheet.js +0 -68
  115. package/src/utils/ssr-media-query/create-stylesheet.js +0 -61
@@ -1,29 +1,42 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { viewports } from '@telus-uds/system-constants'
4
- import { useResponsiveProp } from '../utils'
3
+ import { useTheme } from '../ThemeProvider'
4
+ import ResponsiveProp from './ResponsiveProp'
5
+ import ResponsiveWithMediaQueryStyleSheet from './ResponsiveWithMediaQueryStyleSheet'
5
6
 
6
7
  /**
7
8
  * Responsive conditionally renders children based on whether the viewport matches the provided
8
9
  * min and max viewports.
9
10
  *
10
- * In SSR, like other viewport utilities, it treats the viewport as `xs` both in SSR itself and
11
+ * If enableMediaQueryStyleSheet themeOption is set to false in ThemeProvider, then in SSR,
12
+ * like other viewport utilities, it treats the viewport as `xs` both in SSR itself and
11
13
  * during first hydration on the client side; then if the viewport is not `xs`, it re-renders
12
14
  * after hydration. This may cause a layout shift on devices other than the narrowest.
15
+ *
16
+ * If enableMediaQueryStyleSheet themeOption is set to true in ThemeProvider, then media query stylesheet
17
+ * is used to hide and show children of `Responsive` within a View.
13
18
  */
14
19
 
15
20
  const Responsive = ({ min = 'xs', max, children }) => {
16
- // Start returning children at the 'min' viewport or greater
17
- const byViewports = { [min]: children }
18
- if (max && max !== 'xl') {
19
- // Stop returning children at the viewport one above 'max' or greater
20
- const maxIndex = viewports.keys.indexOf(max)
21
- const maxPlusOne = maxIndex >= 0 ? viewports.keys[maxIndex + 1] : null
22
- if (maxPlusOne) byViewports[maxPlusOne] = null
21
+ const {
22
+ themeOptions: { enableMediaQueryStyleSheet }
23
+ } = useTheme()
24
+ if (enableMediaQueryStyleSheet) {
25
+ return (
26
+ <ResponsiveWithMediaQueryStyleSheet min={min} max={max}>
27
+ {children}
28
+ </ResponsiveWithMediaQueryStyleSheet>
29
+ )
23
30
  }
24
- return <>{useResponsiveProp(byViewports, null)}</>
31
+ return (
32
+ <ResponsiveProp min={min} max={max}>
33
+ {children}
34
+ </ResponsiveProp>
35
+ )
25
36
  }
26
37
 
38
+ Responsive.displayName = 'Responsive'
39
+
27
40
  Responsive.propTypes = {
28
41
  /**
29
42
  * To hide children of `Responsive` if the current viewport is smaller than `min`
@@ -0,0 +1,33 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+
4
+ import { viewports } from '@telus-uds/system-constants'
5
+ import { useResponsiveProp } from '../utils'
6
+
7
+ const ResponsiveProp = ({ min = 'xs', max, children }) => {
8
+ const byViewports = { [min]: children }
9
+ if (max && max !== 'xl') {
10
+ // Stop returning children at the viewport one above 'max' or greater
11
+ const maxIndex = viewports.keys.indexOf(max)
12
+ const maxPlusOne = maxIndex >= 0 ? viewports.keys[maxIndex + 1] : null
13
+ if (maxPlusOne) byViewports[maxPlusOne] = null
14
+ }
15
+ const responsiveProp = useResponsiveProp(byViewports, null)
16
+ return <>{responsiveProp}</>
17
+ }
18
+
19
+ ResponsiveProp.displayName = 'Responsive'
20
+
21
+ ResponsiveProp.propTypes = {
22
+ /**
23
+ * To hide children of `Responsive` if the current viewport is smaller than `min`
24
+ */
25
+ min: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
26
+ /**
27
+ * To hide children of `Responsive` if the current viewport is larger than `max`
28
+ */
29
+ max: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
30
+ children: PropTypes.node.isRequired
31
+ }
32
+
33
+ export default ResponsiveProp
@@ -0,0 +1,58 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { viewports } from '@telus-uds/system-constants'
4
+ import { BaseView, StyleSheet, createMediaQueryStyles } from '../utils'
5
+
6
+ function generateResponsiveStyles(min, max) {
7
+ const viewportsArray = viewports.keys
8
+ const minIndex = viewportsArray.indexOf(min)
9
+ const maxIndex = viewportsArray.indexOf(max)
10
+ let hiddenViewports = []
11
+
12
+ if (minIndex !== -1) {
13
+ hiddenViewports = viewportsArray.slice(0, minIndex)
14
+ }
15
+ if (maxIndex !== -1) {
16
+ hiddenViewports = hiddenViewports.concat(viewportsArray.slice(maxIndex + 1))
17
+ }
18
+
19
+ const styles = {}
20
+
21
+ viewportsArray.forEach((viewport) => {
22
+ if (hiddenViewports.includes(viewport)) {
23
+ styles[viewport] = { display: 'none' }
24
+ }
25
+ })
26
+ return createMediaQueryStyles(styles, false)
27
+ }
28
+ const ResponsiveWithMediaQueryStyleSheet = ({ min, max, children }) => {
29
+ const { ids, styles } = StyleSheet.create({
30
+ responsive: {
31
+ flexDirection: 'inherit',
32
+ alignItems: 'inherit',
33
+ justifyContent: 'inherit',
34
+ ...generateResponsiveStyles(min, max)
35
+ }
36
+ })
37
+ return (
38
+ <BaseView style={styles.responsive} dataSet={ids.responsive && { media: ids.responsive }}>
39
+ {children}
40
+ </BaseView>
41
+ )
42
+ }
43
+
44
+ ResponsiveWithMediaQueryStyleSheet.displayName = 'Responsive'
45
+
46
+ ResponsiveWithMediaQueryStyleSheet.propTypes = {
47
+ /**
48
+ * To hide children of `Responsive` if the current viewport is smaller than `min`
49
+ */
50
+ min: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
51
+ /**
52
+ * To hide children of `Responsive` if the current viewport is larger than `max`
53
+ */
54
+ max: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
55
+ children: PropTypes.node.isRequired
56
+ }
57
+
58
+ export default ResponsiveWithMediaQueryStyleSheet
@@ -16,7 +16,8 @@ const defaultThemeOptions = {
16
16
  // TODO: switch `forceZIndex` to be false by default in the next major version
17
17
  forceZIndex: true,
18
18
  // TODO: switch `enableHelmetSSR` to be false by default in the next major version
19
- enableHelmetSSR: true
19
+ enableHelmetSSR: true,
20
+ enableMediaQueryStyleSheet: false
20
21
  }
21
22
 
22
23
  const ThemeProvider = ({ children, defaultTheme, themeOptions = {} }) => {
@@ -65,12 +66,14 @@ ThemeProvider.propTypes = {
65
66
  * - `enableHelmetSSR`: on Web SSR, allows React Helmet to run during server-side rendering. This should be
66
67
  * disabled unless a web app has been specifically configured to stop React Helmet accumulating
67
68
  * instances (which may cause a memory leak). See React Helmet's docs: https://github.com/nfl/react-helmet
69
+ * - `enableMediaQueryStyleSheet`: enables the use of Media Query StyleSheet.
68
70
  */
69
71
  themeOptions: PropTypes.shape({
70
72
  forceAbsoluteFontSizing: PropTypes.bool,
71
73
  forceZIndex: PropTypes.bool,
72
74
  enableHelmetSSR: PropTypes.bool,
73
- contentMaxWidth: responsiveProps.getTypeOptionallyByViewport(PropTypes.number)
75
+ contentMaxWidth: responsiveProps.getTypeOptionallyByViewport(PropTypes.number),
76
+ enableMediaQueryStyleSheet: PropTypes.bool
74
77
  })
75
78
  }
76
79
 
@@ -2,6 +2,7 @@ import ThemeProvider from './ThemeProvider'
2
2
 
3
3
  export { default as useTheme } from './useTheme'
4
4
  export { default as useSetTheme } from './useSetTheme'
5
+ export { default as useResponsiveThemeTokens } from './useResponsiveThemeTokens'
5
6
  export * from './useThemeTokens'
6
7
 
7
8
  export * from './utils'
@@ -0,0 +1,85 @@
1
+ import { viewports } from '@telus-uds/system-constants'
2
+ import useTheme from './useTheme'
3
+ import { getComponentTheme, mergeAppearances, resolveThemeTokens } from './utils'
4
+
5
+ const getResponsiveThemeTokens = (
6
+ { rules = [], tokens: defaultThemeTokens = {} },
7
+ tokensProp,
8
+ variants = {},
9
+ states
10
+ ) => {
11
+ const appearances = mergeAppearances(variants, states)
12
+
13
+ const tokensByViewport = Object.fromEntries(
14
+ viewports.keys.map((viewport) => [viewport, { ...defaultThemeTokens }])
15
+ )
16
+
17
+ // Go through each rule and collect them for the corresponding viewport if they apply
18
+ rules.forEach((rule) => {
19
+ if (doesRuleApply(rule, appearances)) {
20
+ // If the rule does not have a viewport specified, we collect it in all viewports
21
+ let targetViewports = rule.if.viewport || viewports.keys
22
+ if (!Array.isArray(targetViewports)) {
23
+ targetViewports = [targetViewports]
24
+ }
25
+ targetViewports.forEach((viewport) => {
26
+ tokensByViewport[viewport] = { ...tokensByViewport[viewport], ...rule.tokens }
27
+ })
28
+ }
29
+ })
30
+
31
+ Object.keys(tokensByViewport).forEach((viewport) => {
32
+ tokensByViewport[viewport] = resolveThemeTokens(
33
+ tokensByViewport[viewport],
34
+ appearances,
35
+ tokensProp
36
+ )
37
+ })
38
+
39
+ return tokensByViewport
40
+ }
41
+
42
+ const doesRuleApply = (rule, appearances) =>
43
+ Object.entries(rule.if).every((condition) => doesConditionApply(condition, appearances))
44
+
45
+ const doesConditionApply = ([key, value], appearances) => {
46
+ if (key === 'viewport') {
47
+ return true
48
+ }
49
+ // use null rather than undefined so we can serialise the value in themes
50
+ const appearanceValue = appearances[key] ?? null
51
+ return Array.isArray(value) ? value.includes(appearanceValue) : value === appearanceValue
52
+ }
53
+
54
+ /**
55
+ * @typedef {import('../utils/props/tokens.js').TokensSet} TokensSet
56
+ * @typedef {import('../utils/props/tokens.js').TokensProp} TokensProp
57
+ * @typedef {import('../utils/props/variantProp').AppearanceSet} AppearanceSet
58
+ *
59
+ * Returns a complete set of tokens for a component for each viewport based on which of the
60
+ * component's theme rules apply to the current set of theme appearances.
61
+ * Pass the returned output to createMediaQueryStyles to generate media query styles for use inside
62
+ * the media query stylesheet from './utils/ssr-media-query'.
63
+ *
64
+ * @typedef {Object} ResponsiveObject
65
+ * @property {TokensSet} xs
66
+ * @property {TokensSet} sm
67
+ * @property {TokensSet} md
68
+ * @property {TokensSet} lg
69
+ * @property {TokensSet} xl
70
+ *
71
+ * @param { string } componentName
72
+ * @param { TokensProp } tokens
73
+ * @param { AppearanceSet } variants
74
+ * @param { AppearanceSet } states
75
+ * @returns { ResponsiveObject }
76
+ */
77
+
78
+ const useResponsiveThemeTokens = (componentName, tokens = {}, variants = {}, states = {}) => {
79
+ const theme = useTheme()
80
+ const componentTheme = getComponentTheme(theme, componentName)
81
+ const themeTokens = getResponsiveThemeTokens(componentTheme, tokens, variants, states)
82
+ return themeTokens
83
+ }
84
+
85
+ export default useResponsiveThemeTokens
@@ -2,8 +2,7 @@ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { Text, View } from 'react-native'
4
4
 
5
- import { useTheme, useThemeTokens } from '../ThemeProvider'
6
- import { useViewport } from '../ViewportProvider'
5
+ import { useResponsiveThemeTokens, useTheme, useThemeTokens } from '../ThemeProvider'
7
6
  import { applyTextStyles } from '../ThemeProvider/utils'
8
7
  import {
9
8
  a11yProps,
@@ -15,17 +14,29 @@ import {
15
14
  textTags,
16
15
  textProps,
17
16
  viewProps,
18
- getA11yPropsFromHtmlTag
17
+ getA11yPropsFromHtmlTag,
18
+ StyleSheet,
19
+ createMediaQueryStyles
19
20
  } from '../utils'
21
+ import { useViewport } from '../ViewportProvider'
20
22
  /**
21
23
  * @typedef {import('../utils/a11y/semantics').TextTag} TextTag
22
24
  */
23
25
 
24
26
  const [selectContainerProps, selectedContainerPropTypes] = selectSystemProps([a11yProps, viewProps])
25
27
  const [selectTextProps, selectedTextPropTypes] = selectSystemProps([textProps])
26
-
27
28
  const selectTextStyles = (
28
- { fontWeight, fontSize, color, lineHeight, fontName, textAlign, textTransform, letterSpacing },
29
+ {
30
+ fontWeight,
31
+ fontSize,
32
+ color,
33
+ lineHeight,
34
+ fontName,
35
+ textAlign,
36
+ textTransform,
37
+ letterSpacing,
38
+ textDecorationLine
39
+ },
29
40
  themeOptions
30
41
  ) =>
31
42
  applyTextStyles({
@@ -37,7 +48,8 @@ const selectTextStyles = (
37
48
  themeOptions,
38
49
  textAlign,
39
50
  textTransform,
40
- letterSpacing
51
+ letterSpacing,
52
+ textDecorationLine
41
53
  })
42
54
 
43
55
  // General-purpose flexible theme-neutral base component for text
@@ -59,19 +71,56 @@ const Typography = forwardRef(
59
71
  ref
60
72
  ) => {
61
73
  const viewport = useViewport()
62
- const { superScriptFontSize, ...themeTokens } = useThemeTokens('Typography', tokens, variant, {
63
- viewport
64
- })
65
74
  const { themeOptions } = useTheme()
66
75
 
76
+ const { enableMediaQueryStyleSheet } = themeOptions
77
+
78
+ const useTokens = enableMediaQueryStyleSheet ? useResponsiveThemeTokens : useThemeTokens
79
+ const themeTokens = useTokens('Typography', tokens, variant)
80
+ const maxFontSizeMultiplier = enableMediaQueryStyleSheet
81
+ ? getMaxFontMultiplier(themeTokens[viewport])
82
+ : getMaxFontMultiplier(themeTokens)
83
+ const textDecorationLine = strikeThrough ? 'line-through' : 'none'
84
+
85
+ let textStyles
86
+ let mediaIds
87
+
88
+ if (enableMediaQueryStyleSheet) {
89
+ const transformedThemeTokens = Object.entries(themeTokens).reduce(
90
+ (acc, [vp, viewportTokens]) => {
91
+ acc[vp] = selectTextStyles(
92
+ {
93
+ textAlign: align,
94
+ textDecorationLine,
95
+ ...viewportTokens
96
+ },
97
+ themeOptions
98
+ )
99
+ return acc
100
+ },
101
+ {}
102
+ )
103
+ const mediaQueryStyles = createMediaQueryStyles(transformedThemeTokens)
104
+ const { ids, styles } = StyleSheet.create({
105
+ text: mediaQueryStyles
106
+ })
107
+ textStyles = styles.text
108
+ mediaIds = ids.text
109
+ } else {
110
+ textStyles = selectTextStyles(
111
+ {
112
+ textAlign: align,
113
+ textDecorationLine,
114
+ ...themeTokens
115
+ },
116
+ themeOptions
117
+ )
118
+ }
119
+
67
120
  const resolvedTextProps = {
68
121
  ...selectTextProps(rest),
69
- style: selectTextStyles(
70
- align ? { ...themeTokens, textAlign: align } : themeTokens,
71
- themeOptions
72
- ),
73
122
  dataSet,
74
- maxFontSizeMultiplier: getMaxFontMultiplier(themeTokens)
123
+ maxFontSizeMultiplier
75
124
  }
76
125
 
77
126
  const containerProps = {
@@ -83,7 +132,7 @@ const Typography = forwardRef(
83
132
  const resetTagStyling = (child) => {
84
133
  if (typeof child === 'object' && (child?.type === 'sub' || child?.type === 'sup')) {
85
134
  const childStyles = child?.props?.style || {}
86
- const supFontSize = childStyles.fontSize ?? superScriptFontSize
135
+ const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize
87
136
  const sanitizedChild = React.cloneElement(child, {
88
137
  style: {
89
138
  ...childStyles,
@@ -91,10 +140,8 @@ const Typography = forwardRef(
91
140
  lineHeight: 0
92
141
  }
93
142
  })
94
-
95
143
  return sanitizedChild
96
144
  }
97
-
98
145
  return child
99
146
  }
100
147
 
@@ -106,19 +153,20 @@ const Typography = forwardRef(
106
153
  return resetTagStyling(children)
107
154
  }
108
155
 
109
- const textDecorationLine = strikeThrough ? 'line-through' : 'none'
110
- const textStyles = resolvedTextProps.style
111
- ? { ...resolvedTextProps.style, textDecorationLine }
112
- : { textDecorationLine }
113
-
114
156
  return block ? (
115
157
  <View ref={ref} {...containerProps}>
116
- <Text {...resolvedTextProps} style={textStyles}>
158
+ <Text {...resolvedTextProps} style={textStyles} dataSet={mediaIds && { media: mediaIds }}>
117
159
  {sanitizeChildren(children)}
118
160
  </Text>
119
161
  </View>
120
162
  ) : (
121
- <Text ref={ref} {...containerProps} {...resolvedTextProps} style={textStyles}>
163
+ <Text
164
+ ref={ref}
165
+ {...containerProps}
166
+ {...resolvedTextProps}
167
+ style={textStyles}
168
+ dataSet={mediaIds && { media: mediaIds }}
169
+ >
122
170
  {sanitizeChildren(children)}
123
171
  </Text>
124
172
  )
package/src/index.js CHANGED
@@ -11,6 +11,7 @@ export { default as Checkbox } from './Checkbox'
11
11
  export * from './Checkbox'
12
12
  export { default as CheckboxCard } from './CheckboxCard'
13
13
  export { default as CheckboxCardGroup } from './CheckboxCardGroup'
14
+ export { default as ColourToggle } from './ColourToggle'
14
15
  export { default as Divider } from './Divider'
15
16
  export { default as ExpandCollapse, Accordion } from './ExpandCollapse'
16
17
  export { default as Feedback } from './Feedback'
@@ -28,6 +29,7 @@ export { default as List, ListItem, ListBase } from './List'
28
29
  export { default as Modal } from './Modal'
29
30
  export { default as MultiSelectFilter } from './MultiSelectFilter'
30
31
  export { default as Notification } from './Notification'
32
+ export { default as OrderedList } from './OrderedList'
31
33
  export { default as Pagination } from './Pagination'
32
34
  export { default as Progress } from './Progress'
33
35
  export { default as QuickLinks } from './QuickLinks'
package/src/server.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default as selectSystemProps } from './utils/props/selectSystemProps'
2
+ export { getTokensPropType } from './utils/props/tokens'
3
+ export { default as htmlAttrs } from './utils/htmlAttrs'
4
+ export { getComponentTheme, getThemeTokens } from './ThemeProvider/utils/theme-tokens'
@@ -0,0 +1,41 @@
1
+ import mediaQuery from 'css-mediaquery'
2
+ import { Dimensions } from 'react-native'
3
+ import { isMediaOrPseudo, isMedia } from '../utils/common'
4
+
5
+ const createStyleSheet = (stylesWithQuery) => {
6
+ if (!stylesWithQuery) return { ids: {}, styles: {}, fullStyles: {} }
7
+ let cleanStyles
8
+ const ids = {}
9
+ Object.keys(stylesWithQuery).forEach((key) => {
10
+ if (!stylesWithQuery?.[key]) return
11
+
12
+ const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo)
13
+ cleanStyles = JSON.parse(JSON.stringify(stylesWithQuery))
14
+ mediaQueriesAndPseudoClasses.forEach((str) => {
15
+ if (isMedia(str)) {
16
+ const mqStr = str.replace('@media', '')
17
+ const { width, height } = Dimensions.get('window')
18
+
19
+ const isMatchingMediaQuery = mediaQuery.match(mqStr, {
20
+ width,
21
+ height,
22
+ orientation: width > height ? 'landscape' : 'portrait',
23
+ 'aspect-ratio': width / height
24
+ })
25
+
26
+ if (isMatchingMediaQuery) {
27
+ cleanStyles = {
28
+ ...cleanStyles,
29
+ [key]: { ...cleanStyles[key], ...stylesWithQuery[key][str] }
30
+ }
31
+ }
32
+ }
33
+
34
+ delete cleanStyles[key][str]
35
+ })
36
+ })
37
+
38
+ return { ids, styles: cleanStyles, fullStyles: stylesWithQuery }
39
+ }
40
+
41
+ export default createStyleSheet
@@ -0,0 +1,3 @@
1
+ import createStyleSheet from './create-stylesheet-mobile'
2
+
3
+ export default createStyleSheet
@@ -0,0 +1,3 @@
1
+ import createStyleSheet from './create-stylesheet-mobile'
2
+
3
+ export default createStyleSheet
@@ -0,0 +1,33 @@
1
+ import { addCss } from '../utils/inject'
2
+ import createDeclarationBlock from '../utils/create-declaration-block'
3
+ import hash from '../hash'
4
+ import { isMediaOrPseudo, deepClone, createCssRule } from '../utils/common'
5
+
6
+ const createStyleSheet = (stylesWithQuery) => {
7
+ if (!stylesWithQuery) return { ids: {}, styles: {}, fullStyles: {} }
8
+ let cleanStyles
9
+ let ids = {}
10
+ Object.keys(stylesWithQuery).forEach((key) => {
11
+ if (!stylesWithQuery?.[key]) return
12
+
13
+ const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo)
14
+ cleanStyles = deepClone(stylesWithQuery)
15
+ mediaQueriesAndPseudoClasses.forEach((query) => {
16
+ const css = createDeclarationBlock(stylesWithQuery[key][query])
17
+ const stringHash = `rnmq-${hash(`${key}${query}${css}`)}`
18
+ const rule = createCssRule(query, stringHash, css)
19
+
20
+ addCss(`${stringHash}`, rule)
21
+ delete cleanStyles[key][query]
22
+
23
+ ids = {
24
+ ...ids,
25
+ [key]: `${ids?.[key] ? `${ids[key]} ` : ''}${stringHash}`
26
+ }
27
+ })
28
+ })
29
+
30
+ return { ids, styles: cleanStyles, fullStyles: stylesWithQuery }
31
+ }
32
+
33
+ export default createStyleSheet
@@ -1,20 +1,35 @@
1
1
  import { viewports } from '@telus-uds/system-constants'
2
2
 
3
+ const inherit = ({ xs, sm = xs, md = sm, lg = md, xl = lg }) => ({ xs, sm, md, lg, xl })
4
+
3
5
  /**
4
6
  * @typedef { Object } CssStyles
5
- * @typedef { Record<"xs" | "sm" | "md" | "lg" | "xl", CssStyles> } ViewportStyles
7
+ */
8
+
9
+ /**
10
+ * @typedef { Object } ViewportStyles
11
+ * @property { CssStyles } xs - The CSS styles for the "xs" viewport (required).
12
+ * @property { CssStyles } [sm] - Optional styles for the "sm" viewport. Inherits from "xs" if not specified.
13
+ * @property { CssStyles } [md] - Optional styles for the "md" viewport. Inherits from "sm" if not specified.
14
+ * @property { CssStyles } [lg] - Optional styles for the "lg" viewport. Inherits from "md" if not specified.
15
+ * @property { CssStyles } [xl] - Optional styles for the "xl" viewport. Inherits from "lg" if not specified.
16
+ */
17
+
18
+ /**
6
19
  * @typedef { Record<String, CssStyles> } MediaQueryStyles
7
20
  */
8
21
 
9
22
  /**
10
23
  * Generates media query styles based on specified viewport styles.
11
- * @param {ViewportStyles} viewportStyles
12
- * @returns { MediaQueryStyles }
24
+ * @param { Object } viewportStyles - The styles for different viewports.
25
+ * @param { boolean } [shouldInherit=true] - Flag indicating whether to inherit styles.
26
+ * @returns { Object } - The media query styles.
13
27
  */
14
28
 
15
- function createMediaQueryStyles(viewportStyles) {
16
- const viewportsArray = Object.keys(viewportStyles)
17
- const mediaQueries = Object.entries(viewportStyles).reduce((acc, [viewport, styles]) => {
29
+ function createMediaQueryStyles(viewportStyles, shouldInherit = true) {
30
+ const effectiveStyles = shouldInherit ? inherit(viewportStyles) : viewportStyles
31
+ const viewportsArray = viewports.keys
32
+ const mediaQueries = Object.entries(effectiveStyles).reduce((acc, [viewport, styles]) => {
18
33
  const minWidth = viewports.map.get(viewport)
19
34
  const nextViewport = viewportsArray[viewportsArray.indexOf(viewport) + 1]
20
35
  const maxWidth = viewports.map.get(nextViewport)
@@ -0,0 +1,28 @@
1
+ export interface BadgeProps {
2
+ text: string
3
+ borderColor?: string
4
+ textColor?: string
5
+ }
6
+
7
+ type BadgeVariants = {
8
+ alternative?: boolean
9
+ inverse?: boolean
10
+ outline?: boolean
11
+ purpose?: 'offer' | 'editorial'
12
+ }
13
+
14
+ export type BadgeTokens = {
15
+ backgroundColor?: string
16
+ borderColor?: string
17
+ borderRadius?: number
18
+ borderWidth?: number
19
+ color?: string
20
+ fontName?: string
21
+ fontSize?: number
22
+ fontWeight?: number
23
+ gradient?: string
24
+ paddingBottom?: number
25
+ paddingLeft?: number
26
+ paddingRight?: number
27
+ paddingTop?: number
28
+ }
package/types/Box.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import { ReactNode, ReactElement } from 'react'
2
+ import { ScrollViewProps } from 'react-native'
3
+ import { ResponsiveSpacing, SemanticTag } from './Common'
4
+
5
+ type BoxVariants = {
6
+ background?:
7
+ | 'lightest'
8
+ | 'lighter'
9
+ | 'light'
10
+ | 'dark'
11
+ | 'darker'
12
+ | 'darkest'
13
+ | 'critical'
14
+ | 'danger'
15
+ | 'warning'
16
+ | 'positive'
17
+ | 'black'
18
+ | 'featurePrimary'
19
+ | 'featureSecondary'
20
+ | 'featureNeutral'
21
+ | 'featureBrand'
22
+ }
23
+
24
+ type BoxTokens = {
25
+ backgroundColor?: string
26
+ gradient?: string
27
+ borderWidth?: number
28
+ borderColor?: string
29
+ borderTopLeftRadius?: number
30
+ borderTopRightRadius?: number
31
+ borderBottomLeftRadius?: number
32
+ borderBottomRightRadius?: number
33
+ }
34
+
35
+ export interface BoxProps {
36
+ children: ReactNode | ReactElement
37
+ horizontal?: ResponsiveSpacing | number
38
+ vertical?: ResponsiveSpacing | number
39
+ top?: ResponsiveSpacing | number
40
+ bottom?: ResponsiveSpacing | number
41
+ left?: ResponsiveSpacing | number
42
+ right?: ResponsiveSpacing | number
43
+ variant?: BoxVariants
44
+ tokens?: BoxTokens
45
+ space?: ResponsiveSpacing | number
46
+ flex?: number
47
+ scroll?: boolean | ScrollViewProps
48
+ tag?: SemanticTag
49
+ testID?: string
50
+ accessibilityLabel?: string
51
+ accessible?: boolean
52
+ }