tramway 0.5.4.1 → 0.5.5
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/app/components/tailwind_component.rb +32 -0
- data/app/components/tailwinds/form/builder.rb +54 -15
- data/app/components/tailwinds/form/file_field_component.html.haml +6 -3
- data/app/components/tailwinds/form/multiselect/dropdown_container.html.haml +1 -1
- data/app/components/tailwinds/form/multiselect/item_container.html.haml +3 -3
- data/app/components/tailwinds/form/multiselect/select_as_input.html.haml +11 -1
- data/app/components/tailwinds/form/multiselect/select_as_input.rb +1 -0
- data/app/components/tailwinds/form/multiselect/selected_item_template.html.haml +1 -1
- data/app/components/tailwinds/form/multiselect_component.html.haml +3 -3
- data/app/components/tailwinds/form/multiselect_component.rb +8 -1
- data/app/components/tailwinds/form/number_field_component.html.haml +8 -0
- data/app/components/tailwinds/form/number_field_component.rb +9 -0
- data/app/components/tailwinds/form/select_component.html.haml +5 -1
- data/app/components/tailwinds/form/submit_button_component.html.haml +4 -1
- data/app/components/tailwinds/form/submit_button_component.rb +11 -3
- data/app/components/tailwinds/form/text_area_component.html.haml +4 -1
- data/app/components/tailwinds/form/text_field_component.html.haml +4 -1
- data/app/components/tailwinds/table/header_component.html.haml +1 -1
- data/app/components/tailwinds/table/header_component.rb +6 -1
- data/app/components/tailwinds/table_component.html.haml +1 -1
- data/lib/tramway/helpers/views_helper.rb +7 -2
- data/lib/tramway/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21ffe76c2224bd46292479de272ccdb59f0095075043507af3dd6098d5559933
|
4
|
+
data.tar.gz: 6547f3ac892439dddb165dbf7d8a06dcb90d8adb6f12b65d921cb277ebf7754a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93bdfec725bc98cb5ab5a045604fe00c6669eaf8d89eedb081e0750a4b1073fda7c7f99964a3e4b8bbfb4f668024ca9341f512c5fed77d17ea05eeb31de19f37
|
7
|
+
data.tar.gz: 6d6d161386768b114e82e031888ce118383bfb377c6b5e1551d9f8b7300f077af50eb6cb2bff3a6d4523ab0f43bbc77b69b3af180ed4895d7b8c24558c1876a4
|
@@ -10,4 +10,36 @@ class TailwindComponent < Tramway::Component::Base
|
|
10
10
|
option :options
|
11
11
|
option :label
|
12
12
|
option :for
|
13
|
+
option :size, default: -> { :middle }
|
14
|
+
|
15
|
+
SIZE_CLASSES = {
|
16
|
+
small: {
|
17
|
+
text_input: 'text-sm px-2 py-1',
|
18
|
+
select_input: 'text-sm px-2 py-1',
|
19
|
+
file_button: 'text-sm px-3 py-1',
|
20
|
+
submit_button: 'text-sm px-3 py-1',
|
21
|
+
multiselect_input: 'text-sm px-2 py-1'
|
22
|
+
},
|
23
|
+
middle: {
|
24
|
+
text_input: 'text-base px-3 py-2',
|
25
|
+
select_input: 'text-base px-3 py-2',
|
26
|
+
file_button: 'text-base px-4 py-2',
|
27
|
+
submit_button: 'text-base px-4 py-2',
|
28
|
+
multiselect_input: 'text-base px-3 py-2'
|
29
|
+
},
|
30
|
+
large: {
|
31
|
+
text_input: 'text-lg px-4 py-3',
|
32
|
+
select_input: 'text-lg px-4 py-3',
|
33
|
+
file_button: 'text-lg px-5 py-3',
|
34
|
+
submit_button: 'text-lg px-5 py-3',
|
35
|
+
multiselect_input: 'text-lg px-4 py-3'
|
36
|
+
}
|
37
|
+
}.freeze
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def size_class(key)
|
42
|
+
size_classes = SIZE_CLASSES.fetch(size) { SIZE_CLASSES[:middle] }
|
43
|
+
size_classes.fetch(key) { SIZE_CLASSES[:middle].fetch(key) }
|
44
|
+
end
|
13
45
|
end
|
@@ -5,59 +5,90 @@ module Tailwinds
|
|
5
5
|
# Provides Tailwind-styled forms
|
6
6
|
# :reek:InstanceVariableAssumption
|
7
7
|
class Builder < Tramway::Views::FormBuilder
|
8
|
+
def initialize(object_name, object, template, options)
|
9
|
+
super
|
10
|
+
|
11
|
+
@form_size = options[:size] || options['size'] || :middle
|
12
|
+
end
|
13
|
+
|
8
14
|
def text_field(attribute, **options, &)
|
15
|
+
sanitized_options = sanitize_options(options)
|
16
|
+
|
9
17
|
render(Tailwinds::Form::TextFieldComponent.new(
|
10
18
|
input: input(:text_field),
|
11
|
-
value: get_value(attribute,
|
12
|
-
**default_options(attribute,
|
19
|
+
value: get_value(attribute, sanitized_options),
|
20
|
+
**default_options(attribute, sanitized_options)
|
21
|
+
), &)
|
22
|
+
end
|
23
|
+
|
24
|
+
def number_field(attribute, **options, &)
|
25
|
+
sanitized_options = sanitize_options(options)
|
26
|
+
|
27
|
+
render(Tailwinds::Form::NumberFieldComponent.new(
|
28
|
+
input: input(:number_field),
|
29
|
+
value: get_value(attribute, sanitized_options),
|
30
|
+
**default_options(attribute, sanitized_options)
|
13
31
|
), &)
|
14
32
|
end
|
15
33
|
|
16
34
|
def text_area(attribute, **options, &)
|
35
|
+
sanitized_options = sanitize_options(options)
|
36
|
+
|
17
37
|
render(Tailwinds::Form::TextAreaComponent.new(
|
18
38
|
input: input(:text_area),
|
19
|
-
value: get_value(attribute,
|
20
|
-
**default_options(attribute,
|
39
|
+
value: get_value(attribute, sanitized_options),
|
40
|
+
**default_options(attribute, sanitized_options)
|
21
41
|
), &)
|
22
42
|
end
|
23
43
|
|
24
44
|
def password_field(attribute, **options, &)
|
45
|
+
sanitized_options = sanitize_options(options)
|
46
|
+
|
25
47
|
render(Tailwinds::Form::TextFieldComponent.new(
|
26
48
|
input: input(:password_field),
|
27
|
-
**default_options(attribute,
|
49
|
+
**default_options(attribute, sanitized_options)
|
28
50
|
), &)
|
29
51
|
end
|
30
52
|
|
31
53
|
def file_field(attribute, **options, &)
|
32
|
-
|
54
|
+
sanitized_options = sanitize_options(options)
|
55
|
+
input = super(attribute, **sanitized_options.merge(class: :hidden))
|
33
56
|
|
34
|
-
render(Tailwinds::Form::FileFieldComponent.new(input:, **default_options(attribute,
|
57
|
+
render(Tailwinds::Form::FileFieldComponent.new(input:, **default_options(attribute, sanitized_options)), &)
|
35
58
|
end
|
36
59
|
|
37
60
|
def select(attribute, collection, **options, &)
|
61
|
+
sanitized_options = sanitize_options(options)
|
62
|
+
|
38
63
|
render(Tailwinds::Form::SelectComponent.new(
|
39
64
|
input: input(:select),
|
40
|
-
value:
|
41
|
-
collection: explicitly_add_blank_option(collection,
|
42
|
-
**default_options(attribute,
|
65
|
+
value: sanitized_options[:selected] || object.public_send(attribute),
|
66
|
+
collection: explicitly_add_blank_option(collection, sanitized_options),
|
67
|
+
**default_options(attribute, sanitized_options)
|
43
68
|
), &)
|
44
69
|
end
|
45
70
|
|
46
71
|
def multiselect(attribute, collection, **options, &)
|
72
|
+
sanitized_options = sanitize_options(options)
|
73
|
+
|
47
74
|
render(Tailwinds::Form::MultiselectComponent.new(
|
48
75
|
input: input(:text_field),
|
49
|
-
value:
|
76
|
+
value: sanitized_options[:value] || sanitized_options[:selected] || object.public_send(attribute),
|
50
77
|
collection:,
|
51
|
-
**default_options(attribute,
|
78
|
+
**default_options(attribute, sanitized_options)
|
52
79
|
), &)
|
53
80
|
end
|
54
81
|
|
55
|
-
def submit(action,
|
56
|
-
|
82
|
+
def submit(action, **options, &)
|
83
|
+
sanitized_options = sanitize_options(options)
|
84
|
+
|
85
|
+
render(Tailwinds::Form::SubmitButtonComponent.new(action, size: form_size, **sanitized_options), &)
|
57
86
|
end
|
58
87
|
|
59
88
|
private
|
60
89
|
|
90
|
+
attr_reader :form_size
|
91
|
+
|
61
92
|
def input(method_name)
|
62
93
|
unbound_method = self.class.superclass.instance_method(method_name)
|
63
94
|
unbound_method.bind(self)
|
@@ -72,7 +103,8 @@ module Tailwinds
|
|
72
103
|
attribute:,
|
73
104
|
label: label_build(attribute, options),
|
74
105
|
for: for_id(attribute),
|
75
|
-
options
|
106
|
+
options:,
|
107
|
+
size: form_size
|
76
108
|
}
|
77
109
|
end
|
78
110
|
|
@@ -88,6 +120,13 @@ module Tailwinds
|
|
88
120
|
"#{object_name}_#{attribute}"
|
89
121
|
end
|
90
122
|
|
123
|
+
def sanitize_options(options)
|
124
|
+
options.dup.tap do |opts|
|
125
|
+
opts.delete(:size)
|
126
|
+
opts.delete('size')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
91
130
|
# REMOVE IT. WE MUST UNDERSTAND WHY INCLUDE_BLANK DOES NOT WORK
|
92
131
|
# :reek:UtilityFunction
|
93
132
|
def explicitly_add_blank_option(collection, options)
|
@@ -1,5 +1,8 @@
|
|
1
1
|
.mb-4
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
- if @label
|
3
|
+
- base_classes = 'inline-block bg-blue-500 hover:bg-blue-700 text-white font-bold rounded cursor-pointer mt-4 '
|
4
|
+
- base_classes += 'dark:bg-blue-600 dark:hover:bg-blue-500'
|
5
|
+
- classes = "#{size_class(:file_button)} #{base_classes}"
|
6
|
+
%label{ for: @for, class: classes }
|
7
|
+
= @label
|
5
8
|
= @input
|
@@ -1,3 +1,3 @@
|
|
1
|
-
#dropdown.absolute.shadow.top-11.bg-white.z-40.w-full.lef-0.rounded.max-h-select.overflow-y-auto{ data: { action: "click@window->multiselect#closeOnClickOutside" } }
|
1
|
+
#dropdown.absolute.shadow.top-11.bg-white.z-40.w-full.lef-0.rounded.max-h-select.overflow-y-auto.dark:bg-gray-800.dark:shadow-lg.dark:ring-1.dark:ring-gray-700{ data: { action: "click@window->multiselect#closeOnClickOutside" } }
|
2
2
|
.flex.flex-col.w-full
|
3
3
|
{{content}}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
.cursor-pointer.w-full.border-gray-100.rounded-t.border-b.hover:bg-teal-100{ data: { action: "click->multiselect#toggleItem", text: "{{text}}", value: "{{value}}" } }
|
2
|
-
.flex.w-full.items-center.p-2.pl-2.border-transparent.border-l-2.relative.hover:border-teal-100
|
3
|
-
.w-full.items-center.flex
|
1
|
+
.cursor-pointer.w-full.border-gray-100.rounded-t.border-b.hover:bg-teal-100.dark:border-gray-700.dark:hover:bg-gray-700{ data: { action: "click->multiselect#toggleItem", text: "{{text}}", value: "{{value}}" } }
|
2
|
+
.flex.w-full.items-center.p-2.pl-2.border-transparent.border-l-2.relative.hover:border-teal-100.dark:hover:border-gray-600
|
3
|
+
.w-full.items-center.flex.dark:text-gray-100
|
4
4
|
.mx-2.leading-6
|
5
5
|
{{text}}
|
@@ -1,2 +1,12 @@
|
|
1
1
|
.flex-1
|
2
|
-
|
2
|
+
- base_classes = 'bg-transparent appearance-none outline-none h-full w-full text-gray-800 hidden '
|
3
|
+
- base_classes += 'dark:text-white dark:placeholder-white'
|
4
|
+
- classes = "#{@size_class} #{base_classes}"
|
5
|
+
= @input.call(
|
6
|
+
@attribute,
|
7
|
+
@options.merge(
|
8
|
+
placeholder: "{{placeholder}}",
|
9
|
+
class: classes,
|
10
|
+
data: { 'multiselect-target' => 'hiddenInput' }
|
11
|
+
)
|
12
|
+
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.flex.justify-center.items-center.m-1.font-medium.py-1.px-2.bg-white.rounded-full.text-teal-700.bg-teal-100.border.border-teal-300
|
1
|
+
.flex.justify-center.items-center.m-1.font-medium.py-1.px-2.bg-white.rounded-full.text-teal-700.bg-teal-100.border.border-teal-300.dark:bg-teal-900.dark:text-teal-100.dark:border-teal-700
|
2
2
|
.text-xs.font-normal.leading-none.max-w-full.flex-initial
|
3
3
|
{{text}}
|
4
4
|
.flex.flex-auto.flex-row-reverse
|
@@ -2,9 +2,9 @@
|
|
2
2
|
- if @label
|
3
3
|
= component('tailwinds/form/label', for: @for) do
|
4
4
|
= @label
|
5
|
-
.flex.flex-col.relative{ data: multiselect_hash, id: "#{@for}_multiselect" }
|
5
|
+
.flex.flex-col.relative.dark:text-gray-100{ data: multiselect_hash, id: "#{@for}_multiselect" }
|
6
6
|
.min-w-96.w-fit
|
7
|
-
.p-1.flex.border.border-gray-200.bg-white.rounded{ data: { "multiselect-target" => "dropdown" } }
|
7
|
+
.p-1.flex.border.border-gray-200.bg-white.rounded.dark:border-gray-600.dark:bg-gray-800{ data: { "multiselect-target" => "dropdown" } }
|
8
8
|
.flex.flex-auto.flex-wrap{ data: { "multiselect-target" => "showSelectedArea" } }
|
9
|
-
.text-gray-300.w-8.py-1.pl-2.pr-1.border-l.flex.items-center.border-gray-200
|
9
|
+
.text-gray-300.w-8.py-1.pl-2.pr-1.border-l.flex.items-center.border-gray-200.dark:text-gray-500.dark:border-gray-600
|
10
10
|
^
|
@@ -45,7 +45,14 @@ module Tailwinds
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def select_as_input
|
48
|
-
render(
|
48
|
+
render(
|
49
|
+
Tailwinds::Form::Multiselect::SelectAsInput.new(
|
50
|
+
options:,
|
51
|
+
attribute:,
|
52
|
+
input:,
|
53
|
+
size_class: size_class(:multiselect_input)
|
54
|
+
)
|
55
|
+
)
|
49
56
|
end
|
50
57
|
|
51
58
|
def on_change
|
@@ -0,0 +1,8 @@
|
|
1
|
+
.mb-4
|
2
|
+
- if @label
|
3
|
+
= component('tailwinds/form/label', for: @for) do
|
4
|
+
= @label
|
5
|
+
- base_classes = 'w-full bg-white border border-gray-300 rounded focus:outline-none focus:border-red-500 '
|
6
|
+
- base_classes += 'dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:border-red-400 dark:placeholder-white'
|
7
|
+
- classes = "#{size_class(:text_input)} #{base_classes}"
|
8
|
+
= @input.call @attribute, **@options.merge(class: classes), value: @value
|
@@ -2,4 +2,8 @@
|
|
2
2
|
- if @label
|
3
3
|
= component('tailwinds/form/label', for: @for) do
|
4
4
|
= @label
|
5
|
-
|
5
|
+
- base_classes = 'bg-white border border-gray-300 text-gray-700 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 '
|
6
|
+
- base_classes += 'focus:border-transparent disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed '
|
7
|
+
- base_classes += 'dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:focus:ring-red-400 dark:disabled:bg-gray-800 dark:disabled:text-gray-500'
|
8
|
+
- classes = "#{size_class(:select_input)} #{base_classes}"
|
9
|
+
= @input.call(@attribute, @collection, { selected: @value }, @options.merge(class: classes))
|
@@ -1,4 +1,7 @@
|
|
1
1
|
.flex.items-center.justify-between
|
2
|
-
|
2
|
+
- base_classes = 'bg-red-500 hover:bg-red-700 text-white font-bold rounded focus:outline-none focus:shadow-outline cursor-pointer '
|
3
|
+
- base_classes += 'dark:text-white dark:bg-red-600 dark:hover:bg-red-500 dark:focus:ring-2 dark:focus:ring-red-400'
|
4
|
+
- classes = "#{size_class(:submit_button)} #{base_classes}"
|
5
|
+
%button{ type: :submit, name: :commit, class: classes, **@options }
|
3
6
|
= @text
|
4
7
|
= @content
|
@@ -4,10 +4,18 @@ module Tailwinds
|
|
4
4
|
module Form
|
5
5
|
# Tailwind-styled submit button
|
6
6
|
class SubmitButtonComponent < TailwindComponent
|
7
|
-
def initialize(action, **options)
|
8
|
-
@options = options.except :type
|
9
|
-
|
7
|
+
def initialize(action, size: :middle, **options)
|
10
8
|
@text = action.is_a?(String) ? action : action.to_s.capitalize
|
9
|
+
|
10
|
+
super(
|
11
|
+
input: nil,
|
12
|
+
attribute: nil,
|
13
|
+
value: nil,
|
14
|
+
options: options.except(:type),
|
15
|
+
label: nil,
|
16
|
+
for: nil,
|
17
|
+
size:
|
18
|
+
)
|
11
19
|
end
|
12
20
|
end
|
13
21
|
end
|
@@ -2,4 +2,7 @@
|
|
2
2
|
- if @label
|
3
3
|
= component('tailwinds/form/label', for: @for) do
|
4
4
|
= @label
|
5
|
-
|
5
|
+
- base_classes = 'w-full bg-white border border-gray-300 rounded focus:outline-none focus:border-red-500 '
|
6
|
+
- base_classes += 'dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:border-red-400 dark:placeholder-white'
|
7
|
+
- classes = "#{size_class(:text_input)} #{base_classes}"
|
8
|
+
= @input.call @attribute, **@options.merge(class: classes), value: @value
|
@@ -2,4 +2,7 @@
|
|
2
2
|
- if @label
|
3
3
|
= component('tailwinds/form/label', for: @for) do
|
4
4
|
= @label
|
5
|
-
|
5
|
+
- base_classes = 'w-full bg-white border border-gray-300 rounded focus:outline-none focus:border-red-500 '
|
6
|
+
- base_classes += 'dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:border-red-400 dark:placeholder-white'
|
7
|
+
- classes = "#{size_class(:text_input)} #{base_classes}"
|
8
|
+
= @input.call @attribute, **@options.merge(class: classes), value: @value
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.div-table-row.grid.text-white.text-small.gap-4.bg-purple-700.dark:bg-gray-700.dark:text-gray-400{ class: "grid-cols-#{
|
1
|
+
.div-table-row.grid.text-white.text-small.gap-4.bg-purple-700.dark:bg-gray-700.dark:text-gray-400{ class: "grid-cols-#{columns_count}", aria: { label: "Table Header" }, role: "row" }
|
2
2
|
- if headers.any?
|
3
3
|
- headers.each do |header|
|
4
4
|
.div-table-cell.py-4.px-6
|
@@ -4,7 +4,12 @@ module Tailwinds
|
|
4
4
|
module Table
|
5
5
|
# Component for rendering a header in a table
|
6
6
|
class HeaderComponent < Tramway::Component::Base
|
7
|
-
option :headers
|
7
|
+
option :headers, optional: true, default: -> { [] }
|
8
|
+
option :columns, optional: true, default: -> { 3 }
|
9
|
+
|
10
|
+
def columns_count
|
11
|
+
headers.present? ? headers.size : columns
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
10
15
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
= helpers.component 'tailwinds/table/row/preview'
|
2
2
|
|
3
3
|
- width_class = options[:class]&.include?('w-') ? '' : 'w-full'
|
4
|
-
.div-table.text-left.rtl:text-right.text-gray-500.dark:text-gray-400
|
4
|
+
.div-table.text-left.rtl:text-right.text-gray-500.dark:text-gray-400{ class: "#{options[:class]} #{width_class}", **options.except(:class) }
|
5
5
|
= content
|
@@ -4,8 +4,13 @@ module Tramway
|
|
4
4
|
module Helpers
|
5
5
|
# Provides view-oriented helpers for ActionView
|
6
6
|
module ViewsHelper
|
7
|
-
def tramway_form_for(object, *, **options, &)
|
8
|
-
form_for(
|
7
|
+
def tramway_form_for(object, *, size: :middle, **options, &)
|
8
|
+
form_for(
|
9
|
+
object,
|
10
|
+
*,
|
11
|
+
**options.merge(builder: Tailwinds::Form::Builder, size:),
|
12
|
+
&
|
13
|
+
)
|
9
14
|
end
|
10
15
|
end
|
11
16
|
end
|
data/lib/tramway/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tramway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kalashnikovisme
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-
|
12
|
+
date: 2025-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: anyway_config
|
@@ -158,6 +158,8 @@ files:
|
|
158
158
|
- app/components/tailwinds/form/multiselect/selected_item_template.rb
|
159
159
|
- app/components/tailwinds/form/multiselect_component.html.haml
|
160
160
|
- app/components/tailwinds/form/multiselect_component.rb
|
161
|
+
- app/components/tailwinds/form/number_field_component.html.haml
|
162
|
+
- app/components/tailwinds/form/number_field_component.rb
|
161
163
|
- app/components/tailwinds/form/select_component.html.haml
|
162
164
|
- app/components/tailwinds/form/select_component.rb
|
163
165
|
- app/components/tailwinds/form/submit_button_component.html.haml
|