@financial-times/n-myft-ui 38.0.2 → 38.0.4

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,6 +1,6 @@
1
1
  {
2
2
  "branch": "",
3
3
  "repo": "n-myft-ui",
4
- "version": "032d682829d125edd45469ab17376a909ab61c86",
5
- "tag": "v38.0.2"
4
+ "version": "2e06941445c220495ee1c6c33990cf542f7ae683",
5
+ "tag": "v38.0.4"
6
6
  }
@@ -1,61 +1,81 @@
1
1
  {{#if @root.flags.myFtApiWrite}}
2
- <form class="n-myft-ui n-myft-ui--save" method="GET"
3
- data-content-id="{{contentId}}"
4
- data-myft-ui="saved"
5
- action="/myft/save/{{contentId}}"
6
- data-js-action="/__myft/api/core/saved/content/{{contentId}}?method=put"
7
- data-myft-ui-save-config="{{#if nonModal}}nonModal{{/if}}">
8
- {{> n-myft-ui/components/csrf-token/input}}
9
- <div
10
- class="n-myft-ui__announcement o3-visually-hidden"
11
- aria-live="assertive"
12
- data-pressed-text="Article saved in My FT."
13
- data-unpressed-text="Removed article from My FT."
14
- ></div>
15
- <button
16
- type="submit"
17
- class="{{#if saveButtonWithIcon}}n-myft-ui__save-button-with-icon{{else}}o3-button o3-button--secondary o3-button--small{{#variant}} o3-button--{{this}}{{/variant}}{{/if}}"
18
- data-trackable="{{#if trackableId}}{{trackableId}}{{else}}save-for-later{{/if}}"
19
- {{#if isSaved}}
20
- {{!-- The value of alternate label needs to be the opposite of label / the current saved state. This allows the client side JS to toggle the labels on state changes --}}
21
- title="{{#if title}}{{title}} is{{/if}} Saved to myFT"
22
- aria-label="{{#if title}}{{title}} is{{/if}} Saved to myFT - Unsave"
23
- data-alternate-label="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
24
- aria-pressed="true"
25
- {{else}}
26
- title="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
27
- aria-label="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
28
- data-alternate-label="{{#if title}}{{title}} is{{/if}} Saved to myFT"
29
- aria-pressed="false"
30
- {{/if}}
31
- {{#unlessEquals appIsStreamPage true}}
32
- {{#if saveButtonWithIcon}}
33
- data-text-variant="save-button-with-icon-copy"
2
+ <form
3
+ class="n-myft-ui n-myft-ui--save"
4
+ method="GET"
5
+ data-content-id="{{contentId}}"
6
+ data-myft-ui="saved"
7
+ action="/myft/save/{{contentId}}"
8
+ data-js-action="/__myft/api/core/saved/content/{{contentId}}?method=put"
9
+ data-myft-ui-save-config="{{#if nonModal}}nonModal{{/if}}"
10
+ >
11
+ {{> n-myft-ui/components/csrf-token/input}}
12
+
13
+ <div
14
+ class="n-myft-ui__announcement o3-visually-hidden"
15
+ aria-live="assertive"
16
+ data-pressed-text="Article saved in My FT."
17
+ data-unpressed-text="Removed article from My FT."
18
+ ></div>
19
+
20
+ <button
21
+ type="submit"
22
+ class="{{#if saveButtonWithIcon}}n-myft-ui__save-button-with-icon{{else}}o3-button o3-button--secondary o3-button--small{{/if}}"
23
+ data-trackable="{{#if trackableId}}{{trackableId}}{{else}}save-for-later{{/if}}"
24
+ {{#if variant}}data-o3-theme="inverse"{{/if}}
25
+
26
+ {{#if isSaved}}
27
+ {{!-- The value of alternate label needs to be the opposite of label / the current saved state.
28
+ This allows the client side JS to toggle the labels on state changes --}}
29
+ title="{{#if title}}{{title}} is{{/if}} Saved to myFT"
30
+ aria-label="{{#if title}}{{title}} is{{/if}} Saved to myFT - Unsave"
31
+ data-alternate-label="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
32
+ aria-pressed="true"
34
33
  {{else}}
35
- data-text-variant="save-button-longer-copy"
34
+ title="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
35
+ aria-label="{{#if title}}Save {{title}} to myFT for later{{else}}Save this article to myFT for later{{/if}}"
36
+ data-alternate-label="{{#if title}}{{title}} is{{/if}} Saved to myFT"
37
+ aria-pressed="false"
36
38
  {{/if}}
37
- {{/unlessEquals}}
38
- {{#if alternateText}}
39
- data-alternate-text="{{alternateText}}"
40
- {{else}}
41
- {{#if isSaved}}
42
- data-alternate-text="Save&nbsp;"
39
+
40
+ {{#unlessEquals appIsStreamPage true}}
41
+ {{#if saveButtonWithIcon}}
42
+ data-text-variant="save-button-with-icon-copy"
43
+ {{else}}
44
+ data-text-variant="save-button-longer-copy"
45
+ {{/if}}
46
+ {{/unlessEquals}}
47
+
48
+ {{#if alternateText}}
49
+ data-alternate-text="{{alternateText}}"
43
50
  {{else}}
44
- data-alternate-text="Saved&nbsp;"
51
+ {{#if isSaved}}
52
+ data-alternate-text="Save&nbsp;"
53
+ {{else}}
54
+ data-alternate-text="Saved&nbsp;"
55
+ {{/if}}
45
56
  {{/if}}
46
- {{/if}}
47
- data-content-id="{{contentId}}" {{! duplicated here for tracking}}
57
+
58
+ data-content-id="{{contentId}}" {{! duplicated here for tracking }}
48
59
  >
49
60
  {{#if saveButtonWithIcon}}
50
- <span class="save-button-with-icon-copy" data-variant-label>{{#if buttonText~}}
51
- {{buttonText}}
52
- {{~else~}}
53
- {{#if isSaved}}Saved{{else}}Save{{/if}}
54
- {{~/if}}</span>
61
+ <span class="save-button-with-icon-copy" data-variant-label>
62
+ {{#if buttonText~}}
63
+ {{buttonText}}
64
+ {{~else~}}
65
+ {{#if isSaved}}Saved{{else}}Save{{/if}}
66
+ {{~/if}}
67
+ </span>
55
68
  {{else}}
56
- {{#if buttonText}}{{buttonText}}{{else}}
69
+ {{#if buttonText}}
70
+ {{buttonText}}
71
+ {{else}}
57
72
  {{#unlessEquals appIsStreamPage true}}
58
- <span class="save-button-longer-copy" data-variant-label>{{#if isSaved}}Saved&nbsp;{{else}}Save&nbsp;{{/if}}</span><span class="n-myft-ui__button--viewport-large" aria-hidden="true">to myFT</span>
73
+ <span class="save-button-longer-copy" data-variant-label>
74
+ {{#if isSaved}}Saved&nbsp;{{else}}Save&nbsp;{{/if}}
75
+ </span>
76
+ <span class="n-myft-ui__button--viewport-large" aria-hidden="true">
77
+ to myFT
78
+ </span>
59
79
  {{else}}
60
80
  <span>{{#if isSaved}}Saved{{else}}Save{{/if}}</span>
61
81
  {{/unlessEquals}}
@@ -65,4 +85,4 @@
65
85
  </form>
66
86
  {{else}}
67
87
  <!-- Save button hidden due to myFtApiWrite being off -->
68
- {{/if }}
88
+ {{/if}}
@@ -9,17 +9,11 @@ $system-code: "n-myft-ui-demo";
9
9
  @import '../../components/jsx/follow-plus-instant-alerts/main';
10
10
  @import '../../components/jsx/preferences-modal/main';
11
11
 
12
- @import '../../components/digest-promo/main';
13
-
14
12
  .onboarding-container {
15
13
  background-color: var(--o3-color-palette-slate);
16
14
  padding: 20px;
17
15
  }
18
16
 
19
- .n-myft-digest-promo {
20
- display: block;
21
- }
22
-
23
17
  .demo-container {
24
18
  margin-bottom: 400px;
25
19
  }
@@ -664,20 +664,6 @@
664
664
  {{/each}}
665
665
  </div>
666
666
  </section>
667
-
668
- <section
669
- id="digest-promo"
670
- class="demo-section">
671
- <div class="o-grid-row">
672
- <div data-o-grid-colspan="12">
673
- <h3 class="demo-section__title">
674
- Digest promo
675
- </h3>
676
- {{> n-myft-ui/components/digest-promo/generic-promo-message }}
677
- {{> n-myft-ui/components/digest-promo/promo-message }}
678
- </div>
679
- </div>
680
- </section>
681
667
  </div>
682
668
  </body>
683
669
 
@@ -1,7 +1,8 @@
1
1
  import myFtClient from 'next-myft-client';
2
2
 
3
3
  export default function (el) {
4
- const links = (el && el.nodeName === 'A') ? [el] : Array.from(el.querySelectorAll('a[href^="/myft"]'));
4
+ const targetElement = el || document;
5
+ const links = (targetElement && targetElement.nodeName === 'A') ? [targetElement] : Array.from(targetElement.querySelectorAll('a[href^="/myft"]'));
5
6
  return Promise.all(links.map(link => myFtClient.personaliseUrl(link.getAttribute('href'))
6
7
  .then(personalisedUrl => link.setAttribute('href', personalisedUrl)))
7
8
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/n-myft-ui",
3
- "version": "38.0.2",
3
+ "version": "38.0.4",
4
4
  "description": "Client side component for interaction with myft",
5
5
  "main": "server.js",
6
6
  "scripts": {
@@ -1,37 +0,0 @@
1
- <div class="n-myft-digest-promo n-myft-digest-promo--generic">
2
- <div class="o-grid-container o-grid-container--snappy">
3
- <div class="o-grid-row">
4
- <div data-o-grid-colspan="12 M8" class="n-myft-digest-promo__container">
5
- <div class="o-grid-container o-grid-container--snappy o-grid-container--bleed">
6
- <div class="o-grid-row">
7
-
8
- <div data-o-grid-colspan="12 L8" class="n-myft-digest-promo__content">
9
- <h2 class="o3-type-body-highlight n-myft-digest-promo__heading">
10
- Sign up to <span class="n-myft-digest-promo__branding">myFT Daily Digest</span>
11
- </h2>
12
- <p class ="n-myft-digest-promo__para">Receive the latest news from topics you follow on myFT straight to your inbox</p>
13
- </div>
14
-
15
- <div data-o-grid-colspan="12 L4" class="n-myft-digest-promo__cta-wrapper">
16
- <button aria-label="Sign up to myFT Digest"
17
- aria-pressed="false"
18
- class="n-myft-digest-promo__cta-btn"
19
- data-alternate-label="Unsubscribe"
20
- data-alternate-text="Signed up"
21
- data-trackable="digest-promo"
22
- title="Sign up to myFT Digest"
23
- data-title="{{title}}"
24
- type="submit">
25
- Sign up
26
- </button>
27
- </div>
28
-
29
- {{#unless nonDismissable}}
30
- <button class="n-myft-digest-promo__dismiss-btn" title="dismiss" data-trackable="digest-promo-dismiss"></button>
31
- {{/unless}}
32
- </div>
33
- </div>
34
- </div>
35
- </div>
36
- </div>
37
- </div>
@@ -1,104 +0,0 @@
1
- import myFtClient from 'next-myft-client';
2
- import buttons from '../../myft-common';
3
- import getToken from '../../myft/ui/lib/get-csrf-token';
4
- import superstore from 'superstore-sync';
5
- const STORAGE_KEY = 'n-myft-digest-promo-seen';
6
-
7
- const CLASSES = {
8
- ctaBtn:'.n-myft-digest-promo__cta-btn',
9
- dismissBtn:'.n-myft-digest-promo__dismiss-btn',
10
- promoComponent:'.n-myft-digest-promo',
11
- promoEnabled:'n-myft-digest-promo--enabled'
12
- };
13
-
14
- let btn;
15
- let element;
16
- let conceptId;
17
-
18
- function bindListeners () {
19
- const btn = document.querySelector(CLASSES.ctaBtn);
20
- const dismissBtn = document.querySelector(CLASSES.dismissBtn);
21
-
22
- btn.addEventListener('click', addToDigest, false);
23
-
24
- if (dismissBtn) {
25
- dismissBtn.addEventListener('click', () => {
26
- hidePromo();
27
- setDismissState();
28
- }, false);
29
- }
30
- }
31
-
32
- function shouldShowPromo (conceptId) {
33
- return Promise.all([
34
- myFtClient.get('followed', 'concept', conceptId),
35
- myFtClient.get('preferred', 'preference', 'email-digest')
36
- ]).then(([follows, prefers]) => {
37
- return follows.length === 0 && prefers.length === 0 && !getDismissState();
38
- });
39
- }
40
-
41
- function showPromo () {
42
- element = document.querySelector(CLASSES.promoComponent);
43
- element.classList.add(CLASSES.promoEnabled);
44
- }
45
-
46
- function hidePromo () {
47
- element = document.querySelector(CLASSES.promoComponent);
48
- element.classList.remove(CLASSES.promoEnabled);
49
- }
50
-
51
- function getDismissState () {
52
- return superstore.session.get(STORAGE_KEY);
53
- }
54
-
55
- function setDismissState () {
56
- superstore.session.set(STORAGE_KEY, 1);
57
- }
58
-
59
- function addToDigest () {
60
- const csrfToken = getToken();
61
- const metaConcept = {
62
- name: btn.getAttribute('data-title'),
63
- };
64
-
65
- const directType = btn.getAttribute('data-direct-type');
66
-
67
- if (directType) {
68
- metaConcept.directType = directType;
69
- }
70
-
71
- const metaEmail = {
72
- _rel: {
73
- type: 'daily',
74
- timezone: 'Europe/London'
75
- }
76
- };
77
-
78
- const promises = [myFtClient.add('user', null, 'preferred', 'preference', 'email-digest', Object.assign({}, {token: csrfToken}, metaEmail))];
79
-
80
- if (conceptId) {
81
- promises.push(myFtClient.add('user', null, 'followed', 'concept', conceptId, Object.assign({}, {token: csrfToken}, metaConcept)));
82
- }
83
-
84
- return Promise.all(promises).then(() => {
85
- buttons.toggleState(btn, true);
86
- btn.setAttribute('disabled', true);
87
- btn.setAttribute('aria-pressed', true);
88
- });
89
- }
90
-
91
- function init () {
92
- element = document.querySelector(CLASSES.promoComponent);
93
- if(!superstore.isPersisting() || !element) { return; }
94
- btn = document.querySelector(CLASSES.ctaBtn);
95
- conceptId = btn.getAttribute('data-concept-id');
96
- shouldShowPromo(conceptId).then(shouldShow => {
97
- if(shouldShow) {
98
- showPromo();
99
- bindListeners();
100
- }
101
- });
102
- };
103
-
104
- export { init };
@@ -1,133 +0,0 @@
1
- @import '../../mixins/lozenge/main';
2
-
3
- $icon-width-s: 90px;
4
- $icon-width-m: 90px;
5
-
6
- // TODO Remove below
7
- $spacing-unit: 20px;
8
-
9
- .n-myft-digest-promo {
10
- display: none;
11
- float: none;
12
- position: relative;
13
- background-color: var(--o3-color-palette-white-60);
14
- border-bottom: 1px solid var(--o3-color-palette-black-20);
15
- border-top: 1px solid var(--o3-color-palette-black-20);
16
- margin-bottom: 20px;
17
- }
18
-
19
- .n-myft-digest-promo--enabled {
20
- display: block;
21
- }
22
-
23
- .n-myft-digest-promo__container {
24
- position: relative;
25
- @include oGridRespondTo('M') {
26
- @include oGridCenter;
27
- @include oGridOffset(2);
28
- }
29
- }
30
-
31
- .n-myft-digest-promo__dismiss-btn {
32
- position: absolute;
33
- top: 0;
34
- right: 0;
35
- background-color: transparent;
36
- border-color: transparent;
37
- height: 24px;
38
- width: 24px;
39
-
40
- &::before {
41
- background-color: var(--o3-color-palette-black-80);
42
- mask-image: var(--o3-icon-cross);
43
- mask-repeat: no-repeat;
44
- mask-size: contain;
45
- height: 24px;
46
- width: 24px;
47
- position: absolute;
48
- top: 0;
49
- right: 0;
50
- content: '';
51
- }
52
- }
53
-
54
- .n-myft-digest-promo__content {
55
- position: relative;
56
- padding-left: $icon-width-s;
57
- padding-top: $spacing-unit;
58
-
59
- @include oGridRespondTo('M') {
60
- padding-left: $icon-width-m;
61
-
62
- &::before {
63
- width: $icon-width-m;
64
- }
65
- }
66
-
67
- &::before {
68
- position: absolute;
69
- content: '';
70
- display: block;
71
- width: $icon-width-s;
72
- height: 80px;
73
- left: 0;
74
- background-image: url('https://www.ft.com/__origami/service/image/v2/images/raw/https%3A%2F%2Fwww.ft.com%2F__assets%2Fcreatives%2Fmyft-alerts-prefs%2Fenvelope.svg?source=next&fit=scale-down&compression=best&width=50');
75
- background-repeat: no-repeat;
76
- background-size: 60px auto;
77
- background-position: 10px 0;
78
- }
79
- }
80
-
81
- .n-myft-digest-promo__heading {
82
- margin-top: 0;
83
- margin-bottom: 7px;
84
- }
85
-
86
- .n-myft-digest-promo__para {
87
- line-height: var(--o3-font-lineheight-metric2-negative-2);
88
- font-size: var(--o3-font-size-metric2-negative-2);
89
- font-family: var(--o3-font-family-metric);
90
- margin-top: 0;
91
- }
92
-
93
- .n-myft-digest-promo__branding {
94
- font-weight: normal;
95
- white-space: nowrap;
96
- }
97
-
98
- .n-myft-digest-promo__cta-wrapper {
99
- display: flex;
100
- align-items: flex-end;
101
- justify-content: unset;
102
- padding-bottom: $spacing-unit;
103
- clear: both;
104
-
105
- @include oGridRespondTo('M') {
106
- justify-content: flex-end;
107
- }
108
- }
109
-
110
- .n-myft-digest-promo__cta-btn {
111
- @include myftLozengeToggleButton();
112
- display: inline-block;
113
- text-transform: none;
114
- min-width: 134px;
115
- width: 134px;
116
- margin-left: 80px;
117
-
118
- &[disabled] {
119
- min-width: 55px;
120
- width: 55px;
121
- }
122
-
123
- .n-myft-digest-promo--generic &,
124
- .n-myft-digest-promo--generic &[disabled] {
125
- width: auto;
126
- min-width: auto;
127
- }
128
-
129
- @include oGridRespondTo('M') {
130
- margin-left: 0;
131
- float: right;
132
- }
133
- }
@@ -1,39 +0,0 @@
1
- <div class="n-myft-digest-promo">
2
- <div class="o-grid-container o-grid-container--snappy">
3
- <div class="o-grid-row">
4
- <div data-o-grid-colspan="12 M8" class="n-myft-digest-promo__container">
5
- <div class="o-grid-container o-grid-container--snappy o-grid-container--bleed">
6
- <div class="o-grid-row">
7
-
8
- <div data-o-grid-colspan="12 M8" class="n-myft-digest-promo__content">
9
- <h2 class="o3-type-body-highlight n-myft-digest-promo__heading">
10
- Add to <span class="n-myft-digest-promo__branding">myFT Digest</span>
11
- </h2>
12
- <p class ="n-myft-digest-promo__para">Add this topic to your myFT Digest for news straight to your inbox</p>
13
- </div>
14
-
15
- <div data-o-grid-colspan="12 M4" class="n-myft-digest-promo__cta-wrapper">
16
- <button aria-label="Add {{title}}"
17
- aria-pressed="false"
18
- class="n-myft-digest-promo__cta-btn"
19
- data-alternate-label="Remove {{title}}"
20
- data-alternate-text="Added"
21
- data-concept-id="{{conceptId}}"
22
- data-trackable="digest-promo"
23
- title="Add {{title}}"
24
- data-title="{{title}}"
25
- data-direct-type="{{directType}}"
26
- type="submit">
27
- Add to myFT Digest
28
- </button>
29
- </div>
30
-
31
- {{#unless nonDismissable}}
32
- <button class="n-myft-digest-promo__dismiss-btn" title="dismiss" data-trackable="digest-promo-dismiss"></button>
33
- {{/unless}}
34
- </div>
35
- </div>
36
- </div>
37
- </div>
38
- </div>
39
- </div>