govuk_design_system_formbuilder 1.2.1 → 1.2.6

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/govuk_design_system_formbuilder.rb +4 -0
  4. data/lib/govuk_design_system_formbuilder/builder.rb +49 -29
  5. data/lib/govuk_design_system_formbuilder/containers/character_count.rb +8 -7
  6. data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +18 -10
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +18 -9
  8. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +15 -55
  9. data/lib/govuk_design_system_formbuilder/containers/form_group.rb +18 -10
  10. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +19 -10
  11. data/lib/govuk_design_system_formbuilder/containers/radios.rb +22 -11
  12. data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +3 -3
  13. data/lib/govuk_design_system_formbuilder/elements/caption.rb +8 -6
  14. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +21 -12
  15. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +2 -2
  16. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +16 -12
  17. data/lib/govuk_design_system_formbuilder/elements/date.rb +48 -41
  18. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +3 -3
  19. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +15 -15
  20. data/lib/govuk_design_system_formbuilder/elements/file.rb +11 -10
  21. data/lib/govuk_design_system_formbuilder/elements/hint.rb +13 -13
  22. data/lib/govuk_design_system_formbuilder/elements/inputs/email.rb +2 -0
  23. data/lib/govuk_design_system_formbuilder/elements/label.rb +31 -23
  24. data/lib/govuk_design_system_formbuilder/elements/legend.rb +79 -0
  25. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +23 -14
  26. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +13 -3
  27. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +7 -3
  28. data/lib/govuk_design_system_formbuilder/elements/select.rb +24 -19
  29. data/lib/govuk_design_system_formbuilder/elements/submit.rb +14 -6
  30. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +29 -23
  31. data/lib/govuk_design_system_formbuilder/traits/input.rb +9 -8
  32. data/lib/govuk_design_system_formbuilder/traits/label.rb +2 -2
  33. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  34. metadata +9 -8
@@ -1,80 +1,40 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Containers
3
3
  class Fieldset < Base
4
- using PrefixableArray
5
-
6
- include Traits::Caption
7
- include Traits::Localisation
8
-
9
- LEGEND_SIZES = %w(xl l m s).freeze
10
-
11
4
  def initialize(builder, object_name = nil, attribute_name = nil, legend: {}, caption: {}, described_by: nil, &block)
12
5
  super(builder, object_name, attribute_name, &block)
13
6
 
7
+ @legend = legend
8
+ @caption = caption
14
9
  @described_by = described_by(described_by)
15
10
  @attribute_name = attribute_name
16
-
17
- case legend
18
- when Proc
19
- @legend_raw = legend.call
20
- when Hash
21
- @legend_options = legend_defaults.merge(legend)
22
- @caption = caption
23
- else
24
- fail(ArgumentError, %(legend must be a Proc or Hash))
25
- end
26
11
  end
27
12
 
28
13
  def html
29
- content_tag('fieldset', class: fieldset_classes, aria: { describedby: @described_by }) do
30
- safe_join([legend_content, (@block_content || yield)])
14
+ content_tag('fieldset', **options) do
15
+ safe_join([legend_element, (@block_content || yield)])
31
16
  end
32
17
  end
33
18
 
34
19
  private
35
20
 
36
- def legend_content
37
- @legend_raw || legend
38
- end
39
-
40
- def legend
41
- if legend_text.present?
42
- content_tag('legend', class: legend_classes) do
43
- content_tag(@legend_options.dig(:tag), class: legend_heading_classes) do
44
- safe_join([caption_element, legend_text])
45
- end
46
- end
47
- end
48
- end
49
-
50
- def legend_text
51
- [@legend_options.dig(:text), localised_text(:legend)].compact.first
21
+ def options
22
+ {
23
+ class: classes,
24
+ aria: { describedby: @described_by }
25
+ }
52
26
  end
53
27
 
54
- def fieldset_classes
55
- %w(fieldset).prefix(brand)
28
+ def classes
29
+ %(#{brand}-fieldset)
56
30
  end
57
31
 
58
- def legend_classes
59
- size = @legend_options.dig(:size)
60
- fail "invalid size '#{size}', must be #{LEGEND_SIZES.join(', ')}" unless size.in?(LEGEND_SIZES)
61
-
62
- [%(fieldset__legend), %(fieldset__legend--#{size})].prefix(brand).tap do |classes|
63
- classes.push(%(#{brand}-visually-hidden)) if @legend_options.dig(:hidden)
64
- end
32
+ def legend_element
33
+ @legend_element ||= Elements::Legend.new(@builder, @object_name, @attribute_name, **legend_options)
65
34
  end
66
35
 
67
- def legend_heading_classes
68
- %w(fieldset__heading).prefix(brand)
69
- end
70
-
71
- def legend_defaults
72
- {
73
- hidden: false,
74
- text: nil,
75
- tag: config.default_legend_tag,
76
- size: config.default_legend_size
77
- }
36
+ def legend_options
37
+ { legend: @legend, caption: @caption }
78
38
  end
79
39
  end
80
40
  end
@@ -1,24 +1,32 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Containers
3
3
  class FormGroup < Base
4
- using PrefixableArray
5
-
6
- def initialize(builder, object_name, attribute_name)
4
+ def initialize(builder, object_name, attribute_name, classes: nil)
7
5
  super(builder, object_name, attribute_name)
6
+
7
+ @classes = classes
8
8
  end
9
9
 
10
10
  def html
11
- content_tag('div', class: form_group_classes) do
12
- yield
13
- end
11
+ content_tag('div', class: classes) { yield }
14
12
  end
15
13
 
16
14
  private
17
15
 
18
- def form_group_classes
19
- %w(form-group).prefix(brand).tap do |classes|
20
- classes.push(%(#{brand}-form-group--error)) if has_errors?
21
- end
16
+ def classes
17
+ [form_group_class, error_class, custom_classes].flatten.compact
18
+ end
19
+
20
+ def form_group_class
21
+ %(#{brand}-form-group)
22
+ end
23
+
24
+ def error_class
25
+ %(#{brand}-form-group--error) if has_errors?
26
+ end
27
+
28
+ def custom_classes
29
+ Array.wrap(@classes)
22
30
  end
23
31
  end
24
32
  end
@@ -4,21 +4,22 @@ module GOVUKDesignSystemFormBuilder
4
4
  include Traits::Hint
5
5
  include Traits::Error
6
6
 
7
- def initialize(builder, object_name, attribute_name, hint_text:, legend:, caption:, inline:, small:, classes:, &block)
7
+ def initialize(builder, object_name, attribute_name, hint_text:, legend:, caption:, inline:, small:, classes:, form_group_classes:, &block)
8
8
  super(builder, object_name, attribute_name)
9
9
 
10
- @inline = inline
11
- @small = small
12
- @legend = legend
13
- @caption = caption
14
- @hint_text = hint_text
15
- @classes = classes
16
- @block_content = capture { block.call }
10
+ @inline = inline
11
+ @small = small
12
+ @legend = legend
13
+ @caption = caption
14
+ @hint_text = hint_text
15
+ @classes = classes
16
+ @form_group_classes = form_group_classes
17
+ @block_content = capture { block.call }
17
18
  end
18
19
 
19
20
  def html
20
- Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
21
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_element.error_id, hint_element.hint_id]).html do
21
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name, classes: @form_group_classes).html do
22
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
22
23
  safe_join([hint_element, error_element, radios])
23
24
  end
24
25
  end
@@ -26,6 +27,14 @@ module GOVUKDesignSystemFormBuilder
26
27
 
27
28
  private
28
29
 
30
+ def fieldset_options
31
+ {
32
+ legend: @legend,
33
+ caption: @caption,
34
+ described_by: [error_element.error_id, hint_element.hint_id]
35
+ }
36
+ end
37
+
29
38
  def radios
30
39
  Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
31
40
  @block_content
@@ -1,8 +1,6 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Containers
3
3
  class Radios < Base
4
- using PrefixableArray
5
-
6
4
  include Traits::Hint
7
5
 
8
6
  def initialize(builder, inline:, small:, classes:)
@@ -13,19 +11,32 @@ module GOVUKDesignSystemFormBuilder
13
11
  end
14
12
 
15
13
  def html
16
- content_tag('div', class: radios_classes, data: { module: %(#{brand}-radios) }) do
17
- yield
18
- end
14
+ content_tag('div', **options) { yield }
19
15
  end
20
16
 
21
17
  private
22
18
 
23
- def radios_classes
24
- %w(radios).prefix(brand).tap do |c|
25
- c.push(%(#{brand}-radios--inline)) if @inline
26
- c.push(%(#{brand}-radios--small)) if @small
27
- c.push(@classes) if @classes
28
- end
19
+ def options
20
+ {
21
+ class: classes,
22
+ data: { module: %(#{brand}-radios) }
23
+ }
24
+ end
25
+
26
+ def classes
27
+ [%(#{brand}-radios), inline_class, small_class, custom_classes].flatten.compact
28
+ end
29
+
30
+ def inline_class
31
+ %(#{brand}-radios--inline) if @inline
32
+ end
33
+
34
+ def small_class
35
+ %(#{brand}-radios--small) if @small
36
+ end
37
+
38
+ def custom_classes
39
+ Array.wrap(@classes)
29
40
  end
30
41
  end
31
42
  end
@@ -10,11 +10,11 @@ module GOVUKDesignSystemFormBuilder
10
10
  def html
11
11
  return nil if @content.blank?
12
12
 
13
- content_tag('div', id: supplemental_id) do
14
- @content
15
- end
13
+ content_tag('div', id: supplemental_id) { @content }
16
14
  end
17
15
 
16
+ private
17
+
18
18
  def supplemental_id
19
19
  build_id('supplemental')
20
20
  end
@@ -3,11 +3,11 @@ module GOVUKDesignSystemFormBuilder
3
3
  class Caption < Base
4
4
  include Traits::Localisation
5
5
 
6
- def initialize(builder, object_name, attribute_name, text:, size: 'm')
6
+ def initialize(builder, object_name, attribute_name, text:, size: nil)
7
7
  super(builder, object_name, attribute_name)
8
8
 
9
- @text = caption_text(text)
10
- @size_class = caption_size_class(size)
9
+ @text = text(text)
10
+ @size_class = size_class(size)
11
11
  end
12
12
 
13
13
  def html
@@ -16,12 +16,14 @@ module GOVUKDesignSystemFormBuilder
16
16
  tag.span(@text, class: @size_class)
17
17
  end
18
18
 
19
- def caption_text(override)
19
+ private
20
+
21
+ def text(override)
20
22
  override || localised_text(:caption)
21
23
  end
22
24
 
23
- def caption_size_class(size)
24
- case size
25
+ def size_class(size)
26
+ case size || config.default_caption_size
25
27
  when 'xl' then %(#{brand}-caption-xl)
26
28
  when 'l' then %(#{brand}-caption-l)
27
29
  when 'm' then %(#{brand}-caption-m)
@@ -6,23 +6,24 @@ module GOVUKDesignSystemFormBuilder
6
6
  include Traits::Hint
7
7
  include Traits::Supplemental
8
8
 
9
- def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method: nil, hint_text:, legend:, caption:, small:, classes:, &block)
9
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method: nil, hint_text:, legend:, caption:, small:, classes:, form_group_classes:, &block)
10
10
  super(builder, object_name, attribute_name, &block)
11
11
 
12
- @collection = collection
13
- @value_method = value_method
14
- @text_method = text_method
15
- @hint_method = hint_method
16
- @small = small
17
- @legend = legend
18
- @caption = caption
19
- @hint_text = hint_text
20
- @classes = classes
12
+ @collection = collection
13
+ @value_method = value_method
14
+ @text_method = text_method
15
+ @hint_method = hint_method
16
+ @small = small
17
+ @legend = legend
18
+ @caption = caption
19
+ @hint_text = hint_text
20
+ @classes = classes
21
+ @form_group_classes = form_group_classes
21
22
  end
22
23
 
23
24
  def html
24
- Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
25
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id]).html do
25
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name, classes: @form_group_classes).html do
26
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
26
27
  safe_join([supplemental_content, hint_element, error_element, check_boxes])
27
28
  end
28
29
  end
@@ -30,6 +31,14 @@ module GOVUKDesignSystemFormBuilder
30
31
 
31
32
  private
32
33
 
34
+ def fieldset_options
35
+ {
36
+ legend: @legend,
37
+ caption: @caption,
38
+ described_by: [error_id, hint_id, supplemental_id]
39
+ }
40
+ end
41
+
33
42
  def check_boxes
34
43
  Containers::CheckBoxes.new(@builder, small: @small, classes: @classes).html do
35
44
  collection
@@ -26,10 +26,10 @@ module GOVUKDesignSystemFormBuilder
26
26
  private
27
27
 
28
28
  def check_box
29
- @checkbox.check_box(**check_box_options)
29
+ @checkbox.check_box(**options)
30
30
  end
31
31
 
32
- def check_box_options
32
+ def options
33
33
  {
34
34
  id: field_id(link_errors: @link_errors),
35
35
  class: %(#{brand}-checkboxes__input),
@@ -24,33 +24,41 @@ module GOVUKDesignSystemFormBuilder
24
24
  end
25
25
 
26
26
  def html
27
- safe_join([check_box, @conditional_content])
27
+ safe_join([item, @conditional_content])
28
28
  end
29
29
 
30
30
  private
31
31
 
32
- def check_box
32
+ def item
33
33
  content_tag('div', class: %(#{brand}-checkboxes__item)) do
34
- safe_join([input, label_element, hint_element])
34
+ safe_join([check_box, label_element, hint_element])
35
35
  end
36
36
  end
37
37
 
38
- def input
39
- @builder.check_box(@attribute_name, input_options, @value, false)
38
+ def check_box
39
+ @builder.check_box(@attribute_name, options, @value, false)
40
40
  end
41
41
 
42
- def input_options
42
+ def options
43
43
  {
44
44
  id: field_id(link_errors: @link_errors),
45
- class: check_box_classes,
45
+ class: classes,
46
46
  multiple: @multiple,
47
47
  aria: { describedby: hint_id },
48
48
  data: { 'aria-controls' => @conditional_id }
49
49
  }
50
50
  end
51
51
 
52
+ def classes
53
+ %w(checkboxes__input).prefix(brand)
54
+ end
55
+
52
56
  def label_element
53
- @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, checkbox: true, value: @value, link_errors: @link_errors, **label_options)
57
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, **label_content, **label_options)
58
+ end
59
+
60
+ def label_options
61
+ { checkbox: true, value: @value, link_errors: @link_errors }
54
62
  end
55
63
 
56
64
  def hint_element
@@ -60,10 +68,6 @@ module GOVUKDesignSystemFormBuilder
60
68
  def conditional_classes
61
69
  %w(checkboxes__conditional checkboxes__conditional--hidden).prefix(brand)
62
70
  end
63
-
64
- def check_box_classes
65
- %w(checkboxes__input).prefix(brand)
66
- end
67
71
  end
68
72
  end
69
73
  end
@@ -9,19 +9,20 @@ module GOVUKDesignSystemFormBuilder
9
9
 
10
10
  SEGMENTS = { day: '3i', month: '2i', year: '1i' }.freeze
11
11
 
12
- def initialize(builder, object_name, attribute_name, legend:, caption:, hint_text:, date_of_birth: false, omit_day:, &block)
12
+ def initialize(builder, object_name, attribute_name, legend:, caption:, hint_text:, date_of_birth: false, omit_day:, form_group_classes:, &block)
13
13
  super(builder, object_name, attribute_name, &block)
14
14
 
15
- @legend = legend
16
- @caption = caption
17
- @hint_text = hint_text
18
- @date_of_birth = date_of_birth
19
- @omit_day = omit_day
15
+ @legend = legend
16
+ @caption = caption
17
+ @hint_text = hint_text
18
+ @date_of_birth = date_of_birth
19
+ @omit_day = omit_day
20
+ @form_group_classes = form_group_classes
20
21
  end
21
22
 
22
23
  def html
23
- Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
24
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id]).html do
24
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name, classes: @form_group_classes).html do
25
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
25
26
  safe_join([supplemental_content, hint_element, error_element, date])
26
27
  end
27
28
  end
@@ -29,6 +30,10 @@ module GOVUKDesignSystemFormBuilder
29
30
 
30
31
  private
31
32
 
33
+ def fieldset_options
34
+ { legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id] }
35
+ end
36
+
32
37
  def date
33
38
  content_tag('div', class: %(#{brand}-date-input)) do
34
39
  safe_join([day, month, year])
@@ -42,61 +47,59 @@ module GOVUKDesignSystemFormBuilder
42
47
  def day
43
48
  return nil if omit_day?
44
49
 
45
- date_part_input(:day, link_errors: true)
50
+ date_part(:day, width: 2, link_errors: true)
46
51
  end
47
52
 
48
53
  def month
49
- date_part_input(:month, link_errors: omit_day?)
54
+ date_part(:month, width: 2, link_errors: omit_day?)
50
55
  end
51
56
 
52
57
  def year
53
- date_part_input(:year, width: 4)
58
+ date_part(:year, width: 4)
54
59
  end
55
60
 
56
- def date_part_input(segment, width: 2, link_errors: false)
61
+ def date_part(segment, width:, link_errors: false)
57
62
  value = @builder.object.try(@attribute_name).try(segment)
58
63
 
59
64
  content_tag('div', class: %w(date-input__item).prefix(brand)) do
60
65
  content_tag('div', class: %w(form-group).prefix(brand)) do
61
- safe_join(
62
- [
63
- tag.label(
64
- segment.capitalize,
65
- class: date_part_label_classes,
66
- for: date_part_attribute_id(segment, link_errors)
67
- ),
68
-
69
- tag.input(
70
- id: date_part_attribute_id(segment, link_errors),
71
- class: date_part_input_classes(width),
72
- name: date_part_attribute_name(segment),
73
- type: 'text',
74
- pattern: '[0-9]*',
75
- inputmode: 'numeric',
76
- value: value,
77
- autocomplete: date_of_birth_autocomplete_value(segment)
78
- )
79
- ]
80
- )
66
+ safe_join([label(segment, link_errors), input(segment, link_errors, width, value)])
81
67
  end
82
68
  end
83
69
  end
84
70
 
85
- def date_part_input_classes(width)
71
+ def label(segment, link_errors)
72
+ tag.label(
73
+ segment.capitalize,
74
+ class: label_classes,
75
+ for: id(segment, link_errors)
76
+ )
77
+ end
78
+
79
+ def input(segment, link_errors, width, value)
80
+ tag.input(
81
+ id: id(segment, link_errors),
82
+ class: classes(width),
83
+ name: name(segment),
84
+ type: 'text',
85
+ pattern: '[0-9]*',
86
+ inputmode: 'numeric',
87
+ value: value,
88
+ autocomplete: date_of_birth_autocomplete_value(segment)
89
+ )
90
+ end
91
+
92
+ def classes(width)
86
93
  %w(input date-input__input).prefix(brand).tap do |classes|
87
94
  classes.push(%(#{brand}-input--width-#{width}))
88
95
  classes.push(%(#{brand}-input--error)) if has_errors?
89
96
  end
90
97
  end
91
98
 
92
- def date_part_label_classes
93
- %w(label date-input__label).prefix(brand)
94
- end
95
-
96
99
  # if the field has errors we want the govuk_error_summary to
97
100
  # be able to link to the day field. Otherwise, generate IDs
98
101
  # in the normal fashion
99
- def date_part_attribute_id(segment, link_errors)
102
+ def id(segment, link_errors)
100
103
  if has_errors? && link_errors
101
104
  field_id(link_errors: link_errors)
102
105
  else
@@ -104,11 +107,11 @@ module GOVUKDesignSystemFormBuilder
104
107
  end
105
108
  end
106
109
 
107
- def date_part_attribute_name(segment)
110
+ def name(segment)
108
111
  format(
109
- "%<object_name>s[%<attribute_name>s(%<segment>s)]",
112
+ "%<object_name>s[%<input_name>s(%<segment>s)]",
110
113
  object_name: @object_name,
111
- attribute_name: @attribute_name,
114
+ input_name: @attribute_name,
112
115
  segment: SEGMENTS.fetch(segment)
113
116
  )
114
117
  end
@@ -118,6 +121,10 @@ module GOVUKDesignSystemFormBuilder
118
121
 
119
122
  { day: 'bday-day', month: 'bday-month', year: 'bday-year' }.fetch(segment)
120
123
  end
124
+
125
+ def label_classes
126
+ %w(label date-input__label).prefix(brand)
127
+ end
121
128
  end
122
129
  end
123
130
  end