@telus-uds/components-web 1.3.0 → 1.5.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 (128) hide show
  1. package/CHANGELOG.md +32 -2
  2. package/lib/Breadcrumbs/Breadcrumbs.js +247 -0
  3. package/lib/Breadcrumbs/Item/Item.js +165 -0
  4. package/lib/Breadcrumbs/index.js +15 -0
  5. package/lib/Callout/Callout.js +121 -0
  6. package/lib/Callout/index.js +13 -0
  7. package/lib/DatePicker/CalendarContainer.js +221 -0
  8. package/lib/DatePicker/DatePicker.js +329 -0
  9. package/lib/DatePicker/dictionary.js +134 -0
  10. package/lib/DatePicker/index.js +13 -0
  11. package/lib/DatePicker/reactDatesCss.js +12 -0
  12. package/lib/ExpandCollapseMini/ExpandCollapseMini.js +75 -0
  13. package/lib/ExpandCollapseMini/ExpandCollapseMiniControl.js +95 -0
  14. package/lib/ExpandCollapseMini/index.js +13 -0
  15. package/lib/Footnote/Footnote.js +571 -0
  16. package/lib/Footnote/FootnoteLink.js +149 -0
  17. package/lib/Footnote/dictionary.js +19 -0
  18. package/lib/Footnote/index.js +16 -0
  19. package/lib/Paragraph/Paragraph.js +107 -0
  20. package/lib/Paragraph/index.js +13 -0
  21. package/lib/PreviewCard/AuthorDate.js +64 -0
  22. package/lib/PreviewCard/PreviewCard.js +236 -0
  23. package/lib/PreviewCard/index.js +13 -0
  24. package/lib/PriceLockup/PriceLockup.js +237 -0
  25. package/lib/PriceLockup/index.js +13 -0
  26. package/lib/PriceLockup/tokens.js +131 -0
  27. package/lib/ResponsiveImage/ResponsiveImage.js +115 -0
  28. package/lib/ResponsiveImage/index.js +13 -0
  29. package/lib/Ribbon/Ribbon.js +0 -1
  30. package/lib/Span/Span.js +88 -0
  31. package/lib/Span/index.js +13 -0
  32. package/lib/index.js +91 -1
  33. package/lib/shared/FullBleedContent/FullBleedContent.js +121 -0
  34. package/lib/shared/FullBleedContent/getFullBleedBorderRadius.js +73 -0
  35. package/lib/shared/FullBleedContent/index.js +29 -0
  36. package/lib/shared/FullBleedContent/useFullBleedContentProps.js +73 -0
  37. package/lib/utils/index.js +32 -0
  38. package/lib/utils/logger.js +31 -0
  39. package/lib/utils/media.js +54 -0
  40. package/lib/utils/renderStructuredContent.js +89 -0
  41. package/lib/utils/useTypographyTheme.js +32 -0
  42. package/lib-module/Breadcrumbs/Breadcrumbs.js +228 -0
  43. package/lib-module/Breadcrumbs/Item/Item.js +141 -0
  44. package/lib-module/Breadcrumbs/index.js +1 -0
  45. package/lib-module/Callout/Callout.js +106 -0
  46. package/lib-module/Callout/index.js +2 -0
  47. package/lib-module/DatePicker/CalendarContainer.js +208 -0
  48. package/lib-module/DatePicker/DatePicker.js +302 -0
  49. package/lib-module/DatePicker/dictionary.js +127 -0
  50. package/lib-module/DatePicker/index.js +2 -0
  51. package/lib-module/DatePicker/reactDatesCss.js +3 -0
  52. package/lib-module/ExpandCollapseMini/ExpandCollapseMini.js +56 -0
  53. package/lib-module/ExpandCollapseMini/ExpandCollapseMiniControl.js +80 -0
  54. package/lib-module/ExpandCollapseMini/index.js +2 -0
  55. package/lib-module/Footnote/Footnote.js +541 -0
  56. package/lib-module/Footnote/FootnoteLink.js +130 -0
  57. package/lib-module/Footnote/dictionary.js +12 -0
  58. package/lib-module/Footnote/index.js +4 -0
  59. package/lib-module/Paragraph/Paragraph.js +89 -0
  60. package/lib-module/Paragraph/index.js +2 -0
  61. package/lib-module/PreviewCard/AuthorDate.js +53 -0
  62. package/lib-module/PreviewCard/PreviewCard.js +211 -0
  63. package/lib-module/PreviewCard/index.js +2 -0
  64. package/lib-module/PriceLockup/PriceLockup.js +213 -0
  65. package/lib-module/PriceLockup/index.js +2 -0
  66. package/lib-module/PriceLockup/tokens.js +120 -0
  67. package/lib-module/ResponsiveImage/ResponsiveImage.js +100 -0
  68. package/lib-module/ResponsiveImage/index.js +2 -0
  69. package/lib-module/Ribbon/Ribbon.js +1 -2
  70. package/lib-module/Span/Span.js +70 -0
  71. package/lib-module/Span/index.js +2 -0
  72. package/lib-module/index.js +10 -0
  73. package/lib-module/shared/FullBleedContent/FullBleedContent.js +106 -0
  74. package/lib-module/shared/FullBleedContent/getFullBleedBorderRadius.js +65 -0
  75. package/lib-module/shared/FullBleedContent/index.js +4 -0
  76. package/lib-module/shared/FullBleedContent/useFullBleedContentProps.js +65 -0
  77. package/lib-module/utils/index.js +5 -1
  78. package/lib-module/utils/logger.js +18 -0
  79. package/lib-module/utils/media.js +46 -0
  80. package/lib-module/utils/renderStructuredContent.js +77 -0
  81. package/lib-module/utils/useTypographyTheme.js +24 -0
  82. package/package.json +9 -5
  83. package/src/Breadcrumbs/Breadcrumbs.jsx +222 -0
  84. package/src/Breadcrumbs/Item/Item.jsx +127 -0
  85. package/src/Breadcrumbs/index.js +1 -0
  86. package/src/Callout/Callout.jsx +76 -0
  87. package/src/Callout/index.js +3 -0
  88. package/src/DatePicker/CalendarContainer.jsx +210 -0
  89. package/src/DatePicker/DatePicker.jsx +303 -0
  90. package/src/DatePicker/dictionary.js +92 -0
  91. package/src/DatePicker/index.js +3 -0
  92. package/src/DatePicker/reactDatesCss.js +892 -0
  93. package/src/ExpandCollapseMini/ExpandCollapseMini.jsx +48 -0
  94. package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +67 -0
  95. package/src/ExpandCollapseMini/index.js +3 -0
  96. package/src/Footnote/Footnote.jsx +468 -0
  97. package/src/Footnote/FootnoteLink.jsx +120 -0
  98. package/src/Footnote/dictionary.js +12 -0
  99. package/src/Footnote/index.js +6 -0
  100. package/src/Paragraph/Paragraph.jsx +79 -0
  101. package/src/Paragraph/index.js +3 -0
  102. package/src/PreviewCard/AuthorDate.jsx +31 -0
  103. package/src/PreviewCard/PreviewCard.jsx +201 -0
  104. package/src/PreviewCard/index.js +3 -0
  105. package/src/PriceLockup/PriceLockup.jsx +210 -0
  106. package/src/PriceLockup/index.js +3 -0
  107. package/src/PriceLockup/tokens.js +58 -0
  108. package/src/ResponsiveImage/ResponsiveImage.jsx +77 -0
  109. package/src/ResponsiveImage/index.js +3 -0
  110. package/src/Ribbon/Ribbon.jsx +0 -1
  111. package/src/Span/Span.jsx +66 -0
  112. package/src/Span/index.js +3 -0
  113. package/src/index.js +10 -0
  114. package/src/shared/FullBleedContent/FullBleedContent.jsx +90 -0
  115. package/src/shared/FullBleedContent/getFullBleedBorderRadius.js +55 -0
  116. package/src/shared/FullBleedContent/index.js +6 -0
  117. package/src/shared/FullBleedContent/useFullBleedContentProps.js +63 -0
  118. package/src/utils/index.js +5 -1
  119. package/src/utils/logger.js +20 -0
  120. package/src/utils/media.js +40 -0
  121. package/src/utils/renderStructuredContent.jsx +73 -0
  122. package/src/utils/useTypographyTheme.js +14 -0
  123. package/types/Callout.d.ts +13 -0
  124. package/types/DatePicker.d.ts +21 -0
  125. package/types/Footnote.d.ts +21 -0
  126. package/types/FootnoteLink.d.ts +20 -0
  127. package/types/PriceLockup.d.ts +22 -0
  128. package/types/common.d.ts +14 -0
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import { selectSystemProps } from '@telus-uds/components-base';
5
+ import { htmlAttrs, useTypographyTheme } from '../utils';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
8
+ const StyledParagraph = /*#__PURE__*/styled.p.withConfig({
9
+ displayName: "Paragraph__StyledParagraph",
10
+ componentId: "components-web__sc-1bg9r8p-0"
11
+ })(["", " ", " &:first-child{margin-block-start:0em;}&:last-child{margin-block-end:0em;}"], _ref => {
12
+ let {
13
+ align
14
+ } = _ref;
15
+ return align ? `text-align: ${align};` : '';
16
+ }, _ref2 => {
17
+ let {
18
+ linesBetween
19
+ } = _ref2;
20
+ return `
21
+ margin-block-start: ${linesBetween}em;
22
+ margin-block-end: ${linesBetween}em;
23
+ `;
24
+ });
25
+ /**
26
+ * Block text as an HTML ```<p>``` element.
27
+ *
28
+ * ##Usage criteria
29
+ *
30
+ * - All body text should be contained in a **Paragraph**, regardless of length.
31
+ * - If the Paragraph is on a dark background, variant **{ invert: true }** must be used to maintain sufficient colour
32
+ contrast.
33
+ * - All Allium Typography variants other than header size variants are supported.
34
+ */
35
+
36
+ const Paragraph = _ref3 => {
37
+ let {
38
+ children,
39
+ variant,
40
+ tokens,
41
+ testID,
42
+ align,
43
+ linesBetween = 1,
44
+ ...rest
45
+ } = _ref3;
46
+ const style = useTypographyTheme(variant, tokens);
47
+ return /*#__PURE__*/_jsx(StyledParagraph, {
48
+ linesBetween: linesBetween,
49
+ "data-testid": testID,
50
+ align: align,
51
+ style: style,
52
+ ...selectProps(rest),
53
+ children: children
54
+ });
55
+ };
56
+
57
+ Paragraph.propTypes = { ...selectedSystemPropTypes,
58
+ children: PropTypes.node.isRequired,
59
+ testID: PropTypes.string,
60
+
61
+ /**
62
+ * Sets the alignment style for the paragraph. Same options as Typography's `align` prop.
63
+ * 'justify' should be avoided as it usually reduces ease of reading.
64
+ */
65
+ align: PropTypes.oneOf(['auto', 'left', 'right', 'center', 'justify']),
66
+
67
+ /**
68
+ * How much space between consecutive paragraphs, or between a paragraph and its siblings, in CSS
69
+ * `em` units: 1 gives space equal to one line of paragraph text, 0.5 would be half a line, etc.
70
+ * @default 1
71
+ */
72
+ linesBetween: PropTypes.number,
73
+
74
+ /**
75
+ * Paragraph takes the same tokens overrides as Typography
76
+ */
77
+ tokens: PropTypes.oneOf([PropTypes.object, PropTypes.func]),
78
+
79
+ /**
80
+ * Paragraph takes any of Typography's theme variants except for header sizes
81
+ */
82
+ variant: PropTypes.exact({
83
+ bold: PropTypes.bool,
84
+ colour: PropTypes.oneOf(['secondary', 'tertiary']),
85
+ inverse: PropTypes.bool,
86
+ size: PropTypes.oneOf(['micro', 'small', 'large'])
87
+ })
88
+ };
89
+ export default Paragraph;
@@ -0,0 +1,2 @@
1
+ import Paragraph from './Paragraph';
2
+ export default Paragraph;
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { StackWrap, Typography, useThemeTokens } from '@telus-uds/components-base';
4
+ /**
5
+ * A footer for PreviewCard that composes author and date in a standard way
6
+ *
7
+ * @TODO
8
+ * Add same locale-based date formatting as StoryCard when ready.
9
+ * Get locale based on decision of https://github.com/telus/universal-design-system/issues/715
10
+ */
11
+
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { jsxs as _jsxs } from "react/jsx-runtime";
14
+
15
+ const AuthorDate = _ref => {
16
+ let {
17
+ author,
18
+ date
19
+ } = _ref;
20
+ const {
21
+ separatorColor: color
22
+ } = useThemeTokens('PreviewCard', {}, {});
23
+ return /*#__PURE__*/_jsxs(StackWrap, {
24
+ space: 2,
25
+ children: [/*#__PURE__*/_jsx(Typography, {
26
+ variant: {
27
+ size: 'small',
28
+ colour: 'secondary'
29
+ },
30
+ children: author
31
+ }), /*#__PURE__*/_jsx(Typography, {
32
+ variant: {
33
+ size: 'small'
34
+ },
35
+ tokens: {
36
+ color
37
+ },
38
+ children: "\xB7"
39
+ }), /*#__PURE__*/_jsx(Typography, {
40
+ variant: {
41
+ size: 'small',
42
+ colour: 'secondary'
43
+ },
44
+ children: date
45
+ })]
46
+ });
47
+ };
48
+
49
+ AuthorDate.propTypes = {
50
+ author: PropTypes.string.isRequired,
51
+ date: PropTypes.string.isRequired
52
+ };
53
+ export default AuthorDate;
@@ -0,0 +1,211 @@
1
+ /* eslint-disable react/require-default-props */
2
+ import React, { forwardRef } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import omit from 'lodash.omit';
5
+ import { Box, getThemeTokens, hrefAttrsProp, PressableCardBase, selectSystemProps, Spacer, StackView, Typography, a11yProps, focusHandlerProps, viewProps, withLinkRouter, useTheme } from '@telus-uds/components-base';
6
+ import styled from 'styled-components';
7
+ import FullBleedContent, { getFullBleedBorderRadius, useFullBleedContentProps } from '../shared/FullBleedContent';
8
+ import AuthorDate from './AuthorDate'; // Passes React Native-oriented system props through UDS PressableCardBase
9
+
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { Fragment as _Fragment } from "react/jsx-runtime";
12
+ import { jsxs as _jsxs } from "react/jsx-runtime";
13
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]); // Stop changes to the card's inner border width causing the size and
14
+ // apparent position of the full bleed image to change.
15
+
16
+ const FullBleedOffsetOuter = /*#__PURE__*/styled.div.withConfig({
17
+ displayName: "PreviewCard__FullBleedOffsetOuter",
18
+ componentId: "components-web__sc-1yfz4de-0"
19
+ })(_ref => {
20
+ let {
21
+ borderOffset
22
+ } = _ref;
23
+ return {
24
+ overflow: 'hidden',
25
+ marginTop: borderOffset * 2
26
+ };
27
+ });
28
+ const FullBleedOffsetInner = /*#__PURE__*/styled.div.withConfig({
29
+ displayName: "PreviewCard__FullBleedOffsetInner",
30
+ componentId: "components-web__sc-1yfz4de-1"
31
+ })(_ref2 => {
32
+ let {
33
+ borderOffset
34
+ } = _ref2;
35
+ return {
36
+ position: 'relative',
37
+ margin: 0 - borderOffset
38
+ };
39
+ });
40
+ const defaultTokens = {
41
+ minWidth: 0,
42
+ shadow: null
43
+ };
44
+ /**
45
+ * Showcase and guide users to another page, with a preview containing title and a footer.
46
+ * Whole card is interactive, width expands based on column or container.
47
+ *
48
+ * - Use `tag` to show category of content
49
+ * - Use `title` to show title of the story
50
+ * - Use `footer` to show text such as the author / date
51
+ * - Use `href` to set the target URL
52
+ * - Use `fullBleedContent` to set the thumbnail image
53
+ */
54
+
55
+ const PreviewCard = /*#__PURE__*/forwardRef((_ref3, ref) => {
56
+ let {
57
+ tag,
58
+ title,
59
+ footer,
60
+ fullBleedImage,
61
+ fullBleedContent = fullBleedImage,
62
+ onPress,
63
+ href,
64
+ ...rest
65
+ } = _ref3;
66
+ const {
67
+ fullBleedContentPosition,
68
+ contentStackDirection,
69
+ fullBleedContentProps
70
+ } = useFullBleedContentProps({ ...fullBleedContent,
71
+ position: 'bottom'
72
+ });
73
+ const {
74
+ components: {
75
+ PreviewCard: theme
76
+ }
77
+ } = useTheme();
78
+
79
+ const getPressableCardTokens = cardState => ({ ...omit(getThemeTokens(theme, {}, {}, cardState), 'separatorColor'),
80
+ ...defaultTokens
81
+ });
82
+
83
+ const {
84
+ hrefAttrs,
85
+ rest: unusedRest
86
+ } = hrefAttrsProp.bundle(rest);
87
+ return /*#__PURE__*/_jsx(PressableCardBase, {
88
+ onPress: onPress,
89
+ href: href,
90
+ hrefAttrs: hrefAttrs,
91
+ tokens: getPressableCardTokens,
92
+ ref: ref,
93
+ ...selectProps(unusedRest),
94
+ children: cardState => {
95
+ const {
96
+ borderRadius,
97
+ borderWidth
98
+ } = getPressableCardTokens(cardState); // Stop content jumping around as border size changes
99
+
100
+ const borderOffset = borderWidth - theme.tokens.borderWidth;
101
+ const fullBleedBorderRadius = getFullBleedBorderRadius(borderRadius + borderOffset, fullBleedContentPosition);
102
+ return /*#__PURE__*/_jsxs(StackView, {
103
+ direction: contentStackDirection,
104
+ tokens: {
105
+ justifyContent: 'space-between',
106
+ flexGrow: 1
107
+ },
108
+ children: [/*#__PURE__*/_jsxs(Box, {
109
+ horizontal: {
110
+ xs: 4,
111
+ lg: 5,
112
+ options: {
113
+ subtract: borderOffset
114
+ }
115
+ },
116
+ vertical: {
117
+ xs: 5,
118
+ lg: 7,
119
+ options: {
120
+ subtract: borderOffset
121
+ }
122
+ },
123
+ children: [Boolean(tag) && /*#__PURE__*/_jsxs(_Fragment, {
124
+ children: [/*#__PURE__*/_jsx(Typography, {
125
+ variant: {
126
+ size: 'eyebrow',
127
+ colour: 'secondary'
128
+ },
129
+ children: tag
130
+ }), /*#__PURE__*/_jsx(Spacer, {
131
+ space: 2
132
+ })]
133
+ }), /*#__PURE__*/_jsx(Typography, {
134
+ variant: {
135
+ size: 'h4',
136
+ colour: 'secondary'
137
+ },
138
+ children: title
139
+ }), Boolean(footer) && /*#__PURE__*/_jsxs(_Fragment, {
140
+ children: [/*#__PURE__*/_jsx(Spacer, {
141
+ space: 2
142
+ }), typeof footer === 'string' ? /*#__PURE__*/_jsx(Typography, {
143
+ variant: {
144
+ size: 'small',
145
+ colour: 'secondary'
146
+ },
147
+ children: footer
148
+ }) : footer]
149
+ })]
150
+ }), Boolean(fullBleedContentProps.src || fullBleedContentProps.content) && /*#__PURE__*/_jsx(FullBleedOffsetOuter, {
151
+ borderOffset: borderOffset,
152
+ children: /*#__PURE__*/_jsx(FullBleedOffsetInner, {
153
+ borderOffset: borderOffset,
154
+ children: /*#__PURE__*/_jsx(FullBleedContent, {
155
+ borderRadius: fullBleedBorderRadius,
156
+ ...fullBleedContentProps
157
+ })
158
+ })
159
+ })]
160
+ });
161
+ }
162
+ });
163
+ });
164
+ PreviewCard.displayName = 'PreviewCard'; // Provide standard author/date footer as a preset with the export
165
+
166
+ PreviewCard.AuthorDate = AuthorDate;
167
+ PreviewCard.propTypes = { ...selectedSystemPropTypes,
168
+
169
+ /**
170
+ * The URL of the story to be navigated to. Note that `Video` component does not play well when used within
171
+ * a `PreviewCard` with `href` prop set (the volume and progress sliders can be clicked but are not draggable).
172
+ * Please use `onPress` prop instead `href` to organize navigation in cases like this.
173
+ *
174
+ * @see https://github.com/telus/allium-design-system/issues/6
175
+ */
176
+ href: PropTypes.string,
177
+
178
+ /**
179
+ * Optional function to be called on press e.g. for within-page navigation.
180
+ */
181
+ onPress: PropTypes.func,
182
+
183
+ /**
184
+ * Text stating the category of the content.
185
+ */
186
+ tag: PropTypes.string,
187
+
188
+ /**
189
+ * Section containing additional information, such as author and date.
190
+ * Use `<PreviewCard.AuthorDate author={...} date={...} />` here for author and date.
191
+ */
192
+ footer: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
193
+
194
+ /**
195
+ * Text stating the title or headline of the story.
196
+ */
197
+ title: PropTypes.string.isRequired,
198
+
199
+ /**
200
+ * Full bleed image to be placed on the card, deprecated in favor of `fullBleedContent`.
201
+ *
202
+ * @deprecated
203
+ */
204
+ fullBleedImage: PropTypes.exact(FullBleedContent.propTypes || {}),
205
+
206
+ /**
207
+ * Full bleed content to be placed on the card.
208
+ */
209
+ fullBleedContent: PropTypes.exact(FullBleedContent.propTypes || {})
210
+ };
211
+ export default withLinkRouter(PreviewCard);
@@ -0,0 +1,2 @@
1
+ import PreviewCard from './PreviewCard';
2
+ export default PreviewCard;
@@ -0,0 +1,213 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { A11yText, Divider, selectSystemProps, Typography, useThemeTokens } from '@telus-uds/components-base';
4
+ import styled from 'styled-components';
5
+ import FootnoteLink from '../Footnote/FootnoteLink';
6
+ import typographyTokens from './tokens';
7
+ import { htmlAttrs, warn } from '../utils';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ import { Fragment as _Fragment } from "react/jsx-runtime";
10
+ import { jsxs as _jsxs } from "react/jsx-runtime";
11
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
12
+ const PriceLockupContainer = /*#__PURE__*/styled.div.withConfig({
13
+ displayName: "PriceLockup__PriceLockupContainer",
14
+ componentId: "components-web__sc-1x6duay-0"
15
+ })(["display:flex;flex-direction:column;width:fit-content;"]);
16
+ const PriceContainer = /*#__PURE__*/styled.div.withConfig({
17
+ displayName: "PriceLockup__PriceContainer",
18
+ componentId: "components-web__sc-1x6duay-1"
19
+ })(["display:flex;margin-bottom:", ";"], _ref => {
20
+ let {
21
+ priceMarginBottom
22
+ } = _ref;
23
+ return priceMarginBottom;
24
+ });
25
+ const FootnoteContainer = /*#__PURE__*/styled.div.withConfig({
26
+ displayName: "PriceLockup__FootnoteContainer",
27
+ componentId: "components-web__sc-1x6duay-2"
28
+ })(["display:flex;margin-top:", ";gap:", ";"], _ref2 => {
29
+ let {
30
+ footnoteMarginTop
31
+ } = _ref2;
32
+ return footnoteMarginTop;
33
+ }, _ref3 => {
34
+ let {
35
+ footnoteGap
36
+ } = _ref3;
37
+ return footnoteGap;
38
+ });
39
+ const BottomTextContainer = /*#__PURE__*/styled.div.withConfig({
40
+ displayName: "PriceLockup__BottomTextContainer",
41
+ componentId: "components-web__sc-1x6duay-3"
42
+ })(["margin-top:", ";"], _ref4 => {
43
+ let {
44
+ bottomTextMarginTop
45
+ } = _ref4;
46
+ return bottomTextMarginTop;
47
+ });
48
+ const BottomLinksContainer = /*#__PURE__*/styled.div.withConfig({
49
+ displayName: "PriceLockup__BottomLinksContainer",
50
+ componentId: "components-web__sc-1x6duay-4"
51
+ })(["align-self:center;margin-left:", ";"], _ref5 => {
52
+ let {
53
+ bottomLinksMarginLeft
54
+ } = _ref5;
55
+ return bottomLinksMarginLeft;
56
+ });
57
+ const TopTextContainer = /*#__PURE__*/styled.div.withConfig({
58
+ displayName: "PriceLockup__TopTextContainer",
59
+ componentId: "components-web__sc-1x6duay-5"
60
+ })(["margin-bottom:", ";"], _ref6 => {
61
+ let {
62
+ topTextMarginBottom
63
+ } = _ref6;
64
+ return topTextMarginBottom;
65
+ });
66
+ const RateTextContainer = /*#__PURE__*/styled.div.withConfig({
67
+ displayName: "PriceLockup__RateTextContainer",
68
+ componentId: "components-web__sc-1x6duay-6"
69
+ })(["align-self:flex-end;"]);
70
+ const StrikeThroughContainer = /*#__PURE__*/styled.div.withConfig({
71
+ displayName: "PriceLockup__StrikeThroughContainer",
72
+ componentId: "components-web__sc-1x6duay-7"
73
+ })(["display:flex;position:relative;align-items:center;::before{content:'';width:100%;height:", ";background:", ";position:absolute;}"], _ref7 => {
74
+ let {
75
+ strikeThroughHeight
76
+ } = _ref7;
77
+ return strikeThroughHeight;
78
+ }, _ref8 => {
79
+ let {
80
+ strikeThroughBackground
81
+ } = _ref8;
82
+ return strikeThroughBackground;
83
+ });
84
+
85
+ const PriceLockup = _ref9 => {
86
+ let {
87
+ size = 'medium',
88
+ signDirection = 'left',
89
+ footnoteLinks = [],
90
+ topText,
91
+ price,
92
+ currencySymbol = '$',
93
+ rateText,
94
+ bottomText,
95
+ onClickFootnote,
96
+ strikeThrough,
97
+ a11yText,
98
+ tokens: priceLockupTokens,
99
+ variant = {},
100
+ ...rest
101
+ } = _ref9;
102
+ const {
103
+ footnoteMarginTop,
104
+ footnoteGap,
105
+ bottomTextMarginTop,
106
+ priceMarginBottom,
107
+ bottomLinksMarginLeft,
108
+ topTextMarginBottom,
109
+ strikeThroughHeight,
110
+ strikeThroughBackground,
111
+ fontColor,
112
+ dividerColor
113
+ } = useThemeTokens('PriceLockup', priceLockupTokens, variant);
114
+ const priceString = String(price);
115
+ const lastDotPosition = priceString.lastIndexOf('.');
116
+ const lastCommaPosition = priceString.lastIndexOf(',');
117
+ const [separator, separatorPosition] = lastDotPosition > lastCommaPosition ? ['.', lastDotPosition] : [',', lastCommaPosition]; // If the separator is at the fourth character from the end of the string or more, it's most probably
118
+ // a part of the amount, and the cents are not included in the price string
119
+
120
+ const hasCents = separatorPosition !== -1 && separatorPosition >= priceString.length - 3;
121
+ const amount = hasCents ? priceString.substring(0, separatorPosition) : priceString;
122
+ const cents = hasCents ? priceString.substring(separatorPosition + 1) : null;
123
+ const color = strikeThrough ? strikeThroughBackground : fontColor;
124
+
125
+ const renderTypography = (value, tokens) => /*#__PURE__*/_jsx(Typography, {
126
+ tokens: { ...tokens,
127
+ color
128
+ },
129
+ children: value
130
+ });
131
+
132
+ const renderCurrencySymbol = () => renderTypography(`${currencySymbol}`, typographyTokens.dollarSign[size]);
133
+
134
+ const renderFootnoteLinks = () => footnoteLinks && footnoteLinks.length > 0 ? /*#__PURE__*/_jsx(FootnoteLink, {
135
+ number: footnoteLinks,
136
+ onClick: onClickFootnote
137
+ }) : null;
138
+
139
+ const renderAmount = () => {
140
+ const amountComponent = renderTypography(amount, typographyTokens.amount[size]);
141
+
142
+ if (strikeThrough) {
143
+ return /*#__PURE__*/_jsxs(_Fragment, {
144
+ children: [/*#__PURE__*/_jsx(A11yText, {
145
+ text: a11yText
146
+ }), /*#__PURE__*/_jsx(StrikeThroughContainer, {
147
+ strikeThroughHeight: `${strikeThroughHeight}px`,
148
+ strikeThroughBackground: strikeThroughBackground,
149
+ children: amountComponent
150
+ })]
151
+ });
152
+ }
153
+
154
+ return amountComponent;
155
+ };
156
+
157
+ const renderPrice = () => /*#__PURE__*/_jsxs(_Fragment, {
158
+ children: [/*#__PURE__*/_jsxs(PriceContainer, {
159
+ priceMarginBottom: `${priceMarginBottom}px`,
160
+ children: [signDirection === 'left' && renderCurrencySymbol(), renderAmount(), cents && renderTypography(`${separator}${cents}`, typographyTokens.cents[size]), signDirection === 'right' && /*#__PURE__*/_jsxs(_Fragment, {
161
+ children: ["\xA0", renderCurrencySymbol()]
162
+ }), rateText && /*#__PURE__*/_jsx(RateTextContainer, {
163
+ children: renderTypography(rateText, typographyTokens.rate[size])
164
+ }), !bottomText && footnoteLinks.length <= 3 && /*#__PURE__*/_jsx(BottomLinksContainer, {
165
+ bottomLinksMarginLeft: `${bottomLinksMarginLeft}px`,
166
+ children: renderFootnoteLinks()
167
+ })]
168
+ }), !bottomText && footnoteLinks.length > 3 && renderFootnoteLinks()]
169
+ });
170
+
171
+ const renderFootnoteContent = () => /*#__PURE__*/_jsxs(_Fragment, {
172
+ children: [/*#__PURE__*/_jsxs(FootnoteContainer, {
173
+ footnoteMarginTop: `${footnoteMarginTop}px`,
174
+ footnoteGap: `${footnoteGap}px`,
175
+ children: [/*#__PURE__*/_jsx(BottomTextContainer, {
176
+ bottomTextMarginTop: `${bottomTextMarginTop}px`,
177
+ children: renderTypography(bottomText, typographyTokens.bottomText[size])
178
+ }), footnoteLinks.length <= 3 && renderFootnoteLinks()]
179
+ }), footnoteLinks.length > 3 && renderFootnoteLinks()]
180
+ });
181
+
182
+ if (strikeThrough && !a11yText) {
183
+ warn('PriceLockup', 'a11yText must be provided with strikethrough pricing');
184
+ }
185
+
186
+ return /*#__PURE__*/_jsxs(PriceLockupContainer, { ...selectProps(rest),
187
+ children: [topText && /*#__PURE__*/_jsx(TopTextContainer, {
188
+ topTextMarginBottom: `${topTextMarginBottom}px`,
189
+ children: renderTypography(topText, typographyTokens.topText[size])
190
+ }), renderPrice(), bottomText && /*#__PURE__*/_jsx(Divider, {
191
+ testID: "price-lockup-divider",
192
+ role: "separator",
193
+ tokens: {
194
+ color: dividerColor
195
+ }
196
+ }), bottomText && renderFootnoteContent()]
197
+ });
198
+ };
199
+
200
+ PriceLockup.propTypes = { ...selectedSystemPropTypes,
201
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
202
+ currencySymbol: PropTypes.string,
203
+ topText: PropTypes.string,
204
+ price: PropTypes.string.isRequired,
205
+ rateText: PropTypes.string,
206
+ bottomText: PropTypes.string,
207
+ signDirection: PropTypes.oneOf(['right', 'left']),
208
+ footnoteLinks: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
209
+ onClickFootnote: PropTypes.func,
210
+ strikeThrough: PropTypes.bool,
211
+ a11yText: PropTypes.string
212
+ };
213
+ export default PriceLockup;
@@ -0,0 +1,2 @@
1
+ import PriceLockup from './PriceLockup';
2
+ export default PriceLockup;
@@ -0,0 +1,120 @@
1
+ import palette from '@telus-uds/palette-allium/build/rn/palette';
2
+ const {
3
+ fontSize: {
4
+ size14,
5
+ size16,
6
+ size20,
7
+ size28,
8
+ size36,
9
+ size40,
10
+ size64
11
+ },
12
+ lineHeight: {
13
+ ratio1to1,
14
+ ratio10to7,
15
+ ratio3to2,
16
+ ratio8to5,
17
+ ratio5to4,
18
+ ratio6to5,
19
+ ratio9to8,
20
+ ratio4to3,
21
+ ratio8to7
22
+ },
23
+ letterSpacing: {
24
+ condensed
25
+ }
26
+ } = palette;
27
+ const typographyTokens = {
28
+ topText: {
29
+ small: {
30
+ fontSize: size14,
31
+ lineHeight: ratio10to7
32
+ },
33
+ medium: {
34
+ fontSize: size16,
35
+ lineHeight: ratio3to2
36
+ },
37
+ large: {
38
+ fontSize: size20,
39
+ lineHeight: ratio8to5
40
+ }
41
+ },
42
+ dollarSign: {
43
+ small: {
44
+ fontSize: size16,
45
+ lineHeight: ratio5to4
46
+ },
47
+ medium: {
48
+ fontSize: size20,
49
+ lineHeight: ratio6to5
50
+ },
51
+ large: {
52
+ fontSize: size36,
53
+ lineHeight: ratio9to8
54
+ }
55
+ },
56
+ // TODO - fontWeight should have its own const on palette
57
+ amount: {
58
+ small: {
59
+ fontSize: size28,
60
+ lineHeight: ratio1to1,
61
+ letterSpacing: condensed,
62
+ fontWeight: '300'
63
+ },
64
+ medium: {
65
+ fontSize: size40,
66
+ lineHeight: ratio1to1,
67
+ letterSpacing: condensed,
68
+ fontWeight: '300'
69
+ },
70
+ large: {
71
+ fontSize: size64,
72
+ lineHeight: ratio1to1,
73
+ letterSpacing: condensed,
74
+ fontWeight: '300'
75
+ }
76
+ },
77
+ cents: {
78
+ small: {
79
+ fontSize: size16,
80
+ lineHeight: ratio4to3
81
+ },
82
+ medium: {
83
+ fontSize: size20,
84
+ lineHeight: ratio6to5
85
+ },
86
+ large: {
87
+ fontSize: size36,
88
+ lineHeight: ratio9to8
89
+ }
90
+ },
91
+ rate: {
92
+ small: {
93
+ fontSize: size14,
94
+ lineHeight: ratio8to7
95
+ },
96
+ medium: {
97
+ fontSize: size16,
98
+ lineHeight: ratio5to4
99
+ },
100
+ large: {
101
+ fontSize: size20,
102
+ lineHeight: ratio8to5
103
+ }
104
+ },
105
+ bottomText: {
106
+ small: {
107
+ fontSize: size14,
108
+ lineHeight: ratio10to7
109
+ },
110
+ medium: {
111
+ fontSize: size16,
112
+ lineHeight: ratio3to2
113
+ },
114
+ large: {
115
+ fontSize: size20,
116
+ lineHeight: ratio8to5
117
+ }
118
+ }
119
+ };
120
+ export default typographyTokens;