govuk_publishing_components 34.7.1 → 34.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (20) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +3 -10
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +113 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +2 -11
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +15 -1
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +20 -29
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  8. data/app/models/govuk_publishing_components/component_doc.rb +14 -0
  9. data/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +14 -0
  10. data/app/views/govuk_publishing_components/component_guide/show.html.erb +21 -6
  11. data/app/views/govuk_publishing_components/components/_action_link.html.erb +5 -2
  12. data/app/views/govuk_publishing_components/components/_breadcrumbs.html.erb +6 -2
  13. data/app/views/govuk_publishing_components/components/_details.html.erb +3 -1
  14. data/app/views/govuk_publishing_components/components/docs/action_link.yml +1 -0
  15. data/app/views/govuk_publishing_components/components/docs/breadcrumbs.yml +1 -0
  16. data/app/views/govuk_publishing_components/components/docs/details.yml +17 -0
  17. data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +78 -0
  18. data/lib/govuk_publishing_components/version.rb +1 -1
  19. data/lib/govuk_publishing_components.rb +1 -0
  20. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f9d8b0bbc2f5782c158e6f8cc16b7aab55063e31a4408e5079339141074fa8f
4
- data.tar.gz: a7a9e1ce6693941a070f4a9044e3068fdf70b326e20308dc6efab1d47fa9494a
3
+ metadata.gz: 858a7994e35203e75dfc40439dd630bcefefc4a549027d9b7fb404df0028e45b
4
+ data.tar.gz: a71a277c8860d002129d138e9e6c104ea040f1163e1cd27ee821c431ed109a2c
5
5
  SHA512:
6
- metadata.gz: bc76829c0f80ffad61f561e0fd197967767137681936f1392040b8b44559c72b93c78cd92bedcb50ca3acfa3984f37aad8f42d9576fe90ec41ec99e2cf0273e9
7
- data.tar.gz: 6e151edcbbb519a3073441eeb912f6a39ebc3216fd65a6f4362ac9ce70c7b5a8f91482c461a8bd5f8bd8ed0ec05bd5311641b97e44e08e420c0b17e4c6c7a686
6
+ metadata.gz: 5b7610f82890c3fd2f2ad862ed3443df843a8230cca1f0e2e294ba5cd02f4933dd8393f3be521f053ba8fef46b984fe0f692709d4d8457c1a478e4848de4495e
7
+ data.tar.gz: f66f9a9c0076b364293b3973cc1b85253d6c701a347967a253e5fe970c877fa7a5eb43edd95e927a155737037e427536e34f99eb0ccdb51712a9e02d6f5815fa
@@ -31,8 +31,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
31
31
  Ga4EventTracker.prototype.trackClick = function (event) {
32
32
  var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
33
33
  if (target) {
34
- var schema = new window.GOVUK.analyticsGa4.Schemas().eventSchema()
35
-
36
34
  try {
37
35
  var data = target.getAttribute(this.trackingTrigger)
38
36
  data = JSON.parse(data)
@@ -44,14 +42,9 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
44
42
 
45
43
  var text = data.text || event.target.textContent
46
44
  data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
47
- schema.event = 'event_data'
48
- // get attributes from the data attribute to send to GA
49
- // only allow it if it already exists in the schema
50
- for (var property in data) {
51
- if (property in schema.event_data) {
52
- schema.event_data[property] = data[property]
53
- }
54
- }
45
+
46
+ var schemas = new window.GOVUK.analyticsGa4.Schemas()
47
+ var schema = schemas.mergeProperties(data, 'event_data')
55
48
 
56
49
  /* Ensure it only tracks aria-expanded in an element with data-ga4-expandable on it. */
57
50
  if (target.closest('[data-ga4-expandable]')) {
@@ -0,0 +1,113 @@
1
+ window.GOVUK = window.GOVUK || {}
2
+ window.GOVUK.Modules = window.GOVUK.Modules || {};
3
+
4
+ (function (Modules) {
5
+ 'use strict'
6
+
7
+ function Ga4FormTracker (module) {
8
+ this.module = module
9
+ this.trackingTrigger = 'data-ga4-form' // elements with this attribute get tracked
10
+ }
11
+
12
+ Ga4FormTracker.prototype.init = function () {
13
+ var consentCookie = window.GOVUK.getConsentCookie()
14
+
15
+ if (consentCookie && consentCookie.settings) {
16
+ this.startModule()
17
+ } else {
18
+ this.startModule = this.startModule.bind(this)
19
+ window.addEventListener('cookie-consent', this.startModule)
20
+ }
21
+ }
22
+
23
+ // triggered by cookie-consent event, which happens when users consent to cookies
24
+ Ga4FormTracker.prototype.startModule = function () {
25
+ if (window.dataLayer) {
26
+ this.module.addEventListener('submit', this.trackFormSubmit.bind(this))
27
+ }
28
+ }
29
+
30
+ Ga4FormTracker.prototype.trackFormSubmit = function (event) {
31
+ var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
32
+ if (target) {
33
+ try {
34
+ var data = target.getAttribute(this.trackingTrigger)
35
+ data = JSON.parse(data)
36
+ } catch (e) {
37
+ // if there's a problem with the config, don't start the tracker
38
+ console.warn('GA4 configuration error: ' + e.message, window.location)
39
+ return
40
+ }
41
+
42
+ var formInputs = this.getFormInputs()
43
+ var formData = this.getInputValues(formInputs)
44
+ data.text = this.combineGivenAnswers(formData) || 'No answer given'
45
+
46
+ var schemas = new window.GOVUK.analyticsGa4.Schemas()
47
+ var schema = schemas.mergeProperties(data, 'event_data')
48
+ window.GOVUK.analyticsGa4.core.sendData(schema)
49
+ }
50
+ }
51
+
52
+ Ga4FormTracker.prototype.getFormInputs = function () {
53
+ var inputs = []
54
+ var labels = this.module.querySelectorAll('label')
55
+
56
+ for (var i = 0; i < labels.length; i++) {
57
+ var label = labels[i]
58
+ var labelFor = label.getAttribute('for')
59
+ var input = false
60
+ if (labelFor) {
61
+ input = this.module.querySelector('[id=' + labelFor + ']')
62
+ } else {
63
+ input = label.querySelector('input')
64
+ }
65
+ inputs.push({
66
+ input: input,
67
+ label: label
68
+ })
69
+ }
70
+ return inputs
71
+ }
72
+
73
+ Ga4FormTracker.prototype.getInputValues = function (inputs) {
74
+ for (var i = inputs.length - 1; i >= 0; i--) {
75
+ var input = inputs[i]
76
+ var elem = input.input
77
+ var labelText = input.label.innerText || input.label.textContent
78
+ var inputType = elem.getAttribute('type')
79
+ var inputNodename = elem.nodeName
80
+
81
+ if (inputType === 'checkbox' && elem.checked) {
82
+ input.answer = labelText
83
+ } else if (inputNodename === 'SELECT' && elem.options[elem.selectedIndex].value) {
84
+ input.answer = elem.options[elem.selectedIndex].text
85
+ } else if (inputType === 'text' && elem.value) {
86
+ input.answer = '[REDACTED]'
87
+ } else if (inputType === 'radio' && elem.checked) {
88
+ input.answer = labelText
89
+ } else {
90
+ // remove the input from those gathered as it has no value
91
+ inputs.splice(i, 1)
92
+ }
93
+ }
94
+ return inputs
95
+ }
96
+
97
+ Ga4FormTracker.prototype.combineGivenAnswers = function (data) {
98
+ var answers = ''
99
+ for (var i = 0; i < data.length; i++) {
100
+ var answer = data[i].answer
101
+ if (answer) {
102
+ answers += answer + ','
103
+ }
104
+ }
105
+ // remove the trailing comma
106
+ if (answers.length) {
107
+ answers = answers.slice(0, -1)
108
+ return answers
109
+ }
110
+ }
111
+
112
+ Modules.Ga4FormTracker = Ga4FormTracker
113
+ })(window.GOVUK.Modules)
@@ -58,8 +58,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
58
58
  Ga4LinkTracker.prototype.trackClick = function (event) {
59
59
  var target = window.GOVUK.analyticsGa4.core.trackFunctions.findTrackingAttributes(event.target, this.trackingTrigger)
60
60
  if (target) {
61
- var schema = new window.GOVUK.analyticsGa4.Schemas().eventSchema()
62
-
63
61
  try {
64
62
  var data = target.getAttribute(this.trackingTrigger)
65
63
  data = JSON.parse(data)
@@ -69,7 +67,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
69
67
  return
70
68
  }
71
69
 
72
- schema.event = 'event_data'
73
70
  var text = data.text || event.target.textContent
74
71
  data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
75
72
  var url = data.url || this.findLink(event.target).getAttribute('href')
@@ -79,14 +76,8 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
79
76
  data.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
80
77
  data.external = window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(data.url) ? 'true' : 'false'
81
78
 
82
- // get attributes from the data attribute to send to GA
83
- // only allow it if it already exists in the schema
84
- for (var property in data) {
85
- if (property in schema.event_data) {
86
- schema.event_data[property] = data[property]
87
- }
88
- }
89
-
79
+ var schemas = new window.GOVUK.analyticsGa4.Schemas()
80
+ var schema = schemas.mergeProperties(data, 'event_data')
90
81
  window.GOVUK.analyticsGa4.core.sendData(schema)
91
82
  }
92
83
  }
@@ -23,11 +23,25 @@
23
23
  external: this.undefined,
24
24
  method: this.undefined,
25
25
  link_domain: this.undefined,
26
- link_path_parts: this.undefined
26
+ link_path_parts: this.undefined,
27
+ tool_name: this.undefined
27
28
  }
28
29
  }
29
30
  }
30
31
 
32
+ // get attributes from the data attribute to send to GA
33
+ // only allow it if it already exists in the schema
34
+ Schemas.prototype.mergeProperties = function (data, eventAttribute) {
35
+ var schema = this.eventSchema()
36
+ schema.event = eventAttribute
37
+ for (var property in data) {
38
+ if (property in schema.event_data) {
39
+ schema.event_data[property] = data[property]
40
+ }
41
+ }
42
+ return schema
43
+ }
44
+
31
45
  GOVUK.analyticsGa4 = GOVUK.analyticsGa4 || {}
32
46
  GOVUK.analyticsGa4.Schemas = Schemas
33
47
 
@@ -49,43 +49,34 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
49
49
  if (!href) {
50
50
  return
51
51
  }
52
- var clickData = {}
52
+ var data = {}
53
53
  if (window.GOVUK.analyticsGa4.core.trackFunctions.isMailToLink(href)) {
54
- clickData.event_name = 'navigation'
55
- clickData.type = 'email'
56
- clickData.external = 'true'
54
+ data.event_name = 'navigation'
55
+ data.type = 'email'
56
+ data.external = 'true'
57
57
  } else if (this.isDownloadLink(href)) {
58
- clickData.event_name = 'file_download'
59
- clickData.type = this.isPreviewLink(href) ? 'preview' : 'generic download'
60
- clickData.external = window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(href) ? 'true' : 'false'
58
+ data.event_name = 'file_download'
59
+ data.type = this.isPreviewLink(href) ? 'preview' : 'generic download'
60
+ data.external = window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(href) ? 'true' : 'false'
61
61
  } else if (window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(href)) {
62
- clickData.event_name = 'navigation'
63
- clickData.type = 'generic link'
64
- clickData.external = 'true'
62
+ data.event_name = 'navigation'
63
+ data.type = 'generic link'
64
+ data.external = 'true'
65
65
  }
66
66
 
67
- if (Object.keys(clickData).length > 0) {
68
- clickData.url = href
69
- if (clickData.url) {
70
- clickData.url = window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(clickData.url)
71
- clickData.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(clickData.url)
72
- clickData.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(clickData.url)
67
+ if (Object.keys(data).length > 0) {
68
+ data.url = href
69
+ if (data.url) {
70
+ data.url = window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(data.url)
71
+ data.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(data.url)
72
+ data.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(data.url)
73
73
  }
74
74
 
75
- clickData.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(element.textContent)
76
- clickData.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
77
-
78
- var schema = new window.GOVUK.analyticsGa4.Schemas().eventSchema()
79
- schema.event = 'event_data'
80
-
81
- // get attributes from the clickData object to send to GA
82
- // only allow it if it already exists in the schema
83
- for (var property in clickData) {
84
- if (property in schema.event_data) {
85
- schema.event_data[property] = clickData[property]
86
- }
87
- }
75
+ data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(element.textContent)
76
+ data.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
88
77
 
78
+ var schemas = new window.GOVUK.analyticsGa4.Schemas()
79
+ var schema = schemas.mergeProperties(data, 'event_data')
89
80
  window.GOVUK.analyticsGa4.core.sendData(schema)
90
81
  }
91
82
  },
@@ -7,4 +7,5 @@
7
7
  //= require ./analytics-ga4/ga4-link-tracker
8
8
  //= require ./analytics-ga4/ga4-event-tracker
9
9
  //= require ./analytics-ga4/ga4-ecommerce-tracker
10
+ //= require ./analytics-ga4/ga4-form-tracker
10
11
  //= require ./analytics-ga4/init-ga4
@@ -32,6 +32,12 @@ module GovukPublishingComponents
32
32
  "#{component[:accessibility_criteria]}\n#{shared_accessibility_criteria.join("\n")}"
33
33
  end
34
34
 
35
+ def component_wrapper_options
36
+ if uses_component_wrapper_helper?
37
+ ComponentWrapperHelperOptions.description
38
+ end
39
+ end
40
+
35
41
  def example
36
42
  examples.first
37
43
  end
@@ -48,6 +54,10 @@ module GovukPublishingComponents
48
54
  component[:display_preview].nil? ? true : component[:display_preview]
49
55
  end
50
56
 
57
+ def uses_component_wrapper_helper?
58
+ component[:uses_component_wrapper_helper]
59
+ end
60
+
51
61
  def html_body
52
62
  markdown_to_html(body) if body.present?
53
63
  end
@@ -56,6 +66,10 @@ module GovukPublishingComponents
56
66
  markdown_to_html(accessibility_criteria) if accessibility_criteria.present?
57
67
  end
58
68
 
69
+ def html_component_wrapper_options
70
+ markdown_to_html(component_wrapper_options) if component_wrapper_options.present?
71
+ end
72
+
59
73
  def partial_path
60
74
  if source == "gem"
61
75
  "govuk_publishing_components/components/#{id}"
@@ -0,0 +1,14 @@
1
+ module GovukPublishingComponents
2
+ module ComponentWrapperHelperOptions
3
+ def self.description
4
+ "
5
+ This component uses the component wrapper helper. It accepts the following options and applies them to the parent element of the component. See the [component wrapper helper documentation](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/component-wrapper-helper.md) for more detail.
6
+
7
+ - `id` - accepts a string for the element ID attribute
8
+ - `data` - accepts a hash of data attributes
9
+ - `aria` - accepts a hash of aria attributes
10
+ - `classes` - accepts a space separated string of classes, these should not be used for styling and must be prefixed with `js-`
11
+ "
12
+ end
13
+ end
14
+ end
@@ -30,6 +30,17 @@
30
30
 
31
31
  <div class="component-doc__content-list">
32
32
  <%
33
+ other_examples_links = []
34
+ other_examples_links << {
35
+ href: "#standard-options",
36
+ text: "Standard options"
37
+ } if @component_doc.uses_component_wrapper_helper?
38
+ other_examples_links.concat(@component_doc.other_examples.map do | example |
39
+ {
40
+ href: "##{example.id}",
41
+ text: example.name
42
+ }
43
+ end)
33
44
  content_items = [
34
45
  { href: "#how-it-looks", text: "How it looks" },
35
46
  { href: "#how-to-call-this-component", text: "How to call this component" },
@@ -38,12 +49,7 @@
38
49
  ({
39
50
  href: "#other-examples",
40
51
  text: "Other examples",
41
- items: @component_doc.other_examples.map do | example |
42
- {
43
- href: "##{example.id}",
44
- text: example.name
45
- }
46
- end
52
+ items: other_examples_links
47
53
  } if @component_doc.other_examples.any?),
48
54
  ].compact
49
55
  %>
@@ -90,6 +96,15 @@
90
96
  <div class="examples">
91
97
  <h2 class="component-doc-h2" id="other-examples">Other examples</h2>
92
98
 
99
+ <% if @component_doc.uses_component_wrapper_helper? %>
100
+ <div class="component-example" id="standard-options">
101
+ <h3 class="example-title">Standard options</h3>
102
+ <div class="component-markdown">
103
+ <%= raw(@component_doc.html_component_wrapper_options) %>
104
+ </div>
105
+ </div>
106
+ <% end %>
107
+
93
108
  <% @component_doc.other_examples.each do |example| %>
94
109
  <div class="component-example" id="<%= example.id %>">
95
110
  <h3 class="example-title">
@@ -41,9 +41,12 @@
41
41
  link_classes << shared_helper.classes if classes
42
42
  link_classes << "govuk-link--inverse" if light_text
43
43
  link_classes << shared_helper.get_heading_size(font_size, 'm') if font_size
44
+
45
+ component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
46
+ component_helper.add_class(css_classes.join(" "))
44
47
  %>
45
48
  <% if text.present? %>
46
- <div class="<%= css_classes.join(' ') %>">
49
+ <%= tag.div(**component_helper.all_attributes) do %>
47
50
  <% contents = capture do %>
48
51
  <span class="gem-c-action-link__link-wrapper">
49
52
  <% main_text = capture do %>
@@ -78,5 +81,5 @@
78
81
  <% else %>
79
82
  <%= contents %>
80
83
  <% end %>
81
- </div>
84
+ <% end %>
82
85
  <% end %>
@@ -10,13 +10,17 @@
10
10
  classes << "govuk-breadcrumbs--collapse-on-mobile" if collapse_on_mobile
11
11
  classes << "gem-c-breadcrumbs--inverse" if inverse
12
12
  classes << "gem-c-breadcrumbs--border-bottom" if border == "bottom"
13
+
14
+ component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
15
+ component_helper.add_class(classes.join(" "))
16
+ component_helper.add_data_attribute({ module: "gem-track-click" })
13
17
  %>
14
18
 
15
19
  <script type="application/ld+json">
16
20
  <%= raw JSON.pretty_generate(breadcrumb_presenter.structured_data) %>
17
21
  </script>
18
22
 
19
- <div class="<%= classes.join(" ") %>" data-module="gem-track-click">
23
+ <%= tag.div(**component_helper.all_attributes) do %>
20
24
  <ol class="govuk-breadcrumbs__list">
21
25
  <% breadcrumbs.each_with_index do |crumb, index| %>
22
26
  <% breadcrumb = GovukPublishingComponents::Presenters::Breadcrumb.new(crumb, index) %>
@@ -34,4 +38,4 @@
34
38
  </li>
35
39
  <% end %>
36
40
  </ol>
37
- </div>
41
+ <% end %>
@@ -11,9 +11,11 @@
11
11
 
12
12
  data_attributes ||= {}
13
13
  data_attributes[:details_track_click] = ''
14
+
15
+ summary_aria_attributes ||= {}
14
16
  %>
15
17
  <%= tag.details class: css_classes, data: details_data_attributes, open: open do %>
16
- <%= tag.summary class: "govuk-details__summary", data: data_attributes do %>
18
+ <%= tag.summary class: "govuk-details__summary", data: data_attributes, aria: summary_aria_attributes do %>
17
19
  <span class="govuk-details__summary-text">
18
20
  <%= title %>
19
21
  </span>
@@ -2,6 +2,7 @@ name: Action link
2
2
  description: Use action links to help users get to the next stage of a journey quickly.
3
3
  shared_accessibility_criteria:
4
4
  - link
5
+ uses_component_wrapper_helper: true
5
6
  examples:
6
7
  default:
7
8
  data:
@@ -13,6 +13,7 @@ accessibility_criteria:
13
13
  accessibility_excluded_rules:
14
14
  - skip-link # This component is creating a reference to #content which is part of the layout
15
15
  display_html: true
16
+ uses_component_wrapper_helper: true
16
17
  examples:
17
18
  default:
18
19
  data:
@@ -36,6 +36,23 @@ examples:
36
36
  dimension20: "custom dimension"
37
37
  block: |
38
38
  We need to know your nationality so we can work out which elections you’re entitled to vote in. If you can’t provide your nationality, you’ll have to send copies of identity documents through the post.
39
+ with_aria_attributes:
40
+ description: |
41
+ Aria attributes can be applied to the summary element of the component.
42
+ data:
43
+ title: Works with 2 agencies and public bodies
44
+ summary_aria_attributes:
45
+ label: Attorney General's office
46
+ block: |
47
+ <ul>
48
+ <li>Department 1</li>
49
+ <li>Department 2</li>
50
+ </ul>
51
+ embed: |
52
+ <div>
53
+ <p class="govuk-body">Attorney General's office</p>
54
+ <%= component %>
55
+ </div>
39
56
  with_GTM_tracking:
40
57
  description: Applies a tracking attribute specifically for use by Google Tag Manager in [Content Publisher](https://github.com/alphagov/content-publisher).
41
58
  data:
@@ -0,0 +1,78 @@
1
+ module GovukPublishingComponents
2
+ module Presenters
3
+ class ComponentWrapperHelper
4
+ def initialize(options)
5
+ @options = options
6
+
7
+ check_id_is_valid(@options[:id]) if @options.include?(:id)
8
+ check_classes_are_valid(@options[:classes]) if @options.include?(:classes)
9
+ check_aria_is_valid(@options[:aria]) if @options.include?(:aria)
10
+ end
11
+
12
+ def all_attributes
13
+ {
14
+ id: @options[:id],
15
+ data: @options[:data],
16
+ aria: @options[:aria],
17
+ class: @options[:classes],
18
+ }
19
+ end
20
+
21
+ def set_id(id)
22
+ check_id_is_valid(id)
23
+ @options[:id] = id
24
+ end
25
+
26
+ def add_class(classes)
27
+ check_classes_are_valid(classes)
28
+ extend_string(:classes, classes)
29
+ end
30
+
31
+ def add_data_attribute(attributes)
32
+ extend_object(:data, attributes)
33
+ end
34
+
35
+ def add_aria_attribute(attributes)
36
+ check_aria_is_valid(attributes)
37
+ extend_object(:aria, attributes)
38
+ end
39
+
40
+ private
41
+
42
+ def check_id_is_valid(id)
43
+ raise(ArgumentError, "Id cannot start with a number or contain whitespace and can only contain letters, digits, `_` and `-`") unless /^[a-zA-Z][\w:-]*$/.match?(id)
44
+ end
45
+
46
+ def check_classes_are_valid(classes)
47
+ classes = classes.split(" ")
48
+ unless classes.all? { |c| c.start_with?("js-", "gem-c-", "govuk-") }
49
+ raise(ArgumentError, "Passed classes must be prefixed with `js-`")
50
+ end
51
+ end
52
+
53
+ def check_aria_is_valid(attributes)
54
+ arias = %w[activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby description details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext]
55
+
56
+ unless attributes.all? { |key, _value| arias.include? key.to_s }
57
+ raise(ArgumentError, "Aria attribute is not recognised")
58
+ end
59
+ end
60
+
61
+ def extend_string(option, string)
62
+ ((@options[option] ||= "") << " #{string}").strip!
63
+ end
64
+
65
+ def extend_object(option, object)
66
+ @options[option] ||= {}
67
+ object.each_key do |key|
68
+ @options[option][key] =
69
+ if @options[option].key?(key)
70
+ "#{@options[option][key]} #{object[key]}"
71
+ else
72
+ object[key]
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "34.7.1".freeze
2
+ VERSION = "34.8.0".freeze
3
3
  end
@@ -6,6 +6,7 @@ require "govuk_publishing_components/config"
6
6
  require "govuk_publishing_components/engine"
7
7
  require "govuk_publishing_components/version"
8
8
  require "govuk_publishing_components/presenters/shared_helper"
9
+ require "govuk_publishing_components/presenters/component_wrapper_helper"
9
10
  require "govuk_publishing_components/presenters/attachment_helper"
10
11
  require "govuk_publishing_components/presenters/big_number_helper"
11
12
  require "govuk_publishing_components/presenters/breadcrumbs"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 34.7.1
4
+ version: 34.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-03 00:00:00.000000000 Z
11
+ date: 2023-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_app_config
@@ -442,6 +442,7 @@ files:
442
442
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js
443
443
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-ecommerce-tracker.js
444
444
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js
445
+ - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js
445
446
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js
446
447
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js
447
448
  - app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js
@@ -639,6 +640,7 @@ files:
639
640
  - app/models/govuk_publishing_components/component_doc.rb
640
641
  - app/models/govuk_publishing_components/component_docs.rb
641
642
  - app/models/govuk_publishing_components/component_example.rb
643
+ - app/models/govuk_publishing_components/component_wrapper_helper_options.rb
642
644
  - app/models/govuk_publishing_components/shared_accessibility_criteria.rb
643
645
  - app/views/govuk_publishing_components/audit/_applications.html.erb
644
646
  - app/views/govuk_publishing_components/audit/_component_contents.html.erb
@@ -914,6 +916,7 @@ files:
914
916
  - lib/govuk_publishing_components/presenters/breadcrumbs.rb
915
917
  - lib/govuk_publishing_components/presenters/button_helper.rb
916
918
  - lib/govuk_publishing_components/presenters/checkboxes_helper.rb
919
+ - lib/govuk_publishing_components/presenters/component_wrapper_helper.rb
917
920
  - lib/govuk_publishing_components/presenters/content_breadcrumbs_based_on_ancestors.rb
918
921
  - lib/govuk_publishing_components/presenters/content_breadcrumbs_based_on_taxons.rb
919
922
  - lib/govuk_publishing_components/presenters/content_breadcrumbs_based_on_topic.rb