govuk_design_system_formbuilder 1.2.3 → 2.0.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/govuk_design_system_formbuilder.rb +1 -1
  4. data/lib/govuk_design_system_formbuilder/base.rb +1 -1
  5. data/lib/govuk_design_system_formbuilder/builder.rb +155 -60
  6. data/lib/govuk_design_system_formbuilder/containers/character_count.rb +8 -7
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +18 -10
  8. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +13 -4
  9. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +15 -55
  10. data/lib/govuk_design_system_formbuilder/containers/form_group.rb +19 -10
  11. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +13 -4
  12. data/lib/govuk_design_system_formbuilder/containers/radios.rb +22 -11
  13. data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +3 -3
  14. data/lib/govuk_design_system_formbuilder/elements/caption.rb +6 -4
  15. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +21 -12
  16. data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +9 -7
  17. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +24 -16
  18. data/lib/govuk_design_system_formbuilder/elements/date.rb +47 -40
  19. data/lib/govuk_design_system_formbuilder/elements/error_message.rb +4 -4
  20. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +15 -15
  21. data/lib/govuk_design_system_formbuilder/elements/file.rb +8 -7
  22. data/lib/govuk_design_system_formbuilder/elements/hint.rb +43 -16
  23. data/lib/govuk_design_system_formbuilder/elements/inputs/email.rb +2 -2
  24. data/lib/govuk_design_system_formbuilder/elements/inputs/number.rb +0 -2
  25. data/lib/govuk_design_system_formbuilder/elements/inputs/password.rb +0 -2
  26. data/lib/govuk_design_system_formbuilder/elements/inputs/phone.rb +0 -2
  27. data/lib/govuk_design_system_formbuilder/elements/inputs/text.rb +0 -2
  28. data/lib/govuk_design_system_formbuilder/elements/inputs/url.rb +0 -2
  29. data/lib/govuk_design_system_formbuilder/elements/label.rb +35 -27
  30. data/lib/govuk_design_system_formbuilder/elements/legend.rb +79 -0
  31. data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +23 -14
  32. data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +24 -8
  33. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +19 -7
  34. data/lib/govuk_design_system_formbuilder/elements/select.rb +24 -19
  35. data/lib/govuk_design_system_formbuilder/elements/submit.rb +11 -6
  36. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +31 -25
  37. data/lib/govuk_design_system_formbuilder/traits/collection_item.rb +1 -1
  38. data/lib/govuk_design_system_formbuilder/traits/conditional.rb +1 -1
  39. data/lib/govuk_design_system_formbuilder/traits/hint.rb +15 -2
  40. data/lib/govuk_design_system_formbuilder/traits/input.rb +9 -8
  41. data/lib/govuk_design_system_formbuilder/traits/label.rb +2 -2
  42. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  43. metadata +11 -10
@@ -2,14 +2,14 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Email < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Input
8
6
  include Traits::Error
9
7
  include Traits::Hint
10
8
  include Traits::Label
11
9
  include Traits::Supplemental
12
10
 
11
+ private
12
+
13
13
  def builder_method
14
14
  :email_field
15
15
  end
@@ -2,8 +2,6 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Number < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Input
8
6
  include Traits::Error
9
7
  include Traits::Hint
@@ -2,8 +2,6 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Password < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Input
8
6
  include Traits::Error
9
7
  include Traits::Hint
@@ -2,8 +2,6 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Phone < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Input
8
6
  include Traits::Error
9
7
  include Traits::Hint
@@ -2,8 +2,6 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class Text < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Input
8
6
  include Traits::Error
9
7
  include Traits::Hint
@@ -2,8 +2,6 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Inputs
4
4
  class URL < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Input
8
6
  include Traits::Error
9
7
  include Traits::Hint
@@ -12,21 +12,21 @@ module GOVUKDesignSystemFormBuilder
12
12
  # content is passed in directly via a proc and overrides
13
13
  # the other display options
14
14
  if content
15
- @content = content.call
15
+ @content = capture { content.call }
16
16
  else
17
- @value = value # used by field_id
18
- @text = label_text(text, hidden)
19
- @size_class = label_size_class(size)
20
- @radio_class = radio_class(radio)
21
- @checkbox_class = checkbox_class(checkbox)
22
- @tag = tag
23
- @link_errors = link_errors
24
- @caption = caption
17
+ @value = value # used by field_id
18
+ @text = retrieve_text(text, hidden)
19
+ @size_class = size_class(size)
20
+ @radio = radio
21
+ @checkbox = checkbox
22
+ @tag = tag
23
+ @link_errors = link_errors
24
+ @caption = caption
25
25
  end
26
26
  end
27
27
 
28
28
  def html
29
- return nil if [@content, @text].all?(&:blank?)
29
+ return nil unless active?
30
30
 
31
31
  if @tag.present?
32
32
  content_tag(@tag, class: %(#{brand}-label-wrapper)) { label }
@@ -35,51 +35,59 @@ module GOVUKDesignSystemFormBuilder
35
35
  end
36
36
  end
37
37
 
38
+ def active?
39
+ [@content, @text].any?(&:present?)
40
+ end
41
+
38
42
  private
39
43
 
40
44
  def label
41
- @builder.label(@attribute_name, label_options) do
45
+ @builder.label(@attribute_name, **options) do
42
46
  @content || safe_join([caption, @text])
43
47
  end
44
48
  end
45
49
 
46
- def label_text(option_text, hidden)
47
- text = [option_text, localised_text(:label), @attribute_name.capitalize].compact.first.to_s
50
+ def retrieve_text(option_text, hidden)
51
+ text = [option_text, localised_text(:label), @attribute_name.capitalize].compact.first
48
52
 
49
53
  if hidden
50
- tag.span(text, class: %w(visually-hidden).prefix(brand))
54
+ tag.span(text, class: %(#{brand}-visually-hidden))
51
55
  else
52
56
  text
53
57
  end
54
58
  end
55
59
 
56
- def label_options
60
+ def options
57
61
  {
58
62
  value: @value,
59
63
  for: field_id(link_errors: @link_errors),
60
- class: %w(label).prefix(brand).push(@size_class, @weight_class, @radio_class, @checkbox_class).compact
64
+ class: %w(label).prefix(brand).push(@size_class, @weight_class, radio_class, checkbox_class).compact
61
65
  }
62
66
  end
63
67
 
64
68
  def caption
65
- caption_element.html unless [@radio_class, @checkbox_class].any?
69
+ caption_element.html unless [@radio, @checkbox].any?
66
70
  end
67
71
 
68
- def radio_class(radio)
69
- radio ? %(#{brand}-radios__label) : nil
72
+ def radio_class
73
+ return nil unless @radio
74
+
75
+ %(#{brand}-radios__label)
70
76
  end
71
77
 
72
- def checkbox_class(checkbox)
73
- checkbox ? %(#{brand}-checkboxes__label) : nil
78
+ def checkbox_class
79
+ return nil unless @checkbox
80
+
81
+ %(#{brand}-checkboxes__label)
74
82
  end
75
83
 
76
- def label_size_class(size)
84
+ def size_class(size)
77
85
  case size
78
- when 'xl' then %(#{brand}-label--xl)
79
- when 'l' then %(#{brand}-label--l)
80
- when 'm' then %(#{brand}-label--m)
81
- when 's' then %(#{brand}-label--s)
82
- when nil then nil
86
+ when 'xl' then %(#{brand}-label--xl)
87
+ when 'l' then %(#{brand}-label--l)
88
+ when 'm' then %(#{brand}-label--m)
89
+ when 's' then %(#{brand}-label--s)
90
+ when nil then nil
83
91
  else
84
92
  fail "invalid size '#{size}', must be xl, l, m, s or nil"
85
93
  end
@@ -0,0 +1,79 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ module Elements
3
+ class Legend < Base
4
+ include Traits::Caption
5
+ include Traits::Localisation
6
+
7
+ def initialize(builder, object_name, attribute_name, legend:, caption:)
8
+ super(builder, object_name, attribute_name)
9
+
10
+ case legend
11
+ when Proc
12
+ @raw = capture { legend.call }
13
+ when Hash
14
+ defaults.merge(legend).tap do |l|
15
+ @text = text(l.dig(:text))
16
+ @hidden = l.dig(:hidden)
17
+ @tag = l.dig(:tag)
18
+ @size = l.dig(:size)
19
+ @caption = caption
20
+ end
21
+ else
22
+ fail(ArgumentError, %(legend must be a Proc or Hash))
23
+ end
24
+ end
25
+
26
+ def html
27
+ @raw || content
28
+ end
29
+
30
+ private
31
+
32
+ def content
33
+ if @text.present?
34
+ tag.legend(class: classes) do
35
+ content_tag(@tag, class: heading_classes) do
36
+ safe_join([caption_element, @text])
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def text(supplied_text)
43
+ supplied_text || localised_text(:legend)
44
+ end
45
+
46
+ def classes
47
+ [%(#{brand}-fieldset__legend), size_class, visually_hidden_class].compact
48
+ end
49
+
50
+ def size_class
51
+ case @size
52
+ when 'xl' then %(#{brand}-fieldset__legend--xl)
53
+ when 'l' then %(#{brand}-fieldset__legend--l)
54
+ when 'm' then %(#{brand}-fieldset__legend--m)
55
+ when 's' then %(#{brand}-fieldset__legend--s)
56
+ else
57
+ fail "invalid size '#{@size}', must be xl, l, m or s"
58
+ end
59
+ end
60
+
61
+ def visually_hidden_class
62
+ %(#{brand}-visually-hidden) if @hidden
63
+ end
64
+
65
+ def heading_classes
66
+ %(#{brand}-fieldset__heading)
67
+ end
68
+
69
+ def defaults
70
+ {
71
+ hidden: false,
72
+ text: nil,
73
+ tag: config.default_legend_tag,
74
+ size: config.default_legend_size
75
+ }
76
+ end
77
+ end
78
+ end
79
+ end
@@ -6,25 +6,26 @@ 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:, hint_text:, legend:, caption:, inline:, small:, bold_labels:, classes:, &block)
9
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method:, hint:, legend:, caption:, inline:, small:, bold_labels:, classes:, form_group:, &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
- @inline = inline
17
- @small = small
18
- @legend = legend
19
- @caption = caption
20
- @hint_text = hint_text
21
- @classes = classes
22
- @bold_labels = hint_method.present? || bold_labels
12
+ @collection = collection
13
+ @value_method = value_method
14
+ @text_method = text_method
15
+ @hint_method = hint_method
16
+ @inline = inline
17
+ @small = small
18
+ @legend = legend
19
+ @caption = caption
20
+ @hint = hint
21
+ @classes = classes
22
+ @form_group = form_group
23
+ @bold_labels = hint_method.present? || bold_labels
23
24
  end
24
25
 
25
26
  def html
26
- Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
27
- Containers::Fieldset.new(@builder, @object_name, @attribute_name, legend: @legend, caption: @caption, described_by: [error_id, hint_id, supplemental_id]).html do
27
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
28
+ Containers::Fieldset.new(@builder, @object_name, @attribute_name, **fieldset_options).html do
28
29
  safe_join([supplemental_content, hint_element, error_element, radios])
29
30
  end
30
31
  end
@@ -32,6 +33,14 @@ module GOVUKDesignSystemFormBuilder
32
33
 
33
34
  private
34
35
 
36
+ def fieldset_options
37
+ {
38
+ legend: @legend,
39
+ caption: @caption,
40
+ described_by: [error_id, hint_id, supplemental_id]
41
+ }
42
+ end
43
+
35
44
  def radios
36
45
  Containers::Radios.new(@builder, inline: @inline, small: @small, classes: @classes).html do
37
46
  safe_join(collection)
@@ -2,8 +2,6 @@ module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  module Radios
4
4
  class CollectionRadioButton < Base
5
- using PrefixableArray
6
-
7
5
  include Traits::Hint
8
6
  include Traits::CollectionItem
9
7
 
@@ -23,7 +21,7 @@ module GOVUKDesignSystemFormBuilder
23
21
  end
24
22
 
25
23
  def html
26
- content_tag('div', class: %(#{brand}-radios__item)) do
24
+ tag.div(class: %(#{brand}-radios__item)) do
27
25
  safe_join([radio, label_element, hint_element])
28
26
  end
29
27
  end
@@ -31,23 +29,41 @@ module GOVUKDesignSystemFormBuilder
31
29
  private
32
30
 
33
31
  def radio
34
- @builder.radio_button(@attribute_name, @value, **radio_options)
32
+ @builder.radio_button(@attribute_name, @value, **options)
35
33
  end
36
34
 
37
- def radio_options
35
+ def options
38
36
  {
39
37
  id: field_id(link_errors: @link_errors),
40
38
  aria: { describedby: hint_id },
41
- class: %w(radios__input).prefix(brand)
39
+ class: %(#{brand}-radios__input)
42
40
  }
43
41
  end
44
42
 
45
43
  def hint_element
46
- @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text, @value, radio: true)
44
+ @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_options, **hint_content)
45
+ end
46
+
47
+ def hint_content
48
+ { text: @hint_text }
49
+ end
50
+
51
+ def hint_options
52
+ { value: @value, radio: true }
47
53
  end
48
54
 
49
55
  def label_element
50
- @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, text: @label_text, value: @value, radio: true, size: label_size, link_errors: @link_errors)
56
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, **label_options)
57
+ end
58
+
59
+ def label_options
60
+ {
61
+ text: @label_text,
62
+ value: @value,
63
+ radio: true,
64
+ size: label_size,
65
+ link_errors: @link_errors
66
+ }
51
67
  end
52
68
 
53
69
  def label_size
@@ -8,12 +8,12 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::Hint
9
9
  include Traits::Conditional
10
10
 
11
- def initialize(builder, object_name, attribute_name, value, label:, hint_text:, link_errors:, &block)
11
+ def initialize(builder, object_name, attribute_name, value, label:, hint:, link_errors:, &block)
12
12
  super(builder, object_name, attribute_name)
13
13
 
14
14
  @value = value
15
15
  @label = label
16
- @hint_text = hint_text
16
+ @hint = hint
17
17
  @link_errors = has_errors? && link_errors
18
18
 
19
19
  if block_given?
@@ -29,24 +29,36 @@ module GOVUKDesignSystemFormBuilder
29
29
  private
30
30
 
31
31
  def radio
32
- content_tag('div', class: %(#{brand}-radios__item)) do
32
+ tag.div(class: %(#{brand}-radios__item)) do
33
33
  safe_join([input, label_element, hint_element])
34
34
  end
35
35
  end
36
36
 
37
+ def radio_options
38
+ { radio: true }
39
+ end
40
+
37
41
  def label_element
38
- @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, radio: true, value: @value, link_errors: @link_errors, **label_options)
42
+ @label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, **label_content, **label_options, **@label)
43
+ end
44
+
45
+ def label_options
46
+ { value: @value, link_errors: @link_errors }.merge(radio_options)
39
47
  end
40
48
 
41
49
  def hint_element
42
- @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text, @value, radio: true)
50
+ @hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_options, **hint_content)
51
+ end
52
+
53
+ def hint_options
54
+ { value: @value }.merge(radio_options)
43
55
  end
44
56
 
45
57
  def input
46
- @builder.radio_button(@attribute_name, @value, input_options)
58
+ @builder.radio_button(@attribute_name, @value, **options)
47
59
  end
48
60
 
49
- def input_options
61
+ def options
50
62
  {
51
63
  id: field_id(link_errors: @link_errors),
52
64
  aria: { describedby: hint_id },
@@ -1,28 +1,27 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
2
  module Elements
3
3
  class Select < Base
4
- using PrefixableArray
5
-
6
4
  include Traits::Error
7
5
  include Traits::Label
8
6
  include Traits::Hint
9
7
  include Traits::Supplemental
10
8
 
11
- def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, options: {}, html_options: {}, hint_text:, label:, caption:, &block)
9
+ def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, options: {}, html_options: {}, hint:, label:, caption:, form_group:, &block)
12
10
  super(builder, object_name, attribute_name, &block)
13
11
 
14
- @collection = collection
15
- @value_method = value_method
16
- @text_method = text_method
17
- @options = options
18
- @html_options = html_options
19
- @label = label
20
- @caption = caption
21
- @hint_text = hint_text
12
+ @collection = collection
13
+ @value_method = value_method
14
+ @text_method = text_method
15
+ @options = options
16
+ @html_options = html_options
17
+ @label = label
18
+ @caption = caption
19
+ @hint = hint
20
+ @form_group = form_group
22
21
  end
23
22
 
24
23
  def html
25
- Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
24
+ Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
26
25
  safe_join([label_element, supplemental_content, hint_element, error_element, select])
27
26
  end
28
27
  end
@@ -30,21 +29,27 @@ module GOVUKDesignSystemFormBuilder
30
29
  private
31
30
 
32
31
  def select
33
- @builder.collection_select(@attribute_name, @collection, @value_method, @text_method, @options, select_options)
32
+ @builder.collection_select(@attribute_name, @collection, @value_method, @text_method, @options, **options)
34
33
  end
35
34
 
36
- def select_options
35
+ def options
37
36
  @html_options.deep_merge(
38
37
  id: field_id(link_errors: true),
39
- class: select_classes,
38
+ class: classes,
40
39
  aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
41
40
  )
42
41
  end
43
42
 
44
- def select_classes
45
- %w(select).prefix(brand).tap do |classes|
46
- classes.push(%(#{brand}-select--error)) if has_errors?
47
- end
43
+ def classes
44
+ [%(#{brand}-select), error_class, custom_classes].flatten.compact
45
+ end
46
+
47
+ def error_class
48
+ %(#{brand}-select--error) if has_errors?
49
+ end
50
+
51
+ def custom_classes
52
+ @html_options.dig(:class)
48
53
  end
49
54
  end
50
55
  end