@telus-uds/components-base 1.57.0 → 1.59.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 CHANGED
@@ -1,12 +1,30 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 28 Jul 2023 18:10:45 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 08 Aug 2023 23:51:39 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.59.0
8
+
9
+ Tue, 08 Aug 2023 23:51:39 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `MultiSelectFilter`: Add custom `dictionary` prop and custom callback for `onConfirm` and `onCancel` (shahzaibkhalidmalik@outlook.com)
14
+ - Added a Inverse story to Tabs stories (kyle.king2@telus.com)
15
+ - Bump @telus-uds/system-theme-tokens to v2.41.0
16
+
17
+ ## 1.58.0
18
+
19
+ Wed, 02 Aug 2023 18:13:48 GMT
20
+
21
+ ### Minor changes
22
+
23
+ - added condition on applying "raised" in Carousel for next/prev buttons (kyle.king2@telus.com)
24
+
7
25
  ## 1.57.0
8
26
 
9
- Fri, 28 Jul 2023 18:10:45 GMT
27
+ Fri, 28 Jul 2023 18:18:38 GMT
10
28
 
11
29
  ### Minor changes
12
30
 
@@ -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"
@@ -461,7 +461,8 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
461
461
 
462
462
  const previousNextIconButtonVariants = {
463
463
  size: previousNextIconSize,
464
- raised: true
464
+ raised: !(variant !== null && variant !== void 0 && variant.inverse) && true,
465
+ inverse: variant === null || variant === void 0 ? void 0 : variant.inverse
465
466
  };
466
467
 
467
468
  const getCopyWithPlaceholders = _react.default.useCallback(copyKey => {
@@ -104,7 +104,9 @@ const CarouselThumbnail = _ref2 => {
104
104
  pressed,
105
105
  focus: focused
106
106
  }));
107
- return [pressableStyles, index === activeIndex && styles.selected];
107
+ return [pressableStyles, index === activeIndex && styles.selected, {
108
+ outline: 'none'
109
+ }];
108
110
  },
109
111
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Image.default, {
110
112
  accessibilityIgnoresInvertColors: true,
@@ -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
  */
@@ -405,7 +405,8 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
405
405
 
406
406
  const previousNextIconButtonVariants = {
407
407
  size: previousNextIconSize,
408
- raised: true
408
+ raised: !(variant !== null && variant !== void 0 && variant.inverse) && true,
409
+ inverse: variant === null || variant === void 0 ? void 0 : variant.inverse
409
410
  };
410
411
  const getCopyWithPlaceholders = React.useCallback(copyKey => {
411
412
  const copyText = getCopy(copyKey).replace(/%\{title\}/g, title).replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, activeIndex + 1).replace(/%\{stepCount\}/g, childrenArray.length); // First word might be a lowercase placeholder: capitalize the first letter
@@ -88,7 +88,9 @@ const CarouselThumbnail = _ref2 => {
88
88
  pressed,
89
89
  focus: focused
90
90
  }));
91
- return [pressableStyles, index === activeIndex && styles.selected];
91
+ return [pressableStyles, index === activeIndex && styles.selected, {
92
+ outline: 'none'
93
+ }];
92
94
  },
93
95
  children: /*#__PURE__*/_jsx(Image, {
94
96
  accessibilityIgnoresInvertColors: true,
@@ -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
  */
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.57.0"
75
+ "version": "1.59.0"
76
76
  }
@@ -420,7 +420,11 @@ const Carousel = React.forwardRef(
420
420
  // @TODO: - these are Allium-theme variants and won't have any effect in themes that don't implement them.
421
421
  // Normally we avoid setting variants of subcomponents, however this could be re-considered.
422
422
  // Related discussion - https://github.com/telus/universal-design-system/issues/1549
423
- const previousNextIconButtonVariants = { size: previousNextIconSize, raised: true }
423
+ const previousNextIconButtonVariants = {
424
+ size: previousNextIconSize,
425
+ raised: !variant?.inverse && true,
426
+ inverse: variant?.inverse
427
+ }
424
428
 
425
429
  const getCopyWithPlaceholders = React.useCallback(
426
430
  (copyKey) => {
@@ -60,7 +60,13 @@ const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
60
60
  })
61
61
  )
62
62
 
63
- return [pressableStyles, index === activeIndex && styles.selected]
63
+ return [
64
+ pressableStyles,
65
+ index === activeIndex && styles.selected,
66
+ {
67
+ outline: 'none'
68
+ }
69
+ ]
64
70
  }}
65
71
  >
66
72
  <Image
@@ -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
  */