super 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/super/application.js +5 -4
  3. data/app/helpers/super/form_builder_helper.rb +23 -0
  4. data/app/views/super/application/_filter.html.erb +2 -2
  5. data/app/views/super/application/_filter_type_select.html.erb +5 -18
  6. data/app/views/super/application/_filter_type_text.html.erb +4 -10
  7. data/app/views/super/application/_filter_type_timestamp.html.erb +4 -16
  8. data/app/views/super/application/_form_field__destroy.html.erb +1 -9
  9. data/app/views/super/application/_form_field_checkbox.html.erb +1 -15
  10. data/app/views/super/application/_form_field_rich_text_area.html.erb +1 -13
  11. data/app/views/super/application/_form_field_select.html.erb +1 -23
  12. data/app/views/super/application/_form_field_text.html.erb +1 -13
  13. data/app/views/super/application/_super_schema_display_index.html.erb +2 -2
  14. data/app/views/super/application/_super_schema_form.html.erb +2 -2
  15. data/app/views/super/application/edit.html.erb +1 -0
  16. data/app/views/super/application/index.html.erb +1 -0
  17. data/app/views/super/application/new.html.erb +1 -0
  18. data/app/views/super/application/show.html.erb +1 -0
  19. data/frontend/super-frontend/dist/application.js +5 -4
  20. data/lib/super.rb +1 -0
  21. data/lib/super/engine.rb +2 -0
  22. data/lib/super/error.rb +9 -0
  23. data/lib/super/form/builder.rb +194 -38
  24. data/lib/super/form/inline_errors.rb +26 -0
  25. data/lib/super/version.rb +1 -1
  26. data/lib/super/view_helper.rb +0 -19
  27. metadata +10 -19
  28. data/app/views/super/application/_form_field_generic.html.erb +0 -19
  29. data/app/views/super/application/_form_inline_errors.html.erb +0 -10
  30. data/frontend/super-frontend/build.js +0 -36
  31. data/frontend/super-frontend/package.json +0 -20
  32. data/frontend/super-frontend/postcss.config.js +0 -6
  33. data/frontend/super-frontend/src/javascripts/super/application.js +0 -15
  34. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.js +0 -17
  35. data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.js +0 -15
  36. data/frontend/super-frontend/src/stylesheets/super/application.css +0 -77
  37. data/frontend/super-frontend/tailwind.config.js +0 -15
  38. data/frontend/super-frontend/yarn.lock +0 -5443
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b01ea90f28d8e14b5a5f4bd454e2a15676b9c95623200a17d1a2ed2fb71d87f
4
- data.tar.gz: 753365f90dcc880f4249ab60d9eea04034189fd221ecb03d500a8fc78f02a7a9
3
+ metadata.gz: 043677dcee80c7b83903b21904f1768a411f807567190d7227928df9bf7922c7
4
+ data.tar.gz: 5de2f073926089e4823a4228dc4f7be912fed0471d862f9b6f0f56dde280f154
5
5
  SHA512:
6
- metadata.gz: ec08f45761eefc5645daa6f4976b9b3844fba97c04b81ddbee3217dfd6392666c30eabb7e7a2eca0516f2dad861b4f8a5f85ac8ac36ed583baa6dcb38d7fb4f2
7
- data.tar.gz: ed215af314d49cc4454ba98cb8fd84d351ca32808de1eceaa4c079b2199f18bfbd6ebfc1aa8d388738012868b764482741d933e1e232ac1cf30bf02f3effe26f
6
+ metadata.gz: feeba0baacdaf977c16f9e785e7abf6637679ebe2f624716f1006cce290157e29157b046a01f3d287d1b826378a04ece8c482b59cd2f21dc53bf463a28cf2848
7
+ data.tar.gz: a7d1a568a4c918ececb0200305f1e30042b4fc48946796f13e9568c27b5f95368b60aaac51ac977211566cb79f4973dd3d96a48a421531934c41884ce33ac084
@@ -4303,8 +4303,6 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
4303
4303
 
4304
4304
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
4305
4305
 
4306
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4307
-
4308
4306
  var _default = /*#__PURE__*/function (_Controller) {
4309
4307
  _inherits(_default, _Controller);
4310
4308
 
@@ -4324,14 +4322,17 @@ var _default = /*#__PURE__*/function (_Controller) {
4324
4322
  var content = this.templateTarget.innerHTML.replace(/TEMPLATEINDEX/g, unixtime.toString());
4325
4323
  this.templateTarget.insertAdjacentHTML("beforebegin", content);
4326
4324
  }
4325
+ }], [{
4326
+ key: "targets",
4327
+ get: function get() {
4328
+ return ["template"];
4329
+ }
4327
4330
  }]);
4328
4331
 
4329
4332
  return _default;
4330
4333
  }(_stimulus.Controller);
4331
4334
 
4332
4335
  exports.default = _default;
4333
-
4334
- _defineProperty(_default, "targets", ["template"]);
4335
4336
  },{"stimulus":"../node_modules/stimulus/index.js"}],"javascripts/super/toggle_pending_destruction_controller.js":[function(require,module,exports) {
4336
4337
  "use strict";
4337
4338
 
@@ -0,0 +1,23 @@
1
+ module Super
2
+ module FormBuilderHelper
3
+ def super_form_for(record, options = {}, &block)
4
+ original = ActionView::Base.field_error_proc
5
+ ActionView::Base.field_error_proc = Form::Builder::FIELD_ERROR_PROC
6
+
7
+ options[:builder] ||= Form::Builder
8
+ return form_for(record, options, &block)
9
+ ensure
10
+ ActionView::Base.field_error_proc = original
11
+ end
12
+
13
+ def super_form_with(**options, &block)
14
+ original = ActionView::Base.field_error_proc
15
+ ActionView::Base.field_error_proc = Form::Builder::FIELD_ERROR_PROC
16
+
17
+ options[:builder] ||= Form::Builder
18
+ return form_with(**options, &block)
19
+ ensure
20
+ ActionView::Base.field_error_proc = original
21
+ end
22
+ end
23
+ end
@@ -1,6 +1,6 @@
1
1
  <%= render(Super::Panel.new) do %>
2
2
  <h1 class="text-xl">Filters</h1>
3
- <%= form_for(filter, url: filter.url, method: :get, as: :q, html: { class: "mt-4" }) do |form| %>
3
+ <%= super_form_for(filter, url: filter.url, method: :get, as: :q, html: { class: "mt-4" }) do |form| %>
4
4
  <% filter.each_field do |filter_field| %>
5
5
  <div class="mt-4">
6
6
  <%= render(filter_field, form: form) %>
@@ -8,7 +8,7 @@
8
8
  <% end %>
9
9
 
10
10
  <div>
11
- <%= form.submit "Filter", class: "super-button super-button--border-gray mt-6" %>
11
+ <%= form.super.submit "Filter", class: "super-button--border-gray mt-6" %>
12
12
  </div>
13
13
  <% end %>
14
14
  <% end %>
@@ -1,31 +1,18 @@
1
1
  <div class="super-field-group">
2
2
  <%= form.fields_for(filter_type_select.field_name, filter_type_select) do |form_field| %>
3
3
  <%= form_field.label(:q, filter_type_select.humanized_field_name) %>
4
- <div class="super-input-select inline-block">
5
- <%= form_field.select(
4
+ <div class="relative inline-block">
5
+ <%= form_field.super.select(
6
6
  :op,
7
7
  filter_type_select.operators,
8
- {},
9
- { class: "super-input super-input-select-field" }
8
+ { include_blank: false },
10
9
  ) %>
11
- <div class="super-input-select-icon text-gray-700">
12
- <span class="h-4 w-4">
13
- <%= render "super/feather/chevron_down" %>
14
- </span>
15
- </div>
16
10
  </div>
17
- <div class="super-input-select mt-3">
18
- <%= form_field.select(
11
+ <div class="mt-3">
12
+ <%= form_field.super.select(
19
13
  :q,
20
14
  filter_type_select.field_type.collection,
21
- { include_blank: true },
22
- { class: "super-input super-input-select-field" }
23
15
  ) %>
24
- <div class="super-input-select-icon text-gray-700">
25
- <span class="h-4 w-4">
26
- <%= render "super/feather/chevron_down" %>
27
- </span>
28
- </div>
29
16
  </div>
30
17
  <% end %>
31
18
  </div>
@@ -2,21 +2,15 @@
2
2
  <%= form.fields_for(filter_type_text.field_name, filter_type_text) do |form_field| %>
3
3
  <%= form_field.label(:q, filter_type_text.humanized_field_name) %>
4
4
  <div class="relative inline-block">
5
- <%= form_field.select(
5
+ <%= form_field.super.select(
6
6
  :op,
7
7
  filter_type_text.operators,
8
- {},
9
- { class: "super-input super-input-select-field" }
8
+ { include_blank: false }
10
9
  ) %>
11
- <div class="super-input-select-icon text-gray-700">
12
- <span class="h-4 w-4">
13
- <%= render "super/feather/chevron_down" %>
14
- </span>
15
- </div>
16
10
  </div>
17
- <%= form_field.text_field(
11
+ <%= form_field.super.text_field(
18
12
  :q,
19
- class: "super-input w-full mt-3"
13
+ class: "mt-3"
20
14
  ) %>
21
15
  <% end %>
22
16
  </div>
@@ -2,33 +2,21 @@
2
2
  <%= form.fields_for(filter_type_timestamp.field_name, filter_type_timestamp) do |form_field| %>
3
3
  <%= form_field.label(:q0, filter_type_timestamp.humanized_field_name) %>
4
4
  <div class="relative inline-block mt-2">
5
- <%= form_field.select(
5
+ <%= form_field.super.select(
6
6
  :op,
7
7
  filter_type_timestamp.operators,
8
- {},
9
- { class: "super-input super-input-select-field" }
8
+ { include_blank: false}
10
9
  ) %>
11
- <div class="super-input-select-icon text-gray-700">
12
- <span class="h-4 w-4">
13
- <%= render "super/feather/chevron_down" %>
14
- </span>
15
- </div>
16
10
  </div>
17
11
  <div class="flex items-center mt-3">
18
12
  <div class="flex-initial">
19
- <%= form_field.text_field(
20
- :q0,
21
- class: "super-input w-full"
22
- ) %>
13
+ <%= form_field.super.text_field(:q0) %>
23
14
  </div>
24
15
  <div class="flex-initial px-2">
25
16
  &ndash;
26
17
  </div>
27
18
  <div class="flex-initial">
28
- <%= form_field.text_field(
29
- :q1,
30
- class: "super-input w-full"
31
- ) %>
19
+ <%= form_field.super.text_field(:q1) %>
32
20
  </div>
33
21
  </div>
34
22
  <% end %>
@@ -1,9 +1 @@
1
- <% if !local_assigns[:ungrouped] %>
2
- <div class="super-field-group">
3
- <% end %>
4
- <%= form.check_box(column, data: { action: "toggle-pending-destruction#call" }) %>
5
- <%= form.label(column) %>
6
- <%= render "form_inline_errors", form: form, column: column %>
7
- <% if !local_assigns[:ungrouped] %>
8
- </div>
9
- <% end %>
1
+ <%= form.super.check_box!(column, field: { data: { action: "toggle-pending-destruction#call" } }) %>
@@ -1,15 +1 @@
1
- <% if !local_assigns[:ungrouped] %>
2
- <div class="super-field-group">
3
- <% end %>
4
- <div class="<%= Super::ViewHelper.classes(["mt-1", !local_assigns[:hide_label]]) %>">
5
- <div>
6
- <%= form.check_box(column) %>
7
- <% if !local_assigns[:hide_label] %>
8
- <%= form.label(column, class: "select-none") %>
9
- <% end %>
10
- </div>
11
- <%= render "form_inline_errors", form: form, column: column %>
12
- </div>
13
- <% if !local_assigns[:ungrouped] %>
14
- </div>
15
- <% end %>
1
+ <%= form.super.check_box!(column) %>
@@ -1,13 +1 @@
1
- <% if !local_assigns[:ungrouped] %>
2
- <div class="super-field-group">
3
- <% end %>
4
- <% if !local_assigns[:hide_label] %>
5
- <%= form.label(column, class: "block") %>
6
- <% end %>
7
- <div class="<%= Super::ViewHelper.classes(["mt-1", !local_assigns[:hide_label]]) %>">
8
- <%= form.rich_text_area(column, class: "trix-content super-input w-full") %>
9
- <%= render "form_inline_errors", form: form, column: column %>
10
- </div>
11
- <% if !local_assigns[:ungrouped] %>
12
- </div>
13
- <% end %>
1
+ <%= form.super.rich_text_area!(column) %>
@@ -1,23 +1 @@
1
- <% if !local_assigns[:ungrouped] %>
2
- <div class="super-field-group">
3
- <% end %>
4
- <% if !local_assigns[:hide_label] %>
5
- <%= form.label(column, class: "block") %>
6
- <% end %>
7
- <div class="<%= Super::ViewHelper.classes("super-input-select", ["mt-1", !local_assigns[:hide_label]]) %>">
8
- <%= form.select(
9
- column,
10
- form_field_select[:collection],
11
- { include_blank: true }.merge(form_field_select[:options] || {}),
12
- { class: "super-input super-input-select-field" }
13
- ) %>
14
- <div class="super-input-select-icon text-gray-700">
15
- <span class="h-4 w-4">
16
- <%= render "super/feather/chevron_down" %>
17
- </span>
18
- </div>
19
- </div>
20
- <%= render "form_inline_errors", form: form, column: column %>
21
- <% if !local_assigns[:ungrouped] %>
22
- </div>
23
- <% end %>
1
+ <%= form.super.select!(column, form_field_select[:collection]) %>
@@ -1,13 +1 @@
1
- <% if !local_assigns[:ungrouped] %>
2
- <div class="super-field-group">
3
- <% end %>
4
- <% if !local_assigns[:hide_label] %>
5
- <%= form.label(column, class: "block") %>
6
- <% end %>
7
- <div class="<%= Super::ViewHelper.classes(["mt-1", !local_assigns[:hide_label]]) %>">
8
- <%= form.text_field(column, class: "super-input w-full") %>
9
- <%= render "form_inline_errors", form: form, column: column %>
10
- </div>
11
- <% if !local_assigns[:ungrouped] %>
12
- </div>
13
- <% end %>
1
+ <%= form.super.text_field!(column) %>
@@ -1,9 +1,9 @@
1
- <div class="mt-4 overflow-x-auto lg:overflow-x-visible">
1
+ <div class="mt-4 overflow-x-auto">
2
2
  <table class="w-full border-separate relative" cellspacing="0" cellpadding="0">
3
3
  <thead class="">
4
4
  <tr class="">
5
5
  <% super_schema_display_index.each_attribute_name do |attribute_name| %>
6
- <th class="p-2 first:pl-6 border-b border-b-2 border-gray-400 text-gray-600 text-left text-sm font-normal bg-white sticky top-0 z-10">
6
+ <th class="p-2 first:pl-6 border-b border-b-2 border-gray-400 text-gray-600 text-left text-sm font-normal bg-white top-0 z-10">
7
7
  <%= controls.model.human_attribute_name(attribute_name) %>
8
8
  </th>
9
9
  <% end %>
@@ -1,4 +1,4 @@
1
- <%= form_for(Super.configuration.path_parts(@record), builder: Super::Form::Builder) do |f| %>
1
+ <%= super_form_for(Super.configuration.path_parts(@record), builder: Super::Form::Builder) do |f| %>
2
2
  <div class="max-w-3xl">
3
3
  <% super_schema_form.each_attribute do |field, type| %>
4
4
  <%= render(
@@ -9,7 +9,7 @@
9
9
  <% end %>
10
10
 
11
11
  <div>
12
- <%= f.submit class: "super-button super-button--fill-blue mt-2" %>
12
+ <%= f.super.submit class: "super-button--fill-blue mt-2" %>
13
13
  </div>
14
14
  </div>
15
15
  <% end %>
@@ -1 +1,2 @@
1
+ <% raise Super::Error::NothingToRender, "edit" if @view.nil? %>
1
2
  <%= render(@view) %>
@@ -1 +1,2 @@
1
+ <% raise Super::Error::NothingToRender, "index" if @view.nil? %>
1
2
  <%= render(@view) %>
@@ -1 +1,2 @@
1
+ <% raise Super::Error::NothingToRender, "new" if @view.nil? %>
1
2
  <%= render(@view) %>
@@ -1 +1,2 @@
1
+ <% raise Super::Error::NothingToRender, "show" if @view.nil? %>
1
2
  <%= render(@view) %>
@@ -4303,8 +4303,6 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
4303
4303
 
4304
4304
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
4305
4305
 
4306
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4307
-
4308
4306
  var _default = /*#__PURE__*/function (_Controller) {
4309
4307
  _inherits(_default, _Controller);
4310
4308
 
@@ -4324,14 +4322,17 @@ var _default = /*#__PURE__*/function (_Controller) {
4324
4322
  var content = this.templateTarget.innerHTML.replace(/TEMPLATEINDEX/g, unixtime.toString());
4325
4323
  this.templateTarget.insertAdjacentHTML("beforebegin", content);
4326
4324
  }
4325
+ }], [{
4326
+ key: "targets",
4327
+ get: function get() {
4328
+ return ["template"];
4329
+ }
4327
4330
  }]);
4328
4331
 
4329
4332
  return _default;
4330
4333
  }(_stimulus.Controller);
4331
4334
 
4332
4335
  exports.default = _default;
4333
-
4334
- _defineProperty(_default, "targets", ["template"]);
4335
4336
  },{"stimulus":"../node_modules/stimulus/index.js"}],"javascripts/super/toggle_pending_destruction_controller.js":[function(require,module,exports) {
4336
4337
  "use strict";
4337
4338
 
@@ -23,6 +23,7 @@ require "super/filter/schema_types"
23
23
  require "super/form"
24
24
  require "super/form/builder"
25
25
  require "super/form/guesser"
26
+ require "super/form/inline_errors"
26
27
  require "super/form/schema_types"
27
28
  require "super/form/strong_params"
28
29
  require "super/layout"
@@ -1,6 +1,8 @@
1
1
  module Super
2
2
  # Configures the host Rails app to work with Super
3
3
  class Engine < ::Rails::Engine
4
+ isolate_namespace Super
5
+
4
6
  initializer "super.assets.precompile" do |app|
5
7
  if Super::Assets::Handler.sprockets_available?
6
8
  app.config.assets.precompile << "config/super_manifest.js"
@@ -13,5 +13,14 @@ module Super
13
13
  class ActionInquirerError < Error; end
14
14
  # Error raised when a `Super::Link` couldn't be found
15
15
  class LinkNotRegistered < Error; end
16
+ # Error raised when rendering if `@view` wasn't set by the controller
17
+ class NothingToRender < Error
18
+ def initialize(basename)
19
+ super(
20
+ "Super's built-in `#{basename}.html.erb` requires `@view` to be set " \
21
+ "by the controller, but it wasn't set"
22
+ )
23
+ end
24
+ end
16
25
  end
17
26
  end
@@ -1,48 +1,204 @@
1
1
  module Super
2
2
  class Form
3
- module FieldErrorProc
4
- def error_wrapping(html_tag)
5
- if Thread.current[:super_form_builder]
6
- return html_tag
7
- end
3
+ # Example
4
+ #
5
+ # ```ruby
6
+ # super_form_for([:admin, @member]) do |f|
7
+ # # the long way
8
+ # f.super.label :name
9
+ # f.super.text_field :name
10
+ # f.super.inline_errors :name
11
+ #
12
+ # # the short way (slightly different from the long way, for alignment)
13
+ # f.super.text_field! :position
14
+ # end
15
+ # ```
16
+ #
17
+ # Refer to the Rails docs:
18
+ # https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html
19
+ class Builder < ActionView::Helpers::FormBuilder
20
+ FIELD_ERROR_PROC = proc { |html_tag, instance| html_tag }
21
+ FORM_BUILDER_DEFAULTS = { builder: self }.freeze
8
22
 
9
- super
23
+ def super(**options)
24
+ @super_wrappers ||= Wrappers.new(self, @template)
10
25
  end
11
- end
12
26
 
13
- class Builder < ActionView::Helpers::FormBuilder
14
- # These methods were originally defined in the following files
15
- #
16
- # * actionview/lib/action_view/helpers/form_helper.rb
17
- # * actionview/lib/action_view/helpers/form_options_helper.rb
18
- # * actionview/lib/action_view/helpers/date_helper.rb
19
- %w[
20
- label text_field password_field hidden_field file_field text_area
21
- check_box radio_button color_field search_field telephone_field
22
- date_field time_field datetime_field month_field week_field url_field
23
- email_field number_field range_field
24
-
25
- select collection_select grouped_collection_select time_zone_select
26
- collection_radio_buttons collection_check_boxes
27
-
28
- time_select datetime_select date_select
29
- ].each do |field_type_method|
30
- class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
31
- def #{field_type_method}(*)
32
- Thread.current[:super_form_builder] = true
33
- super
34
- ensure
35
- Thread.current[:super_form_builder] = nil
27
+ class Wrappers
28
+ def initialize(builder, template)
29
+ @builder = builder
30
+ @template = template
31
+ end
32
+
33
+ def inline_errors(attribute)
34
+ if @builder.object
35
+ messages = InlineErrors.error_messages(@builder.object, attribute).map do |msg|
36
+ error_content_tag(msg)
37
+ end
38
+
39
+ @template.safe_join(messages)
40
+ else
41
+ error_content_tag(<<~MSG.html_safe)
42
+ This form doesn't have an object, so something is probably wrong.
43
+ Maybe <code>accepts_nested_attributes_for</code> isn't set up?
44
+ MSG
36
45
  end
37
- RUBY
38
- end
46
+ end
47
+
48
+ def label(attribute, text = nil, options = {}, &block)
49
+ options, defaults = split_defaults(options, class: "block")
50
+ options[:class] = join_classes(defaults[:class], options[:class])
51
+
52
+ @builder.label(attribute, text, options, &block)
53
+ end
54
+
55
+ def check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0")
56
+ @builder.check_box(attribute, options, checked_value, unchecked_value)
57
+ end
58
+
59
+ def password_field(attribute, options = {})
60
+ options, defaults = split_defaults(options, class: "super-input w-full")
61
+ options[:class] = join_classes(defaults[:class], options[:class])
62
+
63
+ @builder.password_field(attribute, options)
64
+ end
65
+
66
+ def rich_text_area(attribute, options = {})
67
+ options, defaults = split_defaults(options, class: "trix-content super-input w-full")
68
+ options[:class] = join_classes(defaults[:class], options[:class])
69
+
70
+ @builder.rich_text_area(attribute, options)
71
+ end
72
+
73
+ def select(attribute, choices, options = {}, html_options = {}, &block)
74
+ options, defaults = split_defaults(options, include_blank: true)
75
+ options = defaults.merge(options)
76
+ html_options, html_defaults = split_defaults(html_options, class: "super-input super-input-select-field")
77
+ html_options[:class] = join_classes(html_defaults[:class], html_options[:class])
78
+
79
+ parts = [
80
+ %(<div class="super-input-select">).html_safe,
81
+ @builder.select(attribute, choices, options, html_options, &block),
82
+ <<~HTML.html_safe,
83
+ <div class="super-input-select-icon text-blue-700">
84
+ <span class="h-4 w-4">
85
+ HTML
86
+ @template.render("super/feather/chevron_down"),
87
+ <<~HTML.html_safe,
88
+ </span>
89
+ </div>
90
+ HTML
91
+ %(</div>).html_safe,
92
+ ]
93
+
94
+ @template.safe_join(parts)
95
+ end
96
+
97
+ def submit(value = nil, options = {})
98
+ value, options = nil, value if value.is_a?(Hash)
99
+ options, defaults = split_defaults(options, class: "super-button")
100
+ options[:class] = join_classes(defaults[:class], options[:class])
101
+
102
+ @builder.submit(value, options)
103
+ end
104
+
105
+ def text_field(attribute, options = {})
106
+ options, defaults = split_defaults(options, class: "super-input w-full")
107
+ options[:class] = join_classes(defaults[:class], options[:class])
108
+
109
+ @builder.text_field(attribute, options)
110
+ end
39
111
 
40
- alias datetime_local_field datetime_field
41
- alias phone_field telephone_field
112
+ def container(&block)
113
+ @template.content_tag(:div, class: "super-field-group", &block)
114
+ end
115
+
116
+ def check_box!(attribute, checked_value = "1", unchecked_value = "0", label: {}, field: {}, show_errors: true)
117
+ label[:super] ||= {}
118
+ label[:super] = { class: "select-none ml-1" }.merge(label[:super])
119
+ container do
120
+ compact_join([
121
+ "<div>".html_safe,
122
+ public_send(:check_box, attribute, field, checked_value, unchecked_value),
123
+ public_send(:label, attribute, nil, label),
124
+ "</div>".html_safe,
125
+ show_errors && inline_errors(attribute),
126
+ ])
127
+ end
128
+ end
129
+
130
+ def password_field!(attribute, label: {}, field: {}, show_errors: true)
131
+ container do
132
+ compact_join([
133
+ public_send(:label, attribute, label),
134
+ %(<div class="mt-1">).html_safe,
135
+ public_send(:password_field, attribute, field),
136
+ show_errors && inline_errors(attribute),
137
+ %(</div>).html_safe,
138
+ ])
139
+ end
140
+ end
141
+
142
+ def rich_text_area!(attribute, label: {}, field: {}, show_errors: true)
143
+ container do
144
+ compact_join([
145
+ public_send(:label, attribute, label),
146
+ %(<div class="mt-1">).html_safe,
147
+ public_send(:rich_text_area, attribute, field),
148
+ show_errors && inline_errors(attribute),
149
+ %(</div>).html_safe,
150
+ ])
151
+ end
152
+ end
153
+
154
+ def select!(attribute, collection, label: {}, field: {}, show_errors: true)
155
+ container do
156
+ compact_join([
157
+ public_send(:label, attribute, label),
158
+ %(<div class="mt-1">).html_safe,
159
+ public_send(:select, attribute, collection, field),
160
+ show_errors && inline_errors(attribute),
161
+ %(</div>).html_safe,
162
+ ])
163
+ end
164
+ end
165
+
166
+ def text_field!(attribute, label: {}, field: {}, show_errors: true)
167
+ container do
168
+ compact_join([
169
+ public_send(:label, attribute, label),
170
+ %(<div class="mt-1">).html_safe,
171
+ public_send(:text_field, attribute, field),
172
+ show_errors && inline_errors(attribute),
173
+ %(</div>).html_safe,
174
+ ])
175
+ end
176
+ end
177
+
178
+ private
179
+
180
+ def split_defaults(options, **internal_defaults)
181
+ defaults = options.delete(:super) || {}
182
+ # prefer options set in `defaults`, since they are user overrides
183
+ defaults = internal_defaults.merge(defaults)
184
+
185
+ [options, defaults]
186
+ end
187
+
188
+ def join_classes(*class_lists)
189
+ class_lists.flatten.map(&:presence).compact
190
+ end
191
+
192
+ def error_content_tag(content)
193
+ @template.content_tag(:p, content, class: "text-red-400 text-xs italic pt-1")
194
+ end
195
+
196
+ def compact_join(*parts)
197
+ @template.safe_join(
198
+ parts.flatten.map(&:presence).compact
199
+ )
200
+ end
201
+ end
42
202
  end
43
203
  end
44
204
  end
45
-
46
- ActionView::Helpers::Tags::Base.class_eval do
47
- prepend Super::Form::FieldErrorProc
48
- end