@telus-uds/components-base 1.20.0 → 1.22.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.
- package/CHANGELOG.md +30 -2
- package/__tests17__/ThemeProvider/ThemeProvider.test.jsx +1 -0
- package/component-docs.json +461 -3
- package/lib/Button/ButtonGroup.js +9 -0
- package/lib/ExpandCollapse/Control.js +3 -1
- package/lib/Feedback/Feedback.js +3 -1
- package/lib/Fieldset/Fieldset.js +42 -13
- package/lib/Fieldset/FieldsetContainer.js +9 -3
- package/lib/QuickLinksFeature/QuickLinksFeature.js +91 -0
- package/lib/QuickLinksFeature/QuickLinksFeatureItem.js +157 -0
- package/lib/QuickLinksFeature/index.js +16 -0
- package/lib/RadioCard/RadioCardGroup.js +2 -0
- package/lib/ThemeProvider/ThemeProvider.js +21 -9
- package/lib/ThemeProvider/utils/styles.js +3 -1
- package/lib/index.js +18 -0
- package/lib-module/Button/ButtonGroup.js +9 -0
- package/lib-module/ExpandCollapse/Control.js +3 -1
- package/lib-module/Feedback/Feedback.js +3 -1
- package/lib-module/Fieldset/Fieldset.js +39 -12
- package/lib-module/Fieldset/FieldsetContainer.js +9 -3
- package/lib-module/QuickLinksFeature/QuickLinksFeature.js +69 -0
- package/lib-module/QuickLinksFeature/QuickLinksFeatureItem.js +130 -0
- package/lib-module/QuickLinksFeature/index.js +4 -0
- package/lib-module/RadioCard/RadioCardGroup.js +2 -0
- package/lib-module/ThemeProvider/ThemeProvider.js +21 -9
- package/lib-module/ThemeProvider/utils/styles.js +3 -1
- package/lib-module/index.js +2 -0
- package/package.json +2 -2
- package/src/Button/ButtonGroup.jsx +10 -0
- package/src/ExpandCollapse/Control.jsx +3 -2
- package/src/Feedback/Feedback.jsx +2 -2
- package/src/Fieldset/Fieldset.jsx +40 -13
- package/src/Fieldset/FieldsetContainer.jsx +29 -12
- package/src/QuickLinksFeature/QuickLinksFeature.jsx +65 -0
- package/src/QuickLinksFeature/QuickLinksFeatureItem.jsx +114 -0
- package/src/QuickLinksFeature/index.js +6 -0
- package/src/RadioCard/RadioCardGroup.jsx +2 -0
- package/src/ThemeProvider/ThemeProvider.jsx +19 -6
- package/src/ThemeProvider/utils/styles.js +3 -1
- package/src/index.js +2 -0
|
@@ -7,17 +7,32 @@ import cssReset from './cssReset'
|
|
|
7
7
|
* On Web, wraps children with a HTML `<fieldset>` and sets its attributes as necessary.
|
|
8
8
|
*/
|
|
9
9
|
const FieldsetContainer = forwardRef(
|
|
10
|
-
(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
10
|
+
(
|
|
11
|
+
{
|
|
12
|
+
children,
|
|
13
|
+
inactive,
|
|
14
|
+
accessibilityRole,
|
|
15
|
+
name: fieldsetName,
|
|
16
|
+
showBorderStyle = false,
|
|
17
|
+
borderStyle
|
|
18
|
+
},
|
|
19
|
+
ref
|
|
20
|
+
) => {
|
|
21
|
+
// If needs border for error design or reset the component style
|
|
22
|
+
const styleContainer = showBorderStyle ? borderStyle : cssReset
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<fieldset
|
|
26
|
+
ref={ref}
|
|
27
|
+
disabled={inactive}
|
|
28
|
+
style={styleContainer}
|
|
29
|
+
role={accessibilityRole}
|
|
30
|
+
name={fieldsetName}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</fieldset>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
21
36
|
)
|
|
22
37
|
FieldsetContainer.displayName = 'FieldsetContainer'
|
|
23
38
|
|
|
@@ -25,7 +40,9 @@ FieldsetContainer.propTypes = {
|
|
|
25
40
|
accessibilityRole: PropTypes.string,
|
|
26
41
|
children: PropTypes.node,
|
|
27
42
|
inactive: PropTypes.bool,
|
|
28
|
-
name: PropTypes.string
|
|
43
|
+
name: PropTypes.string,
|
|
44
|
+
showBorderStyle: PropTypes.bool,
|
|
45
|
+
borderStyle: PropTypes.object
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
export default FieldsetContainer
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React, { forwardRef, Children, cloneElement } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { StackWrap } from '../StackView'
|
|
4
|
+
|
|
5
|
+
import { useThemeTokens } from '../ThemeProvider'
|
|
6
|
+
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
7
|
+
|
|
8
|
+
// pass through and type relevant system props - add more sets for interactive components
|
|
9
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
10
|
+
|
|
11
|
+
const isQuickListItem = (element) => {
|
|
12
|
+
const elementName = element?.type?.displayName || element?.type?.name
|
|
13
|
+
return Boolean(elementName.match(/QuickLinksFeatureItem/))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* QuickLinksFeature renders a list of interactive items.
|
|
18
|
+
* - This is the base component that is used as a wrapper and accepts a List of `QuickLinksFeature.Item`
|
|
19
|
+
*/
|
|
20
|
+
const QuickLinksFeature = forwardRef(({ tokens, variant, tag = 'ul', children, ...rest }, ref) => {
|
|
21
|
+
const { stackGap, stackJustify, stackSpace } = useThemeTokens(
|
|
22
|
+
'QuickLinksFeature',
|
|
23
|
+
tokens,
|
|
24
|
+
variant
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
const items = Children.map(children, (child) => {
|
|
28
|
+
if (isQuickListItem(child)) {
|
|
29
|
+
return cloneElement(child, child.props)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return null
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<StackWrap
|
|
37
|
+
space={stackSpace}
|
|
38
|
+
gap={stackGap}
|
|
39
|
+
tokens={{ justifyContent: stackJustify }}
|
|
40
|
+
tag={tag}
|
|
41
|
+
ref={ref}
|
|
42
|
+
{...selectProps(rest)}
|
|
43
|
+
>
|
|
44
|
+
{items}
|
|
45
|
+
</StackWrap>
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
QuickLinksFeature.displayName = 'QuickLinksFeature'
|
|
50
|
+
|
|
51
|
+
QuickLinksFeature.propTypes = {
|
|
52
|
+
...selectedSystemPropTypes,
|
|
53
|
+
tokens: getTokensPropType('QuickLinksFeature'),
|
|
54
|
+
variant: variantProp.propType,
|
|
55
|
+
/**
|
|
56
|
+
* Default wrapper tag, by default it's "ul"
|
|
57
|
+
*/
|
|
58
|
+
tag: PropTypes.string,
|
|
59
|
+
/**
|
|
60
|
+
* QuickLinksFeature.Item component
|
|
61
|
+
*/
|
|
62
|
+
children: PropTypes.node
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default QuickLinksFeature
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React, { forwardRef, useState } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import { Image, Platform, Text, View } from 'react-native'
|
|
5
|
+
import {
|
|
6
|
+
getTokensPropType,
|
|
7
|
+
variantProp,
|
|
8
|
+
withLinkRouter,
|
|
9
|
+
a11yProps,
|
|
10
|
+
linkProps,
|
|
11
|
+
selectSystemProps
|
|
12
|
+
} from '../utils'
|
|
13
|
+
import { useViewport } from '../ViewportProvider'
|
|
14
|
+
import { useThemeTokensCallback } from '../ThemeProvider'
|
|
15
|
+
import { Link } from '../Link'
|
|
16
|
+
import { StackWrap } from '../StackView'
|
|
17
|
+
|
|
18
|
+
// pass through and type relevant system props - add more sets for interactive components
|
|
19
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps])
|
|
20
|
+
|
|
21
|
+
const selectImageStyle = (imageDimension) => ({
|
|
22
|
+
width: imageDimension,
|
|
23
|
+
height: imageDimension,
|
|
24
|
+
...Platform.select({
|
|
25
|
+
// TODO: https://github.com/telus/universal-design-system/issues/487
|
|
26
|
+
web: { transition: 'width 200ms, height 200ms' }
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const selectContainerStyle = ({ contentMaxDimension, textAlign }) => ({
|
|
31
|
+
textAlign,
|
|
32
|
+
width: contentMaxDimension,
|
|
33
|
+
overflow: 'hidden'
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const selectImageContainerStyle = (contentMaxDimension) => ({
|
|
37
|
+
width: contentMaxDimension,
|
|
38
|
+
height: contentMaxDimension,
|
|
39
|
+
justifyContent: 'center',
|
|
40
|
+
alignItems: 'center'
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Component export along with QuickLinksFeature to be used as children
|
|
45
|
+
*
|
|
46
|
+
* It will receive a image source and a accessibility label and will render a link accordingly with the theme tokens
|
|
47
|
+
*/
|
|
48
|
+
const QuickLinksFeatureItem = forwardRef(
|
|
49
|
+
({ tokens, variant, children, imageAccessibilityLabel, imageSource, ...rest }, ref) => {
|
|
50
|
+
const viewport = useViewport()
|
|
51
|
+
const getTokens = useThemeTokensCallback('QuickLinksFeatureItem', tokens, variant)
|
|
52
|
+
const [hover, setHover] = useState(false)
|
|
53
|
+
const {
|
|
54
|
+
contentDirection,
|
|
55
|
+
contentSpace,
|
|
56
|
+
contentAlignItems,
|
|
57
|
+
contentMaxDimension,
|
|
58
|
+
imageDimension,
|
|
59
|
+
textAlign
|
|
60
|
+
} = getTokens({ viewport, hover })
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Link
|
|
64
|
+
ref={ref}
|
|
65
|
+
tokens={(state) => {
|
|
66
|
+
setHover(state.hover)
|
|
67
|
+
return getTokens(state)
|
|
68
|
+
}}
|
|
69
|
+
{...selectProps(rest)}
|
|
70
|
+
>
|
|
71
|
+
<View style={selectContainerStyle({ contentMaxDimension, textAlign })}>
|
|
72
|
+
<StackWrap
|
|
73
|
+
direction={contentDirection}
|
|
74
|
+
space={contentSpace}
|
|
75
|
+
tokens={{ alignItems: contentAlignItems }}
|
|
76
|
+
>
|
|
77
|
+
<View style={selectImageContainerStyle(contentMaxDimension)}>
|
|
78
|
+
<Image
|
|
79
|
+
accessibilityIgnoresInvertColors
|
|
80
|
+
imageAccessibilityLabel={imageAccessibilityLabel}
|
|
81
|
+
source={imageSource}
|
|
82
|
+
style={selectImageStyle(imageDimension)}
|
|
83
|
+
/>
|
|
84
|
+
</View>
|
|
85
|
+
<Text>{children}</Text>
|
|
86
|
+
</StackWrap>
|
|
87
|
+
</View>
|
|
88
|
+
</Link>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
QuickLinksFeatureItem.displayName = 'QuickLinksFeatureItem'
|
|
94
|
+
|
|
95
|
+
QuickLinksFeatureItem.propTypes = {
|
|
96
|
+
...withLinkRouter.propTypes,
|
|
97
|
+
...selectedSystemPropTypes,
|
|
98
|
+
tokens: getTokensPropType('QuickLinksFeatureItem'),
|
|
99
|
+
variant: variantProp.propType,
|
|
100
|
+
/**
|
|
101
|
+
* Text which will be rendered within the Link
|
|
102
|
+
*/
|
|
103
|
+
children: PropTypes.node.isRequired,
|
|
104
|
+
/**
|
|
105
|
+
* Image accessibility label
|
|
106
|
+
*/
|
|
107
|
+
imageAccessibilityLabel: PropTypes.string.isRequired,
|
|
108
|
+
/**
|
|
109
|
+
* Image node or Image url
|
|
110
|
+
*/
|
|
111
|
+
imageSource: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export default withLinkRouter(QuickLinksFeatureItem)
|
|
@@ -8,15 +8,22 @@ export const uninitialisedError = new Error('Theme context used outside of Theme
|
|
|
8
8
|
export const ThemeContext = createContext(uninitialisedError)
|
|
9
9
|
export const ThemeSetterContext = createContext(uninitialisedError)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
// These options default to `true` in v1.x to match legacy defaults and avoid breaking changes.
|
|
12
|
+
// This should change in future major releases to become "opt-in" legacy support.
|
|
13
|
+
const defaultThemeOptions = {
|
|
14
14
|
// TODO: switch `forceAbsoluteFontSizing` to be false by default in the next major version
|
|
15
|
+
forceAbsoluteFontSizing: true,
|
|
15
16
|
// TODO: switch `forceZIndex` to be false by default in the next major version
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
forceZIndex: true,
|
|
18
|
+
// TODO: switch `enableHelmetSSR` to be false by default in the next major version
|
|
19
|
+
enableHelmetSSR: true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const ThemeProvider = ({ children, defaultTheme, themeOptions = {} }) => {
|
|
18
23
|
const [theme, setTheme] = useState(defaultTheme)
|
|
19
24
|
|
|
25
|
+
const appliedThemeOptions = { ...defaultThemeOptions, ...themeOptions }
|
|
26
|
+
|
|
20
27
|
// Validate the theme tokens version on every render.
|
|
21
28
|
// This will intentionally break the application when attempting to use an invalid theme.
|
|
22
29
|
// This will surface an incompatibility quickly rather than allowing the potential for strange bugs due to missing or incompatible tokens.
|
|
@@ -24,7 +31,9 @@ const ThemeProvider = ({
|
|
|
24
31
|
|
|
25
32
|
return (
|
|
26
33
|
<ThemeSetterContext.Provider value={setTheme}>
|
|
27
|
-
<ThemeContext.Provider value={{ ...theme, themeOptions }}>
|
|
34
|
+
<ThemeContext.Provider value={{ ...theme, themeOptions: appliedThemeOptions }}>
|
|
35
|
+
{children}
|
|
36
|
+
</ThemeContext.Provider>
|
|
28
37
|
</ThemeSetterContext.Provider>
|
|
29
38
|
)
|
|
30
39
|
}
|
|
@@ -46,10 +55,14 @@ ThemeProvider.propTypes = {
|
|
|
46
55
|
* such as Footnote and Notification to avoid content to stretch width more then the page's width
|
|
47
56
|
* - `forceZIndex`: available on web only, when set to false, sets zIndex on `View` to be `auto`
|
|
48
57
|
* and when true, sets zIndex to be `0` (the default from `react-native-web`)
|
|
58
|
+
* - `enableHelmetSSR`: on Web SSR, allows React Helmet to run during server-side rendering. This should be
|
|
59
|
+
* disabled unless a web app has been specifically configured to stop React Helmet accumulating
|
|
60
|
+
* instances (which may cause a memory leak). See React Helmet's docs: https://github.com/nfl/react-helmet
|
|
49
61
|
*/
|
|
50
62
|
themeOptions: PropTypes.shape({
|
|
51
63
|
forceAbsoluteFontSizing: PropTypes.bool,
|
|
52
64
|
forceZIndex: PropTypes.bool,
|
|
65
|
+
enableHelmetSSR: PropTypes.bool,
|
|
53
66
|
contentMaxWidth: responsiveProps.getTypeOptionallyByViewport(PropTypes.number)
|
|
54
67
|
})
|
|
55
68
|
}
|
|
@@ -45,7 +45,9 @@ export function applyTextStyles({
|
|
|
45
45
|
// Don't set undefined font families. May need some validation here that the font is available.
|
|
46
46
|
// Android doesn't recognise font weights natively so apply custom font weights via `fontFamily`.
|
|
47
47
|
styles.fontFamily = `${fontName}${fontWeight}${fontStyle}`
|
|
48
|
-
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (fontWeight) {
|
|
49
51
|
// If using system default font, apply the font weight directly.
|
|
50
52
|
// Font weight support in Android is limited to 'bold' or anything else === 'normal'.
|
|
51
53
|
styles.fontWeight = Platform.OS === 'android' && Number(fontWeight) > 400 ? 'bold' : fontWeight
|
package/src/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export { default as Notification } from './Notification'
|
|
|
26
26
|
export { default as Pagination } from './Pagination'
|
|
27
27
|
export { default as Progress } from './Progress'
|
|
28
28
|
export { default as QuickLinks } from './QuickLinks'
|
|
29
|
+
export { default as QuickLinksFeature } from './QuickLinksFeature'
|
|
29
30
|
export { default as Radio } from './Radio'
|
|
30
31
|
export * from './Radio'
|
|
31
32
|
export { default as RadioCard } from './RadioCard'
|
|
@@ -51,6 +52,7 @@ export { default as Typography } from './Typography'
|
|
|
51
52
|
|
|
52
53
|
export { default as A11yInfoProvider, useA11yInfo } from './A11yInfoProvider'
|
|
53
54
|
export { default as BaseProvider } from './BaseProvider'
|
|
55
|
+
export { useHydrationContext } from './BaseProvider/HydrationContext'
|
|
54
56
|
export { default as ViewportProvider, useViewport, ViewportContext } from './ViewportProvider'
|
|
55
57
|
export {
|
|
56
58
|
default as ThemeProvider,
|