@telus-uds/components-web 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/.eslintignore +2 -0
  2. package/.vscode/settings.json +7 -0
  3. package/CHANGELOG.md +39 -2
  4. package/lib/Autocomplete/Autocomplete.js +393 -0
  5. package/lib/Autocomplete/Loading.js +51 -0
  6. package/lib/Autocomplete/Suggestions.js +81 -0
  7. package/lib/Autocomplete/constants.js +19 -0
  8. package/lib/Autocomplete/dictionary.js +19 -0
  9. package/lib/Autocomplete/index.js +13 -0
  10. package/lib/BlockQuote/BlockQuote.js +173 -0
  11. package/lib/BlockQuote/index.js +13 -0
  12. package/lib/Callout/Callout.js +3 -0
  13. package/lib/Card/Card.js +180 -0
  14. package/lib/Card/CardContent.js +110 -0
  15. package/lib/Card/CardFooter.js +98 -0
  16. package/lib/Card/index.js +13 -0
  17. package/lib/Countdown/Countdown.js +189 -0
  18. package/lib/Countdown/Segment.js +111 -0
  19. package/lib/Countdown/constants.js +14 -0
  20. package/lib/Countdown/dictionary.js +29 -0
  21. package/lib/Countdown/index.js +13 -0
  22. package/lib/Countdown/types.js +39 -0
  23. package/lib/Countdown/useCountdown.js +40 -0
  24. package/lib/IconButton/IconButton.js +70 -0
  25. package/lib/IconButton/index.js +13 -0
  26. package/lib/Listbox/GroupControl.js +94 -0
  27. package/lib/Listbox/Listbox.js +164 -0
  28. package/lib/Listbox/ListboxGroup.js +129 -0
  29. package/lib/Listbox/ListboxItem.js +137 -0
  30. package/lib/Listbox/ListboxOverlay.js +89 -0
  31. package/lib/Listbox/PressableItem.js +149 -0
  32. package/lib/Listbox/index.js +13 -0
  33. package/lib/Modal/ModalContent.js +11 -4
  34. package/lib/NavigationBar/resolveItemSelection.js +24 -0
  35. package/lib/OptimizeImage/OptimizeImage.js +127 -0
  36. package/lib/OptimizeImage/index.js +13 -0
  37. package/lib/OptimizeImage/utils/getFallbackUrl.js +18 -0
  38. package/lib/OptimizeImage/utils/getOptimizedUrl.js +32 -0
  39. package/lib/OptimizeImage/utils/hasWebpSupport.js +38 -0
  40. package/lib/OptimizeImage/utils/index.js +31 -0
  41. package/lib/OptimizeImage/utils/isSvgUrl.js +10 -0
  42. package/lib/QuantitySelector/QuantitySelector.js +253 -0
  43. package/lib/QuantitySelector/dictionary.js +33 -0
  44. package/lib/QuantitySelector/index.js +13 -0
  45. package/lib/QuantitySelector/styles.js +40 -0
  46. package/lib/StoryCard/StoryCard.js +244 -0
  47. package/lib/StoryCard/index.js +13 -0
  48. package/lib/TermsAndConditions/ExpandCollapse.js +141 -0
  49. package/lib/TermsAndConditions/TermsAndConditions.js +221 -0
  50. package/lib/TermsAndConditions/dictionary.js +19 -0
  51. package/lib/TermsAndConditions/index.js +15 -0
  52. package/lib/Testimonial/Testimonial.js +226 -0
  53. package/lib/Testimonial/index.js +13 -0
  54. package/lib/Video/ControlBar/ControlBar.js +315 -0
  55. package/lib/Video/ControlBar/Controls/VideoButton/VideoButton.js +91 -0
  56. package/lib/Video/ControlBar/Controls/VideoMenu/VideoMenu.js +186 -0
  57. package/lib/Video/ControlBar/Controls/VideoProgressBar/VideoProgressBar.js +221 -0
  58. package/lib/Video/ControlBar/Controls/VolumeSlider/VolumeSlider.js +213 -0
  59. package/lib/Video/MiddleControlButton/MiddleControlButton.js +89 -0
  60. package/lib/Video/Video.js +1072 -0
  61. package/lib/Video/index.js +13 -0
  62. package/lib/Video/videoText.js +62 -0
  63. package/lib/WebVideo/WebVideo.js +170 -0
  64. package/lib/WebVideo/index.js +13 -0
  65. package/lib/baseExports.js +0 -12
  66. package/lib/index.js +118 -1
  67. package/lib/shared/VideoSplash/SplashButton/SplashButton.js +102 -0
  68. package/lib/shared/VideoSplash/SplashButtonWithDetails/SplashButtonWithDetails.js +234 -0
  69. package/lib/shared/VideoSplash/VideoSplash.js +86 -0
  70. package/lib/shared/VideoSplash/helpers.js +38 -0
  71. package/lib/utils/index.js +8 -0
  72. package/lib/utils/useOverlaidPosition.js +246 -0
  73. package/lib-module/Autocomplete/Autocomplete.js +369 -0
  74. package/lib-module/Autocomplete/Loading.js +38 -0
  75. package/lib-module/Autocomplete/Suggestions.js +64 -0
  76. package/lib-module/Autocomplete/constants.js +5 -0
  77. package/lib-module/Autocomplete/dictionary.js +12 -0
  78. package/lib-module/Autocomplete/index.js +2 -0
  79. package/lib-module/BlockQuote/BlockQuote.js +156 -0
  80. package/lib-module/BlockQuote/index.js +2 -0
  81. package/lib-module/Callout/Callout.js +3 -0
  82. package/lib-module/Card/Card.js +158 -0
  83. package/lib-module/Card/CardContent.js +92 -0
  84. package/lib-module/Card/CardFooter.js +80 -0
  85. package/lib-module/Card/index.js +2 -0
  86. package/lib-module/Countdown/Countdown.js +165 -0
  87. package/lib-module/Countdown/Segment.js +94 -0
  88. package/lib-module/Countdown/constants.js +4 -0
  89. package/lib-module/Countdown/dictionary.js +22 -0
  90. package/lib-module/Countdown/index.js +2 -0
  91. package/lib-module/Countdown/types.js +23 -0
  92. package/lib-module/Countdown/useCountdown.js +32 -0
  93. package/lib-module/IconButton/IconButton.js +52 -0
  94. package/lib-module/IconButton/index.js +2 -0
  95. package/lib-module/Listbox/GroupControl.js +80 -0
  96. package/lib-module/Listbox/Listbox.js +142 -0
  97. package/lib-module/Listbox/ListboxGroup.js +106 -0
  98. package/lib-module/Listbox/ListboxItem.js +112 -0
  99. package/lib-module/Listbox/ListboxOverlay.js +68 -0
  100. package/lib-module/Listbox/PressableItem.js +128 -0
  101. package/lib-module/Listbox/index.js +2 -0
  102. package/lib-module/Modal/ModalContent.js +10 -4
  103. package/lib-module/NavigationBar/resolveItemSelection.js +16 -0
  104. package/lib-module/OptimizeImage/OptimizeImage.js +106 -0
  105. package/lib-module/OptimizeImage/index.js +2 -0
  106. package/lib-module/OptimizeImage/utils/getFallbackUrl.js +8 -0
  107. package/lib-module/OptimizeImage/utils/getOptimizedUrl.js +22 -0
  108. package/lib-module/OptimizeImage/utils/hasWebpSupport.js +32 -0
  109. package/lib-module/OptimizeImage/utils/index.js +4 -0
  110. package/lib-module/OptimizeImage/utils/isSvgUrl.js +3 -0
  111. package/lib-module/QuantitySelector/QuantitySelector.js +232 -0
  112. package/lib-module/QuantitySelector/dictionary.js +26 -0
  113. package/lib-module/QuantitySelector/index.js +2 -0
  114. package/lib-module/QuantitySelector/styles.js +21 -0
  115. package/lib-module/StoryCard/StoryCard.js +220 -0
  116. package/lib-module/StoryCard/index.js +2 -0
  117. package/lib-module/TermsAndConditions/ExpandCollapse.js +120 -0
  118. package/lib-module/TermsAndConditions/TermsAndConditions.js +193 -0
  119. package/lib-module/TermsAndConditions/dictionary.js +12 -0
  120. package/lib-module/TermsAndConditions/index.js +1 -0
  121. package/lib-module/Testimonial/Testimonial.js +204 -0
  122. package/lib-module/Testimonial/index.js +2 -0
  123. package/lib-module/Video/ControlBar/ControlBar.js +292 -0
  124. package/lib-module/Video/ControlBar/Controls/VideoButton/VideoButton.js +74 -0
  125. package/lib-module/Video/ControlBar/Controls/VideoMenu/VideoMenu.js +167 -0
  126. package/lib-module/Video/ControlBar/Controls/VideoProgressBar/VideoProgressBar.js +201 -0
  127. package/lib-module/Video/ControlBar/Controls/VolumeSlider/VolumeSlider.js +193 -0
  128. package/lib-module/Video/MiddleControlButton/MiddleControlButton.js +72 -0
  129. package/lib-module/Video/Video.js +1042 -0
  130. package/lib-module/Video/index.js +2 -0
  131. package/lib-module/Video/videoText.js +55 -0
  132. package/lib-module/WebVideo/WebVideo.js +144 -0
  133. package/lib-module/WebVideo/index.js +2 -0
  134. package/lib-module/baseExports.js +1 -1
  135. package/lib-module/index.js +13 -0
  136. package/lib-module/shared/VideoSplash/SplashButton/SplashButton.js +85 -0
  137. package/lib-module/shared/VideoSplash/SplashButtonWithDetails/SplashButtonWithDetails.js +216 -0
  138. package/lib-module/shared/VideoSplash/VideoSplash.js +65 -0
  139. package/lib-module/shared/VideoSplash/helpers.js +23 -0
  140. package/lib-module/utils/index.js +2 -1
  141. package/lib-module/utils/useOverlaidPosition.js +235 -0
  142. package/package.json +7 -5
  143. package/src/Autocomplete/Autocomplete.jsx +354 -0
  144. package/src/Autocomplete/Loading.jsx +18 -0
  145. package/src/Autocomplete/Suggestions.jsx +52 -0
  146. package/src/Autocomplete/constants.js +6 -0
  147. package/src/Autocomplete/dictionary.js +12 -0
  148. package/src/Autocomplete/index.js +3 -0
  149. package/src/BlockQuote/BlockQuote.jsx +130 -0
  150. package/src/BlockQuote/index.js +3 -0
  151. package/src/Callout/Callout.jsx +1 -1
  152. package/src/Card/Card.jsx +170 -0
  153. package/src/Card/CardContent.jsx +88 -0
  154. package/src/Card/CardFooter.jsx +70 -0
  155. package/src/Card/index.js +3 -0
  156. package/src/Countdown/Countdown.jsx +144 -0
  157. package/src/Countdown/Segment.jsx +69 -0
  158. package/src/Countdown/constants.js +4 -0
  159. package/src/Countdown/dictionary.js +22 -0
  160. package/src/Countdown/index.js +3 -0
  161. package/src/Countdown/types.js +23 -0
  162. package/src/Countdown/useCountdown.js +34 -0
  163. package/src/IconButton/IconButton.jsx +46 -0
  164. package/src/IconButton/index.js +3 -0
  165. package/src/Listbox/GroupControl.jsx +65 -0
  166. package/src/Listbox/Listbox.jsx +148 -0
  167. package/src/Listbox/ListboxGroup.jsx +110 -0
  168. package/src/Listbox/ListboxItem.jsx +101 -0
  169. package/src/Listbox/ListboxOverlay.jsx +71 -0
  170. package/src/Listbox/PressableItem.jsx +121 -0
  171. package/src/Listbox/index.js +3 -0
  172. package/src/Modal/ModalContent.jsx +8 -4
  173. package/src/NavigationBar/resolveItemSelection.js +11 -0
  174. package/src/OptimizeImage/OptimizeImage.jsx +131 -0
  175. package/src/OptimizeImage/index.js +3 -0
  176. package/src/OptimizeImage/utils/getFallbackUrl.js +9 -0
  177. package/src/OptimizeImage/utils/getOptimizedUrl.js +30 -0
  178. package/src/OptimizeImage/utils/hasWebpSupport.js +33 -0
  179. package/src/OptimizeImage/utils/index.js +5 -0
  180. package/src/OptimizeImage/utils/isSvgUrl.js +3 -0
  181. package/src/QuantitySelector/QuantitySelector.jsx +245 -0
  182. package/src/QuantitySelector/dictionary.js +27 -0
  183. package/src/QuantitySelector/index.js +3 -0
  184. package/src/QuantitySelector/styles.js +83 -0
  185. package/src/StoryCard/StoryCard.jsx +198 -0
  186. package/src/StoryCard/index.js +3 -0
  187. package/src/TermsAndConditions/ExpandCollapse.jsx +106 -0
  188. package/src/TermsAndConditions/TermsAndConditions.jsx +161 -0
  189. package/src/TermsAndConditions/dictionary.js +12 -0
  190. package/src/TermsAndConditions/index.js +1 -0
  191. package/src/Testimonial/Testimonial.jsx +169 -0
  192. package/src/Testimonial/index.js +3 -0
  193. package/src/Video/ControlBar/ControlBar.jsx +261 -0
  194. package/src/Video/ControlBar/Controls/VideoButton/VideoButton.jsx +61 -0
  195. package/src/Video/ControlBar/Controls/VideoMenu/VideoMenu.jsx +159 -0
  196. package/src/Video/ControlBar/Controls/VideoProgressBar/VideoProgressBar.jsx +185 -0
  197. package/src/Video/ControlBar/Controls/VolumeSlider/VolumeSlider.jsx +184 -0
  198. package/src/Video/MiddleControlButton/MiddleControlButton.jsx +64 -0
  199. package/src/Video/Video.jsx +988 -0
  200. package/src/Video/index.js +3 -0
  201. package/src/Video/videoText.js +58 -0
  202. package/src/WebVideo/WebVideo.jsx +131 -0
  203. package/src/WebVideo/index.js +3 -0
  204. package/src/baseExports.js +0 -2
  205. package/src/index.js +13 -0
  206. package/src/shared/VideoSplash/SplashButton/SplashButton.jsx +64 -0
  207. package/src/shared/VideoSplash/SplashButtonWithDetails/SplashButtonWithDetails.jsx +128 -0
  208. package/src/shared/VideoSplash/VideoSplash.jsx +50 -0
  209. package/src/shared/VideoSplash/helpers.js +27 -0
  210. package/src/utils/index.js +10 -1
  211. package/src/utils/useOverlaidPosition.js +226 -0
  212. package/types/Autocomplete.d.ts +32 -0
  213. package/types/Card.d.ts +45 -0
  214. package/types/ControlBar.d.ts +59 -0
  215. package/types/MiddleControlButton.d.ts +15 -0
  216. package/types/Video.d.ts +39 -0
  217. package/types/VideoButton.d.ts +14 -0
  218. package/types/VideoMenu.d.ts +16 -0
  219. package/types/VideoProgressBar.d.ts +17 -0
  220. package/types/VolumeSlider.d.ts +20 -0
@@ -0,0 +1,369 @@
1
+ /* eslint-disable react/require-default-props */
2
+ import React, { forwardRef, useRef, useState } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { throttle } from 'lodash';
5
+ import { InputSupports, inputSupportsProps, selectSystemProps, TextInput, textInputProps, textInputHandlerProps, Typography, useCopy, useSafeLayoutEffect } from '@telus-uds/components-base';
6
+ import Listbox from '../Listbox';
7
+ import { htmlAttrs, useOverlaidPosition } from '../utils';
8
+ import Loading from './Loading';
9
+ import Suggestions from './Suggestions';
10
+ import { DEFAULT_MAX_SUGGESTIONS, DEFAULT_MIN_TO_SUGGESTION, INPUT_LEFT_PADDING, MIN_LISTBOX_WIDTH } from './constants';
11
+ import dictionary from './dictionary';
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { Fragment as _Fragment } from "react/jsx-runtime";
14
+ import { jsxs as _jsxs } from "react/jsx-runtime";
15
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs, inputSupportsProps, textInputHandlerProps, textInputProps]);
16
+ const inputTokens = {
17
+ paddingLeft: INPUT_LEFT_PADDING
18
+ }; // Returns JSX to display a bold string `str` with unbolded occurrences of the
19
+ // `substring` based in the array of `matchIndexes` provided
20
+
21
+ const highlightAllMatches = function (str) {
22
+ let substring = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
23
+ let matchIndexes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
24
+ return (
25
+ /*#__PURE__*/
26
+ // Wrapping all in bold
27
+ _jsx(Typography, {
28
+ variant: {
29
+ bold: false
30
+ },
31
+ children: matchIndexes.reduce((acc, matchIndex, index) => [...acc, // Add a piece of the string up to the first occurrence of the substring
32
+ index === 0 && (str.slice(0, matchIndex) ?? ''),
33
+ /*#__PURE__*/
34
+ // Unbold the occurrence of the substring (while keeping the original casing)
35
+ _jsx(Typography, {
36
+ variant: {
37
+ bold: true
38
+ },
39
+ children: str.slice(matchIndex, matchIndex + substring.length)
40
+ }, matchIndex), // Add the rest of the string until the next occurrence or the end of it
41
+ str.slice(matchIndex + substring.length, matchIndexes[index + 1] ?? str.length)], [])
42
+ })
43
+ );
44
+ };
45
+
46
+ const highlight = function () {
47
+ let items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
48
+ let text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
49
+ return items.reduce((acc, item) => {
50
+ var _Array$from;
51
+
52
+ const matches = (_Array$from = Array.from(item.label.toLowerCase().matchAll(text.toLowerCase()))) === null || _Array$from === void 0 ? void 0 : _Array$from.map(_ref => {
53
+ let {
54
+ index
55
+ } = _ref;
56
+ return index;
57
+ });
58
+
59
+ if (matches !== null && matches !== void 0 && matches.length) {
60
+ return [...acc, { ...item,
61
+ label: highlightAllMatches(item.label, text, matches)
62
+ }];
63
+ }
64
+
65
+ return [...acc, item];
66
+ }, []);
67
+ };
68
+
69
+ const Autocomplete = /*#__PURE__*/forwardRef((_ref2, ref) => {
70
+ var _ref3;
71
+
72
+ let {
73
+ children,
74
+ copy = 'en',
75
+ fullWidth = true,
76
+ initialItems,
77
+ initialValue,
78
+ isLoading = false,
79
+ items,
80
+ maxSuggestions = DEFAULT_MAX_SUGGESTIONS,
81
+ minToSuggestion = DEFAULT_MIN_TO_SUGGESTION,
82
+ noResults,
83
+ onChange,
84
+ onClear,
85
+ onSelect,
86
+ readOnly,
87
+ validation,
88
+ value,
89
+ ...rest
90
+ } = _ref2;
91
+ // The wrapped input is mostly responsible for controlled vs uncontrolled handling,
92
+ // but we also need to adjust suggestions based on the mode:
93
+ // - in controlled mode we rely entirely on the suggestions passed via the `items` prop,
94
+ // - in uncontrolled mode we filter the suggestions ourselves based on the `initialItems`
95
+ // prop and the text entered
96
+ const isControlled = value !== undefined; // We need to store current items for uncontrolled usage
97
+
98
+ const [currentItems, setCurrentItems] = useState(initialItems); // We need to store the current value as well to be able to highlight it
99
+
100
+ const [currentValue, setCurrentValue] = useState(value ?? initialValue); // Setting up the overlay
101
+
102
+ const openOverlayRef = useRef();
103
+ const [isExpanded, setIsExpanded] = useState(((_ref3 = value ?? initialValue) === null || _ref3 === void 0 ? void 0 : _ref3.length) >= minToSuggestion);
104
+ const {
105
+ overlaidPosition,
106
+ sourceRef: inputRef,
107
+ targetRef,
108
+ onTargetLayout,
109
+ isReady
110
+ } = useOverlaidPosition({
111
+ isShown: isExpanded,
112
+ offsets: {
113
+ vertical: 4
114
+ }
115
+ }); // We limit the number of suggestions displayed to avoid huge lists
116
+ // TODO: add a way to make the `Listbox` occupy fixed height and be scrollable
117
+ // within that height, which will unlock similar behaviour for `AutoComplete` as well
118
+
119
+ const itemsToSuggest = function () {
120
+ let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
121
+ return maxSuggestions ? data.slice(0, maxSuggestions) : [...data];
122
+ };
123
+
124
+ const getCopy = useCopy({
125
+ dictionary,
126
+ copy
127
+ }); // Tracking input width changes to resize the listbox overlay accordingly
128
+
129
+ const [inputWidth, setInputWidth] = useState();
130
+ useSafeLayoutEffect(() => {
131
+ const updateInputWidth = () => {
132
+ var _inputRef$current;
133
+
134
+ setInputWidth((inputRef === null || inputRef === void 0 ? void 0 : (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.clientWidth) + 4); // adding back all the input borders / outlines
135
+
136
+ setIsExpanded(false); // close the suggestions while the input is changing
137
+ };
138
+
139
+ const throttledUpdateInputWidth = throttle(updateInputWidth, 100, {
140
+ leading: false
141
+ });
142
+ updateInputWidth();
143
+ window.addEventListener('load', updateInputWidth);
144
+ window.addEventListener('resize', throttledUpdateInputWidth);
145
+ return () => {
146
+ window.removeEventListener('load', updateInputWidth);
147
+ window.removeEventListener('resize', throttledUpdateInputWidth);
148
+ };
149
+ }, [inputRef]);
150
+
151
+ const handleChange = newValue => {
152
+ onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
153
+ setCurrentValue(newValue);
154
+ setIsExpanded((newValue === null || newValue === void 0 ? void 0 : newValue.length) >= minToSuggestion);
155
+
156
+ if (!isControlled && initialItems !== undefined) {
157
+ setCurrentItems(initialItems.filter(_ref4 => {
158
+ var _label$toLowerCase;
159
+
160
+ let {
161
+ label
162
+ } = _ref4;
163
+ return label === null || label === void 0 ? void 0 : (_label$toLowerCase = label.toLowerCase()) === null || _label$toLowerCase === void 0 ? void 0 : _label$toLowerCase.includes(newValue === null || newValue === void 0 ? void 0 : newValue.toLowerCase());
164
+ }));
165
+ }
166
+ };
167
+
168
+ const handleSelect = selectedId => {
169
+ var _ref5;
170
+
171
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(selectedId);
172
+ const {
173
+ label: newValue
174
+ } = (_ref5 = isControlled ? items : currentItems) === null || _ref5 === void 0 ? void 0 : _ref5.find(_ref6 => {
175
+ let {
176
+ id
177
+ } = _ref6;
178
+ return id === selectedId;
179
+ });
180
+ onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
181
+ setCurrentValue(newValue);
182
+ if (!isControlled && inputRef !== null && inputRef !== void 0 && inputRef.current) inputRef.current.value = newValue;
183
+ setIsExpanded(false);
184
+ };
185
+
186
+ const handleClose = event => {
187
+ var _openOverlayRef$curre, _openOverlayRef$curre2;
188
+
189
+ if (event.type === 'keydown') {
190
+ if (event.key === 'Escape' || event.key === 27) {
191
+ setIsExpanded(false);
192
+ } else if (event.key === 'ArrowDown' && isExpanded && !isLoading && targetRef !== null && targetRef !== void 0 && targetRef.current) {
193
+ targetRef.current.focus();
194
+ }
195
+ } else if (event.type === 'click' && openOverlayRef !== null && openOverlayRef !== void 0 && openOverlayRef.current && event.target && !(openOverlayRef !== null && openOverlayRef !== void 0 && (_openOverlayRef$curre = openOverlayRef.current) !== null && _openOverlayRef$curre !== void 0 && _openOverlayRef$curre.contains(event.target))) {
196
+ setIsExpanded(false);
197
+ } else if (event.type === 'touchstart' && openOverlayRef !== null && openOverlayRef !== void 0 && openOverlayRef.current && event.touches[0].target && !(openOverlayRef !== null && openOverlayRef !== void 0 && (_openOverlayRef$curre2 = openOverlayRef.current) !== null && _openOverlayRef$curre2 !== void 0 && _openOverlayRef$curre2.contains(event.touches[0].target))) {
198
+ setIsExpanded(false);
199
+ }
200
+ };
201
+
202
+ const {
203
+ supportsProps,
204
+ ...selectedProps
205
+ } = selectProps(rest);
206
+ return /*#__PURE__*/_jsxs(_Fragment, {
207
+ children: [/*#__PURE__*/_jsx(InputSupports, { ...supportsProps,
208
+ accessibilityAutoComplete: "list",
209
+ accessibilityControls: "autocomplete",
210
+ accessibilityExpanded: isExpanded,
211
+ accessibilityRole: "combobox",
212
+ ...selectedProps,
213
+ validation: validation,
214
+ ref: ref,
215
+ children: _ref7 => {
216
+ let {
217
+ inputId,
218
+ ...props
219
+ } = _ref7;
220
+ if (typeof children === 'function') return children({
221
+ inputId,
222
+ inputRef,
223
+ onChange: handleChange,
224
+ onKeyPress: handleClose,
225
+ readOnly,
226
+ tokens: inputTokens,
227
+ ...selectedProps,
228
+ ...props,
229
+ ...(isControlled ? {
230
+ value
231
+ } : {
232
+ initialValue
233
+ })
234
+ });
235
+ return /*#__PURE__*/_jsx(TextInput, {
236
+ onChange: handleChange,
237
+ onClear: onClear,
238
+ onKeyPress: handleClose,
239
+ readOnly: readOnly,
240
+ ref: inputRef,
241
+ tokens: inputTokens,
242
+ ...selectedProps,
243
+ ...props,
244
+ ...(isControlled ? {
245
+ value
246
+ } : {
247
+ initialValue
248
+ })
249
+ });
250
+ }
251
+ }), isExpanded && /*#__PURE__*/_jsxs(_Fragment, {
252
+ children: [/*#__PURE__*/_jsx(Listbox.Overlay, {
253
+ overlaidPosition: overlaidPosition,
254
+ isReady: isReady,
255
+ minWidth: fullWidth ? inputWidth : MIN_LISTBOX_WIDTH,
256
+ maxWidth: inputWidth,
257
+ onLayout: onTargetLayout,
258
+ ref: openOverlayRef,
259
+ children: isLoading ? /*#__PURE__*/_jsx(Loading, {
260
+ label: getCopy('loading')
261
+ }) : /*#__PURE__*/_jsx(Suggestions, {
262
+ hasResults: getCopy('hasResults'),
263
+ id: "autocomplete",
264
+ items: itemsToSuggest(highlight(isControlled ? items : currentItems, currentValue)),
265
+ noResults: noResults ?? getCopy('noResults'),
266
+ onClose: handleClose,
267
+ onSelect: handleSelect,
268
+ parentRef: inputRef,
269
+ ref: targetRef
270
+ })
271
+ }), (targetRef === null || targetRef === void 0 ? void 0 : targetRef.current) && /*#__PURE__*/_jsx("div", {
272
+ // This catches and shifts focus to other interactive elements.
273
+ onFocus: () => {
274
+ var _targetRef$current;
275
+
276
+ return targetRef === null || targetRef === void 0 ? void 0 : (_targetRef$current = targetRef.current) === null || _targetRef$current === void 0 ? void 0 : _targetRef$current.focus();
277
+ } // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
278
+ ,
279
+ tabIndex: 0
280
+ })]
281
+ })]
282
+ });
283
+ });
284
+ Autocomplete.displayName = 'Autocomplete'; // If a language dictionary entry is provided, it must contain every key
285
+
286
+ const dictionaryContentShape = PropTypes.shape({
287
+ hasResults: PropTypes.string.isRequired,
288
+ loading: PropTypes.string.isRequired,
289
+ noResults: PropTypes.string.isRequired
290
+ });
291
+ Autocomplete.propTypes = { ...selectedSystemPropTypes,
292
+
293
+ /**
294
+ * Can be used to provide a function that renders a custom input:
295
+ * <Autocomplete items={items} value={currentValue}>
296
+ * {({ inputId, inputRef, onChange, onKeyPress, readOnly, tokens, value }) => (
297
+ * <Search
298
+ * nativeID={inputId}
299
+ * ref={inputRef}
300
+ * onChange={onChange}
301
+ * onKeyPress={onKeyPress}
302
+ * readOnly={readOnly}
303
+ * tokens={tokens}
304
+ * value={value}
305
+ * />
306
+ * )}
307
+ * </Autocomplete>
308
+ */
309
+ children: PropTypes.func,
310
+
311
+ /**
312
+ * Copy language identifier
313
+ */
314
+ copy: PropTypes.oneOfType([PropTypes.oneOf(['en', 'fr']), dictionaryContentShape]),
315
+
316
+ /**
317
+ * Set to true in order to display the loading indicator instead of results
318
+ */
319
+ isLoading: PropTypes.bool,
320
+
321
+ /**
322
+ * List of items to display as suggestions
323
+ */
324
+ items: PropTypes.arrayOf(PropTypes.shape({
325
+ id: PropTypes.string,
326
+ label: PropTypes.string
327
+ })),
328
+
329
+ /**
330
+ * Label to display alongside the spinner when in a loading state
331
+ */
332
+ loadingLabel: PropTypes.string,
333
+
334
+ /**
335
+ * Minimum number of characters typed for a list of suggestions to appear
336
+ */
337
+ minToSuggestion: PropTypes.number,
338
+
339
+ /**
340
+ * Maximum number of suggestions provided at the same time
341
+ */
342
+ maxSuggestions: PropTypes.number,
343
+
344
+ /**
345
+ * Text or JSX to render when no results are available
346
+ */
347
+ noResults: PropTypes.node,
348
+
349
+ /**
350
+ * Handler function to be called when the input value changes
351
+ */
352
+ onChange: PropTypes.func,
353
+
354
+ /**
355
+ * Handler function to be called when the clear button (appears if the handler is passed) is pressed
356
+ */
357
+ onClear: PropTypes.func,
358
+
359
+ /**
360
+ * Callback function to be called when an item is selected from the list
361
+ */
362
+ onSelect: PropTypes.func,
363
+
364
+ /**
365
+ * Input value for controlled usage
366
+ */
367
+ value: PropTypes.string
368
+ };
369
+ export default Autocomplete;
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Box, StackView, Typography } from '@telus-uds/components-base';
4
+ import Spinner from '../Spinner';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+
8
+ const Loading = _ref => {
9
+ let {
10
+ label
11
+ } = _ref;
12
+ return /*#__PURE__*/_jsx(Box, {
13
+ space: 3,
14
+ children: /*#__PURE__*/_jsxs(StackView, {
15
+ direction: "row",
16
+ space: 2,
17
+ tokens: {
18
+ alignItems: 'center'
19
+ },
20
+ children: [/*#__PURE__*/_jsx(Spinner, {
21
+ inline: true,
22
+ show: true,
23
+ size: "small"
24
+ }), /*#__PURE__*/_jsx(Typography, {
25
+ variant: {
26
+ size: 'small'
27
+ },
28
+ accessibilityLiveRegion: "polite",
29
+ children: label
30
+ })]
31
+ })
32
+ });
33
+ };
34
+
35
+ Loading.propTypes = {
36
+ label: PropTypes.string
37
+ };
38
+ export default Loading;
@@ -0,0 +1,64 @@
1
+ import React, { forwardRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { A11yText, Box, Typography } from '@telus-uds/components-base';
4
+ import Listbox from '../Listbox';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { Fragment as _Fragment } from "react/jsx-runtime";
7
+ import { jsxs as _jsxs } from "react/jsx-runtime";
8
+ const Suggestions = /*#__PURE__*/forwardRef((_ref, ref) => {
9
+ let {
10
+ hasResults,
11
+ items = [],
12
+ noResults,
13
+ onClose,
14
+ onSelect,
15
+ parentRef
16
+ } = _ref;
17
+ const pressableItems = items.map(_ref2 => {
18
+ let {
19
+ id,
20
+ ...rest
21
+ } = _ref2;
22
+ return {
23
+ id,
24
+ onPress: () => onSelect(id),
25
+ ...rest
26
+ };
27
+ });
28
+ if (items !== null && items !== void 0 && items.length) return /*#__PURE__*/_jsxs(_Fragment, {
29
+ children: [/*#__PURE__*/_jsx(A11yText, {
30
+ accessibilityLiveRegion: "polite",
31
+ text: hasResults
32
+ }), /*#__PURE__*/_jsx(Listbox, {
33
+ items: pressableItems,
34
+ firstItemRef: ref,
35
+ parentRef: parentRef,
36
+ onClose: onClose
37
+ })]
38
+ });
39
+ return /*#__PURE__*/_jsx(Box, {
40
+ space: 3,
41
+ children: typeof noResults === 'string' ? /*#__PURE__*/_jsx(_Fragment, {
42
+ children: /*#__PURE__*/_jsx(Typography, {
43
+ accessibilityLiveRegion: "polite",
44
+ variant: {
45
+ size: 'small'
46
+ },
47
+ children: noResults
48
+ })
49
+ }) : noResults
50
+ });
51
+ });
52
+ Suggestions.displayName = 'Suggestions';
53
+ Suggestions.propTypes = {
54
+ hasResults: PropTypes.string.isRequired,
55
+ items: PropTypes.arrayOf(PropTypes.shape({
56
+ id: PropTypes.string,
57
+ label: PropTypes.node
58
+ })).isRequired,
59
+ noResults: PropTypes.node.isRequired,
60
+ onClose: PropTypes.func.isRequired,
61
+ onSelect: PropTypes.func.isRequired,
62
+ parentRef: PropTypes.object.isRequired
63
+ };
64
+ export default Suggestions;
@@ -0,0 +1,5 @@
1
+ import palette from '@telus-uds/palette-allium/build/web/palette';
2
+ export const DEFAULT_MIN_TO_SUGGESTION = 1;
3
+ export const DEFAULT_MAX_SUGGESTIONS = 5;
4
+ export const INPUT_LEFT_PADDING = palette.size.size16;
5
+ export const MIN_LISTBOX_WIDTH = palette.size.size288;
@@ -0,0 +1,12 @@
1
+ export default {
2
+ en: {
3
+ hasResults: 'Some results are available',
4
+ loading: 'Loading suggestions...',
5
+ noResults: 'No results found'
6
+ },
7
+ fr: {
8
+ hasResults: 'Quelques suggestions sont disponible',
9
+ loading: 'Chargement en cours...',
10
+ noResults: 'Aucun résultat trouvé'
11
+ }
12
+ };
@@ -0,0 +1,2 @@
1
+ import Autocomplete from './Autocomplete';
2
+ export default Autocomplete;
@@ -0,0 +1,156 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Link, selectSystemProps, StackView, Typography, useThemeTokens, withLinkRouter } from '@telus-uds/components-base';
4
+ import styled from 'styled-components';
5
+ import { htmlAttrs, transformGradient } from '../utils';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ import { jsxs as _jsxs } from "react/jsx-runtime";
8
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
9
+ const BlockQuoteContainer = /*#__PURE__*/styled.blockquote.withConfig({
10
+ displayName: "BlockQuote__BlockQuoteContainer",
11
+ componentId: "components-web__sc-vals3u-0"
12
+ })(["margin:0;position:relative;padding-left:", ";padding-right:", ";padding-bottom:", ";padding-top:", ";&::before{content:'';left:0;top:0;position:absolute;height:100%;width:", ";background:", ";}"], _ref => {
13
+ let {
14
+ paddingLeft
15
+ } = _ref;
16
+ return `${paddingLeft}px`;
17
+ }, _ref2 => {
18
+ let {
19
+ paddingRight
20
+ } = _ref2;
21
+ return `${paddingRight}px`;
22
+ }, _ref3 => {
23
+ let {
24
+ paddingBottom
25
+ } = _ref3;
26
+ return `${paddingBottom}px`;
27
+ }, _ref4 => {
28
+ let {
29
+ paddingTop
30
+ } = _ref4;
31
+ return `${paddingTop}px`;
32
+ }, _ref5 => {
33
+ let {
34
+ width
35
+ } = _ref5;
36
+ return `${width}px`;
37
+ }, _ref6 => {
38
+ let {
39
+ backgroundGradient
40
+ } = _ref6;
41
+ return backgroundGradient && transformGradient(backgroundGradient);
42
+ });
43
+ const QuoteContainer = /*#__PURE__*/styled.div.withConfig({
44
+ displayName: "BlockQuote__QuoteContainer",
45
+ componentId: "components-web__sc-vals3u-1"
46
+ })(["margin-bottom:", ";"], _ref7 => {
47
+ let {
48
+ marginBottom
49
+ } = _ref7;
50
+ return `${marginBottom}px`;
51
+ });
52
+
53
+ const BlockQuote = _ref8 => {
54
+ let {
55
+ children,
56
+ link,
57
+ additionalInfo,
58
+ linkHref,
59
+ textStyle = 'large',
60
+ LinkRouter,
61
+ linkRouterProps,
62
+ tokens,
63
+ variant,
64
+ ...rest
65
+ } = _ref8;
66
+ const {
67
+ color,
68
+ paddingTop,
69
+ paddingBottom,
70
+ paddingLeft,
71
+ paddingRight,
72
+ marginBottom,
73
+ width,
74
+ backgroundGradient
75
+ } = useThemeTokens('BlockQuote', tokens, variant);
76
+ const mappedTextSize = textStyle === 'heading' ? 'h3' : textStyle;
77
+
78
+ const renderLink = () => {
79
+ if (linkHref) {
80
+ return /*#__PURE__*/_jsx(Link, {
81
+ href: linkHref,
82
+ tokens: {
83
+ blockFontWeight: '500',
84
+ color
85
+ },
86
+ variant: {
87
+ alternative: true
88
+ },
89
+ LinkRouter: LinkRouter,
90
+ linkRouterProps: linkRouterProps,
91
+ children: link
92
+ });
93
+ }
94
+
95
+ return /*#__PURE__*/_jsx(Typography, {
96
+ tokens: {
97
+ color,
98
+ fontWeight: '500'
99
+ },
100
+ children: link
101
+ });
102
+ };
103
+
104
+ const renderQuote = () => {
105
+ const quote = /*#__PURE__*/_jsx(Typography, {
106
+ tokens: {
107
+ color,
108
+ fontWeight: '400'
109
+ },
110
+ variant: {
111
+ size: mappedTextSize
112
+ },
113
+ children: children
114
+ });
115
+
116
+ if (additionalInfo || link) {
117
+ return /*#__PURE__*/_jsx(QuoteContainer, {
118
+ marginBottom: marginBottom,
119
+ children: quote
120
+ });
121
+ }
122
+
123
+ return quote;
124
+ };
125
+
126
+ return /*#__PURE__*/_jsxs(BlockQuoteContainer, { ...selectProps(rest),
127
+ paddingTop: paddingTop,
128
+ paddingBottom: paddingBottom,
129
+ paddingLeft: paddingLeft,
130
+ paddingRight: paddingRight,
131
+ width: width,
132
+ backgroundGradient: backgroundGradient,
133
+ children: [renderQuote(), (additionalInfo || link) && /*#__PURE__*/_jsxs(StackView, {
134
+ space: 0,
135
+ children: [link && renderLink(), additionalInfo && /*#__PURE__*/_jsx(Typography, {
136
+ tokens: {
137
+ color
138
+ },
139
+ variant: {
140
+ size: 'small'
141
+ },
142
+ children: additionalInfo
143
+ })]
144
+ })]
145
+ });
146
+ };
147
+
148
+ BlockQuote.propTypes = { ...selectedSystemPropTypes,
149
+ ...withLinkRouter.propTypes,
150
+ children: PropTypes.node.isRequired,
151
+ link: PropTypes.string,
152
+ linkHref: PropTypes.string,
153
+ additionalInfo: PropTypes.string,
154
+ textStyle: PropTypes.oneOf(['large', 'heading'])
155
+ };
156
+ export default BlockQuote;
@@ -0,0 +1,2 @@
1
+ import BlockQuote from './BlockQuote';
2
+ export default BlockQuote;
@@ -80,6 +80,9 @@ const Callout = _ref2 => {
80
80
  padding: `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`,
81
81
  ...selectProps(rest),
82
82
  children: [icon && /*#__PURE__*/_jsx(Icon, {
83
+ tokens: {
84
+ color
85
+ },
83
86
  icon: icon,
84
87
  variant: {
85
88
  rank: 'primary',