@telus-uds/components-base 3.27.0 → 3.28.1
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 -5
- package/lib/cjs/Card/CardBase.js +12 -3
- package/lib/cjs/Carousel/Carousel.js +16 -15
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +3 -3
- package/lib/cjs/ExpandCollapse/Control.js +5 -1
- package/lib/cjs/ExpandCollapse/ExpandCollapse.js +17 -8
- package/lib/cjs/ExpandCollapse/Panel.js +7 -2
- package/lib/cjs/IconButton/IconButton.js +10 -5
- package/lib/cjs/Modal/Modal.js +21 -11
- package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +5 -1
- package/lib/cjs/Progress/Progress.js +19 -5
- package/lib/cjs/Progress/ProgressBar.js +22 -4
- package/lib/cjs/Progress/ProgressContext.js +11 -0
- package/lib/cjs/SideNav/Item.js +3 -3
- package/lib/cjs/SideNav/ItemsGroup.js +46 -19
- package/lib/cjs/SideNav/SideNav.js +29 -13
- package/lib/esm/Card/CardBase.js +12 -3
- package/lib/esm/Carousel/Carousel.js +16 -15
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +3 -3
- package/lib/esm/ExpandCollapse/Control.js +5 -1
- package/lib/esm/ExpandCollapse/ExpandCollapse.js +17 -8
- package/lib/esm/ExpandCollapse/Panel.js +7 -2
- package/lib/esm/IconButton/IconButton.js +10 -5
- package/lib/esm/Modal/Modal.js +21 -11
- package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +5 -1
- package/lib/esm/Progress/Progress.js +19 -5
- package/lib/esm/Progress/ProgressBar.js +22 -4
- package/lib/esm/Progress/ProgressContext.js +5 -0
- package/lib/esm/SideNav/Item.js +3 -3
- package/lib/esm/SideNav/ItemsGroup.js +45 -20
- package/lib/esm/SideNav/SideNav.js +29 -13
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Card/CardBase.jsx +9 -3
- package/src/Carousel/Carousel.jsx +16 -15
- package/src/Carousel/CarouselItem/CarouselItem.jsx +3 -3
- package/src/ExpandCollapse/Control.jsx +1 -1
- package/src/ExpandCollapse/ExpandCollapse.jsx +9 -8
- package/src/ExpandCollapse/Panel.jsx +10 -2
- package/src/IconButton/IconButton.jsx +40 -28
- package/src/Modal/Modal.jsx +23 -11
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +6 -1
- package/src/Progress/Progress.jsx +18 -7
- package/src/Progress/ProgressBar.jsx +19 -14
- package/src/Progress/ProgressContext.js +5 -0
- package/src/SideNav/Item.jsx +3 -3
- package/src/SideNav/ItemsGroup.jsx +36 -16
- package/src/SideNav/SideNav.jsx +22 -8
|
@@ -4,6 +4,19 @@ import ItemContent from './ItemContent';
|
|
|
4
4
|
import ExpandCollapse from '../ExpandCollapse';
|
|
5
5
|
import { getTokensPropType, variantProp, componentPropType, selectTokens } from '../utils';
|
|
6
6
|
import { useThemeTokensCallback } from '../ThemeProvider';
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const selectPanelTokens = _ref => {
|
|
9
|
+
let {
|
|
10
|
+
borderWidth,
|
|
11
|
+
borderColor,
|
|
12
|
+
backgroundColor
|
|
13
|
+
} = _ref;
|
|
14
|
+
return {
|
|
15
|
+
contentPanelBackgroundColor: backgroundColor,
|
|
16
|
+
borderBottomWidth: borderWidth,
|
|
17
|
+
borderColor
|
|
18
|
+
};
|
|
19
|
+
};
|
|
7
20
|
|
|
8
21
|
/**
|
|
9
22
|
Expandable content areas for use within `SideNav`.
|
|
@@ -15,8 +28,7 @@ import { useThemeTokensCallback } from '../ThemeProvider';
|
|
|
15
28
|
## Usage Criteria
|
|
16
29
|
- Use `SideNav.ItemsGroup` with large pages that have multiple sections
|
|
17
30
|
*/
|
|
18
|
-
|
|
19
|
-
const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
31
|
+
const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
20
32
|
let {
|
|
21
33
|
children,
|
|
22
34
|
label,
|
|
@@ -27,7 +39,7 @@ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
27
39
|
tokens,
|
|
28
40
|
itemTokens,
|
|
29
41
|
onToggle
|
|
30
|
-
} =
|
|
42
|
+
} = _ref2;
|
|
31
43
|
// A SideNav control uses the same style and theme as SideNavItem, with a 'parent' variant,
|
|
32
44
|
// plus control-specific tokens from the SideNavItemsGroup theme (e.g. open/close icon, etc).
|
|
33
45
|
const getAppearance = appearance => ({
|
|
@@ -40,28 +52,27 @@ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
40
52
|
type: 'parent'
|
|
41
53
|
});
|
|
42
54
|
const getGroupTokens = useThemeTokensCallback('SideNavItemsGroup', tokens, variant);
|
|
43
|
-
const getPanelTokens = appearance => {
|
|
44
|
-
const {
|
|
45
|
-
panelBorderColor,
|
|
46
|
-
...itemsGroupTokens
|
|
47
|
-
} = getGroupTokens(getAppearance(appearance));
|
|
48
|
-
const groupTokens = {
|
|
49
|
-
...itemsGroupTokens,
|
|
50
|
-
borderWidth: 0,
|
|
51
|
-
marginBottom: 0
|
|
52
|
-
};
|
|
53
|
-
return selectTokens('ExpandCollapsePanel', groupTokens);
|
|
54
|
-
};
|
|
55
55
|
const getItemTokens = useThemeTokensCallback('SideNavItem', itemTokens, variant);
|
|
56
|
-
const
|
|
57
|
-
...
|
|
58
|
-
|
|
59
|
-
...
|
|
56
|
+
const getPanelTokens = appearance => selectTokens('ExpandCollapsePanel', {
|
|
57
|
+
...staticTokens.panel,
|
|
58
|
+
...getGroupTokens(getAppearance(appearance)),
|
|
59
|
+
...selectPanelTokens(getItemTokens(getItemAppearance(appearance)))
|
|
60
|
+
});
|
|
61
|
+
const getControlTokens = appearance => ({
|
|
62
|
+
...selectTokens('ExpandCollapseControl', {
|
|
63
|
+
...getItemTokens(getItemAppearance(appearance)),
|
|
64
|
+
// main style from SideNavItem
|
|
65
|
+
...getGroupTokens(getAppearance(appearance)) // control-specific tokens like icon etc,
|
|
66
|
+
}),
|
|
67
|
+
...staticTokens.control
|
|
60
68
|
});
|
|
61
69
|
const controlContent = controlState => {
|
|
62
70
|
const currentItemTokens = getItemTokens(getItemAppearance(controlState));
|
|
63
71
|
return /*#__PURE__*/_jsx(ItemContent, {
|
|
64
|
-
tokens:
|
|
72
|
+
tokens: {
|
|
73
|
+
...currentItemTokens,
|
|
74
|
+
...staticTokens.content
|
|
75
|
+
},
|
|
65
76
|
children: label
|
|
66
77
|
});
|
|
67
78
|
};
|
|
@@ -77,9 +88,23 @@ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
77
88
|
active: isActive
|
|
78
89
|
} // ExpandCollapse.Panel handles expanded state
|
|
79
90
|
,
|
|
91
|
+
disableMobileScrollBuffer: true,
|
|
80
92
|
children: children
|
|
81
93
|
});
|
|
82
94
|
});
|
|
95
|
+
const staticTokens = {
|
|
96
|
+
panel: {
|
|
97
|
+
borderWidth: 0,
|
|
98
|
+
marginBottom: 0
|
|
99
|
+
},
|
|
100
|
+
control: {
|
|
101
|
+
borderWidth: 0,
|
|
102
|
+
textLine: null
|
|
103
|
+
},
|
|
104
|
+
content: {
|
|
105
|
+
accentWidth: 0
|
|
106
|
+
}
|
|
107
|
+
};
|
|
83
108
|
ItemsGroup.displayName = 'ItemsGroup';
|
|
84
109
|
ItemsGroup.propTypes = {
|
|
85
110
|
/**
|
|
@@ -6,13 +6,28 @@ import ItemsGroup from './ItemsGroup';
|
|
|
6
6
|
import { useThemeTokens } from '../ThemeProvider';
|
|
7
7
|
import { a11yProps, componentPropType, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
8
8
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
-
|
|
9
|
+
const selectContainerTokens = _ref => {
|
|
10
|
+
let {
|
|
11
|
+
borderWidth,
|
|
12
|
+
borderStyle,
|
|
13
|
+
borderColor
|
|
14
|
+
} = _ref;
|
|
10
15
|
return {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
borderTopWidth: borderWidth,
|
|
17
|
+
borderStyle,
|
|
18
|
+
borderColor
|
|
14
19
|
};
|
|
15
|
-
}
|
|
20
|
+
};
|
|
21
|
+
const selectItemTokens = function () {
|
|
22
|
+
let tokens = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
23
|
+
let isLastItem = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
24
|
+
return {
|
|
25
|
+
...tokens,
|
|
26
|
+
...(isLastItem ? {
|
|
27
|
+
borderWidth: 0
|
|
28
|
+
} : {})
|
|
29
|
+
};
|
|
30
|
+
};
|
|
16
31
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
17
32
|
|
|
18
33
|
/**
|
|
@@ -20,7 +35,7 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
20
35
|
- Use in conjunction with a large amount of educational / informational content
|
|
21
36
|
- Allow the user to navigate between options frequently and efficiently
|
|
22
37
|
*/
|
|
23
|
-
const SideNav = /*#__PURE__*/React.forwardRef((
|
|
38
|
+
const SideNav = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
24
39
|
let {
|
|
25
40
|
children,
|
|
26
41
|
variant = {},
|
|
@@ -29,7 +44,7 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
29
44
|
itemTokens,
|
|
30
45
|
groupTokens,
|
|
31
46
|
...rest
|
|
32
|
-
} =
|
|
47
|
+
} = _ref2;
|
|
33
48
|
const themeTokens = useThemeTokens('SideNav', tokens, variant);
|
|
34
49
|
const [active, setActive] = React.useState({
|
|
35
50
|
groupId: undefined,
|
|
@@ -47,14 +62,15 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
47
62
|
return /*#__PURE__*/_jsx(ExpandCollapse, {
|
|
48
63
|
ref: ref,
|
|
49
64
|
maxOpen: accordion ? 1 : null,
|
|
50
|
-
|
|
65
|
+
tokens: selectContainerTokens(themeTokens),
|
|
51
66
|
...selectProps(rest),
|
|
52
|
-
children:
|
|
67
|
+
children: _ref3 => {
|
|
53
68
|
let {
|
|
54
69
|
openIds,
|
|
55
70
|
onToggle
|
|
56
|
-
} =
|
|
57
|
-
const renderItem = (item, index, groupId)
|
|
71
|
+
} = _ref3;
|
|
72
|
+
const renderItem = function (item, index, groupId) {
|
|
73
|
+
let isLastItem = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
58
74
|
const {
|
|
59
75
|
itemId = `item-${index}`,
|
|
60
76
|
onPress
|
|
@@ -72,7 +88,7 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
72
88
|
...variant,
|
|
73
89
|
type: 'child'
|
|
74
90
|
} : variant,
|
|
75
|
-
tokens: itemTokens,
|
|
91
|
+
tokens: selectItemTokens(itemTokens, isLastItem),
|
|
76
92
|
isActive: isItemActive(itemId, groupId),
|
|
77
93
|
onPress: handlePress
|
|
78
94
|
});
|
|
@@ -96,7 +112,7 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
96
112
|
openGroups: openIds,
|
|
97
113
|
isActive: isGroupActive,
|
|
98
114
|
onToggle: handleToggle
|
|
99
|
-
}, React.Children.map(child.props.children, (item, itemIndex) => renderItem(item, itemIndex, groupId)));
|
|
115
|
+
}, React.Children.map(child.props.children, (item, itemIndex) => renderItem(item, itemIndex, groupId, itemIndex === child.props.children.length - 1)));
|
|
100
116
|
}
|
|
101
117
|
return null;
|
|
102
118
|
});
|
package/lib/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@react-native-picker/picker": "^2.9.0",
|
|
14
14
|
"@telus-uds/system-constants": "^3.0.0",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^4.20.0",
|
|
16
16
|
"airbnb-prop-types": "^2.16.0",
|
|
17
17
|
"css-mediaquery": "^0.1.2",
|
|
18
18
|
"expo-document-picker": "^13.0.1",
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
"standard-engine": {
|
|
85
85
|
"skip": true
|
|
86
86
|
},
|
|
87
|
-
"version": "3.
|
|
87
|
+
"version": "3.28.1",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@react-native-picker/picker": "^2.9.0",
|
|
14
14
|
"@telus-uds/system-constants": "^3.0.0",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^4.20.0",
|
|
16
16
|
"airbnb-prop-types": "^2.16.0",
|
|
17
17
|
"css-mediaquery": "^0.1.2",
|
|
18
18
|
"expo-document-picker": "^13.0.1",
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
"standard-engine": {
|
|
85
85
|
"skip": true
|
|
86
86
|
},
|
|
87
|
-
"version": "3.
|
|
87
|
+
"version": "3.28.1",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
package/src/Card/CardBase.jsx
CHANGED
|
@@ -233,7 +233,13 @@ export const selectStyles = ({
|
|
|
233
233
|
*/
|
|
234
234
|
const CardBase = React.forwardRef(
|
|
235
235
|
({ children, tokens, dataSet, backgroundImage, fullBleedContent, cardState, ...rest }, ref) => {
|
|
236
|
-
const
|
|
236
|
+
const resolvedTokens = typeof tokens === 'function' ? tokens(cardState) : tokens
|
|
237
|
+
const tokensToUse =
|
|
238
|
+
backgroundImage && backgroundImage.src
|
|
239
|
+
? { ...resolvedTokens, gradient: undefined, backgroundGradient: undefined }
|
|
240
|
+
: resolvedTokens
|
|
241
|
+
|
|
242
|
+
const cardStyle = selectStyles(tokensToUse)
|
|
237
243
|
const props = selectProps(rest)
|
|
238
244
|
|
|
239
245
|
let content = children
|
|
@@ -314,7 +320,7 @@ const CardBase = React.forwardRef(
|
|
|
314
320
|
})
|
|
315
321
|
|
|
316
322
|
return (
|
|
317
|
-
<View style={containerStyle} dataSet={dataSet} ref={ref} {...props}>
|
|
323
|
+
<View style={{ ...containerStyle, borderRadius }} dataSet={dataSet} ref={ref} {...props}>
|
|
318
324
|
{content}
|
|
319
325
|
</View>
|
|
320
326
|
)
|
|
@@ -393,7 +399,7 @@ const staticStyles = StyleSheet.create({
|
|
|
393
399
|
contentOverlay: {
|
|
394
400
|
position: 'relative',
|
|
395
401
|
width: '100%',
|
|
396
|
-
|
|
402
|
+
minHeight: '100%',
|
|
397
403
|
zIndex: 2
|
|
398
404
|
},
|
|
399
405
|
containContainer: {
|
|
@@ -125,7 +125,7 @@ const selectControlButtonPositionStyles = ({
|
|
|
125
125
|
isAutoPlayEnabled,
|
|
126
126
|
viewport,
|
|
127
127
|
maxWidth,
|
|
128
|
-
|
|
128
|
+
containerWidth
|
|
129
129
|
}) => {
|
|
130
130
|
const styles = {}
|
|
131
131
|
|
|
@@ -148,13 +148,11 @@ const selectControlButtonPositionStyles = ({
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
if (enablePeeking) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
positionOffset += leftMargin
|
|
157
|
-
}
|
|
151
|
+
const { peekingMiddleSpace, peekingGap } = getPeekingProps(viewport)
|
|
152
|
+
const clampedMaxWidth = Math.min(maxWidth || containerWidth, containerWidth)
|
|
153
|
+
const slideRightEdge = (containerWidth + clampedMaxWidth) / 2 - peekingMiddleSpace
|
|
154
|
+
const buttonCenter = slideRightEdge + peekingGap / 2
|
|
155
|
+
positionOffset = containerWidth - buttonCenter - buttonWidth / 2
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
styles[positionProperty] = positionOffset
|
|
@@ -173,7 +171,7 @@ const selectPreviousNextNavigationButtonStyles = (
|
|
|
173
171
|
isAutoPlayEnabled,
|
|
174
172
|
viewport,
|
|
175
173
|
maxWidth,
|
|
176
|
-
|
|
174
|
+
containerWidth
|
|
177
175
|
) => {
|
|
178
176
|
const styles = {
|
|
179
177
|
zIndex: 1,
|
|
@@ -199,7 +197,7 @@ const selectPreviousNextNavigationButtonStyles = (
|
|
|
199
197
|
isAutoPlayEnabled,
|
|
200
198
|
viewport,
|
|
201
199
|
maxWidth,
|
|
202
|
-
|
|
200
|
+
containerWidth
|
|
203
201
|
})
|
|
204
202
|
}
|
|
205
203
|
}
|
|
@@ -343,7 +341,7 @@ const calculateFinalWidth = (containerWidth, enablePeeking, viewport, maxWidth)
|
|
|
343
341
|
|
|
344
342
|
if (enablePeeking) {
|
|
345
343
|
const { peekingGap, peekingMiddleSpace } = getPeekingProps(viewport)
|
|
346
|
-
const baseWidth = maxWidth || containerWidth
|
|
344
|
+
const baseWidth = Math.min(maxWidth || containerWidth, containerWidth)
|
|
347
345
|
finalWidth = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER + peekingGap
|
|
348
346
|
}
|
|
349
347
|
|
|
@@ -572,7 +570,10 @@ const Carousel = React.forwardRef(
|
|
|
572
570
|
const { peekingGap, peekingMiddleSpace } = getPeekingProps(viewport)
|
|
573
571
|
|
|
574
572
|
let finalWidth
|
|
575
|
-
const baseWidth =
|
|
573
|
+
const baseWidth = Math.min(
|
|
574
|
+
maxWidth || containerLayoutRef.current.width,
|
|
575
|
+
containerLayoutRef.current.width
|
|
576
|
+
)
|
|
576
577
|
const slideWide = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER
|
|
577
578
|
|
|
578
579
|
if (activeIndexRef.current === 0) {
|
|
@@ -1177,7 +1178,7 @@ const Carousel = React.forwardRef(
|
|
|
1177
1178
|
isAutoPlayEnabled,
|
|
1178
1179
|
viewport,
|
|
1179
1180
|
maxWidth,
|
|
1180
|
-
|
|
1181
|
+
containerWidth: containerLayout.width
|
|
1181
1182
|
})
|
|
1182
1183
|
]}
|
|
1183
1184
|
>
|
|
@@ -1205,7 +1206,7 @@ const Carousel = React.forwardRef(
|
|
|
1205
1206
|
isAutoPlayEnabled,
|
|
1206
1207
|
viewport,
|
|
1207
1208
|
maxWidth,
|
|
1208
|
-
|
|
1209
|
+
containerLayout.width
|
|
1209
1210
|
)}
|
|
1210
1211
|
testID="previous-button-container"
|
|
1211
1212
|
>
|
|
@@ -1303,7 +1304,7 @@ const Carousel = React.forwardRef(
|
|
|
1303
1304
|
isAutoPlayEnabled,
|
|
1304
1305
|
viewport,
|
|
1305
1306
|
maxWidth,
|
|
1306
|
-
|
|
1307
|
+
containerLayout.width
|
|
1307
1308
|
)}
|
|
1308
1309
|
testID="next-button-container"
|
|
1309
1310
|
>
|
|
@@ -31,10 +31,10 @@ const selectContainerStyle = ({
|
|
|
31
31
|
|
|
32
32
|
if (enablePeeking) {
|
|
33
33
|
const isFirst = elementIndex === 0
|
|
34
|
-
const
|
|
35
|
-
adjustedWidth =
|
|
34
|
+
const clampedMaxWidth = Math.min(maxWidth || width, width)
|
|
35
|
+
adjustedWidth = clampedMaxWidth - peekingMiddleSpace * 2
|
|
36
36
|
if (isFirst) {
|
|
37
|
-
marginLeft = peekingMiddleSpace + (viewportWidth -
|
|
37
|
+
marginLeft = peekingMiddleSpace + (viewportWidth - clampedMaxWidth) / 2
|
|
38
38
|
} else {
|
|
39
39
|
marginLeft = peekingGap
|
|
40
40
|
}
|
|
@@ -50,7 +50,7 @@ function selectIconContainerStyles({ iconGap, iconPaddingTop, iconPosition }) {
|
|
|
50
50
|
const paddingSide = iconPosition === 'right' ? 'paddingLeft' : 'paddingRight'
|
|
51
51
|
return {
|
|
52
52
|
[paddingSide]: iconGap,
|
|
53
|
-
|
|
53
|
+
...(iconPaddingTop && { transform: [{ translateY: iconPaddingTop }] })
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -20,13 +20,14 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
|
20
20
|
contentfulProps
|
|
21
21
|
])
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
const selectWrapperStyles = ({ borderWidth, borderTopWidth, borderStyle, borderColor }) => ({
|
|
24
|
+
borderStyle,
|
|
25
|
+
borderColor,
|
|
26
|
+
borderTopWidth,
|
|
27
|
+
borderBottomWidth: borderWidth,
|
|
28
|
+
borderBottomStyle: borderStyle,
|
|
29
|
+
borderBottomColor: borderColor
|
|
30
|
+
})
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Flexible base component for lists where some or all items are collapsible headers.
|
|
@@ -55,7 +56,7 @@ const ExpandCollapse = React.forwardRef(
|
|
|
55
56
|
|
|
56
57
|
return (
|
|
57
58
|
<View style={staticStyles.container} ref={ref} {...selectProps(rest)} dataSet={dataSet}>
|
|
58
|
-
<View style={
|
|
59
|
+
<View style={selectWrapperStyles(themeTokens)}>
|
|
59
60
|
{typeof children === 'function'
|
|
60
61
|
? children({ openIds, onToggle, resetValues, setValues, unsetValues, instanceId })
|
|
61
62
|
: children}
|
|
@@ -96,6 +96,7 @@ const ExpandCollapsePanel = React.forwardRef(
|
|
|
96
96
|
controlRef,
|
|
97
97
|
content,
|
|
98
98
|
copy = 'en',
|
|
99
|
+
disableMobileScrollBuffer = false,
|
|
99
100
|
...rest
|
|
100
101
|
},
|
|
101
102
|
ref
|
|
@@ -118,7 +119,10 @@ const ExpandCollapsePanel = React.forwardRef(
|
|
|
118
119
|
|
|
119
120
|
// on mobile devices we require a scroll buffer equal to the font size
|
|
120
121
|
// to avoid triggering scrolling unnecessarily
|
|
121
|
-
const mobileScrollBuffer =
|
|
122
|
+
const mobileScrollBuffer =
|
|
123
|
+
Platform.OS === 'web' || disableMobileScrollBuffer
|
|
124
|
+
? 0
|
|
125
|
+
: selectTextStyles(themeTokens)?.fontSize
|
|
122
126
|
|
|
123
127
|
const handleControlPress = (event) => {
|
|
124
128
|
onToggle?.(panelId, event)
|
|
@@ -287,7 +291,11 @@ ExpandCollapsePanel.propTypes = {
|
|
|
287
291
|
/**
|
|
288
292
|
* A boolean prop to determine if the panel is a content panel or not. If true, the panel will not have a control
|
|
289
293
|
*/
|
|
290
|
-
content: PropTypes.bool
|
|
294
|
+
content: PropTypes.bool,
|
|
295
|
+
/**
|
|
296
|
+
* A boolean prop to disable the extra scroll buffer on mobile devices (only applicable on iOS/Android, ignored on web)
|
|
297
|
+
*/
|
|
298
|
+
disableMobileScrollBuffer: PropTypes.bool
|
|
291
299
|
}
|
|
292
300
|
|
|
293
301
|
export default ExpandCollapsePanel
|
|
@@ -92,34 +92,46 @@ const selectInnerStyle = (
|
|
|
92
92
|
height
|
|
93
93
|
},
|
|
94
94
|
password
|
|
95
|
-
) =>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
95
|
+
) => {
|
|
96
|
+
const basePadding = calculatePadding(padding, borderWidth)
|
|
97
|
+
|
|
98
|
+
const calculateSpecificPadding = (specificPadding, specificBorderWidth) => {
|
|
99
|
+
const calculated = calculatePadding(
|
|
100
|
+
specificPadding ?? padding,
|
|
101
|
+
specificBorderWidth ?? borderWidth
|
|
102
|
+
)
|
|
103
|
+
return calculated !== basePadding && calculated !== undefined ? calculated : undefined
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
// Inner borders animate with the icon and should be treated like a themable feature of the icon
|
|
108
|
+
borderColor,
|
|
109
|
+
borderRadius,
|
|
110
|
+
borderWidth,
|
|
111
|
+
borderTopLeftRadius,
|
|
112
|
+
borderTopRightRadius,
|
|
113
|
+
borderBottomLeftRadius,
|
|
114
|
+
borderBottomRightRadius,
|
|
115
|
+
borderTopWidth,
|
|
116
|
+
borderRightWidth,
|
|
117
|
+
borderBottomWidth,
|
|
118
|
+
borderLeftWidth,
|
|
119
|
+
padding: basePadding,
|
|
120
|
+
paddingLeft: calculateSpecificPadding(paddingLeft, borderLeftWidth),
|
|
121
|
+
paddingRight: calculateSpecificPadding(paddingRight, borderRightWidth),
|
|
122
|
+
paddingTop: calculateSpecificPadding(paddingTop, borderTopWidth),
|
|
123
|
+
paddingBottom: calculateSpecificPadding(paddingBottom, borderBottomWidth),
|
|
124
|
+
...Platform.select({
|
|
125
|
+
web: {
|
|
126
|
+
pointerEvents: 'none',
|
|
127
|
+
display: 'inline-flex',
|
|
128
|
+
alignItems: 'center',
|
|
129
|
+
justifyContent: 'center'
|
|
130
|
+
}
|
|
131
|
+
}),
|
|
132
|
+
...getPasswordDimensions(password, width, height)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
123
135
|
|
|
124
136
|
/**
|
|
125
137
|
* A pressable themeless base component that handles pressable states and passes tokens
|
package/src/Modal/Modal.jsx
CHANGED
|
@@ -68,9 +68,10 @@ const selectModalStyles = ({
|
|
|
68
68
|
...applyShadowToken(shadow)
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
const selectBackdropStyles = ({ backdropColor, backdropOpacity }) => ({
|
|
71
|
+
const selectBackdropStyles = ({ backdropColor, backdropOpacity, backdropCursor }) => ({
|
|
72
72
|
backgroundColor: backdropColor,
|
|
73
|
-
opacity: backdropOpacity
|
|
73
|
+
opacity: backdropOpacity,
|
|
74
|
+
...(Platform.OS === 'web' && backdropCursor ? { cursor: backdropCursor } : {})
|
|
74
75
|
})
|
|
75
76
|
|
|
76
77
|
const selectCloseButtonContainerStyles = ({ paddingRight, paddingTop }) => ({
|
|
@@ -119,12 +120,20 @@ const Modal = React.forwardRef(
|
|
|
119
120
|
cancelButtonText,
|
|
120
121
|
cancelButtonType,
|
|
121
122
|
footer,
|
|
123
|
+
backgroundDismissible = true,
|
|
122
124
|
...rest
|
|
123
125
|
},
|
|
124
126
|
ref
|
|
125
127
|
) => {
|
|
126
128
|
const viewport = useViewport()
|
|
127
|
-
|
|
129
|
+
|
|
130
|
+
const isBackdropClickable = onClose && backgroundDismissible
|
|
131
|
+
|
|
132
|
+
const themeTokens = useThemeTokens('Modal', tokens, variant, {
|
|
133
|
+
viewport,
|
|
134
|
+
maxWidth,
|
|
135
|
+
backdropCursor: isBackdropClickable ? 'pointer' : 'default'
|
|
136
|
+
})
|
|
128
137
|
const modalRef = useScrollBlocking(isOpen)
|
|
129
138
|
const modalBodyRef = React.useRef(ref)
|
|
130
139
|
const modalContentRef = React.useRef(null)
|
|
@@ -253,7 +262,7 @@ const Modal = React.forwardRef(
|
|
|
253
262
|
</View>
|
|
254
263
|
{/* when a modal becomes open its first focusable element is being automatically focused */}
|
|
255
264
|
{/* and we prefer the close button over backdrop */}
|
|
256
|
-
<TouchableWithoutFeedback onPress={handleClose}>
|
|
265
|
+
<TouchableWithoutFeedback onPress={isBackdropClickable && handleClose}>
|
|
257
266
|
<View style={[staticStyles.backdrop, selectBackdropStyles(themeTokens)]} />
|
|
258
267
|
</TouchableWithoutFeedback>
|
|
259
268
|
</ScrollView>
|
|
@@ -349,7 +358,15 @@ Modal.propTypes = {
|
|
|
349
358
|
/**
|
|
350
359
|
* Receive a react node or an array of nodes to render at the bottom of the modal, above the action buttons.
|
|
351
360
|
*/
|
|
352
|
-
footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
|
|
361
|
+
footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
|
362
|
+
/**
|
|
363
|
+
* Controls whether the modal can be dismissed by clicking on the backdrop.
|
|
364
|
+
* When set to `false`, clicking the backdrop will not close the modal.
|
|
365
|
+
* The backdrop cursor automatically changes to 'default' to indicate it's not clickable.
|
|
366
|
+
* Note: Backdrop dismissal requires `onClose` to be defined.
|
|
367
|
+
* @default true
|
|
368
|
+
*/
|
|
369
|
+
backgroundDismissible: PropTypes.bool
|
|
353
370
|
}
|
|
354
371
|
|
|
355
372
|
export default Modal
|
|
@@ -361,12 +378,7 @@ const staticStyles = StyleSheet.create({
|
|
|
361
378
|
left: 0,
|
|
362
379
|
right: 0,
|
|
363
380
|
bottom: 0,
|
|
364
|
-
zIndex: -1
|
|
365
|
-
...Platform.select({
|
|
366
|
-
web: {
|
|
367
|
-
cursor: 'pointer'
|
|
368
|
-
}
|
|
369
|
-
})
|
|
381
|
+
zIndex: -1
|
|
370
382
|
},
|
|
371
383
|
positioningContainer: {
|
|
372
384
|
flexBasis: '100%',
|
|
@@ -185,6 +185,12 @@ const MultiSelectFilter = React.forwardRef(
|
|
|
185
185
|
|
|
186
186
|
React.useEffect(() => setCheckedIds(currentValues ?? []), [currentValues])
|
|
187
187
|
|
|
188
|
+
React.useEffect(() => {
|
|
189
|
+
if (isOpen && onOpen) {
|
|
190
|
+
onOpen()
|
|
191
|
+
}
|
|
192
|
+
}, [isOpen, onOpen])
|
|
193
|
+
|
|
188
194
|
const uniqueFields = ['id', 'label']
|
|
189
195
|
if (!containUniqueFields(items, uniqueFields)) {
|
|
190
196
|
throw new Error(`MultiSelectFilter items must have unique ${uniqueFields.join(', ')}`)
|
|
@@ -194,7 +200,6 @@ const MultiSelectFilter = React.forwardRef(
|
|
|
194
200
|
|
|
195
201
|
const handleChange = (event) => {
|
|
196
202
|
if (pressHandlers.onPress) pressHandlers?.onPress(event)
|
|
197
|
-
if (isOpen) onOpen()
|
|
198
203
|
setIsOpen(!isOpen)
|
|
199
204
|
}
|
|
200
205
|
|
|
@@ -4,6 +4,7 @@ import { View, StyleSheet } from 'react-native'
|
|
|
4
4
|
|
|
5
5
|
import { applyShadowToken, useThemeTokens } from '../ThemeProvider'
|
|
6
6
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
7
|
+
import ProgressContext from './ProgressContext'
|
|
7
8
|
|
|
8
9
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
9
10
|
|
|
@@ -45,6 +46,12 @@ const selectProgressStyles = ({
|
|
|
45
46
|
*
|
|
46
47
|
* - Use the `size` variant to control the height of your progress bars: passing `'mini'` will make your
|
|
47
48
|
* progress bar container narrower.
|
|
49
|
+
* - Use the `layers` variant to control how multiple progress bars are positioned:
|
|
50
|
+
* - `false` (default): bars are positioned vertically one below the other.
|
|
51
|
+
* - `true`: bars overlay on top of each other (layered/stacked on z-axis).
|
|
52
|
+
* Note: The `layers` prop is deprecated. After August 2026, `layers: true` will become the permanent
|
|
53
|
+
* default behavior and the `layers` prop will be removed. To maintain vertical layout after removal,
|
|
54
|
+
* use separate individual Progress components.
|
|
48
55
|
*
|
|
49
56
|
* ## Usability and A11y guidelines
|
|
50
57
|
*
|
|
@@ -55,15 +62,19 @@ const selectProgressStyles = ({
|
|
|
55
62
|
*/
|
|
56
63
|
const Progress = React.forwardRef(({ children, tokens, variant, ...rest }, ref) => {
|
|
57
64
|
const themeTokens = useThemeTokens('Progress', tokens, variant)
|
|
65
|
+
// Default to false (vertical layout) to preserve existing behavior and avoid breaking changes
|
|
66
|
+
const layers = variant?.layers ?? false
|
|
58
67
|
|
|
59
68
|
return (
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
<ProgressContext.Provider value={{ layers }}>
|
|
70
|
+
<View
|
|
71
|
+
ref={ref}
|
|
72
|
+
style={[staticStyles.progressContainer, selectProgressStyles(themeTokens)]}
|
|
73
|
+
{...selectProps(rest)}
|
|
74
|
+
>
|
|
75
|
+
{children}
|
|
76
|
+
</View>
|
|
77
|
+
</ProgressContext.Provider>
|
|
67
78
|
)
|
|
68
79
|
})
|
|
69
80
|
Progress.displayName = 'Progress'
|