@purpurds/promotion-card 7.6.1 → 7.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LICENSE.txt +4 -4
- package/dist/promotion-card.cjs.js +13 -13
- package/dist/promotion-card.cjs.js.map +1 -1
- package/dist/promotion-card.d.ts +9 -7
- package/dist/promotion-card.d.ts.map +1 -1
- package/dist/promotion-card.es.js +458 -533
- package/dist/promotion-card.es.js.map +1 -1
- package/package.json +15 -14
- package/src/promotion-card.stories.tsx +6 -6
- package/src/promotion-card.tsx +119 -135
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@purpurds/promotion-card",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.8.0",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"main": "./dist/promotion-card.cjs.js",
|
|
6
6
|
"types": "./dist/promotion-card.d.ts",
|
|
@@ -17,36 +17,37 @@
|
|
|
17
17
|
"source": "src/promotion-card.tsx",
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"classnames": "~2.5.0",
|
|
20
|
-
"@purpurds/badge": "7.
|
|
21
|
-
"@purpurds/button": "7.
|
|
22
|
-
"@purpurds/
|
|
23
|
-
"@purpurds/
|
|
24
|
-
"@purpurds/
|
|
25
|
-
"@purpurds/
|
|
26
|
-
"@purpurds/icon": "7.
|
|
27
|
-
"@purpurds/
|
|
20
|
+
"@purpurds/badge": "7.8.0",
|
|
21
|
+
"@purpurds/button": "7.8.0",
|
|
22
|
+
"@purpurds/card": "7.8.0",
|
|
23
|
+
"@purpurds/heading": "7.8.0",
|
|
24
|
+
"@purpurds/paragraph": "7.8.0",
|
|
25
|
+
"@purpurds/cta-link": "7.8.0",
|
|
26
|
+
"@purpurds/icon": "7.8.0",
|
|
27
|
+
"@purpurds/common-types": "7.8.0",
|
|
28
|
+
"@purpurds/tokens": "7.8.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
|
-
"
|
|
31
|
-
"@storybook/react": "^8.6.4",
|
|
32
|
-
"storybook": "^8.6.4",
|
|
31
|
+
"@storybook/react-vite": "^9.0.18",
|
|
33
32
|
"@testing-library/dom": "~10.4.0",
|
|
34
33
|
"@testing-library/jest-dom": "~6.4.0",
|
|
35
34
|
"@testing-library/react": "~16.2.0",
|
|
36
35
|
"@types/node": "20.12.12",
|
|
37
36
|
"@types/react-dom": "^19.0.4",
|
|
38
37
|
"@types/react": "^19.0.10",
|
|
38
|
+
"eslint": "9.24.0",
|
|
39
39
|
"jsdom": "~22.1.0",
|
|
40
40
|
"lint-staged": "15.5.0",
|
|
41
41
|
"prettier": "~2.8.8",
|
|
42
42
|
"react-dom": "^19.0.0",
|
|
43
43
|
"react": "^19.0.0",
|
|
44
|
+
"storybook": "^9.0.18",
|
|
44
45
|
"typescript": "^5.6.3",
|
|
45
46
|
"vite": "^6.2.1",
|
|
46
47
|
"vitest": "^3.1.2",
|
|
47
48
|
"@purpurds/component-rig": "1.0.0",
|
|
48
|
-
"@purpurds/grid": "7.
|
|
49
|
-
"@purpurds/text-spacing": "7.
|
|
49
|
+
"@purpurds/grid": "7.8.0",
|
|
50
|
+
"@purpurds/text-spacing": "7.8.0"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
53
|
"@types/react": "^18 || ^19",
|
|
@@ -6,7 +6,7 @@ import { HeadingTag, TitleVariant } from "@purpurds/heading";
|
|
|
6
6
|
import { IconCheckmark } from "@purpurds/icon/checkmark";
|
|
7
7
|
import { IconOffering } from "@purpurds/icon/offering";
|
|
8
8
|
import { Paragraph } from "@purpurds/paragraph";
|
|
9
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
9
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
10
10
|
|
|
11
11
|
import "@purpurds/badge/styles";
|
|
12
12
|
import "@purpurds/button/styles";
|
|
@@ -126,7 +126,7 @@ export const WithDecorativeImage: Story = {
|
|
|
126
126
|
decorativeImage: (
|
|
127
127
|
<img
|
|
128
128
|
src="https://www.telia.se/images/i15skfqwpurk/5YYelnwdIJGush05RYsE6A/04d4eeb571bca6d5c72b557f6da92c92/Telia_Company_Reinvention_69.jpg?fit=scale&w=536&fm=jpg&q=70"
|
|
129
|
-
alt="
|
|
129
|
+
alt="The family's young ones are watching TV together in a cozy but exciting atmosphere"
|
|
130
130
|
/>
|
|
131
131
|
),
|
|
132
132
|
},
|
|
@@ -150,11 +150,11 @@ export const WithProductImage: Story = {
|
|
|
150
150
|
>
|
|
151
151
|
<source
|
|
152
152
|
type="image/webp"
|
|
153
|
-
srcSet="https://www.telia.se/images/j6b4qnxw7ufu/
|
|
153
|
+
srcSet="https://www.telia.se/images/j6b4qnxw7ufu/5SQlvYckTDsTPdrdxzUbHD/1d6ca31184938d248d4db82f2c126cd4/115282__160_14ab6ec8-98f7-4a84-a630-6c89cc9b9859?fit=scale&w=500&fm=webp&q=99"
|
|
154
154
|
/>
|
|
155
155
|
<img
|
|
156
|
-
src="https://www.telia.se/images/j6b4qnxw7ufu/
|
|
157
|
-
alt="
|
|
156
|
+
src="https://www.telia.se/images/j6b4qnxw7ufu/5SQlvYckTDsTPdrdxzUbHD/1d6ca31184938d248d4db82f2c126cd4/115282__160_14ab6ec8-98f7-4a84-a630-6c89cc9b9859?fit=scale&w=500&fm=png&q=99"
|
|
157
|
+
alt="Iphone 16"
|
|
158
158
|
/>
|
|
159
159
|
</picture>
|
|
160
160
|
),
|
|
@@ -175,7 +175,7 @@ export const CardGroup: Story = {
|
|
|
175
175
|
decorativeImage: (
|
|
176
176
|
<img
|
|
177
177
|
src="https://www.telia.se/images/i15skfqwpurk/5YYelnwdIJGush05RYsE6A/04d4eeb571bca6d5c72b557f6da92c92/Telia_Company_Reinvention_69.jpg?fit=scale&w=536&fm=jpg&q=70"
|
|
178
|
-
alt="
|
|
178
|
+
alt="The family's young ones are watching TV together in a cozy but exciting atmosphere"
|
|
179
179
|
/>
|
|
180
180
|
),
|
|
181
181
|
},
|
package/src/promotion-card.tsx
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
type DetailedHTMLProps,
|
|
3
|
-
type ForwardedRef,
|
|
4
|
-
forwardRef,
|
|
5
|
-
type HTMLAttributes,
|
|
6
|
-
type ReactNode,
|
|
7
|
-
} from "react";
|
|
1
|
+
import React, { forwardRef, type ReactNode } from "react";
|
|
8
2
|
import { Badge } from "@purpurds/badge";
|
|
9
3
|
import { Card } from "@purpurds/card";
|
|
4
|
+
import type { BaseProps } from "@purpurds/common-types";
|
|
10
5
|
import { Heading, type HeadingTagType, type TitleVariantType } from "@purpurds/heading";
|
|
11
6
|
import { Paragraph } from "@purpurds/paragraph";
|
|
12
7
|
import c from "classnames/bind";
|
|
@@ -40,8 +35,7 @@ const colors: StyleRecord = {
|
|
|
40
35
|
type DecorativeImage = { decorativeImage?: ReactNode; hasGradient?: boolean };
|
|
41
36
|
type ProductImage = { productImage?: ReactNode; hasGradient?: never };
|
|
42
37
|
|
|
43
|
-
export type PromotionCardProps = {
|
|
44
|
-
["data-testid"]?: string;
|
|
38
|
+
export type PromotionCardProps = Omit<BaseProps, "children"> & {
|
|
45
39
|
variant?: PromotionCardVariant;
|
|
46
40
|
title: string;
|
|
47
41
|
titleTag?: HeadingTagType;
|
|
@@ -58,142 +52,132 @@ export type PromotionCardProps = {
|
|
|
58
52
|
const cx = c.bind(styles);
|
|
59
53
|
const rootClassName = "purpur-promotion-card";
|
|
60
54
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
className,
|
|
117
|
-
rootClassName,
|
|
118
|
-
`${rootClassName}--${variant}`,
|
|
119
|
-
{
|
|
55
|
+
export const PromotionCard = forwardRef<HTMLDivElement, PromotionCardProps>(
|
|
56
|
+
(
|
|
57
|
+
{
|
|
58
|
+
["data-testid"]: dataTestid,
|
|
59
|
+
variant = "primary",
|
|
60
|
+
badgeText,
|
|
61
|
+
badgeIcon,
|
|
62
|
+
title,
|
|
63
|
+
titleTag = "h2",
|
|
64
|
+
titleVariant = "title-300",
|
|
65
|
+
enableTitleHyphenation = false,
|
|
66
|
+
className,
|
|
67
|
+
actions,
|
|
68
|
+
children,
|
|
69
|
+
style,
|
|
70
|
+
alignment = "space-between",
|
|
71
|
+
additionalText,
|
|
72
|
+
...props
|
|
73
|
+
},
|
|
74
|
+
ref
|
|
75
|
+
) => {
|
|
76
|
+
let rest = props;
|
|
77
|
+
let image;
|
|
78
|
+
let showGradient;
|
|
79
|
+
|
|
80
|
+
if ("decorativeImage" in props) {
|
|
81
|
+
const { hasGradient, decorativeImage, ...spread } = props;
|
|
82
|
+
image = decorativeImage;
|
|
83
|
+
showGradient = hasGradient;
|
|
84
|
+
rest = spread;
|
|
85
|
+
} else if ("productImage" in props) {
|
|
86
|
+
const { hasGradient, productImage, ...spread } = props;
|
|
87
|
+
image = productImage;
|
|
88
|
+
showGradient = hasGradient;
|
|
89
|
+
rest = spread;
|
|
90
|
+
} else if ("hasGradient" in props) {
|
|
91
|
+
const { hasGradient, ...spread } = props;
|
|
92
|
+
showGradient = hasGradient;
|
|
93
|
+
rest = spread;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const customProperties = {
|
|
97
|
+
"--promotion-card-background": backgrounds[variant],
|
|
98
|
+
"--promotion-card-color": colors[variant],
|
|
99
|
+
"--promotion-card-background-image": backgroundImages[variant],
|
|
100
|
+
} as React.CSSProperties;
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Card ref={ref} className={cx(`${rootClassName}__card`)} fullHeight>
|
|
104
|
+
<div
|
|
105
|
+
data-testid={dataTestid}
|
|
106
|
+
style={{
|
|
107
|
+
...customProperties,
|
|
108
|
+
...style,
|
|
109
|
+
}}
|
|
110
|
+
className={cx(className, rootClassName, `${rootClassName}--${variant}`, {
|
|
120
111
|
[`${rootClassName}--with-image`]: image,
|
|
121
112
|
[`${rootClassName}--without-image`]: !image,
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
{...rest}
|
|
125
|
-
>
|
|
126
|
-
<div
|
|
127
|
-
className={cx([
|
|
128
|
-
`${rootClassName}__content`,
|
|
129
|
-
{
|
|
130
|
-
[`${rootClassName}__content--with-image`]: image,
|
|
131
|
-
[`${rootClassName}__content--without-image`]: !image,
|
|
132
|
-
},
|
|
133
|
-
])}
|
|
113
|
+
})}
|
|
114
|
+
{...rest}
|
|
134
115
|
>
|
|
135
|
-
{badgeText && (
|
|
136
|
-
<div data-testid="badgeWrapper" className={cx(`${rootClassName}__badge-wrapper`)}>
|
|
137
|
-
<Badge variant={variant === "primary" ? "special" : "attention"} showIcon={false}>
|
|
138
|
-
{badgeIcon && badgeIcon}
|
|
139
|
-
{badgeText}
|
|
140
|
-
</Badge>
|
|
141
|
-
</div>
|
|
142
|
-
)}
|
|
143
|
-
|
|
144
116
|
<div
|
|
145
|
-
className={cx(
|
|
146
|
-
`${rootClassName}
|
|
147
|
-
`${rootClassName}
|
|
148
|
-
)}
|
|
117
|
+
className={cx(`${rootClassName}__content`, {
|
|
118
|
+
[`${rootClassName}__content--with-image`]: image,
|
|
119
|
+
[`${rootClassName}__content--without-image`]: !image,
|
|
120
|
+
})}
|
|
149
121
|
>
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
negative
|
|
164
|
-
variant="additional-100"
|
|
165
|
-
className={cx(`${rootClassName}__additional-text`)}
|
|
166
|
-
>
|
|
167
|
-
{additionalText}
|
|
168
|
-
</Paragraph>
|
|
122
|
+
{badgeText && (
|
|
123
|
+
<div data-testid="badgeWrapper" className={cx(`${rootClassName}__badge-wrapper`)}>
|
|
124
|
+
<Badge variant={variant === "primary" ? "special" : "attention"} showIcon={false}>
|
|
125
|
+
{badgeIcon && badgeIcon}
|
|
126
|
+
{badgeText}
|
|
127
|
+
</Badge>
|
|
128
|
+
</div>
|
|
129
|
+
)}
|
|
130
|
+
|
|
131
|
+
<div
|
|
132
|
+
className={cx(
|
|
133
|
+
`${rootClassName}__main-content`,
|
|
134
|
+
`${rootClassName}__main-content--${alignment}`
|
|
169
135
|
)}
|
|
136
|
+
>
|
|
137
|
+
<Heading
|
|
138
|
+
tag={titleTag}
|
|
139
|
+
variant={titleVariant}
|
|
140
|
+
enableHyphenation={enableTitleHyphenation}
|
|
141
|
+
className={cx(`${rootClassName}__heading`)}
|
|
142
|
+
>
|
|
143
|
+
{title}
|
|
144
|
+
</Heading>
|
|
145
|
+
<div className={cx(`${rootClassName}__body`)}>
|
|
146
|
+
<div className={cx(`${rootClassName}__child-content`)}>{children}</div>
|
|
147
|
+
{actions && <div className={cx(`${rootClassName}__actions`)}>{actions}</div>}
|
|
148
|
+
{additionalText && (
|
|
149
|
+
<Paragraph
|
|
150
|
+
negative
|
|
151
|
+
variant="additional-100"
|
|
152
|
+
className={cx(`${rootClassName}__additional-text`)}
|
|
153
|
+
>
|
|
154
|
+
{additionalText}
|
|
155
|
+
</Paragraph>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
170
158
|
</div>
|
|
171
159
|
</div>
|
|
172
|
-
</div>
|
|
173
160
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
`${rootClassName}__image-wrapper`,
|
|
178
|
-
{
|
|
161
|
+
{image && (
|
|
162
|
+
<div
|
|
163
|
+
className={cx(`${rootClassName}__image-wrapper`, {
|
|
179
164
|
[`${rootClassName}__image-wrapper--product`]: "productImage" in props,
|
|
180
165
|
[`${rootClassName}__image-wrapper--decorative`]: "decorativeImage" in props,
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
</
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
166
|
+
})}
|
|
167
|
+
>
|
|
168
|
+
{image}
|
|
169
|
+
{showGradient && (
|
|
170
|
+
<div
|
|
171
|
+
className={cx(`${rootClassName}__image-gradient`)}
|
|
172
|
+
data-testid="promotion-card-gradient"
|
|
173
|
+
/>
|
|
174
|
+
)}
|
|
175
|
+
</div>
|
|
176
|
+
)}
|
|
177
|
+
</div>
|
|
178
|
+
</Card>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
);
|
|
197
182
|
|
|
198
|
-
export const PromotionCard = forwardRef(PromotionCardComponent);
|
|
199
183
|
PromotionCard.displayName = "PromotionCard";
|