@telus-uds/components-base 1.95.0 → 1.96.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 +23 -2
- package/lib/Autocomplete/Autocomplete.js +36 -2
- package/lib/Card/CardBase.js +4 -0
- package/lib/List/ListItemBase.js +2 -1
- package/lib/Modal/Modal.js +34 -13
- package/lib/Modal/ModalContent.js +1 -1
- package/lib/Modal/WebModal.js +1 -0
- package/lib/Notification/Notification.js +5 -5
- package/lib/PriceLockup/PriceLockup.js +11 -3
- package/lib/Progress/Progress.js +5 -2
- package/lib/Progress/ProgressBar.js +4 -1
- package/lib/Typography/Typography.js +42 -19
- package/lib/index.js +7 -0
- package/lib-module/Autocomplete/Autocomplete.js +36 -2
- package/lib-module/Card/CardBase.js +4 -0
- package/lib-module/List/ListItemBase.js +2 -1
- package/lib-module/Modal/Modal.js +34 -13
- package/lib-module/Modal/ModalContent.js +1 -1
- package/lib-module/Modal/WebModal.js +1 -0
- package/lib-module/Notification/Notification.js +5 -5
- package/lib-module/PriceLockup/PriceLockup.js +11 -3
- package/lib-module/Progress/Progress.js +6 -3
- package/lib-module/Progress/ProgressBar.js +5 -2
- package/lib-module/Typography/Typography.js +42 -19
- package/lib-module/index.js +1 -1
- package/package.json +2 -2
- package/src/Autocomplete/Autocomplete.jsx +41 -2
- package/src/Card/CardBase.jsx +6 -0
- package/src/List/ListItemBase.jsx +1 -1
- package/src/Modal/Modal.jsx +40 -14
- package/src/Modal/ModalContent.jsx +1 -1
- package/src/Modal/WebModal.jsx +1 -1
- package/src/Notification/Notification.jsx +5 -5
- package/src/PriceLockup/PriceLockup.jsx +9 -1
- package/src/Progress/Progress.jsx +6 -3
- package/src/Progress/ProgressBar.jsx +4 -2
- package/src/Typography/Typography.jsx +37 -13
- package/src/index.js +2 -1
|
@@ -24,6 +24,7 @@ const WebModal = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
24
24
|
children: /*#__PURE__*/_jsx(View, {
|
|
25
25
|
style: staticStyles.container,
|
|
26
26
|
...selectProps(rest),
|
|
27
|
+
focusable: true,
|
|
27
28
|
ref: ref,
|
|
28
29
|
children: /*#__PURE__*/_jsx("div", {
|
|
29
30
|
style: staticStyles.content,
|
|
@@ -99,19 +99,19 @@ const getMediaQueryStyles = (themeTokens, themeOptions, mediaIdsRef, dismissible
|
|
|
99
99
|
justifyContent: 'space-between',
|
|
100
100
|
...createMediaQueryStyles({
|
|
101
101
|
xs: {
|
|
102
|
-
|
|
102
|
+
maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content = themeOptions.contentMaxWidth) === null || _themeOptions$content === void 0 ? void 0 : _themeOptions$content.xs) || '100%'
|
|
103
103
|
},
|
|
104
104
|
md: {
|
|
105
|
-
|
|
105
|
+
maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content2 = themeOptions.contentMaxWidth) === null || _themeOptions$content2 === void 0 ? void 0 : _themeOptions$content2.md) || '100%'
|
|
106
106
|
},
|
|
107
107
|
lg: {
|
|
108
|
-
|
|
108
|
+
maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content3 = themeOptions.contentMaxWidth) === null || _themeOptions$content3 === void 0 ? void 0 : _themeOptions$content3.lg) || '100%'
|
|
109
109
|
},
|
|
110
110
|
sm: {
|
|
111
|
-
|
|
111
|
+
maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content4 = themeOptions.contentMaxWidth) === null || _themeOptions$content4 === void 0 ? void 0 : _themeOptions$content4.sm) || '100%'
|
|
112
112
|
},
|
|
113
113
|
xl: {
|
|
114
|
-
|
|
114
|
+
maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content5 = themeOptions.contentMaxWidth) === null || _themeOptions$content5 === void 0 ? void 0 : _themeOptions$content5.xl) || '100%'
|
|
115
115
|
}
|
|
116
116
|
})
|
|
117
117
|
}
|
|
@@ -87,7 +87,15 @@ const selectBottomTextTypographyTokens = _ref6 => {
|
|
|
87
87
|
lineHeight: bottomTextLineHeight
|
|
88
88
|
};
|
|
89
89
|
};
|
|
90
|
-
const
|
|
90
|
+
const selectContainertokens = _ref7 => {
|
|
91
|
+
let {
|
|
92
|
+
alignItemsText
|
|
93
|
+
} = _ref7;
|
|
94
|
+
return {
|
|
95
|
+
alignItems: alignItemsText
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
const PriceLockup = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
|
|
91
99
|
let {
|
|
92
100
|
size = 'medium',
|
|
93
101
|
signDirection = 'left',
|
|
@@ -104,7 +112,7 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref7, ref) => {
|
|
|
104
112
|
tokens: priceLockupTokens,
|
|
105
113
|
variant = {},
|
|
106
114
|
...rest
|
|
107
|
-
} =
|
|
115
|
+
} = _ref8;
|
|
108
116
|
const viewport = useViewport();
|
|
109
117
|
const {
|
|
110
118
|
footnoteMarginTop,
|
|
@@ -129,7 +137,7 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref7, ref) => {
|
|
|
129
137
|
const topTextTypographyTokens = selectTopTextTypographyTokens(themeTokens);
|
|
130
138
|
const bottomTextTypographyTokens = selectBottomTextTypographyTokens(themeTokens);
|
|
131
139
|
return /*#__PURE__*/_jsxs(View, {
|
|
132
|
-
style: [staticStyles.priceLockupContainer],
|
|
140
|
+
style: [staticStyles.priceLockupContainer, selectContainertokens(themeTokens)],
|
|
133
141
|
ref: ref,
|
|
134
142
|
...selectProps(rest),
|
|
135
143
|
children: [topText ? /*#__PURE__*/_jsx(View, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import View from "react-native-web/dist/exports/View";
|
|
4
|
-
import { useThemeTokens } from '../ThemeProvider';
|
|
4
|
+
import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
|
|
5
5
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
@@ -11,14 +11,16 @@ const selectProgressStyles = _ref => {
|
|
|
11
11
|
borderWidth,
|
|
12
12
|
borderColor,
|
|
13
13
|
borderRadius,
|
|
14
|
-
height
|
|
14
|
+
height,
|
|
15
|
+
shadow
|
|
15
16
|
} = _ref;
|
|
16
17
|
return {
|
|
17
18
|
backgroundColor,
|
|
18
19
|
borderWidth,
|
|
19
20
|
borderColor,
|
|
20
21
|
borderRadius,
|
|
21
|
-
height
|
|
22
|
+
height,
|
|
23
|
+
...applyShadowToken(shadow)
|
|
22
24
|
};
|
|
23
25
|
};
|
|
24
26
|
|
|
@@ -38,6 +40,7 @@ const selectProgressStyles = _ref => {
|
|
|
38
40
|
* - `borderRadius` for the rounded corners,
|
|
39
41
|
* - `borderWidth` to change the border width.
|
|
40
42
|
* - `height` to control the height of the progress bars displayed within the progress bar container.
|
|
43
|
+
* - `shadow` to apply a box shadow to the progress bar container.
|
|
41
44
|
*
|
|
42
45
|
* ## Variants
|
|
43
46
|
*
|
|
@@ -4,7 +4,7 @@ import Platform from "react-native-web/dist/exports/Platform";
|
|
|
4
4
|
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
5
5
|
import View from "react-native-web/dist/exports/View";
|
|
6
6
|
import ProgressBarBackground from './ProgressBarBackground';
|
|
7
|
-
import { useThemeTokens } from '../ThemeProvider';
|
|
7
|
+
import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
|
|
8
8
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
10
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
@@ -13,13 +13,15 @@ const selectBarStyles = (_ref, percentage) => {
|
|
|
13
13
|
backgroundColor,
|
|
14
14
|
borderRadius,
|
|
15
15
|
outlineWidth,
|
|
16
|
-
outlineColor
|
|
16
|
+
outlineColor,
|
|
17
|
+
shadow
|
|
17
18
|
} = _ref;
|
|
18
19
|
return {
|
|
19
20
|
backgroundColor,
|
|
20
21
|
borderRadius,
|
|
21
22
|
outlineWidth,
|
|
22
23
|
outlineColor,
|
|
24
|
+
...applyShadowToken(shadow),
|
|
23
25
|
width: `${percentage}%`
|
|
24
26
|
};
|
|
25
27
|
};
|
|
@@ -39,6 +41,7 @@ const selectBarStyles = (_ref, percentage) => {
|
|
|
39
41
|
* - `borderRadius` for the rounded corners,
|
|
40
42
|
* - `outlineColor` to control the color of the border (outline),
|
|
41
43
|
* - `outlineWidth` to change the outline width.
|
|
44
|
+
* - `shadow` to apply a box shadow to the progress bar.
|
|
42
45
|
*
|
|
43
46
|
* ## Variants
|
|
44
47
|
*
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import Text from "react-native-web/dist/exports/Text";
|
|
4
4
|
import View from "react-native-web/dist/exports/View";
|
|
5
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
5
6
|
import { useResponsiveThemeTokens, useTheme, useThemeTokens } from '../ThemeProvider';
|
|
6
7
|
import { applyTextStyles } from '../ThemeProvider/utils';
|
|
7
8
|
import { a11yProps, variantProp, getTokensPropType, getMaxFontMultiplier, headingTags, selectSystemProps, textTags, textProps, viewProps, getA11yPropsFromHtmlTag, StyleSheet, createMediaQueryStyles } from '../utils';
|
|
@@ -39,9 +40,22 @@ const selectTextStyles = (_ref, themeOptions) => {
|
|
|
39
40
|
gradient
|
|
40
41
|
});
|
|
41
42
|
};
|
|
43
|
+
const HALF_FONT_SIZE = 2;
|
|
44
|
+
const QUARTER_FONT_SIZE = 4;
|
|
45
|
+
const selectMobileSubSupStyles = (_ref2, type) => {
|
|
46
|
+
let {
|
|
47
|
+
fontSize
|
|
48
|
+
} = _ref2;
|
|
49
|
+
return {
|
|
50
|
+
fontSize: fontSize / HALF_FONT_SIZE,
|
|
51
|
+
lineHeight: fontSize,
|
|
52
|
+
position: 'relative',
|
|
53
|
+
top: type === 'sub' ? fontSize / QUARTER_FONT_SIZE : -fontSize / QUARTER_FONT_SIZE
|
|
54
|
+
};
|
|
55
|
+
};
|
|
42
56
|
|
|
43
57
|
// General-purpose flexible theme-neutral base component for text
|
|
44
|
-
const Typography = /*#__PURE__*/React.forwardRef((
|
|
58
|
+
const Typography = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
45
59
|
let {
|
|
46
60
|
children,
|
|
47
61
|
variant,
|
|
@@ -54,7 +68,7 @@ const Typography = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
54
68
|
dataSet,
|
|
55
69
|
strikeThrough = false,
|
|
56
70
|
...rest
|
|
57
|
-
} =
|
|
71
|
+
} = _ref3;
|
|
58
72
|
const viewport = useViewport();
|
|
59
73
|
const {
|
|
60
74
|
themeOptions
|
|
@@ -101,8 +115,8 @@ const Typography = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
101
115
|
let textStyles;
|
|
102
116
|
let mediaIds;
|
|
103
117
|
if (enableMediaQueryStyleSheet) {
|
|
104
|
-
const transformedThemeTokens = Object.entries(themeTokens).reduce((acc,
|
|
105
|
-
let [vp, viewportTokens] =
|
|
118
|
+
const transformedThemeTokens = Object.entries(themeTokens).reduce((acc, _ref4) => {
|
|
119
|
+
let [vp, viewportTokens] = _ref4;
|
|
106
120
|
acc[vp] = selectTextStyles({
|
|
107
121
|
textAlign: align,
|
|
108
122
|
textDecorationLine,
|
|
@@ -136,22 +150,31 @@ const Typography = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
136
150
|
...selectContainerProps(rest)
|
|
137
151
|
};
|
|
138
152
|
const resetTagStyling = child => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize;
|
|
143
|
-
const sanitizedChild = /*#__PURE__*/React.cloneElement(child, {
|
|
144
|
-
style: {
|
|
145
|
-
...childStyles,
|
|
146
|
-
...(supFontSize ? {
|
|
147
|
-
fontSize: supFontSize
|
|
148
|
-
} : {}),
|
|
149
|
-
lineHeight: 0
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
return sanitizedChild;
|
|
153
|
+
var _child$props;
|
|
154
|
+
if (typeof child !== 'object' || !((child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup')) {
|
|
155
|
+
return child;
|
|
153
156
|
}
|
|
154
|
-
|
|
157
|
+
const childStyles = (child === null || child === void 0 ? void 0 : (_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.style) || {};
|
|
158
|
+
const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize;
|
|
159
|
+
const isMobile = Platform.OS === 'ios' || Platform.OS === 'android';
|
|
160
|
+
const isSubSup = (child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup';
|
|
161
|
+
const mobileStyles = isMobile && isSubSup ? selectMobileSubSupStyles(themeTokens, child === null || child === void 0 ? void 0 : child.type) : {};
|
|
162
|
+
const defaultStyles = !isMobile && isSubSup ? {
|
|
163
|
+
fontSize: supFontSize,
|
|
164
|
+
lineHeight: 0
|
|
165
|
+
} : {};
|
|
166
|
+
const sanitizedChild = /*#__PURE__*/React.cloneElement(isMobile && isSubSup ? /*#__PURE__*/_jsx(View, {
|
|
167
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
168
|
+
style: [childStyles, mobileStyles],
|
|
169
|
+
children: child.props.children
|
|
170
|
+
})
|
|
171
|
+
}) : child, {
|
|
172
|
+
style: {
|
|
173
|
+
...childStyles,
|
|
174
|
+
...defaultStyles
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
return sanitizedChild;
|
|
155
178
|
};
|
|
156
179
|
const sanitizeChildren = () => {
|
|
157
180
|
if (Array.isArray(children)) {
|
package/lib-module/index.js
CHANGED
|
@@ -71,6 +71,6 @@ export { default as BaseProvider } from './BaseProvider';
|
|
|
71
71
|
export { useHydrationContext } from './BaseProvider/HydrationContext';
|
|
72
72
|
export { default as Validator } from './Validator';
|
|
73
73
|
export { default as ViewportProvider, useViewport, ViewportContext } from './ViewportProvider';
|
|
74
|
-
export { default as ThemeProvider, useTheme, useSetTheme, useThemeTokens, useThemeTokensCallback, getThemeTokens, applyOuterBorder, applyTextStyles, applyShadowToken } from './ThemeProvider';
|
|
74
|
+
export { default as ThemeProvider, useTheme, useSetTheme, useThemeTokens, useThemeTokensCallback, getThemeTokens, applyOuterBorder, applyTextStyles, applyShadowToken, useResponsiveThemeTokens } from './ThemeProvider';
|
|
75
75
|
export * from './utils';
|
|
76
76
|
export { default as Portal } from './Portal';
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"@floating-ui/react-native": "^0.8.1",
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@telus-uds/system-constants": "^1.3.0",
|
|
14
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
14
|
+
"@telus-uds/system-theme-tokens": "^2.65.0",
|
|
15
15
|
"airbnb-prop-types": "^2.16.0",
|
|
16
16
|
"css-mediaquery": "^0.1.2",
|
|
17
17
|
"expo-linear-gradient": "^12.5.0",
|
|
@@ -86,6 +86,6 @@
|
|
|
86
86
|
"standard-engine": {
|
|
87
87
|
"skip": true
|
|
88
88
|
},
|
|
89
|
-
"version": "1.
|
|
89
|
+
"version": "1.96.0",
|
|
90
90
|
"types": "types/index.d.ts"
|
|
91
91
|
}
|
|
@@ -135,6 +135,8 @@ const Autocomplete = React.forwardRef(
|
|
|
135
135
|
// When it's nested, selected value
|
|
136
136
|
const [nestedSelectedValue, setNestedSelectedValue] = React.useState(null)
|
|
137
137
|
|
|
138
|
+
const [isInputVisible, setIsInputVisible] = React.useState(true)
|
|
139
|
+
|
|
138
140
|
const { supportsProps, ...selectedProps } = selectProps(rest)
|
|
139
141
|
const { hint, label: inputLabel } = supportsProps
|
|
140
142
|
const hintExpansionEnabled = isFocused && helpText && !currentValue
|
|
@@ -244,6 +246,32 @@ const Autocomplete = React.forwardRef(
|
|
|
244
246
|
}
|
|
245
247
|
}, [nestedSelectedValue, items])
|
|
246
248
|
|
|
249
|
+
React.useEffect(() => {
|
|
250
|
+
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
251
|
+
return undefined
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const observer = new IntersectionObserver((entries) => {
|
|
255
|
+
const [entry] = entries
|
|
256
|
+
setIsInputVisible(entry.isIntersecting)
|
|
257
|
+
if (!entry.isIntersecting) {
|
|
258
|
+
setIsExpanded(false)
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
const currentInputRef = inputRef.current
|
|
263
|
+
|
|
264
|
+
if (currentInputRef) {
|
|
265
|
+
observer.observe(currentInputRef)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return () => {
|
|
269
|
+
if (currentInputRef) {
|
|
270
|
+
observer.unobserve(currentInputRef)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}, [inputRef])
|
|
274
|
+
|
|
247
275
|
const handleClose = (event) => {
|
|
248
276
|
if (
|
|
249
277
|
(event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) ||
|
|
@@ -313,7 +341,18 @@ const Autocomplete = React.forwardRef(
|
|
|
313
341
|
readOnly={readOnly}
|
|
314
342
|
ref={inputRef}
|
|
315
343
|
{...(Platform.OS !== 'web'
|
|
316
|
-
? {
|
|
344
|
+
? {
|
|
345
|
+
onLayout: (event) => {
|
|
346
|
+
setSourceLayout(event.nativeEvent.layout)
|
|
347
|
+
const { y, height } = event.nativeEvent.layout
|
|
348
|
+
if (y >= 0 && height > 0) {
|
|
349
|
+
setIsInputVisible(true)
|
|
350
|
+
} else {
|
|
351
|
+
setIsInputVisible(false)
|
|
352
|
+
setIsExpanded(false)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
317
356
|
: {})}
|
|
318
357
|
tokens={inputTokens}
|
|
319
358
|
validation={validation}
|
|
@@ -324,7 +363,7 @@ const Autocomplete = React.forwardRef(
|
|
|
324
363
|
)
|
|
325
364
|
}}
|
|
326
365
|
</InputSupports>
|
|
327
|
-
{(isExpanded || hintExpansionEnabled) && (
|
|
366
|
+
{(isExpanded || hintExpansionEnabled) && isInputVisible && (
|
|
328
367
|
<>
|
|
329
368
|
<Listbox.Overlay
|
|
330
369
|
overlaidPosition={overlaidPosition}
|
package/src/Card/CardBase.jsx
CHANGED
|
@@ -21,6 +21,7 @@ const selectStyles = ({
|
|
|
21
21
|
paddingTop,
|
|
22
22
|
minWidth,
|
|
23
23
|
shadow,
|
|
24
|
+
backgroundGradient,
|
|
24
25
|
gradient
|
|
25
26
|
}) => {
|
|
26
27
|
return {
|
|
@@ -42,6 +43,11 @@ const selectStyles = ({
|
|
|
42
43
|
boxShadow: `inset 0 1000px white`,
|
|
43
44
|
border: `${borderWidth}px solid transparent`
|
|
44
45
|
}
|
|
46
|
+
: {}),
|
|
47
|
+
...(backgroundGradient && Platform.OS === 'web'
|
|
48
|
+
? {
|
|
49
|
+
backgroundImage: `linear-gradient(${backgroundGradient.angle}deg, ${backgroundGradient.stops[0].color}, ${backgroundGradient.stops[1].color})`
|
|
50
|
+
}
|
|
45
51
|
: {})
|
|
46
52
|
}
|
|
47
53
|
}
|
|
@@ -107,7 +107,7 @@ const staticStyles = StyleSheet.create({
|
|
|
107
107
|
flex: 1,
|
|
108
108
|
flexDirection: 'row'
|
|
109
109
|
},
|
|
110
|
-
titleAndContentContainer: { flexDirection: 'column', flexShrink: 1 }
|
|
110
|
+
titleAndContentContainer: { flexDirection: 'column', flexShrink: 1, flexGrow: 1 }
|
|
111
111
|
})
|
|
112
112
|
|
|
113
113
|
ListItemBase.propTypes = {
|
package/src/Modal/Modal.jsx
CHANGED
|
@@ -121,6 +121,8 @@ const Modal = React.forwardRef(
|
|
|
121
121
|
const viewport = useViewport()
|
|
122
122
|
const themeTokens = useThemeTokens('Modal', tokens, variant, { viewport, maxWidth })
|
|
123
123
|
const modalRef = useScrollBlocking(isOpen)
|
|
124
|
+
const modalBodyRef = React.useRef(ref)
|
|
125
|
+
const modalContentRef = React.useRef(null)
|
|
124
126
|
|
|
125
127
|
const { closeIcon: CloseIconComponent } = themeTokens
|
|
126
128
|
|
|
@@ -135,6 +137,32 @@ const Modal = React.forwardRef(
|
|
|
135
137
|
if (event.key === 'Escape') onClose()
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
const manageFocus = React.useCallback(
|
|
141
|
+
(event) => {
|
|
142
|
+
if (event.key === 'Tab') {
|
|
143
|
+
const focusableElements = Array.from(
|
|
144
|
+
modalBodyRef?.current?.querySelectorAll(`
|
|
145
|
+
a[href], button, textarea, input, select,
|
|
146
|
+
[tabindex]:not([tabindex="-1"]),
|
|
147
|
+
[contenteditable="true"]
|
|
148
|
+
`)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
const firstElement = focusableElements[0]
|
|
152
|
+
const lastElement = focusableElements[focusableElements.length - 1]
|
|
153
|
+
|
|
154
|
+
if (event.shiftKey && document.activeElement === firstElement) {
|
|
155
|
+
event.preventDefault()
|
|
156
|
+
lastElement.focus()
|
|
157
|
+
} else if (!event.shiftKey && document.activeElement === lastElement) {
|
|
158
|
+
event.preventDefault()
|
|
159
|
+
firstElement.focus()
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
[modalBodyRef]
|
|
164
|
+
)
|
|
165
|
+
|
|
138
166
|
// Show the custom react node passed to `closedButton` or the default close button if `closeButton` is `undefined`.
|
|
139
167
|
// Hide the close button if `closeButton` is `null`.
|
|
140
168
|
const showCloseButton = closeButton !== null
|
|
@@ -145,22 +173,20 @@ const Modal = React.forwardRef(
|
|
|
145
173
|
|
|
146
174
|
React.useEffect(() => {
|
|
147
175
|
if (Platform.OS === 'web') {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (document.activeElement === focusTrapRef.current && closeButtonRef.current) {
|
|
151
|
-
closeButtonRef.current.focus()
|
|
152
|
-
}
|
|
153
|
-
return undefined
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Add an event listener to manage focus in the web modal container
|
|
157
|
-
document.addEventListener('focusin', handleFocus)
|
|
176
|
+
// Add an event listener to manage keydown and focus in the web modal container
|
|
177
|
+
document.addEventListener('keydown', manageFocus)
|
|
158
178
|
|
|
159
179
|
// Clean up the event listener
|
|
160
|
-
return () => document.removeEventListener('
|
|
180
|
+
return () => document.removeEventListener('keydown', manageFocus)
|
|
161
181
|
}
|
|
162
182
|
return undefined
|
|
163
|
-
}, [])
|
|
183
|
+
}, [manageFocus])
|
|
184
|
+
|
|
185
|
+
React.useEffect(() => {
|
|
186
|
+
if (isOpen) {
|
|
187
|
+
modalContentRef?.current?.focus()
|
|
188
|
+
}
|
|
189
|
+
}, [isOpen, modalContentRef?.current?.focus])
|
|
164
190
|
|
|
165
191
|
if (!isOpen) {
|
|
166
192
|
return null
|
|
@@ -174,7 +200,7 @@ const Modal = React.forwardRef(
|
|
|
174
200
|
pointerEvents="box-none" // don't capture backdrop press events
|
|
175
201
|
>
|
|
176
202
|
<View
|
|
177
|
-
ref={
|
|
203
|
+
ref={modalBodyRef}
|
|
178
204
|
style={[staticStyles.modal, selectModalStyles(themeTokens)]}
|
|
179
205
|
onKeyUp={handleKeyUp}
|
|
180
206
|
>
|
|
@@ -230,7 +256,7 @@ const Modal = React.forwardRef(
|
|
|
230
256
|
|
|
231
257
|
if (Platform.OS === 'web') {
|
|
232
258
|
return (
|
|
233
|
-
<WebModal {...selectProps(rest)}>
|
|
259
|
+
<WebModal {...selectProps(rest)} ref={modalContentRef}>
|
|
234
260
|
{content}
|
|
235
261
|
<View accessibilityRole="button" ref={focusTrapRef} />
|
|
236
262
|
</WebModal>
|
package/src/Modal/WebModal.jsx
CHANGED
|
@@ -17,7 +17,7 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
17
17
|
const WebModal = React.forwardRef(({ children, ...rest }, ref) => {
|
|
18
18
|
return (
|
|
19
19
|
<Portal>
|
|
20
|
-
<View style={staticStyles.container} {...selectProps(rest)} ref={ref}>
|
|
20
|
+
<View style={staticStyles.container} {...selectProps(rest)} focusable={true} ref={ref}>
|
|
21
21
|
<div style={staticStyles.content} role="dialog" aria-modal={true}>
|
|
22
22
|
{children}
|
|
23
23
|
</div>
|
|
@@ -102,11 +102,11 @@ const getMediaQueryStyles = (
|
|
|
102
102
|
flexShrink: 1,
|
|
103
103
|
justifyContent: 'space-between',
|
|
104
104
|
...createMediaQueryStyles({
|
|
105
|
-
xs: {
|
|
106
|
-
md: {
|
|
107
|
-
lg: {
|
|
108
|
-
sm: {
|
|
109
|
-
xl: {
|
|
105
|
+
xs: { maxWidth: themeOptions?.contentMaxWidth?.xs || '100%' },
|
|
106
|
+
md: { maxWidth: themeOptions?.contentMaxWidth?.md || '100%' },
|
|
107
|
+
lg: { maxWidth: themeOptions?.contentMaxWidth?.lg || '100%' },
|
|
108
|
+
sm: { maxWidth: themeOptions?.contentMaxWidth?.sm || '100%' },
|
|
109
|
+
xl: { maxWidth: themeOptions?.contentMaxWidth?.xl || '100%' }
|
|
110
110
|
})
|
|
111
111
|
}
|
|
112
112
|
})
|
|
@@ -61,6 +61,10 @@ const selectBottomTextTypographyTokens = ({ bottomTextFontSize, bottomTextLineHe
|
|
|
61
61
|
lineHeight: bottomTextLineHeight
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
+
const selectContainertokens = ({ alignItemsText }) => ({
|
|
65
|
+
alignItems: alignItemsText
|
|
66
|
+
})
|
|
67
|
+
|
|
64
68
|
const PriceLockup = React.forwardRef(
|
|
65
69
|
(
|
|
66
70
|
{
|
|
@@ -106,7 +110,11 @@ const PriceLockup = React.forwardRef(
|
|
|
106
110
|
const bottomTextTypographyTokens = selectBottomTextTypographyTokens(themeTokens)
|
|
107
111
|
|
|
108
112
|
return (
|
|
109
|
-
<View
|
|
113
|
+
<View
|
|
114
|
+
style={[staticStyles.priceLockupContainer, selectContainertokens(themeTokens)]}
|
|
115
|
+
ref={ref}
|
|
116
|
+
{...selectProps(rest)}
|
|
117
|
+
>
|
|
110
118
|
{topText ? (
|
|
111
119
|
<View style={staticStyles.topText}>
|
|
112
120
|
{renderTypography(topText, topTextTypographyTokens)}
|
|
@@ -2,7 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { View } from 'react-native'
|
|
4
4
|
|
|
5
|
-
import { useThemeTokens } from '../ThemeProvider'
|
|
5
|
+
import { applyShadowToken, useThemeTokens } from '../ThemeProvider'
|
|
6
6
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
7
7
|
|
|
8
8
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
@@ -12,13 +12,15 @@ const selectProgressStyles = ({
|
|
|
12
12
|
borderWidth,
|
|
13
13
|
borderColor,
|
|
14
14
|
borderRadius,
|
|
15
|
-
height
|
|
15
|
+
height,
|
|
16
|
+
shadow
|
|
16
17
|
}) => ({
|
|
17
18
|
backgroundColor,
|
|
18
19
|
borderWidth,
|
|
19
20
|
borderColor,
|
|
20
21
|
borderRadius,
|
|
21
|
-
height
|
|
22
|
+
height,
|
|
23
|
+
...applyShadowToken(shadow)
|
|
22
24
|
})
|
|
23
25
|
|
|
24
26
|
/**
|
|
@@ -37,6 +39,7 @@ const selectProgressStyles = ({
|
|
|
37
39
|
* - `borderRadius` for the rounded corners,
|
|
38
40
|
* - `borderWidth` to change the border width.
|
|
39
41
|
* - `height` to control the height of the progress bars displayed within the progress bar container.
|
|
42
|
+
* - `shadow` to apply a box shadow to the progress bar container.
|
|
40
43
|
*
|
|
41
44
|
* ## Variants
|
|
42
45
|
*
|
|
@@ -3,19 +3,20 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
import { Platform, StyleSheet, View } from 'react-native'
|
|
4
4
|
|
|
5
5
|
import ProgressBarBackground from './ProgressBarBackground'
|
|
6
|
-
import { useThemeTokens } from '../ThemeProvider'
|
|
6
|
+
import { applyShadowToken, useThemeTokens } from '../ThemeProvider'
|
|
7
7
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
8
8
|
|
|
9
9
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
10
10
|
|
|
11
11
|
const selectBarStyles = (
|
|
12
|
-
{ backgroundColor, borderRadius, outlineWidth, outlineColor },
|
|
12
|
+
{ backgroundColor, borderRadius, outlineWidth, outlineColor, shadow },
|
|
13
13
|
percentage
|
|
14
14
|
) => ({
|
|
15
15
|
backgroundColor,
|
|
16
16
|
borderRadius,
|
|
17
17
|
outlineWidth,
|
|
18
18
|
outlineColor,
|
|
19
|
+
...applyShadowToken(shadow),
|
|
19
20
|
width: `${percentage}%`
|
|
20
21
|
})
|
|
21
22
|
|
|
@@ -34,6 +35,7 @@ const selectBarStyles = (
|
|
|
34
35
|
* - `borderRadius` for the rounded corners,
|
|
35
36
|
* - `outlineColor` to control the color of the border (outline),
|
|
36
37
|
* - `outlineWidth` to change the outline width.
|
|
38
|
+
* - `shadow` to apply a box shadow to the progress bar.
|
|
37
39
|
*
|
|
38
40
|
* ## Variants
|
|
39
41
|
*
|