@ons/design-system 45.0.0 → 45.0.1

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.
@@ -0,0 +1,55 @@
1
+ class AbortableFetch {
2
+ constructor(url, options) {
3
+ this.url = url;
4
+ this.options = options;
5
+ this.controller = new window.AbortController();
6
+ this.status = 'UNSENT';
7
+ }
8
+
9
+ send() {
10
+ this.status = 'LOADING';
11
+
12
+ return new Promise((resolve, reject) => {
13
+ abortableFetch(this.url, { signal: this.controller.signal, ...this.options })
14
+ .then(response => {
15
+ if (response.status >= 200 && response.status < 300) {
16
+ this.status = 'DONE';
17
+ resolve(response);
18
+ } else if (response.status >= 400) {
19
+ this.status = 'DONE';
20
+ resolve(response);
21
+ } else {
22
+ this.status = 'DONE';
23
+ reject(response);
24
+ }
25
+ })
26
+ .catch(error => {
27
+ this.status = 'undefined';
28
+ reject(error);
29
+ });
30
+ });
31
+ }
32
+
33
+ abort() {
34
+ this.controller.abort();
35
+ }
36
+ }
37
+
38
+ function abortableFetch(url, options) {
39
+ return window
40
+ .fetch(url, options)
41
+ .then(response => {
42
+ if (response) {
43
+ return response;
44
+ } else {
45
+ const error = new Error(response.status);
46
+ error.response = response;
47
+ throw error;
48
+ }
49
+ })
50
+ .catch(error => {
51
+ throw error;
52
+ });
53
+ }
54
+
55
+ export default (url, options) => new AbortableFetch(url, options);
@@ -0,0 +1,70 @@
1
+ import domready from './domready';
2
+
3
+ export let trackEvent = (event, data) => {
4
+ console.log(`[Analytics disabled] Event: ${event}`); // eslint-disable-line no-console
5
+ console.log(data); // eslint-disable-line no-console
6
+ };
7
+
8
+ if (typeof window.ga !== 'undefined') {
9
+ trackEvent = (evt, data) => {
10
+ window.ga(evt, data);
11
+ };
12
+ }
13
+
14
+ export const trackElement = el => {
15
+ return trackEvent('send', {
16
+ hitType: 'event',
17
+ eventCategory: el.getAttribute('data-ga-category') || '',
18
+ eventAction: el.getAttribute('data-ga-action') || '',
19
+ eventLabel: el.getAttribute('data-ga-label') || '',
20
+ });
21
+ };
22
+
23
+ const isVisible = el => {
24
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
25
+ };
26
+
27
+ export default function initAnalytics() {
28
+ let trackVisibleElements = [...document.querySelectorAll('[data-ga=visible]')];
29
+
30
+ const interval = window.setInterval(() => {
31
+ trackVisibleElements = trackVisibleElements.filter(element => {
32
+ return isVisible(element) ? trackElement(element) && false : true;
33
+ });
34
+ if (trackVisibleElements.length === 0) {
35
+ window.clearInterval(interval);
36
+ }
37
+ }, 200);
38
+
39
+ [...document.querySelectorAll('[data-ga=error]')].map(trackElement);
40
+
41
+ document.body.addEventListener('click', ({ target }) => {
42
+ if (target.getAttribute('data-ga') === 'click') {
43
+ trackElement(target);
44
+ }
45
+ });
46
+
47
+ const afterPrint = () => {
48
+ return trackEvent('send', {
49
+ hitType: 'event',
50
+ eventCategory: 'Print Intent',
51
+ eventAction: 'Print Intent',
52
+ eventLabel: window.location.pathname
53
+ .split('/')
54
+ .slice(-3)
55
+ .join('/'),
56
+ });
57
+ };
58
+
59
+ if (window.matchMedia) {
60
+ const mediaQueryList = window.matchMedia('print');
61
+ mediaQueryList.addListener(function(mql) {
62
+ if (!mql.matches) {
63
+ afterPrint();
64
+ }
65
+ });
66
+ }
67
+ window.onafterprint = afterPrint;
68
+ }
69
+
70
+ domready(initAnalytics);
@@ -0,0 +1,182 @@
1
+ export const DEFAULT_COOKIE_CONSENT = {
2
+ essential: true,
3
+ settings: false,
4
+ usage: false,
5
+ campaigns: false,
6
+ };
7
+
8
+ export const COOKIE_CATEGORIES = {
9
+ RH_SESSION: 'essential',
10
+ session: 'essential',
11
+ ons_cookie_policy: 'essential',
12
+ ons_cookie_message_displayed: 'essential',
13
+ _ga: 'usage',
14
+ _gid: 'usage',
15
+ _gat: 'usage',
16
+ _use_hitbox: 'campaigns',
17
+ VISITOR_INFO1_LIVE: 'campaigns',
18
+ _fbp: 'campaigns',
19
+ COOKIE_SUPPORT: 'essential',
20
+ GUEST_LANGUAGE_ID: 'essential',
21
+ JSESSIONID: 'essential',
22
+ ID: 'essential',
23
+ COMPANY_ID: 'essential',
24
+ USER_UUID: 'essential',
25
+ LFR_SESSION_STATE_: 'essential',
26
+ csfcfc: 'essential',
27
+ };
28
+
29
+ export function cookie(name, value, options) {
30
+ if (typeof value !== 'undefined') {
31
+ if (value === false || value === null) {
32
+ return setCookie(name, '', { days: -1 });
33
+ } else {
34
+ if (typeof options === 'undefined') {
35
+ options = { days: 30 };
36
+ }
37
+ return setCookie(name, value, options);
38
+ }
39
+ } else {
40
+ return getCookie(name);
41
+ }
42
+ }
43
+
44
+ export function setDefaultConsentCookie() {
45
+ const defaultConsentCookie = JSON.stringify(DEFAULT_COOKIE_CONSENT).replace(/"/g, "'");
46
+ setCookie('ons_cookie_policy', defaultConsentCookie, { days: 365 });
47
+ }
48
+
49
+ export function approveAllCookieTypes() {
50
+ let approvedConsent = {
51
+ essential: true,
52
+ settings: true,
53
+ usage: true,
54
+ campaigns: true,
55
+ };
56
+
57
+ setCookie('ons_cookie_policy', JSON.stringify(approvedConsent).replace(/"/g, "'"), { days: 365 });
58
+ }
59
+
60
+ export function getConsentCookie() {
61
+ const consentCookie = cookie('ons_cookie_policy');
62
+ let consentCookieObj;
63
+
64
+ if (consentCookie) {
65
+ consentCookieObj = JSON.parse(consentCookie.replace(/'/g, '"'));
66
+
67
+ if (typeof consentCookieObj !== 'object' && consentCookieObj !== null) {
68
+ consentCookieObj = JSON.parse(consentCookieObj.replace(/'/g, '"'));
69
+ }
70
+ } else {
71
+ return null;
72
+ }
73
+ return consentCookieObj;
74
+ }
75
+
76
+ export function setConsentCookie(options) {
77
+ const domain = getDomain(document.domain);
78
+
79
+ let cookieConsent = getConsentCookie();
80
+ if (!cookieConsent) {
81
+ cookieConsent = JSON.parse(JSON.stringify(DEFAULT_COOKIE_CONSENT).replace(/'/g, '"'));
82
+ }
83
+ for (let cookieType in options) {
84
+ cookieConsent[cookieType] = options[cookieType];
85
+ if (!options[cookieType]) {
86
+ for (let cookies in COOKIE_CATEGORIES) {
87
+ if (COOKIE_CATEGORIES[cookies] === cookieType) {
88
+ cookie(cookies, null);
89
+ if (cookie(cookies)) {
90
+ const cookieString = cookies + '=; expires=' + new Date() + '; domain=' + domain + '; path=/';
91
+ document.cookie = cookieString;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ setCookie('ons_cookie_policy', JSON.stringify(cookieConsent).replace(/"/g, "'"), { days: 365 });
98
+ }
99
+
100
+ export function checkConsentCookieCategory(cookieName, cookieCategory) {
101
+ let currentConsentCookie = getConsentCookie();
102
+ if (!currentConsentCookie && COOKIE_CATEGORIES[cookieName]) {
103
+ return true;
104
+ }
105
+
106
+ currentConsentCookie = getConsentCookie();
107
+ try {
108
+ return currentConsentCookie[cookieCategory];
109
+ } catch (e) {
110
+ console.error(e);
111
+ return false;
112
+ }
113
+ }
114
+
115
+ export function checkConsentCookie(cookieName, cookieValue) {
116
+ // If we're setting the consent, session or RH_SESSION cookie OR deleting a cookie, allow by default
117
+ if (cookieName === 'ons_cookie_policy' || cookieValue === null || cookieValue === false) {
118
+ return true;
119
+ }
120
+
121
+ if (COOKIE_CATEGORIES[cookieName]) {
122
+ const cookieCategory = COOKIE_CATEGORIES[cookieName];
123
+ return checkConsentCookieCategory(cookieName, cookieCategory);
124
+ } else {
125
+ // Deny the cookie if it is not known to us
126
+ return false;
127
+ }
128
+ }
129
+
130
+ export function setCookie(name, value, options) {
131
+ const domain = getDomain(document.domain);
132
+ let setDomain = '';
133
+
134
+ if (domain.indexOf('localhost') === -1) {
135
+ setDomain = '; domain=' + domain;
136
+ }
137
+
138
+ if (checkConsentCookie(name, value)) {
139
+ if (typeof options === 'undefined') {
140
+ options = {};
141
+ }
142
+
143
+ let cookieString = name + '=' + value + setDomain + '; path=/';
144
+ if (options.days) {
145
+ const date = new Date();
146
+ date.setTime(date.getTime() + options.days * 24 * 60 * 60 * 1000);
147
+ cookieString = cookieString + '; expires=' + date.toGMTString();
148
+ }
149
+ if (document.location.protocol === 'https:') {
150
+ cookieString = cookieString + '; Secure';
151
+ }
152
+ document.cookie = cookieString;
153
+ }
154
+ }
155
+
156
+ export function getCookie(name) {
157
+ const nameEQ = name + '=';
158
+ const cookies = document.cookie.split(';');
159
+ for (let i = 0, len = cookies.length; i < len; i++) {
160
+ let cookie = cookies[i];
161
+ while (cookie.charAt(0) === ' ') {
162
+ cookie = cookie.substring(1, cookie.length);
163
+ }
164
+ if (cookie.indexOf(nameEQ) === 0) {
165
+ return decodeURIComponent(cookie.substring(nameEQ.length));
166
+ }
167
+ }
168
+ return null;
169
+ }
170
+
171
+ export function getDomain(domain) {
172
+ let i = 0,
173
+ domainName = domain,
174
+ p = domainName.split('.'),
175
+ s = '_gd' + new Date().getTime();
176
+ while (i < p.length - 1 && document.cookie.indexOf(s + '=' + s) == -1) {
177
+ domainName = p.slice(-1 - ++i).join('.');
178
+ document.cookie = s + '=' + s + ';domain=' + domainName + ';';
179
+ }
180
+ document.cookie = s + '=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain=' + domainName + ';';
181
+ return domainName;
182
+ }
@@ -0,0 +1,13 @@
1
+ import domready from './domready';
2
+
3
+ async function cookiesSettings() {
4
+ const cookiesSettings = [...document.querySelectorAll('[data-module=cookie-settings]')];
5
+ if (cookiesSettings.length) {
6
+ const CookiesSettings = (await import('./cookies-settings')).default;
7
+ cookiesSettings.forEach(form => {
8
+ new CookiesSettings(form);
9
+ });
10
+ }
11
+ }
12
+
13
+ domready(cookiesSettings);
@@ -0,0 +1,105 @@
1
+ import { unset } from 'lodash';
2
+
3
+ import { cookie, setConsentCookie, setCookie, setDefaultConsentCookie } from './cookies-functions';
4
+
5
+ export default class CookiesSettings {
6
+ constructor(component) {
7
+ this.component = component;
8
+ this.returnLink = document.querySelector('.ons-js-return-link');
9
+ this.confirmationMessage = document.querySelector('.ons-cookies-confirmation-message');
10
+ this.cookiesBanner = document.querySelector('.ons-cookies-banner');
11
+
12
+ this.component.addEventListener('submit', this.submitSettingsForm.bind(this));
13
+ this.returnLink.addEventListener('click', this.goBackToPrevPage.bind(this));
14
+
15
+ this.setInitialFormValues();
16
+ }
17
+
18
+ setInitialFormValues() {
19
+ if (!cookie('ons_cookie_policy')) {
20
+ setDefaultConsentCookie();
21
+ }
22
+
23
+ const currentConsentCookie = cookie('ons_cookie_policy');
24
+ let currentConsentCookieJSON = JSON.parse(currentConsentCookie.replace(/'/g, '"'));
25
+
26
+ try {
27
+ unset(currentConsentCookieJSON, 'essential');
28
+ } catch (e) {
29
+ console.error(e);
30
+ }
31
+
32
+ for (let cookieType in currentConsentCookieJSON) {
33
+ let radioButton;
34
+
35
+ if (currentConsentCookieJSON[cookieType]) {
36
+ radioButton = document.querySelector('input[name=cookies-' + cookieType + '][value=on]');
37
+ } else {
38
+ radioButton = document.querySelector('input[name=cookies-' + cookieType + '][value=off]');
39
+ }
40
+
41
+ radioButton.checked = true;
42
+ }
43
+ }
44
+
45
+ submitSettingsForm(event) {
46
+ event.preventDefault();
47
+
48
+ if (!cookie('ons_cookie_message_displayed')) {
49
+ setCookie('ons_cookie_message_displayed', true, { days: 365 });
50
+ }
51
+
52
+ const formInputs = event.target.getElementsByTagName('input');
53
+ let options = {};
54
+
55
+ for (let i = 0; i < formInputs.length; i++) {
56
+ const input = formInputs[i];
57
+ if (input.checked) {
58
+ const name = input.name.replace('cookies-', '');
59
+ const value = input.value === 'on' ? true : false;
60
+
61
+ options[name] = value;
62
+
63
+ if (name === 'usage' && value === true) {
64
+ if (typeof loadGTM != 'undefined') {
65
+ loadGTM();
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ setConsentCookie(options);
72
+
73
+ this.showConfirmationMessage();
74
+ this.hideCookiesBanner();
75
+
76
+ return false;
77
+ }
78
+
79
+ showConfirmationMessage() {
80
+ this.confirmationMessage.classList.remove('ons-u-d-no');
81
+ document.body.scrollTop = document.documentElement.scrollTop = 0;
82
+ this.setConfirmationMessageAttributes();
83
+ }
84
+
85
+ hideCookiesBanner() {
86
+ if (this.cookiesBanner) {
87
+ this.cookiesBanner.style.display = 'none';
88
+ }
89
+ }
90
+
91
+ setConfirmationMessageAttributes() {
92
+ this.confirmationMessage.setAttribute('role', 'alert');
93
+ if (document.referrer != '') {
94
+ this.confirmationMessage.setAttribute('autofocus', 'autofocus');
95
+ this.confirmationMessage.setAttribute('tabindex', '-1');
96
+ this.confirmationMessage.focus();
97
+ } else {
98
+ this.returnLink.style.display = 'none';
99
+ }
100
+ }
101
+
102
+ goBackToPrevPage() {
103
+ window.history.back();
104
+ }
105
+ }
package/js/domready.js ADDED
@@ -0,0 +1,17 @@
1
+ let callbacks = [];
2
+
3
+ const onReady = () => {
4
+ callbacks.forEach(fn => fn.call());
5
+ callbacks = [];
6
+ window.onsDOMReady = true;
7
+ };
8
+
9
+ export default function ready(fn) {
10
+ if (document.readyState === 'loading') {
11
+ callbacks.push(fn);
12
+ } else {
13
+ fn.call();
14
+ }
15
+ }
16
+
17
+ document.addEventListener('DOMContentLoaded', onReady);
package/js/fetch.js ADDED
@@ -0,0 +1,19 @@
1
+ export function checkStatus(response) {
2
+ if (response.status >= 200 && response.status < 300) {
3
+ return response;
4
+ } else {
5
+ const error = new Error(response.statusText);
6
+ error.response = response;
7
+ throw error;
8
+ }
9
+ }
10
+
11
+ export default function(url, options) {
12
+ return window
13
+ .fetch(url, {
14
+ method: 'GET',
15
+ credentials: 'include',
16
+ ...options,
17
+ })
18
+ .then(checkStatus);
19
+ }
@@ -0,0 +1,13 @@
1
+ import domready from './domready';
2
+
3
+ async function initialise() {
4
+ const links = [...document.getElementsByClassName('ons-js-inpagelink')];
5
+
6
+ if (links.length) {
7
+ const inPageLinks = (await import('./inpagelink')).default;
8
+
9
+ inPageLinks(links);
10
+ }
11
+ }
12
+
13
+ domready(initialise);
@@ -0,0 +1,31 @@
1
+ export default function inPageLinks(links) {
2
+ if (document.getElementById('patternlib-page__example') === null) {
3
+ links.forEach(link => {
4
+ const id = link.getAttribute('href').replace('#', '');
5
+
6
+ link.addEventListener('click', event => {
7
+ event.preventDefault();
8
+ focusOnInput(id);
9
+ });
10
+ });
11
+ }
12
+ }
13
+
14
+ function focusOnInput(id) {
15
+ const container = document.getElementById(id);
16
+ container.scrollIntoView();
17
+
18
+ const input = [
19
+ ...container.getElementsByTagName('INPUT'),
20
+ ...container.getElementsByTagName('TEXTAREA'),
21
+ ...container.getElementsByTagName('SELECT'),
22
+ ].filter(input => {
23
+ const type = input.getAttribute('type');
24
+
25
+ return type !== 'readonly' && type !== 'hidden';
26
+ })[0];
27
+
28
+ if (input && input.getAttribute('tabindex') !== '-1') {
29
+ input.focus();
30
+ }
31
+ }
package/js/main.js ADDED
@@ -0,0 +1,27 @@
1
+ import './inpagelink.dom';
2
+ import './print-button';
3
+ import './cookies-settings.dom';
4
+ import '../components/mutually-exclusive/mutually-exclusive.dom';
5
+ import '../components/textarea/textarea.dom';
6
+ import '../components/password/password.dom';
7
+ import '../components/tabs/tabs.dom';
8
+ import '../components/table-of-contents/toc.dom';
9
+ import '../components/collapsible/collapsible.dom';
10
+ import '../components/table/scrollable-table.dom';
11
+ import '../components/table/sortable-table.dom';
12
+ import '../components/header/header-nav.dom';
13
+ import '../components/access-code/uac.dom';
14
+ import '../components/relationships/relationships.dom';
15
+ import '../components/checkboxes/checkboxes.dom';
16
+ import '../components/radios/radios.dom';
17
+ import '../components/autosuggest/autosuggest.dom';
18
+ import '../components/address-input/autosuggest.address.dom';
19
+ import '../components/input/character-check.dom';
20
+ import '../components/cookies-banner/cookies-banner.dom';
21
+ import '../components/button/button.dom';
22
+ import '../components/reply/reply.dom';
23
+ import '../components/skip-to-content/skip-to-content.dom';
24
+ import '../components/download-resources/download-resources';
25
+ import '../components/select/select';
26
+ import '../components/modal/modal.dom';
27
+ import '../components/timeout-modal/timeout.dom';
@@ -0,0 +1,9 @@
1
+ // This must be included for IE support
2
+ import 'core-js';
3
+ //import 'regenerator-runtime/runtime';
4
+ import 'mdn-polyfills/CustomEvent';
5
+ import 'mdn-polyfills/Node.prototype.append';
6
+ import 'mdn-polyfills/Node.prototype.remove';
7
+ import 'mdn-polyfills/Element.prototype.closest';
8
+ import 'whatwg-fetch';
9
+ import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
@@ -0,0 +1,16 @@
1
+ import domready from './domready';
2
+
3
+ export default function addEventListeners() {
4
+ const buttons = [...document.querySelectorAll('.ons-js-print-btn')];
5
+
6
+ buttons.forEach(button => {
7
+ button.addEventListener('click', handleClick);
8
+ button.classList.remove('ons-u-d-no');
9
+ });
10
+ }
11
+
12
+ function handleClick() {
13
+ window.print();
14
+ }
15
+
16
+ domready(addEventListeners);
@@ -0,0 +1,242 @@
1
+ {% from "components/skip-to-content/_macro.njk" import onsSkipToContent %}
2
+ {% from "components/header/_macro.njk" import onsHeader %}
3
+ {% from "components/footer/_macro.njk" import onsFooter %}
4
+
5
+ {% set currentLanguageISOCode = "en" %}
6
+
7
+ {% if pageConfig is defined and pageConfig and pageConfig.language is defined and pageConfig.language and pageConfig.language.languages is defined and pageConfig.language.languages %}
8
+ {% set currentLanguage = pageConfig.language.languages | selectattr("current") | first %}
9
+ {% set currentLanguageISOCode = currentLanguage.ISOCode %}
10
+ {% set otherLanguage = pageConfig.language.languages | rejectattr("current") | first %}
11
+ {% set otherLanguageISOCode = otherLanguage.ISOCode %}
12
+ {% endif %}
13
+
14
+ {# Meta icons #}
15
+ {% if pageConfig is defined and pageConfig and pageConfig.theme is defined and pageConfig.theme %}
16
+ {% set metaicons = pageConfig.theme + "/" + currentLanguageISOCode + "/" %}
17
+ {% else %}
18
+ {% set metaicons = "" %}
19
+ {% endif %}
20
+
21
+ {% set pageColNumber = pageConfig.pageColNumber | default("8") %}
22
+
23
+ {% if pageConfig.cdn is defined and pageConfig.cdn or release_version is defined and release_version %}
24
+ {# Production #}
25
+ {% set cdn_url = (pageConfig.cdn.url if pageConfig.cdn is defined and pageConfig.cdn and pageConfig.cdn.url is defined and pageConfig.cdn.url) or "https://cdn.ons.gov.uk/sdc/design-system" %}
26
+ {% set slash = "" if cdn_url | last == "/" else "/" %}
27
+ {% set assetsURL = cdn_url + slash + ((pageConfig.cdn.version if pageConfig.cdn is defined and pageConfig.cdn and pageConfig.cdn.version is defined and pageConfig.cdn.version) or release_version) %}
28
+ {% elif pageInfo is defined and pageInfo and pageInfo.version is defined and pageInfo.version %}
29
+ {# Prototype kits #}
30
+ {% set assetsURL = "/" + pageInfo.version %}
31
+ {% elif pageConfig.assetsURL is defined and pageConfig.assetsURL %}
32
+ {# Runner Dev #}
33
+ {% set assetsURL = pageConfig.assetsURL %}
34
+ {% else %}
35
+ {# Development #}
36
+ {% set assetsURL = "" %}
37
+ {% endif %}
38
+
39
+ {% if pageConfig is defined and pageConfig and pageConfig.title is defined and pageConfig.title %}
40
+ {% set page_title = pageConfig.title %}
41
+ {% elif pageInfo is defined and pageInfo and pageInfo.title is defined and pageInfo.title %}
42
+ {% set page_title = pageInfo.title %}
43
+ {% else %}
44
+ {% set page_title = "ONS Design System" %}
45
+ {% endif %}
46
+
47
+ <!doctype html>
48
+ <html lang="{{ currentLanguageISOCode }}">
49
+ <head>
50
+ <meta charset="utf-8">
51
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
52
+ <meta name="viewport" content="width=device-width, initial-scale=1">
53
+ <title>{{ page_title }}</title>
54
+ <link rel="stylesheet" href="{{ assetsURL }}/css/{{ pageConfig.theme | default('main') }}.css">
55
+ <link rel="stylesheet" media="print" href="{{ assetsURL }}/css/print.css">
56
+ <meta name="theme-color" content="{% if pageConfig.theme == 'census' %}#902082{% else %}#206095{% endif %}"/>
57
+
58
+ {% if pageConfig.headMeta is defined and pageConfig.headMeta %}
59
+
60
+ {% if pageConfig.headMeta.description is defined and pageConfig.headMeta.description or pageConfig.description is defined and pageConfig.description %}
61
+ <meta name="description" content="{{ pageConfig.headMeta.description | default(pageConfig.description) }}">
62
+ {% endif %}
63
+
64
+ <!-- Open Graph -->
65
+ <meta property="og:type" content="website">
66
+ <meta property="og:url" content="{{ pageConfig.headMeta.canonicalUrl | default(pageConfig.absoluteUrl) }}">
67
+ <meta property="og:title" content="{{ pageConfig.headMeta.title | default(pageConfig.title) }}">
68
+ <meta property="og:image" content="{{ assetsURL }}/favicons/{{ metaicons }}opengraph.png">
69
+ <meta property="og:image:type" content="image/png">
70
+ <meta property="og:image:width" content="1200">
71
+ <meta property="og:image:height" content="630">
72
+ <meta property="og:description" content="{{ pageConfig.headMeta.description | default(pageConfig.description) }}">
73
+ <meta property="og:site_name" content="{{ pageConfig.header.title | default(pageConfig.title) }}">
74
+ <meta property="og:locale" content="{{ currentLanguageISOCode }}">
75
+ {% if otherLanguageISOCode is defined and otherLanguageISOCode %}
76
+ <meta property="og:locale:alternate" content="{{ otherLanguageISOCode }}">
77
+ {% endif %}
78
+
79
+ <!-- Twitter -->
80
+ <meta name="twitter:card" content="summary">
81
+ <meta name="twitter:site" content="{{ pageConfig.headMeta.twitterSite }}">
82
+ <meta name="twitter:url" content="{{ pageConfig.headMeta.canonicalUrl | default(pageConfig.absoluteUrl) }}">
83
+ <meta name="twitter:title" content="{{ pageConfig.headMeta.title | default(pageConfig.title) }}">
84
+ <meta name="twitter:description" content="{{ pageConfig.headMeta.description | default(pageConfig.description) }}">
85
+ <meta name="twitter:image" content="{{ assetsURL }}/favicons/{{ metaicons }}twitter.png">
86
+
87
+ <!-- Canonical -->
88
+ <link rel="canonical" href="{{ pageConfig.headMeta.canonicalUrl | default(pageConfig.absoluteUrl) }}">
89
+
90
+ {% if pageConfig.headMeta.hrefLangs is defined and pageConfig.headMeta.hrefLangs %}
91
+ {% for item in pageConfig.headMeta.hrefLangs %}
92
+ <link rel="alternate" href="{{ item.url }}" hreflang="{{ item.lang }}">
93
+ {% endfor %}
94
+ {% endif %}
95
+
96
+ {% endif %}
97
+
98
+ {% block headIcons %}
99
+ <!-- Favicons -->
100
+ <meta name="msapplication-config" content="{{ assetsURL }}/favicons/{{ metaicons }}browserconfig.json">
101
+ <link rel="icon" type="image/x-icon" href="{{ assetsURL }}/favicons/{{ metaicons }}favicon.ico">
102
+ <link rel="icon" type="image/png" href="{{ assetsURL }}/favicons/{{ metaicons }}favicon-32x32.png" sizes="32x32">
103
+ <link rel="icon" type="image/png" href="{{ assetsURL }}/favicons/{{ metaicons }}favicon-16x16.png" sizes="16x16">
104
+ <link rel="mask-icon" href="{{ assetsURL }}/favicons/{{ metaicons }}safari-pinned-tab.svg" color="#000000">
105
+ <link rel="apple-touch-icon" type="image/png" href="{{ assetsURL }}/favicons/{{ metaicons }}apple-touch-icon.png" sizes="180x180">
106
+ <link rel="manifest" href="{{ assetsURL }}/favicons/{{ metaicons }}manifest.json">
107
+ {% endblock %}
108
+
109
+ {% block head %}{% endblock %}
110
+
111
+ </head>
112
+ <body{% if pageConfig.bodyClasses is defined and pageConfig.bodyClasses %} class="{{ pageConfig.bodyClasses }}"{% endif %}>
113
+ <script{% if pageConfig.cspNonce is defined and pageConfig.cspNonce %} nonce="{{ pageConfig.cspNonce }}"{% elif pageConfig.cspNonce is not defined and csp_nonce is defined and csp_nonce %} nonce="{{ csp_nonce() }}"{% endif %}>document.body.className = ((document.body.className) ? document.body.className + ' ons-js-enabled' : 'ons-js-enabled');</script>
114
+ {% block bodyStart %}{% endblock %}
115
+ {% block body %}
116
+ <div class="ons-page">
117
+ <div class="ons-page__content">
118
+ {% block skipLink %}
119
+ {{
120
+ onsSkipToContent({
121
+ "url": "#main-content",
122
+ "text": "Skip to main content"
123
+ })
124
+ }}
125
+ {% endblock %}
126
+ {% if form is defined and form and form.attributes is defined and form.attributes %}
127
+ <form
128
+ {% if form.classes is defined and form.classes %}class="{{ form.classes }}"{% endif %}
129
+ method="{{ form.method | default('POST') }}"
130
+ {% if form.attributes is defined and form.attributes %}{% for attribute, value in (form.attributes.items() if form.attributes is mapping and form.attributes.items else form.attributes) %}{{ attribute }}{% if value is defined and value %}="{{value}}" {% endif %}{% endfor %}{% endif %}
131
+ >
132
+ {% endif %}
133
+ {% block preHeader %}{% endblock %}
134
+ {% block header %}
135
+ {{
136
+ onsHeader({
137
+ "title": pageConfig.header.title | default(pageConfig.title),
138
+ "classes": pageConfig.header.classes,
139
+ "wide": pageConfig.wide,
140
+ "language": pageConfig.language,
141
+ "button": pageConfig.signoutButton,
142
+ "toggleButton": pageConfig.toggleButton,
143
+ "navigation": pageConfig.navigation,
144
+ "phase": pageConfig.phase,
145
+ "assetsURL": assetsURL,
146
+ "serviceLinks": pageConfig.serviceLinks,
147
+ "logo": pageConfig.header.logo,
148
+ "mobileLogo": pageConfig.header.mobileLogo,
149
+ "logoAlt": pageConfig.header.logoAlt,
150
+ "logoHref": pageConfig.header.logoHref,
151
+ "titleLogo": pageConfig.header.titleLogo,
152
+ "titleLogoAlt": pageConfig.header.titleLogoAlt,
153
+ "titleLogoHref": pageConfig.header.titleLogoHref,
154
+ "customHeaderLogo": pageConfig.header.customHeaderLogo
155
+ })
156
+ }}
157
+ {% endblock %}
158
+ {% block pageContent %}
159
+ <div class="ons-page__container ons-container {{ containerClasses }}">
160
+ {% if pageConfig.breadcrumbs is defined and pageConfig.breadcrumbs %}
161
+ {% from "components/breadcrumbs/_macro.njk" import onsBreadcrumbs %}
162
+ {{
163
+ onsBreadcrumbs({
164
+ "id": pageConfig.breadcrumbs.id,
165
+ "ariaLabel": pageConfig.breadcrumbs.ariaLabel,
166
+ "itemsList": pageConfig.breadcrumbs.itemsList
167
+ })
168
+ }}
169
+ {% endif %}
170
+ {% block preMain %}{% endblock %}
171
+ <div class="ons-grid">
172
+ <div class="ons-grid__col ons-col-{{ pageColNumber }}@m">
173
+ <main id="main-content" class="ons-page__main {{ pageClasses }}">
174
+ {% block main %}{% endblock %}
175
+ </main>
176
+ </div>
177
+ </div>
178
+ </div>
179
+ {% endblock %}
180
+
181
+ {% if form is defined and form and form.attributes is defined and form.attributes %}
182
+ </form>
183
+ {% endif %}
184
+ </div>
185
+ {% block preFooter %}{% endblock %}
186
+ {% block footer %}
187
+ {% if pageConfig.footer is defined and pageConfig.footer %}
188
+ {{
189
+ onsFooter({
190
+ "assetsURL": assetsURL,
191
+ "wide": pageConfig.wide,
192
+ "classes": "ons-page__footer",
193
+ "language": pageConfig.language,
194
+ "lang": currentLanguageISOCode,
195
+ "rows": pageConfig.footer.rows,
196
+ "cols": pageConfig.footer.cols,
197
+ "poweredBy": pageConfig.footer.poweredBy,
198
+ "crest": pageConfig.footer.crest,
199
+ "OGLLink": pageConfig.footer.OGLLink,
200
+ "button": pageConfig.signoutButton,
201
+ "footerWarning": pageConfig.footer.footerWarning,
202
+ "copyrightDeclaration": pageConfig.footer.copyrightDeclaration,
203
+ "newTabWarning": pageConfig.footer.newTabWarning,
204
+ "legal": pageConfig.footer.legal
205
+ })
206
+ }}
207
+ {% endif %}
208
+ {% endblock %}
209
+ </div>
210
+ {% block bodyEnd %}{% endblock %}
211
+ {% endblock %}
212
+
213
+ {% if isPatternLib is defined and isPatternLib %}
214
+ {% set scripts = assetsURL + "/scripts/main.js," + assetsURL + "/scripts/patternlib.js" %}
215
+ {% else %}
216
+ {% set scripts = assetsURL + "/scripts/main.js" %}
217
+ {% endif %}
218
+
219
+ <script{% if pageConfig.cspNonce is defined and pageConfig.cspNonce %} nonce="{{ pageConfig.cspNonce }}"{% elif pageConfig.cspNonce is not defined and csp_nonce is defined and csp_nonce %} nonce="{{ csp_nonce() }}"{% endif %}>
220
+ (function() {
221
+ var s = '{{ scripts | safe }}'.split(','),
222
+ c = document.createElement('script');
223
+
224
+ if (!('noModule' in c)) {
225
+ for (var i = 0; i < s.length; i++) {
226
+ s[i] = s[i].replace('.js', '.es5.js');
227
+ }
228
+ }
229
+
230
+ for (var i = 0; i < s.length; i++) {
231
+ var e = document.createElement('script');
232
+
233
+ e.src = s[i];
234
+
235
+ document.body.appendChild(e);
236
+ }
237
+ })();
238
+ </script>
239
+
240
+ {% block scripts %}{% endblock %}
241
+ </body>
242
+ </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ons/design-system",
3
3
  "description": "ONS Design System built CSS, JS, and Nunjucks templates",
4
- "version": "45.0.0",
4
+ "version": "45.0.1",
5
5
  "main": "index.js",
6
6
  "license": "MIT",
7
7
  "author": {
@@ -19,7 +19,7 @@
19
19
  "test": "STYLES=main gulp build-styles && TEST_MODE=nomodule karma start ./karma.conf.babel-register.js && TEST_MODE=esm karma start ./karma.conf.babel-register.js && codecov",
20
20
  "test:browserstack": "STYLES=main gulp build-styles && TEST_MODE=nomodule TEST_ON_BROWSERSTACK=true karma start ./karma.conf.babel-register.js && TEST_MODE=esm TEST_ON_BROWSERSTACK=true karma start ./karma.conf.babel-register.js",
21
21
  "test-visual": "yarn build && npx percy exec -- babel-node src/tests/visual/percy.snapshots.js",
22
- "tidy-clean": "rm -rf build css favicons fonts img components page-templates templates scripts coverage scss js",
22
+ "tidy-clean": "rm -rf build css favicons fonts img components layout scripts coverage scss js",
23
23
  "check-unused": "npx npm-check-unused",
24
24
  "dedupe-deps": "npx yarn-deduplicate yarn.lock",
25
25
  "lint-staged": "lint-staged",