@financial-times/dotcom-ui-header 7.1.1 → 7.1.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.
package/README.md CHANGED
@@ -35,7 +35,7 @@ import { Header, Drawer } from '@financial-times/dotcom-ui-header'
35
35
 
36
36
  const SiteHeader = (props) => (
37
37
  <Header data={props.navigationData} userIsLoggedIn={props.userIsLoggedIn} />
38
- <Drawer data={props.navigationData} userIsLoggedIn={props.userIsLoggedIn} />
38
+ <Drawer data={props.navigationData} userIsLoggedIn={props.userIsLoggedIn} userIsSubscribed={props.userIsSubscribed} />
39
39
  )
40
40
  ```
41
41
 
@@ -71,6 +71,7 @@ All header components with the exception of `<LogoOnly />` require the following
71
71
  | variant | 'simple' \| 'large-logo' \| string | true | 'simple' | Adds a class name to the header element
72
72
  | userIsAnonymous | boolean | true | true | Marks a user as anonymous - can be set by middleware included with n-express |
73
73
  | userIsLoggedIn | boolean | true | false | Marks a user as logged in - can be set by middleware included with n-express |
74
+ | userIsSubscribed | boolean | true | false | Marks a user as subscribed - set by middleware(ammit task in preflight) included with n-express |
74
75
  | showUserNavigation | boolean | true | true | Show user navigation options such as `Sign out` or `Subscribe` |
75
76
  | showSubNavigation | boolean | true | true | Show the sub-navigation component which may include the crumbtrail |
76
77
  | showStickyHeader | boolean | true | true | Enable rendering of the sticky header component |
@@ -7,24 +7,28 @@ exports.SubscribeButton = exports.EditionsSwitcher = exports.DrawerSpecialItem =
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const utils_1 = require("../../utils");
9
9
  exports.DrawerParentItem = ({ item, idSuffix }) => {
10
+ var _a, _b;
10
11
  const selected = item.selected ? 'selected' : 'unselected';
11
12
  return (react_1.default.createElement(react_1.default.Fragment, null,
12
13
  react_1.default.createElement("div", { key: item.url, className: "o-header__drawer-menu-toggle-wrapper" },
13
- react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--parent`, href: item.url }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label),
14
+ react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--parent`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label),
14
15
  react_1.default.createElement("button", { className: `o-header__drawer-menu-toggle o-header__drawer-menu-toggle--${selected}`, "aria-controls": `o-header-drawer-child-${idSuffix}`, "data-trackable": `sub-level-toggle | ${item.label}` }, `Show more ${item.label}`)),
15
- react_1.default.createElement("ul", { className: "o-header__drawer-menu-list o-header__drawer-menu-list--child", id: `o-header-drawer-child-${idSuffix}`, "data-trackable": "sub-level" }, item.submenu.items.map((item) => {
16
+ react_1.default.createElement("ul", { className: "o-header__drawer-menu-list o-header__drawer-menu-list--child", id: `o-header-drawer-child-${idSuffix}`, "data-trackable": "sub-level" }, ((_b = item.submenu) === null || _b === void 0 ? void 0 : _b.items).map((item) => {
17
+ var _a;
16
18
  const selected = item.selected ? 'selected' : 'unselected';
17
19
  return (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" },
18
- react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--child`, href: item.url, "data-trackable": item.label }, utils_1.ariaSelected(item)), item.label)));
20
+ react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--child`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, utils_1.ariaSelected(item)), item.label)));
19
21
  }))));
20
22
  };
21
23
  exports.DrawerSingleItem = (item) => {
24
+ var _a;
22
25
  const selected = item.selected ? 'selected' : 'unselected';
23
- return (react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected}`, href: item.url, "data-trackable": item.label }, utils_1.ariaSelected(item)), item.label));
26
+ return (react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected}`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, utils_1.ariaSelected(item)), item.label));
24
27
  };
25
28
  exports.DrawerSpecialItem = (item) => {
29
+ var _a;
26
30
  const selected = item.selected ? 'selected' : 'unselected';
27
- return (react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--secondary`, href: item.url, "data-trackable": item.label }, utils_1.ariaSelected(item)), item.label));
31
+ return (react_1.default.createElement("a", Object.assign({ className: `o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--secondary`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, utils_1.ariaSelected(item)), item.label));
28
32
  };
29
33
  exports.EditionsSwitcher = (editions) => (react_1.default.createElement("ul", { className: "o-header__drawer-menu-list" }, editions.others.map(({ id, name, url }) => {
30
34
  const href = `${url}?edition=${id}`;
@@ -41,18 +41,28 @@ const Search = () => (react_1.default.createElement("div", { className: "o-heade
41
41
  react_1.default.createElement("button", { className: "o-header__drawer-search-submit", type: "submit", "data-trackable": "search-submit" },
42
42
  react_1.default.createElement("span", { className: "o-header__visually-hidden" }, "Search")))));
43
43
  const SectionPrimary = (props) => {
44
+ var _a;
44
45
  return (react_1.default.createElement(react_1.default.Fragment, null,
45
46
  react_1.default.createElement("li", { className: "o-header__drawer-menu-item o-header__drawer-menu-item--heading" }, props.label),
46
- props.submenu.items.map((item, index) => (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" }, item.submenu ? (react_1.default.createElement(additionalPartials_1.DrawerParentItem, { item: item, idSuffix: `${index}` })) : (react_1.default.createElement(additionalPartials_1.DrawerSingleItem, Object.assign({}, item))))))));
47
+ ((_a = props.submenu) === null || _a === void 0 ? void 0 : _a.items).map((item, index) => (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" }, item.submenu ? (react_1.default.createElement(additionalPartials_1.DrawerParentItem, { item: item, idSuffix: `${index}` })) : (react_1.default.createElement(additionalPartials_1.DrawerSingleItem, Object.assign({}, item))))))));
48
+ };
49
+ const SectionSecondary = (props) => {
50
+ var _a;
51
+ return (react_1.default.createElement(react_1.default.Fragment, null,
52
+ react_1.default.createElement("li", { className: "o-header__drawer-menu-item o-header__drawer-menu-item--heading" }, props.label),
53
+ ((_a = props.submenu) === null || _a === void 0 ? void 0 : _a.items).map((item, index) => (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" }, item.submenu ? (react_1.default.createElement(additionalPartials_1.DrawerParentItem, { item: item, idSuffix: 'inner' + index })) : (react_1.default.createElement(additionalPartials_1.DrawerSingleItem, Object.assign({}, item))))))));
54
+ };
55
+ const SectionTertiary = (props) => {
56
+ var _a;
57
+ return (react_1.default.createElement(react_1.default.Fragment, null, ((_a = props.submenu) === null || _a === void 0 ? void 0 : _a.items).map((item, index) => {
58
+ const divideItem = index === 0 ? 'o-header__drawer-menu-item--divide' : '';
59
+ return (react_1.default.createElement("li", { key: item.url, className: `o-header__drawer-menu-item ${divideItem}` },
60
+ react_1.default.createElement(additionalPartials_1.DrawerSpecialItem, Object.assign({}, item))));
61
+ })));
47
62
  };
48
- const SectionSecondary = (props) => (react_1.default.createElement(react_1.default.Fragment, null,
49
- react_1.default.createElement("li", { className: "o-header__drawer-menu-item o-header__drawer-menu-item--heading" }, props.label),
50
- props.submenu.items.map((item, index) => (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" }, item.submenu ? (react_1.default.createElement(additionalPartials_1.DrawerParentItem, { item: item, idSuffix: 'inner' + index })) : (react_1.default.createElement(additionalPartials_1.DrawerSingleItem, Object.assign({}, item))))))));
51
- const SectionTertiary = (props) => (react_1.default.createElement(react_1.default.Fragment, null, props.submenu.items.map((item, index) => {
52
- const divideItem = index === 0 ? 'o-header__drawer-menu-item--divide' : '';
53
- return (react_1.default.createElement("li", { key: item.url, className: `o-header__drawer-menu-item ${divideItem}` },
54
- react_1.default.createElement(additionalPartials_1.DrawerSpecialItem, Object.assign({}, item))));
55
- })));
56
63
  const UserMenu = (props) => (react_1.default.createElement("nav", { className: "o-header__drawer-menu o-header__drawer-menu--user", "data-trackable": "user-nav" },
57
- react_1.default.createElement("ul", { className: "o-header__drawer-menu-list" }, props.items.map((item) => (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" },
58
- react_1.default.createElement("a", { className: "o-header__drawer-menu-link", href: item.url, "data-trackable": item.label }, item.label)))))));
64
+ react_1.default.createElement("ul", { className: "o-header__drawer-menu-list" }, props.items.map((item) => {
65
+ var _a;
66
+ return (react_1.default.createElement("li", { key: item.url, className: "o-header__drawer-menu-item" },
67
+ react_1.default.createElement("a", { className: "o-header__drawer-menu-link", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, item.label)));
68
+ }))));
@@ -9,28 +9,37 @@ const utils_1 = require("../../utils");
9
9
  const MobileNav = (props) => {
10
10
  // Only display navigation on pages which are included in this menu
11
11
  const targetUrls = props.data['navbar-simple'].items.map((item) => item.url);
12
- return targetUrls.includes(props.data.currentPath) ? (react_1.default.createElement(NavMobile, { items: props.data['navbar-simple'].items })) : null;
12
+ return props.data.currentPath && targetUrls.includes(props.data.currentPath) ? (react_1.default.createElement(NavMobile, { items: props.data['navbar-simple'].items })) : null;
13
13
  };
14
14
  exports.MobileNav = MobileNav;
15
15
  const NavMobile = ({ items }) => {
16
16
  return (react_1.default.createElement("nav", { id: "o-header-nav-mobile", className: "o-header__row o-header__nav o-header__nav--mobile", "aria-hidden": "true", "data-trackable": "header-nav:mobile" },
17
- react_1.default.createElement("ul", { className: "o-header__nav-list" }, items.map((item, index) => (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
18
- react_1.default.createElement("a", Object.assign({ className: "o-header__nav-link o-header__nav-link--primary", href: item.url }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label)))))));
17
+ react_1.default.createElement("ul", { className: "o-header__nav-list" }, items.map((item, index) => {
18
+ var _a;
19
+ return (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
20
+ react_1.default.createElement("a", Object.assign({ className: "o-header__nav-link o-header__nav-link--primary", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label)));
21
+ }))));
19
22
  };
20
23
  const NavDesktop = (props) => (react_1.default.createElement("nav", { id: "o-header-nav-desktop", className: "o-header__row o-header__nav o-header__nav--desktop", role: "navigation", "aria-label": "Primary navigation", "data-trackable": "header-nav:desktop" },
21
24
  react_1.default.createElement("div", { className: "o-header__container" }, props.children)));
22
25
  exports.NavDesktop = NavDesktop;
23
- const NavListLeft = (props) => (react_1.default.createElement("ul", { className: "o-header__nav-list o-header__nav-list--left", "data-trackable": "primary-nav" }, props.data.navbar.items.map((item, index) => (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
24
- react_1.default.createElement("a", Object.assign({ className: "o-header__nav-link o-header__nav-link--primary", href: item.url, id: `o-header-link-${index}` }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label),
25
- props.showMegaNav && Array.isArray(item.meganav) ? (react_1.default.createElement(MegaNav, { meganav: item.meganav, label: item.label, index: index })) : null)))));
26
+ const NavListLeft = (props) => (react_1.default.createElement("ul", { className: "o-header__nav-list o-header__nav-list--left", "data-trackable": "primary-nav" }, props.data.navbar.items.map((item, index) => {
27
+ var _a;
28
+ return (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
29
+ react_1.default.createElement("a", Object.assign({ className: "o-header__nav-link o-header__nav-link--primary", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, id: `o-header-link-${index}` }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label),
30
+ props.showMegaNav && Array.isArray(item.meganav) ? (react_1.default.createElement(MegaNav, { meganav: item.meganav, label: item.label, index: index })) : null));
31
+ })));
26
32
  exports.NavListLeft = NavListLeft;
27
33
  const NavListRight = (props) => {
28
34
  return props.userIsLoggedIn ? react_1.default.createElement(NavListRightLoggedIn, { items: props.data['navbar-right'].items }) : null;
29
35
  };
30
36
  exports.NavListRight = NavListRight;
31
37
  const NavListRightLoggedIn = ({ items }) => {
32
- return (react_1.default.createElement("ul", { className: "o-header__nav-list o-header__nav-list--right", "data-trackable": "user-nav" }, items.map((item, index) => (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
33
- react_1.default.createElement("a", { className: "o-header__nav-link", href: item.url, "data-trackable": item.label }, item.label))))));
38
+ return (react_1.default.createElement("ul", { className: "o-header__nav-list o-header__nav-list--right", "data-trackable": "user-nav" }, items.map((item, index) => {
39
+ var _a;
40
+ return (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
41
+ react_1.default.createElement("a", { className: "o-header__nav-link", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, item.label)));
42
+ })));
34
43
  };
35
44
  const MegaNav = ({ label, meganav, index }) => {
36
45
  const sections = meganav.find(({ component }) => component === 'sectionlist');
@@ -45,20 +54,29 @@ const SectionList = ({ title, data }) => {
45
54
  return (react_1.default.createElement("div", { className: "o-header__mega-column o-header__mega-column--subsections", "data-trackable": "sections" },
46
55
  react_1.default.createElement("div", { className: "o-header__mega-heading" }, title),
47
56
  react_1.default.createElement("div", { className: "o-header__mega-content" },
48
- react_1.default.createElement("ul", { className: "o-header__mega-list" }, data.map((column) => column.map((item, index) => (react_1.default.createElement("li", { className: "o-header__mega-item", key: `link-${index}` },
49
- react_1.default.createElement("a", Object.assign({ className: "o-header__mega-link", href: item.url }, utils_1.ariaSelected(item), { "data-trackable": "link" }), item.label)))))))));
57
+ react_1.default.createElement("ul", { className: "o-header__mega-list" }, data === null || data === void 0 ? void 0 : data.map((column) => column.map((item, index) => {
58
+ var _a;
59
+ return (react_1.default.createElement("li", { className: "o-header__mega-item", key: `link-${index}` },
60
+ react_1.default.createElement("a", Object.assign({ className: "o-header__mega-link", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined }, utils_1.ariaSelected(item), { "data-trackable": "link" }), item.label)));
61
+ }))))));
50
62
  };
51
63
  const ArticleList = ({ title, data }) => {
52
64
  return (react_1.default.createElement("div", { className: "o-header__mega-column o-header__mega-column--articles", "data-trackable": "popular" },
53
65
  react_1.default.createElement("div", { className: "o-header__mega-heading" }, title),
54
66
  react_1.default.createElement("div", { className: "o-header__mega-content" },
55
- react_1.default.createElement("ul", { className: "o-header__mega-list" }, data.map((item, index) => (react_1.default.createElement("li", { className: "o-header__mega-item", key: `link-${index}` },
56
- react_1.default.createElement("a", Object.assign({ className: "o-header__mega-link", href: item.url }, utils_1.ariaSelected(item), { "data-trackable": "link" }), item.label))))))));
67
+ react_1.default.createElement("ul", { className: "o-header__mega-list" }, data === null || data === void 0 ? void 0 : data.map((item, index) => {
68
+ var _a;
69
+ return (react_1.default.createElement("li", { className: "o-header__mega-item", key: `link-${index}` },
70
+ react_1.default.createElement("a", Object.assign({ className: "o-header__mega-link", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined }, utils_1.ariaSelected(item), { "data-trackable": "link" }), item.label)));
71
+ })))));
57
72
  };
58
73
  const UserActionsNav = (props) => {
59
74
  const userNavItems = props.data['navbar-right-anon'].items;
60
75
  return (react_1.default.createElement("div", { className: "o-header__row o-header__anon", "data-trackable": "header-anon" },
61
- react_1.default.createElement("ul", { className: "o-header__anon-list" }, userNavItems.map((item, index) => (react_1.default.createElement("li", { className: "o-header__anon-item", key: `link-${index}` },
62
- react_1.default.createElement("a", { className: "o-header__anon-link", href: item.url, "data-trackable": item.label }, item.label)))))));
76
+ react_1.default.createElement("ul", { className: "o-header__anon-list" }, userNavItems.map((item, index) => {
77
+ var _a;
78
+ return (react_1.default.createElement("li", { className: "o-header__anon-item", key: `link-${index}` },
79
+ react_1.default.createElement("a", { className: "o-header__anon-link", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, item.label)));
80
+ }))));
63
81
  };
64
82
  exports.UserActionsNav = UserActionsNav;
@@ -16,8 +16,11 @@ const SearchIconSticky = () => (react_1.default.createElement("a", { href: "#",
16
16
  react_1.default.createElement("span", { className: "o-header__top-link-label" }, "Search")));
17
17
  const Navigation = (props) => (react_1.default.createElement("div", { className: "o-header__top-takeover" },
18
18
  react_1.default.createElement("div", { className: "o-header__nav" },
19
- react_1.default.createElement("ul", { className: "o-header__nav-list o-header__nav-list--left", "data-trackable": "primary-nav" }, props.data.navbar.items.map((item, index) => (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
20
- react_1.default.createElement("a", { className: "o-header__nav-link o-header__nav-link--primary", href: item.url, "data-trackable": item.label, tabIndex: -1 }, item.label))))))));
19
+ react_1.default.createElement("ul", { className: "o-header__nav-list o-header__nav-list--left", "data-trackable": "primary-nav" }, props.data.navbar.items.map((item, index) => {
20
+ var _a;
21
+ return (react_1.default.createElement("li", { className: "o-header__nav-item", key: `link-${index}` },
22
+ react_1.default.createElement("a", { className: "o-header__nav-link o-header__nav-link--primary", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label, tabIndex: -1 }, item.label)));
23
+ })))));
21
24
  const Logo = () => (react_1.default.createElement("a", { className: "o-header__top-logo o-header__hide--L", "data-trackable": "logo", href: "/", title: "Go to Financial Times homepage", tabIndex: -1 },
22
25
  react_1.default.createElement("span", { className: "o-header__visually-hidden" }, "Financial Times")));
23
26
  const NavListRightAnonSticky = (props) => {
@@ -57,7 +60,7 @@ const NavListRightLoggedInSticky = (props) => {
57
60
  // - The sticky header renders either the `navbar-right-anon` data or the myFT component
58
61
  // - The normal header renders either the `navbar-right-anon` or the `navbar-right` data
59
62
  const TopColumnRightSticky = (props) => {
60
- let children = null;
63
+ let children = undefined;
61
64
  if (props.userIsLoggedIn) {
62
65
  children = react_1.default.createElement(NavListRightLoggedInSticky, Object.assign({}, props));
63
66
  }
@@ -18,10 +18,11 @@ const SubNavigationWrapper = (props) => (react_1.default.createElement("div", {
18
18
  react_1.default.createElement("div", { className: "o-header__subnav-content" }, props.children)),
19
19
  react_1.default.createElement("button", { className: "o-header__subnav-button o-header__subnav-button--left", title: "scroll left", "aria-label": "scroll left", "aria-hidden": "true", disabled: true }),
20
20
  react_1.default.createElement("button", { className: "o-header__subnav-button o-header__subnav-button--right", title: "scroll right", "aria-label": "scroll right", "aria-hidden": "true", disabled: true })))));
21
- const BreadCrumb = ({ items }) => (react_1.default.createElement("ol", { className: "o-header__subnav-list o-header__subnav-list--breadcrumb", "aria-label": "Breadcrumb", "data-trackable": "breadcrumb" }, items.map((item, index) => {
21
+ const BreadCrumb = ({ items }) => (react_1.default.createElement("ol", { className: "o-header__subnav-list o-header__subnav-list--breadcrumb", "aria-label": "Breadcrumb", "data-trackable": "breadcrumb" }, items === null || items === void 0 ? void 0 : items.map((item, index) => {
22
+ var _a;
22
23
  const selected = item.selected ? 'o-header__subnav-link--highlight' : '';
23
24
  return (react_1.default.createElement("li", { className: "o-header__subnav-item", key: `item-${index}` },
24
- react_1.default.createElement("a", Object.assign({ className: `o-header__subnav-link ${selected}`, href: item.url }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label)));
25
+ react_1.default.createElement("a", Object.assign({ className: `o-header__subnav-link ${selected}`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label)));
25
26
  })));
26
27
  const SubSections = ({ items, rightAlignment }) => {
27
28
  if (!items || items.length === 0) {
@@ -29,8 +30,9 @@ const SubSections = ({ items, rightAlignment }) => {
29
30
  }
30
31
  return (react_1.default.createElement("ul", { className: 'o-header__subnav-list o-header__subnav-list--children' +
31
32
  (rightAlignment ? ' o-header__subnav-list--right' : ''), "aria-label": rightAlignment ? 'Additional Sub Navigation' : 'Subsections', "data-trackable": "subsections" }, items.map((item, index) => {
33
+ var _a;
32
34
  const selected = item.selected ? 'o-header__subnav-link--highlight' : '';
33
35
  return (react_1.default.createElement("li", { className: "o-header__subnav-item", key: `item-${index}` },
34
- react_1.default.createElement("a", Object.assign({ className: `o-header__subnav-link ${selected}`, href: item.url }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label)));
36
+ react_1.default.createElement("a", Object.assign({ className: `o-header__subnav-link ${selected}`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined }, utils_1.ariaSelected(item), { "data-trackable": item.label }), item.label)));
35
37
  })));
36
38
  };
@@ -38,16 +38,18 @@ const TopColumnRightLoggedIn = (props) => {
38
38
  react_1.default.createElement(MyFt, { className: "" })));
39
39
  };
40
40
  const SignInLink = ({ item, variant, className }) => {
41
+ var _a;
41
42
  const setTabIndex = variant === 'sticky' ? { tabIndex: -1 } : null;
42
- return (react_1.default.createElement("a", Object.assign({ className: `o-header__top-link ${className}`, href: item.url, "data-trackable": item.label }, setTabIndex), item.label));
43
+ return (react_1.default.createElement("a", Object.assign({ className: `o-header__top-link ${className}`, href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, setTabIndex), item.label));
43
44
  };
44
45
  exports.SignInLink = SignInLink;
45
46
  const SubscribeButton = ({ item, variant, className }) => {
47
+ var _a;
46
48
  const setTabIndex = variant === 'sticky' ? { tabIndex: -1 } : null;
47
49
  return (react_1.default.createElement("a", Object.assign({ className: `o-header__top-button ${className}`,
48
50
  // Added as the result of a DAC audit. This will be confusing for users of voice activation software
49
51
  // as it looks like a button but behaves like a link without this role.
50
- role: "button", href: item.url, "data-trackable": item.label }, setTabIndex), item.label));
52
+ role: "button", href: (_a = item.url) !== null && _a !== void 0 ? _a : undefined, "data-trackable": item.label }, setTabIndex), item.label));
51
53
  };
52
54
  exports.SubscribeButton = SubscribeButton;
53
55
  const TopColumnRightAnon = ({ items, variant }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/dotcom-ui-header",
3
- "version": "7.1.1",
3
+ "version": "7.1.4",
4
4
  "description": "",
5
5
  "browser": "browser.js",
6
6
  "main": "component.js",
@@ -23,7 +23,7 @@
23
23
  "author": "",
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "@financial-times/dotcom-types-navigation": "^7.1.1",
26
+ "@financial-times/dotcom-types-navigation": "^7.1.4",
27
27
  "n-topic-search": "^4.0.0",
28
28
  "n-ui-foundations": "^9.0.0"
29
29
  },
@@ -14,7 +14,7 @@ export const DrawerParentItem = ({ item, idSuffix }: TDrawerParentItemProps) =>
14
14
  <div key={item.url} className="o-header__drawer-menu-toggle-wrapper">
15
15
  <a
16
16
  className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--parent`}
17
- href={item.url}
17
+ href={item.url ?? undefined}
18
18
  {...ariaSelected(item)}
19
19
  data-trackable={item.label}
20
20
  >
@@ -33,13 +33,13 @@ export const DrawerParentItem = ({ item, idSuffix }: TDrawerParentItemProps) =>
33
33
  id={`o-header-drawer-child-${idSuffix}`}
34
34
  data-trackable="sub-level"
35
35
  >
36
- {(item.submenu.items as TNavMenuItem[]).map((item) => {
36
+ {(item.submenu?.items as TNavMenuItem[]).map((item) => {
37
37
  const selected = item.selected ? 'selected' : 'unselected'
38
38
  return (
39
39
  <li key={item.url} className="o-header__drawer-menu-item">
40
40
  <a
41
41
  className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--child`}
42
- href={item.url}
42
+ href={item.url ?? undefined}
43
43
  data-trackable={item.label}
44
44
  {...ariaSelected(item)}
45
45
  >
@@ -58,7 +58,7 @@ export const DrawerSingleItem = (item: TNavMenuItem) => {
58
58
  return (
59
59
  <a
60
60
  className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected}`}
61
- href={item.url}
61
+ href={item.url ?? undefined}
62
62
  data-trackable={item.label}
63
63
  {...ariaSelected(item)}
64
64
  >
@@ -72,7 +72,7 @@ export const DrawerSpecialItem = (item: TNavMenuItem) => {
72
72
  return (
73
73
  <a
74
74
  className={`o-header__drawer-menu-link o-header__drawer-menu-link--${selected} o-header__drawer-menu-link--secondary`}
75
- href={item.url}
75
+ href={item.url ?? undefined}
76
76
  data-trackable={item.label}
77
77
  {...ariaSelected(item)}
78
78
  >
@@ -102,7 +102,7 @@ const SectionPrimary = (props: TNavMenuItem) => {
102
102
  return (
103
103
  <React.Fragment>
104
104
  <li className="o-header__drawer-menu-item o-header__drawer-menu-item--heading">{props.label}</li>
105
- {(props.submenu.items as TNavMenuItem[]).map((item, index) => (
105
+ {(props.submenu?.items as TNavMenuItem[]).map((item, index) => (
106
106
  <li key={item.url} className="o-header__drawer-menu-item">
107
107
  {item.submenu ? (
108
108
  <DrawerParentItem item={item} idSuffix={`${index}`} />
@@ -118,7 +118,7 @@ const SectionPrimary = (props: TNavMenuItem) => {
118
118
  const SectionSecondary = (props: TNavMenuItem) => (
119
119
  <React.Fragment>
120
120
  <li className="o-header__drawer-menu-item o-header__drawer-menu-item--heading">{props.label}</li>
121
- {(props.submenu.items as TNavMenuItem[]).map((item, index) => (
121
+ {(props.submenu?.items as TNavMenuItem[]).map((item, index) => (
122
122
  <li key={item.url} className="o-header__drawer-menu-item">
123
123
  {item.submenu ? (
124
124
  <DrawerParentItem item={item} idSuffix={'inner' + index} />
@@ -132,7 +132,7 @@ const SectionSecondary = (props: TNavMenuItem) => (
132
132
 
133
133
  const SectionTertiary = (props: TNavMenuItem) => (
134
134
  <React.Fragment>
135
- {(props.submenu.items as TNavMenuItem[]).map((item, index) => {
135
+ {(props.submenu?.items as TNavMenuItem[]).map((item, index) => {
136
136
  const divideItem = index === 0 ? 'o-header__drawer-menu-item--divide' : ''
137
137
 
138
138
  return (
@@ -149,7 +149,7 @@ const UserMenu = (props: TNavMenu) => (
149
149
  <ul className="o-header__drawer-menu-list">
150
150
  {props.items.map((item) => (
151
151
  <li key={item.url} className="o-header__drawer-menu-item">
152
- <a className="o-header__drawer-menu-link" href={item.url} data-trackable={item.label}>
152
+ <a className="o-header__drawer-menu-link" href={item.url ?? undefined} data-trackable={item.label}>
153
153
  {item.label}
154
154
  </a>
155
155
  </li>
@@ -12,7 +12,7 @@ const MobileNav = (props: THeaderProps) => {
12
12
  // Only display navigation on pages which are included in this menu
13
13
  const targetUrls = props.data['navbar-simple'].items.map((item) => item.url)
14
14
 
15
- return targetUrls.includes(props.data.currentPath) ? (
15
+ return props.data.currentPath && targetUrls.includes(props.data.currentPath) ? (
16
16
  <NavMobile items={props.data['navbar-simple'].items} />
17
17
  ) : null
18
18
  }
@@ -30,7 +30,7 @@ const NavMobile = ({ items }: { items: TNavMenuItem[] }) => {
30
30
  <li className="o-header__nav-item" key={`link-${index}`}>
31
31
  <a
32
32
  className="o-header__nav-link o-header__nav-link--primary"
33
- href={item.url}
33
+ href={item.url ?? undefined}
34
34
  {...ariaSelected(item)}
35
35
  data-trackable={item.label}
36
36
  >
@@ -61,7 +61,7 @@ const NavListLeft = (props: THeaderProps) => (
61
61
  <li className="o-header__nav-item" key={`link-${index}`}>
62
62
  <a
63
63
  className="o-header__nav-link o-header__nav-link--primary"
64
- href={item.url}
64
+ href={item.url ?? undefined}
65
65
  id={`o-header-link-${index}`}
66
66
  {...ariaSelected(item)}
67
67
  data-trackable={item.label}
@@ -85,7 +85,7 @@ const NavListRightLoggedIn = ({ items }: { items: TNavMenuItem[] }) => {
85
85
  <ul className="o-header__nav-list o-header__nav-list--right" data-trackable="user-nav">
86
86
  {items.map((item, index) => (
87
87
  <li className="o-header__nav-item" key={`link-${index}`}>
88
- <a className="o-header__nav-link" href={item.url} data-trackable={item.label}>
88
+ <a className="o-header__nav-link" href={item.url ?? undefined} data-trackable={item.label}>
89
89
  {item.label}
90
90
  </a>
91
91
  </li>
@@ -123,12 +123,12 @@ const SectionList = ({ title, data }: INavMeganavSections) => {
123
123
  <div className="o-header__mega-heading">{title}</div>
124
124
  <div className="o-header__mega-content">
125
125
  <ul className="o-header__mega-list">
126
- {data.map((column) =>
126
+ {data?.map((column) =>
127
127
  column.map((item, index) => (
128
128
  <li className="o-header__mega-item" key={`link-${index}`}>
129
129
  <a
130
130
  className="o-header__mega-link"
131
- href={item.url}
131
+ href={item.url ?? undefined}
132
132
  {...ariaSelected(item)}
133
133
  data-trackable="link"
134
134
  >
@@ -149,11 +149,11 @@ const ArticleList = ({ title, data }: INavMeganavArticles) => {
149
149
  <div className="o-header__mega-heading">{title}</div>
150
150
  <div className="o-header__mega-content">
151
151
  <ul className="o-header__mega-list">
152
- {data.map((item, index) => (
152
+ {data?.map((item, index) => (
153
153
  <li className="o-header__mega-item" key={`link-${index}`}>
154
154
  <a
155
155
  className="o-header__mega-link"
156
- href={item.url}
156
+ href={item.url ?? undefined}
157
157
  {...ariaSelected(item)}
158
158
  data-trackable="link"
159
159
  >
@@ -175,7 +175,7 @@ const UserActionsNav = (props: THeaderProps) => {
175
175
  <ul className="o-header__anon-list">
176
176
  {userNavItems.map((item, index) => (
177
177
  <li className="o-header__anon-item" key={`link-${index}`}>
178
- <a className="o-header__anon-link" href={item.url} data-trackable={item.label}>
178
+ <a className="o-header__anon-link" href={item.url ?? undefined} data-trackable={item.label}>
179
179
  {item.label}
180
180
  </a>
181
181
  </li>
@@ -48,7 +48,7 @@ const Navigation = (props: THeaderProps) => (
48
48
  <li className="o-header__nav-item" key={`link-${index}`}>
49
49
  <a
50
50
  className="o-header__nav-link o-header__nav-link--primary"
51
- href={item.url}
51
+ href={item.url ?? undefined}
52
52
  data-trackable={item.label}
53
53
  tabIndex={-1}
54
54
  >
@@ -144,7 +144,7 @@ const NavListRightLoggedInSticky = (props: THeaderProps) => {
144
144
  // - The sticky header renders either the `navbar-right-anon` data or the myFT component
145
145
  // - The normal header renders either the `navbar-right-anon` or the `navbar-right` data
146
146
  const TopColumnRightSticky = (props: THeaderProps) => {
147
- let children = null
147
+ let children: JSX.Element | undefined = undefined
148
148
 
149
149
  if (props.userIsLoggedIn) {
150
150
  children = <NavListRightLoggedInSticky {...props} />
@@ -17,7 +17,8 @@ const SubNavigationWrapper = (props) => (
17
17
  role="navigation"
18
18
  aria-label="Sub navigation"
19
19
  data-o-header-subnav
20
- data-trackable="header-subnav">
20
+ data-trackable="header-subnav"
21
+ >
21
22
  <div className="o-header__container">
22
23
  <div className="o-header__subnav-wrap-outside">
23
24
  <div className="o-header__subnav-wrap-inside" data-o-header-subnav-wrapper>
@@ -43,21 +44,23 @@ const SubNavigationWrapper = (props) => (
43
44
  </div>
44
45
  )
45
46
 
46
- const BreadCrumb = ({ items }: { items: TNavMenuItem[] }) => (
47
+ const BreadCrumb = ({ items }: { items?: TNavMenuItem[] }) => (
47
48
  <ol
48
49
  className="o-header__subnav-list o-header__subnav-list--breadcrumb"
49
50
  aria-label="Breadcrumb"
50
- data-trackable="breadcrumb">
51
- {items.map((item, index) => {
51
+ data-trackable="breadcrumb"
52
+ >
53
+ {items?.map((item, index) => {
52
54
  const selected = item.selected ? 'o-header__subnav-link--highlight' : ''
53
55
 
54
56
  return (
55
57
  <li className="o-header__subnav-item" key={`item-${index}`}>
56
58
  <a
57
59
  className={`o-header__subnav-link ${selected}`}
58
- href={item.url}
60
+ href={item.url ?? undefined}
59
61
  {...ariaSelected(item)}
60
- data-trackable={item.label}>
62
+ data-trackable={item.label}
63
+ >
61
64
  {item.label}
62
65
  </a>
63
66
  </li>
@@ -66,7 +69,7 @@ const BreadCrumb = ({ items }: { items: TNavMenuItem[] }) => (
66
69
  </ol>
67
70
  )
68
71
 
69
- const SubSections = ({ items, rightAlignment }: { items: TNavMenuItem[]; rightAlignment?: boolean }) => {
72
+ const SubSections = ({ items, rightAlignment }: { items?: TNavMenuItem[]; rightAlignment?: boolean }) => {
70
73
  if (!items || items.length === 0) {
71
74
  return null
72
75
  }
@@ -78,7 +81,8 @@ const SubSections = ({ items, rightAlignment }: { items: TNavMenuItem[]; rightAl
78
81
  (rightAlignment ? ' o-header__subnav-list--right' : '')
79
82
  }
80
83
  aria-label={rightAlignment ? 'Additional Sub Navigation' : 'Subsections'}
81
- data-trackable="subsections">
84
+ data-trackable="subsections"
85
+ >
82
86
  {items.map((item, index) => {
83
87
  const selected = item.selected ? 'o-header__subnav-link--highlight' : ''
84
88
 
@@ -86,9 +90,10 @@ const SubSections = ({ items, rightAlignment }: { items: TNavMenuItem[]; rightAl
86
90
  <li className="o-header__subnav-item" key={`item-${index}`}>
87
91
  <a
88
92
  className={`o-header__subnav-link ${selected}`}
89
- href={item.url}
93
+ href={item.url ?? undefined}
90
94
  {...ariaSelected(item)}
91
- data-trackable={item.label}>
95
+ data-trackable={item.label}
96
+ >
92
97
  {item.label}
93
98
  </a>
94
99
  </li>
@@ -118,7 +118,7 @@ const SignInLink = ({
118
118
  return (
119
119
  <a
120
120
  className={`o-header__top-link ${className}`}
121
- href={item.url}
121
+ href={item.url ?? undefined}
122
122
  data-trackable={item.label}
123
123
  {...setTabIndex}
124
124
  >
@@ -142,7 +142,7 @@ const SubscribeButton = ({
142
142
  // Added as the result of a DAC audit. This will be confusing for users of voice activation software
143
143
  // as it looks like a button but behaves like a link without this role.
144
144
  role="button"
145
- href={item.url}
145
+ href={item.url ?? undefined}
146
146
  data-trackable={item.label}
147
147
  {...setTabIndex}
148
148
  >