@telus-uds/components-base 1.96.0 → 1.97.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/lib/Carousel/Carousel.js +1 -1
  3. package/lib/Carousel/CarouselItem/CarouselItem.js +15 -19
  4. package/lib/InputLabel/InputLabel.js +2 -3
  5. package/lib/List/ListItemBase.js +2 -1
  6. package/lib/Listbox/GroupControl.js +4 -0
  7. package/lib/Modal/ModalContent.js +3 -2
  8. package/lib/Pagination/Pagination.js +9 -2
  9. package/lib/Pagination/constants.js +12 -0
  10. package/lib/Pagination/usePagination.js +13 -3
  11. package/lib/Tooltip/Tooltip.native.js +31 -3
  12. package/lib/Tooltip/shared.js +5 -0
  13. package/lib-module/Carousel/Carousel.js +1 -1
  14. package/lib-module/Carousel/CarouselItem/CarouselItem.js +15 -19
  15. package/lib-module/InputLabel/InputLabel.js +2 -3
  16. package/lib-module/List/ListItemBase.js +2 -1
  17. package/lib-module/Listbox/GroupControl.js +4 -0
  18. package/lib-module/Modal/ModalContent.js +3 -2
  19. package/lib-module/Pagination/Pagination.js +9 -2
  20. package/lib-module/Pagination/constants.js +3 -0
  21. package/lib-module/Pagination/usePagination.js +13 -3
  22. package/lib-module/Tooltip/Tooltip.native.js +31 -3
  23. package/lib-module/Tooltip/shared.js +5 -0
  24. package/package.json +2 -2
  25. package/src/Carousel/Carousel.jsx +1 -1
  26. package/src/Carousel/CarouselItem/CarouselItem.jsx +16 -22
  27. package/src/InputLabel/InputLabel.jsx +2 -3
  28. package/src/List/ListItemBase.jsx +6 -1
  29. package/src/Listbox/GroupControl.jsx +6 -1
  30. package/src/Modal/ModalContent.jsx +3 -2
  31. package/src/Pagination/Pagination.jsx +9 -2
  32. package/src/Pagination/constants.js +3 -0
  33. package/src/Pagination/usePagination.js +14 -3
  34. package/src/Tooltip/Tooltip.native.jsx +31 -3
  35. package/src/Tooltip/shared.js +5 -0
  36. package/types/FileUpload.d.ts +40 -0
  37. package/types/index.d.ts +3 -0
package/CHANGELOG.md CHANGED
@@ -1,12 +1,31 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Sat, 12 Oct 2024 00:31:05 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 31 Oct 2024 05:02:44 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.97.0
8
+
9
+ Thu, 31 Oct 2024 05:02:44 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `Pagination`: Enable the option to set number of pages before ellipsis (jaime.tuyuc@telus.com)
14
+ - `Types:` Export BaseProviderProps and add FileUpload types (6854874+kyletsang@users.noreply.github.com)
15
+ - `Tooltip`: add tooltipButtonTokens prop (guillermo.peitzner@telus.com)
16
+ - `Modal`: Enable `footerTopWidth` token for `Modal` component (jaime.tuyuc@telus.com)
17
+ - Bump @telus-uds/system-theme-tokens to v2.66.0
18
+
19
+ ### Patches
20
+
21
+ - `ListBox`: color property distributed throughout the component tree to fix design bugs in the selected state inside `NavigationBar` (35577399+JoshHC@users.noreply.github.com)
22
+ - `Carousel`: fix item's width issues when peeking is enabled (guillermo.peitzner@telus.com)
23
+ - `List`: fix list content drift to center of screen on bigger containers (kristina.kirpichnikova@telus.com)
24
+ - `InputLabel`: fixed an issue when using tooltip. When the user taps the tooltip there was a weird artifact where the input moves down as if there was an extra space between the label and the input. (ashok@ashokamaran.com)
25
+
7
26
  ## 1.96.0
8
27
 
9
- Sat, 12 Oct 2024 00:31:05 GMT
28
+ Sat, 12 Oct 2024 00:40:49 GMT
10
29
 
11
30
  ### Minor changes
12
31
 
@@ -106,7 +106,7 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
106
106
  };
107
107
  };
108
108
  const getPeekingProps = viewport => {
109
- if (viewport === 'xs' || viewport === 'sm') {
109
+ if (viewport === 'xs' || viewport === 'sm' || viewport === 'md') {
110
110
  return {
111
111
  peekingFirstSpace: 48,
112
112
  peekingGap: 16,
@@ -21,39 +21,35 @@ const selectContainerStyle = _ref => {
21
21
  totalItems,
22
22
  enablePeeking,
23
23
  peekingMarginLeft,
24
- peekingMarginRight,
25
24
  peekingFirstSpace,
26
25
  peekingLastSpace,
27
26
  peekingMiddleSpace,
28
27
  peekingGap,
29
28
  hidden
30
29
  } = _ref;
31
- const isFirst = elementIndex === 0;
32
- const isLast = elementIndex === totalItems - 1;
33
- const isMiddle = !isFirst && !isLast;
34
- const isActive = activeIndex === elementIndex;
35
30
  let adjustedWidth = width;
36
31
  let marginLeft = 0;
37
- let marginRight = 0;
32
+ const marginRight = 0;
38
33
  if (enablePeeking) {
34
+ adjustedWidth = width - (peekingMarginLeft + peekingGap + peekingFirstSpace);
35
+ const isFirst = elementIndex === 0;
36
+ const isActive = activeIndex === elementIndex;
39
37
  if (isActive) {
40
- adjustedWidth = width - (peekingMarginLeft + peekingGap + peekingFirstSpace);
41
- } else if (isMiddle) {
42
- adjustedWidth = width - peekingGap;
43
- }
44
- if (isFirst) {
45
- if (isActive) {
38
+ if (isFirst) {
46
39
  marginLeft = peekingMarginLeft;
47
- } else if (activeIndex === totalItems - 1) {
48
- marginLeft = peekingLastSpace;
49
40
  } else {
50
- marginLeft = peekingMiddleSpace;
41
+ marginLeft = peekingGap;
42
+ }
43
+ } else if (isFirst) {
44
+ marginLeft = peekingMarginLeft + peekingGap + peekingFirstSpace + peekingMiddleSpace;
45
+ if (activeIndex > 1) {
46
+ marginLeft += (peekingGap + peekingMiddleSpace * 2) * (activeIndex - 1);
47
+ }
48
+ if (activeIndex === totalItems - 1) {
49
+ marginLeft += peekingLastSpace - peekingMiddleSpace;
51
50
  }
52
- }
53
- if (isLast && isActive) {
54
- marginRight = peekingMarginRight;
55
51
  } else {
56
- marginRight = peekingGap;
52
+ marginLeft = peekingGap;
57
53
  }
58
54
  }
59
55
  const style = {
@@ -135,8 +135,7 @@ exports.default = _default;
135
135
  const staticStyles = _StyleSheet.default.create({
136
136
  container: {
137
137
  flexShrink: 1,
138
- flexDirection: 'row',
139
- alignItems: 'baseline'
138
+ flexDirection: 'row'
140
139
  },
141
140
  label: {
142
141
  flexShrink: 1
@@ -146,7 +145,7 @@ const staticStyles = _StyleSheet.default.create({
146
145
  flexShrink: 0
147
146
  },
148
147
  tooltipAlign: {
149
- alignSelf: 'flex-start',
148
+ alignSelf: 'center',
150
149
  justifyContent: 'center'
151
150
  }
152
151
  });
@@ -136,7 +136,8 @@ const staticStyles = _StyleSheet.default.create({
136
136
  titleAndContentContainer: {
137
137
  flexDirection: 'column',
138
138
  flexShrink: 1,
139
- flexGrow: 1
139
+ flexGrow: 1,
140
+ textAlign: 'justify'
140
141
  }
141
142
  });
142
143
  ListItemBase.propTypes = {
@@ -62,6 +62,9 @@ const GroupControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
62
62
  itemOutline,
63
63
  groupHeight
64
64
  } = tokens;
65
+ const getTextStyles = () => ({
66
+ color: groupColor
67
+ });
65
68
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
66
69
  onPress: () => setSelectedId(id),
67
70
  style: [styles.controlWrapper, {
@@ -81,6 +84,7 @@ const GroupControl = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
81
84
  }],
82
85
  ref: ref,
83
86
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
87
+ style: getTextStyles(),
84
88
  children: label
85
89
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
86
90
  space: 1,
@@ -72,6 +72,7 @@ const ModalContent = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
72
72
  borderColor,
73
73
  gap,
74
74
  direction,
75
+ footerTopWidth,
75
76
  hasBorder
76
77
  } = _ref3;
77
78
  return {
@@ -83,8 +84,8 @@ const ModalContent = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
83
84
  paddingLeft,
84
85
  paddingRight,
85
86
  paddingTop,
86
- borderTopColor: hasBorder ? borderColor : 'transparent',
87
- borderTopWidth: hasBorder ? 1 : 0
87
+ borderTopWidth: footerTopWidth > 0 ? footerTopWidth : hasBorder && 1 || 0,
88
+ borderTopColor: borderColor
88
89
  };
89
90
  };
90
91
  const headingStyles = {
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
8
9
  var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
9
10
  var _Text = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Text"));
10
11
  var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
@@ -47,6 +48,7 @@ const Pagination = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
47
48
  sideButtonTokens,
48
49
  LinkRouter,
49
50
  linkRouterProps,
51
+ numberOfPagesBeforeEllipsis = 4,
50
52
  ...rest
51
53
  } = _ref2;
52
54
  const viewport = (0, _ViewportProvider.useViewport)();
@@ -86,7 +88,8 @@ const Pagination = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
86
88
  shouldRenderEllipsis
87
89
  } = (0, _usePagination.default)({
88
90
  items,
89
- truncateAbove
91
+ truncateAbove,
92
+ numberOfPagesBeforeEllipsis
90
93
  });
91
94
  const ellipsisTextStyles = selectTextStyles(themeTokens, themeOptions);
92
95
  const ellipisContainerStyles = _StyleSheet.default.create({
@@ -207,7 +210,11 @@ Pagination.propTypes = {
207
210
  /**
208
211
  * Custom tokens for `PaginationSideButton`
209
212
  */
210
- sideButtonTokens: (0, _utils.getTokensPropType)('PaginationSideButton')
213
+ sideButtonTokens: (0, _utils.getTokensPropType)('PaginationSideButton'),
214
+ /**
215
+ * The number of pages before the ellipsis is shown
216
+ */
217
+ numberOfPagesBeforeEllipsis: _propTypes.default.number
211
218
  };
212
219
  const staticStyles = _StyleSheet.default.create({
213
220
  container: {
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TRUNCATE_ABOVE_VALUE = exports.MIN_PAGES_TO_SHOW = exports.DEFAULT_PAGE_TO_SHOW_VALUE = void 0;
7
+ const TRUNCATE_ABOVE_VALUE = 4;
8
+ exports.TRUNCATE_ABOVE_VALUE = TRUNCATE_ABOVE_VALUE;
9
+ const MIN_PAGES_TO_SHOW = 3;
10
+ exports.MIN_PAGES_TO_SHOW = MIN_PAGES_TO_SHOW;
11
+ const DEFAULT_PAGE_TO_SHOW_VALUE = 1;
12
+ exports.DEFAULT_PAGE_TO_SHOW_VALUE = DEFAULT_PAGE_TO_SHOW_VALUE;
@@ -4,17 +4,20 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _constants = require("./constants");
7
8
  /**
8
9
  * Handles configurable truncating of pagination items.
9
10
  *
10
11
  * @param {object} props
11
12
  * @param {React.Element[]} items
12
13
  * @param {number} truncateAbove
14
+ * @param {number} numberOfPagesBeforeEllipsis
13
15
  */
14
16
  function usePagination(_ref) {
15
17
  let {
16
18
  items,
17
- truncateAbove
19
+ truncateAbove,
20
+ numberOfPagesBeforeEllipsis
18
21
  } = _ref;
19
22
  const activeItemIndex = Math.max(items.findIndex(item => item.props.isActive), 0 // default to the first item if none is marked as active
20
23
  );
@@ -36,8 +39,15 @@ function usePagination(_ref) {
36
39
  tokens
37
40
  };
38
41
  };
39
- const windowSize = truncateAbove > 4 ? 3 : 1;
40
- const truncateEnabled = items.length > truncateAbove;
42
+ let windowSize;
43
+ if (numberOfPagesBeforeEllipsis >= 1 && numberOfPagesBeforeEllipsis < items.length) {
44
+ windowSize = numberOfPagesBeforeEllipsis;
45
+ } else if (truncateAbove > _constants.TRUNCATE_ABOVE_VALUE) {
46
+ windowSize = _constants.MIN_PAGES_TO_SHOW;
47
+ } else {
48
+ windowSize = _constants.DEFAULT_PAGE_TO_SHOW_VALUE;
49
+ }
50
+ const truncateEnabled = items.length > windowSize;
41
51
  const truncateWindowStart = windowSize;
42
52
  const truncateWindowEnd = items.length - 1 - windowSize;
43
53
 
@@ -125,9 +125,10 @@ const selectArrowStyles = (_ref4, _ref5) => {
125
125
  };
126
126
  };
127
127
  const selectTextStyles = tokens => (0, _ThemeProvider.applyTextStyles)((0, _utils.selectTokens)('Typography', tokens));
128
- const defaultControl = (pressableState, variant) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_TooltipButton.default, {
128
+ const defaultControl = (pressableState, variant, tokens) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_TooltipButton.default, {
129
129
  pressableState: pressableState,
130
- variant: variant
130
+ variant: variant,
131
+ tokens: tokens
131
132
  });
132
133
 
133
134
  /**
@@ -156,6 +157,8 @@ const Tooltip = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
156
157
  variant,
157
158
  inline = false,
158
159
  nativeID,
160
+ activateOnHover = false,
161
+ tooltipButtonTokens,
159
162
  ...rest
160
163
  } = _ref6;
161
164
  const [isOpen, setIsOpen] = _react.default.useState(false);
@@ -256,6 +259,31 @@ const Tooltip = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
256
259
  }
257
260
  setTooltipPosition(updatedPosition);
258
261
  }, [isOpen, position, tooltipDimensions, controlLayout, windowDimensions, arrowWidth, arrowOffset, tooltipPosition]);
262
+ _react.default.useEffect(() => {
263
+ if (_Platform.default.OS !== 'web') {
264
+ return undefined;
265
+ }
266
+ const handleHover = event => {
267
+ if (activateOnHover) {
268
+ const isInsideControl = controlRef.current && controlRef.current.contains(event.target);
269
+ if (isInsideControl) {
270
+ if (!isOpen) {
271
+ setIsOpen(!isOpen);
272
+ }
273
+ } else {
274
+ close();
275
+ }
276
+ }
277
+ };
278
+ document.addEventListener('mouseover', handleHover, {
279
+ capture: true
280
+ });
281
+ return () => {
282
+ document.removeEventListener('mouseover', handleHover, {
283
+ capture: true
284
+ });
285
+ };
286
+ }, [controlLayout, activateOnHover, isOpen, onPress]);
259
287
  const control = children !== undefined ? children : defaultControl;
260
288
  const pressableStyles = control === defaultControl ? _Platform.default.select({
261
289
  web: {
@@ -284,7 +312,7 @@ const Tooltip = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
284
312
  accessibilityLabel: getCopy('a11yText'),
285
313
  accessibilityRole: "button",
286
314
  nativeID: nativeID,
287
- children: typeof control === 'function' ? pressableState => control(getPressableState(pressableState), variant) : control
315
+ children: typeof control === 'function' ? pressableState => control(getPressableState(pressableState), variant, tooltipButtonTokens) : control
288
316
  }), isOpen && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Backdrop.default, {
289
317
  onPress: close,
290
318
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
@@ -37,6 +37,11 @@ const propTypes = {
37
37
  * The `id` of the tooltip button.
38
38
  */
39
39
  nativeID: _propTypes.default.string,
40
+ /**
41
+ * Set to `true` to open the tooltip on hover
42
+ */
43
+ activateOnHover: _propTypes.default.bool,
44
+ tooltipButtonTokens: (0, _utils.getTokensPropType)('TooltipButton'),
40
45
  tokens: (0, _utils.getTokensPropType)('Tooltip'),
41
46
  variant: _utils.variantProp.propType
42
47
  };
@@ -100,7 +100,7 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
100
100
  };
101
101
  };
102
102
  const getPeekingProps = viewport => {
103
- if (viewport === 'xs' || viewport === 'sm') {
103
+ if (viewport === 'xs' || viewport === 'sm' || viewport === 'md') {
104
104
  return {
105
105
  peekingFirstSpace: 48,
106
106
  peekingGap: 16,
@@ -14,39 +14,35 @@ const selectContainerStyle = _ref => {
14
14
  totalItems,
15
15
  enablePeeking,
16
16
  peekingMarginLeft,
17
- peekingMarginRight,
18
17
  peekingFirstSpace,
19
18
  peekingLastSpace,
20
19
  peekingMiddleSpace,
21
20
  peekingGap,
22
21
  hidden
23
22
  } = _ref;
24
- const isFirst = elementIndex === 0;
25
- const isLast = elementIndex === totalItems - 1;
26
- const isMiddle = !isFirst && !isLast;
27
- const isActive = activeIndex === elementIndex;
28
23
  let adjustedWidth = width;
29
24
  let marginLeft = 0;
30
- let marginRight = 0;
25
+ const marginRight = 0;
31
26
  if (enablePeeking) {
27
+ adjustedWidth = width - (peekingMarginLeft + peekingGap + peekingFirstSpace);
28
+ const isFirst = elementIndex === 0;
29
+ const isActive = activeIndex === elementIndex;
32
30
  if (isActive) {
33
- adjustedWidth = width - (peekingMarginLeft + peekingGap + peekingFirstSpace);
34
- } else if (isMiddle) {
35
- adjustedWidth = width - peekingGap;
36
- }
37
- if (isFirst) {
38
- if (isActive) {
31
+ if (isFirst) {
39
32
  marginLeft = peekingMarginLeft;
40
- } else if (activeIndex === totalItems - 1) {
41
- marginLeft = peekingLastSpace;
42
33
  } else {
43
- marginLeft = peekingMiddleSpace;
34
+ marginLeft = peekingGap;
35
+ }
36
+ } else if (isFirst) {
37
+ marginLeft = peekingMarginLeft + peekingGap + peekingFirstSpace + peekingMiddleSpace;
38
+ if (activeIndex > 1) {
39
+ marginLeft += (peekingGap + peekingMiddleSpace * 2) * (activeIndex - 1);
40
+ }
41
+ if (activeIndex === totalItems - 1) {
42
+ marginLeft += peekingLastSpace - peekingMiddleSpace;
44
43
  }
45
- }
46
- if (isLast && isActive) {
47
- marginRight = peekingMarginRight;
48
44
  } else {
49
- marginRight = peekingGap;
45
+ marginLeft = peekingGap;
50
46
  }
51
47
  }
52
48
  const style = {
@@ -129,8 +129,7 @@ export default InputLabel;
129
129
  const staticStyles = StyleSheet.create({
130
130
  container: {
131
131
  flexShrink: 1,
132
- flexDirection: 'row',
133
- alignItems: 'baseline'
132
+ flexDirection: 'row'
134
133
  },
135
134
  label: {
136
135
  flexShrink: 1
@@ -140,7 +139,7 @@ const staticStyles = StyleSheet.create({
140
139
  flexShrink: 0
141
140
  },
142
141
  tooltipAlign: {
143
- alignSelf: 'flex-start',
142
+ alignSelf: 'center',
144
143
  justifyContent: 'center'
145
144
  }
146
145
  });
@@ -130,7 +130,8 @@ const staticStyles = StyleSheet.create({
130
130
  titleAndContentContainer: {
131
131
  flexDirection: 'column',
132
132
  flexShrink: 1,
133
- flexGrow: 1
133
+ flexGrow: 1,
134
+ textAlign: 'justify'
134
135
  }
135
136
  });
136
137
  ListItemBase.propTypes = {
@@ -56,6 +56,9 @@ const GroupControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
56
56
  itemOutline,
57
57
  groupHeight
58
58
  } = tokens;
59
+ const getTextStyles = () => ({
60
+ color: groupColor
61
+ });
59
62
  return /*#__PURE__*/_jsxs(View, {
60
63
  onPress: () => setSelectedId(id),
61
64
  style: [styles.controlWrapper, {
@@ -75,6 +78,7 @@ const GroupControl = /*#__PURE__*/React.forwardRef((_ref, ref) => {
75
78
  }],
76
79
  ref: ref,
77
80
  children: [/*#__PURE__*/_jsx(Text, {
81
+ style: getTextStyles(),
78
82
  children: label
79
83
  }), /*#__PURE__*/_jsx(Spacer, {
80
84
  space: 1,
@@ -66,6 +66,7 @@ const ModalContent = /*#__PURE__*/React.forwardRef((_ref, ref) => {
66
66
  borderColor,
67
67
  gap,
68
68
  direction,
69
+ footerTopWidth,
69
70
  hasBorder
70
71
  } = _ref3;
71
72
  return {
@@ -77,8 +78,8 @@ const ModalContent = /*#__PURE__*/React.forwardRef((_ref, ref) => {
77
78
  paddingLeft,
78
79
  paddingRight,
79
80
  paddingTop,
80
- borderTopColor: hasBorder ? borderColor : 'transparent',
81
- borderTopWidth: hasBorder ? 1 : 0
81
+ borderTopWidth: footerTopWidth > 0 ? footerTopWidth : hasBorder && 1 || 0,
82
+ borderTopColor: borderColor
82
83
  };
83
84
  };
84
85
  const headingStyles = {
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import PropTypes from 'prop-types';
2
3
  import View from "react-native-web/dist/exports/View";
3
4
  import Text from "react-native-web/dist/exports/Text";
4
5
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
@@ -39,6 +40,7 @@ const Pagination = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
39
40
  sideButtonTokens,
40
41
  LinkRouter,
41
42
  linkRouterProps,
43
+ numberOfPagesBeforeEllipsis = 4,
42
44
  ...rest
43
45
  } = _ref2;
44
46
  const viewport = useViewport();
@@ -78,7 +80,8 @@ const Pagination = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
78
80
  shouldRenderEllipsis
79
81
  } = usePagination({
80
82
  items,
81
- truncateAbove
83
+ truncateAbove,
84
+ numberOfPagesBeforeEllipsis
82
85
  });
83
86
  const ellipsisTextStyles = selectTextStyles(themeTokens, themeOptions);
84
87
  const ellipisContainerStyles = StyleSheet.create({
@@ -199,7 +202,11 @@ Pagination.propTypes = {
199
202
  /**
200
203
  * Custom tokens for `PaginationSideButton`
201
204
  */
202
- sideButtonTokens: getTokensPropType('PaginationSideButton')
205
+ sideButtonTokens: getTokensPropType('PaginationSideButton'),
206
+ /**
207
+ * The number of pages before the ellipsis is shown
208
+ */
209
+ numberOfPagesBeforeEllipsis: PropTypes.number
203
210
  };
204
211
  const staticStyles = StyleSheet.create({
205
212
  container: {
@@ -0,0 +1,3 @@
1
+ export const TRUNCATE_ABOVE_VALUE = 4;
2
+ export const MIN_PAGES_TO_SHOW = 3;
3
+ export const DEFAULT_PAGE_TO_SHOW_VALUE = 1;
@@ -1,14 +1,17 @@
1
+ import { DEFAULT_PAGE_TO_SHOW_VALUE, MIN_PAGES_TO_SHOW, TRUNCATE_ABOVE_VALUE } from './constants';
1
2
  /**
2
3
  * Handles configurable truncating of pagination items.
3
4
  *
4
5
  * @param {object} props
5
6
  * @param {React.Element[]} items
6
7
  * @param {number} truncateAbove
8
+ * @param {number} numberOfPagesBeforeEllipsis
7
9
  */
8
10
  function usePagination(_ref) {
9
11
  let {
10
12
  items,
11
- truncateAbove
13
+ truncateAbove,
14
+ numberOfPagesBeforeEllipsis
12
15
  } = _ref;
13
16
  const activeItemIndex = Math.max(items.findIndex(item => item.props.isActive), 0 // default to the first item if none is marked as active
14
17
  );
@@ -30,8 +33,15 @@ function usePagination(_ref) {
30
33
  tokens
31
34
  };
32
35
  };
33
- const windowSize = truncateAbove > 4 ? 3 : 1;
34
- const truncateEnabled = items.length > truncateAbove;
36
+ let windowSize;
37
+ if (numberOfPagesBeforeEllipsis >= 1 && numberOfPagesBeforeEllipsis < items.length) {
38
+ windowSize = numberOfPagesBeforeEllipsis;
39
+ } else if (truncateAbove > TRUNCATE_ABOVE_VALUE) {
40
+ windowSize = MIN_PAGES_TO_SHOW;
41
+ } else {
42
+ windowSize = DEFAULT_PAGE_TO_SHOW_VALUE;
43
+ }
44
+ const truncateEnabled = items.length > windowSize;
35
45
  const truncateWindowStart = windowSize;
36
46
  const truncateWindowEnd = items.length - 1 - windowSize;
37
47
 
@@ -119,9 +119,10 @@ const selectArrowStyles = (_ref4, _ref5) => {
119
119
  };
120
120
  };
121
121
  const selectTextStyles = tokens => applyTextStyles(selectTokens('Typography', tokens));
122
- const defaultControl = (pressableState, variant) => /*#__PURE__*/_jsx(TooltipButton, {
122
+ const defaultControl = (pressableState, variant, tokens) => /*#__PURE__*/_jsx(TooltipButton, {
123
123
  pressableState: pressableState,
124
- variant: variant
124
+ variant: variant,
125
+ tokens: tokens
125
126
  });
126
127
 
127
128
  /**
@@ -150,6 +151,8 @@ const Tooltip = /*#__PURE__*/React.forwardRef((_ref6, ref) => {
150
151
  variant,
151
152
  inline = false,
152
153
  nativeID,
154
+ activateOnHover = false,
155
+ tooltipButtonTokens,
153
156
  ...rest
154
157
  } = _ref6;
155
158
  const [isOpen, setIsOpen] = React.useState(false);
@@ -250,6 +253,31 @@ const Tooltip = /*#__PURE__*/React.forwardRef((_ref6, ref) => {
250
253
  }
251
254
  setTooltipPosition(updatedPosition);
252
255
  }, [isOpen, position, tooltipDimensions, controlLayout, windowDimensions, arrowWidth, arrowOffset, tooltipPosition]);
256
+ React.useEffect(() => {
257
+ if (Platform.OS !== 'web') {
258
+ return undefined;
259
+ }
260
+ const handleHover = event => {
261
+ if (activateOnHover) {
262
+ const isInsideControl = controlRef.current && controlRef.current.contains(event.target);
263
+ if (isInsideControl) {
264
+ if (!isOpen) {
265
+ setIsOpen(!isOpen);
266
+ }
267
+ } else {
268
+ close();
269
+ }
270
+ }
271
+ };
272
+ document.addEventListener('mouseover', handleHover, {
273
+ capture: true
274
+ });
275
+ return () => {
276
+ document.removeEventListener('mouseover', handleHover, {
277
+ capture: true
278
+ });
279
+ };
280
+ }, [controlLayout, activateOnHover, isOpen, onPress]);
253
281
  const control = children !== undefined ? children : defaultControl;
254
282
  const pressableStyles = control === defaultControl ? Platform.select({
255
283
  web: {
@@ -278,7 +306,7 @@ const Tooltip = /*#__PURE__*/React.forwardRef((_ref6, ref) => {
278
306
  accessibilityLabel: getCopy('a11yText'),
279
307
  accessibilityRole: "button",
280
308
  nativeID: nativeID,
281
- children: typeof control === 'function' ? pressableState => control(getPressableState(pressableState), variant) : control
309
+ children: typeof control === 'function' ? pressableState => control(getPressableState(pressableState), variant, tooltipButtonTokens) : control
282
310
  }), isOpen && /*#__PURE__*/_jsx(Backdrop, {
283
311
  onPress: close,
284
312
  children: /*#__PURE__*/_jsxs(View, {
@@ -30,6 +30,11 @@ const propTypes = {
30
30
  * The `id` of the tooltip button.
31
31
  */
32
32
  nativeID: PropTypes.string,
33
+ /**
34
+ * Set to `true` to open the tooltip on hover
35
+ */
36
+ activateOnHover: PropTypes.bool,
37
+ tooltipButtonTokens: getTokensPropType('TooltipButton'),
33
38
  tokens: getTokensPropType('Tooltip'),
34
39
  variant: variantProp.propType
35
40
  };
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.65.0",
14
+ "@telus-uds/system-theme-tokens": "^2.66.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.96.0",
89
+ "version": "1.97.0",
90
90
  "types": "types/index.d.ts"
91
91
  }
@@ -120,7 +120,7 @@ const selectPreviousNextNavigationButtonStyles = (
120
120
  }
121
121
 
122
122
  const getPeekingProps = (viewport) => {
123
- if (viewport === 'xs' || viewport === 'sm') {
123
+ if (viewport === 'xs' || viewport === 'sm' || viewport === 'md') {
124
124
  return {
125
125
  peekingFirstSpace: 48,
126
126
  peekingGap: 16,
@@ -20,43 +20,37 @@ const selectContainerStyle = ({
20
20
  totalItems,
21
21
  enablePeeking,
22
22
  peekingMarginLeft,
23
- peekingMarginRight,
24
23
  peekingFirstSpace,
25
24
  peekingLastSpace,
26
25
  peekingMiddleSpace,
27
26
  peekingGap,
28
27
  hidden
29
28
  }) => {
30
- const isFirst = elementIndex === 0
31
- const isLast = elementIndex === totalItems - 1
32
- const isMiddle = !isFirst && !isLast
33
- const isActive = activeIndex === elementIndex
34
-
35
29
  let adjustedWidth = width
36
30
  let marginLeft = 0
37
- let marginRight = 0
31
+ const marginRight = 0
38
32
 
39
33
  if (enablePeeking) {
40
- if (isActive) {
41
- adjustedWidth = width - (peekingMarginLeft + peekingGap + peekingFirstSpace)
42
- } else if (isMiddle) {
43
- adjustedWidth = width - peekingGap
44
- }
34
+ adjustedWidth = width - (peekingMarginLeft + peekingGap + peekingFirstSpace)
35
+ const isFirst = elementIndex === 0
36
+ const isActive = activeIndex === elementIndex
45
37
 
46
- if (isFirst) {
47
- if (isActive) {
38
+ if (isActive) {
39
+ if (isFirst) {
48
40
  marginLeft = peekingMarginLeft
49
- } else if (activeIndex === totalItems - 1) {
50
- marginLeft = peekingLastSpace
51
41
  } else {
52
- marginLeft = peekingMiddleSpace
42
+ marginLeft = peekingGap
43
+ }
44
+ } else if (isFirst) {
45
+ marginLeft = peekingMarginLeft + peekingGap + peekingFirstSpace + peekingMiddleSpace
46
+ if (activeIndex > 1) {
47
+ marginLeft += (peekingGap + peekingMiddleSpace * 2) * (activeIndex - 1)
48
+ }
49
+ if (activeIndex === totalItems - 1) {
50
+ marginLeft += peekingLastSpace - peekingMiddleSpace
53
51
  }
54
- }
55
-
56
- if (isLast && isActive) {
57
- marginRight = peekingMarginRight
58
52
  } else {
59
- marginRight = peekingGap
53
+ marginLeft = peekingGap
60
54
  }
61
55
  }
62
56
 
@@ -146,8 +146,7 @@ export default InputLabel
146
146
  const staticStyles = StyleSheet.create({
147
147
  container: {
148
148
  flexShrink: 1,
149
- flexDirection: 'row',
150
- alignItems: 'baseline'
149
+ flexDirection: 'row'
151
150
  },
152
151
  label: {
153
152
  flexShrink: 1
@@ -157,7 +156,7 @@ const staticStyles = StyleSheet.create({
157
156
  flexShrink: 0
158
157
  },
159
158
  tooltipAlign: {
160
- alignSelf: 'flex-start',
159
+ alignSelf: 'center',
161
160
  justifyContent: 'center'
162
161
  }
163
162
  })
@@ -107,7 +107,12 @@ const staticStyles = StyleSheet.create({
107
107
  flex: 1,
108
108
  flexDirection: 'row'
109
109
  },
110
- titleAndContentContainer: { flexDirection: 'column', flexShrink: 1, flexGrow: 1 }
110
+ titleAndContentContainer: {
111
+ flexDirection: 'column',
112
+ flexShrink: 1,
113
+ flexGrow: 1,
114
+ textAlign: 'justify'
115
+ }
111
116
  })
112
117
 
113
118
  ListItemBase.propTypes = {
@@ -48,6 +48,11 @@ const GroupControl = React.forwardRef(({ expanded, pressed, hover, focus, label,
48
48
  itemOutline,
49
49
  groupHeight
50
50
  } = tokens
51
+
52
+ const getTextStyles = () => ({
53
+ color: groupColor
54
+ })
55
+
51
56
  return (
52
57
  <View
53
58
  onPress={() => setSelectedId(id)}
@@ -71,7 +76,7 @@ const GroupControl = React.forwardRef(({ expanded, pressed, hover, focus, label,
71
76
  ]}
72
77
  ref={ref}
73
78
  >
74
- <Text>{label}</Text>
79
+ <Text style={getTextStyles()}>{label}</Text>
75
80
  <Spacer space={1} direction="row" />
76
81
  <Icon
77
82
  icon={tokens.groupIcon}
@@ -60,6 +60,7 @@ const ModalContent = React.forwardRef(
60
60
  borderColor,
61
61
  gap,
62
62
  direction,
63
+ footerTopWidth,
63
64
  hasBorder
64
65
  }) => ({
65
66
  flexDirection: direction,
@@ -70,8 +71,8 @@ const ModalContent = React.forwardRef(
70
71
  paddingLeft,
71
72
  paddingRight,
72
73
  paddingTop,
73
- borderTopColor: hasBorder ? borderColor : 'transparent',
74
- borderTopWidth: hasBorder ? 1 : 0
74
+ borderTopWidth: footerTopWidth > 0 ? footerTopWidth : (hasBorder && 1) || 0,
75
+ borderTopColor: borderColor
75
76
  })
76
77
 
77
78
  const headingStyles = {
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+ import PropTypes from 'prop-types'
2
3
  import { View, Text, StyleSheet } from 'react-native'
3
4
 
4
5
  import {
@@ -42,6 +43,7 @@ const Pagination = React.forwardRef(
42
43
  sideButtonTokens,
43
44
  LinkRouter,
44
45
  linkRouterProps,
46
+ numberOfPagesBeforeEllipsis = 4,
45
47
  ...rest
46
48
  },
47
49
  ref
@@ -80,7 +82,8 @@ const Pagination = React.forwardRef(
80
82
  shouldRenderEllipsis
81
83
  } = usePagination({
82
84
  items,
83
- truncateAbove
85
+ truncateAbove,
86
+ numberOfPagesBeforeEllipsis
84
87
  })
85
88
 
86
89
  const ellipsisTextStyles = selectTextStyles(themeTokens, themeOptions)
@@ -220,7 +223,11 @@ Pagination.propTypes = {
220
223
  /**
221
224
  * Custom tokens for `PaginationSideButton`
222
225
  */
223
- sideButtonTokens: getTokensPropType('PaginationSideButton')
226
+ sideButtonTokens: getTokensPropType('PaginationSideButton'),
227
+ /**
228
+ * The number of pages before the ellipsis is shown
229
+ */
230
+ numberOfPagesBeforeEllipsis: PropTypes.number
224
231
  }
225
232
 
226
233
  const staticStyles = StyleSheet.create({
@@ -0,0 +1,3 @@
1
+ export const TRUNCATE_ABOVE_VALUE = 4
2
+ export const MIN_PAGES_TO_SHOW = 3
3
+ export const DEFAULT_PAGE_TO_SHOW_VALUE = 1
@@ -1,11 +1,13 @@
1
+ import { DEFAULT_PAGE_TO_SHOW_VALUE, MIN_PAGES_TO_SHOW, TRUNCATE_ABOVE_VALUE } from './constants'
1
2
  /**
2
3
  * Handles configurable truncating of pagination items.
3
4
  *
4
5
  * @param {object} props
5
6
  * @param {React.Element[]} items
6
7
  * @param {number} truncateAbove
8
+ * @param {number} numberOfPagesBeforeEllipsis
7
9
  */
8
- function usePagination({ items, truncateAbove }) {
10
+ function usePagination({ items, truncateAbove, numberOfPagesBeforeEllipsis }) {
9
11
  const activeItemIndex = Math.max(
10
12
  items.findIndex((item) => item.props.isActive),
11
13
  0 // default to the first item if none is marked as active
@@ -16,8 +18,17 @@ function usePagination({ items, truncateAbove }) {
16
18
  return { onPress, href, hrefAttrs, variant, tokens }
17
19
  }
18
20
 
19
- const windowSize = truncateAbove > 4 ? 3 : 1
20
- const truncateEnabled = items.length > truncateAbove
21
+ let windowSize
22
+
23
+ if (numberOfPagesBeforeEllipsis >= 1 && numberOfPagesBeforeEllipsis < items.length) {
24
+ windowSize = numberOfPagesBeforeEllipsis
25
+ } else if (truncateAbove > TRUNCATE_ABOVE_VALUE) {
26
+ windowSize = MIN_PAGES_TO_SHOW
27
+ } else {
28
+ windowSize = DEFAULT_PAGE_TO_SHOW_VALUE
29
+ }
30
+
31
+ const truncateEnabled = items.length > windowSize
21
32
 
22
33
  const truncateWindowStart = windowSize
23
34
  const truncateWindowEnd = items.length - 1 - windowSize
@@ -88,8 +88,8 @@ const selectArrowStyles = (
88
88
  }
89
89
 
90
90
  const selectTextStyles = (tokens) => applyTextStyles(selectTokens('Typography', tokens))
91
- const defaultControl = (pressableState, variant) => (
92
- <TooltipButton pressableState={pressableState} variant={variant} />
91
+ const defaultControl = (pressableState, variant, tokens) => (
92
+ <TooltipButton pressableState={pressableState} variant={variant} tokens={tokens} />
93
93
  )
94
94
 
95
95
  /**
@@ -119,6 +119,8 @@ const Tooltip = React.forwardRef(
119
119
  variant,
120
120
  inline = false,
121
121
  nativeID,
122
+ activateOnHover = false,
123
+ tooltipButtonTokens,
122
124
  ...rest
123
125
  },
124
126
  ref
@@ -227,6 +229,31 @@ const Tooltip = React.forwardRef(
227
229
  tooltipPosition
228
230
  ])
229
231
 
232
+ React.useEffect(() => {
233
+ if (Platform.OS !== 'web') {
234
+ return undefined
235
+ }
236
+
237
+ const handleHover = (event) => {
238
+ if (activateOnHover) {
239
+ const isInsideControl = controlRef.current && controlRef.current.contains(event.target)
240
+ if (isInsideControl) {
241
+ if (!isOpen) {
242
+ setIsOpen(!isOpen)
243
+ }
244
+ } else {
245
+ close()
246
+ }
247
+ }
248
+ }
249
+
250
+ document.addEventListener('mouseover', handleHover, { capture: true })
251
+
252
+ return () => {
253
+ document.removeEventListener('mouseover', handleHover, { capture: true })
254
+ }
255
+ }, [controlLayout, activateOnHover, isOpen, onPress])
256
+
230
257
  const control = children !== undefined ? children : defaultControl
231
258
  const pressableStyles =
232
259
  control === defaultControl ? Platform.select({ web: { outline: 'none' } }) : undefined
@@ -256,7 +283,8 @@ const Tooltip = React.forwardRef(
256
283
  nativeID={nativeID}
257
284
  >
258
285
  {typeof control === 'function'
259
- ? (pressableState) => control(getPressableState(pressableState), variant)
286
+ ? (pressableState) =>
287
+ control(getPressableState(pressableState), variant, tooltipButtonTokens)
260
288
  : control}
261
289
  </Pressable>
262
290
  {isOpen && (
@@ -32,6 +32,11 @@ const propTypes = {
32
32
  * The `id` of the tooltip button.
33
33
  */
34
34
  nativeID: PropTypes.string,
35
+ /**
36
+ * Set to `true` to open the tooltip on hover
37
+ */
38
+ activateOnHover: PropTypes.bool,
39
+ tooltipButtonTokens: getTokensPropType('TooltipButton'),
35
40
  tokens: getTokensPropType('Tooltip'),
36
41
  variant: variantProp.propType
37
42
  }
@@ -0,0 +1,40 @@
1
+ import type { ComponentType } from 'react'
2
+
3
+ export interface FileUploadTokens {
4
+ buttonBackgroundColor?: string
5
+ buttonBorderColor?: string
6
+ buttonBorderRadius?: number
7
+ buttonBorderWidth?: string
8
+ buttonTextColor?: string
9
+ buttonHeight?: string
10
+ buttonMinWidth?: string
11
+ buttonWidth?: string
12
+ notificationBackgroundColor?: string
13
+ notificationBorderColor?: string
14
+ notificationBorderRadius?: number
15
+ notificationTextColor?: string
16
+ notificationDismissButtonGap?: string
17
+ notificationDismissIcon?: string
18
+ notificationDismissIconColor?: string
19
+ notificationIcon?: string
20
+ notificationIconColor?: string
21
+ notificationIconGap?: string
22
+ notificationIconSize?: number
23
+ }
24
+
25
+ export interface FileUploadProps {
26
+ tokens?: FileUploadTokens
27
+ variant?: Record<string, any>
28
+ copy?: 'en' | 'fr'
29
+ fileTypes?: string[]
30
+ allowMultipleFiles?: boolean
31
+ maxFileSize?: number
32
+ maxFilesCount?: number
33
+ onUpload?: (files: any) => void
34
+ onDelete?: (file: any) => void
35
+ documentPicker?: Record<string, any>
36
+ }
37
+
38
+ declare const FileUpload: ComponentType<FileUploadProps>
39
+
40
+ export default FileUpload
package/types/index.d.ts CHANGED
@@ -30,6 +30,9 @@ export {
30
30
  ExpandCollapsePanelProps
31
31
  } from './ExpandCollapse'
32
32
 
33
+ export { default as FileUpload } from './FileUpload'
34
+ export { FileUploadTokens, FileUploadProps } from './FileUpload'
35
+
33
36
  export { default as HorizontalScrollButton } from './HorizontalScrollButton'
34
37
  export { HorizontalScrollButtonTokens } from './HorizontalScrollButton'
35
38