flowbite-components 0.1.3 → 0.2.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -4
  3. data/README.md +56 -8
  4. data/app/components/flowbite/breadcrumb/home_icon.rb +28 -0
  5. data/app/components/flowbite/breadcrumb/item/current.rb +35 -0
  6. data/app/components/flowbite/breadcrumb/item/first.rb +37 -0
  7. data/app/components/flowbite/breadcrumb/item.rb +50 -0
  8. data/app/components/flowbite/breadcrumb/separator_icon.rb +34 -0
  9. data/app/components/flowbite/breadcrumb.rb +54 -0
  10. data/app/components/flowbite/button/outline.rb +25 -10
  11. data/app/components/flowbite/button/pill.rb +26 -26
  12. data/app/components/flowbite/button.rb +39 -35
  13. data/app/components/flowbite/card/card.html.erb +7 -0
  14. data/app/components/flowbite/card/title.rb +39 -0
  15. data/app/components/flowbite/card.rb +71 -16
  16. data/app/components/flowbite/input/checkbox.rb +13 -11
  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 +13 -11
  21. data/app/components/flowbite/input/hint.rb +16 -8
  22. data/app/components/flowbite/input/label.rb +15 -10
  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 +13 -11
  27. data/app/components/flowbite/input/select.rb +7 -7
  28. data/app/components/flowbite/input/textarea.rb +13 -11
  29. data/app/components/flowbite/input/url.rb +2 -2
  30. data/app/components/flowbite/input/validation_error.rb +32 -2
  31. data/app/components/flowbite/input.rb +155 -0
  32. data/app/components/flowbite/input_field/checkbox.html.erb +2 -4
  33. data/app/components/flowbite/input_field/checkbox.rb +8 -4
  34. data/app/components/flowbite/input_field/date_time.rb +13 -0
  35. data/app/components/flowbite/input_field/input_field.html.erb +2 -2
  36. data/app/components/flowbite/input_field/radio_button.html.erb +2 -4
  37. data/app/components/flowbite/input_field/radio_button.rb +19 -21
  38. data/app/components/flowbite/input_field.rb +117 -49
  39. data/app/components/flowbite/link.rb +43 -0
  40. data/app/components/flowbite/styles.rb +34 -0
  41. data/app/components/flowbite/toast/icon.html.erb +5 -0
  42. data/app/components/flowbite/toast/icon.rb +57 -0
  43. data/app/components/flowbite/toast/toast.html.erb +40 -0
  44. data/app/components/flowbite/toast.rb +37 -0
  45. data/lib/flowbite/components/version.rb +1 -1
  46. data/lib/yard/flowbite_viewcomponent.rb +24 -0
  47. metadata +37 -5
  48. data/app/components/flowbite/input/field.rb +0 -117
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ class Styles
5
+ class StyleNotFoundError < ::KeyError; end
6
+
7
+ class << self
8
+ def from_hash(styles_hash)
9
+ styles = Styles.new
10
+ styles_hash.each do |style_name, states_hash|
11
+ styles.add_style(style_name, states_hash)
12
+ end
13
+ styles
14
+ end
15
+ end
16
+
17
+ def add_style(style_name, states_hash)
18
+ @styles[style_name] = Flowbite::Style.new(states_hash)
19
+ end
20
+
21
+ def fetch(style_name)
22
+ return @styles[style_name] if @styles.key?(style_name)
23
+
24
+ raise \
25
+ StyleNotFoundError,
26
+ "Style not found: #{style_name}. Available styles: " \
27
+ "#{@styles.keys.sort.join(", ")}"
28
+ end
29
+
30
+ def initialize
31
+ @styles = {}
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ <div class="<%= container_classes.join(" ") %>">
2
+ <svg class="w-4 h-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
3
+ <path d="<%= svg_path %>"/>
4
+ </svg>
5
+ </div>
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ class Toast
5
+ # Renders an icon for a toast notification.
6
+ #
7
+ # @param style [Symbol] The color style of the icon (:default, :success, :danger, :warning).
8
+ class Icon < ViewComponent::Base
9
+ class << self
10
+ def classes(style: :default)
11
+ styles.fetch(style).fetch(:classes)
12
+ end
13
+
14
+ def svg_path(style: :default)
15
+ styles.fetch(style).fetch(:svg_path)
16
+ end
17
+
18
+ # rubocop:disable Layout/LineLength
19
+ def styles
20
+ {
21
+ default: {
22
+ classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-blue-500", "bg-blue-100", "rounded-lg", "dark:bg-blue-800", "dark:text-blue-200"],
23
+ svg_path: "M15.147 15.085a7.159 7.159 0 0 1-6.189 3.307A6.713 6.713 0 0 1 3.1 15.444c-2.679-4.513.287-8.737.888-9.548A4.373 4.373 0 0 0 5 1.608c1.287.953 6.445 3.218 5.537 10.5 1.5-1.122 2.706-3.01 2.853-6.14 1.433 1.049 3.993 5.395 1.757 9.117Z"
24
+ },
25
+ success: {
26
+ classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-green-500", "bg-green-100", "rounded-lg", "dark:bg-green-800", "dark:text-green-200"],
27
+ svg_path: "M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"
28
+ },
29
+ danger: {
30
+ classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-red-500", "bg-red-100", "rounded-lg", "dark:bg-red-800", "dark:text-red-200"],
31
+ svg_path: "M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z"
32
+ },
33
+ warning: {
34
+ classes: ["inline-flex", "items-center", "justify-center", "shrink-0", "w-8", "h-8", "text-orange-500", "bg-orange-100", "rounded-lg", "dark:bg-orange-700", "dark:text-orange-200"],
35
+ svg_path: "M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM10 15a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-4a1 1 0 0 1-2 0V6a1 1 0 0 1 2 0v5Z"
36
+ }
37
+ }.freeze
38
+ end
39
+ # rubocop:enable Layout/LineLength
40
+ end
41
+
42
+ attr_reader :style
43
+
44
+ def initialize(style: :default)
45
+ @style = style
46
+ end
47
+
48
+ def container_classes
49
+ self.class.classes(style: style)
50
+ end
51
+
52
+ def svg_path
53
+ self.class.svg_path(style: style)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ <div
2
+ class="<%= container_classes.join(" ") %>"
3
+ role="alert"
4
+ <%= options.map { |k, v| "#{k}=\"#{v}\"" }.join(" ").html_safe %>
5
+ >
6
+ <%= render Flowbite::Toast::Icon.new(style: style) %>
7
+
8
+ <div class="ms-3 text-sm font-normal"><%= message %></div>
9
+
10
+ <% if dismissible %>
11
+ <%# Styles from https://flowbite.com/docs/components/toast/#default-toast %>
12
+ <button
13
+ type="button"
14
+ class="
15
+ ms-auto flex items-center justify-center text-body
16
+ hover:text-heading bg-transparent box-border border
17
+ border-transparent hover:bg-neutral-secondary-medium focus:ring-4
18
+ focus:ring-neutral-tertiary font-medium leading-5 rounded text-sm
19
+ h-8 w-8 focus:outline-none
20
+ "
21
+ aria-label="Close"
22
+ >
23
+ <svg
24
+ class="w-3 h-3"
25
+ aria-hidden="true"
26
+ xmlns="http://www.w3.org/2000/svg"
27
+ fill="none"
28
+ viewBox="0 0 14 14"
29
+ >
30
+ <path
31
+ stroke="currentColor"
32
+ stroke-linecap="round"
33
+ stroke-linejoin="round"
34
+ stroke-width="2"
35
+ d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
36
+ />
37
+ </svg>
38
+ </button>
39
+ <% end %>
40
+ </div>
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ # Renders a toast notification element.
5
+ #
6
+ # @example Usage
7
+ # <%= render(Flowbite::Toast.new(message: "Something has happened!")) %>
8
+ #
9
+ # @see https://flowbite.com/docs/components/toast/
10
+ # @lookbook_embed ToastPreview
11
+ class Toast < ViewComponent::Base
12
+ class << self
13
+ def classes
14
+ ["flex", "items-center", "w-full", "max-w-xs", "p-4", "text-body", "bg-neutral-primary-soft", "rounded-base", "shadow-xs", "border", "border-default"]
15
+ end
16
+ end
17
+
18
+ attr_reader :dismissible, :message, :options, :style
19
+
20
+ # @param class [Array<String>] Additional CSS classes for the toast container.
21
+ # @param dismissible [Boolean] Whether the toast can be dismissed (default: true).
22
+ # @param message [String] The message to display in the toast.
23
+ # @param options [Hash] Additional HTML options for the toast container.
24
+ # @param style [Symbol] The color style of the toast (:default, :success, :danger, :warning).
25
+ def initialize(message:, dismissible: true, style: :default, class: nil, **options)
26
+ @message = message
27
+ @style = style
28
+ @dismissible = dismissible
29
+ @class = Array.wrap(binding.local_variable_get(:class))
30
+ @options = options
31
+ end
32
+
33
+ def container_classes
34
+ self.class.classes + @class
35
+ end
36
+ end
37
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Flowbite
4
4
  module Components
5
- VERSION = "0.1.3"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # YARD plugin for documenting ViewComponent slots
4
+ #
5
+ # This plugin adds a @viewcomponent_slot tag that can be used to document
6
+ # slots defined with renders_one and renders_many in ViewComponent classes.
7
+ #
8
+ # Usage:
9
+ # # @viewcomponent_slot [Flowbite::Card::Title] title The title of the card
10
+ # renders_one :title
11
+ #
12
+ # # @viewcomponent_slot [Flowbite::Breadcrumb::Item] items The breadcrumb items
13
+ # renders_many :items
14
+ #
15
+ # The tag accepts:
16
+ # - Types (optional): The component class(es) that can be rendered in the slot
17
+ # - Name (required): The slot name (matching the symbol passed to renders_one/renders_many)
18
+ # - Description (optional): A description of what the slot is for
19
+
20
+ YARD::Tags::Library.define_tag(
21
+ "ViewComponent Slot",
22
+ :viewcomponent_slot,
23
+ :with_types_and_name
24
+ )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flowbite-components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakob Skjerning
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 4.0.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: yard
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
26
40
  description: A library of View Components based on the Flowbite design system to be
27
41
  used in Rails applications.
28
42
  email:
@@ -35,14 +49,23 @@ files:
35
49
  - LICENSE
36
50
  - README.md
37
51
  - app/assets/tailwind/flowbite_components/engine.css
52
+ - app/components/flowbite/breadcrumb.rb
53
+ - app/components/flowbite/breadcrumb/home_icon.rb
54
+ - app/components/flowbite/breadcrumb/item.rb
55
+ - app/components/flowbite/breadcrumb/item/current.rb
56
+ - app/components/flowbite/breadcrumb/item/first.rb
57
+ - app/components/flowbite/breadcrumb/separator_icon.rb
38
58
  - app/components/flowbite/button.rb
39
59
  - app/components/flowbite/button/outline.rb
40
60
  - app/components/flowbite/button/pill.rb
41
61
  - app/components/flowbite/card.rb
62
+ - app/components/flowbite/card/card.html.erb
63
+ - app/components/flowbite/card/title.rb
64
+ - app/components/flowbite/input.rb
42
65
  - app/components/flowbite/input/checkbox.rb
43
66
  - app/components/flowbite/input/date.rb
67
+ - app/components/flowbite/input/date_time.rb
44
68
  - app/components/flowbite/input/email.rb
45
- - app/components/flowbite/input/field.rb
46
69
  - app/components/flowbite/input/file.rb
47
70
  - app/components/flowbite/input/hint.rb
48
71
  - app/components/flowbite/input/label.rb
@@ -58,6 +81,7 @@ files:
58
81
  - app/components/flowbite/input_field/checkbox.html.erb
59
82
  - app/components/flowbite/input_field/checkbox.rb
60
83
  - app/components/flowbite/input_field/date.rb
84
+ - app/components/flowbite/input_field/date_time.rb
61
85
  - app/components/flowbite/input_field/email.rb
62
86
  - app/components/flowbite/input_field/file.rb
63
87
  - app/components/flowbite/input_field/input_field.html.erb
@@ -70,15 +94,23 @@ files:
70
94
  - app/components/flowbite/input_field/text.rb
71
95
  - app/components/flowbite/input_field/textarea.rb
72
96
  - app/components/flowbite/input_field/url.rb
97
+ - app/components/flowbite/link.rb
73
98
  - app/components/flowbite/style.rb
99
+ - app/components/flowbite/styles.rb
100
+ - app/components/flowbite/toast.rb
101
+ - app/components/flowbite/toast/icon.html.erb
102
+ - app/components/flowbite/toast/icon.rb
103
+ - app/components/flowbite/toast/toast.html.erb
74
104
  - lib/flowbite/components.rb
75
105
  - lib/flowbite/components/engine.rb
76
106
  - lib/flowbite/components/version.rb
77
- homepage: https://github.com/substancelab/flowbite-components
107
+ - lib/yard/flowbite_viewcomponent.rb
108
+ homepage: https://flowbite-components.substancelab.com
78
109
  licenses: []
79
110
  metadata:
80
111
  allowed_push_host: https://rubygems.org/
81
- homepage_uri: https://github.com/substancelab/flowbite-components
112
+ documentation_uri: https://flowbite-components.substancelab.com/docs
113
+ homepage_uri: https://flowbite-components.substancelab.com
82
114
  source_code_uri: https://github.com/substancelab/flowbite-components
83
115
  changelog_uri: https://github.com/substancelab/flowbite-components/blob/main/CHANGELOG.md
84
116
  rdoc_options: []
@@ -96,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
128
  - !ruby/object:Gem::Version
97
129
  version: '0'
98
130
  requirements: []
99
- rubygems_version: 3.6.9
131
+ rubygems_version: 4.0.3
100
132
  specification_version: 4
101
133
  summary: ViewComponents using the Flowbite design system
102
134
  test_files: []
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Flowbite
4
- module Input
5
- # The indivdual input component for use in forms without labels or error
6
- # messages.
7
- #
8
- # Use this when you want to render an input field on its own without any
9
- # surrounding elements, ie as a building block in more complex input
10
- # components.
11
- #
12
- # To render a complete input field with labels and error messages, use
13
- # `Flowbite::InputField` instead.
14
- class Field < ViewComponent::Base
15
- SIZES = {
16
- sm: ["p-2", "text-xs"],
17
- default: ["p-2.5", "text-sm"],
18
- lg: ["p-4", "text-base"]
19
- }.freeze
20
-
21
- STATES = [
22
- DEFAULT = :default,
23
- DISABLED = :disabled,
24
- ERROR = :error
25
- ].freeze
26
-
27
- attr_reader :options, :size, :style
28
-
29
- class << self
30
- def classes(size: :default, state: :default, style: :default)
31
- style = styles.fetch(style)
32
- state_classes = style.fetch(state)
33
- state_classes + sizes.fetch(size)
34
- end
35
-
36
- # Returns the sizes this Field supports.
37
- #
38
- # This is effectively the SIZES constant, but provided as a method to
39
- # return the constant from the current class, not the superclass.
40
- #
41
- # @return [Hash] A hash mapping size names to their corresponding CSS
42
- # classes.
43
- def sizes
44
- const_get(:SIZES)
45
- end
46
-
47
- # rubocop:disable Layout/LineLength
48
- def styles
49
- {
50
- default: Flowbite::Style.new(
51
- default: ["bg-gray-50", "border", "border-gray-300", "text-gray-900", "rounded-lg", "focus:ring-blue-500", "focus:border-blue-500", "block", "w-full", "dark:bg-gray-700", "dark:border-gray-600", "dark:placeholder-gray-400", "dark:text-white", "dark:focus:ring-blue-500", "dark:focus:border-blue-500"],
52
- disabled: ["bg-gray-100", "border", "border-gray-300", "text-gray-900", "text-sm", "rounded-lg", "focus:ring-blue-500", "focus:border-blue-500", "block", "w-full", "p-2.5", "cursor-not-allowed", "dark:bg-gray-700", "dark:border-gray-600", "dark:placeholder-gray-400", "dark:text-gray-400", "dark:focus:ring-blue-500", "dark:focus:border-blue-500"],
53
- error: ["bg-red-50", "border", "border-red-500", "text-red-900", "placeholder-red-700", "rounded-lg", "focus:ring-red-500", "dark:bg-gray-700", "focus:border-red-500", "block", "w-full", "dark:text-red-500", "dark:placeholder-red-500", "dark:border-red-500"]
54
- )
55
- }.freeze
56
- end
57
- # rubocop:enable Layout/LineLength
58
- end
59
-
60
- def initialize(attribute:, form:, disabled: false, options: {}, size: :default)
61
- @attribute = attribute
62
- @disabled = disabled
63
- @form = form
64
- @options = options || {}
65
- @object = form.object
66
- @size = size
67
- end
68
-
69
- # Returns the HTML to use for the actual input field element.
70
- def call
71
- @form.send(
72
- input_field_type,
73
- @attribute,
74
- **input_options
75
- )
76
- end
77
-
78
- # Returns the CSS classes to apply to the input field
79
- def classes
80
- self.class.classes(size: size, state: state)
81
- end
82
-
83
- # Returns the name of the method used to generate HTML for the input field
84
- def input_field_type
85
- :text_field
86
- end
87
-
88
- protected
89
-
90
- # Returns true if the field is disabled
91
- def disabled?
92
- !!@disabled
93
- end
94
-
95
- def errors?
96
- @object.errors.include?(@attribute.intern)
97
- end
98
-
99
- private
100
-
101
- # Returns the options argument for the input field
102
- def input_options
103
- {
104
- class: classes,
105
- disabled: disabled?
106
- }.merge(options)
107
- end
108
-
109
- def state
110
- return DISABLED if disabled?
111
- return ERROR if errors?
112
-
113
- DEFAULT
114
- end
115
- end
116
- end
117
- end