@financial-times/n-conversion-forms 41.1.0 → 41.2.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "branch": "",
3
3
  "repo": "n-conversion-forms",
4
- "version": "934904541de6ceb44cf85d8171392787478cd084",
5
- "tag": "v41.1.0",
6
- "buildNumber": "15757"
4
+ "version": "4ddf21c1d1a8f7e1c6ea79d0628dc66321d77c3a",
5
+ "tag": "v41.2.0",
6
+ "buildNumber": "15786"
7
7
  }
@@ -82,6 +82,21 @@ exports[`PaymentType can initialise with the loader visible 1`] = `
82
82
  </span>
83
83
  </label>
84
84
  </div>
85
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
86
+ <label for="zuorapaymentlink">
87
+ <input type="radio"
88
+ name="paymentType"
89
+ value="zuorapaymentlink"
90
+ id="zuorapaymentlink"
91
+ aria-label="Zuora Payment"
92
+ >
93
+ <span class="o-forms-input__label"
94
+ aria-hidden="true"
95
+ >
96
+ Zuora Payment
97
+ </span>
98
+ </label>
99
+ </div>
85
100
  </div>
86
101
  <div class="o-forms-input__error">
87
102
  Please enter a valid payment type
@@ -173,6 +188,21 @@ exports[`PaymentType render with default props 1`] = `
173
188
  </span>
174
189
  </label>
175
190
  </div>
191
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
192
+ <label for="zuorapaymentlink">
193
+ <input type="radio"
194
+ name="paymentType"
195
+ value="zuorapaymentlink"
196
+ id="zuorapaymentlink"
197
+ aria-label="Zuora Payment"
198
+ >
199
+ <span class="o-forms-input__label"
200
+ aria-hidden="true"
201
+ >
202
+ Zuora Payment
203
+ </span>
204
+ </label>
205
+ </div>
176
206
  </div>
177
207
  <div class="o-forms-input__error">
178
208
  Please enter a valid payment type
@@ -264,6 +294,21 @@ exports[`PaymentType render with enableApplepay 1`] = `
264
294
  </span>
265
295
  </label>
266
296
  </div>
297
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
298
+ <label for="zuorapaymentlink">
299
+ <input type="radio"
300
+ name="paymentType"
301
+ value="zuorapaymentlink"
302
+ id="zuorapaymentlink"
303
+ aria-label="Zuora Payment"
304
+ >
305
+ <span class="o-forms-input__label"
306
+ aria-hidden="true"
307
+ >
308
+ Zuora Payment
309
+ </span>
310
+ </label>
311
+ </div>
267
312
  </div>
268
313
  <div class="o-forms-input__error">
269
314
  Please enter a valid payment type
@@ -355,6 +400,21 @@ exports[`PaymentType render with enableBankTransfer 1`] = `
355
400
  </span>
356
401
  </label>
357
402
  </div>
403
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
404
+ <label for="zuorapaymentlink">
405
+ <input type="radio"
406
+ name="paymentType"
407
+ value="zuorapaymentlink"
408
+ id="zuorapaymentlink"
409
+ aria-label="Zuora Payment"
410
+ >
411
+ <span class="o-forms-input__label"
412
+ aria-hidden="true"
413
+ >
414
+ Zuora Payment
415
+ </span>
416
+ </label>
417
+ </div>
358
418
  </div>
359
419
  <div class="o-forms-input__error">
360
420
  Please enter a valid payment type
@@ -446,6 +506,21 @@ exports[`PaymentType render with enableCreditcard 1`] = `
446
506
  </span>
447
507
  </label>
448
508
  </div>
509
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
510
+ <label for="zuorapaymentlink">
511
+ <input type="radio"
512
+ name="paymentType"
513
+ value="zuorapaymentlink"
514
+ id="zuorapaymentlink"
515
+ aria-label="Zuora Payment"
516
+ >
517
+ <span class="o-forms-input__label"
518
+ aria-hidden="true"
519
+ >
520
+ Zuora Payment
521
+ </span>
522
+ </label>
523
+ </div>
449
524
  </div>
450
525
  <div class="o-forms-input__error">
451
526
  Please enter a valid payment type
@@ -556,6 +631,21 @@ exports[`PaymentType render with enableDirectdebit 1`] = `
556
631
  </span>
557
632
  </label>
558
633
  </div>
634
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
635
+ <label for="zuorapaymentlink">
636
+ <input type="radio"
637
+ name="paymentType"
638
+ value="zuorapaymentlink"
639
+ id="zuorapaymentlink"
640
+ aria-label="Zuora Payment"
641
+ >
642
+ <span class="o-forms-input__label"
643
+ aria-hidden="true"
644
+ >
645
+ Zuora Payment
646
+ </span>
647
+ </label>
648
+ </div>
559
649
  </div>
560
650
  <div class="o-forms-input__error">
561
651
  Please enter a valid payment type
@@ -705,6 +795,21 @@ exports[`PaymentType render with enablePaypal 1`] = `
705
795
  </span>
706
796
  </label>
707
797
  </div>
798
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
799
+ <label for="zuorapaymentlink">
800
+ <input type="radio"
801
+ name="paymentType"
802
+ value="zuorapaymentlink"
803
+ id="zuorapaymentlink"
804
+ aria-label="Zuora Payment"
805
+ >
806
+ <span class="o-forms-input__label"
807
+ aria-hidden="true"
808
+ >
809
+ Zuora Payment
810
+ </span>
811
+ </label>
812
+ </div>
708
813
  </div>
709
814
  <div class="o-forms-input__error">
710
815
  Please enter a valid payment type
@@ -796,6 +901,21 @@ exports[`PaymentType render with isSingleTerm 1`] = `
796
901
  </span>
797
902
  </label>
798
903
  </div>
904
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
905
+ <label for="zuorapaymentlink">
906
+ <input type="radio"
907
+ name="paymentType"
908
+ value="zuorapaymentlink"
909
+ id="zuorapaymentlink"
910
+ aria-label="Zuora Payment"
911
+ >
912
+ <span class="o-forms-input__label"
913
+ aria-hidden="true"
914
+ >
915
+ Zuora Payment
916
+ </span>
917
+ </label>
918
+ </div>
799
919
  </div>
800
920
  <div class="o-forms-input__error">
801
921
  Please enter a valid payment type
@@ -900,6 +1020,21 @@ exports[`PaymentType render with isSingleTermChecked 1`] = `
900
1020
  </span>
901
1021
  </label>
902
1022
  </div>
1023
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
1024
+ <label for="zuorapaymentlink">
1025
+ <input type="radio"
1026
+ name="paymentType"
1027
+ value="zuorapaymentlink"
1028
+ id="zuorapaymentlink"
1029
+ aria-label="Zuora Payment"
1030
+ >
1031
+ <span class="o-forms-input__label"
1032
+ aria-hidden="true"
1033
+ >
1034
+ Zuora Payment
1035
+ </span>
1036
+ </label>
1037
+ </div>
903
1038
  </div>
904
1039
  <div class="o-forms-input__error">
905
1040
  Please enter a valid payment type
@@ -1005,6 +1140,21 @@ exports[`PaymentType render with value 1`] = `
1005
1140
  </span>
1006
1141
  </label>
1007
1142
  </div>
1143
+ <div class="o-forms-input--radio-box__container ncf__payment-type ncf__payment-type--zuorapaymentlink ncf__hidden">
1144
+ <label for="zuorapaymentlink">
1145
+ <input type="radio"
1146
+ name="paymentType"
1147
+ value="zuorapaymentlink"
1148
+ id="zuorapaymentlink"
1149
+ aria-label="Zuora Payment"
1150
+ >
1151
+ <span class="o-forms-input__label"
1152
+ aria-hidden="true"
1153
+ >
1154
+ Zuora Payment
1155
+ </span>
1156
+ </label>
1157
+ </div>
1008
1158
  </div>
1009
1159
  <div class="o-forms-input__error">
1010
1160
  Please enter a valid payment type
@@ -58,3 +58,5 @@ export { GoogleSignIn } from './google-sign-in';
58
58
  export { TextInput } from './text-input';
59
59
  export { DeferredBillingTerms } from './deferred-billing-terms';
60
60
  export { YearOfBirth } from './year-of-birth';
61
+ export { ProceedWithPaymentLink } from './proceed-with-payment-link';
62
+ export { SubscriptionConfirmationWithPaymentLink } from './subscription-confirmation-with-payment-link';
@@ -42,6 +42,7 @@ export function PaymentType({
42
42
  value,
43
43
  isSingleTerm = false,
44
44
  isSingleTermChecked = false,
45
+ enableZuoraPaymentLink = false,
45
46
  }) {
46
47
  const createSecuritySeal = () => {
47
48
  return (
@@ -95,6 +96,11 @@ export function PaymentType({
95
96
  hide: !enableBankTransfer,
96
97
  };
97
98
 
99
+ const zuoraPaymentLink = {
100
+ id: 'zuorapaymentlink',
101
+ label: 'Zuora Payment',
102
+ hide: !enableZuoraPaymentLink,
103
+ };
98
104
  const createPaymentTypes = () => {
99
105
  const paymentTypes = [
100
106
  paymentTypeCreditCard,
@@ -102,6 +108,7 @@ export function PaymentType({
102
108
  paymentTypeDirectDebit,
103
109
  paymentTypeApplePay,
104
110
  paymentTypeBankTransfer,
111
+ zuoraPaymentLink,
105
112
  ].filter(Boolean);
106
113
 
107
114
  return paymentTypes.map((type) => {
@@ -284,4 +291,5 @@ PaymentType.propTypes = {
284
291
  value: PropTypes.string,
285
292
  isSingleTerm: PropTypes.bool,
286
293
  isSingleTermChecked: PropTypes.bool,
294
+ enableZuoraPaymentLink: PropTypes.bool,
287
295
  };
@@ -15,4 +15,5 @@ Basic.args = {
15
15
  enablePaypal: true,
16
16
  showPaypalCustomerCareMessage: true,
17
17
  enableBankTransfer: true,
18
+ enableZuoraPaymentLink: true,
18
19
  };
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ export function ProceedWithPaymentLink({
5
+ id = 'proceedWithPaymentLink',
6
+ title = `By proceeding now, you're:`,
7
+ description,
8
+ listItems = [],
9
+ children = (
10
+ <button className="proceed-with-payment-link__button">Proceed</button>
11
+ ),
12
+ }) {
13
+ return (
14
+ <div id={id} className="proceed-with-payment-link o-forms-field">
15
+ {title && <h2 className="proceed-with-payment-link__heading">{title}</h2>}
16
+ {description && (
17
+ <p className="proceed-with-payment-link__description">{description}</p>
18
+ )}
19
+ {listItems.length > 0 && (
20
+ <ul className="proceed-with-payment-link__list">
21
+ {listItems.map((item, index) => (
22
+ <li key={index} className="proceed-with-payment-link__list-item">
23
+ <span
24
+ className="proceed-with-payment-link__icon"
25
+ aria-hidden="true"
26
+ ></span>
27
+ <span className="proceed-with-payment-link__list-item-text">
28
+ {item}
29
+ </span>
30
+ </li>
31
+ ))}
32
+ </ul>
33
+ )}
34
+ {children && (
35
+ <div className="proceed-with-payment-link__actions">{children}</div>
36
+ )}
37
+ </div>
38
+ );
39
+ }
40
+
41
+ ProceedWithPaymentLink.propTypes = {
42
+ id: PropTypes.string,
43
+ title: PropTypes.string,
44
+ description: PropTypes.string,
45
+ listItems: PropTypes.arrayOf(PropTypes.string),
46
+ children: PropTypes.node,
47
+ };
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { ProceedWithPaymentLink } from './proceed-with-payment-link';
3
+
4
+ export default {
5
+ title: 'Proceed With Payment Link',
6
+ component: ProceedWithPaymentLink,
7
+ argTypes: {
8
+ id: { control: 'text' },
9
+ title: { control: 'text' },
10
+ description: { control: 'text' },
11
+ listItems: { control: 'array' },
12
+ },
13
+ };
14
+
15
+ export const Basic = (args) => (
16
+ <ProceedWithPaymentLink {...args}>
17
+ <button className="proceed-with-payment-link__button">
18
+ {args.buttonText}
19
+ </button>
20
+ </ProceedWithPaymentLink>
21
+ );
22
+
23
+ Basic.args = {
24
+ id: 'payment-section',
25
+ title: `By proceeding now, you're:`,
26
+ listItems: [
27
+ 'Activating the customer’s subscription',
28
+ 'Creating a payment link for the customer to complete their payment on Zuora, which they must do within 24 hours',
29
+ ],
30
+ buttonText: 'Proceed now',
31
+ };
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ export function SubscriptionConfirmationWithPaymentLink({
5
+ id = 'subscriptionConfirmationWithPaymentLink',
6
+ header = 'The subscription is now active',
7
+ body,
8
+ paymentLink,
9
+ }) {
10
+ return (
11
+ <div id={id} className="subscription-active-with-payment-link">
12
+ {/* Header */}
13
+ {header && (
14
+ <div className="subscription-active-with-payment-link__header">
15
+ <div className="subscription-active-with-payment-link__icon-container">
16
+ <span className="subscription-active-with-payment-link__icon"></span>
17
+ </div>
18
+ <h3 className="subscription-active-with-payment-link__title">
19
+ {header}
20
+ </h3>
21
+ </div>
22
+ )}
23
+
24
+ {/* Body */}
25
+ {body && (
26
+ <p
27
+ className="subscription-active-with-payment-link__description"
28
+ dangerouslySetInnerHTML={{ __html: body }}
29
+ />
30
+ )}
31
+
32
+ {/* Payment Link Section */}
33
+ {paymentLink && (
34
+ <>
35
+ <label className="subscription-active-with-payment-link__label">
36
+ Zuora Payment Link
37
+ </label>
38
+ <div className="subscription-active-with-payment-link__payment-box">
39
+ <input
40
+ type="text"
41
+ value={paymentLink}
42
+ readOnly
43
+ className="subscription-active-with-payment-link__input"
44
+ />
45
+ <button className="subscription-active-with-payment-link__button">
46
+ Copy
47
+ </button>
48
+ </div>
49
+ </>
50
+ )}
51
+ </div>
52
+ );
53
+ }
54
+
55
+ SubscriptionConfirmationWithPaymentLink.propTypes = {
56
+ id: PropTypes.string,
57
+ header: PropTypes.string,
58
+ body: PropTypes.string,
59
+ paymentLink: PropTypes.string,
60
+ };
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+ import { action } from '@storybook/addon-actions';
3
+ import { SubscriptionConfirmationWithPaymentLink } from './subscription-confirmation-with-payment-link';
4
+ import SubscriptionConfirmationWithPaymentLinkUtil from '../utils/subscription-confirmation-with-payment-link';
5
+
6
+ // Initialize the utility after story renders
7
+ const initializeUtil = () => {
8
+ const subscriptionConfirmation =
9
+ new SubscriptionConfirmationWithPaymentLinkUtil(document);
10
+ subscriptionConfirmation.handleCopyPaymentLink();
11
+ };
12
+
13
+ export default {
14
+ title: 'Subscription Confirmation With Payment Link',
15
+ component: SubscriptionConfirmationWithPaymentLink,
16
+ argTypes: {
17
+ body: { control: 'text' }, // Allows input of raw HTML in Storybook UI
18
+ },
19
+ parameters: {
20
+ docs: {
21
+ description: {
22
+ component:
23
+ 'A component that displays subscription confirmation with a copyable payment link.',
24
+ },
25
+ },
26
+ },
27
+ };
28
+
29
+ function handleButtonClick(event) {
30
+ const button = event.target.closest('button');
31
+ if (button) {
32
+ navigator.clipboard
33
+ .readText()
34
+ .then((copiedText) => action('copied')(copiedText));
35
+ }
36
+ }
37
+
38
+ // HOC to add utility initialization for stories with payment link
39
+ const withUtilInit = (Story, args) => {
40
+ if (args.paymentLink) {
41
+ setTimeout(initializeUtil, 0);
42
+ }
43
+ return (
44
+ <div className="ncf" onClick={handleButtonClick}>
45
+ <Story {...args} />
46
+ </div>
47
+ );
48
+ };
49
+
50
+ export const WithPaymentLink = (args) =>
51
+ withUtilInit(SubscriptionConfirmationWithPaymentLink, args);
52
+
53
+ WithPaymentLink.args = {
54
+ header: 'The subscription is now active',
55
+ body: 'To remain active, the customer must pay using the Zuora Payment link below <strong>within the next 24 hours</strong>.',
56
+ paymentLink: 'https://knowledgecenter.zuora.com/Zuora_Payments/Process',
57
+ };
58
+
59
+ export const WithoutPaymentLink = (args) =>
60
+ withUtilInit(SubscriptionConfirmationWithPaymentLink, args);
61
+
62
+ WithoutPaymentLink.args = {
63
+ header: 'The subscription is now active',
64
+ body: 'Your subscription has been activated successfully.',
65
+ };
package/dist/index.js CHANGED
@@ -309,6 +309,12 @@ Object.defineProperty(exports, "Position", {
309
309
  return _position.Position;
310
310
  }
311
311
  });
312
+ Object.defineProperty(exports, "ProceedWithPaymentLink", {
313
+ enumerable: true,
314
+ get: function get() {
315
+ return _proceedWithPaymentLink.ProceedWithPaymentLink;
316
+ }
317
+ });
312
318
  Object.defineProperty(exports, "ProgressIndicator", {
313
319
  enumerable: true,
314
320
  get: function get() {
@@ -345,6 +351,12 @@ Object.defineProperty(exports, "Submit", {
345
351
  return _submit.Submit;
346
352
  }
347
353
  });
354
+ Object.defineProperty(exports, "SubscriptionConfirmationWithPaymentLink", {
355
+ enumerable: true,
356
+ get: function get() {
357
+ return _subscriptionConfirmationWithPaymentLink.SubscriptionConfirmationWithPaymentLink;
358
+ }
359
+ });
348
360
  Object.defineProperty(exports, "TextInput", {
349
361
  enumerable: true,
350
362
  get: function get() {
@@ -422,4 +434,6 @@ var _graduationDate = require("./graduation-date");
422
434
  var _googleSignIn = require("./google-sign-in");
423
435
  var _textInput = require("./text-input");
424
436
  var _deferredBillingTerms = require("./deferred-billing-terms");
425
- var _yearOfBirth = require("./year-of-birth");
437
+ var _yearOfBirth = require("./year-of-birth");
438
+ var _proceedWithPaymentLink = require("./proceed-with-payment-link");
439
+ var _subscriptionConfirmationWithPaymentLink = require("./subscription-confirmation-with-payment-link");
@@ -52,7 +52,9 @@ function PaymentType(_ref) {
52
52
  _ref$isSingleTerm = _ref.isSingleTerm,
53
53
  isSingleTerm = _ref$isSingleTerm === void 0 ? false : _ref$isSingleTerm,
54
54
  _ref$isSingleTermChec = _ref.isSingleTermChecked,
55
- isSingleTermChecked = _ref$isSingleTermChec === void 0 ? false : _ref$isSingleTermChec;
55
+ isSingleTermChecked = _ref$isSingleTermChec === void 0 ? false : _ref$isSingleTermChec,
56
+ _ref$enableZuoraPayme = _ref.enableZuoraPaymentLink,
57
+ enableZuoraPaymentLink = _ref$enableZuoraPayme === void 0 ? false : _ref$enableZuoraPayme;
56
58
  var createSecuritySeal = function createSecuritySeal() {
57
59
  return /*#__PURE__*/_react["default"].createElement("div", {
58
60
  className: "ncf__security-seal",
@@ -90,8 +92,13 @@ function PaymentType(_ref) {
90
92
  label: 'Bank Transfer',
91
93
  hide: !enableBankTransfer
92
94
  };
95
+ var zuoraPaymentLink = {
96
+ id: 'zuorapaymentlink',
97
+ label: 'Zuora Payment',
98
+ hide: !enableZuoraPaymentLink
99
+ };
93
100
  var createPaymentTypes = function createPaymentTypes() {
94
- var paymentTypes = [paymentTypeCreditCard, paymentTypePaypal(), paymentTypeDirectDebit, paymentTypeApplePay, paymentTypeBankTransfer].filter(Boolean);
101
+ var paymentTypes = [paymentTypeCreditCard, paymentTypePaypal(), paymentTypeDirectDebit, paymentTypeApplePay, paymentTypeBankTransfer, zuoraPaymentLink].filter(Boolean);
95
102
  return paymentTypes.map(function (type) {
96
103
  if (type.id === undefined) {
97
104
  return type;
@@ -207,5 +214,6 @@ PaymentType.propTypes = {
207
214
  inputId: _propTypes["default"].string,
208
215
  value: _propTypes["default"].string,
209
216
  isSingleTerm: _propTypes["default"].bool,
210
- isSingleTermChecked: _propTypes["default"].bool
217
+ isSingleTermChecked: _propTypes["default"].bool,
218
+ enableZuoraPaymentLink: _propTypes["default"].bool
211
219
  };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.ProceedWithPaymentLink = ProceedWithPaymentLink;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _propTypes = _interopRequireDefault(require("prop-types"));
10
+ function ProceedWithPaymentLink(_ref) {
11
+ var _ref$id = _ref.id,
12
+ id = _ref$id === void 0 ? 'proceedWithPaymentLink' : _ref$id,
13
+ _ref$title = _ref.title,
14
+ title = _ref$title === void 0 ? "By proceeding now, you're:" : _ref$title,
15
+ description = _ref.description,
16
+ _ref$listItems = _ref.listItems,
17
+ listItems = _ref$listItems === void 0 ? [] : _ref$listItems,
18
+ _ref$children = _ref.children,
19
+ children = _ref$children === void 0 ? /*#__PURE__*/_react["default"].createElement("button", {
20
+ className: "proceed-with-payment-link__button"
21
+ }, "Proceed") : _ref$children;
22
+ return /*#__PURE__*/_react["default"].createElement("div", {
23
+ id: id,
24
+ className: "proceed-with-payment-link o-forms-field"
25
+ }, title && /*#__PURE__*/_react["default"].createElement("h2", {
26
+ className: "proceed-with-payment-link__heading"
27
+ }, title), description && /*#__PURE__*/_react["default"].createElement("p", {
28
+ className: "proceed-with-payment-link__description"
29
+ }, description), listItems.length > 0 && /*#__PURE__*/_react["default"].createElement("ul", {
30
+ className: "proceed-with-payment-link__list"
31
+ }, listItems.map(function (item, index) {
32
+ return /*#__PURE__*/_react["default"].createElement("li", {
33
+ key: index,
34
+ className: "proceed-with-payment-link__list-item"
35
+ }, /*#__PURE__*/_react["default"].createElement("span", {
36
+ className: "proceed-with-payment-link__icon",
37
+ "aria-hidden": "true"
38
+ }), /*#__PURE__*/_react["default"].createElement("span", {
39
+ className: "proceed-with-payment-link__list-item-text"
40
+ }, item));
41
+ })), children && /*#__PURE__*/_react["default"].createElement("div", {
42
+ className: "proceed-with-payment-link__actions"
43
+ }, children));
44
+ }
45
+ ProceedWithPaymentLink.propTypes = {
46
+ id: _propTypes["default"].string,
47
+ title: _propTypes["default"].string,
48
+ description: _propTypes["default"].string,
49
+ listItems: _propTypes["default"].arrayOf(_propTypes["default"].string),
50
+ children: _propTypes["default"].node
51
+ };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.SubscriptionConfirmationWithPaymentLink = SubscriptionConfirmationWithPaymentLink;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _propTypes = _interopRequireDefault(require("prop-types"));
10
+ function SubscriptionConfirmationWithPaymentLink(_ref) {
11
+ var _ref$id = _ref.id,
12
+ id = _ref$id === void 0 ? 'subscriptionConfirmationWithPaymentLink' : _ref$id,
13
+ _ref$header = _ref.header,
14
+ header = _ref$header === void 0 ? 'The subscription is now active' : _ref$header,
15
+ body = _ref.body,
16
+ paymentLink = _ref.paymentLink;
17
+ return /*#__PURE__*/_react["default"].createElement("div", {
18
+ id: id,
19
+ className: "subscription-active-with-payment-link"
20
+ }, header && /*#__PURE__*/_react["default"].createElement("div", {
21
+ className: "subscription-active-with-payment-link__header"
22
+ }, /*#__PURE__*/_react["default"].createElement("div", {
23
+ className: "subscription-active-with-payment-link__icon-container"
24
+ }, /*#__PURE__*/_react["default"].createElement("span", {
25
+ className: "subscription-active-with-payment-link__icon"
26
+ })), /*#__PURE__*/_react["default"].createElement("h3", {
27
+ className: "subscription-active-with-payment-link__title"
28
+ }, header)), body && /*#__PURE__*/_react["default"].createElement("p", {
29
+ className: "subscription-active-with-payment-link__description",
30
+ dangerouslySetInnerHTML: {
31
+ __html: body
32
+ }
33
+ }), paymentLink && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("label", {
34
+ className: "subscription-active-with-payment-link__label"
35
+ }, "Zuora Payment Link"), /*#__PURE__*/_react["default"].createElement("div", {
36
+ className: "subscription-active-with-payment-link__payment-box"
37
+ }, /*#__PURE__*/_react["default"].createElement("input", {
38
+ type: "text",
39
+ value: paymentLink,
40
+ readOnly: true,
41
+ className: "subscription-active-with-payment-link__input"
42
+ }), /*#__PURE__*/_react["default"].createElement("button", {
43
+ className: "subscription-active-with-payment-link__button"
44
+ }, "Copy"))));
45
+ }
46
+ SubscriptionConfirmationWithPaymentLink.propTypes = {
47
+ id: _propTypes["default"].string,
48
+ header: _propTypes["default"].string,
49
+ body: _propTypes["default"].string,
50
+ paymentLink: _propTypes["default"].string
51
+ };
package/main.scss CHANGED
@@ -23,6 +23,8 @@
23
23
  @import './styles/google-sign-in';
24
24
  @import './styles/confirmation';
25
25
  @import './styles/ft-edit-registration-confirmation';
26
+ @import './styles/subscription-confirmation-with-payment-link';
27
+ @import './styles/proceed-with-payment-link';
26
28
 
27
29
  @include oTypography();
28
30
  @include oFonts();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/n-conversion-forms",
3
- "version": "41.1.0",
3
+ "version": "41.2.0",
4
4
  "description": "Containing jsx components and styles for forms included on Accounts and Acquisition apps (next-signup, next-profile, next-retention, etc).",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -0,0 +1,69 @@
1
+ @import '@financial-times/o-icons/main';
2
+
3
+ .proceed-with-payment-link {
4
+ font-family: oFontsGetFontFamilyWithFallbacks(MetricWeb);
5
+ font-weight: 400;
6
+ background: oColorsByName('ft-grey');
7
+ padding: 24px;
8
+ color: oColorsByName('white');
9
+ display: flex;
10
+ flex-direction: column;
11
+
12
+ @include oGridRespondTo($from: M) {
13
+ padding: oSpacingByName('s6') oSpacingByName('s6') oSpacingByName('s8');
14
+ }
15
+ }
16
+
17
+ .proceed-with-payment-link__heading {
18
+ margin: 0px;
19
+ margin-bottom: oSpacingByName('s1');
20
+ font-weight: 400;
21
+ }
22
+
23
+ .proceed-with-payment-link__description {
24
+ color: oColorsByName('white');
25
+ margin-top: 0;
26
+ padding-top: 0;
27
+ margin-bottom: 0;
28
+ }
29
+
30
+ .proceed-with-payment-link__list {
31
+ list-style: none;
32
+ padding: 0;
33
+ }
34
+
35
+ .proceed-with-payment-link__list-item {
36
+ display: flex;
37
+ align-items: flex-start;
38
+ margin-bottom: oSpacingByName('s2');
39
+ flex-wrap: nowrap;
40
+ }
41
+
42
+ .proceed-with-payment-link__icon {
43
+ @include oIconsContent($icon-name: 'tick', $color: oColorsByName('ft-pink'), $size: 26);
44
+ margin-right: oSpacingByName('s3');
45
+ flex-shrink: 0;
46
+ min-width: 26px;
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ }
51
+
52
+ .proceed-with-payment-link__list-item-text {
53
+ flex-grow: 1;
54
+ }
55
+
56
+ .proceed-with-payment-link__actions {
57
+ margin-top: oSpacingByName('s2');
58
+
59
+ button {
60
+ @include oButtonsContent($opts: ('type': 'primary', 'theme': ('color': 'ft-pink')));
61
+ color: oColorsByName('ft-grey');
62
+ padding: oSpacingByName('s3') oSpacingByName('s6');
63
+ width: 100%;
64
+ }
65
+
66
+ button:hover {
67
+ background-color: oColorsMix('ft-pink', 'black', 80);
68
+ }
69
+ }
@@ -0,0 +1,86 @@
1
+ @import '@financial-times/o-colors/main';
2
+ @import '@financial-times/o-buttons/main';
3
+
4
+ .subscription-active-with-payment-link {
5
+ background: oColorsByName('ft-grey');
6
+ padding: oSpacingByName('s6') oSpacingByName('s6') oSpacingByName('s8');
7
+ color: oColorsByName('white');
8
+ display: flex;
9
+ flex-direction: column;
10
+ }
11
+
12
+ .subscription-active-with-payment-link--responsive {
13
+ @include oGridRespondTo($from: M) {
14
+ padding: oSpacingByName('s6') 50px oSpacingByName('s8');
15
+ }
16
+ }
17
+
18
+ .subscription-active-with-payment-link__header {
19
+ display: flex;
20
+ align-items: center;
21
+ }
22
+
23
+ .subscription-active-with-payment-link__icon-container {
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ width: 24px;
28
+ height: 24px;
29
+ background-color: oColorsByName('ft-pink');
30
+ border-radius: 50%;
31
+ margin-right: oSpacingByName('s4');
32
+ }
33
+
34
+ .subscription-active-with-payment-link__icon {
35
+ @include oIconsContent($icon-name: 'tick', $color: oColorsByName('ft-grey'), $size: 34);
36
+ }
37
+
38
+ .subscription-active-with-payment-link__title {
39
+ margin: 0;
40
+ @include oTypographySans($scale: 4, $weight: 'regular');
41
+ }
42
+
43
+ .subscription-active-with-payment-link__description {
44
+ @include oTypographySans($scale: 1);
45
+ color: oColorsByName('white');
46
+ }
47
+
48
+ .subscription-active-with-payment-link__label {
49
+ @include oTypographySans($scale: 1);
50
+ color: oColorsByName('ft-pink');
51
+ margin-bottom: oSpacingByName('s2');
52
+ }
53
+
54
+ .subscription-active-with-payment-link__payment-box {
55
+ display: flex;
56
+ align-items: center;
57
+ background: oColorsByName('ft-grey');
58
+ overflow: hidden;
59
+ gap: oSpacingByName('s2');
60
+ width: 100%;
61
+ }
62
+
63
+ .subscription-active-with-payment-link__input {
64
+ flex-grow: 1;
65
+ background: oColorsByName('white-60');
66
+ border: none;
67
+ box-sizing: border-box;
68
+ color: oColorsByName('black-60');
69
+ @include oTypographySans($scale: 1);
70
+ padding: 10px oSpacingByName('s4');
71
+ text-overflow: ellipsis;
72
+ height: 40px;
73
+ }
74
+
75
+ .subscription-active-with-payment-link__button {
76
+ @include oTypographySans($scale: 1);
77
+ @include oButtonsContent($opts: ('type': 'primary', 'theme': ('color': 'ft-pink')));
78
+ color: oColorsByName('ft-grey');
79
+ transition: background 0.2s ease-in-out;
80
+ padding: 10px 20px;
81
+ height: 40px;
82
+ }
83
+
84
+ .subscription-active-with-payment-link__button--copied {
85
+ background-color: oColorsMix($color: 'ft-pink', $background: 'white', $percentage: 80%);
86
+ }
@@ -147,6 +147,10 @@ class PaymentType {
147
147
  static get BANKTRANSFER() {
148
148
  return 'banktransfer';
149
149
  }
150
+
151
+ static get ZUORAPAYMENTLINK() {
152
+ return 'zuorapaymentlink';
153
+ }
150
154
  }
151
155
 
152
156
  module.exports = PaymentType;
package/utils/submit.js CHANGED
@@ -58,6 +58,20 @@ class Submit {
58
58
  isDisabled() {
59
59
  return !!this.$submit.disabled;
60
60
  }
61
+
62
+ /**
63
+ * Hides the submit button
64
+ */
65
+ hide() {
66
+ this.$submit.classList.add('ncf__hidden');
67
+ }
68
+
69
+ /**
70
+ * Shows the submit button
71
+ */
72
+ show() {
73
+ this.$submit.classList.remove('ncf__hidden');
74
+ }
61
75
  }
62
76
 
63
77
  module.exports = Submit;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Utility for the subscription confirmation with payment link component
3
+ * @example
4
+ * const subscriptionConfirmation = new SubscriptionConfirmationWithPaymentLink(document);
5
+ * subscriptionConfirmation.handleCopyPaymentLink((copiedText) => {
6
+ * // Handle copy event
7
+ * });
8
+ */
9
+ class SubscriptionConfirmationWithPaymentLink {
10
+ static CONTAINER_QUERY_SELECTOR = '.subscription-active-with-payment-link';
11
+
12
+ /**
13
+ * Initialize the SubscriptionConfirmationWithPaymentLink utility
14
+ * @param {Element} element Usually the window.document
15
+ * @throws If the document not passed
16
+ * @throws When the component element not found
17
+ */
18
+ constructor(element) {
19
+ if (!element) {
20
+ throw new Error('Please supply a DOM element');
21
+ }
22
+
23
+ this.$container = element.querySelector(
24
+ '.subscription-active-with-payment-link'
25
+ );
26
+
27
+ if (!this.$container) {
28
+ throw new Error(
29
+ 'Please include the subscription confirmation with payment link component on the page'
30
+ );
31
+ }
32
+
33
+ this.$button = this.$container.querySelector(
34
+ '.subscription-active-with-payment-link__button'
35
+ );
36
+ this.$input = this.$container.querySelector(
37
+ '.subscription-active-with-payment-link__input'
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Get the payment link value
43
+ * @return {String}
44
+ */
45
+ getValue() {
46
+ return this.$input ? this.$input.value : '';
47
+ }
48
+
49
+ /**
50
+ * Handle copying the payment link
51
+ * @param {Function} callback Called after successful copy
52
+ */
53
+ handleCopyPaymentLink(callback) {
54
+ if (!this.$button || !this.$input) return;
55
+
56
+ this.$button.addEventListener('click', () => {
57
+ navigator.clipboard.writeText(this.getValue()).then(() => {
58
+ this.$button.textContent = 'Copied';
59
+ this.$button.classList.add(
60
+ 'subscription-active-with-payment-link__button--copied'
61
+ );
62
+
63
+ setTimeout(() => {
64
+ this.$button.textContent = 'Copy';
65
+ this.$button.classList.remove(
66
+ 'subscription-active-with-payment-link__button--copied'
67
+ );
68
+ }, 2000);
69
+
70
+ if (callback) {
71
+ callback(this.getValue());
72
+ }
73
+ });
74
+ });
75
+ }
76
+ }
77
+
78
+ module.exports = SubscriptionConfirmationWithPaymentLink;
@@ -0,0 +1,117 @@
1
+ const SubscriptionConfirmationWithPaymentLink = require('./subscription-confirmation-with-payment-link');
2
+
3
+ describe('SubscriptionConfirmationWithPaymentLink', () => {
4
+ let subscriptionConfirmation;
5
+ let documentStub;
6
+ let containerStub;
7
+ let buttonStub;
8
+ let inputStub;
9
+ let clipboardStub;
10
+
11
+ beforeEach(() => {
12
+ buttonStub = {
13
+ addEventListener: jest.fn(),
14
+ classList: {
15
+ add: jest.fn(),
16
+ remove: jest.fn(),
17
+ },
18
+ };
19
+ inputStub = { value: 'test-link' };
20
+ containerStub = {
21
+ querySelector: jest.fn((selector) => {
22
+ if (selector.includes('button')) return buttonStub;
23
+ if (selector.includes('input')) return inputStub;
24
+ return null;
25
+ }),
26
+ };
27
+ documentStub = {
28
+ querySelector: jest.fn(() => containerStub),
29
+ };
30
+ clipboardStub = Promise.resolve();
31
+ global.navigator.clipboard = { writeText: jest.fn(() => clipboardStub) };
32
+ });
33
+
34
+ afterEach(() => {
35
+ jest.clearAllMocks();
36
+ jest.useRealTimers();
37
+ });
38
+
39
+ describe('constructor', () => {
40
+ it('throws an error if nothing passed', () => {
41
+ expect(() => {
42
+ new SubscriptionConfirmationWithPaymentLink();
43
+ }).toThrow();
44
+ });
45
+
46
+ it('throws an error if container not present', () => {
47
+ documentStub.querySelector.mockReturnValue(false);
48
+ expect(() => {
49
+ new SubscriptionConfirmationWithPaymentLink(documentStub);
50
+ }).toThrow();
51
+ });
52
+ });
53
+
54
+ describe('handleCopyPaymentLink', () => {
55
+ beforeEach(() => {
56
+ documentStub.querySelector.mockReturnValue(containerStub);
57
+ subscriptionConfirmation = new SubscriptionConfirmationWithPaymentLink(
58
+ documentStub
59
+ );
60
+ jest.useFakeTimers();
61
+ });
62
+
63
+ it('adds click event listener to button', () => {
64
+ subscriptionConfirmation.handleCopyPaymentLink();
65
+ expect(buttonStub.addEventListener).toHaveBeenCalledWith(
66
+ 'click',
67
+ expect.any(Function)
68
+ );
69
+ });
70
+
71
+ it('copies input value to clipboard on click', async () => {
72
+ const callback = jest.fn();
73
+ subscriptionConfirmation.handleCopyPaymentLink(callback);
74
+
75
+ const clickHandler = buttonStub.addEventListener.mock.calls[0][1];
76
+ await clickHandler();
77
+
78
+ expect(navigator.clipboard.writeText).toHaveBeenCalledWith('test-link');
79
+ });
80
+
81
+ it('updates button text and style after copy', async () => {
82
+ subscriptionConfirmation.handleCopyPaymentLink();
83
+
84
+ const clickHandler = buttonStub.addEventListener.mock.calls[0][1];
85
+ await clickHandler();
86
+
87
+ expect(buttonStub.textContent).toBe('Copied');
88
+ expect(buttonStub.classList.add).toHaveBeenCalledWith(
89
+ 'subscription-active-with-payment-link__button--copied'
90
+ );
91
+ });
92
+
93
+ it('resets button after timeout', async () => {
94
+ subscriptionConfirmation.handleCopyPaymentLink();
95
+
96
+ const clickHandler = buttonStub.addEventListener.mock.calls[0][1];
97
+ await clickHandler();
98
+
99
+ jest.advanceTimersByTime(2000);
100
+
101
+ expect(buttonStub.textContent).toBe('Copy');
102
+ expect(buttonStub.classList.remove).toHaveBeenCalledWith(
103
+ 'subscription-active-with-payment-link__button--copied'
104
+ );
105
+ });
106
+
107
+ it('calls callback with copied value', async () => {
108
+ const callback = jest.fn();
109
+ subscriptionConfirmation.handleCopyPaymentLink(callback);
110
+
111
+ const clickHandler = buttonStub.addEventListener.mock.calls[0][1];
112
+ await clickHandler();
113
+
114
+ expect(callback).toHaveBeenCalledWith('test-link');
115
+ });
116
+ });
117
+ });