flowbite-components 0.1.4 → 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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -4
  3. data/README.md +23 -4
  4. data/app/components/flowbite/badge/badge.html.erb +4 -0
  5. data/app/components/flowbite/badge/dot.rb +45 -0
  6. data/app/components/flowbite/badge/pill.rb +40 -0
  7. data/app/components/flowbite/badge.rb +116 -0
  8. data/app/components/flowbite/breadcrumb/home_icon.rb +28 -0
  9. data/app/components/flowbite/breadcrumb/item/current.rb +35 -0
  10. data/app/components/flowbite/breadcrumb/item/first.rb +37 -0
  11. data/app/components/flowbite/breadcrumb/item.rb +50 -0
  12. data/app/components/flowbite/breadcrumb/separator_icon.rb +34 -0
  13. data/app/components/flowbite/breadcrumb.rb +54 -0
  14. data/app/components/flowbite/button.rb +6 -5
  15. data/app/components/flowbite/card.rb +15 -1
  16. data/app/components/flowbite/input/checkbox.rb +2 -2
  17. data/app/components/flowbite/input/date.rb +2 -2
  18. data/app/components/flowbite/input/date_time.rb +11 -0
  19. data/app/components/flowbite/input/email.rb +2 -2
  20. data/app/components/flowbite/input/file.rb +2 -2
  21. data/app/components/flowbite/input/hint.rb +6 -1
  22. data/app/components/flowbite/input/label.rb +1 -1
  23. data/app/components/flowbite/input/number.rb +2 -2
  24. data/app/components/flowbite/input/password.rb +2 -2
  25. data/app/components/flowbite/input/phone.rb +2 -2
  26. data/app/components/flowbite/input/radio_button.rb +2 -2
  27. data/app/components/flowbite/input/select.rb +2 -2
  28. data/app/components/flowbite/input/textarea.rb +2 -2
  29. data/app/components/flowbite/input/url.rb +2 -2
  30. data/app/components/flowbite/input/validation_error.rb +1 -1
  31. data/app/components/flowbite/input.rb +155 -0
  32. data/app/components/flowbite/input_field/checkbox.rb +7 -7
  33. data/app/components/flowbite/input_field/date_time.rb +13 -0
  34. data/app/components/flowbite/input_field/input_field.html.erb +2 -2
  35. data/app/components/flowbite/input_field/radio_button.rb +9 -15
  36. data/app/components/flowbite/input_field/select.rb +1 -1
  37. data/app/components/flowbite/input_field.rb +120 -69
  38. data/app/components/flowbite/link.rb +2 -0
  39. data/app/components/flowbite/sidebar/item.rb +68 -0
  40. data/app/components/flowbite/sidebar/navigation.rb +62 -0
  41. data/app/components/flowbite/sidebar.rb +62 -0
  42. data/app/components/flowbite/toast/icon.html.erb +5 -0
  43. data/app/components/flowbite/toast/icon.rb +57 -0
  44. data/app/components/flowbite/toast/toast.html.erb +40 -0
  45. data/app/components/flowbite/toast.rb +37 -0
  46. data/lib/flowbite/components/version.rb +1 -1
  47. data/lib/yard/flowbite_viewcomponent.rb +24 -0
  48. metadata +40 -5
  49. data/app/components/flowbite/input/field.rb +0 -126
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Date < Field
4
+ class Input
5
+ class Date < Input
6
6
  def input_field_type
7
7
  :date_field
8
8
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ class Input
5
+ class DateTime < Input
6
+ def input_field_type
7
+ :datetime_field
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Email < Field
4
+ class Input
5
+ class Email < Input
6
6
  # Returns the name of the method used to generate HTML for the input field
7
7
  def input_field_type
8
8
  :email_field
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class File < Field
4
+ class Input
5
+ class File < Input
6
6
  SIZES = {
7
7
  sm: ["text-sm"],
8
8
  default: ["text-sm"],
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
4
+ class Input
5
+ # A hint element for input fields.
6
+ #
7
+ # Provides additional context or instructions for the user.
8
+ #
9
+ # See https://flowbite.com/docs/forms/input-field/#helper-text
5
10
  class Hint < ViewComponent::Base
6
11
  STATES = [
7
12
  DEFAULT = :default
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
4
+ class Input
5
5
  # https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-label
6
6
  class Label < ViewComponent::Base
7
7
  STATES = [
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Number < Field
4
+ class Input
5
+ class Number < Input
6
6
  def input_field_type
7
7
  :number_field
8
8
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Password < Field
4
+ class Input
5
+ class Password < Input
6
6
  def input_field_type
7
7
  :password_field
8
8
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Phone < Field
4
+ class Input
5
+ class Phone < Input
6
6
  def input_field_type
7
7
  :phone_field
8
8
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
4
+ class Input
5
5
  # The radio button component can be used to allow the user to choose a
6
6
  # single option from one or more available options.
7
7
  #
8
8
  # https://flowbite.com/docs/forms/radio/
9
- class RadioButton < Field
9
+ class RadioButton < Input
10
10
  class << self
11
11
  # Radio buttons only have their default size.
12
12
  def sizes
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
4
+ class Input
5
5
  # The `Select` component renders a select input field for use in forms.
6
6
  #
7
7
  # https://flowbite.com/docs/forms/select/
8
8
  #
9
9
  # Wraps `ActionView::Helpers::FormOptionsHelper#select`: https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select
10
- class Select < Field
10
+ class Select < Input
11
11
  SIZES = {
12
12
  sm: ["px-2.5", "py-2", "text-sm"],
13
13
  default: ["px-3", "py-2.5", "text-sm"],
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Textarea < Field
4
+ class Input
5
+ class Textarea < Input
6
6
  class << self
7
7
  # rubocop:disable Layout/LineLength
8
8
  def styles
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
5
- class Url < Field
4
+ class Input
5
+ class Url < Input
6
6
  # Returns the name of the method used to generate HTML for the input field
7
7
  def input_field_type
8
8
  :url_field
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flowbite
4
- module Input
4
+ class Input
5
5
  class ValidationError < ViewComponent::Base
6
6
  class << self
7
7
  def classes(state: :default, style: :default)
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ # The individual input form element used in forms - without labels, error
5
+ # messages, hints, etc.
6
+ #
7
+ # Use this when you want to render an input field on its own without any
8
+ # surrounding elements, i.e. as a building block in more complex input
9
+ # components. To render a complete input field with labels and error messages,
10
+ # use {Flowbite::InputField} instead.
11
+ #
12
+ # By default this renders a text input field. To render other types of input
13
+ # fields, use one of the subclasses, such as {Flowbite::Input::Checkbox} or
14
+ # {Flowbite::Input::Textarea}.
15
+ #
16
+ # @example Usage
17
+ # <%= render(Flowbite::Input::Email.new(attribute: :email, form: form)) %>
18
+ #
19
+ # @lookbook_embed InputPreview
20
+ class Input < ViewComponent::Base
21
+ SIZES = {
22
+ sm: ["px-2.5", "py-2", "text-sm"],
23
+ default: ["px-3", "py-2.5", "text-sm"],
24
+ lg: ["px-3.5", "py-3", "text-base"]
25
+ }.freeze
26
+
27
+ STATES = [
28
+ DEFAULT = :default,
29
+ DISABLED = :disabled,
30
+ ERROR = :error
31
+ ].freeze
32
+
33
+ attr_reader :options, :size, :style
34
+
35
+ class << self
36
+ # @return [Array<String>] The CSS classes to apply to the input field
37
+ # given the specified +size+, +state+, and +style+.
38
+ def classes(size: :default, state: :default, style: :default)
39
+ style = styles.fetch(style)
40
+ state_classes = style.fetch(state)
41
+ state_classes + sizes.fetch(size)
42
+ end
43
+
44
+ # Returns the sizes this Input supports.
45
+ #
46
+ # This is effectively the {SIZES} constant, but provided as a method to
47
+ # return the constant from the current class, not the superclass.
48
+ #
49
+ # @return [Hash] A hash mapping size names to their corresponding CSS
50
+ # classes.
51
+ def sizes
52
+ const_get(:SIZES)
53
+ end
54
+
55
+ # @return [Flowbite::Styles] The available styles for this input field.
56
+ def styles
57
+ # rubocop:disable Layout/LineLength
58
+ Flowbite::Styles.from_hash(
59
+ {
60
+ default: {
61
+ default: ["bg-neutral-secondary-medium", "border", "border-default-medium", "text-heading", "rounded-base", "focus:ring-brand", "focus:border-brand", "block", "w-full", "shadow-xs", "placeholder:text-body"],
62
+ disabled: ["bg-neutral-secondary-medium", "border", "border-default-medium", "text-fg-disabled", "rounded-base", "focus:ring-brand", "focus:border-brand", "block", "w-full", "shadow-xs", "cursor-not-allowed", "placeholder:text-fg-disabled"],
63
+ error: ["bg-danger-soft", "border", "border-danger-subtle", "text-fg-danger-strong", "rounded-base", "focus:ring-danger", "focus:border-danger", "block", "w-full", "shadow-xs", "placeholder:text-fg-danger-strong"]
64
+ }
65
+ }.freeze
66
+ )
67
+ # rubocop:enable Layout/LineLength
68
+ end
69
+ end
70
+
71
+ # @param attribute [Symbol] The attribute on the form's object this input
72
+ # field is for.
73
+ #
74
+ # @param form [ActionView::Helpers::FormBuilder] The form builder this
75
+ # input field is part of.
76
+ #
77
+ # @param class [String, Array<String>] Additional CSS classes to apply to
78
+ # the input field.
79
+ #
80
+ # @param disabled [Boolean] Whether the input field should be disabled.
81
+ #
82
+ # @param options [Hash] Additional HTML attributes to pass to the input
83
+ # field. For example, you can use this to set placeholder text by
84
+ # passing +options: {placeholder: "Enter your name"}+
85
+ #
86
+ # @param size [Symbol] The size of the input field. Can be one of +:sm+,
87
+ # +:default+, or +:lg+.
88
+ def initialize(attribute:, form:, class: nil, disabled: false, options: {}, size: :default)
89
+ @attribute = attribute
90
+ @class = Array.wrap(binding.local_variable_get(:class))
91
+ @disabled = disabled
92
+ @form = form
93
+ @options = options || {}
94
+ @object = form.object
95
+ @size = size
96
+ end
97
+
98
+ # Returns the HTML to use for the actual input field element.
99
+ def call
100
+ @form.send(
101
+ input_field_type,
102
+ @attribute,
103
+ **input_options
104
+ )
105
+ end
106
+
107
+ # Returns the CSS classes to apply to the input field
108
+ #
109
+ # @return [Array<String>] An array of CSS classes.
110
+ def classes
111
+ self.class.classes(size: size, state: state) + @class
112
+ end
113
+
114
+ # Returns the name of the method used to generate HTML for the input field
115
+ #
116
+ # @return [Symbol] The form helper method name to call on +form+.
117
+ def input_field_type
118
+ :text_field
119
+ end
120
+
121
+ protected
122
+
123
+ # @return [Boolean] Returns true if the field is disabled
124
+ def disabled?
125
+ !!@disabled
126
+ end
127
+
128
+ # Returns true if the object has errors. Returns false if there is no
129
+ # object.
130
+ #
131
+ # @return [Boolean] true if there are errors, false otherwise.
132
+ def errors?
133
+ return false unless @object
134
+
135
+ @object.errors.include?(@attribute.intern)
136
+ end
137
+
138
+ private
139
+
140
+ # Returns the options argument for the input field
141
+ def input_options
142
+ {
143
+ class: classes,
144
+ disabled: disabled?
145
+ }.merge(options)
146
+ end
147
+
148
+ def state
149
+ return DISABLED if disabled?
150
+ return ERROR if errors?
151
+
152
+ DEFAULT
153
+ end
154
+ end
155
+ end
@@ -31,6 +31,13 @@ module Flowbite
31
31
 
32
32
  private
33
33
 
34
+ def default_input_arguments
35
+ args = super
36
+ args[:unchecked_value] = @input[:unchecked_value] if @input.key?(:unchecked_value)
37
+ args[:value] = @input[:value] if @input.key?(:value)
38
+ args
39
+ end
40
+
34
41
  def hint_classes
35
42
  if disabled?
36
43
  "text-xs font-normal text-fg-disabled"
@@ -39,13 +46,6 @@ module Flowbite
39
46
  end
40
47
  end
41
48
 
42
- def input_arguments
43
- args = super
44
- args[:unchecked_value] = @input[:unchecked_value] if @input.key?(:unchecked_value)
45
- args[:value] = @input[:value] if @input.key?(:value)
46
- args
47
- end
48
-
49
49
  def label_classes
50
50
  if disabled?
51
51
  "font-medium text-fg-disabled"
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ class InputField
5
+ class DateTime < InputField
6
+ protected
7
+
8
+ def input_component
9
+ Flowbite::Input::DateTime
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,8 +1,8 @@
1
- <div class="<%= classes.join(" ") %>">
1
+ <%= content_tag(:div, container_options) do %>
2
2
  <%= label %>
3
3
  <%= input %>
4
4
  <%= hint %>
5
5
  <% errors.each do |error| %>
6
6
  <%= render(Flowbite::Input::ValidationError.new) { error.upcase_first } %>
7
7
  <% end %>
8
- </div>
8
+ <% end %>
@@ -26,6 +26,15 @@ module Flowbite
26
26
  input_component.new(**args)
27
27
  end
28
28
 
29
+ def default_hint_options
30
+ return {} unless @hint
31
+
32
+ {
33
+ class: hint_classes,
34
+ id: id_for_hint_element
35
+ }.merge(@hint[:options] || {})
36
+ end
37
+
29
38
  # Returns options for the default label element. This includes CSS classes
30
39
  # since they are specific to RadioButton labels (and Checkbox ones).
31
40
  def default_label_options
@@ -37,21 +46,6 @@ module Flowbite
37
46
  })
38
47
  end
39
48
 
40
- # Returns the HTML to use for the hint element if any
41
- def hint
42
- return unless hint?
43
-
44
- component = Flowbite::Input::Hint.new(
45
- attribute: @attribute,
46
- form: @form,
47
- options: {
48
- class: hint_classes,
49
- id: id_for_hint_element
50
- }
51
- ).with_content(@hint)
52
- render(component)
53
- end
54
-
55
49
  def input_component
56
50
  ::Flowbite::Input::RadioButton
57
51
  end
@@ -19,7 +19,7 @@ module Flowbite
19
19
  form: @form,
20
20
  include_blank: @include_blank,
21
21
  multiple: @multiple,
22
- options: input_options,
22
+ options: default_input_options,
23
23
  size: @size
24
24
  )
25
25
  )