govuk_design_system_formbuilder 2.3.0b1 → 2.5.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/govuk_design_system_formbuilder.rb +6 -1
  4. data/lib/govuk_design_system_formbuilder/base.rb +16 -1
  5. data/lib/govuk_design_system_formbuilder/builder.rb +39 -2
  6. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +2 -2
  7. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +2 -2
  8. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +2 -2
  9. data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +1 -1
  10. data/lib/govuk_design_system_formbuilder/elements/caption.rb +3 -3
  11. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +2 -2
  12. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +2 -2
  13. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +1 -1
  14. data/lib/govuk_design_system_formbuilder/elements/collection_select.rb +52 -0
  15. data/lib/govuk_design_system_formbuilder/elements/date.rb +24 -7
  16. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +1 -1
  17. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +1 -1
  18. data/lib/govuk_design_system_formbuilder/elements/file.rb +1 -1
  19. data/lib/govuk_design_system_formbuilder/elements/hint.rb +1 -1
  20. data/lib/govuk_design_system_formbuilder/elements/label.rb +3 -3
  21. data/lib/govuk_design_system_formbuilder/elements/legend.rb +3 -5
  22. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +3 -3
  23. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +2 -2
  24. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +1 -1
  25. data/lib/govuk_design_system_formbuilder/elements/select.rb +14 -27
  26. data/lib/govuk_design_system_formbuilder/elements/submit.rb +5 -5
  27. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +3 -3
  28. data/lib/govuk_design_system_formbuilder/traits/caption.rb +1 -1
  29. data/lib/govuk_design_system_formbuilder/traits/error.rb +2 -2
  30. data/lib/govuk_design_system_formbuilder/traits/fieldset_item.rb +2 -2
  31. data/lib/govuk_design_system_formbuilder/traits/hint.rb +2 -2
  32. data/lib/govuk_design_system_formbuilder/traits/html_attributes.rb +62 -1
  33. data/lib/govuk_design_system_formbuilder/traits/input.rb +4 -4
  34. data/lib/govuk_design_system_formbuilder/traits/label.rb +1 -1
  35. data/lib/govuk_design_system_formbuilder/traits/select.rb +15 -0
  36. data/lib/govuk_design_system_formbuilder/traits/supplemental.rb +2 -2
  37. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  38. metadata +32 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 641fbc9fbd19bc333cd0872da36c9286c7f956cdfe41ef5b9b234dbe264bc03a
4
- data.tar.gz: 30a0000fa3868e7f7f6bf67347a025cf8f85e5e02a77bff4026d343088c3fb3f
3
+ metadata.gz: 98eb37a7c0dc6926abc94003671567e1d6d9ff64026d92dbd2bbeb62e132b5ac
4
+ data.tar.gz: 3bdd6d81f7c94f28e39841088d056c8eb7615dab89cd750e589d516f71faae0a
5
5
  SHA512:
6
- metadata.gz: 53d6df89df5401b05190709bbad01273d0a2491484792d82307a1ffd6a054ef9de69f8d7d5ab7ae028c677603628bf203439959e70c8e2776504172c41fc2939
7
- data.tar.gz: 5fa7f1475a37d063bab13dc27e4238ca6a7429abbe805b51436a6d3a1310c98df7defe60ad51ff376968d4ae8de8f828611daf79fc75a4602a6dbfeef3ae47f7
6
+ metadata.gz: eae5b13528432a2c01a85aba212b74ecfcdb5740ecbe43bf6548749ebc1ab98b7a37281f7bea6b4e85964d73076e19a1a05326011d2edd71f1599075e6545e2b
7
+ data.tar.gz: c24c784e74e4ae48fdafcca7bf3ba3b5e5f3e22a371f0b5e16bd6fc364f1cb3d386be4bff9ea03de0ce3d5857676eca58001b09284a625d9fcd2dc6ef728a9e5
data/README.md CHANGED
@@ -8,8 +8,8 @@
8
8
  [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=DFE-Digital/govuk_design_system_formbuilder)](https://dependabot.com)
9
9
  [![GitHub license](https://img.shields.io/github/license/DFE-Digital/govuk_design_system_formbuilder)](https://github.com/DFE-Digital/govuk_design_system_formbuilder/blob/master/LICENSE)
10
10
  [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-3.11.0-brightgreen)](https://design-system.service.gov.uk)
11
- [![Rails](https://img.shields.io/badge/Ruby-2.6.6%20%E2%95%B1%202.7.2%20%E2%95%B1%203.0.0-E16D6D)](https://www.ruby-lang.org/en/downloads/)
12
- [![Ruby](https://img.shields.io/badge/Rails-6.0.3%20%E2%95%B1%206.1.0-E16D6D)](https://weblog.rubyonrails.org/releases/)
11
+ [![Rails](https://img.shields.io/badge/Ruby-2.6.7%20%E2%95%B1%202.7.3%20%E2%95%B1%203.0.1-E16D6D)](https://www.ruby-lang.org/en/downloads/)
12
+ [![Ruby](https://img.shields.io/badge/Rails-6.0.3.6%20%E2%95%B1%206.1.3.1-E16D6D)](https://weblog.rubyonrails.org/releases/)
13
13
 
14
14
  This library provides an easy-to-use form builder for the [GOV.UK Design System](https://design-system.service.gov.uk/).
15
15
 
@@ -49,6 +49,9 @@ module GOVUKDesignSystemFormBuilder
49
49
  # * +:localisation_schema_legend+, +:localisation_schema_hint+ and
50
50
  # +:localisation_schema_label+ each override the schema root for their
51
51
  # particular context, allowing them to be independently customised.
52
+ #
53
+ # * +:enable_logger+ controls whether or not the library will emit log
54
+ # messages via Rails.logger.warn, defaults to +true+
52
55
  # ===
53
56
  DEFAULTS = {
54
57
  brand: 'govuk',
@@ -67,7 +70,9 @@ module GOVUKDesignSystemFormBuilder
67
70
  localisation_schema_label: nil,
68
71
  localisation_schema_hint: nil,
69
72
  localisation_schema_legend: nil,
70
- localisation_schema_caption: nil
73
+ localisation_schema_caption: nil,
74
+
75
+ enable_logger: true
71
76
  }.freeze
72
77
 
73
78
  DEFAULTS.each_key { |k| config_accessor(k) { DEFAULTS[k] } }
@@ -25,6 +25,15 @@ module GOVUKDesignSystemFormBuilder
25
25
 
26
26
  private
27
27
 
28
+ # returns the attributes bound to the object that are
29
+ # required to build all contained elements
30
+ #
31
+ # @return [GOVUKDesignSystemFormBuilder::FormBuilder, Symbol, Symbol] an array containing the
32
+ # builder, object name and attribute name
33
+ def bound
34
+ [@builder, @object_name, @attribute_name]
35
+ end
36
+
28
37
  def brand(override = nil)
29
38
  override || config.brand
30
39
  end
@@ -57,7 +66,7 @@ module GOVUKDesignSystemFormBuilder
57
66
  end
58
67
 
59
68
  def described_by(*ids)
60
- ids.flatten.compact.join(' ').presence
69
+ ids.flatten.compact
61
70
  end
62
71
 
63
72
  # Builds the values used for HTML id attributes throughout the builder
@@ -87,5 +96,11 @@ module GOVUKDesignSystemFormBuilder
87
96
  .parameterize
88
97
  .tr(replace, delimiter)
89
98
  end
99
+
100
+ def warn(message)
101
+ return unless config.enable_logger
102
+
103
+ Rails.logger.warn(message)
104
+ end
90
105
  end
91
106
  end
@@ -381,13 +381,13 @@ module GOVUKDesignSystemFormBuilder
381
381
  # supplied the hint will be wrapped in a +div+ instead of a +span+
382
382
  # @option hint text [String] the hint text
383
383
  # @option hint kwargs [Hash] additional arguments are applied as attributes to the hint
384
+ # @param label [Hash,Proc] configures or sets the associated label content
384
385
  # @option label text [String] the label text
385
386
  # @option label size [String] the size of the label font, can be +xl+, +l+, +m+, +s+ or nil
386
387
  # @option label tag [Symbol,String] the label's wrapper tag, intended to allow labels to act as page headings
387
388
  # @option label hidden [Boolean] control the visability of the label. Hidden labels will stil be read by screenreaders
388
389
  # @option label kwargs [Hash] additional arguments are applied as attributes on the +label+ element
389
390
  # @param options [Hash] Options hash passed through to Rails' +collection_select+ helper
390
- # @param html_options [Hash] HTML Options hash passed through to Rails' +collection_select+ helper
391
391
  # @param form_group [Hash] configures the form group
392
392
  # @option form_group classes [Array,String] sets the form group's classes
393
393
  # @option form_group kwargs [Hash] additional attributes added to the form group
@@ -413,7 +413,7 @@ module GOVUKDesignSystemFormBuilder
413
413
  # label: -> { tag.h3("Which team did you represent?") }
414
414
  #
415
415
  def govuk_collection_select(attribute_name, collection, value_method, text_method, options: {}, hint: {}, label: {}, caption: {}, form_group: {}, **kwargs, &block)
416
- Elements::Select.new(
416
+ Elements::CollectionSelect.new(
417
417
  self,
418
418
  object_name,
419
419
  attribute_name,
@@ -430,6 +430,42 @@ module GOVUKDesignSystemFormBuilder
430
430
  ).html
431
431
  end
432
432
 
433
+ # Generates a +select+ element containing an +option+ for every choice provided
434
+ #
435
+ # @param attribute_name [Symbol] The name of the attribute
436
+ # @param choices [Array,Hash] The +option+ values, usually provided via
437
+ # the +options_for_select+ or +grouped_options_for_select+ helpers.
438
+ # @param options [Hash] Options hash passed through to Rails' +select+ helper
439
+ # @param hint [Hash,Proc] The content of the hint. No hint will be added if 'text' is left +nil+. When a +Proc+ is
440
+ # supplied the hint will be wrapped in a +div+ instead of a +span+
441
+ # @option hint text [String] the hint text
442
+ # @option hint kwargs [Hash] additional arguments are applied as attributes to the hint
443
+ # @param label [Hash,Proc] configures or sets the associated label content
444
+ # @option label text [String] the label text
445
+ # @option label size [String] the size of the label font, can be +xl+, +l+, +m+, +s+ or nil
446
+ # @option label tag [Symbol,String] the label's wrapper tag, intended to allow labels to act as page headings
447
+ # @option label hidden [Boolean] control the visability of the label. Hidden labels will stil be read by screenreaders
448
+ # @option label kwargs [Hash] additional arguments are applied as attributes on the +label+ element
449
+ # @param form_group [Hash] configures the form group
450
+ # @option form_group classes [Array,String] sets the form group's classes
451
+ # @option form_group kwargs [Hash] additional attributes added to the form group
452
+ # @param block [Block] build the contents of the select element manually for exact control
453
+ # @see https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select Rails select (called by govuk_collection_select)
454
+ # @return [ActiveSupport::SafeBuffer] HTML output
455
+ #
456
+ # @example A select box with custom data attributes
457
+ #
458
+ # @colours = [
459
+ # ["PapayaWhip", "pw", { data: { hex: "#ffefd5" } }],
460
+ # ["Chocolate", "choc", { data: { hex: "#d2691e" } }],
461
+ # ]
462
+ #
463
+ # = f.govuk_select :hat_colour, options_for_select(@colours)
464
+ #
465
+ def govuk_select(attribute_name, choices = nil, options: {}, label: {}, hint: {}, form_group: {}, caption: {}, **kwargs, &block)
466
+ Elements::Select.new(self, object_name, attribute_name, choices, options: options, label: label, hint: hint, form_group: form_group, caption: caption, **kwargs, &block).html
467
+ end
468
+
433
469
  # Generates a radio button for each item in the supplied collection
434
470
  #
435
471
  # @note Unlike the Rails +#collection_radio_buttons+ helper, this version can also insert
@@ -843,6 +879,7 @@ module GOVUKDesignSystemFormBuilder
843
879
  # @note When using this input be aware that Rails's multiparam time and date handling falls foul
844
880
  # of {https://bugs.ruby-lang.org/issues/5988 this} bug, so incorrect dates like +2019-09-31+ will
845
881
  # be 'rounded' up to +2019-10-01+.
882
+ # @note When using this input values will be retrieved from the attribute if it is a Date object or a multiparam date hash
846
883
  # @param attribute_name [Symbol] The name of the attribute
847
884
  # @param hint [Hash,Proc] The content of the hint. No hint will be added if 'text' is left +nil+. When a +Proc+ is
848
885
  # supplied the hint will be wrapped in a +div+ instead of a +span+
@@ -18,8 +18,8 @@ module GOVUKDesignSystemFormBuilder
18
18
  end
19
19
 
20
20
  def html
21
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
22
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
21
+ Containers::FormGroup.new(*bound, **@form_group).html do
22
+ Containers::Fieldset.new(*bound, **fieldset_options).html do
23
23
  safe_join([hint_element, error_element, hidden_field, checkboxes])
24
24
  end
25
25
  end
@@ -24,7 +24,7 @@ module GOVUKDesignSystemFormBuilder
24
24
  def options
25
25
  {
26
26
  class: classes,
27
- aria: { describedby: @described_by }
27
+ aria: { describedby: [@described_by] }
28
28
  }
29
29
  end
30
30
 
@@ -36,7 +36,7 @@ module GOVUKDesignSystemFormBuilder
36
36
  @legend_element ||= if @legend.nil?
37
37
  Elements::Null.new
38
38
  else
39
- Elements::Legend.new(@builder, @object_name, @attribute_name, **legend_options)
39
+ Elements::Legend.new(*bound, **legend_options)
40
40
  end
41
41
  end
42
42
 
@@ -18,8 +18,8 @@ module GOVUKDesignSystemFormBuilder
18
18
  end
19
19
 
20
20
  def html
21
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
22
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
21
+ Containers::FormGroup.new(*bound, **@form_group).html do
22
+ Containers::Fieldset.new(*bound, **fieldset_options).html do
23
23
  safe_join([hint_element, error_element, radios])
24
24
  end
25
25
  end
@@ -8,7 +8,7 @@ module GOVUKDesignSystemFormBuilder
8
8
  end
9
9
 
10
10
  def html
11
- return nil if @content.blank?
11
+ return if @content.blank?
12
12
 
13
13
  tag.div(id: supplemental_id) { @content }
14
14
  end
@@ -3,7 +3,7 @@ module GOVUKDesignSystemFormBuilder
3
3
  class Caption < Base
4
4
  include Traits::Localisation
5
5
 
6
- def initialize(builder, object_name, attribute_name, text: nil, size: nil, **kwargs)
6
+ def initialize(builder, object_name, attribute_name, text: nil, size: config.default_caption_size, **kwargs)
7
7
  super(builder, object_name, attribute_name)
8
8
 
9
9
  @text = text(text)
@@ -12,7 +12,7 @@ module GOVUKDesignSystemFormBuilder
12
12
  end
13
13
 
14
14
  def html
15
- return nil unless active?
15
+ return unless active?
16
16
 
17
17
  tag.span(@text, class: @size_class, **@html_attributes)
18
18
  end
@@ -28,7 +28,7 @@ module GOVUKDesignSystemFormBuilder
28
28
  end
29
29
 
30
30
  def size_class(size)
31
- case size || config.default_caption_size
31
+ case size
32
32
  when 'xl' then %(#{brand}-caption-xl)
33
33
  when 'l' then %(#{brand}-caption-l)
34
34
  when 'm' then %(#{brand}-caption-m)
@@ -23,8 +23,8 @@ module GOVUKDesignSystemFormBuilder
23
23
  end
24
24
 
25
25
  def html
26
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
27
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
26
+ Containers::FormGroup.new(*bound, **@form_group).html do
27
+ Containers::Fieldset.new(*bound, **fieldset_options).html do
28
28
  safe_join([supplemental_content, hint_element, error_element, check_boxes])
29
29
  end
30
30
  end
@@ -36,11 +36,11 @@ module GOVUKDesignSystemFormBuilder
36
36
  end
37
37
 
38
38
  def label_element
39
- @label_element ||= Label.new(@builder, @object_name, @attribute_name, @checkbox, value: @value, link_errors: @link_errors)
39
+ @label_element ||= Label.new(*bound, @checkbox, value: @value, link_errors: @link_errors)
40
40
  end
41
41
 
42
42
  def hint_element
43
- @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_options, **hint_content)
43
+ @hint_element ||= Elements::Hint.new(*bound, **hint_options, **hint_content)
44
44
  end
45
45
 
46
46
  def hint_options
@@ -48,7 +48,7 @@ module GOVUKDesignSystemFormBuilder
48
48
  id: field_id(link_errors: @link_errors),
49
49
  class: classes,
50
50
  multiple: @multiple,
51
- aria: { describedby: hint_id },
51
+ aria: { describedby: [hint_id] },
52
52
  data: { 'aria-controls' => @conditional_id }
53
53
  }
54
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,6 +8,7 @@ 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
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)
@@ -23,8 +24,8 @@ module GOVUKDesignSystemFormBuilder
23
24
  end
24
25
 
25
26
  def html
26
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group, **@html_attributes).html do
27
- 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
28
29
  safe_join([supplemental_content, hint_element, error_element, date])
29
30
  end
30
31
  end
@@ -47,7 +48,7 @@ module GOVUKDesignSystemFormBuilder
47
48
  end
48
49
 
49
50
  def day
50
- return nil if omit_day?
51
+ return if omit_day?
51
52
 
52
53
  date_part(:day, width: 2, link_errors: true)
53
54
  end
@@ -61,15 +62,31 @@ module GOVUKDesignSystemFormBuilder
61
62
  end
62
63
 
63
64
  def date_part(segment, width:, link_errors: false)
64
- value = @builder.object.try(@attribute_name).try(segment)
65
-
66
65
  tag.div(class: %(#{brand}-date-input__item)) do
67
66
  tag.div(class: %(#{brand}-form-group)) do
68
- 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))])
69
68
  end
70
69
  end
71
70
  end
72
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
+
73
90
  def label(segment, link_errors)
74
91
  tag.label(
75
92
  segment.capitalize,
@@ -125,7 +142,7 @@ module GOVUKDesignSystemFormBuilder
125
142
  end
126
143
 
127
144
  def date_of_birth_autocomplete_value(segment)
128
- return nil unless @date_of_birth
145
+ return unless @date_of_birth
129
146
 
130
147
  { day: 'bday-day', month: 'bday-month', year: 'bday-year' }.fetch(segment)
131
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])
@@ -13,7 +13,7 @@ module GOVUKDesignSystemFormBuilder
13
13
  end
14
14
 
15
15
  def html
16
- return nil unless object_has_errors?
16
+ return unless object_has_errors?
17
17
 
18
18
  tag.div(**attributes(@html_attributes)) do
19
19
  safe_join([title, summary])
@@ -20,7 +20,7 @@ module GOVUKDesignSystemFormBuilder
20
20
  end
21
21
 
22
22
  def html
23
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
23
+ Containers::FormGroup.new(*bound, **@form_group).html do
24
24
  safe_join([label_element, supplemental_content, hint_element, error_element, file])
25
25
  end
26
26
  end
@@ -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
@@ -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
 
@@ -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
@@ -48,7 +48,7 @@ module GOVUKDesignSystemFormBuilder
48
48
  def options
49
49
  {
50
50
  id: field_id(link_errors: @link_errors),
51
- aria: { describedby: hint_id },
51
+ aria: { describedby: [hint_id] },
52
52
  data: { 'aria-controls' => @conditional_id },
53
53
  class: %w(radios__input).prefix(brand)
54
54
  }
@@ -4,56 +4,43 @@ module GOVUKDesignSystemFormBuilder
4
4
  include Traits::Error
5
5
  include Traits::Label
6
6
  include Traits::Hint
7
- include Traits::Supplemental
8
7
  include Traits::HTMLAttributes
8
+ include Traits::Select
9
9
 
10
- def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint:, label:, caption:, form_group:, options: {}, **kwargs, &block)
11
- super(builder, object_name, attribute_name, &block)
10
+ def initialize(builder, object_name, attribute_name, choices, options:, form_group:, label:, hint:, caption:, **kwargs, &block)
11
+ # assign the block to an variable rather than passing to super so
12
+ # we can send it through to #select
13
+ super(builder, object_name, attribute_name)
14
+ @block = block
12
15
 
13
- @collection = collection
14
- @value_method = value_method
15
- @text_method = text_method
16
- @options = options
16
+ @form_group = form_group
17
+ @hint = hint
17
18
  @label = label
18
19
  @caption = caption
19
- @hint = hint
20
- @form_group = form_group
20
+ @choices = choices
21
+ @options = options
21
22
  @html_attributes = kwargs
22
-
23
- # FIXME remove this soon, worth informing people who miss the release notes that the
24
- # args have changed though.
25
- if :html_options.in?(kwargs.keys)
26
- Rails.logger.warn("GOVUKDesignSystemFormBuilder: html_options has been deprecated, use keyword arguments instead")
27
- end
28
23
  end
29
24
 
30
25
  def html
31
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
32
- safe_join([label_element, supplemental_content, hint_element, error_element, select])
26
+ Containers::FormGroup.new(*bound, **@form_group).html do
27
+ safe_join([label_element, hint_element, error_element, select])
33
28
  end
34
29
  end
35
30
 
36
31
  private
37
32
 
38
33
  def select
39
- @builder.collection_select(@attribute_name, @collection, @value_method, @text_method, @options, **attributes(@html_attributes))
34
+ @builder.select(@attribute_name, @choices, @options, attributes(@html_attributes), &@block)
40
35
  end
41
36
 
42
37
  def options
43
38
  {
44
39
  id: field_id(link_errors: true),
45
40
  class: classes,
46
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
41
+ aria: { describedby: described_by(hint_id, error_id) }
47
42
  }
48
43
  end
49
-
50
- def classes
51
- [%(#{brand}-select), error_class].flatten.compact
52
- end
53
-
54
- def error_class
55
- %(#{brand}-select--error) if has_errors?
56
- end
57
44
  end
58
45
  end
59
46
  end
@@ -21,19 +21,19 @@ module GOVUKDesignSystemFormBuilder
21
21
  end
22
22
 
23
23
  def html
24
- @block_content.present? ? button_group : buttons
24
+ @block_content.present? ? button_group : submit
25
25
  end
26
26
 
27
27
  private
28
28
 
29
- def buttons
30
- safe_join([submit, @block_content])
31
- end
32
-
33
29
  def button_group
34
30
  Containers::ButtonGroup.new(@builder, buttons).html
35
31
  end
36
32
 
33
+ def buttons
34
+ safe_join([submit, @block_content])
35
+ end
36
+
37
37
  def submit
38
38
  @builder.submit(@text, **attributes(@html_attributes))
39
39
  end
@@ -25,7 +25,7 @@ module GOVUKDesignSystemFormBuilder
25
25
 
26
26
  def html
27
27
  Containers::CharacterCount.new(@builder, **character_count_options).html do
28
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
28
+ Containers::FormGroup.new(*bound, **@form_group).html do
29
29
  safe_join([label_element, supplemental_content, hint_element, error_element, text_area, limit_description])
30
30
  end
31
31
  end
@@ -78,7 +78,7 @@ module GOVUKDesignSystemFormBuilder
78
78
  end
79
79
 
80
80
  def limit_description
81
- return nil unless limit?
81
+ return unless limit?
82
82
 
83
83
  tag.span(id: limit_id, class: limit_description_classes, aria: { live: 'polite' }) do
84
84
  "You can enter up to #{limit_quantity} #{limit_type}"
@@ -90,7 +90,7 @@ module GOVUKDesignSystemFormBuilder
90
90
  end
91
91
 
92
92
  def limit_description_id
93
- return nil unless limit?
93
+ return unless limit?
94
94
 
95
95
  limit_id
96
96
  end
@@ -7,7 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  @caption_element ||= if @caption.nil?
8
8
  Elements::Null.new
9
9
  else
10
- Elements::Caption.new(@builder, @object_name, @attribute_name, **@caption)
10
+ Elements::Caption.new(*bound, **@caption)
11
11
  end
12
12
  end
13
13
  end
@@ -2,7 +2,7 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Traits
3
3
  module Error
4
4
  def error_id
5
- return nil unless has_errors?
5
+ return unless has_errors?
6
6
 
7
7
  build_id('error')
8
8
  end
@@ -10,7 +10,7 @@ module GOVUKDesignSystemFormBuilder
10
10
  private
11
11
 
12
12
  def error_element
13
- @error_element ||= Elements::ErrorMessage.new(@builder, @object_name, @attribute_name)
13
+ @error_element ||= Elements::ErrorMessage.new(*bound)
14
14
  end
15
15
  end
16
16
  end
@@ -7,7 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  @label_element ||= if @label.nil?
8
8
  Elements::Null.new
9
9
  else
10
- Elements::Label.new(@builder, @object_name, @attribute_name, **label_content, **label_options)
10
+ Elements::Label.new(*bound, **label_content, **label_options)
11
11
  end
12
12
  end
13
13
 
@@ -19,7 +19,7 @@ module GOVUKDesignSystemFormBuilder
19
19
  @hint_element ||= if @hint.nil?
20
20
  Elements::Null.new
21
21
  else
22
- Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_options, **hint_content)
22
+ Elements::Hint.new(*bound, **hint_options, **hint_content)
23
23
  end
24
24
  end
25
25
 
@@ -2,7 +2,7 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Traits
3
3
  module Hint
4
4
  def hint_id
5
- return nil unless hint_element.active?
5
+ return unless hint_element.active?
6
6
 
7
7
  build_id('hint')
8
8
  end
@@ -13,7 +13,7 @@ module GOVUKDesignSystemFormBuilder
13
13
  @hint_element ||= if @hint.nil?
14
14
  Elements::Null.new
15
15
  else
16
- Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_content)
16
+ Elements::Hint.new(*bound, **hint_content)
17
17
  end
18
18
  end
19
19
 
@@ -1,8 +1,69 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Traits
3
3
  module HTMLAttributes
4
+ # Attributes eases working with default and custom attributes by:
5
+ # * deeply merging them so both the default (required) attributes are
6
+ # present
7
+ # * joins the arrays into strings to maintain Rails 6.0.3 compatibility
8
+ class Attributes
9
+ # Don't try to deep merge these fields, when we remove duplicates
10
+ # whilst merging the resulting values later, repeating words are lost
11
+ SKIP = [
12
+ %i(id),
13
+ %i(value),
14
+ %i(title),
15
+ %i(alt),
16
+ %i(href),
17
+ %i(aria label)
18
+ ].freeze
19
+
20
+ def initialize(defaults, custom)
21
+ @merged = defaults.deeper_merge(deep_split_values(custom))
22
+ end
23
+
24
+ def to_h
25
+ deep_join_values(@merged)
26
+ end
27
+
28
+ private
29
+
30
+ def deep_split_values(hash, parent = nil)
31
+ hash.each.with_object({}) do |(key, value), result|
32
+ result[key] = case value
33
+ when Hash
34
+ deep_split_values(value, key)
35
+ when String
36
+ split_list_values(key, value, parent)
37
+ else
38
+ value
39
+ end
40
+ end
41
+ end
42
+
43
+ def split_list_values(key, value, parent = nil)
44
+ if [parent, key].compact.in?(SKIP)
45
+ value
46
+ else
47
+ value.split
48
+ end
49
+ end
50
+
51
+ def deep_join_values(hash)
52
+ hash.each.with_object({}) do |(key, value), result|
53
+ result[key] = case value
54
+ when Hash
55
+ deep_join_values(value)
56
+ when Array
57
+ value.uniq.join(' ').presence
58
+ else
59
+ value
60
+ end
61
+ end
62
+ end
63
+ end
64
+
4
65
  def attributes(html_attributes = {})
5
- options.deeper_merge(html_attributes)
66
+ Attributes.new(options, html_attributes).to_h
6
67
  end
7
68
  end
8
69
  end
@@ -15,7 +15,7 @@ module GOVUKDesignSystemFormBuilder
15
15
  end
16
16
 
17
17
  def html
18
- Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
18
+ Containers::FormGroup.new(*bound, **@form_group).html do
19
19
  safe_join([label_element, supplemental_content, hint_element, error_element, content])
20
20
  end
21
21
  end
@@ -31,7 +31,7 @@ module GOVUKDesignSystemFormBuilder
31
31
  end
32
32
 
33
33
  def affixed_input
34
- content_tag('div', class: %(#{brand}-input__wrapper)) do
34
+ tag.div(class: %(#{brand}-input__wrapper)) do
35
35
  safe_join([prefix, input, suffix])
36
36
  end
37
37
  end
@@ -86,13 +86,13 @@ module GOVUKDesignSystemFormBuilder
86
86
  end
87
87
 
88
88
  def prefix
89
- return nil if @prefix_text.blank?
89
+ return if @prefix_text.blank?
90
90
 
91
91
  tag.span(@prefix_text, class: %(#{brand}-input__prefix), **affix_options)
92
92
  end
93
93
 
94
94
  def suffix
95
- return nil if @suffix_text.blank?
95
+ return if @suffix_text.blank?
96
96
 
97
97
  tag.span(@suffix_text, class: %(#{brand}-input__suffix), **affix_options)
98
98
  end
@@ -7,7 +7,7 @@ module GOVUKDesignSystemFormBuilder
7
7
  @label_element ||= if @label.nil?
8
8
  Elements::Null.new
9
9
  else
10
- Elements::Label.new(@builder, @object_name, @attribute_name, caption: @caption, **label_content)
10
+ Elements::Label.new(*bound, caption: @caption, **label_content)
11
11
  end
12
12
  end
13
13
 
@@ -0,0 +1,15 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Traits
3
+ module Select
4
+ private
5
+
6
+ def classes
7
+ [%(#{brand}-select), error_class].flatten.compact
8
+ end
9
+
10
+ def error_class
11
+ %(#{brand}-select--error) if has_errors?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,7 +2,7 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Traits
3
3
  module Supplemental
4
4
  def supplemental_id
5
- return nil if @block_content.blank?
5
+ return if @block_content.blank?
6
6
 
7
7
  build_id('supplemental')
8
8
  end
@@ -10,7 +10,7 @@ module GOVUKDesignSystemFormBuilder
10
10
  private
11
11
 
12
12
  def supplemental_content
13
- @supplemental_content ||= Containers::Supplemental.new(@builder, @object_name, @attribute_name, @block_content)
13
+ @supplemental_content ||= Containers::Supplemental.new(*bound, @block_content)
14
14
  end
15
15
  end
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
- VERSION = '2.3.0b1'.freeze
2
+ VERSION = '2.5.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_design_system_formbuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0b1
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Yates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-18 00:00:00.000000000 Z
11
+ date: 2021-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -30,42 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '5.2'
33
+ version: '6.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '5.2'
40
+ version: '6.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activemodel
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '5.2'
47
+ version: '6.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '5.2'
54
+ version: '6.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activesupport
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '5.2'
61
+ version: '6.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '5.2'
68
+ version: '6.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop-govuk
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '4.0'
137
+ version: '5.0'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '4.0'
144
+ version: '5.0'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: simplecov
147
147
  requirement: !ruby/object:Gem::Requirement
@@ -255,19 +255,33 @@ dependencies:
255
255
  - !ruby/object:Gem::Version
256
256
  version: 4.1.0
257
257
  - !ruby/object:Gem::Dependency
258
- name: puma
258
+ name: webrick
259
259
  requirement: !ruby/object:Gem::Requirement
260
260
  requirements:
261
261
  - - "~>"
262
262
  - !ruby/object:Gem::Version
263
- version: '5.2'
263
+ version: 1.7.0
264
264
  type: :development
265
265
  prerelease: false
266
266
  version_requirements: !ruby/object:Gem::Requirement
267
267
  requirements:
268
268
  - - "~>"
269
269
  - !ruby/object:Gem::Version
270
- version: '5.2'
270
+ version: 1.7.0
271
+ - !ruby/object:Gem::Dependency
272
+ name: slim_lint
273
+ requirement: !ruby/object:Gem::Requirement
274
+ requirements:
275
+ - - "~>"
276
+ - !ruby/object:Gem::Version
277
+ version: 0.20.2
278
+ type: :development
279
+ prerelease: false
280
+ version_requirements: !ruby/object:Gem::Requirement
281
+ requirements:
282
+ - - "~>"
283
+ - !ruby/object:Gem::Version
284
+ version: 0.20.2
271
285
  description: A Rails form builder that generates form inputs adhering to the GOV.UK
272
286
  Design System
273
287
  email:
@@ -295,6 +309,7 @@ files:
295
309
  - lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb
296
310
  - lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb
297
311
  - lib/govuk_design_system_formbuilder/elements/check_boxes/label.rb
312
+ - lib/govuk_design_system_formbuilder/elements/collection_select.rb
298
313
  - lib/govuk_design_system_formbuilder/elements/date.rb
299
314
  - lib/govuk_design_system_formbuilder/elements/error_message.rb
300
315
  - lib/govuk_design_system_formbuilder/elements/error_summary.rb
@@ -325,6 +340,7 @@ files:
325
340
  - lib/govuk_design_system_formbuilder/traits/input.rb
326
341
  - lib/govuk_design_system_formbuilder/traits/label.rb
327
342
  - lib/govuk_design_system_formbuilder/traits/localisation.rb
343
+ - lib/govuk_design_system_formbuilder/traits/select.rb
328
344
  - lib/govuk_design_system_formbuilder/traits/supplemental.rb
329
345
  - lib/govuk_design_system_formbuilder/version.rb
330
346
  homepage: https://govuk-form-builder.netlify.app
@@ -347,11 +363,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
347
363
  version: '0'
348
364
  required_rubygems_version: !ruby/object:Gem::Requirement
349
365
  requirements:
350
- - - ">"
366
+ - - ">="
351
367
  - !ruby/object:Gem::Version
352
- version: 1.3.1
368
+ version: '0'
353
369
  requirements: []
354
- rubygems_version: 3.1.4
370
+ rubygems_version: 3.1.6
355
371
  signing_key:
356
372
  specification_version: 4
357
373
  summary: GOV.UK-compliant Rails form builder