@telus-uds/components-base 3.7.0 → 3.8.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 +27 -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/Card/PressableCardBase.js +4 -1
- package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +1 -1
- package/lib/cjs/List/ListItemMark.js +13 -2
- package/lib/cjs/MultiSelectFilter/ModalOverlay.js +12 -3
- package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +9 -2
- 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/Card/PressableCardBase.js +4 -1
- package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +1 -1
- package/lib/esm/List/ListItemMark.js +13 -2
- package/lib/esm/MultiSelectFilter/ModalOverlay.js +12 -3
- package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +9 -2
- 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/Card/PressableCardBase.jsx +1 -1
- package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +1 -1
- package/src/List/ListItemMark.jsx +18 -2
- package/src/MultiSelectFilter/ModalOverlay.jsx +15 -3
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +9 -2
- package/src/utils/index.js +1 -0
- package/src/utils/useDetectOutsideClick.js +35 -0
- package/src/utils/useVariants.js +44 -0
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
const RenderActivityIndicator = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
13
|
+
let {
|
|
14
|
+
variant = {},
|
|
15
|
+
dotSize,
|
|
16
|
+
size,
|
|
17
|
+
color,
|
|
18
|
+
indicatorBackgroundColor,
|
|
19
|
+
thickness,
|
|
20
|
+
label,
|
|
21
|
+
isStatic
|
|
22
|
+
} = _ref;
|
|
23
|
+
const {
|
|
24
|
+
dots,
|
|
25
|
+
style
|
|
26
|
+
} = variant || {};
|
|
27
|
+
const isDots = dots === true || style === DOTS_STYLE;
|
|
28
|
+
return isDots ? /*#__PURE__*/_jsx(Dots, {
|
|
29
|
+
ref: ref,
|
|
30
|
+
size: dotSize,
|
|
31
|
+
color: color,
|
|
32
|
+
indicatorBackgroundColor: indicatorBackgroundColor,
|
|
33
|
+
label: label,
|
|
34
|
+
isStatic: isStatic
|
|
35
|
+
}) : /*#__PURE__*/_jsx(Spinner, {
|
|
36
|
+
ref: ref,
|
|
37
|
+
size: size,
|
|
38
|
+
color: color,
|
|
39
|
+
indicatorBackgroundColor: indicatorBackgroundColor,
|
|
40
|
+
thickness: thickness,
|
|
41
|
+
label: label,
|
|
42
|
+
isStatic: isStatic
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
RenderActivityIndicator.displayName = 'RenderActivityIndicator';
|
|
46
|
+
RenderActivityIndicator.propTypes = {
|
|
47
|
+
/**
|
|
48
|
+
* ActivityIndicator variants
|
|
49
|
+
* */
|
|
50
|
+
variant: PropTypes.shape({
|
|
51
|
+
dots: PropTypes.bool,
|
|
52
|
+
style: PropTypes.oneOf([DOTS_STYLE])
|
|
53
|
+
}),
|
|
54
|
+
/**
|
|
55
|
+
* Size of the dots
|
|
56
|
+
* */
|
|
57
|
+
dotSize: PropTypes.number,
|
|
58
|
+
/**
|
|
59
|
+
* Size of the spinner
|
|
60
|
+
* */
|
|
61
|
+
size: PropTypes.number,
|
|
62
|
+
/**
|
|
63
|
+
* Primary color
|
|
64
|
+
* */
|
|
65
|
+
color: PropTypes.string,
|
|
66
|
+
/**
|
|
67
|
+
* Secondary color (background) of the indicator
|
|
68
|
+
* */
|
|
69
|
+
indicatorBackgroundColor: PropTypes.string,
|
|
70
|
+
/**
|
|
71
|
+
* Thickness of the indicator
|
|
72
|
+
* */
|
|
73
|
+
thickness: PropTypes.number,
|
|
74
|
+
/**
|
|
75
|
+
* Label for the ActivityIndicator
|
|
76
|
+
* */
|
|
77
|
+
label: PropTypes.string,
|
|
78
|
+
/**
|
|
79
|
+
* if true, there's no animation for ActivityIndicator
|
|
80
|
+
* */
|
|
81
|
+
isStatic: PropTypes.bool
|
|
82
|
+
};
|
|
83
|
+
export default RenderActivityIndicator;
|
|
@@ -1,45 +1,83 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
4
|
+
import { useScrollBlocking } from '../utils';
|
|
3
5
|
import { useThemeTokens } from '../ThemeProvider';
|
|
4
6
|
import { getTokensPropType, variantProp } from '../utils/props';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
+
import FullScreenIndicator from './FullScreenIndicator';
|
|
8
|
+
import OverlayIndicator from './OverlayIndicator';
|
|
9
|
+
import InlineIndicator from './InlineIndicator';
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
const labelMapping = {
|
|
12
|
+
top: 'column-reverse',
|
|
13
|
+
bottom: 'column',
|
|
14
|
+
left: 'row-reverse',
|
|
15
|
+
right: 'row'
|
|
16
|
+
};
|
|
7
17
|
|
|
8
18
|
/**
|
|
9
19
|
* `ActivityIndicator` renders a visual loading state.
|
|
10
20
|
* It does not handle positioning or layout of that visual loader.
|
|
11
21
|
*/
|
|
12
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
22
|
const ActivityIndicator = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
14
23
|
let {
|
|
15
24
|
variant,
|
|
16
25
|
tokens,
|
|
17
26
|
label,
|
|
18
|
-
|
|
27
|
+
labelPosition = 'bottom',
|
|
28
|
+
showLabel = true,
|
|
29
|
+
inline = false,
|
|
30
|
+
fullScreen = false,
|
|
31
|
+
overlay = false,
|
|
32
|
+
isStatic = false,
|
|
33
|
+
children,
|
|
34
|
+
fullScreenBackgroundColor
|
|
19
35
|
} = _ref;
|
|
20
36
|
const {
|
|
21
37
|
size,
|
|
22
38
|
dotSize,
|
|
23
39
|
color,
|
|
24
40
|
indicatorBackgroundColor,
|
|
41
|
+
fullScreenOverlayBackground,
|
|
25
42
|
thickness
|
|
26
43
|
} = useThemeTokens('ActivityIndicator', tokens, variant);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
useScrollBlocking([Platform.OS === 'web' && fullScreen]);
|
|
45
|
+
const variantProps = {
|
|
46
|
+
variant,
|
|
47
|
+
dotSize,
|
|
48
|
+
size,
|
|
49
|
+
color,
|
|
50
|
+
indicatorBackgroundColor,
|
|
51
|
+
thickness,
|
|
52
|
+
isStatic
|
|
53
|
+
};
|
|
54
|
+
const visibleLabel = showLabel && !!label;
|
|
55
|
+
const commonProps = {
|
|
56
|
+
ref,
|
|
57
|
+
variantProps,
|
|
58
|
+
label,
|
|
59
|
+
labelPosition,
|
|
60
|
+
labelMapping,
|
|
61
|
+
showLabel: visibleLabel
|
|
62
|
+
};
|
|
63
|
+
switch (true) {
|
|
64
|
+
case fullScreen:
|
|
65
|
+
return /*#__PURE__*/_jsx(FullScreenIndicator, {
|
|
66
|
+
...commonProps,
|
|
67
|
+
backgroundColor: fullScreenBackgroundColor || fullScreenOverlayBackground
|
|
68
|
+
});
|
|
69
|
+
case overlay:
|
|
70
|
+
return /*#__PURE__*/_jsx(OverlayIndicator, {
|
|
71
|
+
...commonProps,
|
|
72
|
+
inline: inline,
|
|
73
|
+
isActive: overlay,
|
|
74
|
+
children: children
|
|
75
|
+
});
|
|
76
|
+
default:
|
|
77
|
+
return /*#__PURE__*/_jsx(InlineIndicator, {
|
|
78
|
+
...commonProps
|
|
79
|
+
});
|
|
80
|
+
}
|
|
43
81
|
});
|
|
44
82
|
ActivityIndicator.displayName = 'ActivityIndicator';
|
|
45
83
|
ActivityIndicator.propTypes = {
|
|
@@ -48,10 +86,38 @@ ActivityIndicator.propTypes = {
|
|
|
48
86
|
/**
|
|
49
87
|
* A visually hidden accessible label describing the action taking place
|
|
50
88
|
*/
|
|
51
|
-
label: PropTypes.string
|
|
89
|
+
label: PropTypes.string,
|
|
90
|
+
/**
|
|
91
|
+
* If true, it should render a static ActivityIndicator
|
|
92
|
+
*/
|
|
93
|
+
isStatic: PropTypes.bool,
|
|
94
|
+
/**
|
|
95
|
+
* Position of the label relative to ActivityIndicator
|
|
96
|
+
*/
|
|
97
|
+
labelPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
|
98
|
+
/**
|
|
99
|
+
* show or hide the label
|
|
100
|
+
*/
|
|
101
|
+
showLabel: PropTypes.bool,
|
|
102
|
+
/**
|
|
103
|
+
* If true, the ActivityIndicator will be displayed in full screen mode
|
|
104
|
+
*/
|
|
105
|
+
fullScreen: PropTypes.bool,
|
|
106
|
+
/**
|
|
107
|
+
* If true, the ActivityIndicator will be displayed inline
|
|
108
|
+
*/
|
|
109
|
+
inline: PropTypes.bool,
|
|
110
|
+
/**
|
|
111
|
+
* If true, the ActivityIndicator will be displayed in overlay mode
|
|
112
|
+
*/
|
|
113
|
+
overlay: PropTypes.bool,
|
|
114
|
+
/**
|
|
115
|
+
* Children to be rendered inside ActivityIndicator
|
|
116
|
+
*/
|
|
117
|
+
children: PropTypes.node,
|
|
52
118
|
/**
|
|
53
|
-
*
|
|
119
|
+
* Background color of the full screen overlay
|
|
54
120
|
*/
|
|
55
|
-
|
|
121
|
+
fullScreenBackgroundColor: PropTypes.string
|
|
56
122
|
};
|
|
57
123
|
export default ActivityIndicator;
|
|
@@ -50,6 +50,17 @@ export const DOT_FADEOUT_OUTPUT_RANGE = [1, 1, 0, 0];
|
|
|
50
50
|
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
|
+
|
|
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';
|
|
53
64
|
export const propTypes = {
|
|
54
65
|
color: PropTypes.string.isRequired,
|
|
55
66
|
baseColor: PropTypes.string,
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
export const activityIndicatorCommonProps = {
|
|
41
|
+
/**
|
|
42
|
+
* Props used by RenderActivityIndicator
|
|
43
|
+
* */
|
|
44
|
+
variantProps: activityIndicatorVariantProps,
|
|
45
|
+
/**
|
|
46
|
+
* Shows or hide the label
|
|
47
|
+
* */
|
|
48
|
+
showLabel: PropTypes.bool,
|
|
49
|
+
/**
|
|
50
|
+
* A visually hidden accessible label describing the action taking place
|
|
51
|
+
*/
|
|
52
|
+
label: PropTypes.string,
|
|
53
|
+
/**
|
|
54
|
+
* Position of the label relative to ActivityIndicator
|
|
55
|
+
*/
|
|
56
|
+
labelPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
|
57
|
+
/**
|
|
58
|
+
* Map of flex-direction position for label
|
|
59
|
+
* */
|
|
60
|
+
labelMapping: PropTypes.object.isRequired
|
|
61
|
+
};
|
package/lib/esm/Card/Card.js
CHANGED
|
@@ -126,6 +126,7 @@ const Card = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
126
126
|
const selected = interactiveCard?.variant?.selected;
|
|
127
127
|
const inactive = interactiveCard?.variant?.inactive;
|
|
128
128
|
const selectionType = interactiveCard?.selectionType;
|
|
129
|
+
const isControl = interactiveCard?.variant?.isControl === true;
|
|
129
130
|
const getThemeTokens = useThemeTokensCallback('Card', interactiveCard?.tokens, {
|
|
130
131
|
interactive: true,
|
|
131
132
|
...(interactiveCard?.variant || {})
|
|
@@ -193,6 +194,9 @@ const Card = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
193
194
|
cardStyles = themeTokens;
|
|
194
195
|
}
|
|
195
196
|
const renderInputPerSelectionType = props => {
|
|
197
|
+
if (!isControl) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
196
200
|
switch (selectionType) {
|
|
197
201
|
case SelectionType.Checkbox:
|
|
198
202
|
return /*#__PURE__*/_jsx(View, {
|
|
@@ -220,17 +224,8 @@ const Card = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
220
224
|
return null;
|
|
221
225
|
}
|
|
222
226
|
};
|
|
223
|
-
const renderNoSelectionView = () => /*#__PURE__*/_jsx(View, {
|
|
224
|
-
style: {
|
|
225
|
-
paddingTop,
|
|
226
|
-
paddingBottom,
|
|
227
|
-
paddingLeft,
|
|
228
|
-
paddingRight
|
|
229
|
-
},
|
|
230
|
-
children: children
|
|
231
|
-
});
|
|
232
227
|
return /*#__PURE__*/_jsx(_Fragment, {
|
|
233
|
-
children: /*#__PURE__*/
|
|
228
|
+
children: /*#__PURE__*/_jsxs(CardBase, {
|
|
234
229
|
ref: ref,
|
|
235
230
|
tokens: interactiveCard?.body ? restOfTokens : cardStyles,
|
|
236
231
|
backgroundImage: backgroundImage,
|
|
@@ -238,41 +233,39 @@ const Card = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
238
233
|
media: mediaIds
|
|
239
234
|
},
|
|
240
235
|
...selectProps(rest),
|
|
241
|
-
children: interactiveCard?.body
|
|
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
|
-
}), children && selectionType !== SelectionType.None ? renderNoSelectionView() : null]
|
|
275
|
-
}) : children
|
|
236
|
+
children: [interactiveCard?.body && /*#__PURE__*/_jsx(PressableCardBase, {
|
|
237
|
+
ref: ref,
|
|
238
|
+
tokens: getThemeTokens,
|
|
239
|
+
dataSet: dataSet,
|
|
240
|
+
onPress: onPress,
|
|
241
|
+
href: interactiveCard?.href,
|
|
242
|
+
hrefAttrs: interactiveCard?.hrefAttrs,
|
|
243
|
+
...selectProps(rest),
|
|
244
|
+
children: cardState => {
|
|
245
|
+
const {
|
|
246
|
+
iconColor: checkColor,
|
|
247
|
+
inputBackgroundColor: boxBackgroundColor,
|
|
248
|
+
iconBackgroundColor: checkBackgroundColor
|
|
249
|
+
} = getThemeTokens({
|
|
250
|
+
...cardState,
|
|
251
|
+
selected,
|
|
252
|
+
interactive: true,
|
|
253
|
+
isControl
|
|
254
|
+
}, interactiveCard?.tokens);
|
|
255
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
256
|
+
children: [renderInputPerSelectionType(getInputProps({
|
|
257
|
+
id,
|
|
258
|
+
checkColor,
|
|
259
|
+
boxBackgroundColor,
|
|
260
|
+
checkBackgroundColor,
|
|
261
|
+
isControlled: true,
|
|
262
|
+
isChecked: selected || cardState?.hover,
|
|
263
|
+
isInactive: inactive,
|
|
264
|
+
onPress
|
|
265
|
+
})), typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body]
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}), children]
|
|
276
269
|
})
|
|
277
270
|
});
|
|
278
271
|
});
|
|
@@ -125,7 +125,10 @@ const PressableCardBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
125
125
|
setFocused(false);
|
|
126
126
|
setPressed(false);
|
|
127
127
|
},
|
|
128
|
-
style:
|
|
128
|
+
style: {
|
|
129
|
+
...staticStyles.container,
|
|
130
|
+
textDecoration: 'none'
|
|
131
|
+
},
|
|
129
132
|
...(hrefAttrs || {}),
|
|
130
133
|
children: /*#__PURE__*/_jsx(CardBase, {
|
|
131
134
|
tokens: getCardTokens({
|
|
@@ -38,7 +38,7 @@ const ExpandCollapseMiniControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
38
38
|
const isFocusVisible = Platform.OS === 'web' ? focus && !pressed && !hover : expanded;
|
|
39
39
|
const linkTokens = useThemeTokens('Link', {}, {
|
|
40
40
|
...variant,
|
|
41
|
-
quiet
|
|
41
|
+
quiet
|
|
42
42
|
}, {
|
|
43
43
|
focus: isFocusVisible,
|
|
44
44
|
hover,
|
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import View from "react-native-web/dist/exports/View";
|
|
4
4
|
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
5
5
|
import Icon from '../Icon';
|
|
6
|
+
import { useVariants } from '../utils';
|
|
6
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
8
|
export const tokenTypes = {
|
|
8
9
|
itemIconSize: PropTypes.number.isRequired,
|
|
@@ -53,6 +54,7 @@ const selectBulletContainerStyles = _ref4 => {
|
|
|
53
54
|
alignItems: itemBulletContainerAlign
|
|
54
55
|
};
|
|
55
56
|
};
|
|
57
|
+
const getIconColorVariants = iconVariants => iconVariants?.filter(variant => variant[0] === 'color').map(variant => variant[1]);
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
60
|
* Subcomponent used within ListItem and similar components for rendering bullets or icons
|
|
@@ -71,6 +73,10 @@ const ListItemMark = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
71
73
|
const themeTokens = typeof tokens === 'function' ? tokens() : tokens;
|
|
72
74
|
const sideItemContainerStyles = selectSideItemContainerStyles(themeTokens);
|
|
73
75
|
const bulletContainerStyles = selectBulletContainerStyles(themeTokens);
|
|
76
|
+
|
|
77
|
+
// TODO: Remove it when iconColor custom colors are deprecated.
|
|
78
|
+
const iconVariants = useVariants('Icon');
|
|
79
|
+
const iconColorVariants = getIconColorVariants(iconVariants);
|
|
74
80
|
if (icon) {
|
|
75
81
|
const iconTokens = selectItemIconTokens(themeTokens);
|
|
76
82
|
return /*#__PURE__*/_jsx(View, {
|
|
@@ -78,10 +84,15 @@ const ListItemMark = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
78
84
|
children: /*#__PURE__*/_jsx(Icon, {
|
|
79
85
|
icon: icon,
|
|
80
86
|
tokens: {
|
|
81
|
-
size: iconSize ?? iconTokens.size
|
|
87
|
+
size: iconSize ?? iconTokens.size,
|
|
88
|
+
...((iconColor && !iconColorVariants?.includes(iconColor) || !iconColor) && {
|
|
89
|
+
color: iconColor && !iconColorVariants?.includes(iconColor) ? iconColor : iconTokens.color
|
|
90
|
+
})
|
|
82
91
|
},
|
|
83
92
|
variant: {
|
|
84
|
-
|
|
93
|
+
...(iconColorVariants?.includes(iconColor) && {
|
|
94
|
+
color: iconColor
|
|
95
|
+
})
|
|
85
96
|
}
|
|
86
97
|
})
|
|
87
98
|
});
|
|
@@ -10,6 +10,7 @@ import { useThemeTokens } from '../ThemeProvider';
|
|
|
10
10
|
import dictionary from './dictionary';
|
|
11
11
|
import Card from '../Card';
|
|
12
12
|
import IconButton from '../IconButton';
|
|
13
|
+
import useDetectOutsideClick from '../utils/useDetectOutsideClick';
|
|
13
14
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
15
|
const staticStyles = StyleSheet.create({
|
|
15
16
|
positioner: {
|
|
@@ -89,13 +90,16 @@ const ModalOverlay = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
89
90
|
tokens,
|
|
90
91
|
copy,
|
|
91
92
|
onClose,
|
|
92
|
-
enableFullscreen = false
|
|
93
|
+
enableFullscreen = false,
|
|
94
|
+
dismissWhenPressedOutside = false
|
|
93
95
|
} = _ref2;
|
|
94
96
|
const viewport = useViewport();
|
|
95
97
|
const themeTokens = useThemeTokens('Modal', tokens, variant, {
|
|
96
98
|
viewport,
|
|
97
99
|
maxWidth: false
|
|
98
100
|
});
|
|
101
|
+
const containerRef = React.useRef(ref || null);
|
|
102
|
+
useDetectOutsideClick(containerRef, onClose, dismissWhenPressedOutside);
|
|
99
103
|
const containerWidthHeight = {
|
|
100
104
|
minWidth: tokens.maxWidth ? maxWidthSize : minWidth,
|
|
101
105
|
minHeight: maxHeight ? maxHeightSize : minHeight,
|
|
@@ -112,7 +116,7 @@ const ModalOverlay = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
112
116
|
const closeLabel = getCopy('closeButton');
|
|
113
117
|
return /*#__PURE__*/_jsx(Portal, {
|
|
114
118
|
children: /*#__PURE__*/_jsx(View, {
|
|
115
|
-
ref:
|
|
119
|
+
ref: containerRef,
|
|
116
120
|
onLayout: onLayout,
|
|
117
121
|
style: [overlaidPosition, containerWidthHeight, staticStyles.positioner, !isReady && staticStyles.hidden, selectContainerStyle(enableFullscreen, themeTokens)],
|
|
118
122
|
children: /*#__PURE__*/_jsxs(Card, {
|
|
@@ -150,6 +154,11 @@ ModalOverlay.propTypes = {
|
|
|
150
154
|
tokens: getTokensPropType('Modal'),
|
|
151
155
|
copy: copyPropTypes,
|
|
152
156
|
onClose: PropTypes.func,
|
|
153
|
-
enableFullscreen: PropTypes.bool
|
|
157
|
+
enableFullscreen: PropTypes.bool,
|
|
158
|
+
/**
|
|
159
|
+
* If true, clicking outside the content will trigger the a close callback, dismissing the content.
|
|
160
|
+
* @deprecated This parameter will be removed in the next major release; detection will be always enabled by default.
|
|
161
|
+
*/
|
|
162
|
+
dismissWhenPressedOutside: PropTypes.bool
|
|
154
163
|
};
|
|
155
164
|
export default ModalOverlay;
|
|
@@ -85,6 +85,7 @@ const MultiSelectFilter = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
85
85
|
inactive = false,
|
|
86
86
|
rowLimit = 12,
|
|
87
87
|
dictionary = defaultDictionary,
|
|
88
|
+
dismissWhenPressedOutside = false,
|
|
88
89
|
...rest
|
|
89
90
|
} = _ref3;
|
|
90
91
|
const viewport = useViewport();
|
|
@@ -396,8 +397,9 @@ const MultiSelectFilter = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
396
397
|
})]
|
|
397
398
|
})
|
|
398
399
|
}), isOpen && viewport !== 'xs' && /*#__PURE__*/_jsxs(ModalOverlay, {
|
|
399
|
-
|
|
400
|
+
dismissWhenPressedOutside: dismissWhenPressedOutside,
|
|
400
401
|
onClose: onClose,
|
|
402
|
+
overlaidPosition: overlaidPosition,
|
|
401
403
|
maxHeight: items.length > MAX_ITEMS_THRESHOLD ? true : maxHeight,
|
|
402
404
|
maxHeightSize: maxHeightSize,
|
|
403
405
|
maxWidthSize: maxWidthSize,
|
|
@@ -541,6 +543,11 @@ MultiSelectFilter.propTypes = {
|
|
|
541
543
|
* Sets the maximum number of items in one column. If number of items are more
|
|
542
544
|
* than the `rowLimit`, they will be rendered in 2 columns.
|
|
543
545
|
*/
|
|
544
|
-
rowLimit: PropTypes.number
|
|
546
|
+
rowLimit: PropTypes.number,
|
|
547
|
+
/**
|
|
548
|
+
* If true, clicking outside the content will trigger the a close callback, dismissing the content.
|
|
549
|
+
* @deprecated This parameter will be removed in the next major release; detection will be always enabled by default.
|
|
550
|
+
*/
|
|
551
|
+
dismissWhenPressedOutside: PropTypes.bool
|
|
545
552
|
};
|
|
546
553
|
export default MultiSelectFilter;
|
package/lib/esm/utils/index.js
CHANGED
|
@@ -23,4 +23,5 @@ export { default as htmlAttrs } from './htmlAttrs';
|
|
|
23
23
|
export { transformGradient } from './transformGradient';
|
|
24
24
|
export { default as convertFromMegaByteToByte } from './convertFromMegaByteToByte';
|
|
25
25
|
export { default as formatImageSource } from './formatImageSource';
|
|
26
|
-
export { default as getSpacingScale } from './getSpacingScale';
|
|
26
|
+
export { default as getSpacingScale } from './getSpacingScale';
|
|
27
|
+
export { default as useVariants } from './useVariants';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
3
|
+
/**
|
|
4
|
+
* Hook to detect clicks outside of a ref, only on web.
|
|
5
|
+
*
|
|
6
|
+
* @param {React.RefObject<HTMLElement>} ref
|
|
7
|
+
* Reference to the element you want to “protect.”
|
|
8
|
+
* @param {() => void} onOutside
|
|
9
|
+
* Callback invoked when a click occurs outside that ref.
|
|
10
|
+
* @param {boolean} [enabled=true]
|
|
11
|
+
* Flag to enable or disable the outside-click detection at runtime.
|
|
12
|
+
* @deprecated Will be removed in next major release; detection will always be enabled.
|
|
13
|
+
*/
|
|
14
|
+
function useDetectOutsideClick(ref, onOutside) {
|
|
15
|
+
let enabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
if (!enabled || Platform.OS !== 'web') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const handleClickOutside = e => {
|
|
21
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
22
|
+
onOutside();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
26
|
+
return () => {
|
|
27
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
28
|
+
};
|
|
29
|
+
}, [ref, onOutside, enabled]);
|
|
30
|
+
}
|
|
31
|
+
export default useDetectOutsideClick;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { getComponentTheme, useTheme } from '../ThemeProvider';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generates a label string for a variant based on the provided key and value.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} key - The name of the variant.
|
|
7
|
+
* @param {*} value - The value of the variant. If it's a string, it will be appended to the key.
|
|
8
|
+
* @returns {string} The formatted variant label (e.g., "color: red" or "size").
|
|
9
|
+
*/
|
|
10
|
+
const getVariantLabel = (key, value) => `${key}${typeof value === 'string' ? `: ${value}` : ''}`;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Retrieves the variant options for a given component from the theme.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} componentName - The name of the component to get variants for.
|
|
16
|
+
* @returns {Array<Array>} An array of variant tuples. Each tuple contains:
|
|
17
|
+
* - {string|undefined} The variant key (e.g., 'size', 'color', or undefined for default).
|
|
18
|
+
* - {string|undefined} The variant value (e.g., 'small', 'primary', or undefined for default).
|
|
19
|
+
* - {string} The human-readable label for the variant.
|
|
20
|
+
* Returns [['default', {}]] if no componentName is provided.
|
|
21
|
+
* @throws {Error} If the theme does not define appearances for the given component.
|
|
22
|
+
*/
|
|
23
|
+
const useVariants = componentName => {
|
|
24
|
+
const theme = useTheme();
|
|
25
|
+
if (!componentName) return [['default', {}]];
|
|
26
|
+
const {
|
|
27
|
+
appearances
|
|
28
|
+
} = getComponentTheme(theme, componentName);
|
|
29
|
+
if (!appearances) {
|
|
30
|
+
throw new Error(`Theme ${theme.metadata?.name} does not have any appearances set for ${componentName}`);
|
|
31
|
+
}
|
|
32
|
+
const variants = Object.entries(appearances).reduce((pairs, _ref) => {
|
|
33
|
+
let [key, {
|
|
34
|
+
values,
|
|
35
|
+
type
|
|
36
|
+
} = {}] = _ref;
|
|
37
|
+
return type === 'variant' ? [...pairs, ...values.map(value => [key, value, getVariantLabel(key, value)])] : pairs;
|
|
38
|
+
}, [[undefined, undefined, 'default style']]);
|
|
39
|
+
return variants;
|
|
40
|
+
};
|
|
41
|
+
export default useVariants;
|
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.6.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.8.0",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|