@telus-uds/components-base 1.70.0 → 1.72.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 (96) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/jest.setup.js +7 -0
  3. package/lib/Autocomplete/Autocomplete.js +3 -13
  4. package/lib/Card/Card.js +68 -7
  5. package/lib/Card/PressableCardBase.js +2 -0
  6. package/lib/ColourToggle/ColourBubble.js +135 -0
  7. package/lib/ColourToggle/ColourToggle.js +101 -0
  8. package/lib/ColourToggle/index.js +10 -0
  9. package/lib/FlexGrid/Col/Col.js +50 -64
  10. package/lib/FlexGrid/FlexGrid.js +37 -40
  11. package/lib/FlexGrid/Row/Row.js +43 -44
  12. package/lib/Icon/IconText.js +9 -2
  13. package/lib/Link/LinkBase.js +10 -3
  14. package/lib/Modal/ModalContent.js +4 -6
  15. package/lib/OrderedList/Item.js +180 -0
  16. package/lib/OrderedList/ItemBase.js +48 -0
  17. package/lib/OrderedList/OrderedList.js +71 -0
  18. package/lib/OrderedList/OrderedListBase.js +47 -0
  19. package/lib/OrderedList/index.js +10 -0
  20. package/lib/index.js +16 -0
  21. package/lib/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +56 -0
  22. package/lib/utils/ssr-media-query/create-stylesheet/index.android.js +10 -0
  23. package/lib/utils/ssr-media-query/create-stylesheet/index.ios.js +10 -0
  24. package/lib/utils/ssr-media-query/create-stylesheet/index.js +44 -0
  25. package/lib/utils/ssr-media-query/utils/inject.js +13 -0
  26. package/lib-module/Autocomplete/Autocomplete.js +3 -13
  27. package/lib-module/Card/Card.js +71 -8
  28. package/lib-module/Card/PressableCardBase.js +2 -0
  29. package/lib-module/ColourToggle/ColourBubble.js +125 -0
  30. package/lib-module/ColourToggle/ColourToggle.js +92 -0
  31. package/lib-module/ColourToggle/index.js +2 -0
  32. package/lib-module/FlexGrid/Col/Col.js +51 -65
  33. package/lib-module/FlexGrid/FlexGrid.js +38 -41
  34. package/lib-module/FlexGrid/Row/Row.js +44 -45
  35. package/lib-module/Icon/IconText.js +9 -2
  36. package/lib-module/Link/LinkBase.js +10 -3
  37. package/lib-module/Modal/ModalContent.js +4 -6
  38. package/lib-module/OrderedList/Item.js +171 -0
  39. package/lib-module/OrderedList/ItemBase.js +37 -0
  40. package/lib-module/OrderedList/OrderedList.js +61 -0
  41. package/lib-module/OrderedList/OrderedListBase.js +36 -0
  42. package/lib-module/OrderedList/index.js +2 -0
  43. package/lib-module/index.js +2 -0
  44. package/lib-module/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +48 -0
  45. package/lib-module/utils/ssr-media-query/create-stylesheet/index.android.js +2 -0
  46. package/lib-module/utils/ssr-media-query/create-stylesheet/index.ios.js +2 -0
  47. package/lib-module/utils/ssr-media-query/create-stylesheet/index.js +36 -0
  48. package/lib-module/utils/ssr-media-query/utils/inject.js +13 -0
  49. package/package.json +2 -2
  50. package/src/Autocomplete/Autocomplete.jsx +14 -21
  51. package/src/Card/Card.jsx +73 -11
  52. package/src/Card/PressableCardBase.jsx +2 -0
  53. package/src/ColourToggle/ColourBubble.jsx +111 -0
  54. package/src/ColourToggle/ColourToggle.jsx +83 -0
  55. package/src/ColourToggle/index.js +3 -0
  56. package/src/FlexGrid/Col/Col.jsx +48 -80
  57. package/src/FlexGrid/FlexGrid.jsx +36 -44
  58. package/src/FlexGrid/Row/Row.jsx +38 -56
  59. package/src/Icon/IconText.jsx +11 -1
  60. package/src/Link/ChevronLink.jsx +1 -0
  61. package/src/Link/LinkBase.jsx +16 -6
  62. package/src/Modal/ModalContent.jsx +4 -6
  63. package/src/OrderedList/Item.jsx +152 -0
  64. package/src/OrderedList/ItemBase.jsx +31 -0
  65. package/src/OrderedList/OrderedList.jsx +61 -0
  66. package/src/OrderedList/OrderedListBase.jsx +33 -0
  67. package/src/OrderedList/index.js +3 -0
  68. package/src/index.js +2 -0
  69. package/src/utils/ssr-media-query/create-stylesheet/create-stylesheet-mobile.js +41 -0
  70. package/src/utils/ssr-media-query/create-stylesheet/index.android.js +3 -0
  71. package/src/utils/ssr-media-query/create-stylesheet/index.ios.js +3 -0
  72. package/src/utils/ssr-media-query/create-stylesheet/index.js +33 -0
  73. package/src/utils/ssr-media-query/utils/inject.js +13 -0
  74. package/types/Badge.d.ts +28 -0
  75. package/types/Box.d.ts +52 -0
  76. package/types/ChevronLink.d.ts +47 -0
  77. package/types/Common.d.ts +106 -0
  78. package/types/Divider.d.ts +19 -0
  79. package/types/ExpandCollapse.d.ts +65 -0
  80. package/types/HorizontalScrollButton.d.ts +16 -0
  81. package/types/Icon.d.ts +21 -0
  82. package/types/Link.d.ts +48 -0
  83. package/types/List.d.ts +48 -0
  84. package/types/Search.d.ts +38 -0
  85. package/types/Select.d.ts +57 -0
  86. package/types/Spacer.d.ts +5 -0
  87. package/types/StackView.d.ts +28 -0
  88. package/types/Tabs.d.ts +46 -0
  89. package/types/TextButton.d.ts +11 -0
  90. package/types/ToggleSwitch.d.ts +54 -0
  91. package/types/ToolTip.d.ts +40 -0
  92. package/types/Typography.d.ts +39 -0
  93. package/types/index.d.ts +62 -0
  94. package/lib/utils/ssr-media-query/create-stylesheet.js +0 -76
  95. package/lib-module/utils/ssr-media-query/create-stylesheet.js +0 -68
  96. package/src/utils/ssr-media-query/create-stylesheet.js +0 -61
@@ -1,12 +1,10 @@
1
1
  import React, { forwardRef, useContext } from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { Platform, StyleSheet } from 'react-native'
4
- import { viewports } from '@telus-uds/system-constants'
3
+ import { Platform } from 'react-native'
5
4
 
6
5
  import GutterContext from '../providers/GutterContext'
7
- import { useViewport } from '../../ViewportProvider'
8
6
  import applyInheritance from '../helpers'
9
- import { responsiveProps, BaseView } from '../../utils'
7
+ import { responsiveProps, BaseView, StyleSheet, createMediaQueryStyles } from '../../utils'
10
8
 
11
9
  const Col = forwardRef(
12
10
  (
@@ -29,8 +27,6 @@ const Col = forwardRef(
29
27
  ref
30
28
  ) => {
31
29
  const gutter = useContext(GutterContext)
32
- const viewPort = useViewport()
33
-
34
30
  const hiddenLevels = applyInheritance([xs, sm, md, lg, xl])
35
31
 
36
32
  const getHorizontalAlignLevel = () => {
@@ -84,65 +80,11 @@ const Col = forwardRef(
84
80
  return {}
85
81
  }
86
82
 
87
- const sizeStyles = (sizes) => {
88
- const currViewport = Object.keys(sizes).find((key) => key.startsWith(viewPort))
89
- const currSize = sizes[currViewport]
90
- return {
91
- ...calculateWidth(currSize)
92
- }
93
- }
94
-
95
- const offsetStyles = (offsets) => {
96
- const currViewport = Object.keys(offsets).find((key) => key.startsWith(viewPort))
97
- const currOffset = offsets[currViewport]
98
- return {
99
- ...calculateOffset(currOffset)
100
- }
101
- }
102
-
103
- const gutterPadding = {
104
- paddingLeft: gutter ? 16 : 0,
105
- paddingRight: gutter ? 16 : 0
106
- }
107
-
108
- let hidingStyles = {}
109
-
110
83
  // TODO: consider setting this to always 'flex' in a major release.
111
84
  // `display: block` is invalid in native apps.
112
85
  // See https://telusdigital.atlassian.net/browse/UDS1-92
113
86
  const shown = !flex && Platform.OS === 'web' ? 'block' : 'flex'
114
87
 
115
- if (viewPort === viewports.xs) {
116
- hidingStyles = {
117
- display: hiddenLevels[0] === 0 ? 'none' : shown,
118
- textAlign: horizontalAlignLevel[0]
119
- }
120
- }
121
- if (viewPort === viewports.sm) {
122
- hidingStyles = {
123
- display: hiddenLevels[1] === 0 ? 'none' : shown,
124
- textAlign: horizontalAlignLevel[1]
125
- }
126
- }
127
- if (viewPort === viewports.md) {
128
- hidingStyles = {
129
- display: hiddenLevels[2] === 0 ? 'none' : shown,
130
- textAlign: horizontalAlignLevel[2]
131
- }
132
- }
133
- if (viewPort === viewports.lg) {
134
- hidingStyles = {
135
- display: hiddenLevels[3] === 0 ? 'none' : shown,
136
- textAlign: horizontalAlignLevel[3]
137
- }
138
- }
139
- if (viewPort === viewports.xl) {
140
- hidingStyles = {
141
- display: hiddenLevels[4] === 0 ? 'none' : shown,
142
- textAlign: horizontalAlignLevel[4]
143
- }
144
- }
145
-
146
88
  const sizesArray = [xs, sm, md, lg, xl]
147
89
  const offSetsArray = [xsOffset, smOffset, mdOffset, lgOffset, xlOffset]
148
90
  const sizesWithIheritance = applyInheritance(sizesArray)
@@ -161,18 +103,53 @@ const Col = forwardRef(
161
103
  lg: offsetsWithIheritance[3],
162
104
  xl: offsetsWithIheritance[4]
163
105
  }
106
+
107
+ const mediaQueryStyles = createMediaQueryStyles({
108
+ xs: {
109
+ display: hiddenLevels[0] === 0 ? 'none' : shown,
110
+ textAlign: horizontalAlignLevel[0],
111
+ ...calculateWidth(sizes.xs),
112
+ ...calculateOffset(offsets.xs)
113
+ },
114
+ sm: {
115
+ display: hiddenLevels[1] === 0 ? 'none' : shown,
116
+ textAlign: horizontalAlignLevel[1],
117
+ ...calculateWidth(sizes.sm),
118
+ ...calculateOffset(offsets.sm)
119
+ },
120
+ md: {
121
+ display: hiddenLevels[2] === 0 ? 'none' : shown,
122
+ textAlign: horizontalAlignLevel[2],
123
+ ...calculateWidth(sizes.md),
124
+ ...calculateOffset(offsets.md)
125
+ },
126
+ lg: {
127
+ display: hiddenLevels[3] === 0 ? 'none' : shown,
128
+ textAlign: horizontalAlignLevel[3],
129
+ ...calculateWidth(sizes.lg),
130
+ ...calculateOffset(offsets.lg)
131
+ },
132
+ xl: {
133
+ display: hiddenLevels[4] === 0 ? 'none' : shown,
134
+ textAlign: horizontalAlignLevel[4],
135
+ ...calculateWidth(sizes.xl),
136
+ ...calculateOffset(offsets.xl)
137
+ }
138
+ })
139
+
140
+ const { ids, styles } = StyleSheet.create({
141
+ col: {
142
+ flexGrow: 1,
143
+ flexShrink: 0,
144
+ flexBasis: 'auto',
145
+ maxWidth: '100%',
146
+ paddingLeft: gutter ? 16 : 0,
147
+ paddingRight: gutter ? 16 : 0,
148
+ ...mediaQueryStyles
149
+ }
150
+ })
164
151
  return (
165
- <BaseView
166
- ref={ref}
167
- {...viewProps}
168
- style={[
169
- styles.col,
170
- gutterPadding,
171
- offsetStyles(offsets),
172
- sizeStyles(sizes),
173
- { ...hidingStyles }
174
- ]}
175
- >
152
+ <BaseView ref={ref} {...viewProps} style={[styles.col]} dataSet={{ media: ids.col }}>
176
153
  {children}
177
154
  </BaseView>
178
155
  )
@@ -180,15 +157,6 @@ const Col = forwardRef(
180
157
  )
181
158
  Col.displayName = 'Col'
182
159
 
183
- const styles = StyleSheet.create({
184
- col: {
185
- flexGrow: 1,
186
- flexShrink: 0,
187
- flexBasis: 'auto',
188
- maxWidth: '100%'
189
- }
190
- })
191
-
192
160
  /*
193
161
  * We're disabling default props since passing undefined props to
194
162
  * the react-flexbox-grid component sets up blank classes that may cause
@@ -1,6 +1,6 @@
1
1
  import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { StyleSheet } from 'react-native'
3
+
4
4
  import { viewports } from '@telus-uds/system-constants'
5
5
  import {
6
6
  a11yProps,
@@ -8,12 +8,12 @@ import {
8
8
  getA11yPropsFromHtmlTag,
9
9
  layoutTags,
10
10
  selectSystemProps,
11
- BaseView
11
+ BaseView,
12
+ StyleSheet,
13
+ createMediaQueryStyles
12
14
  } from '../utils'
13
-
14
15
  import Row from './Row'
15
16
  import Col from './Col'
16
- import { useViewport } from '../ViewportProvider'
17
17
  import GutterContext from './providers/GutterContext'
18
18
  import applyInheritance from './helpers'
19
19
 
@@ -41,33 +41,38 @@ const FlexGrid = forwardRef(
41
41
  },
42
42
  ref
43
43
  ) => {
44
- const viewPort = useViewport()
45
44
  const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse])
46
- const marginVertical = 0
47
- const marginHorizontal = outsideGutter ? 'auto' : -16
48
- const width = outsideGutter ? '100%' : 'auto'
49
- let flexDirection
50
- let maxWidth
51
- if (viewPort === viewports.xs) {
52
- // no maxWidth for xs
53
- flexDirection = reverseLevel[0] ? 'column-reverse' : 'column'
54
- }
55
- if (viewPort === viewports.sm) {
56
- maxWidth = limitWidth && viewports.map.get(viewports.sm)
57
- flexDirection = reverseLevel[1] ? 'column-reverse' : 'column'
58
- }
59
- if (viewPort === viewports.md) {
60
- maxWidth = limitWidth && viewports.map.get(viewports.md)
61
- flexDirection = reverseLevel[2] ? 'column-reverse' : 'column'
62
- }
63
- if (viewPort === viewports.lg) {
64
- maxWidth = limitWidth && viewports.map.get(viewports.lg)
65
- flexDirection = reverseLevel[3] ? 'column-reverse' : 'column'
66
- }
67
- if (viewPort === viewports.xl) {
68
- maxWidth = limitWidth && viewports.map.get(viewports.xl)
69
- flexDirection = reverseLevel[4] ? 'column-reverse' : 'column'
70
- }
45
+ const mediaQueryStyles = createMediaQueryStyles({
46
+ xs: {
47
+ flexDirection: reverseLevel[0] ? 'column-reverse' : 'column'
48
+ },
49
+ sm: {
50
+ maxWidth: limitWidth && viewports.map.get('sm'),
51
+ flexDirection: reverseLevel[1] ? 'column-reverse' : 'column'
52
+ },
53
+ md: {
54
+ maxWidth: limitWidth && viewports.map.get('md'),
55
+ flexDirection: reverseLevel[2] ? 'column-reverse' : 'column'
56
+ },
57
+ lg: {
58
+ maxWidth: limitWidth && viewports.map.get('lg'),
59
+ flexDirection: reverseLevel[3] ? 'column-reverse' : 'column'
60
+ },
61
+ xl: {
62
+ maxWidth: limitWidth && viewports.map.get('xl'),
63
+ flexDirection: reverseLevel[4] ? 'column-reverse' : 'column'
64
+ }
65
+ })
66
+
67
+ const { ids, styles } = StyleSheet.create({
68
+ flexgrid: {
69
+ flexWrap: 'wrap',
70
+ width: outsideGutter ? '100%' : 'auto',
71
+ marginVertical: 0,
72
+ marginHorizontal: outsideGutter ? 'auto' : -16,
73
+ ...mediaQueryStyles
74
+ }
75
+ })
71
76
 
72
77
  const props = {
73
78
  accessibilityRole,
@@ -77,14 +82,7 @@ const FlexGrid = forwardRef(
77
82
 
78
83
  return (
79
84
  <GutterContext.Provider value={gutter}>
80
- <BaseView
81
- ref={ref}
82
- {...props}
83
- style={[
84
- styles.grid,
85
- { marginHorizontal, marginVertical, width, flexDirection, maxWidth }
86
- ]}
87
- >
85
+ <BaseView ref={ref} {...props} style={[styles.flexgrid]} dataSet={{ media: ids.flexgrid }}>
88
86
  {children}
89
87
  </BaseView>
90
88
  </GutterContext.Provider>
@@ -93,12 +91,6 @@ const FlexGrid = forwardRef(
93
91
  )
94
92
  FlexGrid.displayName = 'FlexGrid'
95
93
 
96
- const styles = StyleSheet.create({
97
- grid: {
98
- flexWrap: 'wrap'
99
- }
100
- })
101
-
102
94
  FlexGrid.propTypes = {
103
95
  ...selectedSystemPropTypes,
104
96
  /**
@@ -1,11 +1,8 @@
1
1
  import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import { StyleSheet } from 'react-native'
4
- import { viewports } from '@telus-uds/system-constants'
5
3
 
6
- import { useViewport } from '../../ViewportProvider'
7
4
  import applyInheritance from '../helpers'
8
- import { BaseView } from '../../utils'
5
+ import { BaseView, StyleSheet, createMediaQueryStyles } from '../../utils'
9
6
 
10
7
  const horizontalAlignStyles = (horizontalAlign) => {
11
8
  switch (horizontalAlign) {
@@ -69,48 +66,45 @@ const Row = forwardRef(
69
66
  },
70
67
  ref
71
68
  ) => {
72
- const viewPort = useViewport()
73
69
  const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse])
74
-
75
- let flexDirection = ''
76
- let flexWrap = ''
77
-
78
- if (viewPort === viewports.xs) {
79
- flexDirection = reverseLevel[0] ? 'row-reverse' : 'row'
80
- flexWrap = reverseLevel[0] ? 'wrap-reverse' : 'wrap'
81
- }
82
- if (viewPort === viewports.sm) {
83
- flexDirection = reverseLevel[1] ? 'row-reverse' : 'row'
84
- flexWrap = reverseLevel[1] ? 'wrap-reverse' : 'wrap'
85
- }
86
- if (viewPort === viewports.md) {
87
- flexDirection = reverseLevel[2] ? 'row-reverse' : 'row'
88
- flexWrap = reverseLevel[2] ? 'wrap-reverse' : 'wrap'
89
- }
90
- if (viewPort === viewports.lg) {
91
- flexDirection = reverseLevel[3] ? 'row-reverse' : 'row'
92
- flexWrap = reverseLevel[3] ? 'wrap-reverse' : 'wrap'
93
- }
94
- if (viewPort === viewports.xl) {
95
- flexDirection = reverseLevel[4] ? 'row-reverse' : 'row'
96
- flexWrap = reverseLevel[4] ? 'wrap-reverse' : 'wrap'
97
- }
98
-
70
+ const mediaQueryStyles = createMediaQueryStyles({
71
+ xs: {
72
+ flexDirection: reverseLevel[0] ? 'row-reverse' : 'row',
73
+ flexWrap: reverseLevel[0] ? 'wrap-reverse' : 'wrap'
74
+ },
75
+ sm: {
76
+ flexDirection: reverseLevel[1] ? 'row-reverse' : 'row',
77
+ flexWrap: reverseLevel[1] ? 'wrap-reverse' : 'wrap'
78
+ },
79
+ md: {
80
+ flexDirection: reverseLevel[2] ? 'row-reverse' : 'row',
81
+ flexWrap: reverseLevel[2] ? 'wrap-reverse' : 'wrap'
82
+ },
83
+ lg: {
84
+ flexDirection: reverseLevel[3] ? 'row-reverse' : 'row',
85
+ flexWrap: reverseLevel[3] ? 'wrap-reverse' : 'wrap'
86
+ },
87
+ xl: {
88
+ flexDirection: reverseLevel[4] ? 'row-reverse' : 'row',
89
+ flexWrap: reverseLevel[4] ? 'wrap-reverse' : 'wrap'
90
+ }
91
+ })
92
+ const { ids, styles } = StyleSheet.create({
93
+ row: {
94
+ width: '100%',
95
+ marginVertical: 0,
96
+ marginHorizontal: 'auto',
97
+ flexGrow: 0,
98
+ flexShrink: 1,
99
+ flexBasis: 'auto',
100
+ ...horizontalAlignStyles(horizontalAlign),
101
+ ...verticalAlignStyles(verticalAlign),
102
+ ...distributeStyles(distribute),
103
+ ...mediaQueryStyles
104
+ }
105
+ })
99
106
  return (
100
- <BaseView
101
- ref={ref}
102
- {...rest}
103
- style={[
104
- styles.row,
105
- {
106
- flexDirection,
107
- flexWrap,
108
- ...horizontalAlignStyles(horizontalAlign),
109
- ...verticalAlignStyles(verticalAlign),
110
- ...distributeStyles(distribute)
111
- }
112
- ]}
113
- >
107
+ <BaseView ref={ref} {...rest} style={[styles.row]} dataSet={{ media: ids.row }}>
114
108
  {children}
115
109
  </BaseView>
116
110
  )
@@ -118,18 +112,6 @@ const Row = forwardRef(
118
112
  )
119
113
  Row.displayName = 'Row'
120
114
 
121
- const styles = StyleSheet.create({
122
- row: {
123
- width: '100%',
124
- marginVertical: 0,
125
- marginHorizontal: 'auto',
126
- flexGrow: 0,
127
- flexShrink: 1,
128
- flexBasis: 'auto',
129
- flexDirection: 'row'
130
- }
131
- })
132
-
133
115
  Row.propTypes = {
134
116
  /**
135
117
  * Align columns horizontally within their row.
@@ -23,12 +23,22 @@ const IconText = forwardRef(
23
23
  // Inline images on Android are always baseline-aligned which makes them look misaligned - offset it.
24
24
  // See abandoned issue https://github.com/facebook/react-native/issues/6529
25
25
  const size = iconProps?.tokens?.size ?? 0
26
+ const valueTranslateY = iconProps?.tokens?.translateY
27
+ /**
28
+ * These calculations were carried out using a set of linear equations to calculate that the
29
+ * position of the icon "->"" is aligned to the first line of the tooltip text on IOS and Android.
30
+ * The issue was mainly on IOS, the translateY style didn't match with the old calculations.
31
+ */
32
+ const resultY = valueTranslateY ? Math.floor(-1 * (valueTranslateY - 4)) : 0
33
+
26
34
  const iconAdjustedAndriod = (
27
35
  <View style={{ transform: [{ translateY: size * 0.2 }] }}>{iconContent}</View>
28
36
  )
29
37
 
30
38
  const iconAdjustedIOS = (
31
- <View style={{ transform: [{ translateY: size * 0.01 }] }}>{iconContent}</View>
39
+ <View style={{ transform: [{ translateY: valueTranslateY ? resultY : size * 0.01 }] }}>
40
+ {iconContent}
41
+ </View>
32
42
  )
33
43
 
34
44
  const mobile = Platform.OS === 'android' ? iconAdjustedAndriod : iconAdjustedIOS
@@ -30,6 +30,7 @@ const ChevronLink = forwardRef(
30
30
  }
31
31
 
32
32
  const getTokens = useThemeTokensCallback('Link', applyChevronTokens, variant)
33
+
33
34
  return (
34
35
  <LinkBase
35
36
  {...otherlinkProps}
@@ -72,6 +72,7 @@ const selectDecorationStyles = ({ color, textLine, textLineStyle, alignSelf }) =
72
72
  textDecorationLine: textLine,
73
73
  textDecorationStyle: textLineStyle,
74
74
  alignSelf,
75
+
75
76
  ...Platform.select({
76
77
  web: {
77
78
  // TODO: https://github.com/telus/universal-design-system/issues/487
@@ -80,12 +81,21 @@ const selectDecorationStyles = ({ color, textLine, textLineStyle, alignSelf }) =
80
81
  })
81
82
  })
82
83
 
83
- const selectIconTokens = ({ color, iconSize, iconTranslateX, iconTranslateY }) => ({
84
- color,
85
- translateX: iconTranslateX,
86
- translateY: iconTranslateY,
87
- size: iconSize
88
- })
84
+ const selectIconTokens = ({ color, iconSize, blockFontSize, iconTranslateX }) => {
85
+ /**
86
+ * These calculations were carried out using a set of linear equations to calculate that the
87
+ * position of the icon "->"" is aligned to the first line of the tooltip text.
88
+ * The base equation is: X/4 + Y/4 - 4 - |X - Y| = Z
89
+ * where X = blockFontSize, Y = iconSize and Z = translateY
90
+ */
91
+ const translateY = blockFontSize / 4 + iconSize / 4 - 4 - Math.abs(iconSize - blockFontSize)
92
+ return {
93
+ color,
94
+ translateX: iconTranslateX,
95
+ translateY: translateY < 0 ? 0 : translateY,
96
+ size: iconSize
97
+ }
98
+ }
89
99
 
90
100
  /**
91
101
  * Renders a pressable text link, with optional icon. This is rendered as a block element
@@ -25,14 +25,15 @@ const ModalContent = ({
25
25
  children,
26
26
  onCancel
27
27
  }) => {
28
+ const viewport = useViewport()
28
29
  const { headingColor, cancelButtonColor, ...themeTokens } = useThemeTokens(
29
30
  'Modal',
30
31
  tokens,
31
- variant
32
+ variant,
33
+ { viewport }
32
34
  )
33
35
  const [scrollContainerHeight, setScrollContainerHeight] = useState(0)
34
36
  const [scrollContentHeight, setScrollContentHeight] = useState(0)
35
- const viewport = useViewport()
36
37
 
37
38
  const handleContainerLayout = ({
38
39
  nativeEvent: {
@@ -128,7 +129,7 @@ const ModalContent = ({
128
129
  </Button>
129
130
  )}
130
131
  {hasCancelButton ? (
131
- <View style={styles.styledTextButtonContainer}>
132
+ <View>
132
133
  <CancelButton tokens={{ color: cancelButtonColor }} onPress={onCancel}>
133
134
  {cancelButtonText}
134
135
  </CancelButton>
@@ -145,9 +146,6 @@ const styles = StyleSheet.create({
145
146
  flex: 1,
146
147
  flexDirection: 'column',
147
148
  minHeight: Platform.OS === 'web' ? '100%' : 'auto'
148
- },
149
- styledTextButtonContainer: {
150
- flex: 1
151
149
  }
152
150
  })
153
151
 
@@ -0,0 +1,152 @@
1
+ import React, { forwardRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { View, StyleSheet } from 'react-native'
4
+
5
+ import {
6
+ getTokensPropType,
7
+ htmlAttrs,
8
+ selectSystemProps,
9
+ variantProp,
10
+ viewProps,
11
+ wrapStringsInText
12
+ } from '../utils'
13
+ import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider'
14
+ import StackView from '../StackView'
15
+ import Typography from '../Typography'
16
+ import ItemBase from './ItemBase'
17
+
18
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs, viewProps])
19
+
20
+ const selectItemTextStyles = (
21
+ { itemFontHeight, itemFontSize, itemLineHeight, itemFontName, itemColor },
22
+ themeOptions
23
+ ) =>
24
+ applyTextStyles({
25
+ fontWeight: itemFontHeight,
26
+ fontSize: itemFontSize,
27
+ fontName: itemFontName,
28
+ color: itemColor,
29
+ themeOptions,
30
+ lineHeight: itemLineHeight
31
+ })
32
+
33
+ const selectItemCounterStyles = ({
34
+ itemBulletContainerWidth,
35
+ itemBulletContainerAlign,
36
+ itemFontWeight,
37
+ itemFontSize,
38
+ itemFontName,
39
+ itemLineHeight,
40
+ themeOptions,
41
+ listGutter,
42
+ itemColor
43
+ }) => ({
44
+ color: itemColor,
45
+ width: itemBulletContainerWidth,
46
+ paddingRight: listGutter,
47
+ textAlign: itemBulletContainerAlign,
48
+ ...applyTextStyles({
49
+ fontWeight: itemFontWeight,
50
+ fontSize: itemFontSize,
51
+ fontName: itemFontName,
52
+ themeOptions
53
+ }),
54
+ lineHeight: itemLineHeight * itemFontSize
55
+ })
56
+
57
+ const selectItemContentStyles = ({ interItemMargin, ...themeTokens }, isLastChild) => ({
58
+ ...themeTokens,
59
+ marginBottom: !isLastChild ? interItemMargin : 0
60
+ })
61
+
62
+ const Item = forwardRef(
63
+ ({ children, index, isLastChild, title, tokens, variant, ...rest }, ref) => {
64
+ const themeTokens = useThemeTokens('OrderedList', tokens, variant)
65
+ const headingTokens = title && {
66
+ lineHeight: themeTokens.itemLineHeight,
67
+ fontSize: themeTokens.itemFontSize,
68
+ color: themeTokens.itemColor,
69
+ fontName: themeTokens.headerFontName,
70
+ fontWeight: themeTokens.headerFontWeight
71
+ }
72
+
73
+ const { themeOptions } = useTheme()
74
+ const itemContent = wrapStringsInText(children, {
75
+ style: selectItemTextStyles(themeTokens, themeOptions)
76
+ })
77
+ const itemCounter = wrapStringsInText(`${index}.`, {
78
+ style: selectItemTextStyles(themeTokens, themeOptions)
79
+ })
80
+
81
+ return (
82
+ <ItemBase
83
+ ref={ref}
84
+ style={{ ...staticStyles.container, ...themeTokens }}
85
+ {...selectProps(rest)}
86
+ >
87
+ <View style={[staticStyles.itemCounter, selectItemCounterStyles(themeTokens)]}>
88
+ {itemCounter}
89
+ </View>
90
+ <View style={staticStyles.itemContent}>
91
+ {title ? (
92
+ <StackView tokens={{ flexShrink: 1 }} space={0}>
93
+ <Typography variant={{ size: 'h4' }} tokens={headingTokens}>
94
+ {title}
95
+ </Typography>
96
+ <View style={selectItemContentStyles(themeTokens, isLastChild)}>{itemContent}</View>
97
+ </StackView>
98
+ ) : (
99
+ <View style={selectItemContentStyles(themeTokens, isLastChild)}>{itemContent}</View>
100
+ )}
101
+ </View>
102
+ </ItemBase>
103
+ )
104
+ }
105
+ )
106
+
107
+ Item.propTypes = {
108
+ ...selectedSystemPropTypes,
109
+ /**
110
+ * Item content
111
+ */
112
+ children: PropTypes.node.isRequired,
113
+ /**
114
+ * Item index
115
+ */
116
+ index: PropTypes.number,
117
+ /**
118
+ * If true, the item is the last one on the list
119
+ */
120
+ isLastChild: PropTypes.bool,
121
+ /**
122
+ * Defines the title of the `OrderedList.Item`
123
+ */
124
+ title: PropTypes.string,
125
+ /**
126
+ * Item tokens
127
+ */
128
+ tokens: getTokensPropType('List'),
129
+ /**
130
+ * Item variant
131
+ */
132
+ variant: variantProp.propType
133
+ }
134
+
135
+ Item.displayName = 'OrderedListItem'
136
+
137
+ Item.defaultProps = { title: undefined, tokens: {} }
138
+
139
+ export default Item
140
+
141
+ const staticStyles = StyleSheet.create({
142
+ container: {
143
+ flexDirection: 'row'
144
+ },
145
+ itemCounter: {
146
+ flexWrap: 'wrap'
147
+ },
148
+ itemContent: {
149
+ flexDirection: 'column',
150
+ marginLeft: 8
151
+ }
152
+ })