@telus-uds/components-base 1.95.0 → 1.96.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 (38) hide show
  1. package/CHANGELOG.md +23 -2
  2. package/lib/Autocomplete/Autocomplete.js +36 -2
  3. package/lib/Card/CardBase.js +4 -0
  4. package/lib/List/ListItemBase.js +2 -1
  5. package/lib/Modal/Modal.js +34 -13
  6. package/lib/Modal/ModalContent.js +1 -1
  7. package/lib/Modal/WebModal.js +1 -0
  8. package/lib/Notification/Notification.js +5 -5
  9. package/lib/PriceLockup/PriceLockup.js +11 -3
  10. package/lib/Progress/Progress.js +5 -2
  11. package/lib/Progress/ProgressBar.js +4 -1
  12. package/lib/Typography/Typography.js +42 -19
  13. package/lib/index.js +7 -0
  14. package/lib-module/Autocomplete/Autocomplete.js +36 -2
  15. package/lib-module/Card/CardBase.js +4 -0
  16. package/lib-module/List/ListItemBase.js +2 -1
  17. package/lib-module/Modal/Modal.js +34 -13
  18. package/lib-module/Modal/ModalContent.js +1 -1
  19. package/lib-module/Modal/WebModal.js +1 -0
  20. package/lib-module/Notification/Notification.js +5 -5
  21. package/lib-module/PriceLockup/PriceLockup.js +11 -3
  22. package/lib-module/Progress/Progress.js +6 -3
  23. package/lib-module/Progress/ProgressBar.js +5 -2
  24. package/lib-module/Typography/Typography.js +42 -19
  25. package/lib-module/index.js +1 -1
  26. package/package.json +2 -2
  27. package/src/Autocomplete/Autocomplete.jsx +41 -2
  28. package/src/Card/CardBase.jsx +6 -0
  29. package/src/List/ListItemBase.jsx +1 -1
  30. package/src/Modal/Modal.jsx +40 -14
  31. package/src/Modal/ModalContent.jsx +1 -1
  32. package/src/Modal/WebModal.jsx +1 -1
  33. package/src/Notification/Notification.jsx +5 -5
  34. package/src/PriceLockup/PriceLockup.jsx +9 -1
  35. package/src/Progress/Progress.jsx +6 -3
  36. package/src/Progress/ProgressBar.jsx +4 -2
  37. package/src/Typography/Typography.jsx +37 -13
  38. package/src/index.js +2 -1
package/CHANGELOG.md CHANGED
@@ -1,12 +1,33 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Wed, 25 Sep 2024 16:57:49 GMT and should not be manually modified.
3
+ This log was last generated on Sat, 12 Oct 2024 00:31:05 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.96.0
8
+
9
+ Sat, 12 Oct 2024 00:31:05 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - `TermsAndConditions`: export use-responsive-theme-tokens hook (guillermo.peitzner@telus.com)
14
+ - `Progress`: add shadow tokens to Progress and ProgressBar (jacqui.koroll@telus.com)
15
+ - `PriceLockup`: alignItemsText token added to the component to align right (flex-end), left (flex-start) or center the content (35577399+JoshHC@users.noreply.github.com)
16
+ - `Modal`: updated the alignment of the cancel/secondary buttons (sam.obisesan@telus.com)
17
+ - `Card`: new token backgroundGradient added to be able to use the gradient as background (35577399+JoshHC@users.noreply.github.com)
18
+ - Bump @telus-uds/system-theme-tokens to v2.65.0
19
+
20
+ ### Patches
21
+
22
+ - `Modal`: Fix focus trap to ensure focus is contained within the modal and initial focus is set on modal upon open (Mauricio.BatresMontejo@telus.com)
23
+ - `Typography`: fix sub and sup render on mobile devices (guillermo.peitzner@telus.com)
24
+ - `Autocomplete`: fix suggestion list displacement (guillermo.peitzner@telus.com)
25
+ - `List`: Enable `CircleBullet` icon to visualize order of nested lists. (jaime.tuyuc@telus.com)
26
+ - `Notification`: use maxWidth to avoid overflow in media queries (kristina.kirpichnikova@telus.com)
27
+
7
28
  ## 1.95.0
8
29
 
9
- Wed, 25 Sep 2024 16:57:49 GMT
30
+ Wed, 25 Sep 2024 17:07:47 GMT
10
31
 
11
32
  ### Minor changes
12
33
 
@@ -144,6 +144,7 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
144
144
 
145
145
  // When it's nested, selected value
146
146
  const [nestedSelectedValue, setNestedSelectedValue] = _react.default.useState(null);
147
+ const [isInputVisible, setIsInputVisible] = _react.default.useState(true);
147
148
  const {
148
149
  supportsProps,
149
150
  ...selectedProps
@@ -269,6 +270,27 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
269
270
  }));
270
271
  }
271
272
  }, [nestedSelectedValue, items]);
273
+ _react.default.useEffect(() => {
274
+ if (_Platform.default.OS === 'ios' || _Platform.default.OS === 'android') {
275
+ return undefined;
276
+ }
277
+ const observer = new IntersectionObserver(entries => {
278
+ const [entry] = entries;
279
+ setIsInputVisible(entry.isIntersecting);
280
+ if (!entry.isIntersecting) {
281
+ setIsExpanded(false);
282
+ }
283
+ });
284
+ const currentInputRef = inputRef.current;
285
+ if (currentInputRef) {
286
+ observer.observe(currentInputRef);
287
+ }
288
+ return () => {
289
+ if (currentInputRef) {
290
+ observer.unobserve(currentInputRef);
291
+ }
292
+ };
293
+ }, [inputRef]);
272
294
  const handleClose = event => {
273
295
  var _openOverlayRef$curre, _openOverlayRef$curre2;
274
296
  if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27') || event.type === 'click' && !(openOverlayRef !== null && openOverlayRef !== void 0 && (_openOverlayRef$curre = openOverlayRef.current) !== null && _openOverlayRef$curre !== void 0 && _openOverlayRef$curre.contains(event.target)) || 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))) {
@@ -325,7 +347,19 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
325
347
  readOnly: readOnly,
326
348
  ref: inputRef,
327
349
  ...(_Platform.default.OS !== 'web' ? {
328
- onLayout: event => setSourceLayout(event.nativeEvent.layout)
350
+ onLayout: event => {
351
+ setSourceLayout(event.nativeEvent.layout);
352
+ const {
353
+ y,
354
+ height
355
+ } = event.nativeEvent.layout;
356
+ if (y >= 0 && height > 0) {
357
+ setIsInputVisible(true);
358
+ } else {
359
+ setIsInputVisible(false);
360
+ setIsExpanded(false);
361
+ }
362
+ }
329
363
  } : {}),
330
364
  tokens: inputTokens,
331
365
  validation: validation,
@@ -338,7 +372,7 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
338
372
  })
339
373
  });
340
374
  }
341
- }), (isExpanded || hintExpansionEnabled) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
375
+ }), (isExpanded || hintExpansionEnabled) && isInputVisible && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
342
376
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Listbox.default.Overlay, {
343
377
  overlaidPosition: overlaidPosition,
344
378
  isReady: isReady,
@@ -31,6 +31,7 @@ const selectStyles = _ref => {
31
31
  paddingTop,
32
32
  minWidth,
33
33
  shadow,
34
+ backgroundGradient,
34
35
  gradient
35
36
  } = _ref;
36
37
  return {
@@ -50,6 +51,9 @@ const selectStyles = _ref => {
50
51
  backgroundOrigin: `border-box`,
51
52
  boxShadow: `inset 0 1000px white`,
52
53
  border: `${borderWidth}px solid transparent`
54
+ } : {}),
55
+ ...(backgroundGradient && _Platform.default.OS === 'web' ? {
56
+ backgroundImage: `linear-gradient(${backgroundGradient.angle}deg, ${backgroundGradient.stops[0].color}, ${backgroundGradient.stops[1].color})`
53
57
  } : {})
54
58
  };
55
59
  };
@@ -135,7 +135,8 @@ const staticStyles = _StyleSheet.default.create({
135
135
  },
136
136
  titleAndContentContainer: {
137
137
  flexDirection: 'column',
138
- flexShrink: 1
138
+ flexShrink: 1,
139
+ flexGrow: 1
139
140
  }
140
141
  });
141
142
  ListItemBase.propTypes = {
@@ -104,6 +104,7 @@ const selectScrollViewStyles = () => ({
104
104
  * - Don’t use modals consecutively
105
105
  */
106
106
  const Modal = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
107
+ var _modalContentRef$curr2;
107
108
  let {
108
109
  children,
109
110
  isOpen,
@@ -132,6 +133,8 @@ const Modal = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
132
133
  maxWidth
133
134
  });
134
135
  const modalRef = (0, _useScrollBlocking.default)(isOpen);
136
+ const modalBodyRef = _react.default.useRef(ref);
137
+ const modalContentRef = _react.default.useRef(null);
135
138
  const {
136
139
  closeIcon: CloseIconComponent
137
140
  } = themeTokens;
@@ -146,6 +149,25 @@ const Modal = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
146
149
  const handleKeyUp = event => {
147
150
  if (event.key === 'Escape') onClose();
148
151
  };
152
+ const manageFocus = _react.default.useCallback(event => {
153
+ if (event.key === 'Tab') {
154
+ var _modalBodyRef$current;
155
+ const focusableElements = Array.from(modalBodyRef === null || modalBodyRef === void 0 ? void 0 : (_modalBodyRef$current = modalBodyRef.current) === null || _modalBodyRef$current === void 0 ? void 0 : _modalBodyRef$current.querySelectorAll(`
156
+ a[href], button, textarea, input, select,
157
+ [tabindex]:not([tabindex="-1"]),
158
+ [contenteditable="true"]
159
+ `));
160
+ const firstElement = focusableElements[0];
161
+ const lastElement = focusableElements[focusableElements.length - 1];
162
+ if (event.shiftKey && document.activeElement === firstElement) {
163
+ event.preventDefault();
164
+ lastElement.focus();
165
+ } else if (!event.shiftKey && document.activeElement === lastElement) {
166
+ event.preventDefault();
167
+ firstElement.focus();
168
+ }
169
+ }
170
+ }, [modalBodyRef]);
149
171
 
150
172
  // Show the custom react node passed to `closedButton` or the default close button if `closeButton` is `undefined`.
151
173
  // Hide the close button if `closeButton` is `null`.
@@ -156,22 +178,20 @@ const Modal = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
156
178
  const closeButtonRef = _react.default.useRef(null);
157
179
  _react.default.useEffect(() => {
158
180
  if (_Platform.default.OS === 'web') {
159
- const handleFocus = () => {
160
- // If the focus is on the last item of the web modal container, move it to the close button
161
- if (document.activeElement === focusTrapRef.current && closeButtonRef.current) {
162
- closeButtonRef.current.focus();
163
- }
164
- return undefined;
165
- };
166
-
167
- // Add an event listener to manage focus in the web modal container
168
- document.addEventListener('focusin', handleFocus);
181
+ // Add an event listener to manage keydown and focus in the web modal container
182
+ document.addEventListener('keydown', manageFocus);
169
183
 
170
184
  // Clean up the event listener
171
- return () => document.removeEventListener('focusin', handleFocus);
185
+ return () => document.removeEventListener('keydown', manageFocus);
172
186
  }
173
187
  return undefined;
174
- }, []);
188
+ }, [manageFocus]);
189
+ _react.default.useEffect(() => {
190
+ if (isOpen) {
191
+ var _modalContentRef$curr;
192
+ modalContentRef === null || modalContentRef === void 0 ? void 0 : (_modalContentRef$curr = modalContentRef.current) === null || _modalContentRef$curr === void 0 ? void 0 : _modalContentRef$curr.focus();
193
+ }
194
+ }, [isOpen, modalContentRef === null || modalContentRef === void 0 ? void 0 : (_modalContentRef$curr2 = modalContentRef.current) === null || _modalContentRef$curr2 === void 0 ? void 0 : _modalContentRef$curr2.focus]);
175
195
  if (!isOpen) {
176
196
  return null;
177
197
  }
@@ -184,7 +204,7 @@ const Modal = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
184
204
  pointerEvents: "box-none" // don't capture backdrop press events
185
205
  ,
186
206
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
187
- ref: ref,
207
+ ref: modalBodyRef,
188
208
  style: [staticStyles.modal, selectModalStyles(themeTokens)],
189
209
  onKeyUp: handleKeyUp,
190
210
  children: [showCloseButton && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
@@ -229,6 +249,7 @@ const Modal = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
229
249
  if (_Platform.default.OS === 'web') {
230
250
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_WebModal.default, {
231
251
  ...selectProps(rest),
252
+ ref: modalContentRef,
232
253
  children: [content, /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
233
254
  accessibilityRole: "button",
234
255
  ref: focusTrapRef
@@ -162,7 +162,7 @@ const styles = _StyleSheet.default.create({
162
162
  minHeight: _Platform.default.OS === 'web' ? '100%' : 'auto'
163
163
  },
164
164
  cancelButton: {
165
- flex: 1
165
+ display: 'flex'
166
166
  }
167
167
  });
168
168
  ModalContent.propTypes = {
@@ -31,6 +31,7 @@ const WebModal = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
31
31
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
32
32
  style: staticStyles.container,
33
33
  ...selectProps(rest),
34
+ focusable: true,
34
35
  ref: ref,
35
36
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
36
37
  style: staticStyles.content,
@@ -105,19 +105,19 @@ const getMediaQueryStyles = (themeTokens, themeOptions, mediaIdsRef, dismissible
105
105
  justifyContent: 'space-between',
106
106
  ...(0, _utils.createMediaQueryStyles)({
107
107
  xs: {
108
- width: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content = themeOptions.contentMaxWidth) === null || _themeOptions$content === void 0 ? void 0 : _themeOptions$content.xs) || '100%'
108
+ maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content = themeOptions.contentMaxWidth) === null || _themeOptions$content === void 0 ? void 0 : _themeOptions$content.xs) || '100%'
109
109
  },
110
110
  md: {
111
- width: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content2 = themeOptions.contentMaxWidth) === null || _themeOptions$content2 === void 0 ? void 0 : _themeOptions$content2.md) || '100%'
111
+ maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content2 = themeOptions.contentMaxWidth) === null || _themeOptions$content2 === void 0 ? void 0 : _themeOptions$content2.md) || '100%'
112
112
  },
113
113
  lg: {
114
- width: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content3 = themeOptions.contentMaxWidth) === null || _themeOptions$content3 === void 0 ? void 0 : _themeOptions$content3.lg) || '100%'
114
+ maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content3 = themeOptions.contentMaxWidth) === null || _themeOptions$content3 === void 0 ? void 0 : _themeOptions$content3.lg) || '100%'
115
115
  },
116
116
  sm: {
117
- width: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content4 = themeOptions.contentMaxWidth) === null || _themeOptions$content4 === void 0 ? void 0 : _themeOptions$content4.sm) || '100%'
117
+ maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content4 = themeOptions.contentMaxWidth) === null || _themeOptions$content4 === void 0 ? void 0 : _themeOptions$content4.sm) || '100%'
118
118
  },
119
119
  xl: {
120
- width: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content5 = themeOptions.contentMaxWidth) === null || _themeOptions$content5 === void 0 ? void 0 : _themeOptions$content5.xl) || '100%'
120
+ maxWidth: (themeOptions === null || themeOptions === void 0 ? void 0 : (_themeOptions$content5 = themeOptions.contentMaxWidth) === null || _themeOptions$content5 === void 0 ? void 0 : _themeOptions$content5.xl) || '100%'
121
121
  }
122
122
  })
123
123
  }
@@ -92,7 +92,15 @@ const selectBottomTextTypographyTokens = _ref6 => {
92
92
  lineHeight: bottomTextLineHeight
93
93
  };
94
94
  };
95
- const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
95
+ const selectContainertokens = _ref7 => {
96
+ let {
97
+ alignItemsText
98
+ } = _ref7;
99
+ return {
100
+ alignItems: alignItemsText
101
+ };
102
+ };
103
+ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref8, ref) => {
96
104
  let {
97
105
  size = 'medium',
98
106
  signDirection = 'left',
@@ -109,7 +117,7 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
109
117
  tokens: priceLockupTokens,
110
118
  variant = {},
111
119
  ...rest
112
- } = _ref7;
120
+ } = _ref8;
113
121
  const viewport = (0, _ViewportProvider.useViewport)();
114
122
  const {
115
123
  footnoteMarginTop,
@@ -134,7 +142,7 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref7, ref) => {
134
142
  const topTextTypographyTokens = selectTopTextTypographyTokens(themeTokens);
135
143
  const bottomTextTypographyTokens = selectBottomTextTypographyTokens(themeTokens);
136
144
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
137
- style: [staticStyles.priceLockupContainer],
145
+ style: [staticStyles.priceLockupContainer, selectContainertokens(themeTokens)],
138
146
  ref: ref,
139
147
  ...selectProps(rest),
140
148
  children: [topText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
@@ -18,14 +18,16 @@ const selectProgressStyles = _ref => {
18
18
  borderWidth,
19
19
  borderColor,
20
20
  borderRadius,
21
- height
21
+ height,
22
+ shadow
22
23
  } = _ref;
23
24
  return {
24
25
  backgroundColor,
25
26
  borderWidth,
26
27
  borderColor,
27
28
  borderRadius,
28
- height
29
+ height,
30
+ ...(0, _ThemeProvider.applyShadowToken)(shadow)
29
31
  };
30
32
  };
31
33
 
@@ -45,6 +47,7 @@ const selectProgressStyles = _ref => {
45
47
  * - `borderRadius` for the rounded corners,
46
48
  * - `borderWidth` to change the border width.
47
49
  * - `height` to control the height of the progress bars displayed within the progress bar container.
50
+ * - `shadow` to apply a box shadow to the progress bar container.
48
51
  *
49
52
  * ## Variants
50
53
  *
@@ -20,13 +20,15 @@ const selectBarStyles = (_ref, percentage) => {
20
20
  backgroundColor,
21
21
  borderRadius,
22
22
  outlineWidth,
23
- outlineColor
23
+ outlineColor,
24
+ shadow
24
25
  } = _ref;
25
26
  return {
26
27
  backgroundColor,
27
28
  borderRadius,
28
29
  outlineWidth,
29
30
  outlineColor,
31
+ ...(0, _ThemeProvider.applyShadowToken)(shadow),
30
32
  width: `${percentage}%`
31
33
  };
32
34
  };
@@ -46,6 +48,7 @@ const selectBarStyles = (_ref, percentage) => {
46
48
  * - `borderRadius` for the rounded corners,
47
49
  * - `outlineColor` to control the color of the border (outline),
48
50
  * - `outlineWidth` to change the outline width.
51
+ * - `shadow` to apply a box shadow to the progress bar.
49
52
  *
50
53
  * ## Variants
51
54
  *
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _Text = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Text"));
10
10
  var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
11
+ var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
11
12
  var _ThemeProvider = require("../ThemeProvider");
12
13
  var _utils = require("../ThemeProvider/utils");
13
14
  var _utils2 = require("../utils");
@@ -45,9 +46,22 @@ const selectTextStyles = (_ref, themeOptions) => {
45
46
  gradient
46
47
  });
47
48
  };
49
+ const HALF_FONT_SIZE = 2;
50
+ const QUARTER_FONT_SIZE = 4;
51
+ const selectMobileSubSupStyles = (_ref2, type) => {
52
+ let {
53
+ fontSize
54
+ } = _ref2;
55
+ return {
56
+ fontSize: fontSize / HALF_FONT_SIZE,
57
+ lineHeight: fontSize,
58
+ position: 'relative',
59
+ top: type === 'sub' ? fontSize / QUARTER_FONT_SIZE : -fontSize / QUARTER_FONT_SIZE
60
+ };
61
+ };
48
62
 
49
63
  // General-purpose flexible theme-neutral base component for text
50
- const Typography = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
64
+ const Typography = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
51
65
  let {
52
66
  children,
53
67
  variant,
@@ -60,7 +74,7 @@ const Typography = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
60
74
  dataSet,
61
75
  strikeThrough = false,
62
76
  ...rest
63
- } = _ref2;
77
+ } = _ref3;
64
78
  const viewport = (0, _ViewportProvider.useViewport)();
65
79
  const {
66
80
  themeOptions
@@ -107,8 +121,8 @@ const Typography = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
107
121
  let textStyles;
108
122
  let mediaIds;
109
123
  if (enableMediaQueryStyleSheet) {
110
- const transformedThemeTokens = Object.entries(themeTokens).reduce((acc, _ref3) => {
111
- let [vp, viewportTokens] = _ref3;
124
+ const transformedThemeTokens = Object.entries(themeTokens).reduce((acc, _ref4) => {
125
+ let [vp, viewportTokens] = _ref4;
112
126
  acc[vp] = selectTextStyles({
113
127
  textAlign: align,
114
128
  textDecorationLine,
@@ -142,22 +156,31 @@ const Typography = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
142
156
  ...selectContainerProps(rest)
143
157
  };
144
158
  const resetTagStyling = child => {
145
- if (typeof child === 'object' && ((child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup')) {
146
- var _child$props;
147
- const childStyles = (child === null || child === void 0 ? void 0 : (_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.style) || {};
148
- const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize;
149
- const sanitizedChild = /*#__PURE__*/_react.default.cloneElement(child, {
150
- style: {
151
- ...childStyles,
152
- ...(supFontSize ? {
153
- fontSize: supFontSize
154
- } : {}),
155
- lineHeight: 0
156
- }
157
- });
158
- return sanitizedChild;
159
+ var _child$props;
160
+ if (typeof child !== 'object' || !((child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup')) {
161
+ return child;
159
162
  }
160
- return child;
163
+ const childStyles = (child === null || child === void 0 ? void 0 : (_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.style) || {};
164
+ const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize;
165
+ const isMobile = _Platform.default.OS === 'ios' || _Platform.default.OS === 'android';
166
+ const isSubSup = (child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup';
167
+ const mobileStyles = isMobile && isSubSup ? selectMobileSubSupStyles(themeTokens, child === null || child === void 0 ? void 0 : child.type) : {};
168
+ const defaultStyles = !isMobile && isSubSup ? {
169
+ fontSize: supFontSize,
170
+ lineHeight: 0
171
+ } : {};
172
+ const sanitizedChild = /*#__PURE__*/_react.default.cloneElement(isMobile && isSubSup ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
173
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
174
+ style: [childStyles, mobileStyles],
175
+ children: child.props.children
176
+ })
177
+ }) : child, {
178
+ style: {
179
+ ...childStyles,
180
+ ...defaultStyles
181
+ }
182
+ });
183
+ return sanitizedChild;
161
184
  };
162
185
  const sanitizeChildren = () => {
163
186
  if (Array.isArray(children)) {
package/lib/index.js CHANGED
@@ -82,6 +82,7 @@ var _exportNames = {
82
82
  applyOuterBorder: true,
83
83
  applyTextStyles: true,
84
84
  applyShadowToken: true,
85
+ useResponsiveThemeTokens: true,
85
86
  Portal: true
86
87
  };
87
88
  Object.defineProperty(exports, "A11yInfoProvider", {
@@ -528,6 +529,12 @@ Object.defineProperty(exports, "useHydrationContext", {
528
529
  return _HydrationContext.useHydrationContext;
529
530
  }
530
531
  });
532
+ Object.defineProperty(exports, "useResponsiveThemeTokens", {
533
+ enumerable: true,
534
+ get: function () {
535
+ return _ThemeProvider.useResponsiveThemeTokens;
536
+ }
537
+ });
531
538
  Object.defineProperty(exports, "useSetTheme", {
532
539
  enumerable: true,
533
540
  get: function () {
@@ -139,6 +139,7 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
139
139
 
140
140
  // When it's nested, selected value
141
141
  const [nestedSelectedValue, setNestedSelectedValue] = React.useState(null);
142
+ const [isInputVisible, setIsInputVisible] = React.useState(true);
142
143
  const {
143
144
  supportsProps,
144
145
  ...selectedProps
@@ -264,6 +265,27 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
264
265
  }));
265
266
  }
266
267
  }, [nestedSelectedValue, items]);
268
+ React.useEffect(() => {
269
+ if (Platform.OS === 'ios' || Platform.OS === 'android') {
270
+ return undefined;
271
+ }
272
+ const observer = new IntersectionObserver(entries => {
273
+ const [entry] = entries;
274
+ setIsInputVisible(entry.isIntersecting);
275
+ if (!entry.isIntersecting) {
276
+ setIsExpanded(false);
277
+ }
278
+ });
279
+ const currentInputRef = inputRef.current;
280
+ if (currentInputRef) {
281
+ observer.observe(currentInputRef);
282
+ }
283
+ return () => {
284
+ if (currentInputRef) {
285
+ observer.unobserve(currentInputRef);
286
+ }
287
+ };
288
+ }, [inputRef]);
267
289
  const handleClose = event => {
268
290
  var _openOverlayRef$curre, _openOverlayRef$curre2;
269
291
  if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27') || event.type === 'click' && !(openOverlayRef !== null && openOverlayRef !== void 0 && (_openOverlayRef$curre = openOverlayRef.current) !== null && _openOverlayRef$curre !== void 0 && _openOverlayRef$curre.contains(event.target)) || 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))) {
@@ -320,7 +342,19 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
320
342
  readOnly: readOnly,
321
343
  ref: inputRef,
322
344
  ...(Platform.OS !== 'web' ? {
323
- onLayout: event => setSourceLayout(event.nativeEvent.layout)
345
+ onLayout: event => {
346
+ setSourceLayout(event.nativeEvent.layout);
347
+ const {
348
+ y,
349
+ height
350
+ } = event.nativeEvent.layout;
351
+ if (y >= 0 && height > 0) {
352
+ setIsInputVisible(true);
353
+ } else {
354
+ setIsInputVisible(false);
355
+ setIsExpanded(false);
356
+ }
357
+ }
324
358
  } : {}),
325
359
  tokens: inputTokens,
326
360
  validation: validation,
@@ -333,7 +367,7 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
333
367
  })
334
368
  });
335
369
  }
336
- }), (isExpanded || hintExpansionEnabled) && /*#__PURE__*/_jsxs(_Fragment, {
370
+ }), (isExpanded || hintExpansionEnabled) && isInputVisible && /*#__PURE__*/_jsxs(_Fragment, {
337
371
  children: [/*#__PURE__*/_jsx(Listbox.Overlay, {
338
372
  overlaidPosition: overlaidPosition,
339
373
  isReady: isReady,
@@ -24,6 +24,7 @@ const selectStyles = _ref => {
24
24
  paddingTop,
25
25
  minWidth,
26
26
  shadow,
27
+ backgroundGradient,
27
28
  gradient
28
29
  } = _ref;
29
30
  return {
@@ -43,6 +44,9 @@ const selectStyles = _ref => {
43
44
  backgroundOrigin: `border-box`,
44
45
  boxShadow: `inset 0 1000px white`,
45
46
  border: `${borderWidth}px solid transparent`
47
+ } : {}),
48
+ ...(backgroundGradient && Platform.OS === 'web' ? {
49
+ backgroundImage: `linear-gradient(${backgroundGradient.angle}deg, ${backgroundGradient.stops[0].color}, ${backgroundGradient.stops[1].color})`
46
50
  } : {})
47
51
  };
48
52
  };
@@ -129,7 +129,8 @@ const staticStyles = StyleSheet.create({
129
129
  },
130
130
  titleAndContentContainer: {
131
131
  flexDirection: 'column',
132
- flexShrink: 1
132
+ flexShrink: 1,
133
+ flexGrow: 1
133
134
  }
134
135
  });
135
136
  ListItemBase.propTypes = {
@@ -99,6 +99,7 @@ const selectScrollViewStyles = () => ({
99
99
  * - Don’t use modals consecutively
100
100
  */
101
101
  const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
102
+ var _modalContentRef$curr2;
102
103
  let {
103
104
  children,
104
105
  isOpen,
@@ -127,6 +128,8 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
127
128
  maxWidth
128
129
  });
129
130
  const modalRef = useScrollBlocking(isOpen);
131
+ const modalBodyRef = React.useRef(ref);
132
+ const modalContentRef = React.useRef(null);
130
133
  const {
131
134
  closeIcon: CloseIconComponent
132
135
  } = themeTokens;
@@ -141,6 +144,25 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
141
144
  const handleKeyUp = event => {
142
145
  if (event.key === 'Escape') onClose();
143
146
  };
147
+ const manageFocus = React.useCallback(event => {
148
+ if (event.key === 'Tab') {
149
+ var _modalBodyRef$current;
150
+ const focusableElements = Array.from(modalBodyRef === null || modalBodyRef === void 0 ? void 0 : (_modalBodyRef$current = modalBodyRef.current) === null || _modalBodyRef$current === void 0 ? void 0 : _modalBodyRef$current.querySelectorAll(`
151
+ a[href], button, textarea, input, select,
152
+ [tabindex]:not([tabindex="-1"]),
153
+ [contenteditable="true"]
154
+ `));
155
+ const firstElement = focusableElements[0];
156
+ const lastElement = focusableElements[focusableElements.length - 1];
157
+ if (event.shiftKey && document.activeElement === firstElement) {
158
+ event.preventDefault();
159
+ lastElement.focus();
160
+ } else if (!event.shiftKey && document.activeElement === lastElement) {
161
+ event.preventDefault();
162
+ firstElement.focus();
163
+ }
164
+ }
165
+ }, [modalBodyRef]);
144
166
 
145
167
  // Show the custom react node passed to `closedButton` or the default close button if `closeButton` is `undefined`.
146
168
  // Hide the close button if `closeButton` is `null`.
@@ -151,22 +173,20 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
151
173
  const closeButtonRef = React.useRef(null);
152
174
  React.useEffect(() => {
153
175
  if (Platform.OS === 'web') {
154
- const handleFocus = () => {
155
- // If the focus is on the last item of the web modal container, move it to the close button
156
- if (document.activeElement === focusTrapRef.current && closeButtonRef.current) {
157
- closeButtonRef.current.focus();
158
- }
159
- return undefined;
160
- };
161
-
162
- // Add an event listener to manage focus in the web modal container
163
- document.addEventListener('focusin', handleFocus);
176
+ // Add an event listener to manage keydown and focus in the web modal container
177
+ document.addEventListener('keydown', manageFocus);
164
178
 
165
179
  // Clean up the event listener
166
- return () => document.removeEventListener('focusin', handleFocus);
180
+ return () => document.removeEventListener('keydown', manageFocus);
167
181
  }
168
182
  return undefined;
169
- }, []);
183
+ }, [manageFocus]);
184
+ React.useEffect(() => {
185
+ if (isOpen) {
186
+ var _modalContentRef$curr;
187
+ modalContentRef === null || modalContentRef === void 0 ? void 0 : (_modalContentRef$curr = modalContentRef.current) === null || _modalContentRef$curr === void 0 ? void 0 : _modalContentRef$curr.focus();
188
+ }
189
+ }, [isOpen, modalContentRef === null || modalContentRef === void 0 ? void 0 : (_modalContentRef$curr2 = modalContentRef.current) === null || _modalContentRef$curr2 === void 0 ? void 0 : _modalContentRef$curr2.focus]);
170
190
  if (!isOpen) {
171
191
  return null;
172
192
  }
@@ -179,7 +199,7 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
179
199
  pointerEvents: "box-none" // don't capture backdrop press events
180
200
  ,
181
201
  children: /*#__PURE__*/_jsxs(View, {
182
- ref: ref,
202
+ ref: modalBodyRef,
183
203
  style: [staticStyles.modal, selectModalStyles(themeTokens)],
184
204
  onKeyUp: handleKeyUp,
185
205
  children: [showCloseButton && /*#__PURE__*/_jsx(View, {
@@ -224,6 +244,7 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
224
244
  if (Platform.OS === 'web') {
225
245
  return /*#__PURE__*/_jsxs(WebModal, {
226
246
  ...selectProps(rest),
247
+ ref: modalContentRef,
227
248
  children: [content, /*#__PURE__*/_jsx(View, {
228
249
  accessibilityRole: "button",
229
250
  ref: focusTrapRef