@telus-uds/components-base 1.19.0 → 1.21.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 +34 -2
- package/__tests17__/ThemeProvider/ThemeProvider.test.jsx +3 -1
- package/component-docs.json +838 -125
- package/lib/BaseProvider/index.js +2 -1
- package/lib/Box/Box.js +14 -1
- package/lib/Button/ButtonDropdown.js +207 -0
- package/lib/Button/index.js +8 -0
- package/lib/Carousel/Carousel.js +2 -2
- package/lib/Carousel/CarouselItem/CarouselItem.js +7 -1
- package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +21 -4
- package/lib/FlexGrid/Col/Col.js +1 -3
- package/lib/FlexGrid/FlexGrid.js +3 -5
- package/lib/FlexGrid/Row/Row.js +3 -3
- package/lib/IconButton/IconButton.js +12 -4
- package/lib/MultiSelectFilter/MultiSelectFilter.js +276 -0
- package/lib/MultiSelectFilter/dictionary.js +19 -0
- package/lib/MultiSelectFilter/index.js +13 -0
- package/lib/Search/Search.js +4 -1
- package/lib/Select/Picker.native.js +16 -13
- package/lib/Select/Select.js +7 -1
- package/lib/Select/constants.js +15 -0
- package/lib/StepTracker/Step.js +2 -1
- package/lib/TextInput/TextInput.js +9 -2
- package/lib/TextInput/TextInputBase.js +52 -8
- package/lib/TextInput/dictionary.js +15 -0
- package/lib/ThemeProvider/ThemeProvider.js +24 -7
- package/lib/ThemeProvider/utils/styles.js +3 -1
- package/lib/index.js +18 -0
- package/lib/utils/BaseView/BaseView.js +64 -0
- package/lib/utils/BaseView/BaseView.native.js +16 -0
- package/lib/utils/BaseView/index.js +13 -0
- package/lib/utils/index.js +10 -1
- package/lib/utils/input.js +11 -3
- package/lib/utils/props/handlerProps.js +5 -0
- package/lib-module/BaseProvider/index.js +2 -1
- package/lib-module/Box/Box.js +14 -1
- package/lib-module/Button/ButtonDropdown.js +181 -0
- package/lib-module/Button/index.js +2 -1
- package/lib-module/Carousel/Carousel.js +2 -2
- package/lib-module/Carousel/CarouselItem/CarouselItem.js +8 -2
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +23 -6
- package/lib-module/FlexGrid/Col/Col.js +2 -3
- package/lib-module/FlexGrid/FlexGrid.js +2 -3
- package/lib-module/FlexGrid/Row/Row.js +2 -2
- package/lib-module/IconButton/IconButton.js +14 -4
- package/lib-module/MultiSelectFilter/MultiSelectFilter.js +248 -0
- package/lib-module/MultiSelectFilter/dictionary.js +12 -0
- package/lib-module/MultiSelectFilter/index.js +2 -0
- package/lib-module/Search/Search.js +4 -1
- package/lib-module/Select/Picker.native.js +15 -13
- package/lib-module/Select/Select.js +6 -1
- package/lib-module/Select/constants.js +5 -0
- package/lib-module/StepTracker/Step.js +2 -1
- package/lib-module/TextInput/TextInput.js +6 -0
- package/lib-module/TextInput/TextInputBase.js +52 -10
- package/lib-module/TextInput/dictionary.js +8 -0
- package/lib-module/ThemeProvider/ThemeProvider.js +24 -7
- package/lib-module/ThemeProvider/utils/styles.js +3 -1
- package/lib-module/index.js +2 -0
- package/lib-module/utils/BaseView/BaseView.js +43 -0
- package/lib-module/utils/BaseView/BaseView.native.js +6 -0
- package/lib-module/utils/BaseView/index.js +2 -0
- package/lib-module/utils/index.js +2 -1
- package/lib-module/utils/input.js +11 -3
- package/lib-module/utils/props/handlerProps.js +5 -0
- package/package.json +3 -3
- package/src/BaseProvider/index.jsx +4 -1
- package/src/Box/Box.jsx +14 -1
- package/src/Button/ButtonDropdown.jsx +179 -0
- package/src/Button/index.js +2 -1
- package/src/Carousel/Carousel.jsx +6 -3
- package/src/Carousel/CarouselItem/CarouselItem.jsx +9 -2
- package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +19 -5
- package/src/FlexGrid/Col/Col.jsx +4 -4
- package/src/FlexGrid/FlexGrid.jsx +11 -10
- package/src/FlexGrid/Row/Row.jsx +4 -3
- package/src/IconButton/IconButton.jsx +3 -1
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +227 -0
- package/src/MultiSelectFilter/dictionary.js +12 -0
- package/src/MultiSelectFilter/index.js +3 -0
- package/src/Search/Search.jsx +2 -1
- package/src/Select/Picker.native.jsx +29 -14
- package/src/Select/Select.jsx +7 -1
- package/src/Select/constants.js +5 -0
- package/src/StepTracker/Step.jsx +5 -1
- package/src/TextInput/TextInput.jsx +5 -0
- package/src/TextInput/TextInputBase.jsx +43 -8
- package/src/TextInput/dictionary.js +8 -0
- package/src/ThemeProvider/ThemeProvider.jsx +23 -6
- package/src/ThemeProvider/utils/styles.js +3 -1
- package/src/index.js +2 -0
- package/src/utils/BaseView/BaseView.jsx +38 -0
- package/src/utils/BaseView/BaseView.native.jsx +6 -0
- package/src/utils/BaseView/index.js +3 -0
- package/src/utils/index.js +1 -0
- package/src/utils/input.js +9 -4
- package/src/utils/props/handlerProps.js +4 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import NativeView from "react-native-web/dist/exports/View";
|
|
3
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import { useTheme } from '../../ThemeProvider';
|
|
6
|
+
/**
|
|
7
|
+
* Identical to React Native's View and supporting all the same props, but with:
|
|
8
|
+
* - a zIndex: 'auto' style added to prevent unexpectedly causing children to overlap other elements from other stacking contexts
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
const BaseView = /*#__PURE__*/forwardRef((_ref, ref) => {
|
|
13
|
+
let {
|
|
14
|
+
children,
|
|
15
|
+
style,
|
|
16
|
+
...rest
|
|
17
|
+
} = _ref;
|
|
18
|
+
const {
|
|
19
|
+
themeOptions
|
|
20
|
+
} = useTheme();
|
|
21
|
+
const styleProp = Array.isArray(style) ? [...style] : [style];
|
|
22
|
+
|
|
23
|
+
if (!themeOptions.forceZIndex) {
|
|
24
|
+
styleProp.unshift(styles.resetZIndex);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return /*#__PURE__*/_jsx(NativeView, { ...rest,
|
|
28
|
+
style: styleProp,
|
|
29
|
+
ref: ref,
|
|
30
|
+
children: children
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
BaseView.displayName = 'BaseView';
|
|
34
|
+
const styles = StyleSheet.create({
|
|
35
|
+
resetZIndex: {
|
|
36
|
+
zIndex: 'auto'
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
BaseView.propTypes = {
|
|
40
|
+
children: PropTypes.node,
|
|
41
|
+
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
|
|
42
|
+
};
|
|
43
|
+
export default BaseView;
|
|
@@ -15,4 +15,5 @@ export * from './useResponsiveProp';
|
|
|
15
15
|
export { default as useUniqueId } from './useUniqueId';
|
|
16
16
|
export { default as withLinkRouter } from './withLinkRouter';
|
|
17
17
|
export * from './ssr';
|
|
18
|
-
export { default as containUniqueFields } from './containUniqueFields';
|
|
18
|
+
export { default as containUniqueFields } from './containUniqueFields';
|
|
19
|
+
export { default as BaseView } from './BaseView';
|
|
@@ -77,6 +77,7 @@ export const useInputValue = function () {
|
|
|
77
77
|
const {
|
|
78
78
|
value,
|
|
79
79
|
initialValue,
|
|
80
|
+
inputRef,
|
|
80
81
|
onChange,
|
|
81
82
|
readOnly = false
|
|
82
83
|
} = props;
|
|
@@ -90,19 +91,26 @@ export const useInputValue = function () {
|
|
|
90
91
|
}); // Make current value accessible inside useCallback without rememoizing every time the value changes
|
|
91
92
|
|
|
92
93
|
valueRef.current.value = currentValue;
|
|
94
|
+
const isDirty = currentValue !== valueRef.current.initial;
|
|
93
95
|
const setValue = useCallback((arg, event) => {
|
|
94
96
|
if (readOnly) return;
|
|
95
97
|
const newValue = typeof arg === 'function' ? arg(valueRef.current.value) : arg;
|
|
96
|
-
|
|
98
|
+
|
|
99
|
+
if (!isControlled) {
|
|
100
|
+
setOwnValue(newValue);
|
|
101
|
+
if (inputRef !== null && inputRef !== void 0 && inputRef.current) inputRef.current.value = newValue !== null && newValue !== void 0 ? newValue : '';
|
|
102
|
+
} // Call onChange handler if there's something for it to handle (event or a changed value)
|
|
103
|
+
|
|
97
104
|
|
|
98
105
|
if (onChange && (event || valueRef.current.value !== newValue)) onChange(newValue, event);
|
|
99
|
-
}, [isControlled, onChange, readOnly]);
|
|
106
|
+
}, [inputRef, isControlled, onChange, readOnly]);
|
|
100
107
|
const resetValue = useCallback(event => setValue(valueRef.current.initial, event), [setValue]);
|
|
101
108
|
return {
|
|
102
109
|
currentValue,
|
|
103
110
|
setValue,
|
|
104
111
|
resetValue,
|
|
105
|
-
isControlled
|
|
112
|
+
isControlled,
|
|
113
|
+
isDirty
|
|
106
114
|
};
|
|
107
115
|
};
|
|
108
116
|
/**
|
package/package.json
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@gorhom/portal": "^1.0.14",
|
|
11
|
-
"@telus-uds/system-constants": "^1.
|
|
12
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
11
|
+
"@telus-uds/system-constants": "^1.2.0",
|
|
12
|
+
"@telus-uds/system-theme-tokens": "^2.8.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.21.0"
|
|
74
74
|
}
|
|
@@ -21,7 +21,10 @@ const BaseProvider = ({ defaultTheme, children, themeOptions }) => (
|
|
|
21
21
|
BaseProvider.propTypes = {
|
|
22
22
|
children: PropTypes.node.isRequired,
|
|
23
23
|
defaultTheme: ThemeProvider.propTypes?.defaultTheme,
|
|
24
|
-
themeOptions: PropTypes.shape({
|
|
24
|
+
themeOptions: PropTypes.shape({
|
|
25
|
+
forceAbsoluteFontSizing: PropTypes.bool,
|
|
26
|
+
forceZIndex: PropTypes.bool
|
|
27
|
+
})
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
export default BaseProvider
|
package/src/Box/Box.jsx
CHANGED
|
@@ -24,7 +24,20 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
const selectBoxStyles = (tokens) => {
|
|
27
|
-
|
|
27
|
+
let styles = { backgroundColor: tokens.backgroundColor }
|
|
28
|
+
if (tokens.gradient) {
|
|
29
|
+
const {
|
|
30
|
+
gradient: {
|
|
31
|
+
angle,
|
|
32
|
+
stops: [stopOne, stopTwo]
|
|
33
|
+
}
|
|
34
|
+
} = tokens
|
|
35
|
+
styles = {
|
|
36
|
+
...styles,
|
|
37
|
+
backgroundImage: `linear-gradient(${angle}deg, ${stopOne.color}, 75% , ${stopTwo.color})`
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
const paddings = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom']
|
|
29
42
|
// Only set on styles if token provided because we spread this object after the spacing scale values
|
|
30
43
|
paddings.forEach((side) => {
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { Platform, Text, View } from 'react-native'
|
|
4
|
+
import buttonPropTypes, { textAndA11yText } from './propTypes'
|
|
5
|
+
import ButtonBase from './ButtonBase'
|
|
6
|
+
import { useThemeTokensCallback } from '../ThemeProvider'
|
|
7
|
+
import {
|
|
8
|
+
a11yProps,
|
|
9
|
+
focusHandlerProps,
|
|
10
|
+
resolvePressableState,
|
|
11
|
+
selectTokens,
|
|
12
|
+
useInputValue
|
|
13
|
+
} from '../utils'
|
|
14
|
+
import Icon from '../Icon'
|
|
15
|
+
import { getStackedContent } from '../StackView'
|
|
16
|
+
import { getPressHandlersWithArgs } from '../utils/pressability'
|
|
17
|
+
|
|
18
|
+
const selectIconTokens = ({
|
|
19
|
+
icon,
|
|
20
|
+
iconPosition,
|
|
21
|
+
iconSpace,
|
|
22
|
+
iconSize,
|
|
23
|
+
iconColor,
|
|
24
|
+
iconBackground,
|
|
25
|
+
iconBorderRadius,
|
|
26
|
+
iconAlignSelf,
|
|
27
|
+
iconPadding,
|
|
28
|
+
iconTranslateX,
|
|
29
|
+
iconTranslateY
|
|
30
|
+
}) => ({
|
|
31
|
+
icon,
|
|
32
|
+
iconPosition,
|
|
33
|
+
iconSpace,
|
|
34
|
+
iconWrapperStyle: {
|
|
35
|
+
backgroundColor: iconBackground,
|
|
36
|
+
borderRadius: iconBorderRadius,
|
|
37
|
+
alignSelf: iconAlignSelf,
|
|
38
|
+
padding: iconPadding,
|
|
39
|
+
...Platform.select({
|
|
40
|
+
// TODO: https://github.com/telus/universal-design-system/issues/487
|
|
41
|
+
web: { transition: 'color 200ms, background 200ms' }
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
iconTokens: {
|
|
45
|
+
size: iconSize,
|
|
46
|
+
color: iconColor,
|
|
47
|
+
translateX: iconTranslateX,
|
|
48
|
+
translateY: iconTranslateY
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const ButtonDropdown = forwardRef(
|
|
53
|
+
(
|
|
54
|
+
{
|
|
55
|
+
value,
|
|
56
|
+
initialValue,
|
|
57
|
+
onChange,
|
|
58
|
+
label,
|
|
59
|
+
tokens,
|
|
60
|
+
variant,
|
|
61
|
+
inactive = false,
|
|
62
|
+
readOnly = false,
|
|
63
|
+
children = null,
|
|
64
|
+
accessibilityRole = 'radio',
|
|
65
|
+
...props
|
|
66
|
+
},
|
|
67
|
+
ref
|
|
68
|
+
) => {
|
|
69
|
+
const { currentValue: isOpen, setValue: setIsOpen } = useInputValue(
|
|
70
|
+
{
|
|
71
|
+
value,
|
|
72
|
+
initialValue,
|
|
73
|
+
onChange,
|
|
74
|
+
readOnly
|
|
75
|
+
},
|
|
76
|
+
'useButtonDropdownValues'
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
const extraState = {
|
|
80
|
+
open: isOpen,
|
|
81
|
+
inactive,
|
|
82
|
+
...variant
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const getTokens = useThemeTokensCallback('ButtonDropdown', tokens, extraState)
|
|
86
|
+
|
|
87
|
+
const getButtonTokens = (buttonState) => selectTokens('Button', getTokens(buttonState))
|
|
88
|
+
|
|
89
|
+
// Pass an object of relevant component state as first argument for any passed-in press handlers
|
|
90
|
+
const pressHandlers = getPressHandlersWithArgs(props, [{ label, open: isOpen }])
|
|
91
|
+
|
|
92
|
+
const handlePress = (event) => {
|
|
93
|
+
if (!inactive) {
|
|
94
|
+
if (pressHandlers.onPress) pressHandlers?.onPress(event)
|
|
95
|
+
setIsOpen(!isOpen, event)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<ButtonBase
|
|
101
|
+
ref={ref}
|
|
102
|
+
{...pressHandlers}
|
|
103
|
+
onPress={handlePress}
|
|
104
|
+
tokens={getButtonTokens}
|
|
105
|
+
inactive={inactive}
|
|
106
|
+
icon={() => null}
|
|
107
|
+
accessibilityRole={accessibilityRole}
|
|
108
|
+
{...props}
|
|
109
|
+
>
|
|
110
|
+
{({ textStyles, ...buttonState }) => {
|
|
111
|
+
// TODO: once Icon/IconButton designs are stable, see if this sort of styling around
|
|
112
|
+
// an icon should go in Icon itself, or possibly via an IconText token set. Related issues:
|
|
113
|
+
// - Icon: https://github.com/telus/universal-design-system/issues/327
|
|
114
|
+
// - IconButton: https://github.com/telus/universal-design-system/issues/281
|
|
115
|
+
// - Token sets: https://github.com/telus/universal-design-system/issues/782
|
|
116
|
+
|
|
117
|
+
const itemTokens = getTokens(buttonState)
|
|
118
|
+
|
|
119
|
+
const {
|
|
120
|
+
iconTokens,
|
|
121
|
+
iconPosition,
|
|
122
|
+
iconSpace,
|
|
123
|
+
iconWrapperStyle,
|
|
124
|
+
icon: IconComponent
|
|
125
|
+
} = selectIconTokens(itemTokens)
|
|
126
|
+
|
|
127
|
+
const iconContent = IconComponent ? (
|
|
128
|
+
<View style={iconWrapperStyle}>
|
|
129
|
+
<Icon icon={IconComponent} tokens={iconTokens} />
|
|
130
|
+
</View>
|
|
131
|
+
) : null
|
|
132
|
+
|
|
133
|
+
const childrenContent = () =>
|
|
134
|
+
typeof children === 'function'
|
|
135
|
+
? children({ ...resolvePressableState(buttonState, extraState), textStyles })
|
|
136
|
+
: children
|
|
137
|
+
|
|
138
|
+
const content = children ? childrenContent() : <Text style={textStyles}>{label}</Text>
|
|
139
|
+
|
|
140
|
+
return getStackedContent(
|
|
141
|
+
iconPosition === 'left' ? [iconContent, content] : [content, iconContent],
|
|
142
|
+
{ space: iconSpace, direction: 'row' }
|
|
143
|
+
)
|
|
144
|
+
}}
|
|
145
|
+
</ButtonBase>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
ButtonDropdown.displayName = 'ButtonDropdown'
|
|
150
|
+
|
|
151
|
+
ButtonDropdown.propTypes = {
|
|
152
|
+
...a11yProps.types,
|
|
153
|
+
...focusHandlerProps.types,
|
|
154
|
+
...buttonPropTypes,
|
|
155
|
+
children: textAndA11yText,
|
|
156
|
+
/**
|
|
157
|
+
* Callback called when a controlled ButtonDropdown gets interacted with.
|
|
158
|
+
*/
|
|
159
|
+
onChange: PropTypes.func,
|
|
160
|
+
/**
|
|
161
|
+
* `value` prop is being used to set the 'open' state of ButtonDropdown. Use it for
|
|
162
|
+
* controlled ButtonDropdown. For uncontrolled ButtonDropdown, use `initialValue`.
|
|
163
|
+
*/
|
|
164
|
+
value: PropTypes.bool,
|
|
165
|
+
/**
|
|
166
|
+
* Use `initialValue` to provide the initial value for an uncontrolled version.
|
|
167
|
+
*/
|
|
168
|
+
initialValue: PropTypes.bool,
|
|
169
|
+
/**
|
|
170
|
+
* The label of ButtonDropdown.
|
|
171
|
+
*/
|
|
172
|
+
label: PropTypes.string,
|
|
173
|
+
/**
|
|
174
|
+
* By default, `ButtonDropdown` is treated by accessibility tools as a radio button.
|
|
175
|
+
*/
|
|
176
|
+
accessibilityRole: PropTypes.string
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export default ButtonDropdown
|
package/src/Button/index.js
CHANGED
|
@@ -296,7 +296,7 @@ const Carousel = React.forwardRef(
|
|
|
296
296
|
|
|
297
297
|
animate(toValue, index)
|
|
298
298
|
|
|
299
|
-
if (onIndexChanged) onIndexChanged(calcDelta)
|
|
299
|
+
if (onIndexChanged) onIndexChanged(calcDelta, index)
|
|
300
300
|
return calcDelta
|
|
301
301
|
},
|
|
302
302
|
[containerLayout.width, activeIndex, animate, children.length, onIndexChanged]
|
|
@@ -520,7 +520,10 @@ const Carousel = React.forwardRef(
|
|
|
520
520
|
>
|
|
521
521
|
{childrenArray.map((element, index) => {
|
|
522
522
|
const hidden = !isAnimating && index !== activeIndex
|
|
523
|
-
const clonedElement = React.cloneElement(element, {
|
|
523
|
+
const clonedElement = React.cloneElement(element, {
|
|
524
|
+
elementIndex: index,
|
|
525
|
+
hidden
|
|
526
|
+
})
|
|
524
527
|
return <React.Fragment key={index.toFixed(2)}>{clonedElement}</React.Fragment>
|
|
525
528
|
})}
|
|
526
529
|
</Animated.View>
|
|
@@ -609,7 +612,7 @@ Carousel.propTypes = {
|
|
|
609
612
|
* This function is also provided with a parameter indicating changed index (either 1, or -1)
|
|
610
613
|
* Use it as follows:
|
|
611
614
|
* ```js
|
|
612
|
-
* const onIndexChangedCallback = React.useCallback((changedIndex) => {
|
|
615
|
+
* const onIndexChangedCallback = React.useCallback((changedIndex, currentActiveIndex) => {
|
|
613
616
|
* console.log(changedIndex)
|
|
614
617
|
* }, []) // pass local dependencies as per your component
|
|
615
618
|
* <Carousel
|
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
getA11yPropsFromHtmlTag,
|
|
7
7
|
selectSystemProps,
|
|
8
8
|
a11yProps,
|
|
9
|
-
viewProps
|
|
9
|
+
viewProps,
|
|
10
|
+
variantProp
|
|
10
11
|
} from '../../utils'
|
|
11
12
|
import { useCarousel } from '../CarouselContext'
|
|
12
13
|
|
|
@@ -18,6 +19,7 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
18
19
|
*/
|
|
19
20
|
const CarouselItem = ({ children, elementIndex, tag = 'li', hidden, ...rest }) => {
|
|
20
21
|
const { width, activeIndex } = useCarousel()
|
|
22
|
+
|
|
21
23
|
const selectedProps = selectProps({
|
|
22
24
|
...rest,
|
|
23
25
|
...getA11yPropsFromHtmlTag(tag, rest.accessibilityRole)
|
|
@@ -38,6 +40,7 @@ const CarouselItem = ({ children, elementIndex, tag = 'li', hidden, ...rest }) =
|
|
|
38
40
|
|
|
39
41
|
CarouselItem.propTypes = {
|
|
40
42
|
...selectedSystemPropTypes,
|
|
43
|
+
variant: variantProp.propType,
|
|
41
44
|
/**
|
|
42
45
|
* Index of the current slide
|
|
43
46
|
* Don't pass this prop when using `Carousel.Item` as it is already being passed by `Carousel` top-level component
|
|
@@ -58,7 +61,11 @@ CarouselItem.propTypes = {
|
|
|
58
61
|
* Carousel's innermost container defaults to `'ul'` which can be overridden. If the tag of either
|
|
59
62
|
* `Carousel` or `Carousel.Item` is overriden, the other should be too, to avoid producing invalid HTML.
|
|
60
63
|
*/
|
|
61
|
-
tag: PropTypes.oneOf(layoutTags)
|
|
64
|
+
tag: PropTypes.oneOf(layoutTags),
|
|
65
|
+
/**
|
|
66
|
+
* Function to set carousel content background color when slide is being display
|
|
67
|
+
*/
|
|
68
|
+
setContentBackgroundColor: PropTypes.func
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
CarouselItem.displayName = 'Carousel.Item'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef, useRef } from 'react'
|
|
1
|
+
import React, { forwardRef, useEffect, useRef, useState } from 'react'
|
|
2
2
|
import { View } from 'react-native'
|
|
3
3
|
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
@@ -7,10 +7,15 @@ import StackView from '../../StackView'
|
|
|
7
7
|
import { useCarousel } from '../CarouselContext'
|
|
8
8
|
import CarouselTabsPanelItem from './CarouselTabsPanelItem'
|
|
9
9
|
|
|
10
|
+
const selectTabPanelStyle = () => ({
|
|
11
|
+
backgroundColor: 'transparent'
|
|
12
|
+
})
|
|
13
|
+
|
|
10
14
|
const CarouselTabsPanel = forwardRef(({ items }, ref) => {
|
|
11
15
|
const { activeIndex, goTo } = useCarousel()
|
|
12
16
|
const nextFocusRef = useRef()
|
|
13
17
|
const firstTabRef = useRef()
|
|
18
|
+
const [isInverse, setIsInverse] = useState(false)
|
|
14
19
|
|
|
15
20
|
// TODO: figure out a better cross-brand way to specify subcomponent variants.
|
|
16
21
|
// For now, this picks an Allium variant, and does nothing in brands that lack it.
|
|
@@ -19,10 +24,16 @@ const CarouselTabsPanel = forwardRef(({ items }, ref) => {
|
|
|
19
24
|
|
|
20
25
|
const lastTabSelected = activeIndex === items.length - 1
|
|
21
26
|
|
|
27
|
+
// Get current select tab style
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const [selectedVariantIsInverse] = items.filter((_, index) => index === activeIndex)
|
|
30
|
+
setIsInverse(selectedVariantIsInverse?.inverse)
|
|
31
|
+
}, [items, activeIndex])
|
|
32
|
+
|
|
22
33
|
return (
|
|
23
|
-
|
|
34
|
+
<View style={selectTabPanelStyle()}>
|
|
24
35
|
<StackView direction="row" space={3} divider={{ variant: dividerVariant }} ref={ref}>
|
|
25
|
-
{items.map(({ title, onPress, ...panelItemProps }, index) => {
|
|
36
|
+
{items.map(({ title, onPress, inverse, ...panelItemProps }, index) => {
|
|
26
37
|
const selected = index === activeIndex
|
|
27
38
|
const isNext = index === activeIndex + 1
|
|
28
39
|
|
|
@@ -41,6 +52,7 @@ const CarouselTabsPanel = forwardRef(({ items }, ref) => {
|
|
|
41
52
|
title={title}
|
|
42
53
|
selected={selected}
|
|
43
54
|
onPress={handlePress}
|
|
55
|
+
variant={{ inverse: isInverse }}
|
|
44
56
|
{...panelItemProps}
|
|
45
57
|
/>
|
|
46
58
|
)
|
|
@@ -48,12 +60,14 @@ const CarouselTabsPanel = forwardRef(({ items }, ref) => {
|
|
|
48
60
|
</StackView>
|
|
49
61
|
{/* TODO: integrate with skiplink, replace this with focusing skiplink target */}
|
|
50
62
|
<View focusable accessible ref={lastTabSelected ? nextFocusRef : null} />
|
|
51
|
-
|
|
63
|
+
</View>
|
|
52
64
|
)
|
|
53
65
|
})
|
|
54
66
|
CarouselTabsPanel.displayName = 'CarouselTabsPanel'
|
|
55
67
|
CarouselTabsPanel.propTypes = {
|
|
56
|
-
items: PropTypes.arrayOf(PropTypes.shape(CarouselTabsPanelItem.propTypes || {}))
|
|
68
|
+
items: PropTypes.arrayOf(PropTypes.shape(CarouselTabsPanelItem.propTypes || {})),
|
|
69
|
+
// Color defined by `Carousel.item` variant otherwise fallback to transparent
|
|
70
|
+
contentBackgroundColor: PropTypes.string
|
|
57
71
|
}
|
|
58
72
|
|
|
59
73
|
export default CarouselTabsPanel
|
package/src/FlexGrid/Col/Col.jsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { forwardRef, useContext } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import { Platform, StyleSheet
|
|
3
|
+
import { Platform, StyleSheet } from 'react-native'
|
|
4
4
|
import { viewports } from '@telus-uds/system-constants'
|
|
5
5
|
|
|
6
6
|
import GutterContext from '../providers/GutterContext'
|
|
7
7
|
import { useViewport } from '../../ViewportProvider'
|
|
8
8
|
import applyInheritance from '../helpers'
|
|
9
|
-
import { responsiveProps } from '../../utils'
|
|
9
|
+
import { responsiveProps, BaseView } from '../../utils'
|
|
10
10
|
|
|
11
11
|
const Col = forwardRef(
|
|
12
12
|
(
|
|
@@ -162,7 +162,7 @@ const Col = forwardRef(
|
|
|
162
162
|
xl: offsetsWithIheritance[4]
|
|
163
163
|
}
|
|
164
164
|
return (
|
|
165
|
-
<
|
|
165
|
+
<BaseView
|
|
166
166
|
ref={ref}
|
|
167
167
|
{...viewProps}
|
|
168
168
|
style={[
|
|
@@ -174,7 +174,7 @@ const Col = forwardRef(
|
|
|
174
174
|
]}
|
|
175
175
|
>
|
|
176
176
|
{children}
|
|
177
|
-
</
|
|
177
|
+
</BaseView>
|
|
178
178
|
)
|
|
179
179
|
}
|
|
180
180
|
)
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet } from 'react-native'
|
|
4
4
|
import { viewports } from '@telus-uds/system-constants'
|
|
5
|
-
|
|
6
|
-
import Row from './Row'
|
|
7
|
-
import Col from './Col'
|
|
8
|
-
import { useViewport } from '../ViewportProvider'
|
|
9
|
-
import GutterContext from './providers/GutterContext'
|
|
10
|
-
import applyInheritance from './helpers'
|
|
11
5
|
import {
|
|
12
6
|
a11yProps,
|
|
13
7
|
viewProps,
|
|
14
8
|
getA11yPropsFromHtmlTag,
|
|
15
9
|
layoutTags,
|
|
16
|
-
selectSystemProps
|
|
10
|
+
selectSystemProps,
|
|
11
|
+
BaseView
|
|
17
12
|
} from '../utils'
|
|
18
13
|
|
|
14
|
+
import Row from './Row'
|
|
15
|
+
import Col from './Col'
|
|
16
|
+
import { useViewport } from '../ViewportProvider'
|
|
17
|
+
import GutterContext from './providers/GutterContext'
|
|
18
|
+
import applyInheritance from './helpers'
|
|
19
|
+
|
|
19
20
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -75,7 +76,7 @@ const FlexGrid = forwardRef(
|
|
|
75
76
|
|
|
76
77
|
return (
|
|
77
78
|
<GutterContext.Provider value={gutter}>
|
|
78
|
-
<
|
|
79
|
+
<BaseView
|
|
79
80
|
ref={ref}
|
|
80
81
|
{...props}
|
|
81
82
|
style={[
|
|
@@ -84,7 +85,7 @@ const FlexGrid = forwardRef(
|
|
|
84
85
|
]}
|
|
85
86
|
>
|
|
86
87
|
{children}
|
|
87
|
-
</
|
|
88
|
+
</BaseView>
|
|
88
89
|
</GutterContext.Provider>
|
|
89
90
|
)
|
|
90
91
|
}
|
package/src/FlexGrid/Row/Row.jsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet } from 'react-native'
|
|
4
4
|
import { viewports } from '@telus-uds/system-constants'
|
|
5
5
|
|
|
6
6
|
import { useViewport } from '../../ViewportProvider'
|
|
7
7
|
import applyInheritance from '../helpers'
|
|
8
|
+
import { BaseView } from '../../utils'
|
|
8
9
|
|
|
9
10
|
const horizontalAlignStyles = (horizontalAlign) => {
|
|
10
11
|
switch (horizontalAlign) {
|
|
@@ -96,7 +97,7 @@ const Row = forwardRef(
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
return (
|
|
99
|
-
<
|
|
100
|
+
<BaseView
|
|
100
101
|
ref={ref}
|
|
101
102
|
{...rest}
|
|
102
103
|
style={[
|
|
@@ -111,7 +112,7 @@ const Row = forwardRef(
|
|
|
111
112
|
]}
|
|
112
113
|
>
|
|
113
114
|
{children}
|
|
114
|
-
</
|
|
115
|
+
</BaseView>
|
|
115
116
|
)
|
|
116
117
|
}
|
|
117
118
|
)
|
|
@@ -68,7 +68,9 @@ const IconButton = forwardRef(
|
|
|
68
68
|
...rest,
|
|
69
69
|
accessibilityRole
|
|
70
70
|
})
|
|
71
|
-
const handlePress =
|
|
71
|
+
const handlePress = () => {
|
|
72
|
+
linkProps.handleHref({ href, onPress })({ nativeEvent: { target: ref?.current?.id } })
|
|
73
|
+
}
|
|
72
74
|
|
|
73
75
|
const getTokens = useThemeTokensCallback('IconButton', tokens, variant)
|
|
74
76
|
const getOuterStyle = (pressableState) =>
|