@telus-uds/components-base 3.7.1 → 3.9.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/lib/cjs/ActivityIndicator/FullScreenIndicator.js +89 -0
- package/lib/cjs/ActivityIndicator/InlineIndicator.js +64 -0
- package/lib/cjs/ActivityIndicator/OverlayIndicator.js +156 -0
- package/lib/cjs/ActivityIndicator/RenderActivityIndicator.js +88 -0
- package/lib/cjs/ActivityIndicator/index.js +91 -23
- package/lib/cjs/ActivityIndicator/shared.js +12 -1
- package/lib/cjs/ActivityIndicator/sharedProptypes.js +67 -0
- package/lib/cjs/Card/Card.js +38 -45
- package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +1 -1
- package/lib/cjs/List/ListItemMark.js +13 -2
- package/lib/cjs/MultiSelectFilter/ModalOverlay.js +19 -5
- package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +22 -9
- package/lib/cjs/ToggleSwitch/ToggleSwitch.js +13 -2
- package/lib/cjs/Validator/Validator.js +135 -64
- package/lib/cjs/utils/index.js +9 -1
- package/lib/cjs/utils/useDetectOutsideClick.js +39 -0
- package/lib/cjs/utils/useVariants.js +46 -0
- package/lib/esm/ActivityIndicator/FullScreenIndicator.js +82 -0
- package/lib/esm/ActivityIndicator/InlineIndicator.js +57 -0
- package/lib/esm/ActivityIndicator/OverlayIndicator.js +149 -0
- package/lib/esm/ActivityIndicator/RenderActivityIndicator.js +83 -0
- package/lib/esm/ActivityIndicator/index.js +89 -23
- package/lib/esm/ActivityIndicator/shared.js +11 -0
- package/lib/esm/ActivityIndicator/sharedProptypes.js +61 -0
- package/lib/esm/Card/Card.js +38 -45
- package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +1 -1
- package/lib/esm/List/ListItemMark.js +13 -2
- package/lib/esm/MultiSelectFilter/ModalOverlay.js +19 -5
- package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +22 -9
- package/lib/esm/ToggleSwitch/ToggleSwitch.js +13 -2
- package/lib/esm/Validator/Validator.js +135 -64
- package/lib/esm/utils/index.js +2 -1
- package/lib/esm/utils/useDetectOutsideClick.js +31 -0
- package/lib/esm/utils/useVariants.js +41 -0
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/ActivityIndicator/FullScreenIndicator.jsx +65 -0
- package/src/ActivityIndicator/InlineIndicator.jsx +47 -0
- package/src/ActivityIndicator/OverlayIndicator.jsx +140 -0
- package/src/ActivityIndicator/RenderActivityIndicator.jsx +82 -0
- package/src/ActivityIndicator/index.jsx +113 -32
- package/src/ActivityIndicator/shared.js +11 -0
- package/src/ActivityIndicator/sharedProptypes.js +62 -0
- package/src/Card/Card.jsx +51 -54
- package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +1 -1
- package/src/List/ListItemMark.jsx +18 -2
- package/src/MultiSelectFilter/ModalOverlay.jsx +18 -5
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +21 -10
- package/src/ToggleSwitch/ToggleSwitch.jsx +17 -2
- package/src/Validator/Validator.jsx +172 -85
- package/src/utils/index.js +1 -0
- package/src/utils/useDetectOutsideClick.js +35 -0
- package/src/utils/useVariants.js +44 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import Spinner from './Spinner'
|
|
4
|
+
import Dots from './Dots'
|
|
5
|
+
import { DOTS_STYLE } from './shared'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Return <Dots/> or <Spinner/> based on `variant?.dots`.
|
|
9
|
+
* Reused in all the variants of the component.
|
|
10
|
+
*/
|
|
11
|
+
const RenderActivityIndicator = React.forwardRef(
|
|
12
|
+
(
|
|
13
|
+
{ variant = {}, dotSize, size, color, indicatorBackgroundColor, thickness, label, isStatic },
|
|
14
|
+
ref
|
|
15
|
+
) => {
|
|
16
|
+
const { dots, style } = variant || {}
|
|
17
|
+
const isDots = dots === true || style === DOTS_STYLE
|
|
18
|
+
|
|
19
|
+
return isDots ? (
|
|
20
|
+
<Dots
|
|
21
|
+
ref={ref}
|
|
22
|
+
size={dotSize}
|
|
23
|
+
color={color}
|
|
24
|
+
indicatorBackgroundColor={indicatorBackgroundColor}
|
|
25
|
+
label={label}
|
|
26
|
+
isStatic={isStatic}
|
|
27
|
+
/>
|
|
28
|
+
) : (
|
|
29
|
+
<Spinner
|
|
30
|
+
ref={ref}
|
|
31
|
+
size={size}
|
|
32
|
+
color={color}
|
|
33
|
+
indicatorBackgroundColor={indicatorBackgroundColor}
|
|
34
|
+
thickness={thickness}
|
|
35
|
+
label={label}
|
|
36
|
+
isStatic={isStatic}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
RenderActivityIndicator.displayName = 'RenderActivityIndicator'
|
|
43
|
+
|
|
44
|
+
RenderActivityIndicator.propTypes = {
|
|
45
|
+
/**
|
|
46
|
+
* ActivityIndicator variants
|
|
47
|
+
* */
|
|
48
|
+
variant: PropTypes.shape({
|
|
49
|
+
dots: PropTypes.bool,
|
|
50
|
+
style: PropTypes.oneOf([DOTS_STYLE])
|
|
51
|
+
}),
|
|
52
|
+
/**
|
|
53
|
+
* Size of the dots
|
|
54
|
+
* */
|
|
55
|
+
dotSize: PropTypes.number,
|
|
56
|
+
/**
|
|
57
|
+
* Size of the spinner
|
|
58
|
+
* */
|
|
59
|
+
size: PropTypes.number,
|
|
60
|
+
/**
|
|
61
|
+
* Primary color
|
|
62
|
+
* */
|
|
63
|
+
color: PropTypes.string,
|
|
64
|
+
/**
|
|
65
|
+
* Secondary color (background) of the indicator
|
|
66
|
+
* */
|
|
67
|
+
indicatorBackgroundColor: PropTypes.string,
|
|
68
|
+
/**
|
|
69
|
+
* Thickness of the indicator
|
|
70
|
+
* */
|
|
71
|
+
thickness: PropTypes.number,
|
|
72
|
+
/**
|
|
73
|
+
* Label for the ActivityIndicator
|
|
74
|
+
* */
|
|
75
|
+
label: PropTypes.string,
|
|
76
|
+
/**
|
|
77
|
+
* if true, there's no animation for ActivityIndicator
|
|
78
|
+
* */
|
|
79
|
+
isStatic: PropTypes.bool
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default RenderActivityIndicator
|
|
@@ -1,42 +1,95 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
+
import { Platform } from 'react-native'
|
|
4
|
+
import { useScrollBlocking } from '../utils'
|
|
3
5
|
import { useThemeTokens } from '../ThemeProvider'
|
|
4
6
|
import { getTokensPropType, variantProp } from '../utils/props'
|
|
5
7
|
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
+
import FullScreenIndicator from './FullScreenIndicator'
|
|
9
|
+
import OverlayIndicator from './OverlayIndicator'
|
|
10
|
+
import InlineIndicator from './InlineIndicator'
|
|
11
|
+
|
|
12
|
+
const labelMapping = {
|
|
13
|
+
top: 'column-reverse',
|
|
14
|
+
bottom: 'column',
|
|
15
|
+
left: 'row-reverse',
|
|
16
|
+
right: 'row'
|
|
17
|
+
}
|
|
8
18
|
|
|
9
19
|
/**
|
|
10
20
|
* `ActivityIndicator` renders a visual loading state.
|
|
11
21
|
* It does not handle positioning or layout of that visual loader.
|
|
12
22
|
*/
|
|
13
|
-
const ActivityIndicator = React.forwardRef(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
size
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
const ActivityIndicator = React.forwardRef(
|
|
24
|
+
(
|
|
25
|
+
{
|
|
26
|
+
variant,
|
|
27
|
+
tokens,
|
|
28
|
+
label,
|
|
29
|
+
labelPosition = 'bottom',
|
|
30
|
+
showLabel = true,
|
|
31
|
+
inline = false,
|
|
32
|
+
fullScreen = false,
|
|
33
|
+
overlay = false,
|
|
34
|
+
isStatic = false,
|
|
35
|
+
children,
|
|
36
|
+
fullScreenBackgroundColor
|
|
37
|
+
},
|
|
38
|
+
ref
|
|
39
|
+
) => {
|
|
40
|
+
const {
|
|
41
|
+
size,
|
|
42
|
+
dotSize,
|
|
43
|
+
color,
|
|
44
|
+
indicatorBackgroundColor,
|
|
45
|
+
fullScreenOverlayBackground,
|
|
46
|
+
thickness
|
|
47
|
+
} = useThemeTokens('ActivityIndicator', tokens, variant)
|
|
48
|
+
|
|
49
|
+
useScrollBlocking([Platform.OS === 'web' && fullScreen])
|
|
50
|
+
|
|
51
|
+
const variantProps = {
|
|
52
|
+
variant,
|
|
53
|
+
dotSize,
|
|
54
|
+
size,
|
|
55
|
+
color,
|
|
56
|
+
indicatorBackgroundColor,
|
|
57
|
+
thickness,
|
|
58
|
+
isStatic
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const visibleLabel = showLabel && !!label
|
|
62
|
+
|
|
63
|
+
const commonProps = {
|
|
64
|
+
ref,
|
|
65
|
+
variantProps,
|
|
66
|
+
label,
|
|
67
|
+
labelPosition,
|
|
68
|
+
labelMapping,
|
|
69
|
+
showLabel: visibleLabel
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
switch (true) {
|
|
73
|
+
case fullScreen:
|
|
74
|
+
return (
|
|
75
|
+
<FullScreenIndicator
|
|
76
|
+
{...commonProps}
|
|
77
|
+
backgroundColor={fullScreenBackgroundColor || fullScreenOverlayBackground}
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
case overlay:
|
|
82
|
+
return (
|
|
83
|
+
<OverlayIndicator {...commonProps} inline={inline} isActive={overlay}>
|
|
84
|
+
{children}
|
|
85
|
+
</OverlayIndicator>
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
default:
|
|
89
|
+
return <InlineIndicator {...commonProps} />
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
)
|
|
40
93
|
|
|
41
94
|
ActivityIndicator.displayName = 'ActivityIndicator'
|
|
42
95
|
|
|
@@ -46,11 +99,39 @@ ActivityIndicator.propTypes = {
|
|
|
46
99
|
/**
|
|
47
100
|
* A visually hidden accessible label describing the action taking place
|
|
48
101
|
*/
|
|
49
|
-
label: PropTypes.string
|
|
102
|
+
label: PropTypes.string,
|
|
103
|
+
/**
|
|
104
|
+
* If true, it should render a static ActivityIndicator
|
|
105
|
+
*/
|
|
106
|
+
isStatic: PropTypes.bool,
|
|
107
|
+
/**
|
|
108
|
+
* Position of the label relative to ActivityIndicator
|
|
109
|
+
*/
|
|
110
|
+
labelPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
|
111
|
+
/**
|
|
112
|
+
* show or hide the label
|
|
113
|
+
*/
|
|
114
|
+
showLabel: PropTypes.bool,
|
|
115
|
+
/**
|
|
116
|
+
* If true, the ActivityIndicator will be displayed in full screen mode
|
|
117
|
+
*/
|
|
118
|
+
fullScreen: PropTypes.bool,
|
|
119
|
+
/**
|
|
120
|
+
* If true, the ActivityIndicator will be displayed inline
|
|
121
|
+
*/
|
|
122
|
+
inline: PropTypes.bool,
|
|
123
|
+
/**
|
|
124
|
+
* If true, the ActivityIndicator will be displayed in overlay mode
|
|
125
|
+
*/
|
|
126
|
+
overlay: PropTypes.bool,
|
|
127
|
+
/**
|
|
128
|
+
* Children to be rendered inside ActivityIndicator
|
|
129
|
+
*/
|
|
130
|
+
children: PropTypes.node,
|
|
50
131
|
/**
|
|
51
|
-
*
|
|
132
|
+
* Background color of the full screen overlay
|
|
52
133
|
*/
|
|
53
|
-
|
|
134
|
+
fullScreenBackgroundColor: PropTypes.string
|
|
54
135
|
}
|
|
55
136
|
|
|
56
137
|
export default ActivityIndicator
|
|
@@ -51,6 +51,17 @@ export const DOT1_ANIMATION_INPUT_RANGE = [0, 0.1, 0.2, 1]
|
|
|
51
51
|
export const DOT2_ANIMATION_INPUT_RANGE = [0, 0.3, 0.4, 0.5, 1]
|
|
52
52
|
export const DOT3_ANIMATION_INPUT_RANGE = [0, 0.6, 0.7, 0.8, 1]
|
|
53
53
|
|
|
54
|
+
// Backdrop
|
|
55
|
+
export const BACKDROP_OPACITY = 0.06
|
|
56
|
+
export const BACKDROP_Z_INDEX = 1400
|
|
57
|
+
|
|
58
|
+
// Space
|
|
59
|
+
export const SPACE_WITH_LABEL = 3
|
|
60
|
+
export const SPACE_WITHOUT_LABEL = 0
|
|
61
|
+
|
|
62
|
+
// Style
|
|
63
|
+
export const DOTS_STYLE = 'dots'
|
|
64
|
+
|
|
54
65
|
export const propTypes = {
|
|
55
66
|
color: PropTypes.string.isRequired,
|
|
56
67
|
baseColor: PropTypes.string,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PropTypes for the 3 variants of the ActivityIndicator:
|
|
5
|
+
* - InlineIndicator
|
|
6
|
+
* - OverlayIndicator
|
|
7
|
+
* - FullScreenIndicator
|
|
8
|
+
*/
|
|
9
|
+
export const activityIndicatorVariantProps = PropTypes.shape({
|
|
10
|
+
/**
|
|
11
|
+
* Indicates the variant style for the ActivityIndicator
|
|
12
|
+
* */
|
|
13
|
+
variant: PropTypes.object,
|
|
14
|
+
/**
|
|
15
|
+
* Size of the dots
|
|
16
|
+
* */
|
|
17
|
+
dotSize: PropTypes.number,
|
|
18
|
+
/**
|
|
19
|
+
* Size of the ActivityIndicator Spinner
|
|
20
|
+
* */
|
|
21
|
+
size: PropTypes.number,
|
|
22
|
+
/**
|
|
23
|
+
* Primary color (Spinner)
|
|
24
|
+
* */
|
|
25
|
+
color: PropTypes.string,
|
|
26
|
+
/**
|
|
27
|
+
* Secondary color (background) of the indicator
|
|
28
|
+
* */
|
|
29
|
+
indicatorBackgroundColor: PropTypes.string,
|
|
30
|
+
/**
|
|
31
|
+
* Thickness of the ActivityIndicator Spinner
|
|
32
|
+
* */
|
|
33
|
+
thickness: PropTypes.number,
|
|
34
|
+
/**
|
|
35
|
+
* Indicates if the ActivityIndicator is static
|
|
36
|
+
* (not animated)
|
|
37
|
+
* */
|
|
38
|
+
isStatic: PropTypes.bool
|
|
39
|
+
}).isRequired
|
|
40
|
+
|
|
41
|
+
export const activityIndicatorCommonProps = {
|
|
42
|
+
/**
|
|
43
|
+
* Props used by RenderActivityIndicator
|
|
44
|
+
* */
|
|
45
|
+
variantProps: activityIndicatorVariantProps,
|
|
46
|
+
/**
|
|
47
|
+
* Shows or hide the label
|
|
48
|
+
* */
|
|
49
|
+
showLabel: PropTypes.bool,
|
|
50
|
+
/**
|
|
51
|
+
* A visually hidden accessible label describing the action taking place
|
|
52
|
+
*/
|
|
53
|
+
label: PropTypes.string,
|
|
54
|
+
/**
|
|
55
|
+
* Position of the label relative to ActivityIndicator
|
|
56
|
+
*/
|
|
57
|
+
labelPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
|
58
|
+
/**
|
|
59
|
+
* Map of flex-direction position for label
|
|
60
|
+
* */
|
|
61
|
+
labelMapping: PropTypes.object.isRequired
|
|
62
|
+
}
|
package/src/Card/Card.jsx
CHANGED
|
@@ -128,6 +128,7 @@ const Card = React.forwardRef(
|
|
|
128
128
|
const selected = interactiveCard?.variant?.selected
|
|
129
129
|
const inactive = interactiveCard?.variant?.inactive
|
|
130
130
|
const selectionType = interactiveCard?.selectionType
|
|
131
|
+
const isControl = interactiveCard?.variant?.isControl === true
|
|
131
132
|
|
|
132
133
|
const getThemeTokens = useThemeTokensCallback('Card', interactiveCard?.tokens, {
|
|
133
134
|
interactive: true,
|
|
@@ -196,6 +197,10 @@ const Card = React.forwardRef(
|
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
const renderInputPerSelectionType = (props) => {
|
|
200
|
+
if (!isControl) {
|
|
201
|
+
return null
|
|
202
|
+
}
|
|
203
|
+
|
|
199
204
|
switch (selectionType) {
|
|
200
205
|
case SelectionType.Checkbox:
|
|
201
206
|
return (
|
|
@@ -214,10 +219,6 @@ const Card = React.forwardRef(
|
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
|
|
217
|
-
const renderNoSelectionView = () => (
|
|
218
|
-
<View style={{ paddingTop, paddingBottom, paddingLeft, paddingRight }}>{children}</View>
|
|
219
|
-
)
|
|
220
|
-
|
|
221
222
|
return (
|
|
222
223
|
<>
|
|
223
224
|
<CardBase
|
|
@@ -227,57 +228,53 @@ const Card = React.forwardRef(
|
|
|
227
228
|
dataSet={mediaIds && { media: mediaIds }}
|
|
228
229
|
{...selectProps(rest)}
|
|
229
230
|
>
|
|
230
|
-
{interactiveCard?.body
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
{
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
</PressableCardBase>
|
|
276
|
-
{children && selectionType !== SelectionType.None ? renderNoSelectionView() : null}
|
|
277
|
-
</>
|
|
278
|
-
) : (
|
|
279
|
-
children
|
|
231
|
+
{interactiveCard?.body && (
|
|
232
|
+
<PressableCardBase
|
|
233
|
+
ref={ref}
|
|
234
|
+
tokens={getThemeTokens}
|
|
235
|
+
dataSet={dataSet}
|
|
236
|
+
onPress={onPress}
|
|
237
|
+
href={interactiveCard?.href}
|
|
238
|
+
hrefAttrs={interactiveCard?.hrefAttrs}
|
|
239
|
+
{...selectProps(rest)}
|
|
240
|
+
>
|
|
241
|
+
{(cardState) => {
|
|
242
|
+
const {
|
|
243
|
+
iconColor: checkColor,
|
|
244
|
+
inputBackgroundColor: boxBackgroundColor,
|
|
245
|
+
iconBackgroundColor: checkBackgroundColor
|
|
246
|
+
} = getThemeTokens(
|
|
247
|
+
{
|
|
248
|
+
...cardState,
|
|
249
|
+
selected,
|
|
250
|
+
interactive: true,
|
|
251
|
+
isControl
|
|
252
|
+
},
|
|
253
|
+
interactiveCard?.tokens
|
|
254
|
+
)
|
|
255
|
+
return (
|
|
256
|
+
<>
|
|
257
|
+
{renderInputPerSelectionType(
|
|
258
|
+
getInputProps({
|
|
259
|
+
id,
|
|
260
|
+
checkColor,
|
|
261
|
+
boxBackgroundColor,
|
|
262
|
+
checkBackgroundColor,
|
|
263
|
+
isControlled: true,
|
|
264
|
+
isChecked: selected || cardState?.hover,
|
|
265
|
+
isInactive: inactive,
|
|
266
|
+
onPress
|
|
267
|
+
})
|
|
268
|
+
)}
|
|
269
|
+
{typeof interactiveCard?.body === 'function'
|
|
270
|
+
? interactiveCard.body(cardState)
|
|
271
|
+
: interactiveCard.body}
|
|
272
|
+
</>
|
|
273
|
+
)
|
|
274
|
+
}}
|
|
275
|
+
</PressableCardBase>
|
|
280
276
|
)}
|
|
277
|
+
{children}
|
|
281
278
|
</CardBase>
|
|
282
279
|
</>
|
|
283
280
|
)
|
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
|
|
4
4
|
import { View, StyleSheet } from 'react-native'
|
|
5
5
|
import Icon from '../Icon'
|
|
6
|
+
import { useVariants } from '../utils'
|
|
6
7
|
|
|
7
8
|
export const tokenTypes = {
|
|
8
9
|
itemIconSize: PropTypes.number.isRequired,
|
|
@@ -37,6 +38,9 @@ const selectBulletContainerStyles = ({
|
|
|
37
38
|
alignItems: itemBulletContainerAlign
|
|
38
39
|
})
|
|
39
40
|
|
|
41
|
+
const getIconColorVariants = (iconVariants) =>
|
|
42
|
+
iconVariants?.filter((variant) => variant[0] === 'color').map((variant) => variant[1])
|
|
43
|
+
|
|
40
44
|
/**
|
|
41
45
|
* Subcomponent used within ListItem and similar components for rendering bullets or icons
|
|
42
46
|
* that sit alongside a ListIconContent in a { flexDirection: row } container.
|
|
@@ -50,14 +54,26 @@ const ListItemMark = React.forwardRef(({ icon, iconColor, iconSize, tokens = {}
|
|
|
50
54
|
const sideItemContainerStyles = selectSideItemContainerStyles(themeTokens)
|
|
51
55
|
const bulletContainerStyles = selectBulletContainerStyles(themeTokens)
|
|
52
56
|
|
|
57
|
+
// TODO: Remove it when iconColor custom colors are deprecated.
|
|
58
|
+
const iconVariants = useVariants('Icon')
|
|
59
|
+
const iconColorVariants = getIconColorVariants(iconVariants)
|
|
60
|
+
|
|
53
61
|
if (icon) {
|
|
54
62
|
const iconTokens = selectItemIconTokens(themeTokens)
|
|
55
63
|
return (
|
|
56
64
|
<View style={[sideItemContainerStyles, bulletContainerStyles]}>
|
|
57
65
|
<Icon
|
|
58
66
|
icon={icon}
|
|
59
|
-
tokens={{
|
|
60
|
-
|
|
67
|
+
tokens={{
|
|
68
|
+
size: iconSize ?? iconTokens.size,
|
|
69
|
+
...(((iconColor && !iconColorVariants?.includes(iconColor)) || !iconColor) && {
|
|
70
|
+
color:
|
|
71
|
+
iconColor && !iconColorVariants?.includes(iconColor) ? iconColor : iconTokens.color
|
|
72
|
+
})
|
|
73
|
+
}}
|
|
74
|
+
variant={{
|
|
75
|
+
...(iconColorVariants?.includes(iconColor) && { color: iconColor })
|
|
76
|
+
}}
|
|
61
77
|
/>
|
|
62
78
|
</View>
|
|
63
79
|
)
|
|
@@ -9,6 +9,7 @@ import dictionary from './dictionary'
|
|
|
9
9
|
|
|
10
10
|
import Card from '../Card'
|
|
11
11
|
import IconButton from '../IconButton'
|
|
12
|
+
import useDetectOutsideClick from '../utils/useDetectOutsideClick'
|
|
12
13
|
|
|
13
14
|
const staticStyles = StyleSheet.create({
|
|
14
15
|
positioner: {
|
|
@@ -49,6 +50,7 @@ const staticStyles = StyleSheet.create({
|
|
|
49
50
|
|
|
50
51
|
const selectContainerStyle = (enableFullscreen, themeTokens) => ({
|
|
51
52
|
borderColor: themeTokens.borderColor,
|
|
53
|
+
backgroundColor: themeTokens.backgroundColor,
|
|
52
54
|
...Platform.select({
|
|
53
55
|
web: {
|
|
54
56
|
position: enableFullscreen ? 'fixed' : 'absolute'
|
|
@@ -80,12 +82,17 @@ const ModalOverlay = React.forwardRef(
|
|
|
80
82
|
tokens,
|
|
81
83
|
copy,
|
|
82
84
|
onClose,
|
|
83
|
-
enableFullscreen = false
|
|
85
|
+
enableFullscreen = false,
|
|
86
|
+
dismissWhenPressedOutside = false
|
|
84
87
|
},
|
|
85
88
|
ref
|
|
86
89
|
) => {
|
|
87
90
|
const viewport = useViewport()
|
|
88
91
|
const themeTokens = useThemeTokens('Modal', tokens, variant, { viewport, maxWidth: false })
|
|
92
|
+
|
|
93
|
+
const containerRef = React.useRef(ref || null)
|
|
94
|
+
useDetectOutsideClick(containerRef, onClose, dismissWhenPressedOutside)
|
|
95
|
+
|
|
89
96
|
const containerWidthHeight = {
|
|
90
97
|
minWidth: tokens.maxWidth ? maxWidthSize : minWidth,
|
|
91
98
|
minHeight: maxHeight ? maxHeightSize : minHeight,
|
|
@@ -93,7 +100,7 @@ const ModalOverlay = React.forwardRef(
|
|
|
93
100
|
maxHeight: maxHeightSize
|
|
94
101
|
}
|
|
95
102
|
|
|
96
|
-
const { closeIcon: CloseIconComponent } = themeTokens
|
|
103
|
+
const { closeIcon: CloseIconComponent, backgroundColor } = themeTokens
|
|
97
104
|
|
|
98
105
|
const getCopy = useCopy({ dictionary, copy })
|
|
99
106
|
const closeLabel = getCopy('closeButton')
|
|
@@ -101,7 +108,7 @@ const ModalOverlay = React.forwardRef(
|
|
|
101
108
|
return (
|
|
102
109
|
<Portal>
|
|
103
110
|
<View
|
|
104
|
-
ref={
|
|
111
|
+
ref={containerRef}
|
|
105
112
|
onLayout={onLayout}
|
|
106
113
|
style={[
|
|
107
114
|
overlaidPosition,
|
|
@@ -111,7 +118,7 @@ const ModalOverlay = React.forwardRef(
|
|
|
111
118
|
selectContainerStyle(enableFullscreen, themeTokens)
|
|
112
119
|
]}
|
|
113
120
|
>
|
|
114
|
-
<Card tokens={staticStyles.card}>
|
|
121
|
+
<Card tokens={{ ...staticStyles.card, backgroundColor }}>
|
|
115
122
|
<View
|
|
116
123
|
style={[
|
|
117
124
|
staticStyles.closeButtonContainer,
|
|
@@ -132,6 +139,7 @@ const ModalOverlay = React.forwardRef(
|
|
|
132
139
|
)
|
|
133
140
|
}
|
|
134
141
|
)
|
|
142
|
+
|
|
135
143
|
ModalOverlay.displayName = 'ModalOverlay'
|
|
136
144
|
|
|
137
145
|
ModalOverlay.propTypes = {
|
|
@@ -153,7 +161,12 @@ ModalOverlay.propTypes = {
|
|
|
153
161
|
tokens: getTokensPropType('Modal'),
|
|
154
162
|
copy: copyPropTypes,
|
|
155
163
|
onClose: PropTypes.func,
|
|
156
|
-
enableFullscreen: PropTypes.bool
|
|
164
|
+
enableFullscreen: PropTypes.bool,
|
|
165
|
+
/**
|
|
166
|
+
* If true, clicking outside the content will trigger the a close callback, dismissing the content.
|
|
167
|
+
* @deprecated This parameter will be removed in the next major release; detection will be always enabled by default.
|
|
168
|
+
*/
|
|
169
|
+
dismissWhenPressedOutside: PropTypes.bool
|
|
157
170
|
}
|
|
158
171
|
|
|
159
172
|
export default ModalOverlay
|