fluxbit_view_components 0.2.0 → 0.3.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/app/components/fluxbit/form/check_box_component.rb +56 -0
- data/app/components/fluxbit/form/component.rb +18 -24
- data/app/components/fluxbit/form/dropzone_component.html.erb +39 -0
- data/app/components/fluxbit/form/dropzone_component.rb +39 -0
- data/app/components/fluxbit/form/field_component.rb +26 -0
- data/app/components/fluxbit/form/form_builder_component.rb +1 -1
- data/app/components/fluxbit/form/{helper_text_component.rb → help_text_component.rb} +8 -3
- data/app/components/fluxbit/form/label_component.rb +32 -29
- data/app/components/fluxbit/form/range_component.rb +52 -0
- data/app/components/fluxbit/form/select_component.rb +88 -0
- data/app/components/fluxbit/form/text_field_component.rb +168 -0
- data/app/components/fluxbit/form/toggle_component.html.erb +23 -0
- data/app/components/fluxbit/form/toggle_component.rb +81 -0
- data/app/components/fluxbit/form/upload_image_component.html.erb +50 -0
- data/app/components/fluxbit/form/upload_image_component.rb +50 -0
- data/app/helpers/fluxbit/components_helper.rb +23 -51
- data/app/helpers/fluxbit/form_builder.rb +87 -0
- data/lib/fluxbit/config/form/check_box_component.rb +19 -0
- data/lib/fluxbit/config/form/dropzone_component.rb +20 -0
- data/lib/fluxbit/config/form/{helper_text_component.rb → help_text_component.rb} +1 -1
- data/lib/fluxbit/config/form/label_component.rb +30 -0
- data/lib/fluxbit/config/form/range_component.rb +15 -0
- data/lib/fluxbit/config/form/text_field_component.rb +76 -0
- data/{app/components/fluxbit/form/toggle_input_component.rb → lib/fluxbit/config/form/toggle_component.rb} +28 -115
- data/lib/fluxbit/view_components/version.rb +1 -1
- data/lib/fluxbit/view_components.rb +7 -1
- data/lib/install/install.rb +3 -3
- metadata +21 -18
- data/LICENSE.txt +0 -20
- data/app/components/fluxbit/form/checkbox_input_component.rb +0 -61
- data/app/components/fluxbit/form/datepicker_component.rb +0 -7
- data/app/components/fluxbit/form/radio_input_component.rb +0 -21
- data/app/components/fluxbit/form/range_input_component.rb +0 -51
- data/app/components/fluxbit/form/select_free_input_component.rb +0 -77
- data/app/components/fluxbit/form/select_input_component.rb +0 -21
- data/app/components/fluxbit/form/spacer_input_component.rb +0 -12
- data/app/components/fluxbit/form/text_input_component.rb +0 -225
- data/app/components/fluxbit/form/textarea_input_component.rb +0 -57
- data/app/components/fluxbit/form/upload_image_input_component.html.erb +0 -48
- data/app/components/fluxbit/form/upload_image_input_component.rb +0 -61
- data/app/components/fluxbit/form/upload_input_component.html.erb +0 -12
- data/app/components/fluxbit/form/upload_input_component.rb +0 -47
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= content_tag :div, **@wrapper_html do %>
|
2
|
+
<label class="<%= label_class %>">
|
3
|
+
<%= if @invert_label
|
4
|
+
label
|
5
|
+
else
|
6
|
+
@other_label || (other_label if other_label?)
|
7
|
+
end %>
|
8
|
+
|
9
|
+
<% if @form.present? && @attribute.present? %>
|
10
|
+
<%= @form.check_box(@attribute, **@props) %>
|
11
|
+
<% else %>
|
12
|
+
<%= check_box_tag(@name, **@props) %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<span class="<%= toggle_class %>"></span>
|
16
|
+
<%= if @invert_label
|
17
|
+
@other_label || (other_label if other_label?)
|
18
|
+
else
|
19
|
+
label
|
20
|
+
end %>
|
21
|
+
</label>
|
22
|
+
<%= help_text %>
|
23
|
+
<% end %>
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
# The `Fluxbit::Form::ToggleComponent` renders a styled switch/toggle (on/off) input.
|
5
|
+
# It supports custom label placement, color and sizing options, helper text, and is fully compatible
|
6
|
+
# with Rails form builders. Additional options allow you to invert label order, customize colors
|
7
|
+
# for checked/unchecked/button states, and provide an extra label via a slot.
|
8
|
+
#
|
9
|
+
# @example Basic usage
|
10
|
+
# = render Fluxbit::Form::ToggleComponent.new(name: :enabled, label: "Enabled?")
|
11
|
+
#
|
12
|
+
# @see docs/03_Forms/Toggle.md For detailed documentation and examples.
|
13
|
+
class Fluxbit::Form::ToggleComponent < Fluxbit::Form::FieldComponent
|
14
|
+
include Fluxbit::Config::Form::ToggleComponent
|
15
|
+
|
16
|
+
renders_one :other_label, "Fluxbit::Form::LabelComponent"
|
17
|
+
|
18
|
+
# Initializes the toggle component with the given properties.
|
19
|
+
#
|
20
|
+
# @param form [ActionView::Helpers::FormBuilder] The form builder (optional, for Rails forms)
|
21
|
+
# @param attribute [Symbol] The model attribute to be used in the form (required if using form builder)
|
22
|
+
# @param id [String] The id of the input element (optional)
|
23
|
+
# @param label [String] The label for the input field (optional)
|
24
|
+
# @param help_text [String] Additional help text for the input field (optional)
|
25
|
+
# @param helper_popover [String] Content for a popover helper (optional)
|
26
|
+
# @param helper_popover_placement [String] Placement of the popover (default: "right")
|
27
|
+
# @param name [String] Name of the field (required unless using form builder)
|
28
|
+
# @param other_label [String] Additional label, rendered via slot (optional)
|
29
|
+
# @param sizing [Integer] Size index for the toggle (default: config)
|
30
|
+
# @param color [Symbol] Checked toggle color (:default, :success, :failure, :info, :warning, etc)
|
31
|
+
# @param unchecked_color [Symbol] Unchecked toggle color (see config)
|
32
|
+
# @param button_color [Symbol] Color for the toggle button
|
33
|
+
# @param invert_label [Boolean] If true, inverts label/toggle order (default: config)
|
34
|
+
# @param disabled [Boolean] Disables the toggle if true
|
35
|
+
# @param class [String] Additional CSS classes for the input element
|
36
|
+
# @param ... any other HTML attribute supported by <input type="checkbox">
|
37
|
+
def initialize(**props)
|
38
|
+
super(**props)
|
39
|
+
|
40
|
+
@other_label = props.delete(:other_label)
|
41
|
+
@sizing = @props.delete(:sizing) || @@sizing
|
42
|
+
@sizing = (styles[:toggle][:sizes].count - 1) if @sizing > (styles[:toggle][:sizes].count - 1)
|
43
|
+
@color = valid_color(@props.delete(:color))
|
44
|
+
@unchecked_color = options(
|
45
|
+
@props.delete(:unchecked_color),
|
46
|
+
collection: styles[:toggle][:unchecked].keys,
|
47
|
+
default: @@unchecked_color
|
48
|
+
)
|
49
|
+
@button_color = options(@props.delete(:button_color), collection: styles[:toggle][:button].keys, default: @@button_color)
|
50
|
+
@invert_label = options(@props.delete(:invert_label), collection: [ true, false ], default: @@invert_label)
|
51
|
+
|
52
|
+
add to: @props, first_element: true, class: styles[:input]
|
53
|
+
end
|
54
|
+
|
55
|
+
def valid_color(color)
|
56
|
+
return color if styles[:toggle][:checked].key?(color)
|
57
|
+
return :failure if errors.present?
|
58
|
+
|
59
|
+
@@color
|
60
|
+
end
|
61
|
+
|
62
|
+
def label_class
|
63
|
+
styles[:label]
|
64
|
+
end
|
65
|
+
|
66
|
+
def input_class
|
67
|
+
styles[:input]
|
68
|
+
end
|
69
|
+
|
70
|
+
def toggle_class
|
71
|
+
[
|
72
|
+
(@invert_label || @other_label || other_label?) ? styles[:toggle][:invert_label] : nil,
|
73
|
+
styles[:toggle][:base],
|
74
|
+
styles[:toggle][:unchecked][@unchecked_color],
|
75
|
+
styles[:toggle][:checked][@color],
|
76
|
+
styles[:toggle][:button][@button_color],
|
77
|
+
styles[:toggle][:sizes][@sizing],
|
78
|
+
styles[:toggle][:active][(@props[:disabled] ? :off : :on)]
|
79
|
+
].compact.join(" ")
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<%= content_tag :div, **@wrapper_html do %>
|
2
|
+
<div id="<%= id %>" class="mt-6 grow lg:mt-0 lg:ml-6 lg:shrink-0 lg:grow-0">
|
3
|
+
<%= label %>
|
4
|
+
<div class="mt-1 lg:hidden">
|
5
|
+
<div class="flex items-center">
|
6
|
+
<div class="inline-block h-12 w-12 shrink-0 overflow-hidden rounded-full relative" aria-hidden="true">
|
7
|
+
<%= image_element %>
|
8
|
+
</div>
|
9
|
+
<div class="ml-5 rounded-md shadow-xs">
|
10
|
+
<div class="group relative flex items-center justify-center rounded-md border border-slate-300 py-2 px-3 focus-within:ring-2 focus-within:ring-sky-500 focus-within:ring-offset-2 hover:bg-slate-50">
|
11
|
+
<label for="mobile-<%= id %>" class="pointer-events-none relative text-sm font-medium leading-4 text-slate-700">
|
12
|
+
<span><%= @title %></span>
|
13
|
+
<span class="sr-only"><%= @label %></span>
|
14
|
+
</label>
|
15
|
+
<%= input_element(input_id: "mobile-#{id}") %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="relative hidden overflow-hidden rounded-full lg:block w-40">
|
22
|
+
<div class="inline-block h-40 w-40 shrink-0 overflow-hidden rounded-full relative" aria-hidden="true">
|
23
|
+
<%= image_element %>
|
24
|
+
</div>
|
25
|
+
<label for="desktop-<%= id %>" class="absolute inset-0 flex flex-col h-full w-full items-center justify-center bg-blue-800/75 text-sm font-medium text-white opacity-0 hover:opacity-100">
|
26
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-white mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
27
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
|
28
|
+
</svg>
|
29
|
+
<span><%= @title %></span>
|
30
|
+
<span class="sr-only"><%= @label %></span>
|
31
|
+
<%= input_element(input_id: "desktop-#{id}") %>
|
32
|
+
</label>
|
33
|
+
</div>
|
34
|
+
<%= help_text %>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
<script>
|
38
|
+
function loadFile(event, id) {
|
39
|
+
const images = document.querySelectorAll('.img_photo_' + id);
|
40
|
+
if (event.target.files && event.target.files[0]) {
|
41
|
+
images.forEach(function(img) {
|
42
|
+
img.src = URL.createObjectURL(event.target.files[0]);
|
43
|
+
img.onload = function() {
|
44
|
+
URL.revokeObjectURL(img.src);
|
45
|
+
}
|
46
|
+
});
|
47
|
+
}
|
48
|
+
}
|
49
|
+
</script>
|
50
|
+
<% end %>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The `Fluxbit::Form::UploadImageComponent` renders a stylized image upload field with live preview,
|
4
|
+
# drag-and-drop UI, support for both mobile and desktop layouts, labels, helper text, and integration
|
5
|
+
# with Rails form builders and Active Storage attachments. It provides custom title/subtitle, placeholder,
|
6
|
+
# and image preview, and is fully configurable via props.
|
7
|
+
#
|
8
|
+
# @example Basic usage
|
9
|
+
# = render Fluxbit::Form::UploadImageComponent.new(attribute: :avatar, label: "Profile photo")
|
10
|
+
#
|
11
|
+
# @see docs/03_Forms/UploadImage.md For detailed documentation and examples.
|
12
|
+
class Fluxbit::Form::UploadImageComponent < Fluxbit::Form::FieldComponent
|
13
|
+
# Initializes the upload image component with the given properties.
|
14
|
+
#
|
15
|
+
# @param form [ActionView::Helpers::FormBuilder] The form builder (optional, for Rails forms)
|
16
|
+
# @param attribute [Symbol] The model attribute to be used in the form (required if using form builder)
|
17
|
+
# @param id [String] The id of the input element (optional)
|
18
|
+
# @param label [String] The label for the input field (optional)
|
19
|
+
# @param help_text [String] Additional help text for the input field (optional)
|
20
|
+
# @param helper_popover [String] Content for a popover helper (optional)
|
21
|
+
# @param helper_popover_placement [String] Placement of the popover (default: "right")
|
22
|
+
# @param image_path [String] Path to the image to be displayed (optional)
|
23
|
+
# @param image_placeholder [String] Placeholder image path if no image is attached (optional)
|
24
|
+
# @param title [Boolean, String] Whether to show a title (true for default, false to hide, or custom string)
|
25
|
+
# @param class [String] Additional CSS classes for the input element
|
26
|
+
# @param ... any other HTML attribute supported by file_field_tag
|
27
|
+
def initialize(**props)
|
28
|
+
super(**props)
|
29
|
+
@title = @props.delete(:title) || "Change"
|
30
|
+
@image_path = @props.delete(:image_path) ||
|
31
|
+
(if @object&.send(@attribute).respond_to?(:attached?) && @object&.send(@attribute)&.send("attached?")
|
32
|
+
@object&.send(@attribute)&.variant(resize_to_fit: [ 160, 160 ])
|
33
|
+
end) || @props.delete(:image_placeholder) || ""
|
34
|
+
|
35
|
+
@props["class"] = "absolute inset-0 h-full w-full cursor-pointer rounded-md border-gray-300 opacity-0"
|
36
|
+
end
|
37
|
+
|
38
|
+
def input_element(input_id: nil)
|
39
|
+
@props["onchange"] = "loadFile(event, '#{id}')"
|
40
|
+
return file_field_tag @name, @props.merge(id: input_id || id) if @form.nil?
|
41
|
+
|
42
|
+
@form.file_field(@attribute, **@props, id: input_id || id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def image_element
|
46
|
+
image_tag @image_path,
|
47
|
+
class: "img_photo_#{id} img_photo absolute inset-0 w-full h-full object-cover rounded-full",
|
48
|
+
alt: @attribute&.to_s&.humanize
|
49
|
+
end
|
50
|
+
end
|
@@ -3,33 +3,33 @@
|
|
3
3
|
module Fluxbit
|
4
4
|
module ComponentsHelper
|
5
5
|
# Components
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def fx_badge(...) = fluxbit_method("Badge", ...)
|
13
|
-
def fx_card(...) = fluxbit_method("Card", ...)
|
14
|
-
def fx_modal(...) = fluxbit_method("Modal", ...)
|
15
|
-
def fx_popover(...) = fluxbit_method("Popover", ...)
|
16
|
-
def fx_tooltip(...) = fluxbit_method("Tooltip", ...)
|
17
|
-
def fx_flex(...) = fluxbit_method("Flex", ...)
|
18
|
-
def fx_tab(...) = fluxbit_method("Tab", ...)
|
6
|
+
[ :avatar, :avatar_group, :gravatar, :alert, :button, :button_group,
|
7
|
+
:badge, :card, :modal, :popover, :tooltip, :flex, :tab ].each do |component|
|
8
|
+
define_method("fx_#{component}") do |*args, **kwargs, &block|
|
9
|
+
fluxbit_method(component.to_s.camelize, *args, **kwargs, &block)
|
10
|
+
end
|
11
|
+
end
|
19
12
|
|
20
13
|
# Forms
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def fx_select_free_input(...) = fluxbit_method("Form::SelectFreeInput", ...)
|
28
|
-
def fx_text_input(...) = fluxbit_method("Form::TextInput", ...)
|
29
|
-
def fx_textarea_input(...) = fluxbit_method("Form::TextareaInput", ...)
|
30
|
-
def fx_toggle_input(...) = fluxbit_method("Form::ToggleInput", ...)
|
14
|
+
[ :help_text, :check_box, :form_builder, :label, :range,
|
15
|
+
:select, :toggle, :upload_image, :dropzone ].each do |component|
|
16
|
+
define_method("fx_#{component}") do |*args, **kwargs, &block|
|
17
|
+
fluxbit_method("Form::#{component.to_s.camelize}", *args, **kwargs, &block)
|
18
|
+
end
|
19
|
+
end
|
31
20
|
def form_builder(...) = fluxbit_method("Form::FormBuilder", ...)
|
32
21
|
|
22
|
+
Fluxbit::Form::TextFieldComponent::TYPE_OPTIONS.each do |type|
|
23
|
+
define_method(type.in?([ :text_area, :textarea ]) ? "fx_#{type}" : "fx_#{type}_field") do |*args, **kwargs, &block|
|
24
|
+
fluxbit_method("Form::TextField", *args, type: type, **kwargs, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Fluxbit::Form::CheckBoxComponent::TYPE_OPTIONS.each do |type|
|
29
|
+
define_method("fx_#{type}") do |*args, **kwargs, &block|
|
30
|
+
fluxbit_method("Form::CheckBox", *args, type: type, **kwargs, &block)
|
31
|
+
end
|
32
|
+
end
|
33
33
|
# Typography
|
34
34
|
def fx_heading(...) = fluxbit_method("Heading", ...)
|
35
35
|
def fx_txt(...) = fluxbit_method("Text", ...)
|
@@ -43,33 +43,5 @@ module Fluxbit
|
|
43
43
|
render(component_klass.new(*args, **kwargs), &c)
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
# # Succint method for render component
|
48
|
-
# # from: https://dev.to/abeidahmed/advanced-viewcomponent-patterns-in-rails-2b4m
|
49
|
-
# #
|
50
|
-
# # Instead of using 'render XComponent'
|
51
|
-
# # One can use 'render_component "X", **@options'
|
52
|
-
# def render_component(component_path, collection: nil, with_content: nil, **options, &block)
|
53
|
-
# component_klass = "#{component_path.classify}Component".constantize
|
54
|
-
|
55
|
-
# return render component_klass.new(**options).with_content(with_content) if with_content
|
56
|
-
|
57
|
-
# if collection
|
58
|
-
# render component_klass.with_collection(collection, **options), &block
|
59
|
-
# else
|
60
|
-
# render component_klass.new(**options), &block
|
61
|
-
# end
|
62
|
-
# end
|
63
|
-
|
64
|
-
# def method_missing(name, *args, &block)
|
65
|
-
# if name == :alert
|
66
|
-
# render component_klass.new(**options), &block
|
67
|
-
# # do something if the method name is "custom_helper_method"
|
68
|
-
# #content_tag(:div, *args, &block)
|
69
|
-
# else
|
70
|
-
# # call the original method_missing method if the method name is not recognized
|
71
|
-
# super
|
72
|
-
# end
|
73
|
-
# end
|
74
46
|
end
|
75
47
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Fluxbit
|
2
|
+
class FormBuilder < ActionView::Helpers::FormBuilder
|
3
|
+
include ActionView::Helpers::OutputSafetyHelper
|
4
|
+
|
5
|
+
attr_reader :template
|
6
|
+
|
7
|
+
delegate :render, :pluralize, to: :template
|
8
|
+
|
9
|
+
def errors_summary(within: :container)
|
10
|
+
return if object.blank?
|
11
|
+
return unless object.errors.any?
|
12
|
+
|
13
|
+
title = I18n.t(
|
14
|
+
"polaris.form_builder.errors_summary",
|
15
|
+
count: object.errors.count,
|
16
|
+
model: object.class.model_name.human.downcase
|
17
|
+
)
|
18
|
+
|
19
|
+
render Fluxbit::BannerComponent.new(
|
20
|
+
title: title,
|
21
|
+
status: :critical,
|
22
|
+
within: within,
|
23
|
+
data: { errors_summary: true }
|
24
|
+
) do |banner|
|
25
|
+
[
|
26
|
+
render(Fluxbit::ListComponent.new) do |list|
|
27
|
+
object.errors.full_messages.each do |error|
|
28
|
+
list.with_item { error.html_safe }
|
29
|
+
end
|
30
|
+
end,
|
31
|
+
(template.capture { yield(banner) } if block_given?)
|
32
|
+
].compact.join.html_safe
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def error_for(method)
|
37
|
+
return if object.blank?
|
38
|
+
return unless object.errors.key?(method)
|
39
|
+
|
40
|
+
raw object.errors.full_messages_for(method)&.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def fluxbit_inline_error_for(method, **options, &block)
|
44
|
+
error_message = error_for(method)
|
45
|
+
return unless error_message
|
46
|
+
|
47
|
+
render(Fluxbit::InlineErrorComponent.new(**options, &block)) do
|
48
|
+
error_message
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Fluxbit::Form::TextFieldComponent::TYPE_OPTIONS.each do |type|
|
53
|
+
define_method(type.in?([ :text_area, :textarea ]) ? "fx_#{type}" : "fx_#{type}_field") do |method, **options, &block|
|
54
|
+
options[:error] ||= error_for(method)
|
55
|
+
options[:error] = !!options[:error] if options[:error_hidden] && options[:error]
|
56
|
+
render Fluxbit::Form::TextFieldComponent.new(form: self, type: type, attribute: method, **options), &block
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
Fluxbit::Form::CheckBoxComponent::TYPE_OPTIONS.each do |type|
|
61
|
+
define_method("fx_#{type}") do |method, **options, &block|
|
62
|
+
options[:error] ||= error_for(method)
|
63
|
+
options[:error] = !!options[:error] if options[:error_hidden] && options[:error]
|
64
|
+
render Fluxbit::Form::CheckBoxComponent.new(form: self, type: type, attribute: method, **options), &block
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
[ :range, :toggle, :upload_image, :dropzone ].each do |component|
|
69
|
+
define_method("fx_#{component}") do |method, **options, &block|
|
70
|
+
options[:error] ||= error_for(method)
|
71
|
+
options[:error] = !!options[:error] if options[:error_hidden] && options[:error]
|
72
|
+
klass = "Fluxbit::Form::#{component.to_s.camelize}Component".constantize
|
73
|
+
render klass.new(form: self, attribute: method, **options), &block
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# select(object, method, choices = nil, options = {}, html_options = {}, &block) public
|
78
|
+
def fx_select(method, **options, &block)
|
79
|
+
options[:error] ||= error_for(method)
|
80
|
+
options[:error] = !!options[:error] if options[:error_hidden] && options[:error]
|
81
|
+
value = object&.public_send(method)
|
82
|
+
options[:selected] = value if value.present?
|
83
|
+
|
84
|
+
render Fluxbit::Form::SelectComponent.new(form: self, attribute: method, **options, &block)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fluxbit::Config::Form::CheckBoxComponent
|
4
|
+
# rubocop: disable Layout/LineLength, Metrics/BlockLength
|
5
|
+
mattr_accessor :styles do
|
6
|
+
{
|
7
|
+
checkbox: "rounded-sm",
|
8
|
+
base: "w-4 h-4 text-blue-600 bg-slate-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-slate-700 dark:border-slate-600",
|
9
|
+
label: {
|
10
|
+
with_helper: "font-medium text-slate-900 dark:text-slate-300",
|
11
|
+
base: "ml-2 text-sm font-medium text-slate-900 dark:text-slate-300"
|
12
|
+
},
|
13
|
+
input_div: "flex items-center h-5",
|
14
|
+
helper_div: "ml-2 text-sm",
|
15
|
+
no_helper_div: "flex items-center"
|
16
|
+
}
|
17
|
+
end
|
18
|
+
# rubocop: enable Layout/LineLength, Metrics/BlockLength
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fluxbit::Config::Form::DropzoneComponent
|
4
|
+
mattr_accessor :icon, default: "heroicons_outline:cloud-arrow-up"
|
5
|
+
mattr_accessor :height, default: 0
|
6
|
+
|
7
|
+
# rubocop: disable Layout/LineLength, Metrics/BlockLength
|
8
|
+
mattr_accessor :styles do
|
9
|
+
{
|
10
|
+
base: "flex items-center justify-center w-full",
|
11
|
+
label: "flex flex-col items-center justify-center w-full border-2 border-slate-300 border-dashed rounded-lg cursor-pointer bg-slate-50 dark:hover:bg-bray-800 dark:bg-slate-700 hover:bg-slate-100 dark:border-slate-600 dark:hover:border-slate-500 dark:hover:bg-slate-600",
|
12
|
+
inner_div: "flex flex-col items-center justify-center pt-5 pb-6",
|
13
|
+
title: "mb-2 text-sm text-slate-500 dark:text-slate-400",
|
14
|
+
subtitle: "text-xs text-slate-500 dark:text-slate-400",
|
15
|
+
icon: "w-10 h-10 mb-4 text-slate-500 dark:text-slate-400",
|
16
|
+
height: [ "", "h-32", "h-64", "h-96" ]
|
17
|
+
}
|
18
|
+
end
|
19
|
+
# rubocop: enable Layout/LineLength, Metrics/BlockLength
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fluxbit::Config::Form::LabelComponent
|
4
|
+
mattr_accessor :color, default: :default
|
5
|
+
mattr_accessor :helper_popover_icon, default: "heroicons_solid:question-mark-circle"
|
6
|
+
mattr_accessor :helper_popover_icon_class, default: "w-4 h-4"
|
7
|
+
mattr_accessor :sizing, default: 1
|
8
|
+
mattr_accessor :helper_popover_placement, default: "right"
|
9
|
+
|
10
|
+
# rubocop: disable Layout/LineLength, Metrics/BlockLength
|
11
|
+
mattr_accessor :styles do
|
12
|
+
{
|
13
|
+
base: "flex font-medium",
|
14
|
+
colors: {
|
15
|
+
default: "text-gray-900 dark:text-white",
|
16
|
+
success: "text-green-700 dark:text-green-500",
|
17
|
+
failure: "text-red-700 dark:text-red-500",
|
18
|
+
info: "text-cyan-500 dark:text-cyan-600",
|
19
|
+
warning: "text-yellow-500 dark:text-yellow-600"
|
20
|
+
},
|
21
|
+
sizes: [
|
22
|
+
"text-sm",
|
23
|
+
"text-md",
|
24
|
+
"text-lg"
|
25
|
+
],
|
26
|
+
helper_popover: "px-2 text-slate-400"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
# rubocop: enable Layout/LineLength, Metrics/BlockLength
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fluxbit::Config::Form::RangeComponent
|
4
|
+
mattr_accessor :vertical, default: false
|
5
|
+
mattr_accessor :sizing, default: 1
|
6
|
+
|
7
|
+
# rubocop: disable Layout/LineLength, Metrics/BlockLength
|
8
|
+
mattr_accessor :styles do
|
9
|
+
{
|
10
|
+
base: "w-full bg-slate-200 rounded-lg appearance-none cursor-pointer dark:bg-slate-700",
|
11
|
+
sizes: [ "h-1 range-sm", "h-2", "h-3 range-lg" ]
|
12
|
+
}
|
13
|
+
end
|
14
|
+
# rubocop: enable Layout/LineLength, Metrics/BlockLength
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fluxbit::Config::Form::TextFieldComponent
|
4
|
+
mattr_accessor :color, default: :default
|
5
|
+
mattr_accessor :sizing, default: 0
|
6
|
+
|
7
|
+
# rubocop: disable Layout/LineLength, Metrics/BlockLength
|
8
|
+
mattr_accessor :styles do
|
9
|
+
{
|
10
|
+
default: "mt-1 block w-full border disabled:cursor-not-allowed disabled:opacity-50 disabled:text-slate-900 disabled:dark:text-slate-400 disabled:bg-slate-100 disabled:dark:bg-slate-700",
|
11
|
+
text: {
|
12
|
+
default: "text-slate-900 dark:text-white",
|
13
|
+
success: "text-green-900",
|
14
|
+
failure: "text-red-900",
|
15
|
+
info: "text-cyan-900",
|
16
|
+
warning: "text-yellow-900"
|
17
|
+
},
|
18
|
+
ring: {
|
19
|
+
default: "focus:ring-blue-500 dark:focus:ring-blue-500",
|
20
|
+
success: "focus:ring-green-500",
|
21
|
+
failure: "focus:ring-red-500",
|
22
|
+
info: "focus:ring-cyan-500",
|
23
|
+
warning: "focus:ring-yellow-500"
|
24
|
+
},
|
25
|
+
bg: {
|
26
|
+
default: "bg-slate-50 dark:bg-slate-700",
|
27
|
+
success: "bg-green-50 dark:bg-green-100",
|
28
|
+
failure: "bg-red-50 dark:bg-red-100",
|
29
|
+
info: "bg-cyan-50 dark:bg-cyan-100",
|
30
|
+
warning: "bg-yellow-50 dark:bg-yellow-100"
|
31
|
+
},
|
32
|
+
placeholder: {
|
33
|
+
default: "dark:placeholder-slate-400",
|
34
|
+
success: "placeholder-green-700",
|
35
|
+
failure: "placeholder-red-700",
|
36
|
+
info: "placeholder-cyan-700",
|
37
|
+
warning: "placeholder-yellow-700"
|
38
|
+
},
|
39
|
+
border: {
|
40
|
+
default: "border-slate-300 focus:border-blue-500 dark:border-slate-600 dark:focus:border-blue-500",
|
41
|
+
success: "border-green-500 focus:border-green-500 dark:border-green-400",
|
42
|
+
failure: "border-red-500 focus:border-red-500 dark:border-red-400",
|
43
|
+
info: "border-cyan-500 focus:border-cyan-500 dark:border-cyan-400",
|
44
|
+
warning: "border-yellow-500 focus:border-yellow-500 dark:border-yellow-400"
|
45
|
+
},
|
46
|
+
shadow: "shadow-xs dark:shadow-xs-light",
|
47
|
+
icon: "pl-10",
|
48
|
+
right_icon: "pr-10",
|
49
|
+
sizing_md_addon: "p-2.5 rounded-none rounded-r-lg flex-1 min-w-0 text-sm",
|
50
|
+
sizes: [
|
51
|
+
"p-2.5 text-sm rounded-lg",
|
52
|
+
"p-4 sm:text-md rounded-lg",
|
53
|
+
"p-2 rounded-lg sm:text-xs"
|
54
|
+
],
|
55
|
+
additional_icons: {
|
56
|
+
class: {
|
57
|
+
default: "mt-1 w-4 h-4 text-slate-500 dark:text-slate-400",
|
58
|
+
success: "mt-1 w-4 h-4 text-green-500 dark:text-green-400",
|
59
|
+
failure: "mt-1 w-4 h-4 text-red-500 dark:text-red-400",
|
60
|
+
info: "mt-1 w-4 h-4 text-cyan-500 dark:text-cyan-400",
|
61
|
+
warning: "mt-1 w-4 h-4 text-yellow-500 dark:text-yellow-400"
|
62
|
+
},
|
63
|
+
icon: "absolute inset-y-0 left-0 flex items-center pl-3",
|
64
|
+
right_icon: "absolute inset-y-0 right-0 flex items-center pr-3",
|
65
|
+
addon: {
|
66
|
+
default: "mt-1 inline-flex items-center px-3 text-sm text-slate-900 bg-slate-200 border border-r-0 border-slate-300 rounded-l-md dark:bg-slate-600 dark:text-slate-400 dark:border-slate-600",
|
67
|
+
success: "mt-1 inline-flex items-center px-3 text-sm text-green-900 bg-green-200 border border-r-0 border-green-300 rounded-l-md dark:bg-green-600 dark:text-green-400 dark:border-green-600",
|
68
|
+
failure: "mt-1 inline-flex items-center px-3 text-sm text-red-900 bg-red-200 border border-r-0 border-red-300 rounded-l-md dark:bg-red-600 dark:text-red-400 dark:border-red-600",
|
69
|
+
info: "mt-1 inline-flex items-center px-3 text-sm text-cyan-900 bg-cyan-200 border border-r-0 border-cyan-300 rounded-l-md dark:bg-cyan-600 dark:text-cyan-400 dark:border-cyan-600",
|
70
|
+
warning: "mt-1 inline-flex items-center px-3 text-sm text-yellow-900 bg-yellow-200 border border-r-0 border-yellow-300 rounded-l-md dark:bg-yellow-600 dark:text-yellow-400 dark:border-yellow-600"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
end
|
75
|
+
# rubocop: enable Layout/LineLength, Metrics/BlockLength
|
76
|
+
end
|