govuk_design_system_formbuilder 0.9.8 → 2.0.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 +4 -4
- data/README.md +40 -35
- data/lib/govuk_design_system_formbuilder/base.rb +21 -46
- data/lib/govuk_design_system_formbuilder/builder.rb +528 -111
- data/lib/govuk_design_system_formbuilder/containers/character_count.rb +8 -7
- data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +20 -8
- data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +39 -14
- data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +21 -25
- data/lib/govuk_design_system_formbuilder/containers/form_group.rb +20 -9
- data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +28 -14
- data/lib/govuk_design_system_formbuilder/containers/radios.rb +27 -10
- data/lib/govuk_design_system_formbuilder/containers/supplemental.rb +8 -9
- data/lib/govuk_design_system_formbuilder/elements/caption.rb +41 -0
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +34 -22
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +28 -18
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +47 -40
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/label.rb +9 -3
- data/lib/govuk_design_system_formbuilder/elements/date.rb +65 -53
- data/lib/govuk_design_system_formbuilder/elements/error_message.rb +13 -8
- data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +30 -31
- data/lib/govuk_design_system_formbuilder/elements/file.rb +31 -24
- data/lib/govuk_design_system_formbuilder/elements/hint.rb +50 -14
- data/lib/govuk_design_system_formbuilder/elements/inputs/email.rb +8 -0
- data/lib/govuk_design_system_formbuilder/elements/inputs/number.rb +6 -0
- data/lib/govuk_design_system_formbuilder/elements/inputs/password.rb +17 -0
- data/lib/govuk_design_system_formbuilder/elements/inputs/phone.rb +6 -0
- data/lib/govuk_design_system_formbuilder/elements/inputs/text.rb +6 -0
- data/lib/govuk_design_system_formbuilder/elements/inputs/url.rb +6 -0
- data/lib/govuk_design_system_formbuilder/elements/label.rb +63 -34
- data/lib/govuk_design_system_formbuilder/elements/legend.rb +87 -0
- data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +51 -35
- data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +41 -19
- data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +37 -24
- data/lib/govuk_design_system_formbuilder/elements/select.rb +34 -32
- data/lib/govuk_design_system_formbuilder/elements/submit.rb +39 -29
- data/lib/govuk_design_system_formbuilder/elements/text_area.rb +76 -32
- data/lib/govuk_design_system_formbuilder/traits/caption.rb +15 -0
- data/lib/govuk_design_system_formbuilder/traits/collection_item.rb +16 -0
- data/lib/govuk_design_system_formbuilder/traits/conditional.rb +17 -0
- data/lib/govuk_design_system_formbuilder/traits/error.rb +17 -0
- data/lib/govuk_design_system_formbuilder/traits/hint.rb +30 -0
- data/lib/govuk_design_system_formbuilder/traits/input.rb +105 -0
- data/lib/govuk_design_system_formbuilder/traits/label.rb +22 -0
- data/lib/govuk_design_system_formbuilder/traits/localisation.rb +51 -0
- data/lib/govuk_design_system_formbuilder/traits/supplemental.rb +17 -0
- data/lib/govuk_design_system_formbuilder/version.rb +1 -1
- data/lib/govuk_design_system_formbuilder.rb +89 -44
- metadata +62 -52
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/hint.rb +0 -30
- data/lib/govuk_design_system_formbuilder/elements/inputs/base.rb +0 -79
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
module GOVUKDesignSystemFormBuilder
|
|
2
2
|
module Elements
|
|
3
|
-
class Submit <
|
|
4
|
-
|
|
3
|
+
class Submit < Base
|
|
4
|
+
using PrefixableArray
|
|
5
|
+
|
|
6
|
+
def initialize(builder, text, warning:, secondary:, classes:, prevent_double_click:, validate:, disabled:, &block)
|
|
5
7
|
fail ArgumentError, 'buttons can be warning or secondary' if warning && secondary
|
|
6
8
|
|
|
7
9
|
@builder = builder
|
|
@@ -9,52 +11,60 @@ module GOVUKDesignSystemFormBuilder
|
|
|
9
11
|
@prevent_double_click = prevent_double_click
|
|
10
12
|
@warning = warning
|
|
11
13
|
@secondary = secondary
|
|
14
|
+
@classes = classes
|
|
12
15
|
@validate = validate
|
|
16
|
+
@disabled = disabled
|
|
13
17
|
@block_content = capture { block.call } if block_given?
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
def html
|
|
17
|
-
|
|
18
|
-
safe_join(
|
|
19
|
-
[
|
|
20
|
-
@builder.submit(
|
|
21
|
-
@text,
|
|
22
|
-
class: %w(govuk-button).push(
|
|
23
|
-
warning_class,
|
|
24
|
-
secondary_class,
|
|
25
|
-
padding_class(@block_content.present?)
|
|
26
|
-
).compact,
|
|
27
|
-
**extra_args
|
|
28
|
-
),
|
|
29
|
-
@block_content
|
|
30
|
-
]
|
|
31
|
-
)
|
|
32
|
-
end
|
|
21
|
+
safe_join([submit, @block_content])
|
|
33
22
|
end
|
|
34
23
|
|
|
35
24
|
private
|
|
36
25
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def secondary_class
|
|
42
|
-
'govuk-button--secondary' if @secondary
|
|
26
|
+
def submit
|
|
27
|
+
@builder.submit(@text, class: classes, **options)
|
|
43
28
|
end
|
|
44
29
|
|
|
45
|
-
def
|
|
46
|
-
|
|
30
|
+
def classes
|
|
31
|
+
%w(button)
|
|
32
|
+
.prefix(brand)
|
|
33
|
+
.push(warning_class, secondary_class, disabled_class, padding_class, custom_classes)
|
|
34
|
+
.flatten
|
|
35
|
+
.compact
|
|
47
36
|
end
|
|
48
37
|
|
|
49
|
-
def
|
|
38
|
+
def options
|
|
50
39
|
{
|
|
51
40
|
formnovalidate: !@validate,
|
|
41
|
+
disabled: @disabled,
|
|
52
42
|
data: {
|
|
53
|
-
module:
|
|
54
|
-
'prevent-double-click'
|
|
43
|
+
module: %(#{brand}-button),
|
|
44
|
+
'prevent-double-click': @prevent_double_click
|
|
55
45
|
}.select { |_k, v| v.present? }
|
|
56
46
|
}
|
|
57
47
|
end
|
|
48
|
+
|
|
49
|
+
def warning_class
|
|
50
|
+
%(#{brand}-button--warning) if @warning
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def secondary_class
|
|
54
|
+
%(#{brand}-button--secondary) if @secondary
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def padding_class
|
|
58
|
+
%(#{brand}-!-margin-right-1) if @block_content
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def disabled_class
|
|
62
|
+
%(#{brand}-button--disabled) if @disabled
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def custom_classes
|
|
66
|
+
Array.wrap(@classes)
|
|
67
|
+
end
|
|
58
68
|
end
|
|
59
69
|
end
|
|
60
70
|
end
|
|
@@ -1,54 +1,98 @@
|
|
|
1
1
|
module GOVUKDesignSystemFormBuilder
|
|
2
2
|
module Elements
|
|
3
3
|
class TextArea < Base
|
|
4
|
-
|
|
4
|
+
using PrefixableArray
|
|
5
|
+
|
|
6
|
+
include Traits::Error
|
|
7
|
+
include Traits::Hint
|
|
8
|
+
include Traits::Label
|
|
9
|
+
include Traits::Supplemental
|
|
10
|
+
|
|
11
|
+
def initialize(builder, object_name, attribute_name, hint:, label:, caption:, rows:, max_words:, max_chars:, threshold:, form_group:, **kwargs, &block)
|
|
5
12
|
super(builder, object_name, attribute_name, &block)
|
|
6
|
-
|
|
7
|
-
@
|
|
8
|
-
@
|
|
9
|
-
@
|
|
10
|
-
@
|
|
11
|
-
@
|
|
12
|
-
@
|
|
13
|
+
|
|
14
|
+
@label = label
|
|
15
|
+
@caption = caption
|
|
16
|
+
@hint = hint
|
|
17
|
+
@max_words = max_words
|
|
18
|
+
@max_chars = max_chars
|
|
19
|
+
@threshold = threshold
|
|
20
|
+
@rows = rows
|
|
21
|
+
@form_group = form_group
|
|
22
|
+
@html_attributes = kwargs
|
|
13
23
|
end
|
|
14
24
|
|
|
15
25
|
def html
|
|
16
|
-
Containers::CharacterCount.new(@builder,
|
|
17
|
-
Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
|
|
18
|
-
safe_join(
|
|
19
|
-
[
|
|
20
|
-
[label_element, hint_element, error_element, supplemental_content].map(&:html),
|
|
21
|
-
@builder.text_area(
|
|
22
|
-
@attribute_name,
|
|
23
|
-
id: field_id(link_errors: true),
|
|
24
|
-
class: govuk_textarea_classes,
|
|
25
|
-
aria: {
|
|
26
|
-
describedby: described_by(
|
|
27
|
-
hint_id,
|
|
28
|
-
error_id,
|
|
29
|
-
supplemental_id
|
|
30
|
-
)
|
|
31
|
-
},
|
|
32
|
-
**@extra_args.merge(rows: @rows)
|
|
33
|
-
)
|
|
34
|
-
].flatten.compact
|
|
35
|
-
)
|
|
26
|
+
Containers::CharacterCount.new(@builder, **character_count_options).html do
|
|
27
|
+
Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
|
|
28
|
+
safe_join([label_element, supplemental_content, hint_element, error_element, text_area, limit_description])
|
|
36
29
|
end
|
|
37
30
|
end
|
|
38
31
|
end
|
|
39
32
|
|
|
40
33
|
private
|
|
41
34
|
|
|
42
|
-
def
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
def character_count_options
|
|
36
|
+
{ max_words: @max_words, max_chars: @max_chars, threshold: @threshold }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def text_area
|
|
40
|
+
@builder.text_area(@attribute_name, **options, **@html_attributes)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def classes
|
|
44
|
+
%w(textarea).prefix(brand).tap do |classes|
|
|
45
|
+
classes.push(%(#{brand}-textarea--error)) if has_errors?
|
|
46
|
+
classes.push(%(#{brand}-js-character-count)) if limit?
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
|
|
50
|
+
def options
|
|
51
|
+
{
|
|
52
|
+
id: field_id(link_errors: true),
|
|
53
|
+
class: classes,
|
|
54
|
+
rows: @rows,
|
|
55
|
+
aria: { describedby: described_by(hint_id, error_id, supplemental_id, limit_description_id) },
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Provides an id for use by the textual description of character and word limits.
|
|
60
|
+
#
|
|
61
|
+
# @note In order for the GOV.UK Frontend JavaScript to pick up this associated field
|
|
62
|
+
# it has to have the same id as the text area with the additional suffix of '-info'
|
|
63
|
+
def limit_id
|
|
64
|
+
[field_id(link_errors: true), 'info'].join('-')
|
|
65
|
+
end
|
|
66
|
+
|
|
49
67
|
def limit?
|
|
68
|
+
limit_quantity.present?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def limit_quantity
|
|
50
72
|
@max_words || @max_chars
|
|
51
73
|
end
|
|
74
|
+
|
|
75
|
+
def limit_type
|
|
76
|
+
@max_words.present? ? 'words' : 'characters'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def limit_description
|
|
80
|
+
return nil unless limit?
|
|
81
|
+
|
|
82
|
+
tag.span(id: limit_id, class: limit_description_classes, aria: { live: 'polite' }) do
|
|
83
|
+
"You can enter up to #{limit_quantity} #{limit_type}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def limit_description_classes
|
|
88
|
+
%w(hint character-count__message).prefix(brand)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def limit_description_id
|
|
92
|
+
return nil unless limit?
|
|
93
|
+
|
|
94
|
+
limit_id
|
|
95
|
+
end
|
|
52
96
|
end
|
|
53
97
|
end
|
|
54
98
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Caption
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def caption_element
|
|
7
|
+
@caption_element ||= Elements::Caption.new(@builder, @object_name, @attribute_name, **caption_options)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def caption_options
|
|
11
|
+
@caption
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module CollectionItem
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def retrieve(item, method)
|
|
7
|
+
case method
|
|
8
|
+
when Symbol, String
|
|
9
|
+
item.send(method)
|
|
10
|
+
when Proc
|
|
11
|
+
capture { method.call(item) }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Error
|
|
4
|
+
def error_id
|
|
5
|
+
return nil unless has_errors?
|
|
6
|
+
|
|
7
|
+
build_id('error')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def error_element
|
|
13
|
+
@error_element ||= Elements::ErrorMessage.new(@builder, @object_name, @attribute_name)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Hint
|
|
4
|
+
def hint_id
|
|
5
|
+
return nil unless hint_element.active?
|
|
6
|
+
|
|
7
|
+
build_id('hint')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def hint_element
|
|
13
|
+
@hint_element ||= Elements::Hint.new(@builder, @object_name, @attribute_name, **hint_content)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def hint_content
|
|
17
|
+
case @hint
|
|
18
|
+
when NilClass
|
|
19
|
+
{}
|
|
20
|
+
when Hash
|
|
21
|
+
@hint
|
|
22
|
+
when Proc
|
|
23
|
+
{ content: @hint }
|
|
24
|
+
else
|
|
25
|
+
fail(ArgumentError, %(hint must be a Proc or Hash))
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Input
|
|
4
|
+
def initialize(builder, object_name, attribute_name, hint:, label:, caption:, prefix_text:, suffix_text:, width:, form_group:, **kwargs, &block)
|
|
5
|
+
super(builder, object_name, attribute_name, &block)
|
|
6
|
+
|
|
7
|
+
@width = width
|
|
8
|
+
@label = label
|
|
9
|
+
@caption = caption
|
|
10
|
+
@hint = hint
|
|
11
|
+
@prefix_text = prefix_text
|
|
12
|
+
@suffix_text = suffix_text
|
|
13
|
+
@html_attributes = kwargs
|
|
14
|
+
@form_group = form_group
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def html
|
|
18
|
+
Containers::FormGroup.new(@builder, @object_name, @attribute_name, **@form_group).html do
|
|
19
|
+
safe_join([label_element, supplemental_content, hint_element, error_element, content])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def content
|
|
26
|
+
if affixed?
|
|
27
|
+
affixed_input
|
|
28
|
+
else
|
|
29
|
+
input
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def affixed_input
|
|
34
|
+
content_tag('div', class: %(#{brand}-input__wrapper)) do
|
|
35
|
+
safe_join([prefix, input, suffix])
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def input
|
|
40
|
+
@builder.send(builder_method, @attribute_name, **options, **@html_attributes)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def affixed?
|
|
44
|
+
[@prefix_text, @suffix_text].any?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def options
|
|
48
|
+
{
|
|
49
|
+
id: field_id(link_errors: true),
|
|
50
|
+
class: classes,
|
|
51
|
+
aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def classes
|
|
56
|
+
[%(#{brand}-input)].push(width_classes, error_classes).compact
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def error_classes
|
|
60
|
+
%(#{brand}-input--error) if has_errors?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def width_classes
|
|
64
|
+
return if @width.blank?
|
|
65
|
+
|
|
66
|
+
case @width
|
|
67
|
+
|
|
68
|
+
# fixed (character) widths
|
|
69
|
+
when 20 then %(#{brand}-input--width-20)
|
|
70
|
+
when 10 then %(#{brand}-input--width-10)
|
|
71
|
+
when 5 then %(#{brand}-input--width-5)
|
|
72
|
+
when 4 then %(#{brand}-input--width-4)
|
|
73
|
+
when 3 then %(#{brand}-input--width-3)
|
|
74
|
+
when 2 then %(#{brand}-input--width-2)
|
|
75
|
+
|
|
76
|
+
# fluid widths
|
|
77
|
+
when 'full' then %(#{brand}-!-width-full)
|
|
78
|
+
when 'three-quarters' then %(#{brand}-!-width-three-quarters)
|
|
79
|
+
when 'two-thirds' then %(#{brand}-!-width-two-thirds)
|
|
80
|
+
when 'one-half' then %(#{brand}-!-width-one-half)
|
|
81
|
+
when 'one-third' then %(#{brand}-!-width-one-third)
|
|
82
|
+
when 'one-quarter' then %(#{brand}-!-width-one-quarter)
|
|
83
|
+
|
|
84
|
+
else fail(ArgumentError, "invalid width '#{@width}'")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def prefix
|
|
89
|
+
return nil if @prefix_text.blank?
|
|
90
|
+
|
|
91
|
+
tag.span(@prefix_text, class: %(#{brand}-input__prefix), **affix_options)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def suffix
|
|
95
|
+
return nil if @suffix_text.blank?
|
|
96
|
+
|
|
97
|
+
tag.span(@suffix_text, class: %(#{brand}-input__suffix), **affix_options)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def affix_options
|
|
101
|
+
{ aria: { hidden: true } }
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Label
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def label_element
|
|
7
|
+
@label_element ||= Elements::Label.new(@builder, @object_name, @attribute_name, caption: @caption, **label_content)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def label_content
|
|
11
|
+
case @label
|
|
12
|
+
when Hash
|
|
13
|
+
@label
|
|
14
|
+
when Proc
|
|
15
|
+
{ content: @label }
|
|
16
|
+
else
|
|
17
|
+
fail(ArgumentError, %(label must be a Proc or Hash))
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Localisation
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def localised_text(context)
|
|
7
|
+
return unless @object_name.present? && @attribute_name.present?
|
|
8
|
+
|
|
9
|
+
localise(context) || localise_html(context)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def localise(context)
|
|
13
|
+
I18n.translate(schema(context), default: nil)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def localise_html(context)
|
|
17
|
+
I18n.translate("#{schema(context)}_html", default: nil).try(:html_safe)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def schema(context)
|
|
21
|
+
schema_root(context)
|
|
22
|
+
.push(*schema_path)
|
|
23
|
+
.map { |e| e == :__context__ ? context : e }
|
|
24
|
+
.join('.')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def schema_path
|
|
28
|
+
if @value.present?
|
|
29
|
+
[@object_name, "#{@attribute_name}_options", @value]
|
|
30
|
+
else
|
|
31
|
+
[@object_name, @attribute_name]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def schema_root(context)
|
|
36
|
+
contextual_schema = case context
|
|
37
|
+
when :legend
|
|
38
|
+
config.localisation_schema_legend
|
|
39
|
+
when :hint
|
|
40
|
+
config.localisation_schema_hint
|
|
41
|
+
when :label
|
|
42
|
+
config.localisation_schema_label
|
|
43
|
+
when :caption
|
|
44
|
+
config.localisation_schema_caption
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
(contextual_schema || config.localisation_schema_fallback).dup
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
|
2
|
+
module Traits
|
|
3
|
+
module Supplemental
|
|
4
|
+
def supplemental_id
|
|
5
|
+
return nil if @block_content.blank?
|
|
6
|
+
|
|
7
|
+
build_id('supplemental')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def supplemental_content
|
|
13
|
+
@supplemental_content ||= Containers::Supplemental.new(@builder, @object_name, @attribute_name, @block_content)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,53 +1,98 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
require
|
|
6
|
-
require 'govuk_design_system_formbuilder/elements/label'
|
|
7
|
-
require 'govuk_design_system_formbuilder/elements/date'
|
|
8
|
-
require 'govuk_design_system_formbuilder/elements/select'
|
|
9
|
-
require 'govuk_design_system_formbuilder/elements/submit'
|
|
10
|
-
require 'govuk_design_system_formbuilder/elements/text_area'
|
|
11
|
-
require 'govuk_design_system_formbuilder/elements/file'
|
|
12
|
-
|
|
13
|
-
require 'govuk_design_system_formbuilder/elements/inputs/base'
|
|
14
|
-
require 'govuk_design_system_formbuilder/elements/inputs/email'
|
|
15
|
-
require 'govuk_design_system_formbuilder/elements/inputs/number'
|
|
16
|
-
require 'govuk_design_system_formbuilder/elements/inputs/phone'
|
|
17
|
-
require 'govuk_design_system_formbuilder/elements/inputs/text'
|
|
18
|
-
require 'govuk_design_system_formbuilder/elements/inputs/url'
|
|
19
|
-
|
|
20
|
-
require 'govuk_design_system_formbuilder/elements/radios/collection'
|
|
21
|
-
require 'govuk_design_system_formbuilder/elements/radios/collection_radio_button'
|
|
22
|
-
require 'govuk_design_system_formbuilder/elements/radios/fieldset_radio_button'
|
|
23
|
-
|
|
24
|
-
require 'govuk_design_system_formbuilder/elements/check_boxes/collection'
|
|
25
|
-
require 'govuk_design_system_formbuilder/elements/check_boxes/collection_check_box'
|
|
26
|
-
require 'govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box'
|
|
27
|
-
require 'govuk_design_system_formbuilder/elements/check_boxes/label'
|
|
28
|
-
require 'govuk_design_system_formbuilder/elements/check_boxes/hint'
|
|
29
|
-
|
|
30
|
-
require 'govuk_design_system_formbuilder/elements/error_message'
|
|
31
|
-
require 'govuk_design_system_formbuilder/elements/error_summary'
|
|
32
|
-
|
|
33
|
-
require 'govuk_design_system_formbuilder/containers/check_boxes_fieldset'
|
|
34
|
-
require 'govuk_design_system_formbuilder/containers/form_group'
|
|
35
|
-
require 'govuk_design_system_formbuilder/containers/fieldset'
|
|
36
|
-
require 'govuk_design_system_formbuilder/containers/radios'
|
|
37
|
-
require 'govuk_design_system_formbuilder/containers/radio_buttons_fieldset'
|
|
38
|
-
require 'govuk_design_system_formbuilder/containers/check_boxes'
|
|
39
|
-
require 'govuk_design_system_formbuilder/containers/character_count'
|
|
40
|
-
require 'govuk_design_system_formbuilder/containers/supplemental'
|
|
1
|
+
require 'active_support/configurable'
|
|
2
|
+
|
|
3
|
+
[%w(traits *.rb), %w(*.rb), %w(elements ** *.rb), %w(containers ** *.rb)]
|
|
4
|
+
.flat_map { |matcher| Dir.glob(File.join(__dir__, 'govuk_design_system_formbuilder', *matcher)) }
|
|
5
|
+
.each { |file| require file }
|
|
41
6
|
|
|
42
7
|
module GOVUKDesignSystemFormBuilder
|
|
8
|
+
include ActiveSupport::Configurable
|
|
9
|
+
|
|
10
|
+
# @!group Defaults
|
|
11
|
+
|
|
12
|
+
# Default form builder configuration
|
|
13
|
+
#
|
|
14
|
+
# * +:brand+ sets the value used to prefix all classes, used to allow the
|
|
15
|
+
# builder to be branded for alternative (similar) design systems.
|
|
16
|
+
#
|
|
17
|
+
# * +:default_caption_size+ controls the default size of caption text.
|
|
18
|
+
# Can be either +xl+, +l+ or +m+.
|
|
19
|
+
#
|
|
20
|
+
# * +:default_legend_size+ controls the default size of legend text.
|
|
21
|
+
# Can be either +xl+, +l+, +m+ or +s+.
|
|
22
|
+
#
|
|
23
|
+
# * +:default_legend_tag+ controls the default tag that legends are
|
|
24
|
+
# wrapped in. Defaults to +h1+.
|
|
25
|
+
#
|
|
26
|
+
# * +:default_submit_button_text+ sets the value assigned to +govuk_submit+,
|
|
27
|
+
# defaults to 'Continue'.
|
|
28
|
+
#
|
|
29
|
+
# * +:default_submit_button_text+ sets the text used to divide the last radio
|
|
30
|
+
# button in radio button fieldsets. As per the GOV.UK Design System spec,
|
|
31
|
+
# it defaults to 'or'.
|
|
32
|
+
#
|
|
33
|
+
# * +:default_error_summary_title+ sets the text used in error summary
|
|
34
|
+
# blocks. As per the GOV.UK Design System spec, it defaults to
|
|
35
|
+
# 'There is a problem'.
|
|
36
|
+
#
|
|
37
|
+
# * +:localisation_schema_fallback+ sets the prefix elements for the array
|
|
38
|
+
# used to build the localisation string. The final two elements are always
|
|
39
|
+
# are the object name and attribute name. The _special_ value +__context__+,
|
|
40
|
+
# is used as a placeholder for the context (label, fieldset or hint).
|
|
41
|
+
#
|
|
42
|
+
# * +:localisation_schema_legend+, +:localisation_schema_hint+ and
|
|
43
|
+
# +:localisation_schema_label+ each override the schema root for their
|
|
44
|
+
# particular context, allowing them to be independently customised.
|
|
45
|
+
# ===
|
|
46
|
+
DEFAULTS = {
|
|
47
|
+
brand: 'govuk',
|
|
48
|
+
|
|
49
|
+
default_legend_size: 'm',
|
|
50
|
+
default_legend_tag: 'h1',
|
|
51
|
+
default_caption_size: 'm',
|
|
52
|
+
default_submit_button_text: 'Continue',
|
|
53
|
+
default_radio_divider_text: 'or',
|
|
54
|
+
default_error_summary_title: 'There is a problem',
|
|
55
|
+
|
|
56
|
+
localisation_schema_fallback: %i(helpers __context__),
|
|
57
|
+
localisation_schema_label: nil,
|
|
58
|
+
localisation_schema_hint: nil,
|
|
59
|
+
localisation_schema_legend: nil,
|
|
60
|
+
localisation_schema_caption: nil
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
63
|
+
DEFAULTS.each_key { |k| config_accessor(k) { DEFAULTS[k] } }
|
|
64
|
+
# @!endgroup
|
|
65
|
+
|
|
66
|
+
class << self
|
|
67
|
+
# Configure the form builder in the usual manner. All of the
|
|
68
|
+
# keys in {DEFAULTS} can be configured as per the example below
|
|
69
|
+
#
|
|
70
|
+
# @example
|
|
71
|
+
# GOVUKDesignSystemFormBuilder.configure do |conf|
|
|
72
|
+
# conf.default_legend_size = 'xl'
|
|
73
|
+
# conf.default_error_summary_title = 'OMG'
|
|
74
|
+
# end
|
|
75
|
+
def configure
|
|
76
|
+
yield(config)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Resets each of the configurable values to its default
|
|
80
|
+
#
|
|
81
|
+
# @note This method is only really intended for use to clean up
|
|
82
|
+
# during testing
|
|
83
|
+
def reset!
|
|
84
|
+
configure do |c|
|
|
85
|
+
DEFAULTS.each { |k, v| c.send("#{k}=", v) }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
43
90
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
|
44
|
-
delegate :content_tag, :tag, :safe_join, :
|
|
91
|
+
delegate :content_tag, :tag, :safe_join, :link_to, :capture, to: :@template
|
|
45
92
|
|
|
46
93
|
include GOVUKDesignSystemFormBuilder::Builder
|
|
47
94
|
end
|
|
48
95
|
|
|
49
96
|
# Disable Rails' div.field_with_error wrapper
|
|
50
|
-
ActionView::Base.field_error_proc =
|
|
51
|
-
html_tag.html_safe
|
|
52
|
-
end
|
|
97
|
+
ActionView::Base.field_error_proc = ->(html_tag, _instance) { html_tag }
|
|
53
98
|
end
|