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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/fluxbit/form/check_box_component.rb +56 -0
  3. data/app/components/fluxbit/form/component.rb +18 -24
  4. data/app/components/fluxbit/form/dropzone_component.html.erb +39 -0
  5. data/app/components/fluxbit/form/dropzone_component.rb +39 -0
  6. data/app/components/fluxbit/form/field_component.rb +26 -0
  7. data/app/components/fluxbit/form/form_builder_component.rb +1 -1
  8. data/app/components/fluxbit/form/{helper_text_component.rb → help_text_component.rb} +8 -3
  9. data/app/components/fluxbit/form/label_component.rb +32 -29
  10. data/app/components/fluxbit/form/range_component.rb +52 -0
  11. data/app/components/fluxbit/form/select_component.rb +88 -0
  12. data/app/components/fluxbit/form/text_field_component.rb +168 -0
  13. data/app/components/fluxbit/form/toggle_component.html.erb +23 -0
  14. data/app/components/fluxbit/form/toggle_component.rb +81 -0
  15. data/app/components/fluxbit/form/upload_image_component.html.erb +50 -0
  16. data/app/components/fluxbit/form/upload_image_component.rb +50 -0
  17. data/app/helpers/fluxbit/components_helper.rb +23 -51
  18. data/app/helpers/fluxbit/form_builder.rb +87 -0
  19. data/lib/fluxbit/config/form/check_box_component.rb +19 -0
  20. data/lib/fluxbit/config/form/dropzone_component.rb +20 -0
  21. data/lib/fluxbit/config/form/{helper_text_component.rb → help_text_component.rb} +1 -1
  22. data/lib/fluxbit/config/form/label_component.rb +30 -0
  23. data/lib/fluxbit/config/form/range_component.rb +15 -0
  24. data/lib/fluxbit/config/form/text_field_component.rb +76 -0
  25. data/{app/components/fluxbit/form/toggle_input_component.rb → lib/fluxbit/config/form/toggle_component.rb} +28 -115
  26. data/lib/fluxbit/view_components/version.rb +1 -1
  27. data/lib/fluxbit/view_components.rb +7 -1
  28. data/lib/install/install.rb +3 -3
  29. metadata +21 -18
  30. data/LICENSE.txt +0 -20
  31. data/app/components/fluxbit/form/checkbox_input_component.rb +0 -61
  32. data/app/components/fluxbit/form/datepicker_component.rb +0 -7
  33. data/app/components/fluxbit/form/radio_input_component.rb +0 -21
  34. data/app/components/fluxbit/form/range_input_component.rb +0 -51
  35. data/app/components/fluxbit/form/select_free_input_component.rb +0 -77
  36. data/app/components/fluxbit/form/select_input_component.rb +0 -21
  37. data/app/components/fluxbit/form/spacer_input_component.rb +0 -12
  38. data/app/components/fluxbit/form/text_input_component.rb +0 -225
  39. data/app/components/fluxbit/form/textarea_input_component.rb +0 -57
  40. data/app/components/fluxbit/form/upload_image_input_component.html.erb +0 -48
  41. data/app/components/fluxbit/form/upload_image_input_component.rb +0 -61
  42. data/app/components/fluxbit/form/upload_input_component.html.erb +0 -12
  43. 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
- def fx_avatar(...) = fluxbit_method("Avatar", ...)
7
- def fx_avatar_group(...) = fluxbit_method("AvatarGroup", ...)
8
- def fx_gravatar(...) = fluxbit_method("Gravatar", ...)
9
- def fx_alert(...) = fluxbit_method("Alert", ...)
10
- def fx_button(...) = fluxbit_method("Button", ...)
11
- def fx_button_group(...) = fluxbit_method("ButtonGroup", ...)
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
- def fx_helper_text(...) = fluxbit_method("Form::HelperText", ...)
22
- def fx_checkbox_input(...) = fluxbit_method("Form::CheckboxInput", ...)
23
- def fx_form_builder(...) = fluxbit_method("Form::FormBuilder", ...)
24
- def fx_label(...) = fluxbit_method("Form::Label", ...)
25
- def fx_range_input(...) = fluxbit_method("Form::RangeInput", ...)
26
- def fx_select_input(...) = fluxbit_method("Form::SelectInput", ...)
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Fluxbit::Config::Form::HelperTextComponent
3
+ module Fluxbit::Config::Form::HelpTextComponent
4
4
  mattr_accessor :color, default: :default
5
5
 
6
6
  # rubocop: disable Layout/LineLength, Metrics/BlockLength
@@ -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