govuk_design_system_formbuilder 2.5.1 → 2.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98eb37a7c0dc6926abc94003671567e1d6d9ff64026d92dbd2bbeb62e132b5ac
4
- data.tar.gz: 3bdd6d81f7c94f28e39841088d056c8eb7615dab89cd750e589d516f71faae0a
3
+ metadata.gz: '08308443752eddad69642235b4098b788ed5c5eb701b6f97d344171b9654a135'
4
+ data.tar.gz: 0f3b209aee144ea52d46798b14a29ea1a85b9acf545413d0219efeff03b92e8e
5
5
  SHA512:
6
- metadata.gz: eae5b13528432a2c01a85aba212b74ecfcdb5740ecbe43bf6548749ebc1ab98b7a37281f7bea6b4e85964d73076e19a1a05326011d2edd71f1599075e6545e2b
7
- data.tar.gz: c24c784e74e4ae48fdafcca7bf3ba3b5e5f3e22a371f0b5e16bd6fc364f1cb3d386be4bff9ea03de0ce3d5857676eca58001b09284a625d9fcd2dc6ef728a9e5
6
+ metadata.gz: 425224ce7905d2dd33d2123698c6f35f68e2ac640743326f811ab7b45241134f640bc054b7b75a3813edd2be558b794119437d8d4917adbe03f5cc42e38a74b9
7
+ data.tar.gz: 22d147336200ed390422201ece082289db29d6ee637aad76157195c9401fbbe52cfe6c9c9a80cd357f41543d133009a248a207547b0debaae46503503d26fe93
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)
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
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/)
12
+ [![Ruby](https://img.shields.io/badge/Rails-6.0.4%20%E2%95%B1%206.1.3.2-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
 
@@ -41,6 +41,10 @@ module GOVUKDesignSystemFormBuilder
41
41
  # * +:default_collection_radio_buttons_include_hidden+ controls whether or not
42
42
  # a hidden field is added when rendering a collection of radio buttons
43
43
  #
44
+ # * +:default_error_summary_error_order_method+ is the method that the library
45
+ # will check for on the bound object to see whether or not to try ordering the
46
+ # error messages
47
+ #
44
48
  # * +:localisation_schema_fallback+ sets the prefix elements for the array
45
49
  # used to build the localisation string. The final two elements are always
46
50
  # are the object name and attribute name. The _special_ value +__context__+,
@@ -62,6 +66,7 @@ module GOVUKDesignSystemFormBuilder
62
66
  default_submit_button_text: 'Continue',
63
67
  default_radio_divider_text: 'or',
64
68
  default_error_summary_title: 'There is a problem',
69
+ default_error_summary_error_order_method: nil,
65
70
  default_collection_check_boxes_include_hidden: true,
66
71
  default_collection_radio_buttons_include_hidden: true,
67
72
  default_submit_validate: false,
@@ -108,6 +113,8 @@ module GOVUKDesignSystemFormBuilder
108
113
  include GOVUKDesignSystemFormBuilder::Builder
109
114
  end
110
115
 
116
+ class FormBuilderProxy < FormBuilder; end
117
+
111
118
  # Disable Rails' div.field_with_error wrapper
112
119
  ActionView::Base.field_error_proc = ->(html_tag, _instance) { html_tag }
113
120
  end
@@ -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
@@ -23,21 +15,6 @@ module GOVUKDesignSystemFormBuilder
23
15
  html || ''
24
16
  end
25
17
 
26
- private
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
-
37
- def brand(override = nil)
38
- override || config.brand
39
- end
40
-
41
18
  # returns the id value used for the input
42
19
  #
43
20
  # @note field_id is overridden so that the error summary can link to the
@@ -59,6 +36,21 @@ module GOVUKDesignSystemFormBuilder
59
36
  end
60
37
  end
61
38
 
39
+ private
40
+
41
+ # returns the attributes bound to the object that are
42
+ # required to build all contained elements
43
+ #
44
+ # @return [GOVUKDesignSystemFormBuilder::FormBuilder, Symbol, Symbol] an array containing the
45
+ # builder, object name and attribute name
46
+ def bound
47
+ [@builder, @object_name, @attribute_name]
48
+ end
49
+
50
+ def brand(override = nil)
51
+ override || config.brand
52
+ end
53
+
62
54
  def has_errors?
63
55
  @builder.object.respond_to?(:errors) &&
64
56
  @builder.object.errors.any? &&
@@ -843,7 +843,7 @@ module GOVUKDesignSystemFormBuilder
843
843
 
844
844
  # Generates a submit button, green by default
845
845
  #
846
- # @param text [String] the button text
846
+ # @param text [String,Proc] the button text. When a +Proc+ is provided its contents will be rendered within the button element
847
847
  # @param warning [Boolean] makes the button red ({https://design-system.service.gov.uk/components/button/#warning-buttons warning}) when true
848
848
  # @param secondary [Boolean] makes the button grey ({https://design-system.service.gov.uk/components/button/#secondary-buttons secondary}) when true
849
849
  # @param classes [Array,String] Classes to add to the submit button
@@ -853,7 +853,7 @@ module GOVUKDesignSystemFormBuilder
853
853
  # client-side validation provided by the browser. This is to provide a more consistent and accessible user
854
854
  # experience
855
855
  # @param disabled [Boolean] makes the button disabled when true
856
- # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the +input+ element
856
+ # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the +button+ element
857
857
  # @param block [Block] When content is passed in via a block the submit element and the block content will
858
858
  # be wrapped in a +<div class="govuk-button-group">+ which will space the buttons and links within
859
859
  # evenly.
@@ -861,8 +861,9 @@ module GOVUKDesignSystemFormBuilder
861
861
  # @return [ActiveSupport::SafeBuffer] HTML output
862
862
  # @note Only the first additional button or link (passed in via a block) will be given the
863
863
  # correct left margin, subsequent buttons will need to be manually accounted for
864
- # @note This helper always renders an +<input type='submit'>+ tag, HTML content is not supported inside. You
865
- # can place +<button>+ tags inside the form to have the same effect
864
+ # @note This helper always renders an +<button type='submit'>+ tag. Previous versions of this gem rendered
865
+ # a +`<input type='submit'>' tag instead, but there is a {https://github.com/alphagov/govuk_elements/issues/545 longstanding bug}
866
+ # with this approach where the top few pixels don't initiate a submission when clicked.
866
867
  # @see https://design-system.service.gov.uk/components/button/#stop-users-from-accidentally-sending-information-more-than-once
867
868
  # GOV.UK double click prevention
868
869
  #
@@ -930,7 +931,11 @@ module GOVUKDesignSystemFormBuilder
930
931
  # @param title [String] the error summary heading
931
932
  # @param link_base_errors_to [Symbol,String] set the field that errors on +:base+ are linked
932
933
  # to, as there won't be a field representing the object base.
934
+ # @param order [Array<Symbol>] the attribute order in which error messages are displayed. Ordered
935
+ # attributes will appear first and unordered ones will be last, sorted in the default manner (in
936
+ # which they were defined on the model).
933
937
  # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the error summary +div+ element
938
+ # @param block [Block] arbitrary HTML that will be rendered between title and error message list
934
939
  #
935
940
  # @note Only the first error in the +#errors+ array for each attribute will
936
941
  # be included.
@@ -939,8 +944,8 @@ module GOVUKDesignSystemFormBuilder
939
944
  # = f.govuk_error_summary 'Uh-oh, spaghettios'
940
945
  #
941
946
  # @see https://design-system.service.gov.uk/components/error-summary/ GOV.UK error summary
942
- def govuk_error_summary(title = config.default_error_summary_title, link_base_errors_to: nil, **kwargs)
943
- Elements::ErrorSummary.new(self, object_name, title, link_base_errors_to: link_base_errors_to, **kwargs).html
947
+ def govuk_error_summary(title = config.default_error_summary_title, link_base_errors_to: nil, order: nil, **kwargs, &block)
948
+ Elements::ErrorSummary.new(self, object_name, title, link_base_errors_to: link_base_errors_to, order: order, **kwargs, &block).html
944
949
  end
945
950
 
946
951
  # Generates a fieldset containing the contents of the block
@@ -0,0 +1,65 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ # NOTE: this is currently considered experimental, it's likely to change based on feedback.
3
+ #
4
+ # BuilderHelper contains methods that expose the form builder's functionality
5
+ # externally. The objectives are to allow:
6
+ #
7
+ # * rendering the error summary outside of the form
8
+ #
9
+ # * setting the id of custom form elements (rich text editors, date pickers,
10
+ # sliders, etc) using the formbuilder's internal logic, allowing them to be
11
+ # linked from the error summary
12
+ module BuilderHelper
13
+ # Returns the form builder generated id for an object's attribute, allowing
14
+ # users to force their custom element ids to match those that'll be generated
15
+ # by the error summary.
16
+ # @param object [ActiveRecord::Base,ActiveModel::Model,Object] the object that we want to
17
+ # generate an id for
18
+ # @param object_name [Symbol] the object's name, the singular version of the object's class
19
+ # name, e.g., +Person+ is +:person+.
20
+ # @param attribute_name [Symbol] the attribute we're generating an id for
21
+ # @param value [Object] the value of the attribute. Only necessary for fields with
22
+ # multiple form elements like radio buttons and checkboxes
23
+ # @param link_errors [Boolean] toggles whether or not to override the field id with the
24
+ # error id when there are errors on the +object+. Only relevant for radio buttons
25
+ # and check boxes.
26
+ def govuk_field_id(object, attribute_name, object_name = nil, value: nil, link_errors: true)
27
+ (object_name = retrieve_object_name(object)) if object_name.nil?
28
+
29
+ proxy_base(object, object_name, attribute_name, value: value).field_id(link_errors: link_errors)
30
+ end
31
+
32
+ # Renders an error summary
33
+ # @param object [ActiveRecord::Base,ActiveModel::Model,Object] the object we'll be rendering
34
+ # the errors for
35
+ # @param object_name [Symbol] the object's name, the singular version of the object's class
36
+ # name, e.g., +Person+ is +:person+. If none is supplied we'll try to infer it from
37
+ # the object, so it'll probably be necessary for regular Ruby objects
38
+ # @option args [Array] options passed through to the builder's +#govuk_error_summary+
39
+ # @option kwargs [Hash] keyword options passed through to the builder's +#govuk_error_summary+
40
+ #
41
+ # @example
42
+ # = govuk_error_summary(@registration)
43
+ #
44
+ # @see https://design-system.service.gov.uk/components/error-summary/ GOV.UK error summary
45
+ def govuk_error_summary(object, object_name = nil, *args, **kwargs, &block)
46
+ (object_name = retrieve_object_name(object)) if object_name.nil?
47
+
48
+ proxy_builder(object, object_name, self, {}).govuk_error_summary(*args, **kwargs, &block)
49
+ end
50
+
51
+ private
52
+
53
+ def proxy_base(object, object_name, attribute_name, value: nil)
54
+ GOVUKDesignSystemFormBuilder::Proxy.new(object, object_name, attribute_name, value: value)
55
+ end
56
+
57
+ def proxy_builder(object, object_name, template, options)
58
+ GOVUKDesignSystemFormBuilder::FormBuilderProxy.new(object_name, object, template, options)
59
+ end
60
+
61
+ def retrieve_object_name(object)
62
+ object.to_model.model_name.singular
63
+ end
64
+ end
65
+ end
@@ -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
@@ -4,12 +4,13 @@ module GOVUKDesignSystemFormBuilder
4
4
  include Traits::Error
5
5
  include Traits::HTMLAttributes
6
6
 
7
- def initialize(builder, object_name, title, link_base_errors_to:, **kwargs)
8
- super(builder, object_name, nil)
7
+ def initialize(builder, object_name, title, link_base_errors_to:, order:, **kwargs, &block)
8
+ super(builder, object_name, nil, &block)
9
9
 
10
10
  @title = title
11
11
  @link_base_errors_to = link_base_errors_to
12
12
  @html_attributes = kwargs
13
+ @order = order
13
14
  end
14
15
 
15
16
  def html
@@ -27,17 +28,45 @@ module GOVUKDesignSystemFormBuilder
27
28
  end
28
29
 
29
30
  def summary
30
- tag.div(class: summary_class('body')) do
31
- tag.ul(class: [%(#{brand}-list), summary_class('list')]) do
32
- safe_join(list)
33
- end
34
- end
31
+ tag.div(class: summary_class('body')) { safe_join([@block_content, list]) }
35
32
  end
36
33
 
37
34
  def list
38
- @builder.object.errors.messages.map do |attribute, messages|
39
- list_item(attribute, messages.first)
35
+ tag.ul(class: [%(#{brand}-list), summary_class('list')]) do
36
+ safe_join(error_messages.map { |attribute, messages| list_item(attribute, messages.first) })
37
+ end
38
+ end
39
+
40
+ def error_messages
41
+ messages = @builder.object.errors.messages
42
+
43
+ if reorder_errors?
44
+ adjustment = error_order.size + messages.size
45
+
46
+ return messages.sort_by.with_index do |(attr, _val), i|
47
+ error_order.index(attr) || (i + adjustment)
48
+ end
40
49
  end
50
+
51
+ @builder.object.errors.messages
52
+ end
53
+
54
+ def reorder_errors?
55
+ object = @builder.object
56
+
57
+ @order || (error_order_method &&
58
+ object.respond_to?(error_order_method) &&
59
+ object.send(error_order_method).present?)
60
+ end
61
+
62
+ def error_order
63
+ @order || @builder.object.send(config.default_error_summary_error_order_method)
64
+ end
65
+
66
+ # this method will be called on the bound object to see if custom error ordering
67
+ # has been enabled
68
+ def error_order_method
69
+ config.default_error_summary_error_order_method
41
70
  end
42
71
 
43
72
  def list_item(attribute, message)
@@ -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
@@ -9,7 +9,7 @@ module GOVUKDesignSystemFormBuilder
9
9
 
10
10
  fail ArgumentError, 'buttons can be warning or secondary' if warning && secondary
11
11
 
12
- @text = text
12
+ @text = build_text(text)
13
13
  @prevent_double_click = prevent_double_click
14
14
  @warning = warning
15
15
  @secondary = secondary
@@ -26,6 +26,17 @@ module GOVUKDesignSystemFormBuilder
26
26
 
27
27
  private
28
28
 
29
+ def build_text(text)
30
+ case text
31
+ when String
32
+ text
33
+ when Proc
34
+ capture { text.call }
35
+ else
36
+ fail(ArgumentError, %(text must be a String or Proc))
37
+ end
38
+ end
39
+
29
40
  def button_group
30
41
  Containers::ButtonGroup.new(@builder, buttons).html
31
42
  end
@@ -35,11 +46,12 @@ module GOVUKDesignSystemFormBuilder
35
46
  end
36
47
 
37
48
  def submit
38
- @builder.submit(@text, **attributes(@html_attributes))
49
+ @builder.tag.button(@text, **attributes(@html_attributes))
39
50
  end
40
51
 
41
52
  def options
42
53
  {
54
+ type: 'submit',
43
55
  formnovalidate: !@validate,
44
56
  disabled: @disabled,
45
57
  class: classes,
@@ -0,0 +1,13 @@
1
+ require_relative 'base'
2
+
3
+ module GOVUKDesignSystemFormBuilder
4
+ class Proxy < GOVUKDesignSystemFormBuilder::Base
5
+ NullBuilder = Struct.new(:object)
6
+
7
+ def initialize(object, object_name, attribute_name, value: nil)
8
+ super(NullBuilder.new(object), object_name, attribute_name)
9
+
10
+ @value = value
11
+ end
12
+ end
13
+ 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? && (capture { 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
+ 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
@@ -6,16 +6,11 @@ module GOVUKDesignSystemFormBuilder
6
6
  # present
7
7
  # * joins the arrays into strings to maintain Rails 6.0.3 compatibility
8
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
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
19
14
 
20
15
  def initialize(defaults, custom)
21
16
  @merged = defaults.deeper_merge(deep_split_values(custom))
@@ -33,19 +28,17 @@ module GOVUKDesignSystemFormBuilder
33
28
  when Hash
34
29
  deep_split_values(value, key)
35
30
  when String
36
- split_list_values(key, value, parent)
31
+ split_mergeable(key, value, parent)
37
32
  else
38
33
  value
39
34
  end
40
35
  end
41
36
  end
42
37
 
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
38
+ def split_mergeable(key, value, parent = nil)
39
+ return value if [parent, key].compact.in?(UNMERGEABLE)
40
+
41
+ value.split
49
42
  end
50
43
 
51
44
  def deep_join_values(hash)
@@ -1,3 +1,3 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
- VERSION = '2.5.1'.freeze
2
+ VERSION = '2.7.0'.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.5.1
4
+ version: 2.7.0
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-05-13 00:00:00.000000000 Z
11
+ date: 2021-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: rubocop-govuk
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '='
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 4.0.0.pre.1
75
+ version: 4.0.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '='
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 4.0.0.pre.1
82
+ version: 4.0.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -274,14 +274,14 @@ dependencies:
274
274
  requirements:
275
275
  - - "~>"
276
276
  - !ruby/object:Gem::Version
277
- version: 0.20.2
277
+ version: 0.21.1
278
278
  type: :development
279
279
  prerelease: false
280
280
  version_requirements: !ruby/object:Gem::Requirement
281
281
  requirements:
282
282
  - - "~>"
283
283
  - !ruby/object:Gem::Version
284
- version: 0.20.2
284
+ version: 0.21.1
285
285
  description: A Rails form builder that generates form inputs adhering to the GOV.UK
286
286
  Design System
287
287
  email:
@@ -295,6 +295,7 @@ files:
295
295
  - lib/govuk_design_system_formbuilder.rb
296
296
  - lib/govuk_design_system_formbuilder/base.rb
297
297
  - lib/govuk_design_system_formbuilder/builder.rb
298
+ - lib/govuk_design_system_formbuilder/builder_helper.rb
298
299
  - lib/govuk_design_system_formbuilder/containers/button_group.rb
299
300
  - lib/govuk_design_system_formbuilder/containers/character_count.rb
300
301
  - lib/govuk_design_system_formbuilder/containers/check_boxes.rb
@@ -330,9 +331,10 @@ files:
330
331
  - lib/govuk_design_system_formbuilder/elements/select.rb
331
332
  - lib/govuk_design_system_formbuilder/elements/submit.rb
332
333
  - lib/govuk_design_system_formbuilder/elements/text_area.rb
334
+ - lib/govuk_design_system_formbuilder/proxy.rb
335
+ - lib/govuk_design_system_formbuilder/refinements/prefixable_array.rb
333
336
  - lib/govuk_design_system_formbuilder/traits/caption.rb
334
337
  - lib/govuk_design_system_formbuilder/traits/collection_item.rb
335
- - lib/govuk_design_system_formbuilder/traits/conditional.rb
336
338
  - lib/govuk_design_system_formbuilder/traits/error.rb
337
339
  - lib/govuk_design_system_formbuilder/traits/fieldset_item.rb
338
340
  - lib/govuk_design_system_formbuilder/traits/hint.rb
@@ -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