govuk_design_system_formbuilder 2.3.0 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f56b92f232ffd2b98c38637c49b2e4255f3be12cab3825f795a735cbfae0107
4
- data.tar.gz: 0f4dfd572130559b3140a838310ce471a4adee41f46fed32ca5046cfa29ed9d0
3
+ metadata.gz: 6307ddd694fd135e13d060b9cb742464e8c5579da4d1026dfffaffedb26c8c39
4
+ data.tar.gz: 7238c7b22b04727d86393822df54284c97a74197b2d887b2bf7f89e27fadfa2a
5
5
  SHA512:
6
- metadata.gz: 67861fee01f6a14cac7bbf9db87d1633dcf13e569aaa2179f5e16d21f8aed5e7b7d553a5bd96e601ab5b4181e6c27c905fa5fd6d7e80c811a2cff28d42b1f83f
7
- data.tar.gz: a889d6d02fd1978e73aa2328debc5b6268993eca88755b3cf31889dfe4c973d28e09dfb9d13bbe462347aeea74a1f46dfb8ba8f4f7c20ad3da5c2c8d1d6aa114
6
+ metadata.gz: 63a462903bafafb449b2e6ec8d17e269360fc62fa75fd8f5ffda238a8529f23a6725080de31884c681bb8ce106f806d4e728b88e22a5e89dff96919a90addfc9
7
+ data.tar.gz: 5f78fdecbd0e4c67b3a9b6ea26854dfd1658a1cbd4da59b01527947ccb4ba89dc1444b39b1ffb03090820142a15fafd25ca2e444a1715259d7216a8a6e84f300
data/README.md CHANGED
@@ -7,9 +7,9 @@
7
7
  [![Test Coverage](https://api.codeclimate.com/v1/badges/fde73b5dc9476197281b/test_coverage)](https://codeclimate.com/github/DFE-Digital/govuk_design_system_formbuilder/test_coverage)
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
- [![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/)
10
+ [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-3.12.0-brightgreen)](https://design-system.service.gov.uk)
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
 
@@ -1,7 +1,7 @@
1
1
  require 'deep_merge/rails_compat'
2
2
  require 'active_support/configurable'
3
3
 
4
- [%w(traits *.rb), %w(*.rb), %w(elements ** *.rb), %w(containers ** *.rb)]
4
+ [%w(refinements *.rb), %w(traits *.rb), %w(*.rb), %w(elements ** *.rb), %w(containers ** *.rb)]
5
5
  .flat_map { |matcher| Dir.glob(File.join(__dir__, 'govuk_design_system_formbuilder', *matcher)) }
6
6
  .each { |file| require file }
7
7
 
@@ -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] } }
@@ -1,12 +1,4 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
- module PrefixableArray
3
- refine Array do
4
- def prefix(text, delimiter: '-')
5
- map { |item| text + delimiter + item }
6
- end
7
- end
8
- end
9
-
10
2
  class Base
11
3
  delegate :content_tag, :safe_join, :tag, :link_to, :capture, to: :@builder
12
4
  delegate :config, to: GOVUKDesignSystemFormBuilder
@@ -66,7 +58,7 @@ module GOVUKDesignSystemFormBuilder
66
58
  end
67
59
 
68
60
  def described_by(*ids)
69
- ids.flatten.compact.join(' ').presence
61
+ ids.flatten.compact
70
62
  end
71
63
 
72
64
  # Builds the values used for HTML id attributes throughout the builder
@@ -96,5 +88,11 @@ module GOVUKDesignSystemFormBuilder
96
88
  .parameterize
97
89
  .tr(replace, delimiter)
98
90
  end
91
+
92
+ def warn(message)
93
+ return unless config.enable_logger
94
+
95
+ Rails.logger.warn(message)
96
+ end
99
97
  end
100
98
  end
@@ -381,6 +381,7 @@ 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
@@ -412,7 +413,7 @@ module GOVUKDesignSystemFormBuilder
412
413
  # label: -> { tag.h3("Which team did you represent?") }
413
414
  #
414
415
  def govuk_collection_select(attribute_name, collection, value_method, text_method, options: {}, hint: {}, label: {}, caption: {}, form_group: {}, **kwargs, &block)
415
- Elements::Select.new(
416
+ Elements::CollectionSelect.new(
416
417
  self,
417
418
  object_name,
418
419
  attribute_name,
@@ -429,6 +430,42 @@ module GOVUKDesignSystemFormBuilder
429
430
  ).html
430
431
  end
431
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
+
432
469
  # Generates a radio button for each item in the supplied collection
433
470
  #
434
471
  # @note Unlike the Rails +#collection_radio_buttons+ helper, this version can also insert
@@ -842,6 +879,7 @@ module GOVUKDesignSystemFormBuilder
842
879
  # @note When using this input be aware that Rails's multiparam time and date handling falls foul
843
880
  # of {https://bugs.ruby-lang.org/issues/5988 this} bug, so incorrect dates like +2019-09-31+ will
844
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
845
883
  # @param attribute_name [Symbol] The name of the attribute
846
884
  # @param hint [Hash,Proc] The content of the hint. No hint will be added if 'text' is left +nil+. When a +Proc+ is
847
885
  # supplied the hint will be wrapped in a +div+ instead of a +span+
@@ -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
 
@@ -2,13 +2,10 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module CheckBoxes
4
4
  class FieldsetCheckBox < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Label
8
6
  include Traits::Hint
9
- include Traits::FieldsetItem
10
- include Traits::Conditional
11
7
  include Traits::HTMLAttributes
8
+ include Traits::FieldsetItem
12
9
 
13
10
  def initialize(builder, object_name, attribute_name, value, unchecked_value, label:, hint:, link_errors:, multiple:, **kwargs, &block)
14
11
  super(builder, object_name, attribute_name)
@@ -21,49 +18,22 @@ module GOVUKDesignSystemFormBuilder
21
18
  @link_errors = link_errors
22
19
  @html_attributes = kwargs
23
20
 
24
- if block_given?
25
- @conditional_content = wrap_conditional(block)
26
- @conditional_id = conditional_id
27
- end
28
- end
29
-
30
- def html
31
- safe_join([item, @conditional_content])
21
+ conditional_content(&block)
32
22
  end
33
23
 
34
24
  private
35
25
 
36
- def item
37
- tag.div(class: %(#{brand}-checkboxes__item)) do
38
- safe_join([check_box, label_element, hint_element])
39
- end
26
+ def input_type
27
+ :checkboxes
40
28
  end
41
29
 
42
- def check_box
30
+ def input
43
31
  @builder.check_box(@attribute_name, attributes(@html_attributes), @value, @unchecked_value)
44
32
  end
45
33
 
46
- def options
47
- {
48
- id: field_id(link_errors: @link_errors),
49
- class: classes,
50
- multiple: @multiple,
51
- aria: { describedby: hint_id },
52
- data: { 'aria-controls' => @conditional_id }
53
- }
54
- end
55
-
56
- def classes
57
- %w(checkboxes__input).prefix(brand)
58
- end
59
-
60
34
  def fieldset_options
61
35
  { checkbox: true }
62
36
  end
63
-
64
- def conditional_classes
65
- %w(checkboxes__conditional checkboxes__conditional--hidden).prefix(brand)
66
- end
67
37
  end
68
38
  end
69
39
  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)
@@ -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,
@@ -2,13 +2,10 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Radios
4
4
  class FieldsetRadioButton < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Label
8
6
  include Traits::Hint
9
- include Traits::FieldsetItem
10
- include Traits::Conditional
11
7
  include Traits::HTMLAttributes
8
+ include Traits::FieldsetItem
12
9
 
13
10
  def initialize(builder, object_name, attribute_name, value, label:, hint:, link_errors:, **kwargs, &block)
14
11
  super(builder, object_name, attribute_name)
@@ -19,43 +16,21 @@ module GOVUKDesignSystemFormBuilder
19
16
  @link_errors = has_errors? && link_errors
20
17
  @html_attributes = kwargs
21
18
 
22
- if block_given?
23
- @conditional_content = wrap_conditional(block)
24
- @conditional_id = conditional_id
25
- end
26
- end
27
-
28
- def html
29
- safe_join([radio, @conditional_content])
19
+ conditional_content(&block)
30
20
  end
31
21
 
32
22
  private
33
23
 
34
- def radio
35
- tag.div(class: %(#{brand}-radios__item)) do
36
- safe_join([input, label_element, hint_element])
37
- end
38
- end
39
-
40
- def fieldset_options
41
- { radio: true }
24
+ def input_type
25
+ :radios
42
26
  end
43
27
 
44
28
  def input
45
29
  @builder.radio_button(@attribute_name, @value, **attributes(@html_attributes))
46
30
  end
47
31
 
48
- def options
49
- {
50
- id: field_id(link_errors: @link_errors),
51
- aria: { describedby: hint_id },
52
- data: { 'aria-controls' => @conditional_id },
53
- class: %w(radios__input).prefix(brand)
54
- }
55
- end
56
-
57
- def conditional_classes
58
- %w(radios__conditional radios__conditional--hidden).prefix(brand)
32
+ def fieldset_options
33
+ { radio: true }
59
34
  end
60
35
  end
61
36
  end
@@ -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
26
  Containers::FormGroup.new(*bound, **@form_group).html do
32
- safe_join([label_element, supplemental_content, hint_element, error_element, select])
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
@@ -0,0 +1,9 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module PrefixableArray
3
+ refine Array do
4
+ def prefix(text, delimiter: '-')
5
+ map { |item| [text, item].join(delimiter.to_s) }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,8 +1,38 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Traits
3
3
  module FieldsetItem
4
+ using PrefixableArray
5
+
6
+ def html
7
+ safe_join([item, @conditional])
8
+ end
9
+
4
10
  private
5
11
 
12
+ def class_prefix
13
+ %(#{brand}-#{input_type})
14
+ end
15
+
16
+ def item
17
+ tag.div(class: %(#{class_prefix}__item)) do
18
+ safe_join([input, label_element, hint_element])
19
+ end
20
+ end
21
+
22
+ def options
23
+ {
24
+ id: field_id(link_errors: @link_errors),
25
+ class: classes,
26
+ multiple: @multiple,
27
+ aria: { describedby: [hint_id] },
28
+ data: { 'aria-controls' => @conditional_id }
29
+ }
30
+ end
31
+
32
+ def classes
33
+ [%(#{class_prefix}__input)]
34
+ end
35
+
6
36
  def label_element
7
37
  @label_element ||= if @label.nil?
8
38
  Elements::Null.new
@@ -26,6 +56,27 @@ module GOVUKDesignSystemFormBuilder
26
56
  def hint_options
27
57
  { value: @value }.merge(fieldset_options)
28
58
  end
59
+
60
+ def conditional_id
61
+ build_id('conditional')
62
+ end
63
+
64
+ def conditional_content(&block)
65
+ if (conditional_block_content = block_given? && block.call.presence)
66
+ @conditional = conditional_container(conditional_block_content)
67
+ @conditional_id = conditional_id
68
+ end
69
+ end
70
+
71
+ def conditional_container(content)
72
+ tag.div(class: conditional_classes, id: conditional_id) do
73
+ capture { content }
74
+ end
75
+ end
76
+
77
+ def conditional_classes
78
+ %w(__conditional __conditional--hidden).prefix(class_prefix, delimiter: nil)
79
+ end
29
80
  end
30
81
  end
31
82
  end
@@ -1,8 +1,62 @@
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
+ # Rather than attempt to combine these attributes, just overwrite the
10
+ # form internally-generated values with those that are passed in. This
11
+ # prevents the merge/unique value logic from affecting the content
12
+ # (i.e. by remvoving duplicated words).
13
+ UNMERGEABLE = [%i(id), %i(value), %i(title), %i(alt), %i(href), %i(aria label)].freeze
14
+
15
+ def initialize(defaults, custom)
16
+ @merged = defaults.deeper_merge(deep_split_values(custom))
17
+ end
18
+
19
+ def to_h
20
+ deep_join_values(@merged)
21
+ end
22
+
23
+ private
24
+
25
+ def deep_split_values(hash, parent = nil)
26
+ hash.each.with_object({}) do |(key, value), result|
27
+ result[key] = case value
28
+ when Hash
29
+ deep_split_values(value, key)
30
+ when String
31
+ split_mergeable(key, value, parent)
32
+ else
33
+ value
34
+ end
35
+ end
36
+ end
37
+
38
+ def split_mergeable(key, value, parent = nil)
39
+ return value if [parent, key].compact.in?(UNMERGEABLE)
40
+
41
+ value.split
42
+ end
43
+
44
+ def deep_join_values(hash)
45
+ hash.each.with_object({}) do |(key, value), result|
46
+ result[key] = case value
47
+ when Hash
48
+ deep_join_values(value)
49
+ when Array
50
+ value.uniq.join(' ').presence
51
+ else
52
+ value
53
+ end
54
+ end
55
+ end
56
+ end
57
+
4
58
  def attributes(html_attributes = {})
5
- options.deeper_merge(html_attributes)
59
+ Attributes.new(options, html_attributes).to_h
6
60
  end
7
61
  end
8
62
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
- VERSION = '2.3.0'.freeze
2
+ VERSION = '2.5.2'.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.0
4
+ version: 2.5.2
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-30 00:00:00.000000000 Z
11
+ date: 2021-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -28,58 +28,76 @@ dependencies:
28
28
  name: actionview
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 6.1.3.1
31
34
  - - ">="
32
35
  - !ruby/object:Gem::Version
33
- version: '5.2'
36
+ version: '6.1'
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: 6.1.3.1
38
44
  - - ">="
39
45
  - !ruby/object:Gem::Version
40
- version: '5.2'
46
+ version: '6.1'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: activemodel
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 6.1.3.1
45
54
  - - ">="
46
55
  - !ruby/object:Gem::Version
47
- version: '5.2'
56
+ version: '6.1'
48
57
  type: :runtime
49
58
  prerelease: false
50
59
  version_requirements: !ruby/object:Gem::Requirement
51
60
  requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: 6.1.3.1
52
64
  - - ">="
53
65
  - !ruby/object:Gem::Version
54
- version: '5.2'
66
+ version: '6.1'
55
67
  - !ruby/object:Gem::Dependency
56
68
  name: activesupport
57
69
  requirement: !ruby/object:Gem::Requirement
58
70
  requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: 6.1.3.1
59
74
  - - ">="
60
75
  - !ruby/object:Gem::Version
61
- version: '5.2'
76
+ version: '6.1'
62
77
  type: :runtime
63
78
  prerelease: false
64
79
  version_requirements: !ruby/object:Gem::Requirement
65
80
  requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 6.1.3.1
66
84
  - - ">="
67
85
  - !ruby/object:Gem::Version
68
- version: '5.2'
86
+ version: '6.1'
69
87
  - !ruby/object:Gem::Dependency
70
88
  name: rubocop-govuk
71
89
  requirement: !ruby/object:Gem::Requirement
72
90
  requirements:
73
- - - '='
91
+ - - "~>"
74
92
  - !ruby/object:Gem::Version
75
- version: 4.0.0.pre.1
93
+ version: 4.0.0
76
94
  type: :development
77
95
  prerelease: false
78
96
  version_requirements: !ruby/object:Gem::Requirement
79
97
  requirements:
80
- - - '='
98
+ - - "~>"
81
99
  - !ruby/object:Gem::Version
82
- version: 4.0.0.pre.1
100
+ version: 4.0.0
83
101
  - !ruby/object:Gem::Dependency
84
102
  name: pry
85
103
  requirement: !ruby/object:Gem::Requirement
@@ -134,14 +152,14 @@ dependencies:
134
152
  requirements:
135
153
  - - "~>"
136
154
  - !ruby/object:Gem::Version
137
- version: '4.0'
155
+ version: '5.0'
138
156
  type: :development
139
157
  prerelease: false
140
158
  version_requirements: !ruby/object:Gem::Requirement
141
159
  requirements:
142
160
  - - "~>"
143
161
  - !ruby/object:Gem::Version
144
- version: '4.0'
162
+ version: '5.0'
145
163
  - !ruby/object:Gem::Dependency
146
164
  name: simplecov
147
165
  requirement: !ruby/object:Gem::Requirement
@@ -255,19 +273,33 @@ dependencies:
255
273
  - !ruby/object:Gem::Version
256
274
  version: 4.1.0
257
275
  - !ruby/object:Gem::Dependency
258
- name: puma
276
+ name: webrick
277
+ requirement: !ruby/object:Gem::Requirement
278
+ requirements:
279
+ - - "~>"
280
+ - !ruby/object:Gem::Version
281
+ version: 1.7.0
282
+ type: :development
283
+ prerelease: false
284
+ version_requirements: !ruby/object:Gem::Requirement
285
+ requirements:
286
+ - - "~>"
287
+ - !ruby/object:Gem::Version
288
+ version: 1.7.0
289
+ - !ruby/object:Gem::Dependency
290
+ name: slim_lint
259
291
  requirement: !ruby/object:Gem::Requirement
260
292
  requirements:
261
293
  - - "~>"
262
294
  - !ruby/object:Gem::Version
263
- version: '5.2'
295
+ version: 0.21.1
264
296
  type: :development
265
297
  prerelease: false
266
298
  version_requirements: !ruby/object:Gem::Requirement
267
299
  requirements:
268
300
  - - "~>"
269
301
  - !ruby/object:Gem::Version
270
- version: '5.2'
302
+ version: 0.21.1
271
303
  description: A Rails form builder that generates form inputs adhering to the GOV.UK
272
304
  Design System
273
305
  email:
@@ -295,6 +327,7 @@ files:
295
327
  - lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb
296
328
  - lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb
297
329
  - lib/govuk_design_system_formbuilder/elements/check_boxes/label.rb
330
+ - lib/govuk_design_system_formbuilder/elements/collection_select.rb
298
331
  - lib/govuk_design_system_formbuilder/elements/date.rb
299
332
  - lib/govuk_design_system_formbuilder/elements/error_message.rb
300
333
  - lib/govuk_design_system_formbuilder/elements/error_summary.rb
@@ -315,9 +348,9 @@ files:
315
348
  - lib/govuk_design_system_formbuilder/elements/select.rb
316
349
  - lib/govuk_design_system_formbuilder/elements/submit.rb
317
350
  - lib/govuk_design_system_formbuilder/elements/text_area.rb
351
+ - lib/govuk_design_system_formbuilder/refinements/prefixable_array.rb
318
352
  - lib/govuk_design_system_formbuilder/traits/caption.rb
319
353
  - lib/govuk_design_system_formbuilder/traits/collection_item.rb
320
- - lib/govuk_design_system_formbuilder/traits/conditional.rb
321
354
  - lib/govuk_design_system_formbuilder/traits/error.rb
322
355
  - lib/govuk_design_system_formbuilder/traits/fieldset_item.rb
323
356
  - lib/govuk_design_system_formbuilder/traits/hint.rb
@@ -325,6 +358,7 @@ files:
325
358
  - lib/govuk_design_system_formbuilder/traits/input.rb
326
359
  - lib/govuk_design_system_formbuilder/traits/label.rb
327
360
  - lib/govuk_design_system_formbuilder/traits/localisation.rb
361
+ - lib/govuk_design_system_formbuilder/traits/select.rb
328
362
  - lib/govuk_design_system_formbuilder/traits/supplemental.rb
329
363
  - lib/govuk_design_system_formbuilder/version.rb
330
364
  homepage: https://govuk-form-builder.netlify.app
@@ -351,7 +385,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
351
385
  - !ruby/object:Gem::Version
352
386
  version: '0'
353
387
  requirements: []
354
- rubygems_version: 3.1.4
388
+ rubygems_version: 3.1.6
355
389
  signing_key:
356
390
  specification_version: 4
357
391
  summary: GOV.UK-compliant Rails form builder
@@ -1,17 +0,0 @@
1
- module GOVUKDesignSystemFormBuilder
2
- module Traits
3
- module Conditional
4
- private
5
-
6
- def conditional_id
7
- build_id('conditional')
8
- end
9
-
10
- def wrap_conditional(block)
11
- tag.div(class: conditional_classes, id: conditional_id) do
12
- capture { block.call }
13
- end
14
- end
15
- end
16
- end
17
- end