govuk_design_system_formbuilder 2.1.9 → 2.5.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/README.md +2 -2
  4. data/lib/govuk_design_system_formbuilder.rb +8 -1
  5. data/lib/govuk_design_system_formbuilder/base.rb +16 -1
  6. data/lib/govuk_design_system_formbuilder/builder.rb +60 -15
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +2 -2
  8. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +12 -9
  9. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +2 -2
  10. data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +1 -1
  11. data/lib/govuk_design_system_formbuilder/elements/caption.rb +3 -3
  12. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +2 -2
  13. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +2 -2
  14. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +5 -3
  15. data/lib/govuk_design_system_formbuilder/elements/collection_select.rb +52 -0
  16. data/lib/govuk_design_system_formbuilder/elements/date.rb +33 -15
  17. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +1 -1
  18. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +11 -4
  19. data/lib/govuk_design_system_formbuilder/elements/file.rb +3 -2
  20. data/lib/govuk_design_system_formbuilder/elements/hint.rb +1 -1
  21. data/lib/govuk_design_system_formbuilder/elements/inputs/email.rb +1 -0
  22. data/lib/govuk_design_system_formbuilder/elements/inputs/number.rb +1 -0
  23. data/lib/govuk_design_system_formbuilder/elements/inputs/password.rb +1 -0
  24. data/lib/govuk_design_system_formbuilder/elements/inputs/phone.rb +1 -0
  25. data/lib/govuk_design_system_formbuilder/elements/inputs/text.rb +1 -0
  26. data/lib/govuk_design_system_formbuilder/elements/inputs/url.rb +1 -0
  27. data/lib/govuk_design_system_formbuilder/elements/label.rb +3 -3
  28. data/lib/govuk_design_system_formbuilder/elements/legend.rb +3 -5
  29. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +3 -3
  30. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +3 -3
  31. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +9 -7
  32. data/lib/govuk_design_system_formbuilder/elements/select.rb +22 -32
  33. data/lib/govuk_design_system_formbuilder/elements/submit.rb +17 -14
  34. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +5 -4
  35. data/lib/govuk_design_system_formbuilder/traits/caption.rb +1 -1
  36. data/lib/govuk_design_system_formbuilder/traits/error.rb +2 -2
  37. data/lib/govuk_design_system_formbuilder/traits/fieldset_item.rb +2 -2
  38. data/lib/govuk_design_system_formbuilder/traits/hint.rb +2 -2
  39. data/lib/govuk_design_system_formbuilder/traits/html_attributes.rb +51 -0
  40. data/lib/govuk_design_system_formbuilder/traits/input.rb +5 -5
  41. data/lib/govuk_design_system_formbuilder/traits/label.rb +1 -1
  42. data/lib/govuk_design_system_formbuilder/traits/select.rb +15 -0
  43. data/lib/govuk_design_system_formbuilder/traits/supplemental.rb +2 -2
  44. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  45. metadata +45 -13
@@ -8,8 +8,9 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::Hint
9
9
  include Traits::FieldsetItem
10
10
  include Traits::Conditional
11
+ include Traits::HTMLAttributes
11
12
 
12
- def initialize(builder, object_name, attribute_name, value, unchecked_value, label:, hint:, link_errors:, multiple:, &block)
13
+ def initialize(builder, object_name, attribute_name, value, unchecked_value, label:, hint:, link_errors:, multiple:, **kwargs, &block)
13
14
  super(builder, object_name, attribute_name)
14
15
 
15
16
  @value = value
@@ -18,6 +19,7 @@ module GOVUKDesignSystemFormBuilder
18
19
  @hint = hint
19
20
  @multiple = multiple
20
21
  @link_errors = link_errors
22
+ @html_attributes = kwargs
21
23
 
22
24
  if block_given?
23
25
  @conditional_content = wrap_conditional(block)
@@ -38,7 +40,7 @@ module GOVUKDesignSystemFormBuilder
38
40
  end
39
41
 
40
42
  def check_box
41
- @builder.check_box(@attribute_name, options, @value, @unchecked_value)
43
+ @builder.check_box(@attribute_name, attributes(@html_attributes), @value, @unchecked_value)
42
44
  end
43
45
 
44
46
  def options
@@ -46,7 +48,7 @@ module GOVUKDesignSystemFormBuilder
46
48
  id: field_id(link_errors: @link_errors),
47
49
  class: classes,
48
50
  multiple: @multiple,
49
- aria: { describedby: hint_id },
51
+ aria: { describedby: [hint_id] },
50
52
  data: { 'aria-controls' => @conditional_id }
51
53
  }
52
54
  end
@@ -0,0 +1,52 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ class CollectionSelect < Base
4
+ include Traits::Error
5
+ include Traits::Label
6
+ include Traits::Hint
7
+ include Traits::Supplemental
8
+ include Traits::HTMLAttributes
9
+ include Traits::Select
10
+
11
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint:, label:, caption:, form_group:, options: {}, **kwargs, &block)
12
+ super(builder, object_name, attribute_name, &block)
13
+
14
+ @collection = collection
15
+ @value_method = value_method
16
+ @text_method = text_method
17
+ @options = options
18
+ @label = label
19
+ @caption = caption
20
+ @hint = hint
21
+ @form_group = form_group
22
+ @html_attributes = kwargs
23
+
24
+ # FIXME remove this soon, worth informing people who miss the release notes that the
25
+ # args have changed though.
26
+ if :html_options.in?(kwargs.keys)
27
+ warn("GOVUKDesignSystemFormBuilder: html_options has been deprecated, use keyword arguments instead")
28
+ end
29
+ end
30
+
31
+ def html
32
+ Containers::FormGroup.new(*bound, **@form_group).html do
33
+ safe_join([label_element, supplemental_content, hint_element, error_element, collection_select])
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def options
40
+ {
41
+ id: field_id(link_errors: true),
42
+ class: classes,
43
+ aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
44
+ }
45
+ end
46
+
47
+ def collection_select
48
+ @builder.collection_select(@attribute_name, @collection, @value_method, @text_method, @options, **attributes(@html_attributes))
49
+ end
50
+ end
51
+ end
52
+ end
@@ -8,22 +8,24 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::Supplemental
9
9
 
10
10
  SEGMENTS = { day: '3i', month: '2i', year: '1i' }.freeze
11
+ MULTIPARAMETER_KEY = { day: 3, month: 2, year: 1 }.freeze
11
12
 
12
- def initialize(builder, object_name, attribute_name, legend:, caption:, hint:, omit_day:, form_group:, wildcards:, date_of_birth: false, &block)
13
+ def initialize(builder, object_name, attribute_name, legend:, caption:, hint:, omit_day:, form_group:, wildcards:, date_of_birth: false, **kwargs, &block)
13
14
  super(builder, object_name, attribute_name, &block)
14
15
 
15
- @legend = legend
16
- @caption = caption
17
- @hint = hint
18
- @date_of_birth = date_of_birth
19
- @omit_day = omit_day
20
- @form_group = form_group
21
- @wildcards = wildcards
16
+ @legend = legend
17
+ @caption = caption
18
+ @hint = hint
19
+ @date_of_birth = date_of_birth
20
+ @omit_day = omit_day
21
+ @form_group = form_group
22
+ @wildcards = wildcards
23
+ @html_attributes = kwargs
22
24
  end
23
25
 
24
26
  def html
25
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
26
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
27
+ Containers::FormGroup.new(*bound, **@form_group, **@html_attributes).html do
28
+ Containers::Fieldset.new(*bound, **fieldset_options).html do
27
29
  safe_join([supplemental_content, hint_element, error_element, date])
28
30
  end
29
31
  end
@@ -46,7 +48,7 @@ module GOVUKDesignSystemFormBuilder
46
48
  end
47
49
 
48
50
  def day
49
- return nil if omit_day?
51
+ return if omit_day?
50
52
 
51
53
  date_part(:day, width: 2, link_errors: true)
52
54
  end
@@ -60,15 +62,31 @@ module GOVUKDesignSystemFormBuilder
60
62
  end
61
63
 
62
64
  def date_part(segment, width:, link_errors: false)
63
- value = @builder.object.try(@attribute_name).try(segment)
64
-
65
65
  tag.div(class: %(#{brand}-date-input__item)) do
66
66
  tag.div(class: %(#{brand}-form-group)) do
67
- safe_join([label(segment, link_errors), input(segment, link_errors, width, value)])
67
+ safe_join([label(segment, link_errors), input(segment, link_errors, width, value(segment))])
68
68
  end
69
69
  end
70
70
  end
71
71
 
72
+ def value(segment)
73
+ attribute = @builder.object.try(@attribute_name)
74
+
75
+ return unless attribute
76
+
77
+ if attribute.respond_to?(segment)
78
+ attribute.send(segment)
79
+ elsif attribute.respond_to?(:fetch)
80
+ attribute.fetch(MULTIPARAMETER_KEY[segment]) do
81
+ warn("No key '#{segment}' found in MULTIPARAMETER_KEY hash. Expected to find #{MULTIPARAMETER_KEY.values}")
82
+
83
+ nil
84
+ end
85
+ else
86
+ fail(ArgumentError, "invalid Date-like object: must be a Date, Time, DateTime or Hash in MULTIPARAMETER_KEY format")
87
+ end
88
+ end
89
+
72
90
  def label(segment, link_errors)
73
91
  tag.label(
74
92
  segment.capitalize,
@@ -124,7 +142,7 @@ module GOVUKDesignSystemFormBuilder
124
142
  end
125
143
 
126
144
  def date_of_birth_autocomplete_value(segment)
127
- return nil unless @date_of_birth
145
+ return unless @date_of_birth
128
146
 
129
147
  { day: 'bday-day', month: 'bday-month', year: 'bday-year' }.fetch(segment)
130
148
  end
@@ -6,7 +6,7 @@ module GOVUKDesignSystemFormBuilder
6
6
  include Traits::Error
7
7
 
8
8
  def html
9
- return nil unless has_errors?
9
+ return unless has_errors?
10
10
 
11
11
  tag.span(class: %(#{brand}-error-message), id: error_id) do
12
12
  safe_join([hidden_prefix, message])
@@ -2,18 +2,20 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class ErrorSummary < Base
4
4
  include Traits::Error
5
+ include Traits::HTMLAttributes
5
6
 
6
- def initialize(builder, object_name, title, link_base_errors_to:)
7
+ def initialize(builder, object_name, title, link_base_errors_to:, **kwargs)
7
8
  super(builder, object_name, nil)
8
9
 
9
10
  @title = title
10
11
  @link_base_errors_to = link_base_errors_to
12
+ @html_attributes = kwargs
11
13
  end
12
14
 
13
15
  def html
14
- return nil unless object_has_errors?
16
+ return unless object_has_errors?
15
17
 
16
- tag.div(class: summary_class, **summary_options) do
18
+ tag.div(**attributes(@html_attributes)) do
17
19
  safe_join([title, summary])
18
20
  end
19
21
  end
@@ -46,6 +48,10 @@ module GOVUKDesignSystemFormBuilder
46
48
  '#'.concat(target)
47
49
  end
48
50
 
51
+ def classes
52
+ Array.wrap(summary_class)
53
+ end
54
+
49
55
  def summary_class(part = nil)
50
56
  if part
51
57
  %(#{brand}-error-summary).concat('__', part)
@@ -70,8 +76,9 @@ module GOVUKDesignSystemFormBuilder
70
76
  @builder.object.errors.any?
71
77
  end
72
78
 
73
- def summary_options
79
+ def options
74
80
  {
81
+ class: classes,
75
82
  tabindex: -1,
76
83
  role: 'alert',
77
84
  data: {
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  def initialize(builder, object_name, attribute_name, hint:, label:, caption:, form_group:, **kwargs, &block)
12
13
  super(builder, object_name, attribute_name, &block)
@@ -19,7 +20,7 @@ module GOVUKDesignSystemFormBuilder
19
20
  end
20
21
 
21
22
  def html
22
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
23
+ Containers::FormGroup.new(*bound, **@form_group).html do
23
24
  safe_join([label_element, supplemental_content, hint_element, error_element, file])
24
25
  end
25
26
  end
@@ -27,7 +28,7 @@ module GOVUKDesignSystemFormBuilder
27
28
  private
28
29
 
29
30
  def file
30
- @builder.file_field(@attribute_name, **options, **@html_attributes)
31
+ @builder.file_field(@attribute_name, attributes(@html_attributes))
31
32
  end
32
33
 
33
34
  def options
@@ -31,7 +31,7 @@ module GOVUKDesignSystemFormBuilder
31
31
  end
32
32
 
33
33
  def hint_id
34
- return nil unless active?
34
+ return unless active?
35
35
 
36
36
  build_id('hint')
37
37
  end
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  private
12
13
 
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  def builder_method
12
13
  :number_field
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  def builder_method
12
13
  :password_field
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  def builder_method
12
13
  :phone_field
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  def builder_method
12
13
  :text_field
@@ -7,6 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::Hint
8
8
  include Traits::Label
9
9
  include Traits::Supplemental
10
+ include Traits::HTMLAttributes
10
11
 
11
12
  def builder_method
12
13
  :url_field
@@ -28,7 +28,7 @@ module GOVUKDesignSystemFormBuilder
28
28
  end
29
29
 
30
30
  def html
31
- return nil unless active?
31
+ return unless active?
32
32
 
33
33
  if @tag.present?
34
34
  content_tag(@tag, class: %(#{brand}-label-wrapper)) { label }
@@ -72,13 +72,13 @@ module GOVUKDesignSystemFormBuilder
72
72
  end
73
73
 
74
74
  def radio_class
75
- return nil unless @radio
75
+ return unless @radio
76
76
 
77
77
  %(#{brand}-radios__label)
78
78
  end
79
79
 
80
80
  def checkbox_class
81
- return nil unless @checkbox
81
+ return unless @checkbox
82
82
 
83
83
  %(#{brand}-checkboxes__label)
84
84
  end
@@ -39,11 +39,9 @@ module GOVUKDesignSystemFormBuilder
39
39
  def legend_content
40
40
  caption_and_text = safe_join([caption_element, @text])
41
41
 
42
- if @tag.present?
43
- content_tag(@tag, class: heading_classes) { caption_and_text }
44
- else
45
- caption_and_text
46
- end
42
+ return caption_and_text if @tag.blank?
43
+
44
+ content_tag(@tag, class: heading_classes) { caption_and_text }
47
45
  end
48
46
 
49
47
  def retrieve_text(supplied_text)
@@ -25,8 +25,8 @@ module GOVUKDesignSystemFormBuilder
25
25
  end
26
26
 
27
27
  def html
28
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
29
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
28
+ Containers::FormGroup.new(*bound, **@form_group).html do
29
+ Containers::Fieldset.new(*bound, **fieldset_options).html do
30
30
  safe_join([hidden_field, supplemental_content, hint_element, error_element, radios])
31
31
  end
32
32
  end
@@ -56,7 +56,7 @@ module GOVUKDesignSystemFormBuilder
56
56
 
57
57
  def collection
58
58
  @collection.map.with_index do |item, i|
59
- Elements::Radios::CollectionRadioButton.new(@builder, @object_name, @attribute_name, item, **collection_options(i)).html
59
+ Elements::Radios::CollectionRadioButton.new(*bound, item, **collection_options(i)).html
60
60
  end
61
61
  end
62
62
 
@@ -9,7 +9,7 @@ module GOVUKDesignSystemFormBuilder
9
9
  # error summary requires that the id of the first radio is linked-to from the corresponding
10
10
  # error message. As when the summary is built what happens later in the form is unknown, we
11
11
  # need to control this to ensure the link is generated correctly
12
- def initialize(builder, object_name, attribute_name, item, value_method:, text_method:, hint_method:, link_errors: false, bold_labels:)
12
+ def initialize(builder, object_name, attribute_name, item, value_method:, text_method:, hint_method:, bold_labels:, link_errors: false)
13
13
  super(builder, object_name, attribute_name)
14
14
 
15
15
  @item = item
@@ -41,7 +41,7 @@ module GOVUKDesignSystemFormBuilder
41
41
  end
42
42
 
43
43
  def hint_element
44
- @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_options, **hint_content)
44
+ @hint_element ||= Elements::Hint.new(*bound, **hint_options, **hint_content)
45
45
  end
46
46
 
47
47
  def hint_content
@@ -53,7 +53,7 @@ module GOVUKDesignSystemFormBuilder
53
53
  end
54
54
 
55
55
  def label_element
56
- @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, **label_options)
56
+ @label_element ||= Elements::Label.new(*bound, **label_options)
57
57
  end
58
58
 
59
59
  def label_options
@@ -8,14 +8,16 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::Hint
9
9
  include Traits::FieldsetItem
10
10
  include Traits::Conditional
11
+ include Traits::HTMLAttributes
11
12
 
12
- def initialize(builder, object_name, attribute_name, value, label:, hint:, link_errors:, &block)
13
+ def initialize(builder, object_name, attribute_name, value, label:, hint:, link_errors:, **kwargs, &block)
13
14
  super(builder, object_name, attribute_name)
14
15
 
15
- @value = value
16
- @label = label
17
- @hint = hint
18
- @link_errors = has_errors? && link_errors
16
+ @value = value
17
+ @label = label
18
+ @hint = hint
19
+ @link_errors = has_errors? && link_errors
20
+ @html_attributes = kwargs
19
21
 
20
22
  if block_given?
21
23
  @conditional_content = wrap_conditional(block)
@@ -40,13 +42,13 @@ module GOVUKDesignSystemFormBuilder
40
42
  end
41
43
 
42
44
  def input
43
- @builder.radio_button(@attribute_name, @value, **options)
45
+ @builder.radio_button(@attribute_name, @value, **attributes(@html_attributes))
44
46
  end
45
47
 
46
48
  def options
47
49
  {
48
50
  id: field_id(link_errors: @link_errors),
49
- aria: { describedby: hint_id },
51
+ aria: { describedby: [hint_id] },
50
52
  data: { 'aria-controls' => @conditional_id },
51
53
  class: %w(radios__input).prefix(brand)
52
54
  }