@telus-uds/components-base 1.21.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 +18 -2
- package/component-docs.json +455 -1
- 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/index.js +9 -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/index.js +1 -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/index.js +1 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React, { forwardRef, Children, cloneElement } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { StackWrap } from '../StackView';
|
|
4
|
+
import { useThemeTokens } from '../ThemeProvider';
|
|
5
|
+
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'; // pass through and type relevant system props - add more sets for interactive components
|
|
6
|
+
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
9
|
+
|
|
10
|
+
const isQuickListItem = element => {
|
|
11
|
+
var _element$type, _element$type2;
|
|
12
|
+
|
|
13
|
+
const elementName = (element === null || element === void 0 ? void 0 : (_element$type = element.type) === null || _element$type === void 0 ? void 0 : _element$type.displayName) || (element === null || element === void 0 ? void 0 : (_element$type2 = element.type) === null || _element$type2 === void 0 ? void 0 : _element$type2.name);
|
|
14
|
+
return Boolean(elementName.match(/QuickLinksFeatureItem/));
|
|
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
|
+
|
|
21
|
+
|
|
22
|
+
const QuickLinksFeature = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
23
|
+
let {
|
|
24
|
+
tokens,
|
|
25
|
+
variant,
|
|
26
|
+
tag = 'ul',
|
|
27
|
+
children,
|
|
28
|
+
...rest
|
|
29
|
+
} = _ref;
|
|
30
|
+
const {
|
|
31
|
+
stackGap,
|
|
32
|
+
stackJustify,
|
|
33
|
+
stackSpace
|
|
34
|
+
} = useThemeTokens('QuickLinksFeature', tokens, variant);
|
|
35
|
+
const items = Children.map(children, child => {
|
|
36
|
+
if (isQuickListItem(child)) {
|
|
37
|
+
return /*#__PURE__*/cloneElement(child, child.props);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
});
|
|
42
|
+
return /*#__PURE__*/_jsx(StackWrap, {
|
|
43
|
+
space: stackSpace,
|
|
44
|
+
gap: stackGap,
|
|
45
|
+
tokens: {
|
|
46
|
+
justifyContent: stackJustify
|
|
47
|
+
},
|
|
48
|
+
tag: tag,
|
|
49
|
+
ref: ref,
|
|
50
|
+
...selectProps(rest),
|
|
51
|
+
children: items
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
QuickLinksFeature.displayName = 'QuickLinksFeature';
|
|
55
|
+
QuickLinksFeature.propTypes = { ...selectedSystemPropTypes,
|
|
56
|
+
tokens: getTokensPropType('QuickLinksFeature'),
|
|
57
|
+
variant: variantProp.propType,
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Default wrapper tag, by default it's "ul"
|
|
61
|
+
*/
|
|
62
|
+
tag: PropTypes.string,
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* QuickLinksFeature.Item component
|
|
66
|
+
*/
|
|
67
|
+
children: PropTypes.node
|
|
68
|
+
};
|
|
69
|
+
export default QuickLinksFeature;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { forwardRef, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Image from "react-native-web/dist/exports/Image";
|
|
4
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
5
|
+
import Text from "react-native-web/dist/exports/Text";
|
|
6
|
+
import View from "react-native-web/dist/exports/View";
|
|
7
|
+
import { getTokensPropType, variantProp, withLinkRouter, a11yProps, linkProps, selectSystemProps } from '../utils';
|
|
8
|
+
import { useViewport } from '../ViewportProvider';
|
|
9
|
+
import { useThemeTokensCallback } from '../ThemeProvider';
|
|
10
|
+
import { Link } from '../Link';
|
|
11
|
+
import { StackWrap } from '../StackView'; // pass through and type relevant system props - add more sets for interactive components
|
|
12
|
+
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps]);
|
|
16
|
+
|
|
17
|
+
const selectImageStyle = imageDimension => ({
|
|
18
|
+
width: imageDimension,
|
|
19
|
+
height: imageDimension,
|
|
20
|
+
...Platform.select({
|
|
21
|
+
// TODO: https://github.com/telus/universal-design-system/issues/487
|
|
22
|
+
web: {
|
|
23
|
+
transition: 'width 200ms, height 200ms'
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const selectContainerStyle = _ref => {
|
|
29
|
+
let {
|
|
30
|
+
contentMaxDimension,
|
|
31
|
+
textAlign
|
|
32
|
+
} = _ref;
|
|
33
|
+
return {
|
|
34
|
+
textAlign,
|
|
35
|
+
width: contentMaxDimension,
|
|
36
|
+
overflow: 'hidden'
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const selectImageContainerStyle = contentMaxDimension => ({
|
|
41
|
+
width: contentMaxDimension,
|
|
42
|
+
height: contentMaxDimension,
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
alignItems: 'center'
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Component export along with QuickLinksFeature to be used as children
|
|
48
|
+
*
|
|
49
|
+
* It will receive a image source and a accessibility label and will render a link accordingly with the theme tokens
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
const QuickLinksFeatureItem = /*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
54
|
+
let {
|
|
55
|
+
tokens,
|
|
56
|
+
variant,
|
|
57
|
+
children,
|
|
58
|
+
imageAccessibilityLabel,
|
|
59
|
+
imageSource,
|
|
60
|
+
...rest
|
|
61
|
+
} = _ref2;
|
|
62
|
+
const viewport = useViewport();
|
|
63
|
+
const getTokens = useThemeTokensCallback('QuickLinksFeatureItem', tokens, variant);
|
|
64
|
+
const [hover, setHover] = useState(false);
|
|
65
|
+
const {
|
|
66
|
+
contentDirection,
|
|
67
|
+
contentSpace,
|
|
68
|
+
contentAlignItems,
|
|
69
|
+
contentMaxDimension,
|
|
70
|
+
imageDimension,
|
|
71
|
+
textAlign
|
|
72
|
+
} = getTokens({
|
|
73
|
+
viewport,
|
|
74
|
+
hover
|
|
75
|
+
});
|
|
76
|
+
return /*#__PURE__*/_jsx(Link, {
|
|
77
|
+
ref: ref,
|
|
78
|
+
tokens: state => {
|
|
79
|
+
setHover(state.hover);
|
|
80
|
+
return getTokens(state);
|
|
81
|
+
},
|
|
82
|
+
...selectProps(rest),
|
|
83
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
84
|
+
style: selectContainerStyle({
|
|
85
|
+
contentMaxDimension,
|
|
86
|
+
textAlign
|
|
87
|
+
}),
|
|
88
|
+
children: /*#__PURE__*/_jsxs(StackWrap, {
|
|
89
|
+
direction: contentDirection,
|
|
90
|
+
space: contentSpace,
|
|
91
|
+
tokens: {
|
|
92
|
+
alignItems: contentAlignItems
|
|
93
|
+
},
|
|
94
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
95
|
+
style: selectImageContainerStyle(contentMaxDimension),
|
|
96
|
+
children: /*#__PURE__*/_jsx(Image, {
|
|
97
|
+
accessibilityIgnoresInvertColors: true,
|
|
98
|
+
imageAccessibilityLabel: imageAccessibilityLabel,
|
|
99
|
+
source: imageSource,
|
|
100
|
+
style: selectImageStyle(imageDimension)
|
|
101
|
+
})
|
|
102
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
103
|
+
children: children
|
|
104
|
+
})]
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
QuickLinksFeatureItem.displayName = 'QuickLinksFeatureItem';
|
|
110
|
+
QuickLinksFeatureItem.propTypes = { ...withLinkRouter.propTypes,
|
|
111
|
+
...selectedSystemPropTypes,
|
|
112
|
+
tokens: getTokensPropType('QuickLinksFeatureItem'),
|
|
113
|
+
variant: variantProp.propType,
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Text which will be rendered within the Link
|
|
117
|
+
*/
|
|
118
|
+
children: PropTypes.node.isRequired,
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Image accessibility label
|
|
122
|
+
*/
|
|
123
|
+
imageAccessibilityLabel: PropTypes.string.isRequired,
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Image node or Image url
|
|
127
|
+
*/
|
|
128
|
+
imageSource: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired
|
|
129
|
+
};
|
|
130
|
+
export default withLinkRouter(QuickLinksFeatureItem);
|
|
@@ -120,6 +120,8 @@ const RadioCardGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
|
120
120
|
feedback: feedback,
|
|
121
121
|
inactive: inactive || readOnly,
|
|
122
122
|
validation: validation,
|
|
123
|
+
showErrorBorder: true,
|
|
124
|
+
showIcon: true,
|
|
123
125
|
accessibilityRole: "radiogroup",
|
|
124
126
|
...selectProps(rest),
|
|
125
127
|
children: props => /*#__PURE__*/_jsx(StackContainer, {
|
package/lib-module/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';
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@gorhom/portal": "^1.0.14",
|
|
11
11
|
"@telus-uds/system-constants": "^1.2.0",
|
|
12
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
12
|
+
"@telus-uds/system-theme-tokens": "^2.9.0",
|
|
13
13
|
"airbnb-prop-types": "^2.16.0",
|
|
14
14
|
"lodash.debounce": "^4.0.8",
|
|
15
15
|
"lodash.merge": "^4.6.2",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"standard-engine": {
|
|
71
71
|
"skip": true
|
|
72
72
|
},
|
|
73
|
-
"version": "1.
|
|
73
|
+
"version": "1.22.0"
|
|
74
74
|
}
|
|
@@ -50,6 +50,8 @@ const ButtonGroup = forwardRef(
|
|
|
50
50
|
feedback,
|
|
51
51
|
name: inputGroupName,
|
|
52
52
|
copy,
|
|
53
|
+
iconPosition,
|
|
54
|
+
|
|
53
55
|
accessibilityRole = maxValues === 1
|
|
54
56
|
? 'radiogroup' // radiogroup is cross-platform; only web aria has generic groups
|
|
55
57
|
: Platform.select({ web: 'group', default: 'none' }),
|
|
@@ -123,6 +125,8 @@ const ButtonGroup = forwardRef(
|
|
|
123
125
|
toggleOneValue(id, event)
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
const iconProp = itemRest.icon || undefined
|
|
129
|
+
|
|
126
130
|
const itemA11y = {
|
|
127
131
|
accessibilityState: { checked: isSelected },
|
|
128
132
|
accessibilityRole: itemA11yRole,
|
|
@@ -141,10 +145,12 @@ const ButtonGroup = forwardRef(
|
|
|
141
145
|
tokens={getButtonTokens}
|
|
142
146
|
selected={isSelected}
|
|
143
147
|
inactive={inactive}
|
|
148
|
+
icon={iconProp}
|
|
144
149
|
{...selectItemProps({
|
|
145
150
|
...itemRest,
|
|
146
151
|
...itemA11y
|
|
147
152
|
})}
|
|
153
|
+
iconPosition={iconPosition}
|
|
148
154
|
>
|
|
149
155
|
{label}
|
|
150
156
|
</ButtonBase>
|
|
@@ -213,6 +219,10 @@ ButtonGroup.propTypes = {
|
|
|
213
219
|
* Changing the `initialValues` does not change the user's selections.
|
|
214
220
|
*/
|
|
215
221
|
initialValues: PropTypes.arrayOf(PropTypes.string),
|
|
222
|
+
/**
|
|
223
|
+
* Defines if the icon will be displayed on the right or left side of the label.
|
|
224
|
+
*/
|
|
225
|
+
iconPosition: PropTypes.oneOf(['left', 'right']),
|
|
216
226
|
/**
|
|
217
227
|
* Main text used to describe this group, used in Fieldset's Legend element.
|
|
218
228
|
*/
|
|
@@ -35,10 +35,11 @@ function selectContainerStyles({
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// TODO: use stack / spacer when available
|
|
38
|
-
function selectIconContainerStyles({ iconGap, iconPosition }) {
|
|
38
|
+
function selectIconContainerStyles({ iconGap, iconPaddingTop, iconPosition }) {
|
|
39
39
|
const paddingSide = iconPosition === 'right' ? 'paddingLeft' : 'paddingRight'
|
|
40
40
|
return {
|
|
41
|
-
[paddingSide]: iconGap
|
|
41
|
+
[paddingSide]: iconGap,
|
|
42
|
+
paddingTop: iconPaddingTop
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -56,8 +56,8 @@ const selectIconContainerStyles = ({ iconGap }) => ({
|
|
|
56
56
|
* All accessibility props set on this component will be applied to the outer container.
|
|
57
57
|
*/
|
|
58
58
|
const Feedback = forwardRef(
|
|
59
|
-
({ title, children, id, validation, tokens, variant, ...rest }, ref) => {
|
|
60
|
-
const themeTokens = useThemeTokens('Feedback', tokens, { ...variant, validation })
|
|
59
|
+
({ title, children, id, validation, tokens, variant, icon, ...rest }, ref) => {
|
|
60
|
+
const themeTokens = useThemeTokens('Feedback', tokens, { ...variant, validation, icon })
|
|
61
61
|
const { space } = themeTokens
|
|
62
62
|
|
|
63
63
|
const { icon: IconComponent } = themeTokens
|
|
@@ -1,5 +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
5
|
import Feedback from '../Feedback'
|
|
5
6
|
import { spacingProps } from '../utils'
|
|
@@ -7,7 +8,6 @@ import FieldsetContainer from './FieldsetContainer'
|
|
|
7
8
|
import { getStackedContent } from '../StackView'
|
|
8
9
|
import InputLabel from '../InputLabel'
|
|
9
10
|
import useInputSupports from '../InputSupports/useInputSupports'
|
|
10
|
-
import Legend from './Legend'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* An alternative to InputSupports for groups of input elements that, on web, are to be
|
|
@@ -23,6 +23,8 @@ const Fieldset = forwardRef(
|
|
|
23
23
|
feedback,
|
|
24
24
|
feedbackPosition = 'top',
|
|
25
25
|
validation,
|
|
26
|
+
showIcon = false,
|
|
27
|
+
showErrorBorder = false,
|
|
26
28
|
legend,
|
|
27
29
|
hint,
|
|
28
30
|
hintPosition,
|
|
@@ -43,19 +45,17 @@ const Fieldset = forwardRef(
|
|
|
43
45
|
})
|
|
44
46
|
|
|
45
47
|
const legendContent = legend && (
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/>
|
|
55
|
-
</Legend>
|
|
48
|
+
<InputLabel
|
|
49
|
+
copy={copy}
|
|
50
|
+
label={legend}
|
|
51
|
+
hint={hint}
|
|
52
|
+
hintPosition={hintPosition}
|
|
53
|
+
hintId={hintId}
|
|
54
|
+
tooltip={tooltip}
|
|
55
|
+
/>
|
|
56
56
|
)
|
|
57
57
|
const feedbackContent = feedback && (
|
|
58
|
-
<Feedback id={feedbackId} title={feedback} validation={validation} />
|
|
58
|
+
<Feedback id={feedbackId} title={feedback} validation={validation} icon={showIcon} />
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
// Some accessibility patterns depend on elements being direct children, e.g. fieldset -> legend,
|
|
@@ -68,6 +68,9 @@ const Fieldset = forwardRef(
|
|
|
68
68
|
? [legendContent, feedbackContent, childContent]
|
|
69
69
|
: [legendContent, childContent, feedbackContent]
|
|
70
70
|
const stackedContent = getStackedContent(orderedContent, { space, preserveFragments: true })
|
|
71
|
+
const borderStyle =
|
|
72
|
+
(validation === 'error' && showErrorBorder && staticStyles.errorBorder) ||
|
|
73
|
+
staticStyles.noBorder
|
|
71
74
|
|
|
72
75
|
return (
|
|
73
76
|
<FieldsetContainer
|
|
@@ -75,12 +78,28 @@ const Fieldset = forwardRef(
|
|
|
75
78
|
inactive={inactive}
|
|
76
79
|
accessibilityRole={accessibilityRole}
|
|
77
80
|
name={fieldsetName}
|
|
81
|
+
borderStyle={borderStyle}
|
|
82
|
+
showBorderStyle={showErrorBorder}
|
|
78
83
|
>
|
|
79
84
|
{stackedContent}
|
|
80
85
|
</FieldsetContainer>
|
|
81
86
|
)
|
|
82
87
|
}
|
|
83
88
|
)
|
|
89
|
+
const staticStyles = StyleSheet.create({
|
|
90
|
+
errorBorder: {
|
|
91
|
+
border: true,
|
|
92
|
+
borderWidth: 1,
|
|
93
|
+
borderColor: 'red',
|
|
94
|
+
borderRadius: 10,
|
|
95
|
+
padding: 8
|
|
96
|
+
},
|
|
97
|
+
noBorder: {
|
|
98
|
+
padding: 9,
|
|
99
|
+
border: 'unset'
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
|
|
84
103
|
Fieldset.displayName = 'Fieldset'
|
|
85
104
|
|
|
86
105
|
Fieldset.propTypes = {
|
|
@@ -136,7 +155,15 @@ Fieldset.propTypes = {
|
|
|
136
155
|
/**
|
|
137
156
|
* Use to visually mark an input as valid or invalid.
|
|
138
157
|
*/
|
|
139
|
-
validation: PropTypes.oneOf(['error', 'success'])
|
|
158
|
+
validation: PropTypes.oneOf(['error', 'success']),
|
|
159
|
+
/**
|
|
160
|
+
* Use to show error or success icon in the feedback
|
|
161
|
+
*/
|
|
162
|
+
showIcon: PropTypes.bool,
|
|
163
|
+
/**
|
|
164
|
+
* Use to show border in case of error for a group of components
|
|
165
|
+
*/
|
|
166
|
+
showErrorBorder: PropTypes.bool
|
|
140
167
|
}
|
|
141
168
|
|
|
142
169
|
export default Fieldset
|
|
@@ -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)
|
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'
|