flowbite-components 0.1.3 → 0.1.4
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/CHANGELOG.md +16 -3
- data/README.md +34 -5
- data/app/components/flowbite/button/outline.rb +25 -10
- data/app/components/flowbite/button/pill.rb +26 -26
- data/app/components/flowbite/button.rb +33 -30
- data/app/components/flowbite/card/card.html.erb +7 -0
- data/app/components/flowbite/card/title.rb +39 -0
- data/app/components/flowbite/card.rb +56 -15
- data/app/components/flowbite/input/checkbox.rb +11 -9
- data/app/components/flowbite/input/field.rb +21 -12
- data/app/components/flowbite/input/file.rb +11 -9
- data/app/components/flowbite/input/hint.rb +10 -7
- data/app/components/flowbite/input/label.rb +14 -9
- data/app/components/flowbite/input/radio_button.rb +11 -9
- data/app/components/flowbite/input/select.rb +5 -5
- data/app/components/flowbite/input/textarea.rb +11 -9
- data/app/components/flowbite/input/validation_error.rb +31 -1
- data/app/components/flowbite/input_field/checkbox.html.erb +2 -4
- data/app/components/flowbite/input_field/checkbox.rb +8 -4
- data/app/components/flowbite/input_field/input_field.html.erb +1 -1
- data/app/components/flowbite/input_field/radio_button.html.erb +2 -4
- data/app/components/flowbite/input_field/radio_button.rb +10 -6
- data/app/components/flowbite/input_field.rb +26 -2
- data/app/components/flowbite/link.rb +41 -0
- data/app/components/flowbite/styles.rb +34 -0
- data/lib/flowbite/components/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0013a87a4e4924d4ca2fe6f3ba8eff3f9f266be23a15b07cbddd25164d436805
|
|
4
|
+
data.tar.gz: d50dd418f1403dc2375754f4b0d295c9c2d4f1a09c0904bffce88fc76268135b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e410ab1f18d6264c18cae8e5c0322c612422e33aa4136ab99ff21e6b0564ceaeb95decd262a265d72b9029022ff76965c19eeb0438d3d295c85cd2962986a3ab
|
|
7
|
+
data.tar.gz: 168b101505fbddfc952c334cc169c1e12e5f129beb8c3f884ffd32047c0548bd22655fd03a6da3589f9ff5071c94850d727761c7aacb96b2712c09420657147c
|
data/CHANGELOG.md
CHANGED
|
@@ -7,15 +7,28 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
### Added
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [0.1.4]
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
* Flowbite::Link component to render links.
|
|
20
|
+
* Flowbite::Card now displays a title via the title argument/slot.
|
|
21
|
+
* Improved error message when an unknown style is requested.
|
|
22
|
+
* Input-elements now support forms without an object; ie forms built with `form_tag` - not `form_for` or `form_with`.
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
13
25
|
|
|
14
|
-
*
|
|
26
|
+
* [BREAKING] All components now use Flowbite 4 style classes. This adds the option for easier styling, uses semantic variant names, and keeps us up to date with Flowbite proper.
|
|
27
|
+
* Extra CSS classes passed to components in the `class` argument are now added to the default classes from the component. This optimizes for minor tweaks and additions, which is likely to be the most common use case. If you need to replace all classes on the root element of the component, pass them in `options[:class]` instead.
|
|
15
28
|
|
|
16
29
|
### Removed
|
|
17
30
|
|
|
18
|
-
*
|
|
31
|
+
* [BREAKING] Color-specific styles from Flowbite::Button, ie `alternative`, `green`, `light`, `purple`, `red`, `yellow`.
|
|
19
32
|
|
|
20
33
|
|
|
21
34
|
## [0.1.3]
|
data/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Flowbite Components provides a comprehensive library of UI components following
|
|
|
22
22
|
Add the gem to your application's Gemfile:
|
|
23
23
|
|
|
24
24
|
```ruby
|
|
25
|
-
gem
|
|
25
|
+
gem "flowbite-components"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Then execute:
|
|
@@ -31,9 +31,9 @@ Then execute:
|
|
|
31
31
|
bundle install
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
###
|
|
34
|
+
### tailwindcss-rails
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Tailwind needs to be able to look through your code in order to generate the final CSS file with the class names you actually use. To allow Tailwind to find CSS class names inside flowbite-components you need to use [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) gem:
|
|
37
37
|
|
|
38
38
|
```ruby
|
|
39
39
|
gem "tailwindcss-rails", ">= 4.3.0"
|
|
@@ -44,17 +44,19 @@ gem "tailwindcss-rails", ">= 4.3.0"
|
|
|
44
44
|
Install Flowbite as an npm dependency:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
|
|
47
|
+
yarn add flowbite
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Add Flowbite to your Tailwind CSS configuration. In your `app/assets/tailwind/application.css`:
|
|
51
51
|
|
|
52
52
|
```css
|
|
53
|
-
@import "flowbite/src/themes/default";
|
|
54
53
|
@plugin "flowbite/plugin";
|
|
54
|
+
@import "flowbite/src/themes/default";
|
|
55
55
|
@import "../builds/tailwind/flowbite_components";
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
If you want to use one of the other [Flowbite themes](https://flowbite.com/docs/customize/theming/), change `@import "flowbite/src/themes/default";` accordingly.
|
|
59
|
+
|
|
58
60
|
## Usage examples
|
|
59
61
|
|
|
60
62
|
### Basic Form Field
|
|
@@ -217,6 +219,33 @@ renders
|
|
|
217
219
|
- **Outline Button**: `Flowbite::Button::Outline`
|
|
218
220
|
- **Pill Button**: `Flowbite::Button::Pill`
|
|
219
221
|
|
|
222
|
+
#### Cards
|
|
223
|
+
- **Card**: `Flowbite::Card` (default card with content and title)
|
|
224
|
+
|
|
225
|
+
#### Navigation
|
|
226
|
+
- **Link**: `Flowbite::Link` (default link styling)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
## Principles
|
|
230
|
+
|
|
231
|
+
### CSS classes are additive
|
|
232
|
+
|
|
233
|
+
Passing classes via the `class` argument to a component adds the classes to the
|
|
234
|
+
default ones instead of replacing them.
|
|
235
|
+
|
|
236
|
+
```ruby
|
|
237
|
+
render(Component.new(class: "these are added"))
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
This makes for easier customization of components, where you don't have to
|
|
241
|
+
recreate the entire classlist, ie in order to increase sizes or add margins or
|
|
242
|
+
whatever.
|
|
243
|
+
|
|
244
|
+
If you want to replace the entire class attribute for a component, pass it as part of the `options` hash, ie
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
render(Component.new(options: {class: "these replace the classes"}))
|
|
248
|
+
```
|
|
220
249
|
|
|
221
250
|
## Development
|
|
222
251
|
|
|
@@ -4,18 +4,33 @@ module Flowbite
|
|
|
4
4
|
class Button
|
|
5
5
|
class Outline < Flowbite::Button
|
|
6
6
|
class << self
|
|
7
|
-
# rubocop:disable Layout/LineLength
|
|
7
|
+
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
|
8
8
|
def styles
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
default: ["text-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
default: ["
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
Flowbite::Styles.from_hash({
|
|
10
|
+
danger: {
|
|
11
|
+
default: ["focus:outline-none", "text-danger", "bg-transparent", "box-border", "border", "border-danger", "hover:text-white", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
12
|
+
},
|
|
13
|
+
dark: {
|
|
14
|
+
default: ["focus:outline-none", "text-dark", "bg-transparent", "box-border", "border", "border-dark", "hover:text-white", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
15
|
+
},
|
|
16
|
+
default: {
|
|
17
|
+
default: ["focus:outline-none", "text-brand", "bg-transparent", "box-border", "border", "border-brand", "hover:text-white", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
18
|
+
},
|
|
19
|
+
secondary: {
|
|
20
|
+
default: ["focus:outline-none", "text-body", "bg-transparent", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
21
|
+
},
|
|
22
|
+
success: {
|
|
23
|
+
default: ["focus:outline-none", "text-success", "bg-transparent", "box-border", "border", "border-success", "hover:text-white", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
24
|
+
},
|
|
25
|
+
tertiary: {
|
|
26
|
+
default: ["focus:outline-none", "text-body", "bg-transparent", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
27
|
+
},
|
|
28
|
+
warning: {
|
|
29
|
+
default: ["focus:outline-none", "text-warning", "bg-transparent", "box-border", "border", "border-warning", "hover:text-white", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
|
|
30
|
+
}
|
|
31
|
+
}.freeze)
|
|
17
32
|
end
|
|
18
|
-
# rubocop:enable Layout/LineLength
|
|
33
|
+
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
|
19
34
|
end
|
|
20
35
|
end
|
|
21
36
|
end
|
|
@@ -6,32 +6,32 @@ module Flowbite
|
|
|
6
6
|
class << self
|
|
7
7
|
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
|
8
8
|
def styles
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
default: ["
|
|
12
|
-
|
|
13
|
-
dark:
|
|
14
|
-
default: ["text-white", "bg-
|
|
15
|
-
|
|
16
|
-
default:
|
|
17
|
-
default: ["text-white", "bg-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
default: ["text-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
default: ["text-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
default: ["text-white", "bg-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
default: ["text-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
default: ["text-white", "bg-
|
|
33
|
-
|
|
34
|
-
}
|
|
9
|
+
Flowbite::Styles.from_hash({
|
|
10
|
+
danger: {
|
|
11
|
+
default: ["focus:outline-none", "text-white", "bg-danger", "box-border", "border", "border-transparent", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
12
|
+
},
|
|
13
|
+
dark: {
|
|
14
|
+
default: ["focus:outline-none", "text-white", "bg-dark", "box-border", "border", "border-transparent", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
15
|
+
},
|
|
16
|
+
default: {
|
|
17
|
+
default: ["focus:outline-none", "text-white", "bg-brand", "box-border", "border", "border-transparent", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
18
|
+
},
|
|
19
|
+
ghost: {
|
|
20
|
+
default: ["focus:outline-none", "text-heading", "bg-transparent", "box-border", "border", "border-transparent", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
21
|
+
},
|
|
22
|
+
secondary: {
|
|
23
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
24
|
+
},
|
|
25
|
+
success: {
|
|
26
|
+
default: ["focus:outline-none", "text-white", "bg-success", "box-border", "border", "border-transparent", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
27
|
+
},
|
|
28
|
+
tertiary: {
|
|
29
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-primary-soft", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
30
|
+
},
|
|
31
|
+
warning: {
|
|
32
|
+
default: ["focus:outline-none", "text-white", "bg-warning", "box-border", "border", "border-transparent", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
|
|
33
|
+
}
|
|
34
|
+
}.freeze)
|
|
35
35
|
end
|
|
36
36
|
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
|
37
37
|
end
|
|
@@ -11,9 +11,9 @@ module Flowbite
|
|
|
11
11
|
# as HTML attributes.
|
|
12
12
|
class Button < ViewComponent::Base
|
|
13
13
|
SIZES = {
|
|
14
|
-
xs: ["text-xs", "px-3", "py-
|
|
14
|
+
xs: ["text-xs", "px-3", "py-1.5"],
|
|
15
15
|
sm: ["text-sm", "px-3", "py-2"],
|
|
16
|
-
default: ["text-sm", "px-
|
|
16
|
+
default: ["text-sm", "px-4", "py-2.5"],
|
|
17
17
|
lg: ["text-base", "px-5", "py-3"],
|
|
18
18
|
xl: ["text-base", "px-6", "py-3.5"]
|
|
19
19
|
}.freeze
|
|
@@ -31,39 +31,42 @@ module Flowbite
|
|
|
31
31
|
|
|
32
32
|
# rubocop:disable Layout/LineLength
|
|
33
33
|
def styles
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
default:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
34
|
+
Flowbite::Styles.from_hash(
|
|
35
|
+
{
|
|
36
|
+
danger: {
|
|
37
|
+
default: ["focus:outline-none", "text-white", "bg-danger", "box-border", "border", "border-transparent", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
38
|
+
},
|
|
39
|
+
dark: {
|
|
40
|
+
default: ["focus:outline-none", "text-white", "bg-dark", "box-border", "border", "border-transparent", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
41
|
+
},
|
|
42
|
+
default: {
|
|
43
|
+
default: ["focus:outline-none", "text-white", "bg-brand", "box-border", "border", "border-transparent", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
44
|
+
},
|
|
45
|
+
ghost: {
|
|
46
|
+
default: ["focus:outline-none", "text-heading", "bg-transparent", "box-border", "border", "border-transparent", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "font-medium", "leading-5", "rounded-base"]
|
|
47
|
+
},
|
|
48
|
+
secondary: {
|
|
49
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
50
|
+
},
|
|
51
|
+
success: {
|
|
52
|
+
default: ["focus:outline-none", "text-white", "bg-success", "box-border", "border", "border-transparent", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
53
|
+
},
|
|
54
|
+
tertiary: {
|
|
55
|
+
default: ["focus:outline-none", "text-body", "bg-neutral-primary-soft", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
56
|
+
},
|
|
57
|
+
warning: {
|
|
58
|
+
default: ["focus:outline-none", "text-white", "bg-warning", "box-border", "border", "border-transparent", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
|
|
59
|
+
}
|
|
60
|
+
}.freeze
|
|
61
|
+
)
|
|
60
62
|
end
|
|
61
63
|
# rubocop:enable Layout/LineLength
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
attr_reader :button_attributes, :size, :style
|
|
65
67
|
|
|
66
|
-
def initialize(size: :default, style: :default, **button_attributes)
|
|
68
|
+
def initialize(class: nil, size: :default, style: :default, **button_attributes)
|
|
69
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
67
70
|
@size = size
|
|
68
71
|
@style = style
|
|
69
72
|
@button_attributes = button_attributes
|
|
@@ -80,7 +83,7 @@ module Flowbite
|
|
|
80
83
|
private
|
|
81
84
|
|
|
82
85
|
def classes
|
|
83
|
-
self.class.classes(size: size, state: :default, style: style)
|
|
86
|
+
self.class.classes(size: size, state: :default, style: style) + @class
|
|
84
87
|
end
|
|
85
88
|
|
|
86
89
|
def options
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
class Card
|
|
5
|
+
# Renders the title of a card element.
|
|
6
|
+
class Title < ViewComponent::Base
|
|
7
|
+
class << self
|
|
8
|
+
def classes(state: :default, style: :default)
|
|
9
|
+
style = styles.fetch(style)
|
|
10
|
+
style.fetch(state)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# rubocop:disable Layout/LineLength
|
|
14
|
+
def styles
|
|
15
|
+
Flowbite::Styles.from_hash(
|
|
16
|
+
{
|
|
17
|
+
default: {
|
|
18
|
+
default: ["mb-2", "text-2xl", "font-semibold", "tracking-tight", "text-heading"]
|
|
19
|
+
}
|
|
20
|
+
}.freeze
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
# rubocop:enable Layout/LineLength
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def call
|
|
27
|
+
title_options = {
|
|
28
|
+
class: self.class.classes
|
|
29
|
+
}.merge(@options)
|
|
30
|
+
|
|
31
|
+
content_tag(:h5, content, **title_options)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def initialize(**options)
|
|
35
|
+
@options = options || {}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -5,6 +5,8 @@ module Flowbite
|
|
|
5
5
|
#
|
|
6
6
|
# See https://flowbite.com/docs/components/cards/
|
|
7
7
|
class Card < ViewComponent::Base
|
|
8
|
+
renders_one :title
|
|
9
|
+
|
|
8
10
|
class << self
|
|
9
11
|
def classes(state: :default, style: :default)
|
|
10
12
|
style = styles.fetch(style)
|
|
@@ -13,33 +15,72 @@ module Flowbite
|
|
|
13
15
|
|
|
14
16
|
# rubocop:disable Layout/LineLength
|
|
15
17
|
def styles
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
default:
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
Flowbite::Styles.from_hash(
|
|
19
|
+
{
|
|
20
|
+
default: {
|
|
21
|
+
default: ["p-6", "bg-neutral-primary-soft", "border", "border-default", "rounded-base", "shadow-xs"]
|
|
22
|
+
}
|
|
23
|
+
}.freeze
|
|
24
|
+
)
|
|
21
25
|
end
|
|
22
26
|
# rubocop:enable Layout/LineLength
|
|
23
27
|
end
|
|
24
28
|
|
|
25
|
-
def call
|
|
26
|
-
card_options = {}
|
|
27
|
-
card_options[:class] = self.class.classes + @class
|
|
28
|
-
|
|
29
|
-
content_tag(:div, card_options.merge(@options)) do
|
|
30
|
-
concat(content_tag(:div, content, class: "font-normal text-gray-700 dark:text-gray-400"))
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
29
|
# @param class [Array<String>] Additional CSS classes for the card
|
|
35
30
|
# container.
|
|
36
31
|
#
|
|
37
32
|
# @param options [Hash] Additional HTML options for the card container
|
|
38
33
|
# (e.g., custom classes, data attributes). These options are merged into
|
|
39
34
|
# the card's root element.
|
|
40
|
-
|
|
35
|
+
#
|
|
36
|
+
# @param title [Hash] An optional title for the card. If provided,
|
|
37
|
+
# it will be rendered at the top of the card in a h5 tag using the
|
|
38
|
+
# Card::Title component. The hash can contain:
|
|
39
|
+
# - `content`: The text content of the title
|
|
40
|
+
# - `options`: Additional HTML options to pass to the title element
|
|
41
|
+
# Alternatively, you can use the `title` slot to provide the entire
|
|
42
|
+
# title element yourself.
|
|
43
|
+
def initialize(class: [], options: {}, title: {})
|
|
41
44
|
@class = Array(binding.local_variable_get(:class)) || []
|
|
42
45
|
@options = options || {}
|
|
46
|
+
@title = title
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
def card_options
|
|
52
|
+
card_options = {}
|
|
53
|
+
card_options[:class] = self.class.classes + @class
|
|
54
|
+
card_options.merge(@options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns the HTML to use for the title element if any
|
|
58
|
+
def default_title
|
|
59
|
+
component = Flowbite::Card::Title.new(**default_title_options)
|
|
60
|
+
|
|
61
|
+
if default_title_content
|
|
62
|
+
component.with_content(default_title_content)
|
|
63
|
+
else
|
|
64
|
+
component
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
render(component)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def default_title_content
|
|
71
|
+
return nil unless @title
|
|
72
|
+
|
|
73
|
+
@title[:content]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @return [Hash] The options to pass to the default title component
|
|
77
|
+
def default_title_options
|
|
78
|
+
title_options = @title.dup
|
|
79
|
+
title_options[:options] || {}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def title?
|
|
83
|
+
@title.present?
|
|
43
84
|
end
|
|
44
85
|
end
|
|
45
86
|
end
|
|
@@ -22,13 +22,15 @@ module Flowbite
|
|
|
22
22
|
|
|
23
23
|
# rubocop:disable Layout/LineLength
|
|
24
24
|
def styles
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
default:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
Flowbite::Styles.from_hash(
|
|
26
|
+
{
|
|
27
|
+
default: {
|
|
28
|
+
default: ["text-brand", "bg-neutral-secondary-medium", "border-default-medium", "rounded-sm", "focus:ring-brand", "focus:ring-2"],
|
|
29
|
+
disabled: ["text-brand", "bg-neutral-secondary-medium", "border-default-medium", "rounded-sm", "focus:ring-brand", "focus:ring-2", "cursor-not-allowed"],
|
|
30
|
+
error: ["text-danger", "bg-danger-soft", "border-danger-subtle", "rounded-sm", "focus:ring-danger", "focus:ring-2"]
|
|
31
|
+
}
|
|
32
|
+
}.freeze
|
|
33
|
+
)
|
|
32
34
|
end
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -43,8 +45,8 @@ module Flowbite
|
|
|
43
45
|
)
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
def initialize(attribute:, form:, disabled: false, options: {}, size: :default, unchecked_value: DEFAULT_UNCHECKED_VALUE, value: DEFAULT_CHECKED_VALUE)
|
|
47
|
-
super(attribute: attribute, form: form, disabled: disabled, options: options, size: size)
|
|
48
|
+
def initialize(attribute:, form:, class: nil, disabled: false, options: {}, size: :default, unchecked_value: DEFAULT_UNCHECKED_VALUE, value: DEFAULT_CHECKED_VALUE)
|
|
49
|
+
super(attribute: attribute, class: binding.local_variable_get(:class), form: form, disabled: disabled, options: options, size: size)
|
|
48
50
|
@unchecked_value = unchecked_value
|
|
49
51
|
@value = value
|
|
50
52
|
end
|
|
@@ -13,9 +13,9 @@ module Flowbite
|
|
|
13
13
|
# `Flowbite::InputField` instead.
|
|
14
14
|
class Field < ViewComponent::Base
|
|
15
15
|
SIZES = {
|
|
16
|
-
sm: ["
|
|
17
|
-
default: ["
|
|
18
|
-
lg: ["
|
|
16
|
+
sm: ["px-2.5", "py-2", "text-sm"],
|
|
17
|
+
default: ["px-3", "py-2.5", "text-sm"],
|
|
18
|
+
lg: ["px-3.5", "py-3", "text-base"]
|
|
19
19
|
}.freeze
|
|
20
20
|
|
|
21
21
|
STATES = [
|
|
@@ -46,19 +46,22 @@ module Flowbite
|
|
|
46
46
|
|
|
47
47
|
# rubocop:disable Layout/LineLength
|
|
48
48
|
def styles
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
default:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
Flowbite::Styles.from_hash(
|
|
50
|
+
{
|
|
51
|
+
default: {
|
|
52
|
+
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"],
|
|
53
|
+
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"],
|
|
54
|
+
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"]
|
|
55
|
+
}
|
|
56
|
+
}.freeze
|
|
57
|
+
)
|
|
56
58
|
end
|
|
57
59
|
# rubocop:enable Layout/LineLength
|
|
58
60
|
end
|
|
59
61
|
|
|
60
|
-
def initialize(attribute:, form:, disabled: false, options: {}, size: :default)
|
|
62
|
+
def initialize(attribute:, form:, class: nil, disabled: false, options: {}, size: :default)
|
|
61
63
|
@attribute = attribute
|
|
64
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
62
65
|
@disabled = disabled
|
|
63
66
|
@form = form
|
|
64
67
|
@options = options || {}
|
|
@@ -77,7 +80,7 @@ module Flowbite
|
|
|
77
80
|
|
|
78
81
|
# Returns the CSS classes to apply to the input field
|
|
79
82
|
def classes
|
|
80
|
-
self.class.classes(size: size, state: state)
|
|
83
|
+
self.class.classes(size: size, state: state) + @class
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
# Returns the name of the method used to generate HTML for the input field
|
|
@@ -92,7 +95,13 @@ module Flowbite
|
|
|
92
95
|
!!@disabled
|
|
93
96
|
end
|
|
94
97
|
|
|
98
|
+
# Returns true if the object has errors. Returns false if there is no
|
|
99
|
+
# object.
|
|
100
|
+
#
|
|
101
|
+
# @return [Boolean] true if there are errors, false otherwise.
|
|
95
102
|
def errors?
|
|
103
|
+
return false unless @object
|
|
104
|
+
|
|
96
105
|
@object.errors.include?(@attribute.intern)
|
|
97
106
|
end
|
|
98
107
|
|
|
@@ -4,9 +4,9 @@ module Flowbite
|
|
|
4
4
|
module Input
|
|
5
5
|
class File < Field
|
|
6
6
|
SIZES = {
|
|
7
|
-
sm: ["text-
|
|
7
|
+
sm: ["text-sm"],
|
|
8
8
|
default: ["text-sm"],
|
|
9
|
-
lg: ["text-
|
|
9
|
+
lg: ["text-base"]
|
|
10
10
|
}.freeze
|
|
11
11
|
|
|
12
12
|
# Returns the name of the method used to generate HTML for the input field
|
|
@@ -16,13 +16,15 @@ module Flowbite
|
|
|
16
16
|
|
|
17
17
|
# rubocop:disable Layout/LineLength
|
|
18
18
|
def self.styles
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
default:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
Flowbite::Styles.from_hash(
|
|
20
|
+
{
|
|
21
|
+
default: {
|
|
22
|
+
default: ["block", "w-full", "text-heading", "border", "border-default-medium", "rounded-base", "cursor-pointer", "bg-neutral-secondary-medium", "focus:outline-none"],
|
|
23
|
+
disabled: ["block", "w-full", "text-fg-disabled", "border", "border-default-medium", "rounded-base", "cursor-not-allowed", "bg-neutral-secondary-medium"],
|
|
24
|
+
error: ["block", "w-full", "text-fg-danger-strong", "border", "border-danger-subtle", "rounded-base", "cursor-pointer", "bg-danger-soft", "focus:outline-none"]
|
|
25
|
+
}
|
|
26
|
+
}.freeze
|
|
27
|
+
)
|
|
26
28
|
end
|
|
27
29
|
# rubocop:enable Layout/LineLength
|
|
28
30
|
end
|
|
@@ -14,11 +14,13 @@ module Flowbite
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def styles
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
default:
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
Flowbite::Styles.from_hash(
|
|
18
|
+
{
|
|
19
|
+
default: {
|
|
20
|
+
default: ["mt-2.5", "text-sm", "text-body"]
|
|
21
|
+
}
|
|
22
|
+
}.freeze
|
|
23
|
+
)
|
|
22
24
|
end
|
|
23
25
|
end
|
|
24
26
|
|
|
@@ -30,8 +32,9 @@ module Flowbite
|
|
|
30
32
|
)
|
|
31
33
|
end
|
|
32
34
|
|
|
33
|
-
def initialize(attribute:, form:, options: {})
|
|
35
|
+
def initialize(attribute:, form:, class: nil, options: {})
|
|
34
36
|
@attribute = attribute
|
|
37
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
35
38
|
@form = form
|
|
36
39
|
@options = options
|
|
37
40
|
@object = form.object
|
|
@@ -39,7 +42,7 @@ module Flowbite
|
|
|
39
42
|
|
|
40
43
|
# Returns an array with the CSS classes to apply to the label element
|
|
41
44
|
def classes
|
|
42
|
-
self.class.classes(state: state)
|
|
45
|
+
self.class.classes(state: state) + @class
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
protected
|
|
@@ -17,13 +17,15 @@ module Flowbite
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def styles
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
default:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
Flowbite::Styles.from_hash(
|
|
21
|
+
{
|
|
22
|
+
default: {
|
|
23
|
+
default: ["block", "mb-2.5", "text-sm", "font-medium", "text-heading"],
|
|
24
|
+
disabled: ["block", "mb-2.5", "text-sm", "font-medium", "text-fg-disabled"],
|
|
25
|
+
error: ["block", "mb-2.5", "text-sm", "font-medium", "text-fg-danger-strong"]
|
|
26
|
+
}
|
|
27
|
+
}.freeze
|
|
28
|
+
)
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
@@ -36,11 +38,14 @@ module Flowbite
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
def errors?
|
|
41
|
+
return false unless @object
|
|
42
|
+
|
|
39
43
|
@object.errors.include?(@attribute.intern)
|
|
40
44
|
end
|
|
41
45
|
|
|
42
|
-
def initialize(attribute:, form:, disabled: false, options: {})
|
|
46
|
+
def initialize(attribute:, form:, class: nil, disabled: false, options: {})
|
|
43
47
|
@attribute = attribute
|
|
48
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
44
49
|
@disabled = disabled
|
|
45
50
|
@form = form
|
|
46
51
|
@object = form.object
|
|
@@ -49,7 +54,7 @@ module Flowbite
|
|
|
49
54
|
|
|
50
55
|
# Returns an array with the CSS classes to apply to the label element
|
|
51
56
|
def classes
|
|
52
|
-
self.class.classes(state: state)
|
|
57
|
+
self.class.classes(state: state) + @class
|
|
53
58
|
end
|
|
54
59
|
|
|
55
60
|
protected
|
|
@@ -17,13 +17,15 @@ module Flowbite
|
|
|
17
17
|
|
|
18
18
|
# rubocop:disable Layout/LineLength
|
|
19
19
|
def styles
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
default:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
Flowbite::Styles.from_hash(
|
|
21
|
+
{
|
|
22
|
+
default: {
|
|
23
|
+
default: ["text-brand", "bg-neutral-secondary-medium", "border-default-medium", "focus:ring-brand", "focus:ring-2"],
|
|
24
|
+
disabled: ["text-brand", "bg-neutral-secondary-medium", "border-default-medium", "focus:ring-brand", "focus:ring-2", "cursor-not-allowed"],
|
|
25
|
+
error: ["text-danger", "bg-danger-soft", "border-danger-subtle", "focus:ring-danger", "focus:ring-2"]
|
|
26
|
+
}
|
|
27
|
+
}.freeze
|
|
28
|
+
)
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
@@ -37,8 +39,8 @@ module Flowbite
|
|
|
37
39
|
)
|
|
38
40
|
end
|
|
39
41
|
|
|
40
|
-
def initialize(attribute:, form:, value:, disabled: false, options: {})
|
|
41
|
-
super(attribute: attribute, disabled: disabled, form: form, options: options)
|
|
42
|
+
def initialize(attribute:, form:, value:, class: nil, disabled: false, options: {})
|
|
43
|
+
super(attribute: attribute, class: binding.local_variable_get(:class), disabled: disabled, form: form, options: options)
|
|
42
44
|
@value = value
|
|
43
45
|
end
|
|
44
46
|
|
|
@@ -9,13 +9,13 @@ module Flowbite
|
|
|
9
9
|
# Wraps `ActionView::Helpers::FormOptionsHelper#select`: https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select
|
|
10
10
|
class Select < Field
|
|
11
11
|
SIZES = {
|
|
12
|
-
sm: ["
|
|
13
|
-
default: ["
|
|
14
|
-
lg: ["px-
|
|
12
|
+
sm: ["px-2.5", "py-2", "text-sm"],
|
|
13
|
+
default: ["px-3", "py-2.5", "text-sm"],
|
|
14
|
+
lg: ["px-3.5", "py-3", "text-base"]
|
|
15
15
|
}.freeze
|
|
16
16
|
|
|
17
|
-
def initialize(form:, attribute:, collection: [], disabled: false, include_blank: false, multiple: false, options: {}, size: :default)
|
|
18
|
-
super(form: form, attribute: attribute, disabled: disabled, options: options, size: size)
|
|
17
|
+
def initialize(form:, attribute:, class: nil, collection: [], disabled: false, include_blank: false, multiple: false, options: {}, size: :default)
|
|
18
|
+
super(form: form, attribute: attribute, class: binding.local_variable_get(:class), disabled: disabled, options: options, size: size)
|
|
19
19
|
@collection = collection
|
|
20
20
|
@include_blank = include_blank
|
|
21
21
|
@multiple = multiple
|
|
@@ -6,16 +6,18 @@ module Flowbite
|
|
|
6
6
|
class << self
|
|
7
7
|
# rubocop:disable Layout/LineLength
|
|
8
8
|
def styles
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
default:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
Flowbite::Styles.from_hash(
|
|
10
|
+
{
|
|
11
|
+
default: {
|
|
12
|
+
default: ["block", "w-full", "text-heading", "bg-neutral-secondary-medium", "rounded-base", "border", "border-default-medium", "focus:ring-brand", "focus:border-brand", "shadow-xs", "placeholder:text-body"],
|
|
13
|
+
disabled: ["block", "w-full", "bg-neutral-secondary-medium", "rounded-base", "border", "border-default-medium", "text-fg-disabled", "cursor-not-allowed", "shadow-xs", "placeholder:text-fg-disabled"],
|
|
14
|
+
error: ["block", "w-full", "bg-danger-soft", "border", "border-danger-subtle", "text-fg-danger-strong", "placeholder:text-fg-danger-strong", "rounded-base", "focus:ring-danger", "focus:border-danger", "shadow-xs"]
|
|
15
|
+
}
|
|
16
|
+
}.freeze
|
|
17
|
+
)
|
|
16
18
|
end
|
|
17
|
-
# rubocop:enable Layout/LineLength
|
|
18
19
|
end
|
|
20
|
+
# rubocop:enable Layout/LineLength
|
|
19
21
|
|
|
20
22
|
# Returns the HTML to use for the actual input field element.
|
|
21
23
|
def call
|
|
@@ -30,7 +32,7 @@ module Flowbite
|
|
|
30
32
|
|
|
31
33
|
# Returns the CSS classes to apply to the input field
|
|
32
34
|
def classes
|
|
33
|
-
self.class.classes(size: size, state: state)
|
|
35
|
+
self.class.classes(size: size, state: state) + @class
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
# Returns the name of the method used to generate HTML for the input field
|
|
@@ -3,8 +3,38 @@
|
|
|
3
3
|
module Flowbite
|
|
4
4
|
module Input
|
|
5
5
|
class ValidationError < ViewComponent::Base
|
|
6
|
+
class << self
|
|
7
|
+
def classes(state: :default, style: :default)
|
|
8
|
+
style = styles.fetch(style)
|
|
9
|
+
style.fetch(state)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# rubocop:disable Layout/LineLength
|
|
13
|
+
def styles
|
|
14
|
+
Flowbite::Styles.from_hash(
|
|
15
|
+
{
|
|
16
|
+
default: {
|
|
17
|
+
default: ["mt-2", "text-sm", "text-red-600", "dark:text-red-500"]
|
|
18
|
+
}
|
|
19
|
+
}.freeze
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
# rubocop:enable Layout/LineLength
|
|
23
|
+
end
|
|
24
|
+
|
|
6
25
|
def call
|
|
7
|
-
tag.p(content, class:
|
|
26
|
+
tag.p(content, class: classes)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize(class: nil)
|
|
30
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
protected
|
|
34
|
+
|
|
35
|
+
# Returns the CSS classes to apply to the validation error
|
|
36
|
+
def classes
|
|
37
|
+
self.class.classes + @class
|
|
8
38
|
end
|
|
9
39
|
end
|
|
10
40
|
end
|
|
@@ -5,6 +5,10 @@ module Flowbite
|
|
|
5
5
|
class Checkbox < InputField
|
|
6
6
|
protected
|
|
7
7
|
|
|
8
|
+
def default_container_classes
|
|
9
|
+
["flex"]
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
def default_hint_options
|
|
9
13
|
return {} unless @hint
|
|
10
14
|
|
|
@@ -29,9 +33,9 @@ module Flowbite
|
|
|
29
33
|
|
|
30
34
|
def hint_classes
|
|
31
35
|
if disabled?
|
|
32
|
-
"text-xs font-normal text-
|
|
36
|
+
"text-xs font-normal text-fg-disabled"
|
|
33
37
|
else
|
|
34
|
-
"text-xs font-normal text-
|
|
38
|
+
"text-xs font-normal text-body"
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
|
|
@@ -44,9 +48,9 @@ module Flowbite
|
|
|
44
48
|
|
|
45
49
|
def label_classes
|
|
46
50
|
if disabled?
|
|
47
|
-
"font-medium text-
|
|
51
|
+
"font-medium text-fg-disabled"
|
|
48
52
|
else
|
|
49
|
-
"font-medium text-
|
|
53
|
+
"font-medium text-heading"
|
|
50
54
|
end
|
|
51
55
|
end
|
|
52
56
|
end
|
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
module Flowbite
|
|
4
4
|
class InputField
|
|
5
5
|
class RadioButton < InputField
|
|
6
|
-
def initialize(attribute:, form:, value:, disabled: false, hint: nil, input: {}, label: {})
|
|
7
|
-
super(attribute: attribute, form: form, disabled: disabled, hint: hint, input: input, label: label)
|
|
6
|
+
def initialize(attribute:, form:, value:, class: nil, disabled: false, hint: nil, input: {}, label: {}, options: {})
|
|
7
|
+
super(attribute: attribute, class: binding.local_variable_get(:class), form: form, disabled: disabled, hint: hint, input: input, label: label, options: options)
|
|
8
8
|
@value = value
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
protected
|
|
12
12
|
|
|
13
|
+
def default_container_classes
|
|
14
|
+
["flex"]
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
def default_input
|
|
14
18
|
args = {
|
|
15
19
|
attribute: @attribute,
|
|
@@ -56,9 +60,9 @@ module Flowbite
|
|
|
56
60
|
|
|
57
61
|
def hint_classes
|
|
58
62
|
if disabled?
|
|
59
|
-
"text-xs font-normal text-
|
|
63
|
+
"text-xs font-normal text-fg-disabled"
|
|
60
64
|
else
|
|
61
|
-
"text-xs font-normal text-
|
|
65
|
+
"text-xs font-normal text-body"
|
|
62
66
|
end
|
|
63
67
|
end
|
|
64
68
|
|
|
@@ -76,9 +80,9 @@ module Flowbite
|
|
|
76
80
|
|
|
77
81
|
def label_classes
|
|
78
82
|
if disabled?
|
|
79
|
-
"font-medium text-
|
|
83
|
+
"font-medium text-fg-disabled"
|
|
80
84
|
else
|
|
81
|
-
"font-medium text-
|
|
85
|
+
"font-medium text-heading"
|
|
82
86
|
end
|
|
83
87
|
end
|
|
84
88
|
end
|
|
@@ -67,18 +67,24 @@ module Flowbite
|
|
|
67
67
|
renders_one :label
|
|
68
68
|
|
|
69
69
|
# Returns the errors for attribute
|
|
70
|
+
#
|
|
71
|
+
# @return [Array<String>] An array of error messages for the attribute.
|
|
70
72
|
def errors
|
|
73
|
+
return [] unless @object
|
|
74
|
+
|
|
71
75
|
@object.errors[@attribute] || []
|
|
72
76
|
end
|
|
73
77
|
|
|
74
|
-
def initialize(attribute:, form:, disabled: false, hint: nil, input: {}, label: {}, size: :default)
|
|
78
|
+
def initialize(attribute:, form:, class: nil, disabled: false, hint: nil, input: {}, label: {}, options: {}, size: :default)
|
|
75
79
|
@attribute = attribute
|
|
80
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
76
81
|
@disabled = disabled
|
|
77
82
|
@form = form
|
|
78
83
|
@hint = hint
|
|
79
84
|
@input = input
|
|
80
85
|
@label = label
|
|
81
86
|
@object = form.object
|
|
87
|
+
@options = options || {}
|
|
82
88
|
@size = size
|
|
83
89
|
end
|
|
84
90
|
|
|
@@ -88,6 +94,18 @@ module Flowbite
|
|
|
88
94
|
|
|
89
95
|
protected
|
|
90
96
|
|
|
97
|
+
def classes
|
|
98
|
+
if @options[:class]
|
|
99
|
+
Array.wrap(@options[:class])
|
|
100
|
+
else
|
|
101
|
+
[default_container_classes, @class].flatten.compact
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def default_container_classes
|
|
106
|
+
[]
|
|
107
|
+
end
|
|
108
|
+
|
|
91
109
|
# Returns the HTML to use for the hint element if any
|
|
92
110
|
def default_hint
|
|
93
111
|
return unless hint?
|
|
@@ -171,7 +189,13 @@ module Flowbite
|
|
|
171
189
|
end
|
|
172
190
|
|
|
173
191
|
def id_for_hint_element
|
|
174
|
-
|
|
192
|
+
[
|
|
193
|
+
@form.object_name,
|
|
194
|
+
@attribute,
|
|
195
|
+
"hint"
|
|
196
|
+
]
|
|
197
|
+
.compact_blank
|
|
198
|
+
.join("_")
|
|
175
199
|
end
|
|
176
200
|
|
|
177
201
|
# @return [Hash] The keyword arguments for the input component.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flowbite
|
|
4
|
+
# The link component can be used to set hyperlinks from one page to another or
|
|
5
|
+
# to an external website when clicking on an inline text item, button, or card
|
|
6
|
+
#
|
|
7
|
+
# Use this component to add default styles to an inline link element.
|
|
8
|
+
class Link < ViewComponent::Base
|
|
9
|
+
attr_reader :href, :options
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def classes
|
|
13
|
+
["font-medium", "text-fg-brand", "hover:underline"]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Initialize the Link component.
|
|
18
|
+
#
|
|
19
|
+
# @param href What to link to. This can be a String or anything else that
|
|
20
|
+
# `link_to` supports. See `ActionView::Helpers::UrlHelper#link_to` for more
|
|
21
|
+
# details.
|
|
22
|
+
#
|
|
23
|
+
# @param options [Hash] Additional HTML options for the link element
|
|
24
|
+
def initialize(href:, class: nil, **options)
|
|
25
|
+
super()
|
|
26
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
27
|
+
@href = href
|
|
28
|
+
@options = options
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def call
|
|
32
|
+
link_to(content, href, {class: classes}.merge(options))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def classes
|
|
38
|
+
self.class.classes + @class
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -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
|
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.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jakob Skjerning
|
|
@@ -39,6 +39,8 @@ files:
|
|
|
39
39
|
- app/components/flowbite/button/outline.rb
|
|
40
40
|
- app/components/flowbite/button/pill.rb
|
|
41
41
|
- app/components/flowbite/card.rb
|
|
42
|
+
- app/components/flowbite/card/card.html.erb
|
|
43
|
+
- app/components/flowbite/card/title.rb
|
|
42
44
|
- app/components/flowbite/input/checkbox.rb
|
|
43
45
|
- app/components/flowbite/input/date.rb
|
|
44
46
|
- app/components/flowbite/input/email.rb
|
|
@@ -70,7 +72,9 @@ files:
|
|
|
70
72
|
- app/components/flowbite/input_field/text.rb
|
|
71
73
|
- app/components/flowbite/input_field/textarea.rb
|
|
72
74
|
- app/components/flowbite/input_field/url.rb
|
|
75
|
+
- app/components/flowbite/link.rb
|
|
73
76
|
- app/components/flowbite/style.rb
|
|
77
|
+
- app/components/flowbite/styles.rb
|
|
74
78
|
- lib/flowbite/components.rb
|
|
75
79
|
- lib/flowbite/components/engine.rb
|
|
76
80
|
- lib/flowbite/components/version.rb
|