@asantemedia-org/atlas-copco-vt-storybook 1.0.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 (59) hide show
  1. package/.eslintrc.json +3 -0
  2. package/.nvmrc +1 -0
  3. package/.prettierignore +2 -0
  4. package/.prettierrc +8 -0
  5. package/.storybook/AtlasCopcoTheme.ts +14 -0
  6. package/.storybook/global.scss +15 -0
  7. package/.storybook/main.ts +125 -0
  8. package/.storybook/manager.ts +6 -0
  9. package/.storybook/preview-head.html +4 -0
  10. package/.storybook/preview.tsx +73 -0
  11. package/.storybook/types.d.ts +5 -0
  12. package/.vscode/settings.json +4 -0
  13. package/README.md +59 -0
  14. package/next.config.js +8 -0
  15. package/package.json +76 -0
  16. package/postcss.config.js +6 -0
  17. package/public/.gitkeep +0 -0
  18. package/public/assets/.gitkeep +0 -0
  19. package/public/fonts/.gitkeep +0 -0
  20. package/src/app/globals.css +13 -0
  21. package/src/app/layout.tsx +18 -0
  22. package/src/app/page.tsx +11 -0
  23. package/src/components/Button/Button.module.scss +77 -0
  24. package/src/components/Button/Button.stories.tsx +97 -0
  25. package/src/components/Button/Button.tsx +47 -0
  26. package/src/components/Button/index.ts +2 -0
  27. package/src/components/Image/Image.module.scss +75 -0
  28. package/src/components/Image/Image.tsx +114 -0
  29. package/src/components/Image/Image.types.ts +34 -0
  30. package/src/components/Image/index.ts +2 -0
  31. package/src/components/ProductCardDetails/ProductCardDetails.module.scss +129 -0
  32. package/src/components/ProductCardDetails/ProductCardDetails.stories.tsx +138 -0
  33. package/src/components/ProductCardDetails/ProductCardDetails.tsx +61 -0
  34. package/src/components/ProductCardDetails/index.ts +2 -0
  35. package/src/components/ProductCardHorizontal/ProductCardHorizontal.module.scss +93 -0
  36. package/src/components/ProductCardHorizontal/ProductCardHorizontal.stories.tsx +72 -0
  37. package/src/components/ProductCardHorizontal/ProductCardHorizontal.tsx +50 -0
  38. package/src/components/ProductCardHorizontal/index.ts +2 -0
  39. package/src/experience/algolia-dynamic-search/AlgoliaDynamicSearch.scss +135 -0
  40. package/src/experience/algolia-dynamic-search/AlgoliaDynamicSearch.stories.tsx +109 -0
  41. package/src/experience/algolia-dynamic-search/AlgoliaDynamicSearch.tsx +67 -0
  42. package/src/experience/algolia-dynamic-search/index.ts +2 -0
  43. package/src/experience/qr-form-journey/QrFormJourney.scss +37 -0
  44. package/src/experience/qr-form-journey/QrFormJourney.stories.tsx +134 -0
  45. package/src/experience/qr-form-journey/QrFormJourney.tsx +69 -0
  46. package/src/experience/qr-form-journey/index.ts +2 -0
  47. package/src/index.ts +19 -0
  48. package/src/stories/foundation/_components/StoryLayout.tsx +67 -0
  49. package/src/stories/introduction/Welcome.mdx +36 -0
  50. package/src/types/buttons.ts +4 -0
  51. package/src/types/cards.ts +37 -0
  52. package/src/utils/data/algolia-dynamic-widget-product-data.json +46 -0
  53. package/src/utils/styles/base.scss +100 -0
  54. package/src/utils/styles/global.scss +29 -0
  55. package/src/utils/styles/index.ts +1 -0
  56. package/src/utils/styles/typography.scss +60 -0
  57. package/tailwind.config.js +19 -0
  58. package/tsconfig.json +41 -0
  59. package/types/@asantemedia-org__edwardsvacuum-design-system.d.ts +8 -0
@@ -0,0 +1,72 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { ProductCardHorizontal, ProductCardHorizontalParts } from "./ProductCardHorizontal";
3
+
4
+ const meta: Meta<typeof ProductCardHorizontal> = {
5
+ title: "Components/Cards/ProductCardHorizontal",
6
+ component: ProductCardHorizontal,
7
+ tags: ["autodocs"],
8
+ parameters: {
9
+ layout: "padded",
10
+ },
11
+ };
12
+
13
+ export default meta;
14
+ type Story = StoryObj<typeof ProductCardHorizontal>;
15
+
16
+ export const Default: Story = {
17
+ args: {
18
+ id: "1",
19
+ title: "GA 30+ - Oil-injected rotary screw compressor",
20
+ url: "#",
21
+ imageUrl: "https://via.placeholder.com/150",
22
+ price: "GBP 5,600.00",
23
+ description: "Reliable industrial compressor for demanding applications",
24
+ },
25
+ };
26
+
27
+ export const WithoutImage: Story = {
28
+ args: {
29
+ id: "2",
30
+ title: "GX 11 - Oil-free scroll compressor",
31
+ url: "#",
32
+ price: "GBP 3,250.00",
33
+ },
34
+ };
35
+
36
+ export const WithoutPrice: Story = {
37
+ args: {
38
+ id: "3",
39
+ title: "Vacuum Pump - Industrial Grade",
40
+ url: "#",
41
+ imageUrl: "https://via.placeholder.com/150",
42
+ description: "High-performance vacuum pump for industrial use",
43
+ },
44
+ };
45
+
46
+ export const WithButton: Story = {
47
+ args: {
48
+ id: "4",
49
+ title: "GA 30+ - Oil-injected rotary screw compressor",
50
+ url: "#",
51
+ imageUrl: "https://via.placeholder.com/150",
52
+ price: "GBP 5,600.00",
53
+ description: "Reliable industrial compressor",
54
+ button: { label: "View Product", onClick: () => window.open("#", "_blank") },
55
+ },
56
+ };
57
+
58
+ export const ProductCardHorizontalPartsDefault: StoryObj<typeof ProductCardHorizontalParts> = {
59
+ render: (args) => (
60
+ <div style={{ width: "300px" }}>
61
+ <ProductCardHorizontalParts {...args} />
62
+ </div>
63
+ ),
64
+ args: {
65
+ url: "#",
66
+ title: "GA 30+ - Oil-injected rotary screw compressor",
67
+ description: "A50873130",
68
+ price: "GBP 5,600.00",
69
+ button: { label: "Buy Now", onClick: () => window.open("#", "_blank") },
70
+ imageUrl: "https://via.placeholder.com/150",
71
+ },
72
+ };
@@ -0,0 +1,50 @@
1
+ import React from "react";
2
+ import { ProductCardHorizontalProps } from "../../types/cards";
3
+ import styles from "./ProductCardHorizontal.module.scss";
4
+ import { Button } from "../Button";
5
+ import { Image } from "../Image";
6
+
7
+ export const ProductCardHorizontal: React.FC<ProductCardHorizontalProps> = ({
8
+ id,
9
+ imageUrl,
10
+ url,
11
+ title,
12
+ description,
13
+ price,
14
+ button,
15
+ className = "",
16
+ }) => {
17
+ if (!title) {
18
+ return null;
19
+ }
20
+
21
+ return (
22
+ <a
23
+ href={url}
24
+ className={`${styles.productCard} ${className}`}
25
+ aria-label={`View product: ${title}`}
26
+ >
27
+ <div className={`${styles.productWrapper} ${imageUrl ? styles.withImage : ""}`}>
28
+ {imageUrl && (
29
+ <div className={styles.productImage}>
30
+ <Image src={imageUrl} alt={title} />
31
+ </div>
32
+ )}
33
+ <div className={styles.productTitleDescriptionWrapper}>
34
+ <h3 className={styles.productTitle}>{title}</h3>
35
+ {description && <p className={styles.productDescription}>{description}</p>}
36
+ </div>
37
+ <div className={styles.productPriceCtaWrapper}>
38
+ <p className={styles.productPrice}>{price || " "}</p>
39
+ {button && (
40
+ <Button className={styles.productButton} onClick={button.onClick} size="small">
41
+ {button.label}
42
+ </Button>
43
+ )}
44
+ </div>
45
+ </div>
46
+ </a>
47
+ );
48
+ };
49
+
50
+ export const ProductCardHorizontalParts = ProductCardHorizontal;
@@ -0,0 +1,2 @@
1
+ export { ProductCardHorizontal, ProductCardHorizontalParts } from "./ProductCardHorizontal";
2
+ export type { ProductCardHorizontalProps } from "../../types/cards";
@@ -0,0 +1,135 @@
1
+ @use "../../utils/styles/base.scss" as *;
2
+
3
+ :global {
4
+ @keyframes loading {
5
+ 0% {
6
+ transform: skewX(-10deg) translateX(-100%);
7
+ }
8
+ 100% {
9
+ transform: skewX(-10deg) translateX(200%);
10
+ }
11
+ }
12
+ }
13
+
14
+ .cmpAlgoliaDynamicSearchWidget {
15
+ position: relative;
16
+ padding: 2rem 1rem;
17
+ @media (min-width: 768px) {
18
+ padding: 4rem 1rem;
19
+ }
20
+
21
+ &.isLoading {
22
+ .cmpAlgoliaDynamicSearchWidget__placeholder {
23
+ opacity: 1;
24
+ z-index: 1;
25
+ }
26
+ .cmpAlgoliaDynamicSearchWidget__container {
27
+ opacity: 0;
28
+ z-index: -1;
29
+ }
30
+ }
31
+
32
+ &__container {
33
+ margin-left: auto;
34
+ margin-right: auto;
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: 3rem;
38
+ z-index: 1;
39
+ transition: opacity 0.5s;
40
+ @media (min-width: 961px) {
41
+ max-width: 1280px;
42
+ }
43
+ }
44
+
45
+ &__header {
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: 1.5rem;
49
+ @media screen and (min-width: 768px) {
50
+ flex-direction: row;
51
+ justify-content: space-between;
52
+ align-items: flex-start;
53
+ }
54
+ h1,
55
+ h2,
56
+ h3,
57
+ h4,
58
+ h5,
59
+ h6,
60
+ p {
61
+ margin: 0;
62
+ color: $secondary-color;
63
+ }
64
+ &__text {
65
+ display: flex;
66
+ flex-direction: column;
67
+ gap: 1rem;
68
+ @media screen and (min-width: 768px) {
69
+ max-width: 75%;
70
+ }
71
+ }
72
+ }
73
+
74
+ &__cards {
75
+ display: grid;
76
+ gap: 1rem;
77
+ grid-template-columns: 1fr;
78
+ @media (min-width: 768px) {
79
+ grid-template-columns: repeat(2, 1fr);
80
+ }
81
+ @media (min-width: 961px) {
82
+ grid-template-columns: repeat(3, 1fr);
83
+ }
84
+ }
85
+
86
+ &.isQueryContent .cmpAlgoliaDynamicSearchWidget__cards {
87
+ grid-template-columns: repeat(2, 1fr);
88
+ @media (min-width: 961px) {
89
+ grid-template-columns: repeat(4, 1fr);
90
+ }
91
+ }
92
+
93
+ &.hasStyleSilverGradientBackground {
94
+ background: $bg-secondary;
95
+ }
96
+
97
+ &.hasStyleGreyBackground {
98
+ background: $secondary-color;
99
+ .cmpAlgoliaDynamicSearchWidget__header__text {
100
+ color: white;
101
+ h1,
102
+ h2,
103
+ h3,
104
+ h4,
105
+ h5,
106
+ h6,
107
+ p {
108
+ color: white;
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ .cmpAlgoliaDynamicSearchWidget__placeholder {
115
+ opacity: 0;
116
+ position: absolute;
117
+ top: 0;
118
+ left: 0;
119
+ width: 100%;
120
+ height: 100%;
121
+ min-height: 500px;
122
+ z-index: -1;
123
+ background-color: $secondary-color;
124
+ transition: opacity 0.5s;
125
+ &__loading::before {
126
+ content: "";
127
+ position: absolute;
128
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.9), transparent);
129
+ width: 50%;
130
+ height: 100%;
131
+ top: 0;
132
+ left: 0;
133
+ animation: loading 1s infinite;
134
+ }
135
+ }
@@ -0,0 +1,109 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import AlgoliaDynamicSearchVT from "./AlgoliaDynamicSearch";
3
+ import productData from "../../utils/data/algolia-dynamic-widget-product-data.json";
4
+
5
+ const VT_DOMAIN = "https://www.atlascopco.com";
6
+
7
+ const generatePath = (src: string) => `${VT_DOMAIN}${src}`;
8
+
9
+ const cleanProductData = productData.hits.map((product: any) => {
10
+ const title = product.name
11
+ ? product.name.split(",").shift()?.trim() || "Product Title"
12
+ : "Product Title";
13
+ const code = product.code ? product.code : product.name?.split(",").pop()?.trim() || "";
14
+ const link = product.url ? generatePath(product.url) : "#";
15
+ const price = product.priceValue ? String(product.priceValue) : "£0.00";
16
+ const image = product["img-product"] ? generatePath(product["img-product"]) : "";
17
+ const spares = product.related_products ? product.related_products : [];
18
+ return {
19
+ image,
20
+ title,
21
+ code,
22
+ link,
23
+ price,
24
+ imageAlt: title,
25
+ spares,
26
+ ...product,
27
+ };
28
+ });
29
+
30
+ const meta: Meta<typeof AlgoliaDynamicSearchVT> = {
31
+ title: "Experience/AlgoliaDynamicSearch",
32
+ component: AlgoliaDynamicSearchVT,
33
+ argTypes: {
34
+ className: { table: { disable: true } },
35
+ backgroundColour: {
36
+ options: ["dark-grey", "silver", "white"],
37
+ control: { type: "select" },
38
+ },
39
+ queryType: {
40
+ options: ["products", "content", "careers"],
41
+ control: { type: "select" },
42
+ },
43
+ titleSize: {
44
+ options: ["h2", "h3", "h4", "h5", "h6"],
45
+ control: { type: "select" },
46
+ },
47
+ callToActionText: { control: { type: "text" }, table: { category: "Call To Action" } },
48
+ callToActionType: {
49
+ options: ["External", "Internal", "Email", "Phone"],
50
+ control: { type: "radio" },
51
+ table: { category: "Call To Action" },
52
+ },
53
+ callToActionTargetSelector: {
54
+ control: { type: "text" },
55
+ table: { category: "Call To Action" },
56
+ },
57
+ callToActionUrl: { control: { type: "text" }, table: { category: "Call To Action" } },
58
+ maxResults: { control: { type: "range", min: 3, max: 6, step: 1 } },
59
+ },
60
+ };
61
+
62
+ export default meta;
63
+ type Story = StoryObj<typeof AlgoliaDynamicSearchVT>;
64
+
65
+ export const Products: Story = {
66
+ args: {
67
+ className: "cmp-algolia-dynamic-search-widget",
68
+ heading: "Products from the webstore",
69
+ titleSize: "h2",
70
+ subtext:
71
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
72
+ callToActionText: "Search",
73
+ callToActionUrl: "https://www.atlascopco.com",
74
+ queryType: "products",
75
+ hits: cleanProductData,
76
+ hitCta: "View Product",
77
+ query: "compressor",
78
+ showProductPrice: false,
79
+ backgroundColour: "dark-grey",
80
+ maxResults: 6,
81
+ isLoading: false,
82
+ },
83
+ };
84
+
85
+ export const ProductDetails: Story = {
86
+ render: (args) => (
87
+ <div style={{ maxWidth: "1200px", margin: "0 auto", backgroundColor: "#F6F7F9" }}>
88
+ <AlgoliaDynamicSearchVT {...args} />
89
+ </div>
90
+ ),
91
+ name: "Single Product",
92
+ args: {
93
+ className: "cmp-algolia-dynamic-search-widget",
94
+ queryType: "productDetails",
95
+ hits: cleanProductData,
96
+ hitCta: "View Product",
97
+ query: cleanProductData[0]?.code || "A50873130",
98
+ showProductPrice: true,
99
+ backgroundColour: "white",
100
+ maxResults: 1,
101
+ isLoading: false,
102
+ facets: [
103
+ { name: "powerTotalRated", label: "Power Total Rated" },
104
+ { name: "connectionVacuumInletFlange", label: "Connection Vacuum Inlet Flange" },
105
+ { name: "pumpingSpeedAirNitrogen", label: "Pumping Speed Air Nitrogen" },
106
+ { name: "pressureUltimate", label: "Pressure Ultimate" },
107
+ ],
108
+ },
109
+ };
@@ -0,0 +1,67 @@
1
+ import React from "react";
2
+ import { AlgoliaDynamicSearchRaw } from "@asantemedia-org/edwardsvacuum-design-system";
3
+ import { ProductCardHorizontalParts } from "../../components/ProductCardHorizontal/ProductCardHorizontal";
4
+ import { ProductCardDetails } from "../../components/ProductCardDetails/ProductCardDetails";
5
+ import "./AlgoliaDynamicSearch.scss";
6
+
7
+ const ProductCardAdapter = (props: any) => {
8
+ const { hit, title, cardLink, productPrice, cta, showProductPrice, className, code } = props;
9
+ const url = cardLink || hit?.link || "#";
10
+ const price = showProductPrice ? productPrice || hit?.price || "" : "";
11
+ const productTitle = title || hit?.title || "";
12
+ const productCode = code || hit?.code || "";
13
+ const buttonLabel = cta || "View Product";
14
+
15
+ return (
16
+ <ProductCardHorizontalParts
17
+ imageUrl=""
18
+ url={url}
19
+ title={productTitle}
20
+ description={productCode}
21
+ price={price}
22
+ button={{ label: buttonLabel, onClick: () => window.open(url, "_blank") }}
23
+ className={className}
24
+ />
25
+ );
26
+ };
27
+
28
+ const ProductCardDetailsAdapter = (props: any) => {
29
+ const {
30
+ hit,
31
+ title,
32
+ cardLink,
33
+ productPrice,
34
+ cta,
35
+ showProductPrice,
36
+ className,
37
+ code,
38
+ facets,
39
+ related_products,
40
+ } = props;
41
+ if (!title) {
42
+ return null;
43
+ }
44
+ return (
45
+ <ProductCardDetails
46
+ imageUrl={hit?.image || ""}
47
+ title={title}
48
+ description={hit?.description || ""}
49
+ price={hit?.price || productPrice || ""}
50
+ code={hit?.code || code || ""}
51
+ hit={hit}
52
+ className={className}
53
+ facets={facets}
54
+ relatedProducts={hit?.related_products || related_products}
55
+ />
56
+ );
57
+ };
58
+
59
+ export const AlgoliaDynamicSearchVT = (props: any) => {
60
+ const innerComponents = {
61
+ ProductCard: ProductCardAdapter,
62
+ ProductDetailsCard: ProductCardDetailsAdapter,
63
+ };
64
+ return <AlgoliaDynamicSearchRaw {...props} innerComponents={innerComponents} />;
65
+ };
66
+
67
+ export default AlgoliaDynamicSearchVT;
@@ -0,0 +1,2 @@
1
+ export { AlgoliaDynamicSearchVT } from "./AlgoliaDynamicSearch";
2
+ export { default } from "./AlgoliaDynamicSearch";
@@ -0,0 +1,37 @@
1
+ @use "../../utils/styles/base.scss" as *;
2
+
3
+ .qr-journey-form-wrapper {
4
+ * {
5
+ font-family: $font-family-base;
6
+ font-size: $font-size-base;
7
+ }
8
+
9
+ ::placeholder {
10
+ font-style: normal;
11
+ }
12
+
13
+ h1 {
14
+ font-size: 28px;
15
+ font-weight: 400;
16
+ color: $text-secondary;
17
+ margin-bottom: 2em;
18
+ position: relative;
19
+ &::after {
20
+ content: "";
21
+ display: block;
22
+ position: relative;
23
+ top: 0.8em;
24
+ width: 100%;
25
+ height: 2px;
26
+ background-color: $border-color;
27
+ }
28
+ }
29
+
30
+ h2 {
31
+ font-size: 21px;
32
+ font-weight: 700;
33
+ line-height: 1.6em;
34
+ color: $primary-color;
35
+ margin: $spacing-md 0 0 0;
36
+ }
37
+ }
@@ -0,0 +1,134 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import React from "react";
3
+ import { QrFormVT } from "./QrFormJourney";
4
+
5
+ const meta: Meta<typeof QrFormVT> = {
6
+ title: "Experience/QrFormJourney",
7
+ component: QrFormVT,
8
+ parameters: {
9
+ layout: "padded",
10
+ },
11
+ };
12
+
13
+ const defaultArgs = {
14
+ formHeader: "Contact Atlas Copco VT support for technical guidance",
15
+ next: "Next",
16
+ previous: "Previous",
17
+ submit: "Submit",
18
+ required: "This field is mandatory",
19
+ consents: [
20
+ {
21
+ policyMandatory: true,
22
+ policyText: "I have read and agree to the Privacy Policy.",
23
+ policyLink: "https://www.atlascopco.com/privacy-policy",
24
+ },
25
+ {
26
+ policyMandatory: false,
27
+ policyText: "I agree to receive marketing communications.",
28
+ policyLink: "https://www.atlascopco.com/marketing-opt-in",
29
+ },
30
+ {
31
+ policyMandatory: true,
32
+ policyText: "I confirm that I have read the Terms & Conditions.",
33
+ policyLink: "https://www.atlascopco.com/terms",
34
+ },
35
+ ],
36
+ fields: [
37
+ {
38
+ name: "serial-number",
39
+ label: "Serial Number",
40
+ value: "SerialNumber",
41
+ type: "text",
42
+ errorMessage: "",
43
+ isDisabled: true,
44
+ },
45
+ {
46
+ name: "product-number",
47
+ label: "Product Number",
48
+ value: "productNumber",
49
+ type: "text",
50
+ errorMessage: "",
51
+ isDisabled: true,
52
+ },
53
+ {
54
+ name: "product-hierarchy",
55
+ label: "Product Hierarchy",
56
+ value: "",
57
+ type: "text",
58
+ errorMessage: "",
59
+ isDisabled: true,
60
+ },
61
+ {
62
+ name: "software-version",
63
+ label: "Software Version",
64
+ value: "softwareVersion",
65
+ type: "text",
66
+ errorMessage: "",
67
+ isDisabled: true,
68
+ },
69
+ ],
70
+ showThankYou: false,
71
+ buttonText: "Submit",
72
+ linkType: "INTERNAL" as const,
73
+ url: "#",
74
+ newTab: false,
75
+ captchaKey: "FCMV995O03V7RIMQ",
76
+ };
77
+
78
+ export default meta;
79
+ type Story = StoryObj<typeof QrFormVT>;
80
+
81
+ function QrFormWithState(props: React.ComponentProps<typeof QrFormVT>) {
82
+ const [showThankYou, setShowThankYou] = React.useState(false);
83
+ return (
84
+ <QrFormVT {...props} showThankYou={showThankYou} onSubmit={() => setShowThankYou(true)} />
85
+ );
86
+ }
87
+
88
+ export const Default: Story = {
89
+ name: "QR Form Journey",
90
+ args: defaultArgs,
91
+ render: (args) => <QrFormWithState {...args} />,
92
+ };
93
+
94
+ export const InWrapper: Story = {
95
+ name: "QR Form (AEM-style wrapper)",
96
+ render: (args) => (
97
+ <div
98
+ className="qr-form-journey-aem-wrapper"
99
+ style={{ backgroundColor: "#f0f0f0", padding: "32px" }}
100
+ >
101
+ <QrFormVT {...args} />
102
+ </div>
103
+ ),
104
+ args: {
105
+ ...defaultArgs,
106
+ hubspotId: "formId123",
107
+ hubspotAppId: "PortalId123",
108
+ formAction: "",
109
+ fields: [
110
+ {
111
+ name: "serialNumber",
112
+ label: "Serial Number",
113
+ required: false,
114
+ value: "",
115
+ type: "text",
116
+ placeholder: "",
117
+ errorMessage: "",
118
+ isDisabled: true,
119
+ checked: false,
120
+ },
121
+ {
122
+ name: "productNumber",
123
+ label: "Product Number",
124
+ required: false,
125
+ value: "",
126
+ placeholder: "",
127
+ type: "text",
128
+ errorMessage: "",
129
+ isDisabled: false,
130
+ checked: false,
131
+ },
132
+ ],
133
+ },
134
+ };
@@ -0,0 +1,69 @@
1
+ import React from "react";
2
+ import { QrForm } from "@asantemedia-org/edwardsvacuum-design-system";
3
+ import "./QrFormJourney.scss";
4
+ import { Button } from "../../components/Button";
5
+
6
+ interface QrFormButtonProps {
7
+ label?: string;
8
+ onClick?: (e: React.MouseEvent) => void;
9
+ buttonStyle?: "primary" | "secondary";
10
+ href?: string;
11
+ target?: string;
12
+ type?: "button" | "submit";
13
+ element?: "a" | "button";
14
+ "data-page_target"?: number;
15
+ className?: string;
16
+ }
17
+
18
+ const QrFormButtonAdapter: React.FC<QrFormButtonProps> = ({
19
+ label,
20
+ onClick,
21
+ buttonStyle = "primary",
22
+ href,
23
+ target,
24
+ type = "button",
25
+ element,
26
+ "data-page_target": pageTarget,
27
+ className,
28
+ }) => {
29
+ const variant = buttonStyle === "secondary" ? "secondary" : "primary";
30
+
31
+ if (element === "a" || href) {
32
+ return (
33
+ <a
34
+ href={href}
35
+ target={target}
36
+ className={className}
37
+ data-page_target={pageTarget}
38
+ onClick={onClick}
39
+ style={{ display: "inline-block", textDecoration: "none" }}
40
+ >
41
+ <Button variant={variant} type={type} size="small">
42
+ {label}
43
+ </Button>
44
+ </a>
45
+ );
46
+ }
47
+
48
+ return (
49
+ <Button
50
+ variant={variant}
51
+ type={type}
52
+ onClick={onClick ? (e) => onClick(e as React.MouseEvent) : undefined}
53
+ className={className}
54
+ size="small"
55
+ >
56
+ {label}
57
+ </Button>
58
+ );
59
+ };
60
+
61
+ export const QrFormVT = (props: any) => {
62
+ return (
63
+ <div className="qr-journey-form-wrapper">
64
+ <QrForm {...props} ButtonComponent={QrFormButtonAdapter} />
65
+ </div>
66
+ );
67
+ };
68
+
69
+ export default QrFormVT;
@@ -0,0 +1,2 @@
1
+ export { QrFormVT } from "./QrFormJourney";
2
+ export { default } from "./QrFormJourney";