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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +19 -2
  3. data/app/assets/javascripts/govuk_publishing_components/components/govspeak.js +9 -0
  4. data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +128 -57
  5. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +1 -1
  6. data/app/assets/javascripts/govuk_publishing_components/lib/govspeak/table-scroll.js +120 -0
  7. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +2 -2
  8. data/app/assets/stylesheets/component_guide/application.scss +7 -3
  9. data/app/assets/stylesheets/govuk_publishing_components/all-components.scss +0 -1
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_cards.scss +0 -13
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_chart.scss +31 -6
  12. data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +0 -4
  13. data/app/assets/stylesheets/govuk_publishing_components/components/_service-navigation.scss +1 -0
  14. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_tables.scss +71 -0
  15. data/app/views/govuk_publishing_components/components/_chart.html.erb +5 -5
  16. data/app/views/govuk_publishing_components/components/_metadata.html.erb +0 -6
  17. data/app/views/govuk_publishing_components/components/_radio.html.erb +1 -2
  18. data/app/views/govuk_publishing_components/components/docs/chart.yml +76 -2
  19. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +29 -0
  20. data/app/views/govuk_publishing_components/components/docs/metadata.yml +12 -12
  21. data/app/views/govuk_publishing_components/components/docs/service_navigation.yml +37 -1
  22. data/config/locales/ar.yml +2 -10
  23. data/config/locales/az.yml +2 -10
  24. data/config/locales/be.yml +2 -10
  25. data/config/locales/bg.yml +2 -10
  26. data/config/locales/bn.yml +2 -10
  27. data/config/locales/cs.yml +2 -10
  28. data/config/locales/cy.yml +6 -14
  29. data/config/locales/da.yml +2 -10
  30. data/config/locales/de.yml +2 -10
  31. data/config/locales/dr.yml +2 -10
  32. data/config/locales/el.yml +2 -10
  33. data/config/locales/en.yml +14 -22
  34. data/config/locales/es-419.yml +2 -10
  35. data/config/locales/es.yml +2 -10
  36. data/config/locales/et.yml +2 -10
  37. data/config/locales/fa.yml +2 -10
  38. data/config/locales/fi.yml +2 -10
  39. data/config/locales/fr.yml +2 -10
  40. data/config/locales/gd.yml +2 -10
  41. data/config/locales/gu.yml +2 -10
  42. data/config/locales/he.yml +2 -10
  43. data/config/locales/hi.yml +2 -10
  44. data/config/locales/hr.yml +2 -10
  45. data/config/locales/hu.yml +2 -10
  46. data/config/locales/hy.yml +2 -10
  47. data/config/locales/id.yml +2 -10
  48. data/config/locales/is.yml +2 -10
  49. data/config/locales/it.yml +2 -10
  50. data/config/locales/ja.yml +2 -10
  51. data/config/locales/ka.yml +2 -10
  52. data/config/locales/kk.yml +2 -10
  53. data/config/locales/ko.yml +2 -10
  54. data/config/locales/ku.yml +2 -10
  55. data/config/locales/ky.yml +2 -10
  56. data/config/locales/lt.yml +2 -10
  57. data/config/locales/lv.yml +2 -10
  58. data/config/locales/ms.yml +2 -10
  59. data/config/locales/mt.yml +2 -10
  60. data/config/locales/ne.yml +2 -10
  61. data/config/locales/nl.yml +2 -10
  62. data/config/locales/no.yml +2 -10
  63. data/config/locales/pa-pk.yml +2 -10
  64. data/config/locales/pa.yml +2 -10
  65. data/config/locales/pl.yml +2 -10
  66. data/config/locales/ps.yml +2 -10
  67. data/config/locales/pt.yml +2 -10
  68. data/config/locales/ro.yml +2 -10
  69. data/config/locales/ru.yml +2 -10
  70. data/config/locales/si.yml +2 -10
  71. data/config/locales/sk.yml +2 -10
  72. data/config/locales/sl.yml +2 -10
  73. data/config/locales/so.yml +2 -10
  74. data/config/locales/sq.yml +2 -10
  75. data/config/locales/sr.yml +2 -10
  76. data/config/locales/sv.yml +2 -10
  77. data/config/locales/sw.yml +2 -10
  78. data/config/locales/ta.yml +2 -10
  79. data/config/locales/th.yml +2 -10
  80. data/config/locales/ti.yml +2 -10
  81. data/config/locales/tk.yml +2 -10
  82. data/config/locales/tr.yml +2 -10
  83. data/config/locales/uk.yml +2 -10
  84. data/config/locales/ur.yml +2 -10
  85. data/config/locales/uz.yml +2 -10
  86. data/config/locales/vi.yml +2 -10
  87. data/config/locales/zh-hk.yml +2 -10
  88. data/config/locales/zh-tw.yml +2 -10
  89. data/config/locales/zh.yml +2 -10
  90. data/lib/govuk_publishing_components/presenters/chart_helper.rb +33 -12
  91. data/lib/govuk_publishing_components/presenters/machine_readable/has_part_schema.rb +1 -3
  92. data/lib/govuk_publishing_components/version.rb +1 -1
  93. data/node_modules/axe-core/README.md +1 -0
  94. data/node_modules/axe-core/axe.js +7695 -3210
  95. data/node_modules/axe-core/axe.min.js +2 -2
  96. data/node_modules/axe-core/locales/_template.json +46 -20
  97. data/node_modules/axe-core/locales/az.json +1161 -0
  98. data/node_modules/axe-core/locales/de.json +1 -1
  99. data/node_modules/axe-core/package.json +7 -8
  100. data/node_modules/axe-core/sri-history.json +4 -0
  101. metadata +4 -6
  102. data/app/assets/javascripts/govuk_publishing_components/components/metadata.js +0 -24
  103. data/app/assets/stylesheets/govuk_publishing_components/components/_published-dates.scss +0 -55
  104. data/app/views/govuk_publishing_components/components/_published_dates.html.erb +0 -48
  105. 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: c7b177c9da6fb435cb1e67132c22ed5d934c3c4d1195ebbbad43f4bdf840db6b
4
- data.tar.gz: b1e988e6f1af0ea310b5aee90fa639e7eab8f1081369224569185649d0564948
3
+ metadata.gz: 8e03438d3c963276e86d21ca8e2da336a8cd15220298b2ffbb57cbf53ca86e56
4
+ data.tar.gz: 8e2052d81d95e829bf5239d2cde0080fc21a62ba7aa2097fe707d131db63ae20
5
5
  SHA512:
6
- metadata.gz: 6d64abc0c3978040d42a6050dd242715afc67d72c1f23029a40a872c66949ece8dfcca0c5326f842ae9768121cc9c4203bd2694b5a0d667a866b4a16f730c9a6
7
- data.tar.gz: 6e8a95eb759c7fad99b61bca15d2f889a181f0152dbb7e1c0911e4a720eaac5f38655105645f91574e856f8bb735701f98cfa4bd251bbb29a72d605f7fd82782
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
- return this.PIIRemover.stripPIIWithOverride(this.stripGaParam(document.location.href), this.stripDates, true)
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 XMLHttpRequest */
1
+ /* global fetch, DOMException, AbortController */
2
2
  (function (Modules) {
3
- function SinglePageNotificationButton ($module) {
4
- this.$module = $module
5
- this.basePath = this.$module.querySelector('input[name="base_path"]').value
6
- this.buttonLocation = this.$module.getAttribute('data-button-location')
7
- this.buttonVisibleClass = 'gem-c-single-page-notification-button--visible'
8
-
9
- this.personalisationEndpoint = '/api/personalisation/check-email-subscription?base_path=' + this.basePath
10
- // This attribute is passed through to the personalisation API to ensure the updated button has the same button_location for analytics
11
- if (this.buttonLocation) this.personalisationEndpoint += '&button_location=' + this.buttonLocation
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
- SinglePageNotificationButton.prototype.init = function () {
15
- var xhr = new XMLHttpRequest()
16
- xhr.open('GET', this.personalisationEndpoint, true)
17
- // if XHR to the personalisation endpoint is taking an incredibly long time to complete, we are better off leaving the button in its default unpersonalised state. Content changing before the user's eyes while they are browsing can be jarring and should be avoided.
18
- xhr.timeout = 10000
19
-
20
- xhr.ontimeout = function () {
21
- this.makeVisible(this.$module)
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
- }.bind(this)
52
- xhr.send()
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
- SinglePageNotificationButton.prototype.responseIsJSON = function (string) {
56
- try {
57
- JSON.parse(string)
58
- } catch (e) {
59
- return false
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
- SinglePageNotificationButton.prototype.makeVisible = function (target) {
65
- target.classList.add(this.buttonVisibleClass)
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.firstChild
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.2";
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 }, { options: options }));
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
- .govuk-table .govuk-table__header {
32
- text-align: center;
33
- }
31
+ }
34
32
 
35
- .govuk-table .govuk-table__cell {
36
- text-align: center;
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;
@@ -8,10 +8,6 @@
8
8
  @include govuk-link-common;
9
9
  @include govuk-link-style-default;
10
10
  }
11
-
12
- .gem-c-metadata__definition-link {
13
- font-weight: normal;
14
- }
15
11
  }
16
12
 
17
13
  .direction-rtl .gem-c-metadata,
@@ -2,6 +2,7 @@
2
2
 
3
3
  .gem-c-service-navigation--full-width {
4
4
  padding-left: govuk-spacing(3);
5
+ padding-right: govuk-spacing(3);
5
6
  }
6
7
 
7
8
  .gem-c-service-navigation--hide-service-name-on-mobile {
@@ -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
- @include_script ||= OpenStruct.new(script_included: false)
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 @include_script[:script_included] %>
34
+ <% unless @include_chart_script[:script_included] %>
35
35
  <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
36
- <% @include_script[:script_included] = true %>
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 %>