headmin 0.3.4 → 0.4.2

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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +27 -0
  3. data/.gitignore +14 -0
  4. data/.lock-487e157d270f3062a98b7b2a012753708-1272821827 +0 -0
  5. data/.nvmrc +1 -0
  6. data/CHANGELOG.md +31 -0
  7. data/Gemfile +7 -4
  8. data/Gemfile.lock +191 -25
  9. data/README.md +7 -0
  10. data/Rakefile +1 -7
  11. data/app/assets/javascripts/headmin/config/i18n.js +9 -9
  12. data/app/assets/javascripts/headmin/controllers/autocomplete_controller.js +318 -0
  13. data/app/assets/javascripts/headmin/controllers/blocks_controller.js +74 -79
  14. data/app/assets/javascripts/headmin/controllers/date_range_controller.js +24 -24
  15. data/app/assets/javascripts/headmin/controllers/dropzone_controller.js +23 -25
  16. data/app/assets/javascripts/headmin/controllers/file_preview_controller.js +237 -237
  17. data/app/assets/javascripts/headmin/controllers/filter_controller.js +44 -44
  18. data/app/assets/javascripts/headmin/controllers/filters_controller.js +57 -61
  19. data/app/assets/javascripts/headmin/controllers/flatpickr_controller.js +29 -29
  20. data/app/assets/javascripts/headmin/controllers/hello_controller.js +3 -3
  21. data/app/assets/javascripts/headmin/controllers/notification_controller.js +7 -6
  22. data/app/assets/javascripts/headmin/controllers/popup_controller.js +57 -51
  23. data/app/assets/javascripts/headmin/controllers/redactorx_controller.js +36 -9
  24. data/app/assets/javascripts/headmin/controllers/repeater_controller.js +122 -125
  25. data/app/assets/javascripts/headmin/controllers/select_controller.js +40 -39
  26. data/app/assets/javascripts/headmin/controllers/table_actions_controller.js +100 -101
  27. data/app/assets/javascripts/headmin/controllers/table_controller.js +115 -115
  28. data/app/assets/javascripts/headmin/index.js +38 -35
  29. data/app/assets/javascripts/headmin.js +295 -37
  30. data/app/assets/stylesheets/headmin/forms/autocomplete.scss +21 -0
  31. data/app/assets/stylesheets/headmin/forms/file.scss +46 -0
  32. data/app/assets/stylesheets/headmin/forms/repeater.scss +62 -0
  33. data/app/assets/stylesheets/headmin/forms/search.scss +12 -0
  34. data/app/assets/stylesheets/headmin/forms.scss +11 -0
  35. data/app/assets/stylesheets/headmin/general.scss +14 -0
  36. data/app/assets/stylesheets/headmin/overrides/bootstrap.scss +5 -3
  37. data/app/assets/stylesheets/headmin/overrides/redactorx.scss +74 -0
  38. data/app/assets/stylesheets/headmin/popup.scss +1 -0
  39. data/app/assets/stylesheets/headmin/syntax.scss +36 -349
  40. data/app/assets/stylesheets/headmin/table.scss +1 -1
  41. data/app/assets/stylesheets/headmin/utilities/buttons.scss +19 -0
  42. data/app/assets/stylesheets/headmin/utilities/dropzone.scss +72 -0
  43. data/app/assets/stylesheets/headmin/utilities.scss +2 -68
  44. data/app/assets/stylesheets/headmin.css +209 -205
  45. data/app/assets/stylesheets/headmin.scss +1 -1
  46. data/app/helpers/headmin/admin_helper.rb +0 -1
  47. data/app/helpers/headmin/form_helper.rb +2 -8
  48. data/app/models/concerns/headmin/blockable.rb +1 -1
  49. data/app/models/concerns/headmin/field.rb +4 -1
  50. data/app/models/concerns/headmin/fieldable.rb +138 -44
  51. data/app/models/concerns/headmin/form/autocompletable.rb +38 -0
  52. data/app/models/concerns/headmin/form/hintable.rb +19 -0
  53. data/app/models/concerns/headmin/form/input_groupable.rb +23 -0
  54. data/app/models/concerns/headmin/form/labelable.rb +33 -0
  55. data/app/models/concerns/headmin/form/listable.rb +28 -0
  56. data/app/models/concerns/headmin/form/placeholderable.rb +13 -0
  57. data/app/models/concerns/headmin/form/validatable.rb +40 -0
  58. data/app/models/concerns/headmin/form/wrappable.rb +21 -0
  59. data/app/models/headmin/.DS_Store +0 -0
  60. data/app/models/headmin/blocks_view.rb +15 -0
  61. data/app/models/headmin/form/blocks_view.rb +29 -0
  62. data/app/models/headmin/form/checkbox_view.rb +52 -0
  63. data/app/models/headmin/form/date_range_view.rb +25 -0
  64. data/app/models/headmin/form/date_view.rb +45 -0
  65. data/app/models/headmin/form/email_view.rb +48 -0
  66. data/app/models/headmin/form/file_view.rb +116 -0
  67. data/app/models/headmin/form/flatpickr_range_view.rb +102 -0
  68. data/app/models/headmin/form/flatpickr_view.rb +37 -0
  69. data/app/models/headmin/form/hidden_view.rb +10 -0
  70. data/app/models/headmin/form/hint_view.rb +6 -0
  71. data/app/models/headmin/form/input_group_view.rb +19 -0
  72. data/app/models/headmin/form/label_view.rb +24 -0
  73. data/app/models/headmin/form/number_view.rb +49 -0
  74. data/app/models/headmin/form/password_view.rb +44 -0
  75. data/app/models/headmin/form/redactorx_view.rb +59 -0
  76. data/app/models/headmin/form/search_view.rb +48 -0
  77. data/app/models/headmin/form/select_view.rb +62 -0
  78. data/app/models/headmin/form/switch_view.rb +23 -0
  79. data/app/models/headmin/form/text_view.rb +48 -0
  80. data/app/models/headmin/form/textarea_view.rb +44 -0
  81. data/app/models/headmin/form/url_view.rb +48 -0
  82. data/app/models/headmin/form/wrapper_view.rb +19 -0
  83. data/app/models/headmin/form/wysiwyg_view.rb +17 -0
  84. data/app/models/headmin/{thumbnail.rb → thumbnail_view.rb} +6 -1
  85. data/app/models/view_model.rb +58 -0
  86. data/app/views/headmin/_blocks.html.erb +13 -9
  87. data/app/views/headmin/_heading.html.erb +7 -1
  88. data/app/views/headmin/_thumbnail.html.erb +1 -37
  89. data/app/views/headmin/forms/_autocomplete.html.erb +11 -0
  90. data/app/views/headmin/forms/_blocks.html.erb +16 -17
  91. data/app/views/headmin/forms/_checkbox.html.erb +24 -29
  92. data/app/views/headmin/forms/_datalist.html.erb +3 -0
  93. data/app/views/headmin/forms/_date.html.erb +24 -24
  94. data/app/views/headmin/forms/_date_range.html.erb +19 -21
  95. data/app/views/headmin/forms/_email.html.erb +27 -32
  96. data/app/views/headmin/forms/_errors.html.erb +2 -3
  97. data/app/views/headmin/forms/_file.html.erb +84 -181
  98. data/app/views/headmin/forms/_flatpickr.html.erb +19 -20
  99. data/app/views/headmin/forms/_flatpickr_range.html.erb +28 -37
  100. data/app/views/headmin/forms/_hidden.html.erb +9 -10
  101. data/app/views/headmin/forms/_hint.html.erb +16 -0
  102. data/app/views/headmin/forms/_input_group.html.erb +21 -0
  103. data/app/views/headmin/forms/_label.html.erb +5 -13
  104. data/app/views/headmin/forms/_number.html.erb +23 -35
  105. data/app/views/headmin/forms/_password.html.erb +21 -30
  106. data/app/views/headmin/forms/_redactorx.html.erb +21 -40
  107. data/app/views/headmin/forms/_repeater.html.erb +55 -60
  108. data/app/views/headmin/forms/_search.html.erb +43 -0
  109. data/app/views/headmin/forms/_select.html.erb +24 -49
  110. data/app/views/headmin/forms/_switch.html.erb +29 -0
  111. data/app/views/headmin/forms/_text.html.erb +42 -96
  112. data/app/views/headmin/forms/_textarea.html.erb +21 -32
  113. data/app/views/headmin/forms/_url.html.erb +26 -31
  114. data/app/views/headmin/forms/_validation.html.erb +10 -13
  115. data/app/views/headmin/forms/_wrapper.html.erb +9 -0
  116. data/app/views/headmin/forms/_wysiwyg.html.erb +28 -0
  117. data/app/views/headmin/forms/autocomplete/_item.html.erb +3 -0
  118. data/app/views/headmin/forms/autocomplete/_list.html.erb +3 -0
  119. data/app/views/headmin/forms/fields/_file.html.erb +1 -1
  120. data/app/views/headmin/forms/fields/_files.html.erb +17 -0
  121. data/app/views/headmin/forms/fields/_group.html.erb +9 -2
  122. data/app/views/headmin/forms/repeater/_row.html.erb +4 -4
  123. data/bin/console +0 -1
  124. data/config/locales/headmin/forms/en.yml +1 -12
  125. data/config/locales/headmin/forms/nl.yml +1 -12
  126. data/esbuild-css.js +18 -18
  127. data/esbuild-js.js +8 -8
  128. data/headmin.gemspec +1 -3
  129. data/lib/generators/templates/controllers/auth/confirmations_controller.rb +0 -2
  130. data/lib/generators/templates/controllers/auth/omniauth_callbacks_controller.rb +0 -2
  131. data/lib/generators/templates/controllers/auth/passwords_controller.rb +0 -2
  132. data/lib/generators/templates/controllers/auth/registrations_controller.rb +0 -2
  133. data/lib/generators/templates/controllers/auth/sessions_controller.rb +0 -2
  134. data/lib/generators/templates/controllers/auth/unlocks_controller.rb +0 -2
  135. data/lib/headmin/version.rb +1 -3
  136. data/lib/headmin.rb +0 -2
  137. data/package-lock.json +5359 -0
  138. data/package.json +12 -4
  139. data/view_model_benchmark.rb +74 -0
  140. data/yarn-error.log +17 -12
  141. data/yarn.lock +1575 -31
  142. metadata +64 -25
  143. data/app/assets/stylesheets/headmin/form.scss +0 -132
  144. data/app/assets/stylesheets/headmin/overrides/redactorx.css +0 -3
  145. data/app/helpers/headmin/documentation_helper.rb +0 -35
  146. data/app/models/headmin/documentation_renderer.rb +0 -32
  147. data/app/models/headmin/form/base.rb +0 -78
  148. data/app/models/headmin/form/text.rb +0 -51
  149. data/app/services/block_service.rb +0 -72
  150. data/app/views/headmin/_card.html.erb +0 -52
  151. data/app/views/headmin/forms/_actions.html.erb +0 -28
  152. data/app/views/headmin/forms/_base.html.erb +0 -114
  153. data/app/views/headmin/forms/_image.html.erb +0 -21
  154. data/app/views/headmin/forms/_video.html.erb +0 -21
  155. data/app/views/headmin/forms/actions/_destroy.html.erb +0 -13
  156. data/app/views/headmin/forms/actions/_save.html.erb +0 -12
  157. data/app/views/headmin/forms/actions/_view.html.erb +0 -15
  158. data/app/views/headmin/forms/fields/_image.html.erb +0 -17
  159. data/docs/blocks-and-fields.md +0 -54
  160. data/docs/blocks.md +0 -48
  161. data/docs/devise.md +0 -41
  162. data/docs/fields.md +0 -79
@@ -6,68 +6,162 @@ module Headmin
6
6
  has_many :fields, as: :fieldable, dependent: :destroy
7
7
  accepts_nested_attributes_for :fields, allow_destroy: true
8
8
 
9
+ # Callbacks
10
+ before_validation :build_fields
11
+
9
12
  def fields_hash
10
- fields.order(position: :asc).map do |field|
11
- parse_hash_tree(field.hash_tree)
12
- end.reduce({}, :merge)
13
+ @fields_hash ||= parse_fields
13
14
  end
14
15
 
15
16
  def fields_hash=(hash)
16
- parse_fields_hash(hash)
17
+ @fields_hash = hash
17
18
  end
18
19
 
19
20
  private
20
21
 
21
- def parse_fields_hash(hash)
22
+ def parse_fields
23
+ fields.where(parent: nil).order(position: :asc).map { |field| parse_hash_tree(field.hash_tree) }.reduce({}, :merge)
24
+ end
25
+
26
+ def build_fields
27
+ return unless @fields_hash
28
+ self.fields = fields_for(@fields_hash)
29
+ end
30
+
31
+ def fields_for(hash)
22
32
  hash.map do |key, value|
23
33
  case value
24
34
  when Hash
25
- fields.build(
26
- name: key,
27
- field_type: "group",
28
- fields: parse_fields_hash(value)
29
- )
35
+ field_for_hash(key, value)
30
36
  when Array
31
- fields.build(
32
- name: key,
33
- field_type: "list",
34
- fields: value.map do |item|
35
- fields.new(name: "item", field_type: "group", fields: parse_fields_hash(item))
36
- end
37
- )
38
- when String
39
- fields.build(
40
- name: key,
41
- field_type: "text",
42
- value: value
43
- )
37
+ field_for_array(key, value)
38
+ when File
39
+ field_for_file(key, value)
44
40
  else
45
- fields.build(
46
- name: key,
47
- field_type: "file",
48
- file: value
49
- )
41
+ field_for_string(key, value)
50
42
  end
51
43
  end
52
44
  end
53
45
 
46
+ def field_for_hash(name, hash)
47
+ ::Field.new(
48
+ fieldable: self,
49
+ name: name,
50
+ field_type: "group",
51
+ fields: fields_for(hash)
52
+ )
53
+ end
54
+
55
+ def field_for_array(name, array)
56
+ if array.all? { |item| item.is_a?(File) }
57
+ field_for_files(name, array)
58
+ elsif array.all? { |item| item.is_a?(Hash) }
59
+ field_for_group_list(name, array)
60
+ else
61
+ field_for_simple_list(name, array)
62
+ end
63
+ end
64
+
65
+ def field_for_simple_list(name, array)
66
+ ::Field.new(
67
+ fieldable: self,
68
+ name: name,
69
+ field_type: "list",
70
+ fields: array.map { |item| fields_for({item: item}) }.flatten
71
+ )
72
+ end
73
+
74
+ def field_for_group_list(name, array)
75
+ ::Field.new(
76
+ fieldable: self,
77
+ name: name,
78
+ field_type: "list",
79
+ fields: array.map { |item| ::Field.new(fieldable: self, name: "item", field_type: "group", fields: fields_for(item)) }
80
+ )
81
+ end
82
+
83
+ def field_for_string(name, string)
84
+ ::Field.new(
85
+ fieldable: self,
86
+ name: name,
87
+ field_type: "text",
88
+ value: string
89
+ )
90
+ end
91
+
92
+ def field_for_file(name, file)
93
+ ::Field.new(
94
+ fieldable: self,
95
+ name: name,
96
+ field_type: "file",
97
+ value: nil,
98
+ files: [ActiveStorage::Blob.create_and_upload!(
99
+ io: file,
100
+ filename: File.basename(file.path)
101
+ )]
102
+ )
103
+ end
104
+
105
+ def field_for_files(name, files)
106
+ ::Field.new(
107
+ fieldable: self,
108
+ name: name,
109
+ field_type: "files",
110
+ value: nil,
111
+ files: files.map { |file|
112
+ ActiveStorage::Blob.create_and_upload!(
113
+ io: file,
114
+ filename: File.basename(file.path)
115
+ )
116
+ }
117
+ )
118
+ end
119
+
120
+ # From hash tree to hash
54
121
  def parse_hash_tree(hash_tree)
55
- hash_tree.map do |field, children|
56
- case field.field_type.to_sym
57
- when :group
58
- children = children.any? ? children : field.hash_tree
59
- [field.name, parse_hash_tree(children)]
60
- when :list
61
- children = children.any? ? children : field.hash_tree
62
- [field.name, children.map { |child, grand_children| parse_hash_tree(grand_children) }]
63
- when :image
64
- [field.name, field.file]
65
- when :file
66
- [field.name, field.file]
67
- else
68
- [field.name, field.value]
69
- end
70
- end.to_h
122
+ new_hash = {}
123
+ hash_tree.each do |field, children|
124
+ new_hash[field.name.to_sym] = parse_field(field, children)
125
+ end
126
+ new_hash
127
+ end
128
+
129
+ # Parse value for given field
130
+ def parse_field(field, children)
131
+ case field.field_type.to_sym
132
+ when :group
133
+ parse_group_field(field, children)
134
+ when :list
135
+ parse_list_field(field, children)
136
+ when :files
137
+ parse_files_field(field)
138
+ when :file
139
+ parse_file_field(field)
140
+ else
141
+ parse_text_field(field)
142
+ end
143
+ end
144
+
145
+ def parse_group_field(field, children)
146
+ parse_hash_tree(children)
147
+ end
148
+
149
+ def parse_list_field(field, children)
150
+ children.map do |child, grand_children|
151
+ parse_field(child, grand_children)
152
+ end
153
+ end
154
+
155
+ def parse_files_field(field)
156
+ field.files.all
157
+ end
158
+
159
+ def parse_file_field(field)
160
+ field.files.last
161
+ end
162
+
163
+ def parse_text_field(field)
164
+ field.value
71
165
  end
72
166
  end
73
167
  end
@@ -0,0 +1,38 @@
1
+ module Headmin
2
+ module Form
3
+ module Autocompletable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def autocomplete?
8
+ collection.is_a?(String) || collection.is_a?(Array)
9
+ end
10
+
11
+ def autocomplete_options
12
+ {
13
+ collection: collection.is_a?(Array) ? collection : []
14
+ }
15
+ end
16
+
17
+ def autocomplete_input_options
18
+ {
19
+ data: {
20
+ autocomplete_target: autocomplete? ? "input" : nil
21
+ }
22
+ }
23
+ end
24
+
25
+ def autocomplete_input_group_options
26
+ options = {
27
+ data: {
28
+ controller: autocomplete? ? "autocomplete" : nil,
29
+ autocomplete_url_value: collection.is_a?(String) ? collection : nil
30
+ }
31
+ }
32
+ options = options.merge(bypass: false) if autocomplete?
33
+ options
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ module Headmin
2
+ module Form
3
+ module Hintable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def hint?
8
+ hint.present?
9
+ end
10
+
11
+ def hint_options
12
+ {
13
+ content: hint
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module Headmin
2
+ module Form
3
+ module InputGroupable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def input_group_options
8
+ default_input_group_options.merge(@input_group || {})
9
+ end
10
+
11
+ private
12
+
13
+ def default_input_group_options
14
+ {
15
+ bypass: !(prepend || append || @input_group),
16
+ prepend: prepend,
17
+ append: append
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module Headmin
2
+ module Form
3
+ module Labelable
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ def label?
7
+ label != false
8
+ end
9
+
10
+ def prepend_label?
11
+ label != false && !float
12
+ end
13
+
14
+ def append_label?
15
+ label != false && float
16
+ end
17
+
18
+ def label_input_group_options
19
+ float ? {bypass: true} : {}
20
+ end
21
+
22
+ def label_options
23
+ {
24
+ attribute: attribute,
25
+ form: form,
26
+ required: required,
27
+ text: label
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ module Headmin
2
+ module Form
3
+ module Listable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def list
8
+ datalist_id if @list
9
+ end
10
+
11
+ def datalist?
12
+ @list.present?
13
+ end
14
+
15
+ def datalist_options
16
+ {
17
+ collection: @list,
18
+ id: datalist_id
19
+ }
20
+ end
21
+
22
+ def datalist_id
23
+ "#{attribute}_list"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Headmin
2
+ module Form
3
+ module Placeholderable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def placeholder
8
+ float ? @placeholder || attribute : @placeholder
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module Headmin
2
+ module Form
3
+ module Validatable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def validation_options
8
+ {
9
+ id: validation_id,
10
+ message: validation_message,
11
+ valid: valid?
12
+ }
13
+ end
14
+
15
+ def validate?
16
+ form.object&.errors&.any?
17
+ end
18
+
19
+ private
20
+
21
+ def valid?
22
+ !form.object&.errors&.has_key?(attribute)
23
+ end
24
+
25
+ def validation_message
26
+ form.object&.errors&.full_messages_for(attribute)&.join(", ")
27
+ end
28
+
29
+ def validation_id
30
+ [attribute.to_s, "validation"].join("_").parameterize.underscore
31
+ end
32
+
33
+ def validation_class
34
+ return unless validate?
35
+ valid? ? "is-valid" : "is-invalid"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module Headmin
2
+ module Form
3
+ module Wrappable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def wrapper_options
8
+ default_wrapper_options.merge(@wrapper || {})
9
+ end
10
+
11
+ private
12
+
13
+ def default_wrapper_options
14
+ {
15
+ bypass: @wrapper == false
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
Binary file
@@ -0,0 +1,15 @@
1
+ module Headmin
2
+ class BlocksView < ViewModel
3
+ def show_blocks?
4
+ blockable&.respond_to?(:blocks)
5
+ end
6
+
7
+ def paths
8
+ @paths || []
9
+ end
10
+
11
+ def prefixes
12
+ paths + ["website/blocks", "blocks", ""]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ module Headmin
2
+ module Form
3
+ class BlocksView < ViewModel
4
+ def repeater_options
5
+ keys = %i[form attribute names label]
6
+ options = to_h.slice(*keys)
7
+ default_repeater_options.deep_merge(options)
8
+ end
9
+
10
+ def paths
11
+ @paths || []
12
+ end
13
+
14
+ def prefixes
15
+ paths + ["admin/blocks", "blocks", ""]
16
+ end
17
+
18
+ private
19
+
20
+ def default_repeater_options
21
+ {
22
+ attribute: "blocks",
23
+ label: false,
24
+ templates: names
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,52 @@
1
+ module Headmin
2
+ module Form
3
+ class CheckboxView < ViewModel
4
+ include Headmin::Form::Hintable
5
+ include Headmin::Form::Labelable
6
+ include Headmin::Form::Validatable
7
+ include Headmin::Form::Wrappable
8
+
9
+ def checked_value
10
+ @checked_value || "1"
11
+ end
12
+
13
+ def unchecked_value
14
+ @unchecked_value || "0"
15
+ end
16
+
17
+ def input_options
18
+ keys = attributes - %i[attribute form label validate wrapper checked_value unchecked_value]
19
+ options = to_h.slice(*keys)
20
+ default_input_options.deep_merge(options)
21
+ end
22
+
23
+ def label_options
24
+ {
25
+ class: ["form-check-label"],
26
+ attribute: attribute,
27
+ form: form,
28
+ required: required,
29
+ text: label
30
+ }
31
+ end
32
+
33
+ def wrapper_options
34
+ default_wrapper_options.deep_merge(
35
+ {
36
+ class: %w[form-check mb-3]
37
+ }
38
+ ).deep_merge(@wrapper || {})
39
+ end
40
+
41
+ private
42
+
43
+ def default_input_options
44
+ {
45
+ aria: {describedby: validation_id},
46
+ class: ["form-check-input", validation_class],
47
+ placeholder: placeholder
48
+ }
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,25 @@
1
+ module Headmin
2
+ module Form
3
+ class DateRangeView < ViewModel
4
+ def start_options
5
+ default_start_options.deep_merge(@start || {})
6
+ end
7
+
8
+ def end_options
9
+ default_end_options.deep_merge(@end || {})
10
+ end
11
+
12
+ private
13
+
14
+ def default_start_options
15
+ keys = attributes - %i[start]
16
+ to_h.slice(*keys)
17
+ end
18
+
19
+ def default_end_options
20
+ keys = attributes - %i[end]
21
+ to_h.slice(*keys)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ module Headmin
2
+ module Form
3
+ class DateView < ViewModel
4
+ include Headmin::Form::Hintable
5
+ include Headmin::Form::InputGroupable
6
+ include Headmin::Form::Labelable
7
+ include Headmin::Form::Listable
8
+ include Headmin::Form::Placeholderable
9
+ include Headmin::Form::Validatable
10
+ include Headmin::Form::Wrappable
11
+
12
+ def input_options
13
+ keys = attributes - %i[append attribute float form input_group input_group label prepend validate wrapper]
14
+ options = to_h.slice(*keys)
15
+ default_input_options.deep_merge(options)
16
+ end
17
+
18
+ def input_group_options
19
+ default_input_group_options
20
+ .deep_merge(label_input_group_options)
21
+ .deep_merge(@input_group || {})
22
+ end
23
+
24
+ def wrapper_options
25
+ default_wrapper_options.deep_merge({
26
+ class: ["mb-3", ("form-floating" if float)]
27
+ }).deep_merge(@wrapper || {})
28
+ end
29
+
30
+ private
31
+
32
+ def default_input_options
33
+ {
34
+ aria: {describedby: validation_id},
35
+ class: [form_control_class, validation_class],
36
+ placeholder: placeholder
37
+ }
38
+ end
39
+
40
+ def form_control_class
41
+ plaintext ? "form-control-plaintext" : "form-control"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ module Headmin
2
+ module Form
3
+ class EmailView < ViewModel
4
+ include Headmin::Form::Autocompletable
5
+ include Headmin::Form::Hintable
6
+ include Headmin::Form::InputGroupable
7
+ include Headmin::Form::Labelable
8
+ include Headmin::Form::Listable
9
+ include Headmin::Form::Placeholderable
10
+ include Headmin::Form::Validatable
11
+ include Headmin::Form::Wrappable
12
+
13
+ def input_options
14
+ keys = attributes - %i[append attribute collection float form input_group label prepend validate wrapper]
15
+ options = to_h.slice(*keys)
16
+ options = default_input_options.deep_merge(options)
17
+ options.deep_merge(autocomplete_input_options)
18
+ end
19
+
20
+ def input_group_options
21
+ default_input_group_options
22
+ .deep_merge(autocomplete_input_group_options)
23
+ .deep_merge(label_input_group_options)
24
+ .deep_merge(@input_group || {})
25
+ end
26
+
27
+ def wrapper_options
28
+ default_wrapper_options.deep_merge({
29
+ class: ["mb-3", ("form-floating" if float)]
30
+ }).deep_merge(@wrapper || {})
31
+ end
32
+
33
+ private
34
+
35
+ def default_input_options
36
+ {
37
+ aria: {describedby: validation_id},
38
+ class: [form_control_class, validation_class],
39
+ placeholder: placeholder
40
+ }
41
+ end
42
+
43
+ def form_control_class
44
+ plaintext ? "form-control-plaintext" : "form-control"
45
+ end
46
+ end
47
+ end
48
+ end