@telus-uds/components-base 1.74.0 → 1.76.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 (50) hide show
  1. package/CHANGELOG.md +26 -2
  2. package/lib/Carousel/CarouselThumbnail.js +10 -4
  3. package/lib/Carousel/CarouselThumbnailNavigation.js +3 -3
  4. package/lib/Footnote/Footnote.js +9 -13
  5. package/lib/Link/ChevronLink.js +2 -0
  6. package/lib/Link/InlinePressable.js +15 -2
  7. package/lib/Link/LinkBase.js +1 -0
  8. package/lib/Notification/Notification.js +213 -35
  9. package/lib/OrderedList/OrderedList.js +21 -20
  10. package/lib/PriceLockup/PriceLockup.js +220 -0
  11. package/lib/PriceLockup/index.js +10 -0
  12. package/lib/PriceLockup/utils/renderFootnoteContent.js +93 -0
  13. package/lib/PriceLockup/utils/renderFootnoteLinks.js +36 -0
  14. package/lib/PriceLockup/utils/renderPrice.js +147 -0
  15. package/lib/PriceLockup/utils/renderTypography.js +31 -0
  16. package/lib/index.js +8 -0
  17. package/lib/utils/ssr-media-query/create-stylesheet/index.js +1 -2
  18. package/lib-module/Carousel/CarouselThumbnail.js +10 -4
  19. package/lib-module/Carousel/CarouselThumbnailNavigation.js +3 -3
  20. package/lib-module/Footnote/Footnote.js +9 -13
  21. package/lib-module/Link/ChevronLink.js +2 -0
  22. package/lib-module/Link/InlinePressable.js +16 -2
  23. package/lib-module/Link/LinkBase.js +1 -0
  24. package/lib-module/Notification/Notification.js +216 -38
  25. package/lib-module/OrderedList/OrderedList.js +21 -20
  26. package/lib-module/PriceLockup/PriceLockup.js +214 -0
  27. package/lib-module/PriceLockup/index.js +2 -0
  28. package/lib-module/PriceLockup/utils/renderFootnoteContent.js +87 -0
  29. package/lib-module/PriceLockup/utils/renderFootnoteLinks.js +28 -0
  30. package/lib-module/PriceLockup/utils/renderPrice.js +141 -0
  31. package/lib-module/PriceLockup/utils/renderTypography.js +23 -0
  32. package/lib-module/index.js +1 -0
  33. package/lib-module/utils/ssr-media-query/create-stylesheet/index.js +1 -2
  34. package/package.json +2 -2
  35. package/src/Carousel/CarouselThumbnail.jsx +8 -6
  36. package/src/Carousel/CarouselThumbnailNavigation.jsx +3 -4
  37. package/src/Footnote/Footnote.jsx +3 -6
  38. package/src/Link/ChevronLink.jsx +5 -1
  39. package/src/Link/InlinePressable.jsx +36 -15
  40. package/src/Link/LinkBase.jsx +1 -0
  41. package/src/Notification/Notification.jsx +213 -34
  42. package/src/OrderedList/OrderedList.jsx +17 -20
  43. package/src/PriceLockup/PriceLockup.jsx +218 -0
  44. package/src/PriceLockup/index.js +3 -0
  45. package/src/PriceLockup/utils/renderFootnoteContent.jsx +77 -0
  46. package/src/PriceLockup/utils/renderFootnoteLinks.jsx +38 -0
  47. package/src/PriceLockup/utils/renderPrice.jsx +201 -0
  48. package/src/PriceLockup/utils/renderTypography.jsx +13 -0
  49. package/src/index.js +1 -0
  50. package/src/utils/ssr-media-query/create-stylesheet/index.js +3 -2
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
3
+ import View from "react-native-web/dist/exports/View";
4
+ import Text from "react-native-web/dist/exports/Text";
5
+ import Platform from "react-native-web/dist/exports/Platform";
6
+ import renderTypography from './renderTypography';
7
+ import renderFootnoteLinks from './renderFootnoteLinks';
8
+ import { jsxs as _jsxs } from "react/jsx-runtime";
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ import { Fragment as _Fragment } from "react/jsx-runtime";
11
+ const selectFootnoteContainer = _ref => {
12
+ let {
13
+ footnoteMarginTop
14
+ } = _ref;
15
+ return {
16
+ marginTop: footnoteMarginTop
17
+ };
18
+ };
19
+ const selectFootnoteBottomTextContainer = _ref2 => {
20
+ let {
21
+ bottomTextMarginTop
22
+ } = _ref2;
23
+ return {
24
+ marginTop: bottomTextMarginTop
25
+ };
26
+ };
27
+ const selectFootnoteLinksStyles = _ref3 => {
28
+ let {
29
+ bottomLinksMarginLeft
30
+ } = _ref3;
31
+ return {
32
+ marginLeft: bottomLinksMarginLeft
33
+ };
34
+ };
35
+ const renderFootnoteContent = (footnoteMarginTop, bottomTextMarginTop, bottomText, bottomTextTypographyTokens, fontColor, footnoteLinks, bottomLinksMarginLeft, onClickFootnote, themeTokens) => {
36
+ const MAX_FOOTNOTE_LINKS_ALLOWED = 3;
37
+ return /*#__PURE__*/_jsxs(_Fragment, {
38
+ children: [/*#__PURE__*/_jsxs(View, {
39
+ style: [staticStyles.footnoteContainer, selectFootnoteContainer({
40
+ footnoteMarginTop
41
+ })],
42
+ children: [/*#__PURE__*/_jsxs(Text, {
43
+ style: selectFootnoteBottomTextContainer({
44
+ bottomTextMarginTop
45
+ }),
46
+ children: [renderTypography(bottomText, bottomTextTypographyTokens, undefined, fontColor), ' ']
47
+ }), footnoteLinks.length <= MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/_jsx(View, {
48
+ style: [staticStyles.footnoteLinkContainer, selectFootnoteLinksStyles({
49
+ bottomLinksMarginLeft
50
+ })],
51
+ children: renderFootnoteLinks(footnoteLinks, themeTokens, onClickFootnote)
52
+ }) : null]
53
+ }), footnoteLinks.length > MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/_jsx(View, {
54
+ style: staticStyles.verticalFootnoteLinkContainer,
55
+ children: renderFootnoteLinks(footnoteLinks, themeTokens, onClickFootnote)
56
+ }) : null]
57
+ });
58
+ };
59
+ export default renderFootnoteContent;
60
+ const staticStyles = StyleSheet.create({
61
+ footnoteContainer: {
62
+ flexDirection: 'row'
63
+ },
64
+ footnoteLinkContainer: {
65
+ flexDirection: 'row',
66
+ ...Platform.select({
67
+ ios: {
68
+ alignSelf: 'flex-end',
69
+ top: 2
70
+ },
71
+ android: {
72
+ alignSelf: 'center',
73
+ top: -8
74
+ }
75
+ })
76
+ },
77
+ verticalFootnoteLinkContainer: {
78
+ ...Platform.select({
79
+ ios: {
80
+ top: 10
81
+ },
82
+ android: {
83
+ top: -2
84
+ }
85
+ })
86
+ }
87
+ });
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import FootnoteLink from '../../Footnote/FootnoteLink';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ const selectFootnoteLinkStyles = (_ref, footnoteLinks) => {
5
+ let {
6
+ footnoteLinkColor,
7
+ footnoteLinkFontName,
8
+ footnoteLinkFontWeight,
9
+ footnoteLinkLineHeight,
10
+ footnoteLinkFontSize
11
+ } = _ref;
12
+ // This is used to apply the proper line height when there is 4 or more footnote links
13
+ const MAX_FOOTNOTE_LINKS_ALLOWED = 3;
14
+ const lineHeight = footnoteLinks.length > MAX_FOOTNOTE_LINKS_ALLOWED ? footnoteLinkFontSize * footnoteLinkLineHeight : undefined;
15
+ return {
16
+ color: footnoteLinkColor,
17
+ fontName: footnoteLinkFontName,
18
+ fontWeight: footnoteLinkFontWeight,
19
+ lineHeight,
20
+ fontSize: footnoteLinkFontSize
21
+ };
22
+ };
23
+ const renderFootnoteLinks = (footnoteLinks, themeTokens, onClickFootnote) => footnoteLinks && footnoteLinks.length > 0 ? /*#__PURE__*/_jsx(FootnoteLink, {
24
+ tokens: selectFootnoteLinkStyles(themeTokens, footnoteLinks),
25
+ content: footnoteLinks,
26
+ onClick: onClickFootnote
27
+ }) : null;
28
+ export default renderFootnoteLinks;
@@ -0,0 +1,141 @@
1
+ import React from 'react';
2
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
3
+ import View from "react-native-web/dist/exports/View";
4
+ import Text from "react-native-web/dist/exports/Text";
5
+ import Platform from "react-native-web/dist/exports/Platform";
6
+ import A11yText from '../../A11yText';
7
+ import renderTypography from './renderTypography';
8
+ import renderFootnoteLinks from './renderFootnoteLinks';
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ import { Fragment as _Fragment } from "react/jsx-runtime";
11
+ import { jsxs as _jsxs } from "react/jsx-runtime";
12
+ const selectStrikeThroughStyles = _ref => {
13
+ let {
14
+ strikeThroughColor
15
+ } = _ref;
16
+ return {
17
+ textDecorationColor: strikeThroughColor
18
+ };
19
+ };
20
+ const selectFootnoteLinksStyles = _ref2 => {
21
+ let {
22
+ bottomLinksMarginLeft
23
+ } = _ref2;
24
+ return {
25
+ marginLeft: bottomLinksMarginLeft
26
+ };
27
+ };
28
+ const renderCurrencySymbol = (currencySymbol, currencySymbolTypographyTokens, ratePosition, fontColor) => renderTypography(`${currencySymbol}`, currencySymbolTypographyTokens, ratePosition, fontColor);
29
+ const renderAmount = (amount, amountTypographyTokens, strikeThrough, a11yText, fontColor, themeTokens) => {
30
+ const amountText = renderTypography(amount, amountTypographyTokens, undefined, fontColor); // undefined is ratePosition
31
+ if (strikeThrough) {
32
+ return /*#__PURE__*/_jsxs(_Fragment, {
33
+ children: [/*#__PURE__*/_jsx(A11yText, {
34
+ text: a11yText
35
+ }), /*#__PURE__*/_jsx(Text, {
36
+ style: [staticStyles.strikeThroughContainer, selectStrikeThroughStyles(themeTokens)],
37
+ children: amountText
38
+ })]
39
+ });
40
+ }
41
+ return amountText;
42
+ };
43
+ const renderPrice = (price, rateText, ratePosition, signDirection, currencySymbol, currencySymbolTypographyTokens, amountTypographyTokens, centsTypographyTokens, rateTypographyTokens, fontColor, strikeThrough, a11yText, bottomText, bottomLinksMarginLeft, footnoteLinks, onClickFootnote, themeTokens) => {
44
+ const priceString = price;
45
+ const lastDotPosition = priceString.lastIndexOf('.');
46
+ const lastCommaPosition = priceString.lastIndexOf(',');
47
+ const [separator, separatorPosition] = lastDotPosition > lastCommaPosition ? ['.', lastDotPosition] : [',', lastCommaPosition];
48
+
49
+ // If the separator is at the fourth character from the end of the string or more, it's most probably
50
+ // a part of the amount, and the cents are not included in the price string
51
+ const EXCLUDE_CENTS = 3;
52
+ const hasCents = separatorPosition !== -1 && separatorPosition >= priceString.length - EXCLUDE_CENTS;
53
+ const amount = hasCents ? priceString.substring(0, separatorPosition) : priceString;
54
+ const cents = hasCents ? priceString.substring(separatorPosition + 1) : null;
55
+ const footnoteLinkPositionStyles = rateText ? staticStyles.footnoteLinksWithoutBottomText : staticStyles.footnoteLinksWithoutBottomTextAndRateText;
56
+ const MAX_FOOTNOTE_LINKS_ALLOWED = 3;
57
+ return /*#__PURE__*/_jsxs(_Fragment, {
58
+ children: [/*#__PURE__*/_jsxs(View, {
59
+ style: ratePosition === 'bottom' ? staticStyles.priceContainerColumn : staticStyles.priceContainerRow,
60
+ children: [/*#__PURE__*/_jsxs(View, {
61
+ style: staticStyles.priceContainer,
62
+ children: [signDirection === 'left' ? /*#__PURE__*/_jsx(Text, {
63
+ children: renderCurrencySymbol(currencySymbol, currencySymbolTypographyTokens, ratePosition, fontColor)
64
+ }) : null, renderAmount(amount, amountTypographyTokens, strikeThrough, a11yText, fontColor, themeTokens), cents ? renderTypography(`${separator}${cents}`, centsTypographyTokens, undefined, fontColor) : null, signDirection === 'right' ? /*#__PURE__*/_jsx(Text, {
65
+ style: staticStyles.currencySymbol,
66
+ children: renderCurrencySymbol(currencySymbol, currencySymbolTypographyTokens, ratePosition, fontColor)
67
+ }) : null]
68
+ }), rateText ? /*#__PURE__*/_jsx(Text, {
69
+ style: ratePosition === 'bottom' ? staticStyles.rateTextVerticalPosition : [staticStyles.rateTextPosition, staticStyles.rateTextVerticalPosition],
70
+ children: renderTypography(rateText, rateTypographyTokens, ratePosition, fontColor)
71
+ }) : null, !bottomText && footnoteLinks.length <= MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/_jsx(Text, {
72
+ style: [footnoteLinkPositionStyles, selectFootnoteLinksStyles({
73
+ bottomLinksMarginLeft
74
+ })],
75
+ children: renderFootnoteLinks(footnoteLinks, themeTokens, onClickFootnote)
76
+ }) : null]
77
+ }), !bottomText && footnoteLinks.length > MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/_jsx(View, {
78
+ style: staticStyles.verticalFootnoteLinkContainer,
79
+ children: renderFootnoteLinks(footnoteLinks, themeTokens, onClickFootnote)
80
+ }) : null]
81
+ });
82
+ };
83
+ export default renderPrice;
84
+ const staticStyles = StyleSheet.create({
85
+ priceContainerRow: {
86
+ flexDirection: 'row'
87
+ },
88
+ priceContainerColumn: {
89
+ flexDirection: 'column'
90
+ },
91
+ priceContainer: {
92
+ flexDirection: 'row',
93
+ alignSelf: 'flex-start',
94
+ marginTop: 4
95
+ },
96
+ currencySymbol: {
97
+ paddingLeft: 4
98
+ },
99
+ verticalFootnoteLinkContainer: {
100
+ ...Platform.select({
101
+ ios: {
102
+ top: 10
103
+ },
104
+ android: {
105
+ top: -2
106
+ }
107
+ })
108
+ },
109
+ footnoteLinksWithoutBottomText: {
110
+ ...Platform.select({
111
+ ios: {
112
+ alignSelf: 'flex-end',
113
+ top: -10
114
+ },
115
+ android: {
116
+ alignSelf: 'center',
117
+ top: -14
118
+ }
119
+ })
120
+ },
121
+ footnoteLinksWithoutBottomTextAndRateText: {
122
+ ...Platform.select({
123
+ ios: {
124
+ alignSelf: 'center'
125
+ },
126
+ android: {
127
+ alignSelf: 'flex-start'
128
+ }
129
+ })
130
+ },
131
+ strikeThroughContainer: {
132
+ textDecorationLine: 'line-through',
133
+ textDecorationThickness: '1px'
134
+ },
135
+ rateTextPosition: {
136
+ alignSelf: 'flex-end'
137
+ },
138
+ rateTextVerticalPosition: {
139
+ top: -8
140
+ }
141
+ });
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import Typography from '../../Typography';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ const renderTypography = (value, themeTokens, ratePosition, fontColor) => {
5
+ const customProps = ratePosition === 'bottom' ? {
6
+ variant: {
7
+ size: 'micro'
8
+ },
9
+ tokens: {
10
+ color: fontColor
11
+ }
12
+ } : {
13
+ tokens: {
14
+ ...themeTokens,
15
+ color: fontColor
16
+ }
17
+ };
18
+ return /*#__PURE__*/_jsx(Typography, {
19
+ ...customProps,
20
+ children: value
21
+ });
22
+ };
23
+ export default renderTypography;
@@ -32,6 +32,7 @@ export { default as MultiSelectFilter } from './MultiSelectFilter';
32
32
  export { default as Notification } from './Notification';
33
33
  export { default as OrderedList } from './OrderedList';
34
34
  export { default as Pagination } from './Pagination';
35
+ export { default as PriceLockup } from './PriceLockup';
35
36
  export { default as Progress } from './Progress';
36
37
  export { default as QuickLinks } from './QuickLinks';
37
38
  export { default as QuickLinksFeature } from './QuickLinksFeature';
@@ -8,12 +8,11 @@ const createStyleSheet = stylesWithQuery => {
8
8
  styles: {},
9
9
  fullStyles: {}
10
10
  };
11
- let cleanStyles;
12
11
  let ids = {};
12
+ const cleanStyles = deepClone(stylesWithQuery);
13
13
  Object.keys(stylesWithQuery).forEach(key => {
14
14
  if (!(stylesWithQuery !== null && stylesWithQuery !== void 0 && stylesWithQuery[key])) return;
15
15
  const mediaQueriesAndPseudoClasses = Object.keys(stylesWithQuery[key]).filter(isMediaOrPseudo);
16
- cleanStyles = deepClone(stylesWithQuery);
17
16
  mediaQueriesAndPseudoClasses.forEach(query => {
18
17
  var _ids;
19
18
  const css = createDeclarationBlock(stylesWithQuery[key][query]);
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.50.0",
14
+ "@telus-uds/system-theme-tokens": "^2.50.1",
15
15
  "airbnb-prop-types": "^2.16.0",
16
16
  "css-mediaquery": "^0.1.2",
17
17
  "expo-linear-gradient": "^12.5.0",
@@ -85,5 +85,5 @@
85
85
  "standard-engine": {
86
86
  "skip": true
87
87
  },
88
- "version": "1.74.0"
88
+ "version": "1.76.0"
89
89
  }
@@ -32,7 +32,7 @@ const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
32
32
  // Allow using the spacebar for navigation
33
33
  if (event?.key === ' ') goTo(index)
34
34
  }
35
- const { borderWidth, padding, selectedBorderColor, selectedBorderWidth, size } =
35
+ const { borderWidth, padding, selectedBorderColor, selectedBorderWidth, size, margin } =
36
36
  getThumbnailTokens({ viewport })
37
37
  const styles = {
38
38
  image: {
@@ -42,7 +42,12 @@ const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
42
42
  selected: {
43
43
  borderColor: selectedBorderColor,
44
44
  borderWidth: selectedBorderWidth,
45
- padding: padding - selectedBorderWidth + borderWidth
45
+ padding: padding - selectedBorderWidth,
46
+ marginBottom: margin + selectedBorderWidth
47
+ },
48
+ nonSelected: {
49
+ padding: padding - borderWidth,
50
+ marginBottom: margin + selectedBorderWidth
46
51
  }
47
52
  }
48
53
 
@@ -62,10 +67,7 @@ const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
62
67
 
63
68
  return [
64
69
  pressableStyles,
65
- index === activeIndex && styles.selected,
66
- {
67
- outline: 'none'
68
- }
70
+ index === activeIndex ? [styles.selected, { outline: 'none' }] : styles.nonSelected
69
71
  ]
70
72
  }}
71
73
  >
@@ -14,20 +14,19 @@ const CarouselThumbnailNavigation = forwardRef(({ thumbnails = [] }, ref) => {
14
14
  if (thumbnails.length !== totalItems) {
15
15
  throw new Error('Thumbnail set provided does not match the number of slides in the carousel')
16
16
  }
17
- const { containerPaddingTop: thumbnailContainerPaddingTop, margin: thumbnailMargin } =
18
- useThemeTokens('CarouselThumbnail')
17
+ const { containerPaddingTop: thumbnailContainerPaddingTop } = useThemeTokens('CarouselThumbnail')
19
18
  const stackWrapTokens = {
20
19
  justifyContent: 'flex-start'
21
20
  }
22
21
  const containerStyles = {
23
22
  justifyContent: 'center',
24
23
  alignItems,
25
- paddingTop: thumbnailContainerPaddingTop - thumbnailMargin
24
+ paddingTop: thumbnailContainerPaddingTop
26
25
  }
27
26
 
28
27
  return (
29
28
  <View style={containerStyles}>
30
- <StackWrap direction="row" tokens={stackWrapTokens} ref={ref}>
29
+ <StackWrap direction="row" tokens={stackWrapTokens} space={2} ref={ref}>
31
30
  {thumbnails.map(({ accessibilityLabel, alt, src }, index) => (
32
31
  <CarouselThumbnail
33
32
  accessibilityLabel={accessibilityLabel}
@@ -156,13 +156,10 @@ const Footnote = ({
156
156
  }
157
157
 
158
158
  return (
159
- // TODO: Extract the OrderedList.Item from the array when the issue #4361 is fixed
160
159
  <OrderedList start={number}>
161
- {[
162
- <OrderedList.Item key={number}>
163
- <Text style={selectCustomContentFontStyle(themeTokens)}>{content}</Text>
164
- </OrderedList.Item>
165
- ]}
160
+ <OrderedList.Item key={number}>
161
+ <Text style={selectCustomContentFontStyle(themeTokens)}>{content}</Text>
162
+ </OrderedList.Item>
166
163
  </OrderedList>
167
164
  )
168
165
  }, [content, number, themeTokens])
@@ -12,7 +12,10 @@ import LinkBase from './LinkBase'
12
12
  * ChevronLink is not intended to be deeply themable; variants passed to ChevronLink are forwarded to Link.
13
13
  */
14
14
  const ChevronLink = forwardRef(
15
- ({ direction = 'right', children, tokens = {}, variant, dataSet, ...otherlinkProps }, ref) => {
15
+ (
16
+ { direction = 'right', children, tokens = {}, variant, dataSet, onPress, ...otherlinkProps },
17
+ ref
18
+ ) => {
16
19
  const getChevronTokens = useThemeTokensCallback('ChevronLink', tokens, variant)
17
20
  const applyChevronTokens = (linkState) => {
18
21
  const { leftIcon, rightIcon, iconDisplace, height, fontSize, ...otherTokens } =
@@ -38,6 +41,7 @@ const ChevronLink = forwardRef(
38
41
  tokens={getTokens}
39
42
  dataSet={dataSet}
40
43
  ref={ref}
44
+ onPress={onPress}
41
45
  >
42
46
  {children}
43
47
  </LinkBase>
@@ -1,5 +1,5 @@
1
- import React, { forwardRef } from 'react'
2
- import { Pressable, StyleSheet } from 'react-native'
1
+ import React, { forwardRef, useCallback } from 'react'
2
+ import { Pressable, StyleSheet, Platform } from 'react-native'
3
3
 
4
4
  /**
5
5
  * @typedef {import('react-native').PressableProps} PressableProps
@@ -14,19 +14,40 @@ import { Pressable, StyleSheet } from 'react-native'
14
14
  * @param {PressableProps} PressableProps
15
15
  */
16
16
  // React Native exports prop Types but not propTypes, use JSDoc types here rather than duplicate RN
17
- // eslint-disable-next-line react/prop-types
18
- const InlinePressable = forwardRef(({ children, inlineFlex = true, style, ...props }, ref) => (
19
- <Pressable
20
- ref={ref}
21
- style={(pressState) => [
22
- typeof style === 'function' ? style(pressState) : style,
23
- staticStyles[inlineFlex ? 'inlineFlex' : 'inline']
24
- ]}
25
- {...props}
26
- >
27
- {(pressState) => (typeof children === 'function' ? children(pressState) : children)}
28
- </Pressable>
29
- ))
17
+ /* eslint-disable react/prop-types */
18
+ const InlinePressable = forwardRef(
19
+ ({ children, inlineFlex = true, style, onPress, ...props }, ref) => {
20
+ const handlePress = useCallback(() => {
21
+ if (onPress) {
22
+ onPress()
23
+ }
24
+ }, [onPress])
25
+
26
+ const handleKeyPress = useCallback(
27
+ (e) => {
28
+ if (e.key === 'Enter' || e.key === ' ') {
29
+ handlePress()
30
+ }
31
+ },
32
+ [handlePress]
33
+ )
34
+
35
+ return (
36
+ <Pressable
37
+ ref={ref}
38
+ style={(pressState) => [
39
+ typeof style === 'function' ? style(pressState) : style,
40
+ staticStyles[inlineFlex ? 'inlineFlex' : 'inline']
41
+ ]}
42
+ onPress={handlePress}
43
+ onKeyDown={Platform.OS === 'web' ? handleKeyPress : undefined}
44
+ {...props}
45
+ >
46
+ {(pressState) => (typeof children === 'function' ? children(pressState) : children)}
47
+ </Pressable>
48
+ )
49
+ }
50
+ )
30
51
  InlinePressable.displayName = 'InlinePressable'
31
52
 
32
53
  const staticStyles = StyleSheet.create({
@@ -162,6 +162,7 @@ const LinkBase = forwardRef(
162
162
  inlineFlex={hasIcon}
163
163
  // assuming links without icons should be inline (even if they are long)
164
164
  ref={ref}
165
+ keyboardShouldPersistTaps="handled"
165
166
  style={(linkState) => {
166
167
  const themeTokens = resolveLinkTokens(linkState)
167
168
  const outerBorderStyles = selectOuterBorderStyles(themeTokens)