bootstrap_form 4.1.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -0
  3. data/.rubocop.yml +3 -2
  4. data/.travis.yml +7 -1
  5. data/CHANGELOG.md +15 -1
  6. data/CONTRIBUTING.md +11 -0
  7. data/Dangerfile +4 -4
  8. data/Gemfile +7 -2
  9. data/OLD-README.md +795 -0
  10. data/README.md +150 -93
  11. data/Rakefile +2 -4
  12. data/bootstrap_form.gemspec +2 -1
  13. data/demo/.postcssrc.yml +3 -0
  14. data/demo/app/assets/config/manifest.js +2 -0
  15. data/demo/app/assets/stylesheets/actiontext.scss +38 -0
  16. data/demo/app/assets/stylesheets/application.scss +1 -0
  17. data/demo/app/helpers/bootstrap_helper.rb +16 -10
  18. data/demo/app/javascript/channels/consumer.js +6 -0
  19. data/demo/app/javascript/channels/index.js +5 -0
  20. data/demo/app/javascript/packs/application.js +11 -0
  21. data/demo/app/models/user.rb +2 -0
  22. data/demo/app/views/active_storage/blobs/_blob.html.erb +14 -0
  23. data/demo/app/views/bootstrap/form.html.erb +2 -1
  24. data/demo/app/views/layouts/application.html.erb +3 -0
  25. data/demo/bin/webpack +15 -0
  26. data/demo/bin/webpack-dev-server +15 -0
  27. data/demo/config/application.rb +2 -3
  28. data/demo/config/environments/development.rb +3 -1
  29. data/demo/config/environments/production.rb +48 -0
  30. data/demo/config/webpack/development.js +5 -0
  31. data/demo/config/webpack/environment.js +3 -0
  32. data/demo/config/webpack/production.js +5 -0
  33. data/demo/config/webpack/test.js +5 -0
  34. data/demo/config/webpacker.yml +92 -0
  35. data/demo/db/schema.rb +63 -18
  36. data/demo/package.json +13 -1
  37. data/demo/test/fixtures/action_text/rich_texts.yml +4 -0
  38. data/demo/yarn.lock +6257 -0
  39. data/lib/bootstrap_form.rb +34 -8
  40. data/lib/bootstrap_form/action_view_extensions/form_helper.rb +71 -0
  41. data/lib/bootstrap_form/components.rb +17 -0
  42. data/lib/bootstrap_form/components/hints.rb +60 -0
  43. data/lib/bootstrap_form/components/labels.rb +56 -0
  44. data/lib/bootstrap_form/components/layout.rb +39 -0
  45. data/lib/bootstrap_form/components/validation.rb +61 -0
  46. data/lib/bootstrap_form/engine.rb +10 -0
  47. data/lib/bootstrap_form/form_builder.rb +54 -524
  48. data/lib/bootstrap_form/form_group.rb +64 -0
  49. data/lib/bootstrap_form/form_group_builder.rb +103 -0
  50. data/lib/bootstrap_form/helpers.rb +9 -0
  51. data/lib/bootstrap_form/helpers/bootstrap.rb +39 -31
  52. data/lib/bootstrap_form/inputs.rb +40 -0
  53. data/lib/bootstrap_form/inputs/base.rb +40 -0
  54. data/lib/bootstrap_form/inputs/check_box.rb +89 -0
  55. data/lib/bootstrap_form/inputs/collection_check_boxes.rb +23 -0
  56. data/lib/bootstrap_form/inputs/collection_radio_buttons.rb +21 -0
  57. data/lib/bootstrap_form/inputs/collection_select.rb +25 -0
  58. data/lib/bootstrap_form/inputs/color_field.rb +14 -0
  59. data/lib/bootstrap_form/inputs/date_field.rb +14 -0
  60. data/lib/bootstrap_form/inputs/date_select.rb +14 -0
  61. data/lib/bootstrap_form/inputs/datetime_field.rb +14 -0
  62. data/lib/bootstrap_form/inputs/datetime_local_field.rb +14 -0
  63. data/lib/bootstrap_form/inputs/datetime_select.rb +14 -0
  64. data/lib/bootstrap_form/inputs/email_field.rb +14 -0
  65. data/lib/bootstrap_form/inputs/file_field.rb +35 -0
  66. data/lib/bootstrap_form/inputs/grouped_collection_select.rb +29 -0
  67. data/lib/bootstrap_form/inputs/inputs_collection.rb +44 -0
  68. data/lib/bootstrap_form/inputs/month_field.rb +14 -0
  69. data/lib/bootstrap_form/inputs/number_field.rb +14 -0
  70. data/lib/bootstrap_form/inputs/password_field.rb +14 -0
  71. data/lib/bootstrap_form/inputs/phone_field.rb +14 -0
  72. data/lib/bootstrap_form/inputs/radio_button.rb +77 -0
  73. data/lib/bootstrap_form/inputs/range_field.rb +14 -0
  74. data/lib/bootstrap_form/inputs/rich_text_area.rb +23 -0
  75. data/lib/bootstrap_form/inputs/search_field.rb +14 -0
  76. data/lib/bootstrap_form/inputs/select.rb +22 -0
  77. data/lib/bootstrap_form/inputs/telephone_field.rb +14 -0
  78. data/lib/bootstrap_form/inputs/text_area.rb +14 -0
  79. data/lib/bootstrap_form/inputs/text_field.rb +14 -0
  80. data/lib/bootstrap_form/inputs/time_field.rb +14 -0
  81. data/lib/bootstrap_form/inputs/time_select.rb +14 -0
  82. data/lib/bootstrap_form/inputs/time_zone_select.rb +22 -0
  83. data/lib/bootstrap_form/inputs/url_field.rb +14 -0
  84. data/lib/bootstrap_form/inputs/week_field.rb +14 -0
  85. data/lib/bootstrap_form/version.rb +1 -1
  86. metadata +79 -6
  87. data/.rubocop_todo.yml +0 -104
  88. data/lib/bootstrap_form/aliasing.rb +0 -35
  89. data/lib/bootstrap_form/helper.rb +0 -52
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module CollectionCheckBoxes
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+ include InputsCollection
9
+
10
+ included do
11
+ def collection_check_boxes_with_bootstrap(*args)
12
+ html = inputs_collection(*args) do |name, value, options|
13
+ options[:multiple] = true
14
+ check_box(name, options, value, nil)
15
+ end
16
+ hidden_field(args.first, value: "", multiple: true).concat(html)
17
+ end
18
+
19
+ bootstrap_alias :collection_check_boxes
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module CollectionRadioButtons
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+ include InputsCollection
9
+
10
+ included do
11
+ def collection_radio_buttons_with_bootstrap(*args)
12
+ inputs_collection(*args) do |name, value, options|
13
+ radio_button(name, value, options)
14
+ end
15
+ end
16
+
17
+ bootstrap_alias :collection_radio_buttons
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module CollectionSelect
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ # Disabling Metrics/ParameterLists because the upstream Rails method has the same parameters
11
+ # rubocop:disable Metrics/ParameterLists
12
+ def collection_select_with_bootstrap(method, collection, value_method, text_method, options={}, html_options={})
13
+ form_group_builder(method, options, html_options) do
14
+ input_with_error(method) do
15
+ collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)
16
+ end
17
+ end
18
+ end
19
+ # rubocop:enable Metrics/ParameterLists
20
+
21
+ bootstrap_alias :collection_select
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module ColorField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :color_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module DateField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :date_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module DateSelect
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_select_group :date_select
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module DatetimeField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :datetime_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module DatetimeLocalField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :datetime_local_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module DatetimeSelect
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_select_group :datetime_select
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module EmailField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :email_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module FileField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ def file_field_with_bootstrap(name, options={})
11
+ options = options.reverse_merge(control_class: "custom-file-input")
12
+ form_group_builder(name, options) do
13
+ content_tag(:div, class: "custom-file") do
14
+ input_with_error(name) do
15
+ file_field_input(name, options)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ bootstrap_alias :file_field
22
+ end
23
+
24
+ private
25
+
26
+ def file_field_input(name, options)
27
+ placeholder = options.delete(:placeholder) || "Choose file"
28
+ placeholder_opts = { class: "custom-file-label" }
29
+ placeholder_opts[:for] = options[:id] if options[:id].present?
30
+
31
+ file_field_without_bootstrap(name, options) + label(name, placeholder, placeholder_opts)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module GroupedCollectionSelect
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ # Disabling Metrics/ParameterLists because the upstream Rails method has the same parameters
11
+ # rubocop:disable Metrics/ParameterLists
12
+ def grouped_collection_select_with_bootstrap(method, collection, group_method,
13
+ group_label_method, option_key_method,
14
+ option_value_method, options={}, html_options={})
15
+ form_group_builder(method, options, html_options) do
16
+ input_with_error(method) do
17
+ grouped_collection_select_without_bootstrap(method, collection, group_method,
18
+ group_label_method, option_key_method,
19
+ option_value_method, options, html_options)
20
+ end
21
+ end
22
+ end
23
+ # rubocop:enable Metrics/ParameterLists
24
+
25
+ bootstrap_alias :grouped_collection_select
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ module BootstrapForm
2
+ module Inputs
3
+ module InputsCollection
4
+ extend ActiveSupport::Concern
5
+
6
+ private
7
+
8
+ def inputs_collection(name, collection, value, text, options={})
9
+ options[:inline] ||= layout_inline?(options[:layout])
10
+
11
+ form_group_builder(name, options) do
12
+ inputs = ActiveSupport::SafeBuffer.new
13
+
14
+ collection.each_with_index do |obj, i|
15
+ input_value = value.respond_to?(:call) ? value.call(obj) : obj.send(value)
16
+ input_options = form_group_collection_input_options(options, text, obj, i, input_value, collection)
17
+ inputs << yield(name, input_value, input_options)
18
+ end
19
+
20
+ inputs
21
+ end
22
+ end
23
+
24
+ # FIXME: Find a way to reduce the parameter list size
25
+ # rubocop:disable Metrics/ParameterLists
26
+ def form_group_collection_input_options(options, text, obj, index, input_value, collection)
27
+ input_options = options.merge(label: text.respond_to?(:call) ? text.call(obj) : obj.send(text))
28
+ if (checked = input_options[:checked])
29
+ input_options[:checked] = form_group_collection_input_checked?(checked, obj, input_value)
30
+ end
31
+
32
+ input_options[:error_message] = index == collection.size - 1
33
+ input_options.except!(:class)
34
+ input_options
35
+ end
36
+ # rubocop:enable Metrics/ParameterLists
37
+
38
+ def form_group_collection_input_checked?(checked, obj, input_value)
39
+ checked == input_value || Array(checked).try(:include?, input_value) ||
40
+ checked == obj || Array(checked).try(:include?, obj)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module MonthField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :month_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module NumberField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :number_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module PasswordField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :password_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module PhoneField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :phone_field
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module RadioButton
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ def radio_button_with_bootstrap(name, value, *args)
11
+ options = args.extract_options!.symbolize_keys!
12
+ radio_button_options = options.except(:class, :label, :label_class, :error_message, :help,
13
+ :inline, :custom, :hide_label, :skip_label, :wrapper_class)
14
+
15
+ radio_button_options[:class] = radio_button_classes(name, options)
16
+
17
+ content_tag(:div, class: radio_button_wrapper_class(options)) do
18
+ html = radio_button_without_bootstrap(name, value, radio_button_options)
19
+ html.concat(radio_button_label(name, value, options)) unless options[:skip_label]
20
+ html.concat(generate_error(name)) if options[:error_message]
21
+ html
22
+ end
23
+ end
24
+
25
+ bootstrap_alias :radio_button
26
+ end
27
+
28
+ private
29
+
30
+ def radio_button_label(name, value, options)
31
+ label_options = { value: value, class: radio_button_label_class(options) }
32
+ label_options[:for] = options[:id] if options[:id].present?
33
+ label(name, options[:label], label_options)
34
+ end
35
+
36
+ def radio_button_classes(name, options)
37
+ classes = [options[:class]]
38
+ classes << (options[:custom] ? "custom-control-input" : "form-check-input")
39
+ classes << "is-invalid" if error?(name)
40
+ classes << "position-static" if options[:skip_label] || options[:hide_label]
41
+ classes.flatten.compact
42
+ end
43
+
44
+ def radio_button_label_class(options)
45
+ classes = []
46
+ classes << (options[:custom] ? "custom-control-label" : "form-check-label")
47
+ classes << options[:label_class]
48
+ classes << hide_class if options[:hide_label]
49
+ classes.flatten.compact
50
+ end
51
+
52
+ def radio_button_wrapper_class(options)
53
+ classes = []
54
+ classes << if options[:custom]
55
+ custom_radio_button_wrapper_class(options)
56
+ else
57
+ standard_radio_button_wrapper_class(options)
58
+ end
59
+ classes << options[:wrapper_class] if options[:wrapper_class].present?
60
+ classes.flatten.compact
61
+ end
62
+
63
+ def standard_radio_button_wrapper_class(options)
64
+ classes = ["form-check"]
65
+ classes << "form-check-inline" if layout_inline?(options[:inline])
66
+ classes << "disabled" if options[:disabled]
67
+ classes
68
+ end
69
+
70
+ def custom_radio_button_wrapper_class(options)
71
+ classes = ["custom-control", "custom-radio"]
72
+ classes << "custom-control-inline" if layout_inline?(options[:inline])
73
+ classes
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BootstrapForm
4
+ module Inputs
5
+ module RangeField
6
+ extend ActiveSupport::Concern
7
+ include Base
8
+
9
+ included do
10
+ bootstrap_field :range_field
11
+ end
12
+ end
13
+ end
14
+ end