govuk_publishing_components 70.2.1 → 71.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +19 -2
- data/app/assets/javascripts/govuk_publishing_components/components/govspeak.js +9 -0
- data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +128 -57
- data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +1 -1
- data/app/assets/javascripts/govuk_publishing_components/lib/govspeak/table-scroll.js +120 -0
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +2 -2
- data/app/assets/stylesheets/component_guide/application.scss +7 -3
- data/app/assets/stylesheets/govuk_publishing_components/all-components.scss +0 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/_cards.scss +0 -13
- data/app/assets/stylesheets/govuk_publishing_components/components/_chart.scss +31 -6
- data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +0 -4
- data/app/assets/stylesheets/govuk_publishing_components/components/_service-navigation.scss +1 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_tables.scss +71 -0
- data/app/views/govuk_publishing_components/components/_chart.html.erb +5 -5
- data/app/views/govuk_publishing_components/components/_metadata.html.erb +0 -6
- data/app/views/govuk_publishing_components/components/_radio.html.erb +1 -2
- data/app/views/govuk_publishing_components/components/docs/chart.yml +76 -2
- data/app/views/govuk_publishing_components/components/docs/govspeak.yml +29 -0
- data/app/views/govuk_publishing_components/components/docs/metadata.yml +12 -12
- data/app/views/govuk_publishing_components/components/docs/service_navigation.yml +37 -1
- data/config/locales/ar.yml +2 -10
- data/config/locales/az.yml +2 -10
- data/config/locales/be.yml +2 -10
- data/config/locales/bg.yml +2 -10
- data/config/locales/bn.yml +2 -10
- data/config/locales/cs.yml +2 -10
- data/config/locales/cy.yml +6 -14
- data/config/locales/da.yml +2 -10
- data/config/locales/de.yml +2 -10
- data/config/locales/dr.yml +2 -10
- data/config/locales/el.yml +2 -10
- data/config/locales/en.yml +14 -22
- data/config/locales/es-419.yml +2 -10
- data/config/locales/es.yml +2 -10
- data/config/locales/et.yml +2 -10
- data/config/locales/fa.yml +2 -10
- data/config/locales/fi.yml +2 -10
- data/config/locales/fr.yml +2 -10
- data/config/locales/gd.yml +2 -10
- data/config/locales/gu.yml +2 -10
- data/config/locales/he.yml +2 -10
- data/config/locales/hi.yml +2 -10
- data/config/locales/hr.yml +2 -10
- data/config/locales/hu.yml +2 -10
- data/config/locales/hy.yml +2 -10
- data/config/locales/id.yml +2 -10
- data/config/locales/is.yml +2 -10
- data/config/locales/it.yml +2 -10
- data/config/locales/ja.yml +2 -10
- data/config/locales/ka.yml +2 -10
- data/config/locales/kk.yml +2 -10
- data/config/locales/ko.yml +2 -10
- data/config/locales/ku.yml +2 -10
- data/config/locales/ky.yml +2 -10
- data/config/locales/lt.yml +2 -10
- data/config/locales/lv.yml +2 -10
- data/config/locales/ms.yml +2 -10
- data/config/locales/mt.yml +2 -10
- data/config/locales/ne.yml +2 -10
- data/config/locales/nl.yml +2 -10
- data/config/locales/no.yml +2 -10
- data/config/locales/pa-pk.yml +2 -10
- data/config/locales/pa.yml +2 -10
- data/config/locales/pl.yml +2 -10
- data/config/locales/ps.yml +2 -10
- data/config/locales/pt.yml +2 -10
- data/config/locales/ro.yml +2 -10
- data/config/locales/ru.yml +2 -10
- data/config/locales/si.yml +2 -10
- data/config/locales/sk.yml +2 -10
- data/config/locales/sl.yml +2 -10
- data/config/locales/so.yml +2 -10
- data/config/locales/sq.yml +2 -10
- data/config/locales/sr.yml +2 -10
- data/config/locales/sv.yml +2 -10
- data/config/locales/sw.yml +2 -10
- data/config/locales/ta.yml +2 -10
- data/config/locales/th.yml +2 -10
- data/config/locales/ti.yml +2 -10
- data/config/locales/tk.yml +2 -10
- data/config/locales/tr.yml +2 -10
- data/config/locales/uk.yml +2 -10
- data/config/locales/ur.yml +2 -10
- data/config/locales/uz.yml +2 -10
- data/config/locales/vi.yml +2 -10
- data/config/locales/zh-hk.yml +2 -10
- data/config/locales/zh-tw.yml +2 -10
- data/config/locales/zh.yml +2 -10
- data/lib/govuk_publishing_components/presenters/chart_helper.rb +33 -12
- data/lib/govuk_publishing_components/presenters/machine_readable/has_part_schema.rb +1 -3
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/README.md +1 -0
- data/node_modules/axe-core/axe.js +7695 -3210
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/locales/_template.json +46 -20
- data/node_modules/axe-core/locales/az.json +1161 -0
- data/node_modules/axe-core/locales/de.json +1 -1
- data/node_modules/axe-core/package.json +7 -8
- data/node_modules/axe-core/sri-history.json +4 -0
- metadata +4 -6
- data/app/assets/javascripts/govuk_publishing_components/components/metadata.js +0 -24
- data/app/assets/stylesheets/govuk_publishing_components/components/_published-dates.scss +0 -55
- data/app/views/govuk_publishing_components/components/_published_dates.html.erb +0 -48
- data/app/views/govuk_publishing_components/components/docs/published_dates.yml +0 -37
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e03438d3c963276e86d21ca8e2da336a8cd15220298b2ffbb57cbf53ca86e56
|
|
4
|
+
data.tar.gz: 8e2052d81d95e829bf5239d2cde0080fc21a62ba7aa2097fe707d131db63ae20
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5278c358eb404521e67e9bb9fb95e8df365f7ae1a7df0ba88a9f43b57a5281d735206b7265c28cab4f06843ba30b57d43800b516ff701ed794c31c411bc36713
|
|
7
|
+
data.tar.gz: 5aecaf5b41cb5c02b8d85cd194b561e21b8d120adadd4f09dbd1bd6e07fb031d9eecde6d63cf4f3af955f8b0593967ba7b4d4a3d683594b24eb9c41e8161b0e7
|
|
@@ -69,13 +69,28 @@
|
|
|
69
69
|
user_created_at: this.getMetaContent('user-created-at'),
|
|
70
70
|
user_organisation_name: this.getMetaContent('user-organisation-name'),
|
|
71
71
|
user_role: this.getMetaContent('user-role'),
|
|
72
|
-
user_id: this.getMetaContent('user-id')
|
|
72
|
+
user_id: this.getMetaContent('user-id'),
|
|
73
|
+
|
|
74
|
+
utm_source: this.getUtmParams('utm_source'),
|
|
75
|
+
utm_medium: this.getUtmParams('utm_medium'),
|
|
76
|
+
utm_campaign: this.getUtmParams('utm_campaign'),
|
|
77
|
+
utm_term: this.getUtmParams('utm_term'),
|
|
78
|
+
utm_content: this.getUtmParams('utm_content')
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
window.GOVUK.analyticsGa4.core.sendData(data)
|
|
76
82
|
}
|
|
77
83
|
},
|
|
78
84
|
|
|
85
|
+
getUtmParams: function (key) {
|
|
86
|
+
if (this.getLocation().indexOf('?') > -1) {
|
|
87
|
+
var queryStringParams = new URLSearchParams(this.getLocation().split('?')[1])
|
|
88
|
+
return queryStringParams.get(key) || undefined
|
|
89
|
+
} else {
|
|
90
|
+
return undefined
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
|
|
79
94
|
removeHyphensAndDowncase: function (text) {
|
|
80
95
|
if (text) {
|
|
81
96
|
return text.replace(/-/g, ' ').toLowerCase()
|
|
@@ -102,7 +117,8 @@
|
|
|
102
117
|
|
|
103
118
|
getLocation: function () {
|
|
104
119
|
// We don't want to remove dates on search pages.
|
|
105
|
-
|
|
120
|
+
// Where a token is present this should be redacted
|
|
121
|
+
return this.PIIRemover.stripPIIWithOverride(this.stripGaParam(document.location.href.replace(/(&token=)(\S+)/, '')), this.stripDates, true)
|
|
106
122
|
},
|
|
107
123
|
|
|
108
124
|
getSearchTerm: function () {
|
|
@@ -149,6 +165,7 @@
|
|
|
149
165
|
queryString = this.stripGaParam(queryString)
|
|
150
166
|
queryString = this.PIIRemover.stripPIIWithOverride(queryString, this.stripDates, true)
|
|
151
167
|
queryString = queryString.substring(1) // removes the '?' character from the start.
|
|
168
|
+
queryString = queryString.replace(/(&token=)(\S+)/, '') // where a token is present this should be redacted
|
|
152
169
|
return queryString
|
|
153
170
|
}
|
|
154
171
|
},
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
this.createBarcharts()
|
|
12
|
+
|
|
13
|
+
if (this.$module.querySelectorAll('table').length) {
|
|
14
|
+
this.tableScroll()
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
Govspeak.prototype.embedYoutube = function () {
|
|
@@ -21,5 +25,10 @@
|
|
|
21
25
|
enhancement.init()
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
Govspeak.prototype.tableScroll = function () {
|
|
29
|
+
var enhancement = new window.GOVUK.GovspeakTableScroll(this.$module)
|
|
30
|
+
enhancement.init()
|
|
31
|
+
}
|
|
32
|
+
|
|
24
33
|
Modules.Govspeak = Govspeak
|
|
25
34
|
})(window.GOVUK.Modules)
|
|
@@ -1,68 +1,139 @@
|
|
|
1
|
-
/* global
|
|
1
|
+
/* global fetch, DOMException, AbortController */
|
|
2
2
|
(function (Modules) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
class SinglePageNotificationButton {
|
|
4
|
+
constructor ($module) {
|
|
5
|
+
/** @type {HTMLDivElement} */
|
|
6
|
+
this.$module = $module
|
|
7
|
+
|
|
8
|
+
/** @type {HTMLInputElement | null} */
|
|
9
|
+
this.basePathInput = this.$module.querySelector('input[name="base_path"]')
|
|
10
|
+
|
|
11
|
+
/** @type {HTMLButtonElement | null} */
|
|
12
|
+
this.button = this.$module.querySelector('.gem-c-button__outline--notification')
|
|
13
|
+
|
|
14
|
+
/** @type {string | null} */
|
|
15
|
+
this.buttonLocation = this.$module.getAttribute('data-button-location')
|
|
16
|
+
|
|
17
|
+
/** @type {string | null} */
|
|
18
|
+
this.customSubscribeText = this.$module.getAttribute('data-button-text-subscribe')
|
|
19
|
+
|
|
20
|
+
/** @type {string | null} */
|
|
21
|
+
this.customUnsubscribeText = this.$module.getAttribute('data-button-text-unsubscribe')
|
|
22
|
+
|
|
23
|
+
/** @type {string} */
|
|
24
|
+
this.buttonVisibleClass = 'gem-c-single-page-notification-button--visible'
|
|
25
|
+
|
|
26
|
+
/** @type {number | null} */
|
|
27
|
+
this.fetchRequestTimeoutId = null
|
|
28
|
+
}
|
|
13
29
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}.bind(this)
|
|
23
|
-
|
|
24
|
-
xhr.onreadystatechange = function () {
|
|
25
|
-
if (xhr.readyState === 4) {
|
|
26
|
-
if (xhr.status === 200) {
|
|
27
|
-
var responseText = xhr.responseText
|
|
28
|
-
// if response text exists and is JSON parse-able, parse the response and update the button html
|
|
29
|
-
if (responseText && this.responseIsJSON(responseText)) {
|
|
30
|
-
var active = JSON.parse(responseText).active
|
|
31
|
-
|
|
32
|
-
var customSubscribeText = this.$module.getAttribute('data-button-text-subscribe')
|
|
33
|
-
var customUnsubscribeText = this.$module.getAttribute('data-button-text-unsubscribe')
|
|
34
|
-
// Only set custom button text if both text items are provided
|
|
35
|
-
var customText = customSubscribeText && customUnsubscribeText
|
|
36
|
-
|
|
37
|
-
// If response returns active, user has subscribed to notifications
|
|
38
|
-
if (active === true) {
|
|
39
|
-
if (customText) {
|
|
40
|
-
this.$module.querySelector('.gem-c-button__outline--notification').textContent = customUnsubscribeText
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
if (customText) {
|
|
44
|
-
this.$module.querySelector('.gem-c-button__outline--notification').textContent = customSubscribeText
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
30
|
+
/**
|
|
31
|
+
* Initialise the single page notification button
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
async init () {
|
|
35
|
+
try {
|
|
36
|
+
if (this.button === null) {
|
|
37
|
+
throw new Error('Button required')
|
|
48
38
|
}
|
|
39
|
+
|
|
40
|
+
if (this.basePathInput === null) {
|
|
41
|
+
throw new Error('Base path required')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const personalisationEndpoint = this.getPersonalisationEndpoint(this.basePathInput.value, this.buttonLocation)
|
|
45
|
+
const personalisationData = await this.getPersonalisationData(personalisationEndpoint, 10000)
|
|
46
|
+
const customButtonText = this.getCustomButtonText(personalisationData.active, this.customSubscribeText, this.customUnsubscribeText)
|
|
47
|
+
|
|
48
|
+
if (customButtonText) {
|
|
49
|
+
this.button.textContent = customButtonText
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(error)
|
|
53
|
+
} finally {
|
|
49
54
|
this.makeVisible(this.$module)
|
|
55
|
+
clearTimeout(this.fetchRequestTimeoutId)
|
|
50
56
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get the personalisation data endpoint
|
|
61
|
+
*
|
|
62
|
+
* @param {string} basePath The base path to use
|
|
63
|
+
* @param {string | null} buttonLocation This attribute is passed through to the personalisation API to ensure the updated button has the same button_location for analytics
|
|
64
|
+
* @returns {string} The personalisation endpoint to use
|
|
65
|
+
*/
|
|
66
|
+
getPersonalisationEndpoint (basePath, buttonLocation) {
|
|
67
|
+
const checkEmailSubscriptionEndpoint = '/api/personalisation/check-email-subscription'
|
|
54
68
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return
|
|
69
|
+
if (buttonLocation) {
|
|
70
|
+
return `${checkEmailSubscriptionEndpoint}?base_path=${basePath}&button_location=${buttonLocation}`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return `${checkEmailSubscriptionEndpoint}?base_path=${basePath}`
|
|
60
74
|
}
|
|
61
|
-
return true
|
|
62
|
-
}
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Fetch data from the personalisation endpoint for checking if an email subscription is active
|
|
78
|
+
*
|
|
79
|
+
* @param {string} personalisationEndpoint The personalisation URL to fetch data from
|
|
80
|
+
* @param {number} timer Set the time in milliseconds when the fetch request should abort
|
|
81
|
+
* @returns {Promise<EmailSubscriptionData>}
|
|
82
|
+
* @throws {DOMException} if the request times out
|
|
83
|
+
* @throws {Error} if the request response is not ok
|
|
84
|
+
*/
|
|
85
|
+
async getPersonalisationData (personalisationEndpoint, timer) {
|
|
86
|
+
const abortController = new AbortController()
|
|
87
|
+
this.fetchRequestTimeoutId = setTimeout(() => abortController.abort(new DOMException('Timeout', 'AbortError')), timer)
|
|
88
|
+
|
|
89
|
+
const response = await fetch(personalisationEndpoint, {
|
|
90
|
+
headers: { Accept: 'application/json' },
|
|
91
|
+
signal: abortController.signal
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
throw new Error(`Response status: ${response.status}`)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return await response.json()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Make the single page notification button visible
|
|
103
|
+
*
|
|
104
|
+
* @param {HTMLDivElement} module The element to add the visible class to
|
|
105
|
+
*/
|
|
106
|
+
makeVisible (module) {
|
|
107
|
+
module.classList.add(this.buttonVisibleClass)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get custom button text depending on whether the email subscription is active
|
|
112
|
+
*
|
|
113
|
+
* @param {boolean} activeState If the user has an email subscription to the page
|
|
114
|
+
* @param {string} customSubscribeText The custom subscribe text used when the activeState is false
|
|
115
|
+
* @param {string} customUnsubscribeText The custom subscribe text used when the activeState is true
|
|
116
|
+
* @returns {string | undefined} Returns the custom button text to use or `undefined` if the custom button text cannot be determined
|
|
117
|
+
*/
|
|
118
|
+
getCustomButtonText (activeState, customSubscribeText, customUnsubscribeText) {
|
|
119
|
+
if (typeof activeState !== 'boolean') return
|
|
120
|
+
// Only set custom button text if both text items are provided
|
|
121
|
+
if (!customSubscribeText || !customUnsubscribeText) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (activeState === true) return customUnsubscribeText
|
|
126
|
+
if (activeState === false) return customSubscribeText
|
|
127
|
+
}
|
|
66
128
|
}
|
|
129
|
+
|
|
67
130
|
Modules.SinglePageNotificationButton = SinglePageNotificationButton
|
|
68
131
|
})(window.GOVUK.Modules)
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @typedef {object} EmailSubscriptionData
|
|
135
|
+
* @property {string} base_path the base_path parameter
|
|
136
|
+
* @property {boolean} active whether the email subscription is active
|
|
137
|
+
*
|
|
138
|
+
* @see {@link https://docs.publishing.service.gov.uk/repos/account-api/api.html#get-apipersonalisationcheck-email-subscription}
|
|
139
|
+
*/
|
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
|
|
288
288
|
var loaded = this.loadFromSessionStorage(this.$module.sessionStoreLink)
|
|
289
289
|
var activeParent = this.$module.querySelectorAll('.' + this.$module.activeLinkClass)[0]
|
|
290
|
-
var activeChild = activeParent.
|
|
290
|
+
var activeChild = activeParent.firstElementChild
|
|
291
291
|
var foundLink = activeChild.getAttribute('data-position')
|
|
292
292
|
var lastClicked = loaded || foundLink // the value saved has priority
|
|
293
293
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* global ResizeObserver */
|
|
2
|
+
(function (GOVUK) {
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
var TableScroll = function ($element) {
|
|
6
|
+
this.element = $element
|
|
7
|
+
this.tables = this.element.querySelectorAll('table')
|
|
8
|
+
this.windowResizeTimeout = null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
TableScroll.prototype.init = function () {
|
|
12
|
+
if (this.tables.length === 0) {
|
|
13
|
+
return
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// a small timeout ensures scrollWidth is accurate
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
this.windowResized()
|
|
19
|
+
}, 10)
|
|
20
|
+
|
|
21
|
+
// for all browsers
|
|
22
|
+
window.onresize = () => {
|
|
23
|
+
this.detectSizeChange()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// for Firefox with 'zoom text only' (does not trigger onresize)
|
|
27
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
28
|
+
this.detectSizeChange()
|
|
29
|
+
})
|
|
30
|
+
resizeObserver.observe(this.tables[0])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
TableScroll.prototype.detectSizeChange = function () {
|
|
34
|
+
if (this.windowResizeTimeout) {
|
|
35
|
+
clearTimeout(this.windowResizeTimeout)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.windowResizeTimeout = setTimeout(function () {
|
|
39
|
+
this.windowResized()
|
|
40
|
+
}.bind(this), 300)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
TableScroll.prototype.windowResized = function () {
|
|
44
|
+
this.destroyElements()
|
|
45
|
+
this.setupElements()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
TableScroll.prototype.setupElements = function () {
|
|
49
|
+
this.tables.forEach(table => {
|
|
50
|
+
const tablewrapper = table.closest('.tablewrapper')
|
|
51
|
+
|
|
52
|
+
if (!(table.scrollWidth > table.clientWidth)) {
|
|
53
|
+
if (tablewrapper) {
|
|
54
|
+
tablewrapper.className = 'tablewrapper'
|
|
55
|
+
}
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// wrap the table in a div, but only the first time
|
|
60
|
+
if (!tablewrapper) {
|
|
61
|
+
var wrapper = document.createElement('div')
|
|
62
|
+
wrapper.classList.add('tablewrapper')
|
|
63
|
+
table.parentNode.insertBefore(wrapper, table)
|
|
64
|
+
wrapper.appendChild(table)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const scrollBar = document.createElement('div')
|
|
68
|
+
scrollBar.setAttribute('tabindex', '-1')
|
|
69
|
+
scrollBar.classList.add('govspeak-table-scrollbar')
|
|
70
|
+
|
|
71
|
+
const scrollBarChild = document.createElement('div')
|
|
72
|
+
scrollBarChild.classList.add('govspeak-table-scrollbar__child')
|
|
73
|
+
scrollBarChild.style.width = `${table.scrollWidth}px`
|
|
74
|
+
|
|
75
|
+
scrollBar.append(scrollBarChild)
|
|
76
|
+
table.before(scrollBar)
|
|
77
|
+
scrollBar.scrollLeft = table.scrollLeft
|
|
78
|
+
this.updateLeftRight(table)
|
|
79
|
+
|
|
80
|
+
scrollBar.onscroll = () => {
|
|
81
|
+
if (this.preventScrolling) {
|
|
82
|
+
this.preventScrolling = false
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
this.preventScrolling = true
|
|
86
|
+
table.scrollLeft = scrollBar.scrollLeft
|
|
87
|
+
this.updateLeftRight(table)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
table.onscroll = () => {
|
|
91
|
+
if (this.preventScrolling) {
|
|
92
|
+
this.preventScrolling = false
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
this.preventScrolling = true
|
|
96
|
+
scrollBar.scrollLeft = table.scrollLeft
|
|
97
|
+
this.updateLeftRight(table)
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
TableScroll.prototype.updateLeftRight = function (table) {
|
|
103
|
+
if ((table.scrollWidth - table.scrollLeft) < (table.offsetWidth + 1)) {
|
|
104
|
+
table.parentElement.className = 'tablewrapper tablewrapper--active tablewrapper--end'
|
|
105
|
+
} else if (table.scrollLeft < 1) {
|
|
106
|
+
table.parentElement.className = 'tablewrapper tablewrapper--active tablewrapper--start'
|
|
107
|
+
} else {
|
|
108
|
+
table.parentElement.className = 'tablewrapper tablewrapper--active'
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
TableScroll.prototype.destroyElements = function () {
|
|
113
|
+
const scrollBars = this.element.querySelectorAll('.govspeak-table-scrollbar')
|
|
114
|
+
scrollBars.forEach(bar => {
|
|
115
|
+
bar.remove()
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
GOVUK.GovspeakTableScroll = TableScroll
|
|
120
|
+
}(window.GOVUK))
|
|
@@ -298,7 +298,7 @@
|
|
|
298
298
|
return sendBeaconImpl(url, data);
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
var version = "4.5.
|
|
301
|
+
var version = "4.5.3";
|
|
302
302
|
var pkg = {
|
|
303
303
|
version: version};
|
|
304
304
|
|
|
@@ -1191,7 +1191,7 @@
|
|
|
1191
1191
|
var po = new PerformanceObserver(function (list) {
|
|
1192
1192
|
list.getEntries().forEach(function (entry) { return callback(entry); });
|
|
1193
1193
|
});
|
|
1194
|
-
po.observe(Object.assign({ type: type, buffered: true },
|
|
1194
|
+
po.observe(Object.assign({ type: type, buffered: true }, options));
|
|
1195
1195
|
return po;
|
|
1196
1196
|
}
|
|
1197
1197
|
return undefined;
|
|
@@ -115,7 +115,7 @@ $gem-guide-border-width: 1px;
|
|
|
115
115
|
.component-guide-preview--violation,
|
|
116
116
|
.component-guide-preview--warning {
|
|
117
117
|
margin-top: -$gem-guide-border-width;
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
color: govuk-functional-colour(text);
|
|
120
120
|
@include govuk-font($size: 19);
|
|
121
121
|
|
|
@@ -217,6 +217,11 @@ html {
|
|
|
217
217
|
.preview-title {
|
|
218
218
|
padding-left: govuk-spacing(3);
|
|
219
219
|
}
|
|
220
|
+
|
|
221
|
+
.gem-full-width__element {
|
|
222
|
+
margin-left: 0;
|
|
223
|
+
margin-right: 0;
|
|
224
|
+
}
|
|
220
225
|
}
|
|
221
226
|
|
|
222
227
|
// Rouge syntax highlighting
|
|
@@ -489,10 +494,9 @@ $code-delete-bg: #fadddd;
|
|
|
489
494
|
padding: 0;
|
|
490
495
|
padding-bottom: 0.1px; // forces child margin inside
|
|
491
496
|
border: 0;
|
|
497
|
+
border-top: solid 1px govuk-functional-colour(border);
|
|
492
498
|
margin-left: -(govuk-spacing(3));
|
|
493
499
|
margin-right: -(govuk-spacing(3));
|
|
494
|
-
border-top: solid 1px govuk-functional-colour(border);
|
|
495
|
-
border-bottom: solid 1px govuk-functional-colour(border);
|
|
496
500
|
|
|
497
501
|
@include govuk-media-query($from: tablet) {
|
|
498
502
|
margin-left: -(govuk-spacing(6));
|
|
@@ -72,7 +72,6 @@ $govuk-output-custom-properties: true;
|
|
|
72
72
|
@import "components/phase-banner";
|
|
73
73
|
@import "components/pagination";
|
|
74
74
|
@import "components/print-link";
|
|
75
|
-
@import "components/published-dates";
|
|
76
75
|
@import "components/radio";
|
|
77
76
|
@import "components/related-navigation";
|
|
78
77
|
@import "components/reorderable-list";
|
|
@@ -7,20 +7,7 @@
|
|
|
7
7
|
padding: 0;
|
|
8
8
|
margin: 0;
|
|
9
9
|
display: grid;
|
|
10
|
-
// stylelint-disable-next-line property-no-deprecated
|
|
11
|
-
grid-column-gap: govuk-spacing(6); // Use deprecated grid-column-gap for Grade C browser support
|
|
12
10
|
column-gap: govuk-spacing(6);
|
|
13
|
-
|
|
14
|
-
@include govuk-media-query($from: "desktop") {
|
|
15
|
-
// For browsers that don't support CSS grid, constrain the width to 50% to improve usability
|
|
16
|
-
// especially for screen magnifier users
|
|
17
|
-
width: 50%;
|
|
18
|
-
|
|
19
|
-
// Reset the width for browsers that support CSS grid
|
|
20
|
-
@supports (display: grid) {
|
|
21
|
-
width: initial;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
11
|
}
|
|
25
12
|
|
|
26
13
|
.gem-c-cards__list--one-column {
|
|
@@ -28,15 +28,36 @@
|
|
|
28
28
|
margin: 0;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
text-align: center;
|
|
33
|
-
}
|
|
31
|
+
}
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
.gem-c-chart div svg g[clip-path] rect,
|
|
34
|
+
.gem-c-chart div svg g[clip-path] circle {
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Legend
|
|
39
|
+
.gem-c-chart div svg g:has(text[text-anchor="start"]) * {
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// For line chart points
|
|
44
|
+
.gem-c-chart svg circle {
|
|
45
|
+
cursor: pointer;
|
|
38
46
|
}
|
|
39
47
|
|
|
48
|
+
// Prevent line chart lines having cursor: pointer
|
|
49
|
+
.gem-c-chart svg g[clip-path] path[fill="none"] {
|
|
50
|
+
cursor: default;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Force grid lines back to default
|
|
54
|
+
.gem-c-chart div svg g[clip-path] rect[height="1"],
|
|
55
|
+
.gem-c-chart div svg g[clip-path] rect[width="1"] {
|
|
56
|
+
cursor: default;
|
|
57
|
+
pointer-events: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
40
61
|
.gem-c-chart .gem-c-chart__a11y-note-link {
|
|
41
62
|
display: none;
|
|
42
63
|
margin-bottom: govuk-spacing(2);
|
|
@@ -56,6 +77,10 @@
|
|
|
56
77
|
}
|
|
57
78
|
}
|
|
58
79
|
|
|
80
|
+
.gem-c-chart__source {
|
|
81
|
+
color: govuk-functional-colour(secondary-text);
|
|
82
|
+
}
|
|
83
|
+
|
|
59
84
|
.js-enabled {
|
|
60
85
|
.gem-c-chart .gem-c-chart__a11y-note-link {
|
|
61
86
|
display: inline;
|
|
@@ -54,6 +54,77 @@
|
|
|
54
54
|
text-align: right;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
|
|
58
|
+
.tablewrapper {
|
|
59
|
+
position: relative;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.tablewrapper--active {
|
|
63
|
+
&::before,
|
|
64
|
+
&::after {
|
|
65
|
+
content: "";
|
|
66
|
+
position: absolute;
|
|
67
|
+
top: 24px;
|
|
68
|
+
width: 10px;
|
|
69
|
+
bottom: 20px;
|
|
70
|
+
background: rgb(0, 0, 0, 0.1);
|
|
71
|
+
border-color: $govuk-border-colour;
|
|
72
|
+
border-width: 5px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&::before {
|
|
76
|
+
left: 0;
|
|
77
|
+
border-left-style: solid;
|
|
78
|
+
border-radius: 0 15px 15px 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&::after {
|
|
82
|
+
right: 0;
|
|
83
|
+
border-right-style: solid;
|
|
84
|
+
border-radius: 15px 0 0 15px;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.tablewrapper--start {
|
|
89
|
+
&::before {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.tablewrapper--end {
|
|
95
|
+
&::after {
|
|
96
|
+
display: none;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.govspeak-table-scrollbar {
|
|
101
|
+
position: sticky;
|
|
102
|
+
background: #FFFFFF;
|
|
103
|
+
z-index: 1;
|
|
104
|
+
top: 0;
|
|
105
|
+
overflow-x: scroll;
|
|
106
|
+
overflow-y: hidden;
|
|
107
|
+
height: 20px;
|
|
108
|
+
margin-bottom: 5px;
|
|
109
|
+
|
|
110
|
+
&:focus {
|
|
111
|
+
outline: none;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.govspeak-table-scrollbar__child {
|
|
116
|
+
height: 20px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.govspeak-table-scrollbar + table:focus {
|
|
120
|
+
outline: $govuk-focus-width solid govuk-functional-colour(focus);
|
|
121
|
+
box-shadow: 0 0 0 6px govuk-functional-colour("focus-text");
|
|
122
|
+
|
|
123
|
+
&::before,
|
|
124
|
+
&::after {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
57
128
|
}
|
|
58
129
|
|
|
59
130
|
// Add rtl table styling when `direction: "rtl"` is set
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
chart_id = "chart-id-#{SecureRandom.hex(4)}"
|
|
22
22
|
table_id = "table-id-#{SecureRandom.hex(4)}"
|
|
23
23
|
|
|
24
|
-
@
|
|
24
|
+
@include_chart_script ||= OpenStruct.new(script_included: false)
|
|
25
25
|
|
|
26
26
|
chart_helper = GovukPublishingComponents::Presenters::ChartHelper.new(local_assigns)
|
|
27
27
|
component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
Chartkick.options[:html] = '<div id="%{id}"><noscript><p class="govuk-body">This chart uses JavaScript to work. To view the chart, turn on JavaScript in your browser’s settings.</p></noscript></div>'
|
|
32
32
|
%>
|
|
33
33
|
<% if rows.length > 0 && keys.length > 0 %>
|
|
34
|
-
<% unless @
|
|
34
|
+
<% unless @include_chart_script[:script_included] %>
|
|
35
35
|
<%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
|
|
36
|
-
<% @
|
|
36
|
+
<% @include_chart_script[:script_included] = true %>
|
|
37
37
|
<% end %>
|
|
38
38
|
<%= tag.div(**component_helper.all_attributes) do %>
|
|
39
39
|
<div class="<%= header_class %>">
|
|
@@ -80,13 +80,13 @@
|
|
|
80
80
|
<td class="govuk-table__cell"></td>
|
|
81
81
|
<% if table_direction == "horizontal" %>
|
|
82
82
|
<% keys.each do |key| %>
|
|
83
|
-
<th class="govuk-table__header" scope="col">
|
|
83
|
+
<th class="govuk-table__header govuk-table__cell--numeric" scope="col">
|
|
84
84
|
<%= key %>
|
|
85
85
|
</th>
|
|
86
86
|
<% end %>
|
|
87
87
|
<% else %>
|
|
88
88
|
<% rows.each do |row| %>
|
|
89
|
-
<th class="govuk-table__header govuk-table__header--stacked" scope="row">
|
|
89
|
+
<th class="govuk-table__header govuk-table__header--stacked govuk-table__cell--numeric" scope="row">
|
|
90
90
|
<%= row[:label] %>
|
|
91
91
|
</th>
|
|
92
92
|
<% end %>
|