govuk_design_system_formbuilder 0.7.9 → 0.7.10

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +52 -18
  3. data/lib/govuk_design_system_formbuilder.rb +19 -4
  4. data/lib/govuk_design_system_formbuilder/base.rb +54 -17
  5. data/lib/govuk_design_system_formbuilder/builder.rb +147 -93
  6. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +28 -0
  7. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +3 -9
  8. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +29 -0
  9. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +62 -0
  10. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +21 -7
  11. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +75 -0
  12. data/lib/govuk_design_system_formbuilder/elements/check_boxes/hint.rb +9 -17
  13. data/lib/govuk_design_system_formbuilder/elements/check_boxes/label.rb +5 -4
  14. data/lib/govuk_design_system_formbuilder/elements/date.rb +18 -14
  15. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +6 -4
  16. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +23 -8
  17. data/lib/govuk_design_system_formbuilder/elements/file.rb +40 -0
  18. data/lib/govuk_design_system_formbuilder/elements/hint.rb +1 -1
  19. data/lib/govuk_design_system_formbuilder/elements/input.rb +4 -12
  20. data/lib/govuk_design_system_formbuilder/elements/label.rb +16 -6
  21. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +55 -0
  22. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +48 -0
  23. data/lib/govuk_design_system_formbuilder/elements/radios/{fieldset_radio.rb → fieldset_radio_button.rb} +17 -8
  24. data/lib/govuk_design_system_formbuilder/elements/select.rb +51 -0
  25. data/lib/govuk_design_system_formbuilder/elements/submit.rb +21 -13
  26. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +4 -8
  27. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  28. metadata +32 -12
  29. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio.rb +0 -33
@@ -0,0 +1,40 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ class File < GOVUKDesignSystemFormBuilder::Base
4
+ def initialize(builder, object_name, attribute_name, hint_text:, label:, **extra_args)
5
+ super(builder, object_name, attribute_name)
6
+
7
+ @label = label
8
+ @hint_text = hint_text
9
+ @extra_args = extra_args
10
+ end
11
+
12
+ def html
13
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
14
+ @builder.safe_join(
15
+ [
16
+ label_element.html,
17
+ hint_element.html,
18
+ error_element.html,
19
+ @builder.file_field(
20
+ @attribute_name,
21
+ id: field_id(link_errors: true),
22
+ class: file_classes,
23
+ aria: { describedby: described_by(hint_element.hint_id, error_element.error_id) },
24
+ **@extra_args
25
+ )
26
+ ]
27
+ )
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def file_classes
34
+ %w(govuk-file-upload).tap do |c|
35
+ c.push('govuk-file-upload--error') if has_errors?
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -11,7 +11,7 @@ module GOVUKDesignSystemFormBuilder
11
11
  end
12
12
 
13
13
  def html
14
- return nil unless @hint_text.present?
14
+ return nil if @hint_text.blank?
15
15
 
16
16
  @builder.tag.span(@hint_text, class: hint_classes, id: hint_id)
17
17
  end
@@ -12,10 +12,6 @@ module GOVUKDesignSystemFormBuilder
12
12
  end
13
13
 
14
14
  def html
15
- hint_element = Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text)
16
- label_element = Elements::Label.new(@builder, @object_name, @attribute_name, @label)
17
- error_element = Elements::ErrorMessage.new(@builder, @object_name, @attribute_name)
18
-
19
15
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
20
16
  @builder.safe_join(
21
17
  [
@@ -25,13 +21,9 @@ module GOVUKDesignSystemFormBuilder
25
21
  @builder.send(
26
22
  @builder_method,
27
23
  @attribute_name,
24
+ id: field_id(link_errors: true),
28
25
  class: input_classes,
29
- aria: {
30
- describedby: [
31
- hint_element.hint_id,
32
- error_element.error_id
33
- ].compact.join(' ').presence
34
- },
26
+ aria: { describedby: described_by(hint_element.hint_id, error_element.error_id) },
35
27
  **@extra_args
36
28
  )
37
29
  ]
@@ -49,7 +41,7 @@ module GOVUKDesignSystemFormBuilder
49
41
  end
50
42
 
51
43
  def width_classes
52
- return unless @width.present?
44
+ return if @width.blank?
53
45
 
54
46
  case @width
55
47
  # fixed (character) widths
@@ -68,7 +60,7 @@ module GOVUKDesignSystemFormBuilder
68
60
  when 'one-third' then 'govuk-!-width-one-third'
69
61
  when 'one-quarter' then 'govuk-!-width-one-quarter'
70
62
 
71
- else fail "invalid width #{@width}"
63
+ else fail(ArgumentError, "invalid width '#{@width}'")
72
64
  end
73
65
  end
74
66
  end
@@ -1,29 +1,39 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class Label < GOVUKDesignSystemFormBuilder::Base
4
- def initialize(builder, object_name, attribute_name, text: nil, value: nil, size: nil, radio: false, checkbox: false)
4
+ def initialize(builder, object_name, attribute_name, text: nil, value: nil, size: nil, radio: false, checkbox: false, tag: nil)
5
5
  super(builder, object_name, attribute_name)
6
6
 
7
7
  @text = label_text(text)
8
- @value = value # used by attribute_descriptor
8
+ @value = value # used by field_id
9
9
  @size_class = label_size_class(size)
10
10
  @radio_class = radio_class(radio)
11
11
  @checkbox_class = checkbox_class(checkbox)
12
+ @tag = tag
12
13
  end
13
14
 
14
15
  def html
15
- return nil unless @text.present?
16
+ return nil if @text.blank?
16
17
 
18
+ if @tag.present?
19
+ @builder.content_tag(@tag, class: 'govuk-label-wrapper') { build_label }
20
+ else
21
+ build_label
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def build_label
17
28
  @builder.label(
18
29
  @attribute_name,
19
30
  @text,
20
31
  value: @value,
32
+ for: field_id,
21
33
  class: %w(govuk-label).push(@size_class, @weight_class, @radio_class, @checkbox_class).compact
22
34
  )
23
35
  end
24
36
 
25
- private
26
-
27
37
  def label_text(option_text)
28
38
  [option_text, @value, @attribute_name.capitalize].compact.first
29
39
  end
@@ -44,7 +54,7 @@ module GOVUKDesignSystemFormBuilder
44
54
  when 's' then "govuk-label--s"
45
55
  when nil then nil
46
56
  else
47
- fail "size must be either 'xl', 'l', 'm', 's' or nil"
57
+ fail "invalid size '#{size}', must be xl, l, m, s or nil"
48
58
  end
49
59
  end
50
60
  end
@@ -0,0 +1,55 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ module Radios
4
+ class Collection < GOVUKDesignSystemFormBuilder::Base
5
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method:, hint_text:, legend:, inline:, small:, &block)
6
+ super(builder, object_name, attribute_name)
7
+
8
+ @collection = collection
9
+ @value_method = value_method
10
+ @text_method = text_method
11
+ @hint_method = hint_method
12
+ @inline = inline
13
+ @small = small
14
+ @legend = legend
15
+ @hint_text = hint_text
16
+ @block_content = @builder.capture { block.call } if block_given?
17
+ end
18
+
19
+ def html
20
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
21
+ Containers::Fieldset.new(@builder, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
22
+ @builder.safe_join(
23
+ [
24
+ hint_element.html,
25
+ error_element.html,
26
+ @block_content,
27
+ Containers::Radios.new(@builder, inline: @inline, small: @small).html do
28
+ @builder.safe_join(build_collection)
29
+ end
30
+ ]
31
+ )
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def build_collection
39
+ @collection.map.with_index do |item, i|
40
+ Elements::Radios::CollectionRadioButton.new(
41
+ @builder,
42
+ @object_name,
43
+ @attribute_name,
44
+ item,
45
+ value_method: @value_method,
46
+ text_method: @text_method,
47
+ hint_method: @hint_method,
48
+ link_errors: has_errors? && i.zero?
49
+ ).html
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,48 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ module Radios
4
+ class CollectionRadioButton < Base
5
+ # @param link_errors [Boolean] used to control the id generated for radio buttons. The
6
+ # error summary requires that the id of the first radio is linked-to from the corresponding
7
+ # error message. As when the summary is built what happens later in the form is unknown, we
8
+ # need to control this to ensure the link is generated correctly
9
+ def initialize(builder, object_name, attribute_name, item, value_method:, text_method:, hint_method:, link_errors: false)
10
+ super(builder, object_name, attribute_name)
11
+ @item = item
12
+ @value = item.send(value_method)
13
+ @text = item.send(text_method)
14
+ @hint_text = item.send(hint_method) if hint_method.present?
15
+ @link_errors = link_errors
16
+ end
17
+
18
+ def html
19
+ @builder.content_tag('div', class: 'govuk-radios__item') do
20
+ @builder.safe_join(
21
+ [
22
+ @builder.radio_button(
23
+ @attribute_name,
24
+ @value,
25
+ id: field_id(link_errors: @link_errors),
26
+ aria: { describedby: hint_id },
27
+ class: %w(govuk-radios__input)
28
+ ),
29
+ label_element.html,
30
+ hint_element.html
31
+ ]
32
+ )
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def hint_element
39
+ @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text, @value, radio: true)
40
+ end
41
+
42
+ def label_element
43
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, text: @text, value: @value, radio: true)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,13 +1,14 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Radios
4
- class FieldsetRadio < Base
5
- def initialize(builder, object_name, attribute_name, value, label:, hint_text:, &block)
4
+ class FieldsetRadioButton < Base
5
+ def initialize(builder, object_name, attribute_name, value, label:, hint_text:, link_errors:, &block)
6
6
  super(builder, object_name, attribute_name)
7
7
 
8
- @value = value
9
- @label = label
10
- @hint_text = hint_text
8
+ @value = value
9
+ @label = label
10
+ @hint_text = hint_text
11
+ @link_errors = has_errors? && link_errors
11
12
 
12
13
  if block_given?
13
14
  @conditional_content = wrap_conditional(block)
@@ -20,8 +21,8 @@ module GOVUKDesignSystemFormBuilder
20
21
  @builder.safe_join(
21
22
  [
22
23
  input,
23
- Elements::Label.new(@builder, @object_name, @attribute_name, radio: true, value: @value, **@label).html,
24
- Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text, radio: true).html,
24
+ label_element.html,
25
+ hint_element.html,
25
26
  @conditional_content
26
27
  ]
27
28
  )
@@ -30,11 +31,19 @@ module GOVUKDesignSystemFormBuilder
30
31
 
31
32
  private
32
33
 
34
+ def label_element
35
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, radio: true, value: @value, **@label)
36
+ end
37
+
38
+ def hint_element
39
+ @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text, radio: true)
40
+ end
41
+
33
42
  def input
34
43
  @builder.radio_button(
35
44
  @attribute_name,
36
45
  @value,
37
- id: attribute_descriptor,
46
+ id: field_id(link_errors: @link_errors),
38
47
  aria: { describedby: hint_id },
39
48
  data: { 'aria-controls' => @conditional_id },
40
49
  class: %w(govuk-radios__input)
@@ -0,0 +1,51 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ class Select < GOVUKDesignSystemFormBuilder::Base
4
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, options: {}, html_options: {}, hint_text:, label:, &block)
5
+ super(builder, object_name, attribute_name)
6
+
7
+ @collection = collection
8
+ @value_method = value_method
9
+ @text_method = text_method
10
+ @options = options
11
+ @html_options = html_options
12
+ @label = label
13
+ @hint_text = hint_text
14
+ @block_content = @builder.capture { block.call } if block_given?
15
+ end
16
+
17
+ def html
18
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
19
+ @builder.safe_join([
20
+ label_element.html,
21
+ hint_element.html,
22
+ error_element.html,
23
+ @block_content,
24
+ @builder.collection_select(
25
+ @attribute_name,
26
+ @collection,
27
+ @value_method,
28
+ @text_method,
29
+ @options,
30
+ build_html_options(hint_element, error_element)
31
+ )
32
+ ])
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def build_html_options(hint_element, error_element)
39
+ @html_options.deep_merge(
40
+ id: field_id(link_errors: true),
41
+ class: select_classes,
42
+ aria: { describedby: described_by(hint_element.hint_id, error_element.error_id) }
43
+ )
44
+ end
45
+
46
+ def select_classes
47
+ %w(govuk-select)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -16,7 +16,12 @@ module GOVUKDesignSystemFormBuilder
16
16
  def html
17
17
  @builder.content_tag('div', class: %w(govuk-form-group)) do
18
18
  @builder.safe_join([
19
- @builder.submit(@text, class: submit_button_classes(@block_content.present?), **extra_args),
19
+ @builder.submit(@text, class: %w(govuk-button).push(
20
+ warning_class,
21
+ secondary_class,
22
+ padding_class(@block_content.present?)
23
+ ),
24
+ **extra_args),
20
25
  @block_content
21
26
  ])
22
27
  end
@@ -24,22 +29,25 @@ module GOVUKDesignSystemFormBuilder
24
29
 
25
30
  private
26
31
 
27
- def submit_button_classes(content_present)
28
- %w(govuk-button).tap do |classes|
29
- classes.push('govuk-button--warning') if @warning
30
- classes.push('govuk-button--secondary') if @secondary
32
+ def warning_class
33
+ 'govuk-button--warning' if @warning
34
+ end
31
35
 
32
- # NOTE only this input will receive a right margin, block
33
- # contents must be addressed individually
34
- classes.push('govuk-!-margin-right-1') if content_present
35
- end
36
+ def secondary_class
37
+ 'govuk-button--secondary' if @secondary
38
+ end
39
+
40
+ def padding_class(content_present)
41
+ 'govuk-!-margin-right-1' if content_present
36
42
  end
37
43
 
38
44
  def extra_args
39
- {}.tap do |ea|
40
- ea[:data] = { 'prevent-double-click' => @prevent_double_click } if @prevent_double_click
41
- ea[:formnovalidate] = !@validate
42
- end
45
+ {
46
+ formnovalidate: !@validate,
47
+ data: {
48
+ 'prevent-double-click' => @prevent_double_click
49
+ }.select { |_k, v| v.present? }
50
+ }
43
51
  end
44
52
  end
45
53
  end
@@ -13,24 +13,20 @@ module GOVUKDesignSystemFormBuilder
13
13
  end
14
14
 
15
15
  def html
16
- hint_element = Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text)
17
- label_element = Elements::Label.new(@builder, @object_name, @attribute_name, @label)
18
- error_element = Elements::ErrorMessage.new(@builder, @object_name, @attribute_name)
19
-
20
16
  Containers::CharacterCount.new(@builder, max_words: @max_words, max_chars: @max_chars, threshold: @threshold).html do
21
17
  Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
22
18
  @builder.safe_join(
23
19
  [
24
- label_element.html,
25
- hint_element.html,
26
- error_element.html,
20
+ [label_element, hint_element, error_element].map(&:html),
27
21
  @builder.text_area(
28
22
  @attribute_name,
23
+ id: field_id(link_errors: true),
29
24
  class: govuk_textarea_classes,
25
+ aria: { describedby: described_by(hint_element.hint_id, error_element.error_id) },
30
26
  **@extra_args.merge(rows: @rows)
31
27
  ),
32
28
  character_count_info
33
- ]
29
+ ].flatten.compact
34
30
  )
35
31
  end
36
32
  end
@@ -1,3 +1,3 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
- VERSION = '0.7.9'.freeze
2
+ VERSION = '0.7.10'.freeze
3
3
  end