f_components 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +144 -0
- data/Rakefile +20 -0
- data/app/components/f_components/avatar/component.html.erb +1 -0
- data/app/components/f_components/avatar/component.rb +30 -0
- data/app/components/f_components/avatar/component.scss +3 -0
- data/app/components/f_components/base.rb +14 -0
- data/app/components/f_components/button/component.html.erb +5 -0
- data/app/components/f_components/button/component.rb +68 -0
- data/app/components/f_components/button/component.scss +9 -0
- data/app/components/f_components/collapsible/component.html.erb +6 -0
- data/app/components/f_components/collapsible/component.rb +15 -0
- data/app/components/f_components/collapsible/component.scss +19 -0
- data/app/components/f_components/dropdown/component.html.erb +10 -0
- data/app/components/f_components/dropdown/component.rb +19 -0
- data/app/components/f_components/dropdown/component.scss +10 -0
- data/app/components/f_components/form_field/component.html.erb +25 -0
- data/app/components/f_components/form_field/component.rb +124 -0
- data/app/components/f_components/resource_table/component.html.erb +17 -0
- data/app/components/f_components/resource_table/component.rb +139 -0
- data/app/components/f_components/table/component.html.erb +23 -0
- data/app/components/f_components/table/component.rb +88 -0
- data/app/components/f_components/table/component_controller.js +84 -0
- data/app/components/f_components/table/desktop/component.html.erb +25 -0
- data/app/components/f_components/table/desktop/component.rb +71 -0
- data/app/components/f_components/table/mobile/component.html.erb +8 -0
- data/app/components/f_components/table/mobile/component.rb +102 -0
- data/app/frontend/f_components/stylesheets/blocks/_button.scss +189 -0
- data/app/frontend/f_components/stylesheets/f_components.scss +12 -0
- data/app/frontend/f_components/stylesheets/variables/_breakpoints.scss +3 -0
- data/app/frontend/f_components/stylesheets/variables/_colors.scss +19 -0
- data/app/helpers/f_components/application_helper.rb +13 -0
- data/app/helpers/f_components/components_helper.rb +33 -0
- data/app/helpers/f_components/icons_helper.rb +34 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +7 -0
- data/config/webpacker.yml +89 -0
- data/lib/f_components/engine.rb +28 -0
- data/lib/f_components/railtie.rb +12 -0
- data/lib/f_components/version.rb +5 -0
- data/lib/f_components.rb +18 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 23b88d28e2e9948702351020207b6aff6fddbd01e54e9f4ebfdb0532e08eee06
|
4
|
+
data.tar.gz: 90a0556f1bd62124ba52d0643cdd8274e6512f23e65bbabbdab239126f67d65c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db56d7fc4a18a99bac2bc3d70b650f1eb49df41dfd4305de745fa3f285c13673ac14a482db220349eee6d2e7820f31d5fbc016b539946befd67235210f1c3568
|
7
|
+
data.tar.gz: 7a0d5d29de3e02f3ca7478477480fa65ea8ee68cc146d368a7e8d7f01fd3135bdba968e5846c1e340b328dc46ebfbfab6bf9d6c2fc31f56055fd3b8d0a06749f
|
data/README.md
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# FComponents
|
2
|
+
|
3
|
+
A library to share essential frontend components among applications.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'f_components', git: 'git@gitlab.com:fretadao/libs/f_components.git'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
This will allow the application to have access to view components classes and helpers.
|
20
|
+
|
21
|
+
Add this line to dependencies in your package.json file:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
"f_components": "git+ssh://git@gitlab.com:fretadao/libs/f_components.git",
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
$ yarn
|
31
|
+
```
|
32
|
+
|
33
|
+
This will allow the application to apply the packed stylesheets and JavaScript from the library into your application. It's up to you chose whether it is convenient to be imported by sprockets or Webpacker.
|
34
|
+
|
35
|
+
### Sprockets
|
36
|
+
|
37
|
+
#### Sass
|
38
|
+
|
39
|
+
If you're using sprockets as the main asset packing system, you may create a file sass with the following configurations:
|
40
|
+
|
41
|
+
`app/assets/stylesheets/f_components.scss`:
|
42
|
+
|
43
|
+
```scss
|
44
|
+
$fc-clr-primary: <app primary color>;
|
45
|
+
$fc-clr-primary--dk: <app primary color dark>;
|
46
|
+
$fc-clr-secondary: <app secondary color>;
|
47
|
+
$fc-clr-secondary--dk: <app secondary color dark>;
|
48
|
+
|
49
|
+
$fc-clr-text: <app primary text color>;
|
50
|
+
$fc-clr-text-secondary: <app secondary text color>;
|
51
|
+
|
52
|
+
$fc-clr-success: <app success color>;
|
53
|
+
$fc-clr-warning: <app warning color>;
|
54
|
+
$fc-clr-error: <app error color>;
|
55
|
+
|
56
|
+
$fc-clr-disabled: <app disabled color>;
|
57
|
+
$fc-clr-border: <app border color>;
|
58
|
+
|
59
|
+
$fc-clr-background: <app background color>;
|
60
|
+
|
61
|
+
@import 'f_components/app/frontend/f_components/stylesheets/f_components';
|
62
|
+
```
|
63
|
+
|
64
|
+
After creating the file you may import it in your `app/assets/stylesheets/application.scss` :
|
65
|
+
|
66
|
+
```scss
|
67
|
+
@import 'f_components';
|
68
|
+
```
|
69
|
+
|
70
|
+
### Webpacker
|
71
|
+
|
72
|
+
#### Sass
|
73
|
+
|
74
|
+
If you're using webpacker as the main asset packing system, you may create a file sass with the following configurations:
|
75
|
+
|
76
|
+
`app/javascripts/stylesheets/f_components.scss`:
|
77
|
+
|
78
|
+
```scss
|
79
|
+
$fc-clr-primary: <app-primary-color>;
|
80
|
+
$fc-clr-primary--dk: <app-primary-color-dark>;
|
81
|
+
$fc-clr-secondary: <app-secondary-color>;
|
82
|
+
$fc-clr-secondary--dk: <app-secondary-color-dark>;
|
83
|
+
|
84
|
+
$fc-clr-text: <app-primary-text-color>;
|
85
|
+
$fc-clr-text-secondary: <app-secondary-text-color>;
|
86
|
+
|
87
|
+
$fc-clr-success: <app-success-color>;
|
88
|
+
$fc-clr-warning: <app-warning-color>;
|
89
|
+
$fc-clr-error: <app-error-color>;
|
90
|
+
|
91
|
+
$fc-clr-disabled: <app-disabled-color>;
|
92
|
+
$fc-clr-border: <app-border-color>;
|
93
|
+
|
94
|
+
$fc-clr-background: <app-background-color>;
|
95
|
+
|
96
|
+
@import 'f_components/app/frontend/f_components/stylesheets/f_components';
|
97
|
+
```
|
98
|
+
|
99
|
+
After creating the file you may import it in your `app/javascripts/packs/application.js` :
|
100
|
+
|
101
|
+
```javascript
|
102
|
+
import '../stylesheets/f_components';
|
103
|
+
```
|
104
|
+
|
105
|
+
Some components have Stimulus controllers, so you'll have to import them too:
|
106
|
+
|
107
|
+
```javascript
|
108
|
+
import {Application} from 'stimulus';
|
109
|
+
import {TableComponentController} from 'f_components'; // Import controllers
|
110
|
+
|
111
|
+
const application = Application.start();
|
112
|
+
|
113
|
+
// Register the controllers. Please, keep the same naming. Otherwise, components won't work!
|
114
|
+
application.register('f-table-component', TableComponentController);
|
115
|
+
|
116
|
+
export {application};
|
117
|
+
```
|
118
|
+
|
119
|
+
## Development
|
120
|
+
|
121
|
+
### Previews
|
122
|
+
|
123
|
+
To preview components access the dummy app:
|
124
|
+
|
125
|
+
```bash
|
126
|
+
$ cd fretadao
|
127
|
+
```
|
128
|
+
|
129
|
+
Run the servers (using docker):
|
130
|
+
|
131
|
+
```bash
|
132
|
+
$ rake docker:dev:f_components
|
133
|
+
```
|
134
|
+
|
135
|
+
Run the tests (using docker):
|
136
|
+
|
137
|
+
```bash
|
138
|
+
$ rake docker:bash:f_components
|
139
|
+
|
140
|
+
# inside the container:
|
141
|
+
$ rspec
|
142
|
+
```
|
143
|
+
|
144
|
+
Now just access `localhost:3030/previews` and see the components.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
6
|
+
load 'rails/tasks/engine.rake'
|
7
|
+
|
8
|
+
load 'rails/tasks/statistics.rake'
|
9
|
+
|
10
|
+
require 'bundler/gem_tasks'
|
11
|
+
|
12
|
+
require 'rake/testtask'
|
13
|
+
|
14
|
+
Rake::TestTask.new(:test) do |t|
|
15
|
+
t.libs << 'test'
|
16
|
+
t.pattern = 'test/**/*_test.rb'
|
17
|
+
t.verbose = false
|
18
|
+
end
|
19
|
+
|
20
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= tag.img(src: image_url, class: class_names('Avatar', @class), loading: :lazy, width: size, height: size) %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FComponents
|
4
|
+
module Avatar
|
5
|
+
class Component < Base
|
6
|
+
def initialize(opts = {})
|
7
|
+
@class = opts.delete(:class) { '' }
|
8
|
+
@opts = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def image_url
|
14
|
+
"https://ui-avatars.com/api/?#{params}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def params
|
18
|
+
default_options.merge(@opts).to_query
|
19
|
+
end
|
20
|
+
|
21
|
+
def size
|
22
|
+
@opts.fetch(:size, 64)
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_options
|
26
|
+
{ bold: true }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FComponents
|
4
|
+
module Button
|
5
|
+
class Component < FComponents::Base
|
6
|
+
TYPE_CLASSES = {
|
7
|
+
primary: 'bt--primary',
|
8
|
+
secondary: 'bt--primary bt--outlined',
|
9
|
+
tertiary: 'bt--tertiary',
|
10
|
+
custom: ''
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
MODIFIERS = {
|
14
|
+
success: 'bt--success',
|
15
|
+
secondary: 'bt--secondary',
|
16
|
+
error: 'bt--error',
|
17
|
+
white: 'bt--white',
|
18
|
+
warning: 'bt--warning',
|
19
|
+
fit: 'w--fit max-w--fit',
|
20
|
+
full: 'bt--full',
|
21
|
+
outlined: 'bt--outlined',
|
22
|
+
small: 'bt--smr',
|
23
|
+
large: 'bt--lg',
|
24
|
+
centered: 'mx--auto'
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
MODS = MODIFIERS.to_h.deep_dup
|
28
|
+
MODS.default_proc = proc { |_hash, key| "bt--#{key}" }
|
29
|
+
|
30
|
+
attr_reader :href, :options
|
31
|
+
|
32
|
+
def initialize(title, href = nil, **options)
|
33
|
+
@title = title
|
34
|
+
@href = href || 'javascript: void(0);'
|
35
|
+
@modifiers = options.delete(:mods)
|
36
|
+
@type = options.delete(:type) || :primary
|
37
|
+
@tag = options.delete(:tag) || :a
|
38
|
+
@class = options.delete(:class) || ''
|
39
|
+
@left_icon = options.delete(:left_icon)
|
40
|
+
@options = options
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def button_tag?
|
46
|
+
@tag == :button
|
47
|
+
end
|
48
|
+
|
49
|
+
def title
|
50
|
+
@left_icon.present? ? fa_icon(@left_icon, class: 'bt-leftIcon', text: @title) : @title
|
51
|
+
end
|
52
|
+
|
53
|
+
def classes
|
54
|
+
"bt bt--round #{button_type_class} #{modifiers} #{@class}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def button_type_class
|
58
|
+
raise 'Unkown button type' unless TYPE_CLASSES.has_key?(@type)
|
59
|
+
|
60
|
+
TYPE_CLASSES[@type]
|
61
|
+
end
|
62
|
+
|
63
|
+
def modifiers
|
64
|
+
MODS.values_at(*@modifiers).compact.join(' ')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FComponents
|
4
|
+
module Collapsible
|
5
|
+
class Component < Base
|
6
|
+
attributes :summary, class: nil
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def formatted_summary
|
11
|
+
tag.div(class: 'flex space-x-5 justify-start items-center max-w-full') { summary }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
.Collapsible > summary {
|
2
|
+
list-style-type: none;
|
3
|
+
}
|
4
|
+
|
5
|
+
.Collapsible > summary::-webkit-details-marker {
|
6
|
+
display: none;
|
7
|
+
}
|
8
|
+
|
9
|
+
.Collapsible > summary::after {
|
10
|
+
font-family: "Font Awesome 5 Free";
|
11
|
+
font-weight: 900;
|
12
|
+
content: "\f078";
|
13
|
+
}
|
14
|
+
|
15
|
+
.Collapsible[open] > summary::after {
|
16
|
+
font-family: "Font Awesome 5 Free";
|
17
|
+
font-weight: 900;
|
18
|
+
content: "\f077";
|
19
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<details class="Dropdown h-10 w-full bg-white rounded border-2 border-gray-lt open:border-primary <%= @class %>">
|
2
|
+
<summary class="Dropdown-label px-5 h-full flex items-center cursor-pointer <%= @label_class %>">
|
3
|
+
<%= icon %>
|
4
|
+
<%= label %>
|
5
|
+
</summary>
|
6
|
+
|
7
|
+
<div class="relative shadow-md rounded bg-white z-10 mt-1 md:inset-auto <%= padding_class %> <%= content_class %>">
|
8
|
+
<%= content %>
|
9
|
+
</div>
|
10
|
+
</details>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FComponents
|
4
|
+
module Dropdown
|
5
|
+
class Component < Base
|
6
|
+
attributes :label, icon: nil, class: nil, label_class: nil, content_class: nil, padding: true
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def icon
|
11
|
+
@icon ? fa_icon(@icon, class: 'mr-5') : nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def padding_class
|
15
|
+
'p-5' if padding
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<%= tag.div(**container_options) do %>
|
2
|
+
<% if label? %>
|
3
|
+
<%= form.label @attribute_name, sanitize(label_options.delete(:text)), class: label_options[:class] %>
|
4
|
+
<% end %>
|
5
|
+
<% if icon? %>
|
6
|
+
<%= fa_icon icon_position_options[:icon], **icon_position_options.except(:icon) %>
|
7
|
+
<% end %>
|
8
|
+
<% if select_field? %>
|
9
|
+
<%=
|
10
|
+
form.select(
|
11
|
+
@attribute_name,
|
12
|
+
options_for_select(select_options[:collection], select_options[:selected]),
|
13
|
+
select_options.except(:collection, :selected),
|
14
|
+
**field_options
|
15
|
+
)
|
16
|
+
%>
|
17
|
+
<% else %>
|
18
|
+
<%= form.text_field @attribute_name, **field_options %>
|
19
|
+
<% end %>
|
20
|
+
<% if field_with_error? %>
|
21
|
+
<% field_errors.each do |field_error| %>
|
22
|
+
<span class="Form-errorMessage"><%= field_error %></span>
|
23
|
+
<% end %>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FComponents
|
4
|
+
module FormField
|
5
|
+
class Component < Base
|
6
|
+
attr_reader :attribute_name, :options, :form
|
7
|
+
|
8
|
+
def initialize(form, attribute_name, **options)
|
9
|
+
@form = form
|
10
|
+
@attribute_name = attribute_name
|
11
|
+
@options = options
|
12
|
+
|
13
|
+
define_elements_classes
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def define_elements_classes
|
19
|
+
define_container_classes
|
20
|
+
define_label_classes
|
21
|
+
define_field_classes
|
22
|
+
define_icon_classes
|
23
|
+
end
|
24
|
+
|
25
|
+
def define_container_classes
|
26
|
+
container_classes = %w[Form-inputGroup w-full]
|
27
|
+
container_classes << container_options[:class]
|
28
|
+
|
29
|
+
container_options[:class] = container_classes.compact.join(' ')
|
30
|
+
end
|
31
|
+
|
32
|
+
def define_label_classes
|
33
|
+
label_classes = %w[Form-label w-full]
|
34
|
+
label_classes << label_options[:class]
|
35
|
+
|
36
|
+
label_options[:class] = label_classes.compact.join(' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_field_classes
|
40
|
+
field_classes = %w[Form-input w-full]
|
41
|
+
|
42
|
+
field_classes << input_icon_position_class if icon?
|
43
|
+
field_classes << 'Form-input--error' if field_with_error?
|
44
|
+
field_classes << field_options[:class]
|
45
|
+
|
46
|
+
field_options[:class] = field_classes.compact.join(' ')
|
47
|
+
end
|
48
|
+
|
49
|
+
def define_icon_classes
|
50
|
+
return unless icon?
|
51
|
+
|
52
|
+
icon_classes = ['Form-icon', icon_position_class, icon_position_options[:class]]
|
53
|
+
|
54
|
+
icon_position_options[:class] = icon_classes.compact.join(' ')
|
55
|
+
end
|
56
|
+
|
57
|
+
def icon_position_options
|
58
|
+
return @icon_position_options if defined? @icon_position_options
|
59
|
+
|
60
|
+
@icon_position_options = icon_options[:leading_icon] || icon_options[:trailing_icon]
|
61
|
+
end
|
62
|
+
|
63
|
+
def container_options
|
64
|
+
@container_options ||= options[:container_options].to_h
|
65
|
+
end
|
66
|
+
|
67
|
+
def label_options
|
68
|
+
@label_options ||= options[:label_options].to_h
|
69
|
+
end
|
70
|
+
|
71
|
+
def field_options
|
72
|
+
@field_options ||= options[:field_options].to_h
|
73
|
+
end
|
74
|
+
|
75
|
+
def icon_options
|
76
|
+
@icon_options ||= options[:icon_options].to_h
|
77
|
+
end
|
78
|
+
|
79
|
+
def select_options
|
80
|
+
return @select_options if defined?(@select_options)
|
81
|
+
|
82
|
+
@select_options = field_options.delete(:select_options).to_h
|
83
|
+
end
|
84
|
+
|
85
|
+
def field_errors
|
86
|
+
return [] if @form.object.nil?
|
87
|
+
|
88
|
+
@field_errors = @form.object.errors[@attribute_name]
|
89
|
+
end
|
90
|
+
|
91
|
+
def input_icon_position_class
|
92
|
+
leading_icon? ? 'Form-input--withLeftIcon' : 'Form-input--withRightIcon'
|
93
|
+
end
|
94
|
+
|
95
|
+
def icon_position_class
|
96
|
+
leading_icon? ? 'Form-iconLeft' : 'Form-iconRight'
|
97
|
+
end
|
98
|
+
|
99
|
+
def icon?
|
100
|
+
icon_position_options.present?
|
101
|
+
end
|
102
|
+
|
103
|
+
def label?
|
104
|
+
label_options[:text] != false
|
105
|
+
end
|
106
|
+
|
107
|
+
def leading_icon?
|
108
|
+
icon_options[:leading_icon].present?
|
109
|
+
end
|
110
|
+
|
111
|
+
def trailing_icon?
|
112
|
+
icon_options[:trailing_icon].present?
|
113
|
+
end
|
114
|
+
|
115
|
+
def field_with_error?
|
116
|
+
field_errors.any?
|
117
|
+
end
|
118
|
+
|
119
|
+
def select_field?
|
120
|
+
select_options.present?
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<table class="w-full hidden <%= table_layout %> <%= @class %>">
|
2
|
+
<%= table_header %>
|
3
|
+
<tbody class="text-sm">
|
4
|
+
<% resources.each do |resource| %>
|
5
|
+
<%= table_row(resource, class: 'even:bg-gray-ltr') %>
|
6
|
+
<% end %>
|
7
|
+
</tbody>
|
8
|
+
</table>
|
9
|
+
|
10
|
+
<div class="md:hidden <%= @class %>">
|
11
|
+
<% resources.each_with_index do |resource| %>
|
12
|
+
<%= mobile_header(resource, class: 'bg-white border-b border-gray-lt') do %>
|
13
|
+
<%= mobile_rows(resource, class: 'flex flex-col space-y-5 mt-5') %>
|
14
|
+
<%= link_to_resource(resource, display_as: :button) %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
</div>
|