@telus-uds/components-base 1.58.0 → 1.59.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,16 +1,35 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Wed, 02 Aug 2023 18:10:10 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 21 Aug 2023 19:02:53 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.59.1
8
+
9
+ Mon, 21 Aug 2023 19:02:53 GMT
10
+
11
+ ### Patches
12
+
13
+ - Synced up event propagation to the relevant element taking `id` (shahzaibkhalidmalik@outlook.com)
14
+ - fixes on tooltip component (mauricio.batresmontejo@telus.com)
15
+
16
+ ## 1.59.0
17
+
18
+ Wed, 09 Aug 2023 00:02:59 GMT
19
+
20
+ ### Minor changes
21
+
22
+ - `MultiSelectFilter`: Add custom `dictionary` prop and custom callback for `onConfirm` and `onCancel` (shahzaibkhalidmalik@outlook.com)
23
+ - Added a Inverse story to Tabs stories (kyle.king2@telus.com)
24
+ - Bump @telus-uds/system-theme-tokens to v2.41.0
25
+
7
26
  ## 1.58.0
8
27
 
9
- Wed, 02 Aug 2023 18:10:10 GMT
28
+ Wed, 02 Aug 2023 18:13:48 GMT
10
29
 
11
30
  ### Minor changes
12
31
 
13
- - added condition on applying "raised" in Carousel for next/prev buttons (kyle.king2@telus.com)
32
+ - added condition on applying "raised" in Carousel for next/prev buttons (kyle.king2@telus.com)
14
33
 
15
34
  ## 1.57.0
16
35
 
@@ -76,7 +76,10 @@
76
76
  "fontName": "fontName",
77
77
  "fontSize": "fontSize",
78
78
  "lineHeight": "lineHeight",
79
- "stickyBackgroundColor": "color"
79
+ "stickyBackgroundColor": "color",
80
+ "fontColor": "color",
81
+ "borderColor": "color",
82
+ "borderWidth": "border"
80
83
  },
81
84
  "Image": {
82
85
  "borderRadius": "radius"
@@ -284,7 +287,8 @@
284
287
  "footnoteLinkColor": "color",
285
288
  "footnoteLinkFontName": "fontName",
286
289
  "footnoteLinkFontWeight": "fontWeight",
287
- "footnoteLinkFontSize": "fontSize"
290
+ "footnoteLinkFontSize": "fontSize",
291
+ "footnoteLinkLineHeight": "lineHeight"
288
292
  },
289
293
  "ActivityIndicator": {
290
294
  "size": "size",
@@ -7312,6 +7316,28 @@
7312
7316
  "required": false,
7313
7317
  "description": "If provided sets maxHeight to be active"
7314
7318
  },
7319
+ "onConfirm": {
7320
+ "defaultValue": {
7321
+ "value": "() => {}",
7322
+ "computed": false
7323
+ },
7324
+ "type": {
7325
+ "name": "func"
7326
+ },
7327
+ "required": false,
7328
+ "description": "If provided, this function is called when the selection is confirmed."
7329
+ },
7330
+ "onCancel": {
7331
+ "defaultValue": {
7332
+ "value": "() => {}",
7333
+ "computed": false
7334
+ },
7335
+ "type": {
7336
+ "name": "func"
7337
+ },
7338
+ "required": false,
7339
+ "description": "If provided, this function is called when `MultiSelectFilter` is closed."
7340
+ },
7315
7341
  "copy": {
7316
7342
  "defaultValue": {
7317
7343
  "value": "'en'",
@@ -7366,6 +7392,29 @@
7366
7392
  "required": false,
7367
7393
  "description": "Sets the maximum number of items in one column. If number of items are more\nthan the `rowLimit`, they will be rendered in 2 columns."
7368
7394
  },
7395
+ "dictionary": {
7396
+ "defaultValue": {
7397
+ "value": "{\n en: {\n filterByLabel: 'Filter by %{filterCategory}:',\n applyButtonLabel: 'Apply',\n clearButtonLabel: 'Clear'\n },\n fr: {\n filterByLabel: 'Filtrer par %{filterCategory}:',\n applyButtonLabel: 'Appliquer',\n clearButtonLabel: 'Effacer'\n }\n}",
7398
+ "computed": false
7399
+ },
7400
+ "type": {
7401
+ "name": "shape",
7402
+ "value": {
7403
+ "en": {
7404
+ "name": "custom",
7405
+ "raw": "dictionaryContentShape",
7406
+ "required": false
7407
+ },
7408
+ "fr": {
7409
+ "name": "custom",
7410
+ "raw": "dictionaryContentShape",
7411
+ "required": false
7412
+ }
7413
+ }
7414
+ },
7415
+ "required": false,
7416
+ "description": "Custom dictionary containing the labels"
7417
+ },
7369
7418
  "label": {
7370
7419
  "type": {
7371
7420
  "name": "string"
@@ -9079,6 +9128,13 @@
9079
9128
  },
9080
9129
  "required": false,
9081
9130
  "description": ""
9131
+ },
9132
+ "nativeSubmitBtnID": {
9133
+ "type": {
9134
+ "name": "string"
9135
+ },
9136
+ "required": false,
9137
+ "description": "ID for Submit button element on web"
9082
9138
  }
9083
9139
  },
9084
9140
  "attributes": {
@@ -13,6 +13,8 @@ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Vi
13
13
 
14
14
  var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
15
15
 
16
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
17
+
16
18
  var _propTypes = _interopRequireDefault(require("prop-types"));
17
19
 
18
20
  var _ThemeProvider = require("../ThemeProvider");
@@ -150,11 +152,11 @@ const ExpandCollapseControl = /*#__PURE__*/(0, _react.forwardRef)((_ref4, ref) =
150
152
  } = getControlTokens(pressableState);
151
153
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
152
154
  children: [IconComponent && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
153
- style: selectIconContainerStyles(themeTokens),
155
+ style: [selectIconContainerStyles(themeTokens), staticStyles.bubblePointerEvents],
154
156
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(IconComponent, { ...selectIconTokens(themeTokens)
155
157
  })
156
158
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
157
- style: selectTextContainerStyles(themeTokens),
159
+ style: [selectTextContainerStyles(themeTokens), staticStyles.bubblePointerEvents],
158
160
  children: typeof children === 'function' ? children(getControlState(pressableState)) : children
159
161
  })]
160
162
  });
@@ -162,6 +164,13 @@ const ExpandCollapseControl = /*#__PURE__*/(0, _react.forwardRef)((_ref4, ref) =
162
164
  });
163
165
  });
164
166
  ExpandCollapseControl.displayName = 'ExpandCollapseControl';
167
+
168
+ const staticStyles = _StyleSheet.default.create({
169
+ bubblePointerEvents: {
170
+ pointerEvents: 'none'
171
+ }
172
+ });
173
+
165
174
  ExpandCollapseControl.propTypes = { ...selectedSystemPropTypes,
166
175
  tokens: (0, _utils.getTokensPropType)('ExpandCollapseControl'),
167
176
  variant: _utils.variantProp.propType,
@@ -107,7 +107,12 @@ const selectInnerStyle = _ref2 => {
107
107
  paddingLeft: calculatePadding(paddingLeft, borderLeftWidth),
108
108
  paddingRight: calculatePadding(paddingRight, borderRightWidth),
109
109
  paddingTop: calculatePadding(paddingTop, borderTopWidth),
110
- paddingBottom: calculatePadding(paddingBottom, borderBottomWidth)
110
+ paddingBottom: calculatePadding(paddingBottom, borderBottomWidth),
111
+ ..._Platform.default.select({
112
+ web: {
113
+ pointerEvents: 'none'
114
+ }
115
+ })
111
116
  };
112
117
  };
113
118
  /**
@@ -93,10 +93,13 @@ const MultiSelectFilter = _ref3 => {
93
93
  initialValues,
94
94
  maxValues,
95
95
  onChange,
96
+ onConfirm = () => {},
97
+ onCancel = () => {},
96
98
  copy = 'en',
97
99
  readOnly = false,
98
100
  inactive = false,
99
101
  rowLimit = 12,
102
+ dictionary = _dictionary.default,
100
103
  ...rest
101
104
  } = _ref3;
102
105
  const viewport = (0, _ViewportProvider.useViewport)();
@@ -119,7 +122,7 @@ const MultiSelectFilter = _ref3 => {
119
122
  const getButtonTokens = buttonState => (0, _utils.selectTokens)('Button', getItemTokens(buttonState));
120
123
 
121
124
  const getCopy = (0, _utils.useCopy)({
122
- dictionary: _dictionary.default,
125
+ dictionary,
123
126
  copy
124
127
  });
125
128
  const colSizeNotMobile = items.length > rowLimit ? 2 : 1;
@@ -171,11 +174,19 @@ const MultiSelectFilter = _ref3 => {
171
174
  const onApply = e => {
172
175
  setValues(e);
173
176
  setIsOpen(false);
177
+ onConfirm(e);
174
178
  };
175
179
 
176
180
  const onClear = () => {
177
181
  setCheckedIds(() => []);
178
- onApply([]);
182
+ setValues([]);
183
+ setIsOpen(false);
184
+ onCancel();
185
+ };
186
+
187
+ const onClose = () => {
188
+ setIsOpen(false);
189
+ onCancel();
179
190
  };
180
191
 
181
192
  const {
@@ -230,7 +241,7 @@ const MultiSelectFilter = _ref3 => {
230
241
  inactive: inactive
231
242
  }, id), isOpen && viewport === 'xs' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Modal.default, {
232
243
  isOpen: isOpen,
233
- onClose: () => setIsOpen(false),
244
+ onClose: onClose,
234
245
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
235
246
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
236
247
  tokens: { ...headerStyles,
@@ -294,7 +305,7 @@ const MultiSelectFilter = _ref3 => {
294
305
  children: getCopy('applyButtonLabel')
295
306
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
296
307
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Link.TextButton, {
297
- onPress: () => onClear(),
308
+ onPress: onClear,
298
309
  children: getCopy('clearButtonLabel')
299
310
  })
300
311
  })]
@@ -302,7 +313,7 @@ const MultiSelectFilter = _ref3 => {
302
313
  })]
303
314
  }), isOpen && viewport !== 'xs' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_ModalOverlay.default, {
304
315
  overlaidPosition: overlaidPosition,
305
- onClose: () => setIsOpen(false),
316
+ onClose: onClose,
306
317
  maxHeight: maxHeight,
307
318
  maxHeightSize: maxHeightSize,
308
319
  maxWidthSize: maxWidthSize,
@@ -380,7 +391,7 @@ const MultiSelectFilter = _ref3 => {
380
391
  children: getCopy('applyButtonLabel')
381
392
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
382
393
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Link.TextButton, {
383
- onPress: () => onClear(),
394
+ onPress: onClear,
384
395
  children: getCopy('clearButtonLabel')
385
396
  })
386
397
  })]
@@ -396,6 +407,13 @@ const styles = _StyleSheet.default.create({
396
407
  textContainerStyle: {
397
408
  marginRight: 52
398
409
  }
410
+ }); // If a language dictionary entry is provided, it must contain every key
411
+
412
+
413
+ const dictionaryContentShape = _propTypes.default.shape({
414
+ filterByLabel: _propTypes.default.string.isRequired,
415
+ applyButtonLabel: _propTypes.default.string.isRequired,
416
+ clearButtonLabel: _propTypes.default.string.isRequired
399
417
  });
400
418
 
401
419
  MultiSelectFilter.propTypes = {
@@ -472,11 +490,29 @@ MultiSelectFilter.propTypes = {
472
490
  */
473
491
  onChange: _propTypes.default.func,
474
492
 
493
+ /**
494
+ * If provided, this function is called when the selection is confirmed.
495
+ */
496
+ onConfirm: _propTypes.default.func,
497
+
498
+ /**
499
+ * If provided, this function is called when `MultiSelectFilter` is closed.
500
+ * */
501
+ onCancel: _propTypes.default.func,
502
+
475
503
  /**
476
504
  * Select English or French copy for the accessible label.
477
505
  */
478
506
  copy: _propTypes.default.oneOf(['en', 'fr']),
479
507
 
508
+ /**
509
+ * Custom dictionary containing the labels
510
+ */
511
+ dictionary: _propTypes.default.shape({
512
+ en: dictionaryContentShape,
513
+ fr: dictionaryContentShape
514
+ }),
515
+
480
516
  /**
481
517
  * If true, the ButtonDropdown cannot be selected by the user and simply show their current state.
482
518
  */
@@ -98,6 +98,7 @@ const Search = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
98
98
  copy = 'en',
99
99
  tokens,
100
100
  variant,
101
+ nativeSubmitBtnID,
101
102
  ...rest
102
103
  } = _ref3;
103
104
  const {
@@ -195,6 +196,7 @@ const Search = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
195
196
  tokens: buttonState => selectButtonTokens(getButtonTokens({ ...buttonState,
196
197
  priority: 'high'
197
198
  })),
199
+ nativeID: nativeSubmitBtnID,
198
200
  children: buttonState => /*#__PURE__*/(0, _jsxRuntime.jsx)(SubmitButtonIcon, { ...selectIconTokens(getButtonTokens({ ...buttonState,
199
201
  priority: 'high'
200
202
  }))
@@ -262,7 +264,12 @@ Search.propTypes = { ...selectedContainerPropTypes,
262
264
  submitButtonAccessibilityLabel: _propTypes.default.string
263
265
  })]),
264
266
  tokens: (0, _utils.getTokensPropType)('Search'),
265
- variant: _utils.variantProp.propType
267
+ variant: _utils.variantProp.propType,
268
+
269
+ /**
270
+ * ID for Submit button element on web
271
+ */
272
+ nativeSubmitBtnID: _propTypes.default.string
266
273
  };
267
274
  var _default = Search;
268
275
  exports.default = _default;
package/lib/Tabs/Tabs.js CHANGED
@@ -132,6 +132,7 @@ const Tabs = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
132
132
  const itemProps = selectItemProps(itemRest);
133
133
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_TabsItem.default, {
134
134
  ref: itemRef,
135
+ id: itemId,
135
136
  href: href,
136
137
  variant: variant,
137
138
  tokens: itemTokens,
@@ -122,6 +122,7 @@ const TabsItem = /*#__PURE__*/(0, _react.forwardRef)((_ref4, ref) => {
122
122
  accessibilityState = accessibilityRole === 'tab' ? {
123
123
  selected
124
124
  } : undefined,
125
+ id,
125
126
  ...rawRest
126
127
  } = _ref4;
127
128
 
@@ -187,6 +188,7 @@ const TabsItem = /*#__PURE__*/(0, _react.forwardRef)((_ref4, ref) => {
187
188
  href: href,
188
189
  style: getPressableStyle,
189
190
  onLayout: handleLayout,
191
+ nativeID: id,
190
192
  ...selectedProps,
191
193
  children: pressableState => {
192
194
  const {
@@ -234,7 +236,8 @@ TabsItem.propTypes = { ...selectedSystemPropTypes,
234
236
  index: _propTypes.default.number,
235
237
  selected: _propTypes.default.bool,
236
238
  itemPositions: itemPositionsPropType,
237
- children: _propTypes.default.string
239
+ children: _propTypes.default.string,
240
+ id: _propTypes.default.string
238
241
  };
239
242
 
240
243
  const staticStyles = _StyleSheet.default.create({
@@ -250,7 +253,12 @@ const staticStyles = _StyleSheet.default.create({
250
253
  container: {
251
254
  flexGrow: 1,
252
255
  alignItems: 'center',
253
- justifyContent: 'center'
256
+ justifyContent: 'center',
257
+ ..._Platform.default.select({
258
+ web: {
259
+ pointerEvents: 'none'
260
+ }
261
+ })
254
262
  }
255
263
  });
256
264
 
@@ -125,14 +125,14 @@ const selectArrowStyles = (_ref4, _ref5) => {
125
125
  },
126
126
  left: {
127
127
  right: verticalOffset,
128
- top: tooltipHeight / 2 - horizontalOffset,
128
+ top: tooltipHeight <= 45 ? tooltipHeight / 2 - horizontalOffset : tooltipHeight - (tooltipHeight - 10),
129
129
  transform: [{
130
130
  rotateZ: '-45deg'
131
131
  }]
132
132
  },
133
133
  right: {
134
134
  left: verticalOffset,
135
- top: tooltipHeight / 2 - horizontalOffset,
135
+ top: tooltipHeight <= 45 ? tooltipHeight / 2 - horizontalOffset : tooltipHeight - (tooltipHeight - 10),
136
136
  transform: [{
137
137
  rotateZ: '135deg'
138
138
  }]
@@ -101,7 +101,7 @@ function getTooltipPosition(position, _ref2) {
101
101
  right: windowWidth - (controlX + controlWidth / 2 + tooltipWidth / 2)
102
102
  };
103
103
  const verticalBounds = {
104
- top: controlY + controlHeight / 2 - tooltipHeight / 2,
104
+ top: controlY,
105
105
  bottom: windowHeight - (controlY + controlHeight / 2 + tooltipHeight / 2)
106
106
  }; // calculate absolute coordinates for each of the potential positions (relative to window)
107
107
 
@@ -2,6 +2,7 @@ import React, { forwardRef } from 'react';
2
2
  import Pressable from "react-native-web/dist/exports/Pressable";
3
3
  import View from "react-native-web/dist/exports/View";
4
4
  import Platform from "react-native-web/dist/exports/Platform";
5
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
6
  import PropTypes from 'prop-types';
6
7
  import { useThemeTokensCallback, verticalAlignRow } from '../ThemeProvider';
7
8
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
@@ -131,11 +132,11 @@ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref4, ref) => {
131
132
  } = getControlTokens(pressableState);
132
133
  return /*#__PURE__*/_jsxs(_Fragment, {
133
134
  children: [IconComponent && /*#__PURE__*/_jsx(View, {
134
- style: selectIconContainerStyles(themeTokens),
135
+ style: [selectIconContainerStyles(themeTokens), staticStyles.bubblePointerEvents],
135
136
  children: /*#__PURE__*/_jsx(IconComponent, { ...selectIconTokens(themeTokens)
136
137
  })
137
138
  }), /*#__PURE__*/_jsx(View, {
138
- style: selectTextContainerStyles(themeTokens),
139
+ style: [selectTextContainerStyles(themeTokens), staticStyles.bubblePointerEvents],
139
140
  children: typeof children === 'function' ? children(getControlState(pressableState)) : children
140
141
  })]
141
142
  });
@@ -143,6 +144,11 @@ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref4, ref) => {
143
144
  });
144
145
  });
145
146
  ExpandCollapseControl.displayName = 'ExpandCollapseControl';
147
+ const staticStyles = StyleSheet.create({
148
+ bubblePointerEvents: {
149
+ pointerEvents: 'none'
150
+ }
151
+ });
146
152
  ExpandCollapseControl.propTypes = { ...selectedSystemPropTypes,
147
153
  tokens: getTokensPropType('ExpandCollapseControl'),
148
154
  variant: variantProp.propType,
@@ -84,7 +84,12 @@ const selectInnerStyle = _ref2 => {
84
84
  paddingLeft: calculatePadding(paddingLeft, borderLeftWidth),
85
85
  paddingRight: calculatePadding(paddingRight, borderRightWidth),
86
86
  paddingTop: calculatePadding(paddingTop, borderTopWidth),
87
- paddingBottom: calculatePadding(paddingBottom, borderBottomWidth)
87
+ paddingBottom: calculatePadding(paddingBottom, borderBottomWidth),
88
+ ...Platform.select({
89
+ web: {
90
+ pointerEvents: 'none'
91
+ }
92
+ })
88
93
  };
89
94
  };
90
95
  /**
@@ -4,7 +4,7 @@ import View from "react-native-web/dist/exports/View";
4
4
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
5
  import { useThemeTokens, useThemeTokensCallback, applyTextStyles } from '../ThemeProvider';
6
6
  import { containUniqueFields, getTokensPropType, getPressHandlersWithArgs, selectTokens, useOverlaidPosition, useCopy, useMultipleInputValues, useResponsiveProp, variantProp } from '../utils';
7
- import dictionary from './dictionary';
7
+ import defaultDictionary from './dictionary';
8
8
  import { useViewport } from '../ViewportProvider';
9
9
  import Box from '../Box';
10
10
  import { Button, ButtonDropdown } from '../Button';
@@ -62,10 +62,13 @@ const MultiSelectFilter = _ref3 => {
62
62
  initialValues,
63
63
  maxValues,
64
64
  onChange,
65
+ onConfirm = () => {},
66
+ onCancel = () => {},
65
67
  copy = 'en',
66
68
  readOnly = false,
67
69
  inactive = false,
68
70
  rowLimit = 12,
71
+ dictionary = defaultDictionary,
69
72
  ...rest
70
73
  } = _ref3;
71
74
  const viewport = useViewport();
@@ -140,11 +143,19 @@ const MultiSelectFilter = _ref3 => {
140
143
  const onApply = e => {
141
144
  setValues(e);
142
145
  setIsOpen(false);
146
+ onConfirm(e);
143
147
  };
144
148
 
145
149
  const onClear = () => {
146
150
  setCheckedIds(() => []);
147
- onApply([]);
151
+ setValues([]);
152
+ setIsOpen(false);
153
+ onCancel();
154
+ };
155
+
156
+ const onClose = () => {
157
+ setIsOpen(false);
158
+ onCancel();
148
159
  };
149
160
 
150
161
  const {
@@ -199,7 +210,7 @@ const MultiSelectFilter = _ref3 => {
199
210
  inactive: inactive
200
211
  }, id), isOpen && viewport === 'xs' && /*#__PURE__*/_jsxs(Modal, {
201
212
  isOpen: isOpen,
202
- onClose: () => setIsOpen(false),
213
+ onClose: onClose,
203
214
  children: [/*#__PURE__*/_jsx(Row, {
204
215
  children: /*#__PURE__*/_jsx(Typography, {
205
216
  tokens: { ...headerStyles,
@@ -263,7 +274,7 @@ const MultiSelectFilter = _ref3 => {
263
274
  children: getCopy('applyButtonLabel')
264
275
  }), /*#__PURE__*/_jsx(Box, {
265
276
  children: /*#__PURE__*/_jsx(TextButton, {
266
- onPress: () => onClear(),
277
+ onPress: onClear,
267
278
  children: getCopy('clearButtonLabel')
268
279
  })
269
280
  })]
@@ -271,7 +282,7 @@ const MultiSelectFilter = _ref3 => {
271
282
  })]
272
283
  }), isOpen && viewport !== 'xs' && /*#__PURE__*/_jsxs(ModalOverlay, {
273
284
  overlaidPosition: overlaidPosition,
274
- onClose: () => setIsOpen(false),
285
+ onClose: onClose,
275
286
  maxHeight: maxHeight,
276
287
  maxHeightSize: maxHeightSize,
277
288
  maxWidthSize: maxWidthSize,
@@ -349,7 +360,7 @@ const MultiSelectFilter = _ref3 => {
349
360
  children: getCopy('applyButtonLabel')
350
361
  }), /*#__PURE__*/_jsx(Box, {
351
362
  children: /*#__PURE__*/_jsx(TextButton, {
352
- onPress: () => onClear(),
363
+ onPress: onClear,
353
364
  children: getCopy('clearButtonLabel')
354
365
  })
355
366
  })]
@@ -364,6 +375,12 @@ const styles = StyleSheet.create({
364
375
  textContainerStyle: {
365
376
  marginRight: 52
366
377
  }
378
+ }); // If a language dictionary entry is provided, it must contain every key
379
+
380
+ const dictionaryContentShape = PropTypes.shape({
381
+ filterByLabel: PropTypes.string.isRequired,
382
+ applyButtonLabel: PropTypes.string.isRequired,
383
+ clearButtonLabel: PropTypes.string.isRequired
367
384
  });
368
385
  MultiSelectFilter.propTypes = {
369
386
  /**
@@ -439,11 +456,29 @@ MultiSelectFilter.propTypes = {
439
456
  */
440
457
  onChange: PropTypes.func,
441
458
 
459
+ /**
460
+ * If provided, this function is called when the selection is confirmed.
461
+ */
462
+ onConfirm: PropTypes.func,
463
+
464
+ /**
465
+ * If provided, this function is called when `MultiSelectFilter` is closed.
466
+ * */
467
+ onCancel: PropTypes.func,
468
+
442
469
  /**
443
470
  * Select English or French copy for the accessible label.
444
471
  */
445
472
  copy: PropTypes.oneOf(['en', 'fr']),
446
473
 
474
+ /**
475
+ * Custom dictionary containing the labels
476
+ */
477
+ dictionary: PropTypes.shape({
478
+ en: dictionaryContentShape,
479
+ fr: dictionaryContentShape
480
+ }),
481
+
447
482
  /**
448
483
  * If true, the ButtonDropdown cannot be selected by the user and simply show their current state.
449
484
  */
@@ -75,6 +75,7 @@ const Search = /*#__PURE__*/forwardRef((_ref3, ref) => {
75
75
  copy = 'en',
76
76
  tokens,
77
77
  variant,
78
+ nativeSubmitBtnID,
78
79
  ...rest
79
80
  } = _ref3;
80
81
  const {
@@ -172,6 +173,7 @@ const Search = /*#__PURE__*/forwardRef((_ref3, ref) => {
172
173
  tokens: buttonState => selectButtonTokens(getButtonTokens({ ...buttonState,
173
174
  priority: 'high'
174
175
  })),
176
+ nativeID: nativeSubmitBtnID,
175
177
  children: buttonState => /*#__PURE__*/_jsx(SubmitButtonIcon, { ...selectIconTokens(getButtonTokens({ ...buttonState,
176
178
  priority: 'high'
177
179
  }))
@@ -239,6 +241,11 @@ Search.propTypes = { ...selectedContainerPropTypes,
239
241
  submitButtonAccessibilityLabel: PropTypes.string
240
242
  })]),
241
243
  tokens: getTokensPropType('Search'),
242
- variant: variantProp.propType
244
+ variant: variantProp.propType,
245
+
246
+ /**
247
+ * ID for Submit button element on web
248
+ */
249
+ nativeSubmitBtnID: PropTypes.string
243
250
  };
244
251
  export default Search;
@@ -110,6 +110,7 @@ const Tabs = /*#__PURE__*/forwardRef((_ref, ref) => {
110
110
  const itemProps = selectItemProps(itemRest);
111
111
  return /*#__PURE__*/_jsx(TabsItem, {
112
112
  ref: itemRef,
113
+ id: itemId,
113
114
  href: href,
114
115
  variant: variant,
115
116
  tokens: itemTokens,
@@ -98,6 +98,7 @@ const TabsItem = /*#__PURE__*/forwardRef((_ref4, ref) => {
98
98
  accessibilityState = accessibilityRole === 'tab' ? {
99
99
  selected
100
100
  } : undefined,
101
+ id,
101
102
  ...rawRest
102
103
  } = _ref4;
103
104
  // Convert onClick etc to onPress etc if used in an integration
@@ -160,6 +161,7 @@ const TabsItem = /*#__PURE__*/forwardRef((_ref4, ref) => {
160
161
  href: href,
161
162
  style: getPressableStyle,
162
163
  onLayout: handleLayout,
164
+ nativeID: id,
163
165
  ...selectedProps,
164
166
  children: pressableState => {
165
167
  const {
@@ -207,7 +209,8 @@ TabsItem.propTypes = { ...selectedSystemPropTypes,
207
209
  index: PropTypes.number,
208
210
  selected: PropTypes.bool,
209
211
  itemPositions: itemPositionsPropType,
210
- children: PropTypes.string
212
+ children: PropTypes.string,
213
+ id: PropTypes.string
211
214
  };
212
215
  const staticStyles = StyleSheet.create({
213
216
  center: {
@@ -222,7 +225,12 @@ const staticStyles = StyleSheet.create({
222
225
  container: {
223
226
  flexGrow: 1,
224
227
  alignItems: 'center',
225
- justifyContent: 'center'
228
+ justifyContent: 'center',
229
+ ...Platform.select({
230
+ web: {
231
+ pointerEvents: 'none'
232
+ }
233
+ })
226
234
  }
227
235
  });
228
236
  export default withLinkRouter(TabsItem);
@@ -97,14 +97,14 @@ const selectArrowStyles = (_ref4, _ref5) => {
97
97
  },
98
98
  left: {
99
99
  right: verticalOffset,
100
- top: tooltipHeight / 2 - horizontalOffset,
100
+ top: tooltipHeight <= 45 ? tooltipHeight / 2 - horizontalOffset : tooltipHeight - (tooltipHeight - 10),
101
101
  transform: [{
102
102
  rotateZ: '-45deg'
103
103
  }]
104
104
  },
105
105
  right: {
106
106
  left: verticalOffset,
107
- top: tooltipHeight / 2 - horizontalOffset,
107
+ top: tooltipHeight <= 45 ? tooltipHeight / 2 - horizontalOffset : tooltipHeight - (tooltipHeight - 10),
108
108
  transform: [{
109
109
  rotateZ: '135deg'
110
110
  }]
@@ -94,7 +94,7 @@ function getTooltipPosition(position, _ref2) {
94
94
  right: windowWidth - (controlX + controlWidth / 2 + tooltipWidth / 2)
95
95
  };
96
96
  const verticalBounds = {
97
- top: controlY + controlHeight / 2 - tooltipHeight / 2,
97
+ top: controlY,
98
98
  bottom: windowHeight - (controlY + controlHeight / 2 + tooltipHeight / 2)
99
99
  }; // calculate absolute coordinates for each of the potential positions (relative to window)
100
100
 
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.40.0",
14
+ "@telus-uds/system-theme-tokens": "^2.41.0",
15
15
  "airbnb-prop-types": "^2.16.0",
16
16
  "lodash.debounce": "^4.0.8",
17
17
  "lodash.merge": "^4.6.2",
@@ -72,5 +72,5 @@
72
72
  "standard-engine": {
73
73
  "skip": true
74
74
  },
75
- "version": "1.58.0"
75
+ "version": "1.59.1"
76
76
  }
@@ -1,5 +1,5 @@
1
1
  import React, { forwardRef } from 'react'
2
- import { Pressable, View, Platform } from 'react-native'
2
+ import { Pressable, View, Platform, StyleSheet } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
 
5
5
  import { useThemeTokensCallback, verticalAlignRow } from '../ThemeProvider'
@@ -101,11 +101,15 @@ const ExpandCollapseControl = forwardRef(
101
101
  return (
102
102
  <>
103
103
  {IconComponent && (
104
- <View style={selectIconContainerStyles(themeTokens)}>
104
+ <View
105
+ style={[selectIconContainerStyles(themeTokens), staticStyles.bubblePointerEvents]}
106
+ >
105
107
  <IconComponent {...selectIconTokens(themeTokens)} />
106
108
  </View>
107
109
  )}
108
- <View style={selectTextContainerStyles(themeTokens)}>
110
+ <View
111
+ style={[selectTextContainerStyles(themeTokens), staticStyles.bubblePointerEvents]}
112
+ >
109
113
  {typeof children === 'function'
110
114
  ? children(getControlState(pressableState))
111
115
  : children}
@@ -119,6 +123,12 @@ const ExpandCollapseControl = forwardRef(
119
123
  )
120
124
  ExpandCollapseControl.displayName = 'ExpandCollapseControl'
121
125
 
126
+ const staticStyles = StyleSheet.create({
127
+ bubblePointerEvents: {
128
+ pointerEvents: 'none'
129
+ }
130
+ })
131
+
122
132
  ExpandCollapseControl.propTypes = {
123
133
  ...selectedSystemPropTypes,
124
134
  tokens: getTokensPropType('ExpandCollapseControl'),
@@ -86,7 +86,12 @@ const selectInnerStyle = ({
86
86
  paddingLeft: calculatePadding(paddingLeft, borderLeftWidth),
87
87
  paddingRight: calculatePadding(paddingRight, borderRightWidth),
88
88
  paddingTop: calculatePadding(paddingTop, borderTopWidth),
89
- paddingBottom: calculatePadding(paddingBottom, borderBottomWidth)
89
+ paddingBottom: calculatePadding(paddingBottom, borderBottomWidth),
90
+ ...Platform.select({
91
+ web: {
92
+ pointerEvents: 'none'
93
+ }
94
+ })
90
95
  })
91
96
 
92
97
  /**
@@ -14,7 +14,7 @@ import {
14
14
  useResponsiveProp,
15
15
  variantProp
16
16
  } from '../utils'
17
- import dictionary from './dictionary'
17
+ import defaultDictionary from './dictionary'
18
18
  import { useViewport } from '../ViewportProvider'
19
19
  import Box from '../Box'
20
20
  import { Button, ButtonDropdown } from '../Button'
@@ -53,10 +53,13 @@ const MultiSelectFilter = ({
53
53
  initialValues,
54
54
  maxValues,
55
55
  onChange,
56
+ onConfirm = () => {},
57
+ onCancel = () => {},
56
58
  copy = 'en',
57
59
  readOnly = false,
58
60
  inactive = false,
59
61
  rowLimit = 12,
62
+ dictionary = defaultDictionary,
60
63
  ...rest
61
64
  }) => {
62
65
  const viewport = useViewport()
@@ -116,11 +119,19 @@ const MultiSelectFilter = ({
116
119
  const onApply = (e) => {
117
120
  setValues(e)
118
121
  setIsOpen(false)
122
+ onConfirm(e)
119
123
  }
120
124
 
121
125
  const onClear = () => {
122
126
  setCheckedIds(() => [])
123
- onApply([])
127
+ setValues([])
128
+ setIsOpen(false)
129
+ onCancel()
130
+ }
131
+
132
+ const onClose = () => {
133
+ setIsOpen(false)
134
+ onCancel()
124
135
  }
125
136
 
126
137
  const { align, offsets } = useResponsiveProp({
@@ -163,7 +174,7 @@ const MultiSelectFilter = ({
163
174
  inactive={inactive}
164
175
  />
165
176
  {isOpen && viewport === 'xs' && (
166
- <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
177
+ <Modal isOpen={isOpen} onClose={onClose}>
167
178
  <Row>
168
179
  <Typography tokens={{ ...headerStyles, lineHeight: headerLineHeight }}>
169
180
  {getCopy('filterByLabel').replace(/%\{filterCategory\}/g, label.toLowerCase())}
@@ -215,7 +226,7 @@ const MultiSelectFilter = ({
215
226
  {getCopy('applyButtonLabel')}
216
227
  </Button>
217
228
  <Box>
218
- <TextButton onPress={() => onClear()}>{getCopy('clearButtonLabel')}</TextButton>
229
+ <TextButton onPress={onClear}>{getCopy('clearButtonLabel')}</TextButton>
219
230
  </Box>
220
231
  </StackView>
221
232
  </Row>
@@ -224,7 +235,7 @@ const MultiSelectFilter = ({
224
235
  {isOpen && viewport !== 'xs' && (
225
236
  <ModalOverlay
226
237
  overlaidPosition={overlaidPosition}
227
- onClose={() => setIsOpen(false)}
238
+ onClose={onClose}
228
239
  maxHeight={maxHeight}
229
240
  maxHeightSize={maxHeightSize}
230
241
  maxWidthSize={maxWidthSize}
@@ -291,7 +302,7 @@ const MultiSelectFilter = ({
291
302
  {getCopy('applyButtonLabel')}
292
303
  </Button>
293
304
  <Box>
294
- <TextButton onPress={() => onClear()}>{getCopy('clearButtonLabel')}</TextButton>
305
+ <TextButton onPress={onClear}>{getCopy('clearButtonLabel')}</TextButton>
295
306
  </Box>
296
307
  </StackView>
297
308
  </Row>
@@ -307,6 +318,13 @@ const styles = StyleSheet.create({
307
318
  textContainerStyle: { marginRight: 52 }
308
319
  })
309
320
 
321
+ // If a language dictionary entry is provided, it must contain every key
322
+ const dictionaryContentShape = PropTypes.shape({
323
+ filterByLabel: PropTypes.string.isRequired,
324
+ applyButtonLabel: PropTypes.string.isRequired,
325
+ clearButtonLabel: PropTypes.string.isRequired
326
+ })
327
+
310
328
  MultiSelectFilter.propTypes = {
311
329
  /**
312
330
  * The text displayed to the user in a ButtonDropdown.
@@ -370,12 +388,26 @@ MultiSelectFilter.propTypes = {
370
388
  * If provided, this function is called when the current selection is changed
371
389
  * and is passed an array of the `id`s of all currently selected `items`.
372
390
  */
373
-
374
391
  onChange: PropTypes.func,
392
+ /**
393
+ * If provided, this function is called when the selection is confirmed.
394
+ */
395
+ onConfirm: PropTypes.func,
396
+ /**
397
+ * If provided, this function is called when `MultiSelectFilter` is closed.
398
+ * */
399
+ onCancel: PropTypes.func,
375
400
  /**
376
401
  * Select English or French copy for the accessible label.
377
402
  */
378
403
  copy: PropTypes.oneOf(['en', 'fr']),
404
+ /**
405
+ * Custom dictionary containing the labels
406
+ */
407
+ dictionary: PropTypes.shape({
408
+ en: dictionaryContentShape,
409
+ fr: dictionaryContentShape
410
+ }),
379
411
  /**
380
412
  * If true, the ButtonDropdown cannot be selected by the user and simply show their current state.
381
413
  */
@@ -71,6 +71,7 @@ const Search = forwardRef(
71
71
  copy = 'en',
72
72
  tokens,
73
73
  variant,
74
+ nativeSubmitBtnID,
74
75
  ...rest
75
76
  },
76
77
  ref
@@ -173,6 +174,7 @@ const Search = forwardRef(
173
174
  tokens={(buttonState) =>
174
175
  selectButtonTokens(getButtonTokens({ ...buttonState, priority: 'high' }))
175
176
  }
177
+ nativeID={nativeSubmitBtnID}
176
178
  >
177
179
  {(buttonState) => (
178
180
  <SubmitButtonIcon
@@ -242,7 +244,11 @@ Search.propTypes = {
242
244
  })
243
245
  ]),
244
246
  tokens: getTokensPropType('Search'),
245
- variant: variantProp.propType
247
+ variant: variantProp.propType,
248
+ /**
249
+ * ID for Submit button element on web
250
+ */
251
+ nativeSubmitBtnID: PropTypes.string
246
252
  }
247
253
 
248
254
  export default Search
package/src/Tabs/Tabs.jsx CHANGED
@@ -127,6 +127,7 @@ const Tabs = forwardRef(
127
127
  <TabsItem
128
128
  ref={itemRef}
129
129
  key={itemId}
130
+ id={itemId}
130
131
  href={href}
131
132
  variant={variant}
132
133
  tokens={itemTokens}
@@ -91,6 +91,7 @@ const TabsItem = forwardRef(
91
91
  ? 'page'
92
92
  : undefined,
93
93
  accessibilityState = accessibilityRole === 'tab' ? { selected } : undefined,
94
+ id,
94
95
  ...rawRest
95
96
  },
96
97
  ref
@@ -150,6 +151,7 @@ const TabsItem = forwardRef(
150
151
  href={href}
151
152
  style={getPressableStyle}
152
153
  onLayout={handleLayout}
154
+ nativeID={id}
153
155
  {...selectedProps}
154
156
  >
155
157
  {(pressableState) => {
@@ -199,7 +201,8 @@ TabsItem.propTypes = {
199
201
  index: PropTypes.number,
200
202
  selected: PropTypes.bool,
201
203
  itemPositions: itemPositionsPropType,
202
- children: PropTypes.string
204
+ children: PropTypes.string,
205
+ id: PropTypes.string
203
206
  }
204
207
 
205
208
  const staticStyles = StyleSheet.create({
@@ -215,7 +218,12 @@ const staticStyles = StyleSheet.create({
215
218
  container: {
216
219
  flexGrow: 1,
217
220
  alignItems: 'center',
218
- justifyContent: 'center'
221
+ justifyContent: 'center',
222
+ ...Platform.select({
223
+ web: {
224
+ pointerEvents: 'none'
225
+ }
226
+ })
219
227
  }
220
228
  })
221
229
 
@@ -61,12 +61,18 @@ const selectArrowStyles = (
61
61
  },
62
62
  left: {
63
63
  right: verticalOffset,
64
- top: tooltipHeight / 2 - horizontalOffset,
64
+ top:
65
+ tooltipHeight <= 45
66
+ ? tooltipHeight / 2 - horizontalOffset
67
+ : tooltipHeight - (tooltipHeight - 10),
65
68
  transform: [{ rotateZ: '-45deg' }]
66
69
  },
67
70
  right: {
68
71
  left: verticalOffset,
69
- top: tooltipHeight / 2 - horizontalOffset,
72
+ top:
73
+ tooltipHeight <= 45
74
+ ? tooltipHeight / 2 - horizontalOffset
75
+ : tooltipHeight - (tooltipHeight - 10),
70
76
  transform: [{ rotateZ: '135deg' }]
71
77
  }
72
78
  }
@@ -71,7 +71,7 @@ function getTooltipPosition(
71
71
  }
72
72
 
73
73
  const verticalBounds = {
74
- top: controlY + controlHeight / 2 - tooltipHeight / 2,
74
+ top: controlY,
75
75
  bottom: windowHeight - (controlY + controlHeight / 2 + tooltipHeight / 2)
76
76
  }
77
77