shoelace-rails 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +16 -14
- data/Appraisals +1 -1
- data/CHANGELOG.md +39 -1
- data/README.md +85 -5
- data/app/helpers/shoelace/form_helper.rb +38 -127
- data/app/helpers/shoelace/tag_helper.rb +27 -0
- data/gemfiles/rails_edge.gemfile +1 -1
- data/lib/shoelace/rails/version.rb +1 -1
- data/lib/shoelace/railtie.rb +17 -3
- data/lib/shoelace/testing.rb +2 -2
- data/lib/tasks/{assets.rake → shoelace.rake} +3 -0
- data/test/dummy_app/app/views/hotwire_forms/form.html.erb +1 -1
- data/test/dummy_app/app/views/layouts/application.html.erb +2 -2
- data/test/dummy_app/test/system/hotwire_form_test.rb +0 -2
- data/test/dummy_app/test/system/turbolinks_form_test.rb +0 -1
- data/test/helpers/form_helper_test.rb +147 -71
- data/test/helpers/tag_helper_test.rb +58 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d765c426ef9b3551956028e292d1fe312f04c85b5e1184d2f44193c348809ae
|
4
|
+
data.tar.gz: 662389bc95dc73c15851d9343304da787d70b6f93bff4dcb16124d42fa8fb7c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21e95f106d6c8cff0b8edb1cdfec3d3e5d11e1a477a7ba2eff509035194666cdecadeef43465d8f426ea22082b4ce174fb3e47d82e8f7f9be4aa7e257e4a0e76
|
7
|
+
data.tar.gz: 4eeb6447fb6c65179fd0514e58171ca45045069b87835cb993c8935aa4011e267b308308fffebca5fbe2409013d78548904defba33d8f28716d7370569c19b0b
|
data/.github/workflows/main.yml
CHANGED
@@ -9,22 +9,24 @@ jobs:
|
|
9
9
|
strategy:
|
10
10
|
matrix:
|
11
11
|
ruby_version:
|
12
|
+
- '3.2'
|
12
13
|
- '3.1'
|
13
14
|
- '3.0'
|
14
15
|
- '2.7'
|
15
|
-
- 'jruby-9.3
|
16
|
+
- 'jruby-9.3'
|
17
|
+
- 'jruby-9.4'
|
16
18
|
gemfile:
|
17
19
|
- gemfiles/rails_70.gemfile
|
18
20
|
- gemfiles/rails_61.gemfile
|
19
21
|
- gemfiles/rails_60.gemfile
|
20
22
|
exclude:
|
21
|
-
- ruby_version: 'jruby-9.3
|
23
|
+
- ruby_version: 'jruby-9.3'
|
22
24
|
gemfile: gemfiles/rails_70.gemfile
|
23
|
-
runs-on: ubuntu-
|
25
|
+
runs-on: ubuntu-22.04
|
24
26
|
env:
|
25
27
|
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
26
28
|
steps:
|
27
|
-
- uses: actions/checkout@
|
29
|
+
- uses: actions/checkout@v3
|
28
30
|
- name: Set up Ruby
|
29
31
|
uses: ruby/setup-ruby@v1
|
30
32
|
with:
|
@@ -34,13 +36,13 @@ jobs:
|
|
34
36
|
|
35
37
|
system:
|
36
38
|
needs: unit
|
37
|
-
runs-on: ubuntu-
|
39
|
+
runs-on: ubuntu-22.04
|
38
40
|
steps:
|
39
|
-
- uses: actions/checkout@
|
41
|
+
- uses: actions/checkout@v3
|
40
42
|
- name: Set up Ruby
|
41
43
|
uses: ruby/setup-ruby@v1
|
42
44
|
with:
|
43
|
-
ruby-version: 3.
|
45
|
+
ruby-version: 3.2.0
|
44
46
|
bundler-cache: true
|
45
47
|
- name: Install dependencies
|
46
48
|
run: |
|
@@ -53,11 +55,11 @@ jobs:
|
|
53
55
|
|
54
56
|
rails_edge:
|
55
57
|
needs: system
|
56
|
-
runs-on: ubuntu-
|
58
|
+
runs-on: ubuntu-22.04
|
57
59
|
env:
|
58
60
|
BUNDLE_GEMFILE: gemfiles/rails_edge.gemfile
|
59
61
|
steps:
|
60
|
-
- uses: actions/checkout@
|
62
|
+
- uses: actions/checkout@v3
|
61
63
|
- name: Set up Ruby
|
62
64
|
uses: ruby/setup-ruby@v1
|
63
65
|
with:
|
@@ -72,11 +74,11 @@ jobs:
|
|
72
74
|
gemfile:
|
73
75
|
- gemfiles/rails_edge.gemfile
|
74
76
|
- gemfiles/rails_70.gemfile
|
75
|
-
runs-on: ubuntu-
|
77
|
+
runs-on: ubuntu-22.04
|
76
78
|
env:
|
77
79
|
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
78
80
|
steps:
|
79
|
-
- uses: actions/checkout@
|
81
|
+
- uses: actions/checkout@v3
|
80
82
|
- name: Set up Ruby
|
81
83
|
uses: ruby/setup-ruby@v1
|
82
84
|
with:
|
@@ -85,13 +87,13 @@ jobs:
|
|
85
87
|
- run: bundle exec rake || echo "Ruby edge test is done."
|
86
88
|
|
87
89
|
# browser_tests:
|
88
|
-
# runs-on: ubuntu-
|
90
|
+
# runs-on: ubuntu-22.04
|
89
91
|
# steps:
|
90
|
-
# - uses: actions/checkout@
|
92
|
+
# - uses: actions/checkout@v3
|
91
93
|
# - name: Set up Ruby
|
92
94
|
# uses: ruby/setup-ruby@v1
|
93
95
|
# with:
|
94
|
-
# ruby-version: 3.
|
96
|
+
# ruby-version: 3.2.0
|
95
97
|
# bundler-cache: true
|
96
98
|
# - name: Install dependencies
|
97
99
|
# run: |
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,42 @@
|
|
1
|
-
## v0.
|
1
|
+
## v0.4.0
|
2
|
+
|
3
|
+
#### 🚨 Breaking Changes
|
4
|
+
|
5
|
+
- No longer works with 2.0.0-beta.88 and below.
|
6
|
+
|
7
|
+
#### ⭐️ Features
|
8
|
+
|
9
|
+
- Support Shoelace.style 2.0.0-beta.88
|
10
|
+
|
11
|
+
## [v0.3.0](https://github.com/yuki24/shoelace-rails/tree/v0.3.0)
|
12
|
+
|
13
|
+
_<sup>released at 2023-01-05 08:49:23 UTC</sup>_
|
14
|
+
|
15
|
+
#### Features
|
16
|
+
|
17
|
+
- No longer requires the `sl-form` component ([<tt>4fdbfa1</tt>](https://github.com/yuki24/shoelace-rails/commit/4fdbfa15fa10db9e7240378ca34ebcc494d18f1a))
|
18
|
+
- The `#text_area` method now accepts a block ([<tt>5092dc1</tt>](https://github.com/yuki24/shoelace-rails/commit/5092dc1cbc7e8e74552451450804baa378ab1f11))
|
19
|
+
- Allow overriding the value attribute for `<sl-select>` ([<tt>1f38be7</tt>](https://github.com/yuki24/shoelace-rails/commit/1f38be73e3335c10e846393ebcf5155d155b00b2))
|
20
|
+
- Auto-display labels whenever possible ([<tt>c1e3a95</tt>](https://github.com/yuki24/shoelace-rails/commit/c1e3a950c3e8ac4238ed3e83e4d87467a68eb91f))
|
21
|
+
- `<sl-select>` now always has a label by default ([<tt>f9fb5f0</tt>](https://github.com/yuki24/shoelace-rails/commit/f9fb5f0cd74d179241be51510fa1c306481946c9))
|
22
|
+
- Support Ruby 3.2 ([<tt>b286cbc</tt>](https://github.com/yuki24/shoelace-rails/commit/b286cbc18930218ab5c82bd8648a51e9c6ce53db))
|
23
|
+
- Add `#sl_button_to` ([<tt>e1bdedb</tt>](https://github.com/yuki24/shoelace-rails/commit/e1bdedba4656d89a82c78641644490085da1fa37))
|
24
|
+
- Add `#sl_icon_tag` ([<tt>8a2187a</tt>](https://github.com/yuki24/shoelace-rails/commit/8a2187a2800771512fccf2c8231378a77be59df4))
|
25
|
+
- Add `#sl_avatar_tag` ([<tt>77dccdb</tt>](https://github.com/yuki24/shoelace-rails/commit/77dccdb24cfc014bd997ffb66ad89ff95afb3ef7))
|
26
|
+
- Allow using the `Shoelace::FormBuilder` in a cleaner way ([<tt>43dea33</tt>](https://github.com/yuki24/shoelace-rails/commit/43dea3309c3e0cf9d9b43b6957f6e54ad9497c9f))
|
27
|
+
|
28
|
+
#### Bug Fixes
|
29
|
+
|
30
|
+
- Fixes a bug where the gem rake tasks are not loaded ([<tt>115bfb3</tt>](https://github.com/yuki24/shoelace-rails/commit/115bfb3d81ca19b5b922a5fb32f46adb1d6e8544))
|
31
|
+
- Fixes a bug where values are not properly passed in to `<sl-textarea>` ([<tt>3d16384</tt>](https://github.com/yuki24/shoelace-rails/commit/3d16384554bd4a6143e28e483f8d6bee8fb2e073))
|
32
|
+
- Make sure yarn install is always executed before copying shoelace assets ([<tt>98018a2</tt>](https://github.com/yuki24/shoelace-rails/commit/98018a27a29ddc9ff2c2fa066bbe986709803a1d))
|
33
|
+
- Fixes a bug where the `@object` needs to respond to `#errors` ([<tt>bb981ed</tt>](https://github.com/yuki24/shoelace-rails/commit/bb981ed05825707cef89d70a7d1699c12cd0ba9b))
|
34
|
+
- Fixes a bug where the `size` attr is ignored by the `#text_area` method ([<tt>8bc4c37</tt>](https://github.com/yuki24/shoelace-rails/commit/8bc4c3784a458e7fc9c18a143578b2cbf588e9e7))
|
35
|
+
- Fixes a bug where unchecked checkbox values are not captured ([<tt>dc658be</tt>](https://github.com/yuki24/shoelace-rails/commit/dc658bea9fc4d4205dacdfe133b091c5a5edf14c))
|
36
|
+
|
37
|
+
## [v0.2.0](https://github.com/yuki24/shoelace-rails/tree/v0.2.0)
|
38
|
+
|
39
|
+
_<sup>released at 2022-06-24 05:14:01 UTC</sup>_
|
2
40
|
|
3
41
|
#### Features
|
4
42
|
|
data/README.md
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
The `shoelace-rails` gem adds useful helper methods for [Shoelace.style](https://shoelace.style), the design system.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Compatibility with Shoelace
|
6
|
+
|
7
|
+
* **For Shoelace version >= 2.0.0-beta.88, use the gem version `0.4.0` or above**.
|
8
|
+
* For Shoelace version <= 2.0.0-beta.87, use the gem version `0.3.0`.
|
6
9
|
|
7
|
-
|
8
|
-
the [`jsbundling-rails`](https://github.com/rails/jsbundling-rails) gem. You may have to tweak the examples here if
|
9
|
-
you do not use it. However, the principle here should be the same regardless of the JS bundler you use.
|
10
|
+
## Installation
|
10
11
|
|
11
12
|
Add this line to your application's Gemfile:
|
12
13
|
|
@@ -70,7 +71,11 @@ Shoelace icons are automatically set up to load properly, so you don't need to a
|
|
70
71
|
|
71
72
|
## View Helpers
|
72
73
|
|
73
|
-
As explained above, this gem provides drop-in replacements to
|
74
|
+
As explained above, this gem provides drop-in replacements to Rails view helpers.
|
75
|
+
|
76
|
+
### Form Helpers
|
77
|
+
|
78
|
+
The `sl_form_with` or `sl_form_for` method could be used to generate a form with the Shoelace components:
|
74
79
|
|
75
80
|
```erb
|
76
81
|
<%= sl_form_for @user do |form| %>
|
@@ -115,6 +120,81 @@ And this code will produce:
|
|
115
120
|
</form>
|
116
121
|
```
|
117
122
|
|
123
|
+
#### Using The `sl-select` component with `multiple`
|
124
|
+
|
125
|
+
TDB
|
126
|
+
|
127
|
+
#### Using the Shoelace FormBuilder with other gems
|
128
|
+
|
129
|
+
Sometimes you want to use the Shoelace FormBuilder with other gems, such as [ransack](https://github.com/activerecord-hackery/ransack).
|
130
|
+
In this case, you can not use the `sl_form_for` or `sl_form_with` methods in tandem with `ransack`, but you can use
|
131
|
+
the `Shoelace::FormBuilder` with e.g. [the `search_form_for` method](https://activerecord-hackery.github.io/ransack/getting-started/simple-mode/#form-helper):
|
132
|
+
|
133
|
+
```erb
|
134
|
+
<%= search_form_for @q, builder: Shoelace::FormBuilder do |form| %>
|
135
|
+
...
|
136
|
+
<% end %>
|
137
|
+
```
|
138
|
+
|
139
|
+
### Tag Helpers
|
140
|
+
|
141
|
+
#### `#sl_avatar_tag`
|
142
|
+
|
143
|
+
The `@sl_avatar_tag` method behaves just like the `image_tag` method.
|
144
|
+
|
145
|
+
```erb
|
146
|
+
<%= sl_avatar_tag "/path/to/image.jpg" %>
|
147
|
+
```
|
148
|
+
|
149
|
+
Will produce:
|
150
|
+
|
151
|
+
```html
|
152
|
+
<sl-avatar image="/path/to/image.jpg"></sl-avatar>
|
153
|
+
```
|
154
|
+
|
155
|
+
#### `#sl_button_to`
|
156
|
+
|
157
|
+
The `sl_button_to` method behaves just like the `link_to` method. Note that this is slightly different from the
|
158
|
+
built-in `button_to` method.
|
159
|
+
|
160
|
+
Without a block:
|
161
|
+
|
162
|
+
```erb
|
163
|
+
<%= sl_button_to "Next Page", "/components?page=2" %>
|
164
|
+
```
|
165
|
+
|
166
|
+
```html
|
167
|
+
<sl-button href="/components?page=2">
|
168
|
+
Next Page
|
169
|
+
</sl-button>
|
170
|
+
```
|
171
|
+
|
172
|
+
With a block:
|
173
|
+
|
174
|
+
```erb
|
175
|
+
<%= sl_button_to "/components?page=2" do %>
|
176
|
+
Next Page
|
177
|
+
<% end %>
|
178
|
+
```
|
179
|
+
|
180
|
+
```html
|
181
|
+
<sl-button href="/components?page=2">
|
182
|
+
Next Page
|
183
|
+
</sl-button>
|
184
|
+
```
|
185
|
+
|
186
|
+
#### `#sl_icon_tag`
|
187
|
+
|
188
|
+
The `sl_icon_tag` method takes the `name` attribute value as the first argument:
|
189
|
+
|
190
|
+
```erb
|
191
|
+
<%= sl_icon_tag "apple" %>
|
192
|
+
```
|
193
|
+
|
194
|
+
```html
|
195
|
+
<sl-icon name="apple"></sl-icon>
|
196
|
+
```
|
197
|
+
|
118
198
|
## Development
|
119
199
|
|
120
200
|
1. Run `bundle install`
|
@@ -2,11 +2,8 @@
|
|
2
2
|
|
3
3
|
module Shoelace
|
4
4
|
module FormHelper
|
5
|
-
mattr_accessor :
|
6
|
-
self.
|
7
|
-
|
8
|
-
mattr_accessor :remote_form
|
9
|
-
self.remote_form = false
|
5
|
+
mattr_accessor :invalid_input_class_name
|
6
|
+
self.invalid_input_class_name = nil
|
10
7
|
|
11
8
|
class ShoelaceInputField < ActionView::Helpers::Tags::TextField #:nodoc:
|
12
9
|
attr_reader :field_type
|
@@ -24,7 +21,8 @@ module Shoelace
|
|
24
21
|
|
25
22
|
options["size"] = options["maxlength"] unless options.key?("size")
|
26
23
|
options["type"] ||= field_type
|
27
|
-
options["
|
24
|
+
options["class"] ||= [options["class"], Shoelace::FormHelper.invalid_input_class_name].compact.join(" ") if @object.respond_to?(:errors) && @object.errors[@method_name].present?
|
25
|
+
|
28
26
|
add_default_name_and_id(options)
|
29
27
|
|
30
28
|
@template_object.content_tag('sl-input', '', options, &block)
|
@@ -68,10 +66,12 @@ module Shoelace
|
|
68
66
|
end
|
69
67
|
|
70
68
|
class ShoelaceTextArea < ActionView::Helpers::Tags::TextArea #:nodoc:
|
71
|
-
def
|
72
|
-
options
|
69
|
+
def render(&block)
|
70
|
+
options = @options.stringify_keys
|
71
|
+
options["value"] = options.fetch("value") { value_before_type_cast }
|
72
|
+
add_default_name_and_id(options)
|
73
73
|
|
74
|
-
|
74
|
+
@template_object.content_tag("sl-textarea", '', options, &block)
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -86,7 +86,7 @@ module Shoelace
|
|
86
86
|
|
87
87
|
def select_content_tag(option_tags, _options, html_options)
|
88
88
|
html_options = html_options.stringify_keys
|
89
|
-
html_options['value']
|
89
|
+
html_options['value'] ||= value
|
90
90
|
add_default_name_and_id(html_options)
|
91
91
|
|
92
92
|
@template_object.content_tag("sl-select", option_tags, html_options)
|
@@ -100,7 +100,7 @@ module Shoelace
|
|
100
100
|
|
101
101
|
def select_content_tag(option_tags, _options, html_options)
|
102
102
|
html_options = html_options.stringify_keys
|
103
|
-
html_options['value']
|
103
|
+
html_options['value'] ||= value
|
104
104
|
add_default_name_and_id(html_options)
|
105
105
|
|
106
106
|
@template_object.content_tag("sl-select", option_tags, html_options)
|
@@ -120,10 +120,18 @@ module Shoelace
|
|
120
120
|
add_default_name_and_id(options)
|
121
121
|
end
|
122
122
|
|
123
|
-
|
124
|
-
|
123
|
+
include_hidden = options.delete("include_hidden") { true }
|
124
|
+
|
125
|
+
sl_checkbox_tag = if block_given?
|
126
|
+
@template_object.content_tag('sl-checkbox', '', options, &block)
|
127
|
+
else
|
128
|
+
@template_object.content_tag('sl-checkbox', @method_name.to_s.humanize, options)
|
129
|
+
end
|
130
|
+
|
131
|
+
if include_hidden
|
132
|
+
hidden_field_for_checkbox(options) + sl_checkbox_tag
|
125
133
|
else
|
126
|
-
|
134
|
+
sl_checkbox_tag
|
127
135
|
end
|
128
136
|
end
|
129
137
|
end
|
@@ -198,7 +206,7 @@ module Shoelace
|
|
198
206
|
alias color_picker color_field
|
199
207
|
|
200
208
|
def range_field(method, **options)
|
201
|
-
ShoelaceRange.new(object_name, method, @template, options.with_defaults(object: @object)).render
|
209
|
+
ShoelaceRange.new(object_name, method, @template, options.with_defaults(object: @object, label: method.to_s.humanize)).render
|
202
210
|
end
|
203
211
|
alias range range_field
|
204
212
|
|
@@ -207,8 +215,8 @@ module Shoelace
|
|
207
215
|
end
|
208
216
|
alias switch switch_field
|
209
217
|
|
210
|
-
def text_area(method, **options)
|
211
|
-
ShoelaceTextArea.new(object_name, method, @template, options.with_defaults(object: @object, resize: 'auto')).render
|
218
|
+
def text_area(method, **options, &block)
|
219
|
+
ShoelaceTextArea.new(object_name, method, @template, options.with_defaults(object: @object, label: method.to_s.humanize, resize: 'auto')).render(&block)
|
212
220
|
end
|
213
221
|
|
214
222
|
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0", &block)
|
@@ -216,11 +224,11 @@ module Shoelace
|
|
216
224
|
end
|
217
225
|
|
218
226
|
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
219
|
-
ShoelaceSelect.new(object_name, method, @template, choices, options.with_defaults(object: @object), html_options, &block).render
|
227
|
+
ShoelaceSelect.new(object_name, method, @template, choices, options.with_defaults(object: @object), html_options.with_defaults(label: method.to_s.humanize), &block).render
|
220
228
|
end
|
221
229
|
|
222
230
|
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
223
|
-
ShoelaceCollectionSelect.new(object_name, method, @template, collection, value_method, text_method, options.with_defaults(object: @object), html_options, &block).render
|
231
|
+
ShoelaceCollectionSelect.new(object_name, method, @template, collection, value_method, text_method, options.with_defaults(object: @object), html_options.with_defaults(label: method.to_s.humanize), &block).render
|
224
232
|
end
|
225
233
|
|
226
234
|
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
@@ -234,118 +242,19 @@ module Shoelace
|
|
234
242
|
end
|
235
243
|
end
|
236
244
|
|
237
|
-
DEFAULT_FORM_PARAMETERS = {
|
238
|
-
builder: ShoelaceFormBuilder,
|
239
|
-
data: {
|
240
|
-
remote: true,
|
241
|
-
}
|
242
|
-
}
|
243
|
-
|
244
|
-
DEFAULT_TURBO_FORM_PARAMETERS = {
|
245
|
-
builder: ShoelaceFormBuilder,
|
246
|
-
}
|
247
|
-
|
245
|
+
DEFAULT_FORM_PARAMETERS = { builder: ShoelaceFormBuilder }
|
248
246
|
DIVIDER_TAG = "<sl-divider></sl-divider>".html_safe
|
249
|
-
OPENING_SL_FORM_TAG = '<sl-form'.html_safe
|
250
|
-
CLOSING_SL_FORM_TAG = '</sl-form>'.html_safe
|
251
|
-
OPENING_SL_TURBO_FORM_TAG = '<sl-turbo-form'.html_safe
|
252
|
-
CLOSING_SL_TURBO_FORM_TAG = '</sl-turbo-form>'.html_safe
|
253
247
|
|
254
|
-
private_constant :DEFAULT_FORM_PARAMETERS, :DIVIDER_TAG
|
248
|
+
private_constant :DEFAULT_FORM_PARAMETERS, :DIVIDER_TAG
|
255
249
|
|
256
250
|
def sl_form_for(*args, **options, &block)
|
257
|
-
|
258
|
-
DEFAULT_FORM_PARAMETERS.deep_merge(options)
|
259
|
-
else
|
260
|
-
DEFAULT_FORM_PARAMETERS.without(:data).merge(options)
|
261
|
-
end
|
262
|
-
|
263
|
-
content = form_for(*args, **form_params, &block)
|
264
|
-
|
265
|
-
if ::Shoelace::FormHelper.use_sl_form_tag
|
266
|
-
content[0, 5] = OPENING_SL_FORM_TAG
|
267
|
-
content[-7, 7] = CLOSING_SL_FORM_TAG
|
268
|
-
end
|
269
|
-
|
270
|
-
content
|
251
|
+
form_for(*args, **DEFAULT_FORM_PARAMETERS, **options, &block)
|
271
252
|
end
|
272
253
|
|
273
254
|
def sl_form_with(**args, &block)
|
274
|
-
|
275
|
-
|
276
|
-
if ::Shoelace::FormHelper.use_sl_form_tag
|
277
|
-
content[0, 5] = OPENING_SL_FORM_TAG
|
278
|
-
content[-7, 7] = CLOSING_SL_FORM_TAG
|
279
|
-
end
|
280
|
-
|
281
|
-
content
|
255
|
+
form_with(**args, **DEFAULT_FORM_PARAMETERS, &block)
|
282
256
|
end
|
283
257
|
|
284
|
-
def sl_form_tag(url_for_options = {}, options = {}, &block)
|
285
|
-
content = form_tag(url_for_options, options.with_defaults(DEFAULT_FORM_PARAMETERS.except(:builder)), &block)
|
286
|
-
|
287
|
-
if ::Shoelace::FormHelper.use_sl_form_tag
|
288
|
-
content[0, 5] = OPENING_SL_FORM_TAG
|
289
|
-
content[-7, 7] = CLOSING_SL_FORM_TAG
|
290
|
-
end
|
291
|
-
|
292
|
-
content
|
293
|
-
end
|
294
|
-
|
295
|
-
def sl_turbo_form_for(*args, **options, &block)
|
296
|
-
content = form_for(*args, **DEFAULT_TURBO_FORM_PARAMETERS.merge(options), &block)
|
297
|
-
|
298
|
-
if ::Shoelace::FormHelper.use_sl_form_tag
|
299
|
-
content[0, 5] = OPENING_SL_TURBO_FORM_TAG
|
300
|
-
content[-7, 7] = CLOSING_SL_TURBO_FORM_TAG
|
301
|
-
end
|
302
|
-
|
303
|
-
content
|
304
|
-
end
|
305
|
-
|
306
|
-
def sl_turbo_form_with(**args, &block)
|
307
|
-
content = form_with(**args, **DEFAULT_TURBO_FORM_PARAMETERS, &block)
|
308
|
-
|
309
|
-
if ::Shoelace::FormHelper.use_sl_form_tag
|
310
|
-
content[0, 5] = OPENING_SL_TURBO_FORM_TAG
|
311
|
-
content[-7, 7] = CLOSING_SL_TURBO_FORM_TAG
|
312
|
-
end
|
313
|
-
|
314
|
-
content
|
315
|
-
end
|
316
|
-
|
317
|
-
def sl_turbo_form_tag(url_for_options = {}, options = {}, &block)
|
318
|
-
content = form_tag(url_for_options, options.with_defaults(DEFAULT_TURBO_FORM_PARAMETERS.except(:builder)), &block)
|
319
|
-
|
320
|
-
if ::Shoelace::FormHelper.use_sl_form_tag
|
321
|
-
content[0, 5] = OPENING_SL_TURBO_FORM_TAG
|
322
|
-
content[-7, 7] = CLOSING_SL_TURBO_FORM_TAG
|
323
|
-
end
|
324
|
-
|
325
|
-
content
|
326
|
-
end
|
327
|
-
|
328
|
-
# Creates a generic +<sl-button>+ element.
|
329
|
-
def sl_button_tag(**attrs, &block)
|
330
|
-
content_tag("sl-button", **attrs, &block)
|
331
|
-
end
|
332
|
-
|
333
|
-
# Not providing this helper for now due to potentially untraceable HTML. E.g.
|
334
|
-
#
|
335
|
-
# <a href="...">
|
336
|
-
# <sl-button>...</sl-button>
|
337
|
-
# </a>
|
338
|
-
#
|
339
|
-
# may be trackable and traceable by search bots and scrapers, but:
|
340
|
-
#
|
341
|
-
# <sl-button href="...">...</sl-button>
|
342
|
-
#
|
343
|
-
# may not be. In the mean time, it is advisable to wrap a <sl-button> tag with an <a> tag.
|
344
|
-
#
|
345
|
-
# def sl_button_to(href, **attrs, &block)
|
346
|
-
# sl_button_tag(href: href, **attrs, &block)
|
347
|
-
# end
|
348
|
-
|
349
258
|
# Creates a submit button with the text value as the caption, with the +submit+ attribute.
|
350
259
|
def sl_submit_tag(value = 'Save changes', **options)
|
351
260
|
options = options.deep_stringify_keys
|
@@ -365,7 +274,7 @@ module Shoelace
|
|
365
274
|
content_tag('sl-input', '', { "type" => "text", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys), &block)
|
366
275
|
end
|
367
276
|
|
368
|
-
# Returns a string of +<sl-
|
277
|
+
# Returns a string of +<sl-option>+ tags, like +options_for_select+, but prepends a +<small>+ tag to
|
369
278
|
# each group.
|
370
279
|
def grouped_sl_options_for_select(grouped_options, options)
|
371
280
|
body = "".html_safe
|
@@ -374,14 +283,14 @@ module Shoelace
|
|
374
283
|
label, values = container
|
375
284
|
|
376
285
|
body.safe_concat(DIVIDER_TAG) if index > 0
|
377
|
-
body.safe_concat(content_tag("
|
286
|
+
body.safe_concat(content_tag("small", label)) if label.present?
|
378
287
|
body.safe_concat(sl_options_for_select(values, options))
|
379
288
|
end
|
380
289
|
|
381
290
|
body
|
382
291
|
end
|
383
292
|
|
384
|
-
# Accepts an enumerable (hash, array, enumerable, your type) and returns a string of +sl-
|
293
|
+
# Accepts an enumerable (hash, array, enumerable, your type) and returns a string of +sl-option+ tags. Given
|
385
294
|
# an enumerable where the elements respond to +first+ and +last+ (such as a two-element array), the “lasts” serve
|
386
295
|
# as option values and the “firsts” as option text.
|
387
296
|
def sl_options_for_select(enumerable, options = nil)
|
@@ -397,11 +306,11 @@ module Shoelace
|
|
397
306
|
html_attributes[:disabled] ||= disabled.include?(value)
|
398
307
|
html_attributes[:value] = value
|
399
308
|
|
400
|
-
tag_builder.content_tag_string('sl-
|
309
|
+
tag_builder.content_tag_string('sl-option', text, html_attributes)
|
401
310
|
end.join("\n").html_safe
|
402
311
|
end
|
403
312
|
|
404
|
-
# Returns a string of +<sl-
|
313
|
+
# Returns a string of +<sl-option>+ tags compiled by iterating over the collection and assigning the result of
|
405
314
|
# a call to the +value_method+ as the option value and the +text_method+ as the option text.
|
406
315
|
def sl_options_from_collection_for_select(collection, value_method, text_method, selected = nil)
|
407
316
|
options = collection.map do |element|
|
@@ -448,4 +357,6 @@ module Shoelace
|
|
448
357
|
RUBY
|
449
358
|
end
|
450
359
|
end
|
360
|
+
|
361
|
+
FormBuilder = FormHelper::ShoelaceFormBuilder
|
451
362
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shoelace
|
4
|
+
module TagHelper
|
5
|
+
# Creates a generic +<sl-button>+ element.
|
6
|
+
def sl_button_tag(**attrs, &block)
|
7
|
+
content_tag("sl-button", **attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Creates an <sl-button> tag with the href value as the caption.
|
11
|
+
def sl_button_to(body, href = nil, **attrs, &block)
|
12
|
+
if block_given?
|
13
|
+
sl_button_tag(href: body, **(href || {}), **attrs, &block)
|
14
|
+
else
|
15
|
+
sl_button_tag(href: href, **attrs) { body }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def sl_icon_tag(name, **attrs)
|
20
|
+
tag.sl_icon(name: name, **attrs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def sl_avatar_tag(source, **attrs, &block)
|
24
|
+
tag.sl_avatar(image: source, **attrs, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/gemfiles/rails_edge.gemfile
CHANGED
data/lib/shoelace/railtie.rb
CHANGED
@@ -23,18 +23,32 @@ module Shoelace
|
|
23
23
|
|
24
24
|
class Railtie < ::Rails::Railtie #:nodoc:
|
25
25
|
config.shoelace = ActiveSupport::OrderedOptions.new
|
26
|
-
|
27
|
-
|
26
|
+
|
27
|
+
# Path to the shoelace assets.
|
28
|
+
config.shoelace.dist_path = "node_modules/@shoelace-style/shoelace/dist"
|
29
|
+
|
30
|
+
# Class name that is added to a form input when the corresponding attribute has an `ActiveModel` error.
|
31
|
+
config.shoelace.invalid_input_class_name = nil
|
28
32
|
|
29
33
|
initializer "shoelace.use_rack_middleware" do |app|
|
30
34
|
icon_dir = File.join(app.paths["public"].first, "assets/icons")
|
31
35
|
|
32
36
|
if !Dir.exist?(icon_dir)
|
33
|
-
path = app.root.join(config.shoelace.dist_path).to_s
|
37
|
+
path = app.root.join(app.config.shoelace.dist_path).to_s
|
34
38
|
headers = app.config.public_file_server.headers || {}
|
35
39
|
|
36
40
|
app.config.middleware.insert_after ActionDispatch::Static, Shoelace::AssetProvider, path, index: "index.html", headers: headers
|
37
41
|
end
|
38
42
|
end
|
43
|
+
|
44
|
+
initializer "shoelace.form_helper" do |app|
|
45
|
+
ActiveSupport.on_load :action_view do
|
46
|
+
Shoelace::FormHelper.invalid_input_class_name = app.config.shoelace.invalid_input_class_name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
rake_tasks do
|
51
|
+
load "tasks/shoelace.rake"
|
52
|
+
end
|
39
53
|
end
|
40
54
|
end
|
data/lib/shoelace/testing.rb
CHANGED
@@ -7,7 +7,7 @@ module Shoelace
|
|
7
7
|
select_element.click
|
8
8
|
|
9
9
|
within select_element do
|
10
|
-
find('sl-
|
10
|
+
find('sl-option', text: option_text).click
|
11
11
|
end
|
12
12
|
|
13
13
|
select_element
|
@@ -19,7 +19,7 @@ module Shoelace
|
|
19
19
|
select_element.click
|
20
20
|
within select_element do
|
21
21
|
options_to_select.each do |option_text|
|
22
|
-
find('sl-
|
22
|
+
find('sl-option', text: option_text).click
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -12,6 +12,9 @@ namespace :shoelace do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
# Make sure `yarn install` is run before running `shoelace:icons:copy`.
|
16
|
+
Rake::Task["shoelace:icons:copy"].enhance(["javascript:build"])
|
17
|
+
|
15
18
|
if Rake::Task.task_defined?("assets:precompile")
|
16
19
|
Rake::Task["assets:precompile"].enhance(["shoelace:icons:copy"])
|
17
20
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% locations = { tokyo: "Tokyo", new_york: "New York", london: "London" } %>
|
2
|
-
<%=
|
2
|
+
<%= sl_form_for(@user, url: hotwire_forms_path) do |form| %>
|
3
3
|
<div>
|
4
4
|
<%= form.text_field :name do %>
|
5
5
|
<span slot="help-text" style="color: rgb(var(--sl-color-danger-600));">
|
@@ -21,8 +21,8 @@
|
|
21
21
|
}
|
22
22
|
</style>
|
23
23
|
|
24
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.
|
25
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.
|
24
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.88/dist/themes/light.css">
|
25
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.88/dist/shoelace.js"></script>
|
26
26
|
|
27
27
|
<% if request.path.include?("hotwire") %>
|
28
28
|
<%= javascript_pack_tag 'hotwire' %>
|
@@ -22,7 +22,6 @@ class HotwireFormTest < ApplicationSystemTestCase
|
|
22
22
|
assert_current_path hotwire_form_path(1)
|
23
23
|
assert_text "Name: Yuki Nishijima"
|
24
24
|
assert_text "Description: I am a human."
|
25
|
-
assert_text "Color: #ffffff"
|
26
25
|
assert_text "Score: 50"
|
27
26
|
# assert_text "Current City:"
|
28
27
|
assert_text "Previous City: tokyo"
|
@@ -48,7 +47,6 @@ class HotwireFormTest < ApplicationSystemTestCase
|
|
48
47
|
assert_current_path hotwire_form_path(1)
|
49
48
|
assert_text "Name: Yuki Nishijima"
|
50
49
|
assert_text "Description: I am a human."
|
51
|
-
assert_text "Color: #ffffff"
|
52
50
|
assert_text "Score: 50"
|
53
51
|
# assert_text "Current City:"
|
54
52
|
assert_text "Previous City: tokyo"
|
@@ -22,7 +22,6 @@ class TurbolinksFormTest < ApplicationSystemTestCase
|
|
22
22
|
assert_current_path turbolinks_forms_path
|
23
23
|
assert_text "Name: Yuki Nishijima"
|
24
24
|
assert_text "Description: I am a human."
|
25
|
-
assert_text "Color: #ffffff"
|
26
25
|
assert_text "Score: 50"
|
27
26
|
# assert_text "Current City:"
|
28
27
|
assert_text "Previous City: tokyo"
|
@@ -44,26 +44,12 @@ class FormHelperTest < ActionView::TestCase
|
|
44
44
|
HTML
|
45
45
|
end
|
46
46
|
|
47
|
-
test "#sl_button_tag" do
|
48
|
-
assert_dom_equal(<<~HTML, sl_button_tag { "Submit" })
|
49
|
-
<sl-button>Submit</sl-button>
|
50
|
-
HTML
|
51
|
-
end
|
52
|
-
|
53
47
|
test "#sl_radio_button" do
|
54
48
|
assert_dom_equal(<<~HTML, sl_radio_button(:user, :name, 'userid-314', checked: true) { "Yuki Nishijima" })
|
55
49
|
<sl-radio value="userid-314" checked="checked" name="user[name]" id="user_name_userid-314">Yuki Nishijima</sl-radio>
|
56
50
|
HTML
|
57
51
|
end
|
58
52
|
|
59
|
-
test "#sl_form_tag" do
|
60
|
-
assert_dom_equal(<<~HTML, sl_form_tag("/posts") { })
|
61
|
-
<form data-remote="true" action="/posts" accept-charset="UTF-8" method="post">
|
62
|
-
<input name="utf8" type="hidden" value="✓" #{AUTOCOMPLETE_ATTRIBUTE} />
|
63
|
-
</sl-form>
|
64
|
-
HTML
|
65
|
-
end
|
66
|
-
|
67
53
|
test "#sl_form_with" do
|
68
54
|
assert_dom_equal(<<~HTML, sl_form_with(url: "/") {})
|
69
55
|
<form action="/" accept-charset="UTF-8" data-remote="true" method="post">
|
@@ -80,30 +66,6 @@ class FormHelperTest < ActionView::TestCase
|
|
80
66
|
HTML
|
81
67
|
end
|
82
68
|
|
83
|
-
test "#sl_turbo_form_tag" do
|
84
|
-
assert_dom_equal(<<~HTML, sl_turbo_form_tag("/posts") { })
|
85
|
-
<form action="/posts" accept-charset="UTF-8" method="post">
|
86
|
-
<input name="utf8" type="hidden" value="✓" #{AUTOCOMPLETE_ATTRIBUTE} />
|
87
|
-
</form>
|
88
|
-
HTML
|
89
|
-
end
|
90
|
-
|
91
|
-
test "#sl_turbo_form_with" do
|
92
|
-
assert_dom_equal(<<~HTML, sl_turbo_form_with(url: "/") {})
|
93
|
-
<form action="/" accept-charset="UTF-8" data-remote="true" method="post">
|
94
|
-
<input name="utf8" type="hidden" value="✓" #{AUTOCOMPLETE_ATTRIBUTE} />
|
95
|
-
</form>
|
96
|
-
HTML
|
97
|
-
end
|
98
|
-
|
99
|
-
test "#sl_turbo_form_for" do
|
100
|
-
assert_dom_equal(<<~HTML, sl_turbo_form_for(User.new, url: "/") { })
|
101
|
-
<form class="new_user" id="new_user" action="/" accept-charset="UTF-8" method="post">
|
102
|
-
<input name="utf8" type="hidden" value="✓" #{AUTOCOMPLETE_ATTRIBUTE} />
|
103
|
-
</form>
|
104
|
-
HTML
|
105
|
-
end
|
106
|
-
|
107
69
|
test "#text_field" do
|
108
70
|
sl_form_for(User.new, url: "/") do |form|
|
109
71
|
assert_dom_equal <<~HTML, form.text_field(:name)
|
@@ -195,6 +157,14 @@ class FormHelperTest < ActionView::TestCase
|
|
195
157
|
test "#range_field" do
|
196
158
|
sl_form_for(User.new, url: "/") do |form|
|
197
159
|
assert_dom_equal <<~HTML, form.range_field(:name)
|
160
|
+
<sl-range label="Name" name="user[name]" id="user_name"></sl-range>
|
161
|
+
HTML
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
test "#range_field without a label" do
|
166
|
+
sl_form_for(User.new, url: "/") do |form|
|
167
|
+
assert_dom_equal <<~HTML, form.range_field(:name, label: nil)
|
198
168
|
<sl-range name="user[name]" id="user_name"></sl-range>
|
199
169
|
HTML
|
200
170
|
end
|
@@ -211,22 +181,92 @@ class FormHelperTest < ActionView::TestCase
|
|
211
181
|
test "#text_area" do
|
212
182
|
sl_form_for(User.new, url: "/") do |form|
|
213
183
|
assert_dom_equal <<~HTML, form.text_area(:name)
|
184
|
+
<sl-textarea label="Name" resize="auto" name="user[name]" id="user_name"></sl-textarea>
|
185
|
+
HTML
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
test "#text_area with a value" do
|
190
|
+
sl_form_for(User.new(name: "Yuki Nishijima"), url: "/") do |form|
|
191
|
+
assert_dom_equal <<~HTML, form.text_area(:name)
|
192
|
+
<sl-textarea label="Name" resize="auto" value="Yuki Nishijima" name="user[name]" id="user_name"></sl-textarea>
|
193
|
+
HTML
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
test "#text_area with an one-off value" do
|
198
|
+
sl_form_for(User.new(name: "Yuki Nishijima"), url: "/") do |form|
|
199
|
+
assert_dom_equal <<~HTML, form.text_area(:name, value: "Yuki")
|
200
|
+
<sl-textarea label="Name" resize="auto" value="Yuki" name="user[name]" id="user_name"></sl-textarea>
|
201
|
+
HTML
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
test "#text_area without a label" do
|
206
|
+
sl_form_for(User.new, url: "/") do |form|
|
207
|
+
assert_dom_equal <<~HTML, form.text_area(:name, label: nil)
|
214
208
|
<sl-textarea resize="auto" name="user[name]" id="user_name"></sl-textarea>
|
215
209
|
HTML
|
216
210
|
end
|
217
211
|
end
|
218
212
|
|
219
|
-
test "#
|
213
|
+
test "#text_area with a size" do
|
220
214
|
sl_form_for(User.new, url: "/") do |form|
|
221
|
-
assert_dom_equal <<~HTML, form.
|
222
|
-
<sl-
|
215
|
+
assert_dom_equal <<~HTML, form.text_area(:name, size: "small")
|
216
|
+
<sl-textarea label="Name" resize="auto" size="small" name="user[name]" id="user_name"></sl-textarea>
|
223
217
|
HTML
|
224
218
|
end
|
225
219
|
end
|
226
220
|
|
221
|
+
test "#text_area with a block" do
|
222
|
+
sl_form_for(User.new, url: "/") do |form|
|
223
|
+
expected = <<~HTML
|
224
|
+
<sl-textarea label="Name" resize="auto" name="user[name]" id="user_name">
|
225
|
+
<div slot="help-text">Name can not be blank.</div>
|
226
|
+
</sl-textarea>
|
227
|
+
HTML
|
228
|
+
|
229
|
+
assert_dom_equal(expected, form.text_area(:name) {
|
230
|
+
content_tag(:div, "Name can not be blank.", slot: "help-text")
|
231
|
+
})
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
test "#check_box" do
|
236
|
+
sl_form_for(User.new, url: "/") do |form|
|
237
|
+
if ActionView::VERSION::STRING >= '6.1.0'
|
238
|
+
assert_dom_equal <<~HTML, form.check_box(:name)
|
239
|
+
<input name="user[name]" type="hidden" value="0" autocomplete="off" />
|
240
|
+
<sl-checkbox value="1" name="user[name]" id="user_name">Name</sl-checkbox>
|
241
|
+
HTML
|
242
|
+
else
|
243
|
+
assert_dom_equal <<~HTML, form.check_box(:name)
|
244
|
+
<input name="user[name]" type="hidden" value="0" />
|
245
|
+
<sl-checkbox value="1" name="user[name]" id="user_name">Name</sl-checkbox>
|
246
|
+
HTML
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
227
251
|
test "#check_box with a block" do
|
228
252
|
sl_form_for(User.new, url: "/") do |form|
|
229
|
-
|
253
|
+
if ActionView::VERSION::STRING >= '6.1.0'
|
254
|
+
assert_dom_equal <<~HTML, form.check_box(:name) { "Maintainer Name" }
|
255
|
+
<input name="user[name]" type="hidden" value="0" autocomplete="off" />
|
256
|
+
<sl-checkbox value="1" name="user[name]" id="user_name">Maintainer Name</sl-checkbox>
|
257
|
+
HTML
|
258
|
+
else
|
259
|
+
assert_dom_equal <<~HTML, form.check_box(:name) { "Maintainer Name" }
|
260
|
+
<input name="user[name]" type="hidden" value="0" />
|
261
|
+
<sl-checkbox value="1" name="user[name]" id="user_name">Maintainer Name</sl-checkbox>
|
262
|
+
HTML
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
test "#check_box without a hidden input" do
|
268
|
+
sl_form_for(User.new, url: "/") do |form|
|
269
|
+
assert_dom_equal <<~HTML, form.check_box(:name, include_hidden: false) { "Maintainer Name" }
|
230
270
|
<sl-checkbox value="1" name="user[name]" id="user_name">Maintainer Name</sl-checkbox>
|
231
271
|
HTML
|
232
272
|
end
|
@@ -241,10 +281,46 @@ class FormHelperTest < ActionView::TestCase
|
|
241
281
|
|
242
282
|
sl_form_for(User.new, url: "/") do |form|
|
243
283
|
assert_dom_equal <<~HTML, form.select(:name, users)
|
244
|
-
<sl-select name="user[name]" id="user_name">
|
245
|
-
<sl-
|
246
|
-
<sl-
|
247
|
-
<sl-
|
284
|
+
<sl-select label="Name" name="user[name]" id="user_name">
|
285
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
286
|
+
<sl-option value="2">Matz</sl-option>
|
287
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
288
|
+
</sl-select>
|
289
|
+
HTML
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
test "#select with a custom value" do
|
294
|
+
users = {
|
295
|
+
"Yuki Nishijima" => 1,
|
296
|
+
"Matz" => 2,
|
297
|
+
"Koichi Sasada" => 3
|
298
|
+
}
|
299
|
+
|
300
|
+
sl_form_for(User.new, url: "/") do |form|
|
301
|
+
assert_dom_equal <<~HTML, form.select(:name, users, {}, { value: 3 })
|
302
|
+
<sl-select label="Name" value="3" name="user[name]" id="user_name">
|
303
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
304
|
+
<sl-option value="2">Matz</sl-option>
|
305
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
306
|
+
</sl-select>
|
307
|
+
HTML
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
test "#select with custom selected and disabled values" do
|
312
|
+
users = {
|
313
|
+
"Yuki Nishijima" => 1,
|
314
|
+
"Matz" => 2,
|
315
|
+
"Koichi Sasada" => 3
|
316
|
+
}
|
317
|
+
|
318
|
+
sl_form_for(User.new, url: "/") do |form|
|
319
|
+
assert_dom_equal <<~HTML, form.select(:name, users, selected: 3, disabled: 1)
|
320
|
+
<sl-select label="Name" name="user[name]" id="user_name">
|
321
|
+
<sl-option value="1" disabled="disabled">Yuki Nishijima</sl-option>
|
322
|
+
<sl-option value="2">Matz</sl-option>
|
323
|
+
<sl-option value="3" checked="checked">Koichi Sasada</sl-option>
|
248
324
|
</sl-select>
|
249
325
|
HTML
|
250
326
|
end
|
@@ -259,10 +335,10 @@ class FormHelperTest < ActionView::TestCase
|
|
259
335
|
|
260
336
|
sl_form_for(User.new, url: "/") do |form|
|
261
337
|
assert_dom_equal <<~HTML, form.select(:name, users, {}, { multiple: true })
|
262
|
-
<sl-select name="user[name][]" id="user_name" multiple="multiple">
|
263
|
-
<sl-
|
264
|
-
<sl-
|
265
|
-
<sl-
|
338
|
+
<sl-select label="Name" name="user[name][]" id="user_name" multiple="multiple">
|
339
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
340
|
+
<sl-option value="2">Matz</sl-option>
|
341
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
266
342
|
</sl-select>
|
267
343
|
HTML
|
268
344
|
end
|
@@ -281,13 +357,13 @@ class FormHelperTest < ActionView::TestCase
|
|
281
357
|
|
282
358
|
sl_form_for(User.new, url: "/") do |form|
|
283
359
|
assert_dom_equal <<~HTML, form.select(:name, users)
|
284
|
-
<sl-select name="user[name]" id="user_name">
|
285
|
-
<
|
286
|
-
<sl-
|
287
|
-
<sl-
|
360
|
+
<sl-select label="Name" name="user[name]" id="user_name">
|
361
|
+
<small>Main maintainers</small>
|
362
|
+
<sl-option value="2">Matz</sl-option>
|
363
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
288
364
|
<sl-divider></sl-divider>
|
289
|
-
<
|
290
|
-
<sl-
|
365
|
+
<small>Default gem maintainers</small>
|
366
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
291
367
|
</sl-select>
|
292
368
|
HTML
|
293
369
|
end
|
@@ -304,15 +380,15 @@ class FormHelperTest < ActionView::TestCase
|
|
304
380
|
]
|
305
381
|
}
|
306
382
|
|
307
|
-
sl_form_for(User.new(name:
|
383
|
+
sl_form_for(User.new(name: 2), url: "/") do |form|
|
308
384
|
assert_dom_equal <<~HTML, form.select(:name, users)
|
309
|
-
<sl-select name="user[name]" id="user_name" value="2">
|
310
|
-
<
|
311
|
-
<sl-
|
312
|
-
<sl-
|
385
|
+
<sl-select label="Name" name="user[name]" id="user_name" value="2">
|
386
|
+
<small>Main maintainers</small>
|
387
|
+
<sl-option value="2" checked="checked">Matz</sl-option>
|
388
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
313
389
|
<sl-divider></sl-divider>
|
314
|
-
<
|
315
|
-
<sl-
|
390
|
+
<small>Default gem maintainers</small>
|
391
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
316
392
|
</sl-select>
|
317
393
|
HTML
|
318
394
|
end
|
@@ -327,10 +403,10 @@ class FormHelperTest < ActionView::TestCase
|
|
327
403
|
|
328
404
|
sl_form_for(User.new, url: "/") do |form|
|
329
405
|
assert_dom_equal <<~HTML, form.collection_select(:name, users, :first, :last)
|
330
|
-
<sl-select name="user[name]" id="user_name">
|
331
|
-
<sl-
|
332
|
-
<sl-
|
333
|
-
<sl-
|
406
|
+
<sl-select label="Name" name="user[name]" id="user_name">
|
407
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
408
|
+
<sl-option value="2">Matz</sl-option>
|
409
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
334
410
|
</sl-select>
|
335
411
|
HTML
|
336
412
|
end
|
@@ -345,10 +421,10 @@ class FormHelperTest < ActionView::TestCase
|
|
345
421
|
|
346
422
|
sl_form_for(User.new(name: "2"), url: "/") do |form|
|
347
423
|
assert_dom_equal <<~HTML, form.collection_select(:name, users, :first, :last)
|
348
|
-
<sl-select name="user[name]" id="user_name" value="2">
|
349
|
-
<sl-
|
350
|
-
<sl-
|
351
|
-
<sl-
|
424
|
+
<sl-select label="Name" name="user[name]" id="user_name" value="2">
|
425
|
+
<sl-option value="1">Yuki Nishijima</sl-option>
|
426
|
+
<sl-option value="2" checked="checked">Matz</sl-option>
|
427
|
+
<sl-option value="3">Koichi Sasada</sl-option>
|
352
428
|
</sl-select>
|
353
429
|
HTML
|
354
430
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
require_relative '../../app/helpers/shoelace/tag_helper'
|
5
|
+
|
6
|
+
class TagHelperTest < ActionView::TestCase
|
7
|
+
include Shoelace::TagHelper
|
8
|
+
|
9
|
+
test "#sl_button_tag" do
|
10
|
+
assert_dom_equal(<<~HTML, sl_button_tag { "Submit" })
|
11
|
+
<sl-button>Submit</sl-button>
|
12
|
+
HTML
|
13
|
+
end
|
14
|
+
|
15
|
+
test "#sl_button_to" do
|
16
|
+
assert_dom_equal <<~HTML, sl_button_to("Next", "/next")
|
17
|
+
<sl-button href="/next">Next</sl-button>
|
18
|
+
HTML
|
19
|
+
|
20
|
+
assert_dom_equal <<~HTML, sl_button_to("Next", "/next", class: "mt-1")
|
21
|
+
<sl-button href="/next" class="mt-1">Next</sl-button>
|
22
|
+
HTML
|
23
|
+
|
24
|
+
assert_dom_equal(<<~HTML, sl_button_to("/next") { "Next" })
|
25
|
+
<sl-button href="/next">Next</sl-button>
|
26
|
+
HTML
|
27
|
+
|
28
|
+
assert_dom_equal(<<~HTML, sl_button_to("/next", class: "mt-1") { "Next" })
|
29
|
+
<sl-button href="/next" class="mt-1">Next</sl-button>
|
30
|
+
HTML
|
31
|
+
|
32
|
+
assert_dom_equal <<~HTML, sl_button_to("Next")
|
33
|
+
<sl-button>Next</sl-button>
|
34
|
+
HTML
|
35
|
+
end
|
36
|
+
|
37
|
+
test "#sl_icon_tag"do
|
38
|
+
assert_dom_equal <<~HTML, sl_icon_tag("0-circle-fill")
|
39
|
+
<sl-icon name="0-circle-fill"></sl-icon>
|
40
|
+
HTML
|
41
|
+
|
42
|
+
assert_dom_equal <<~HTML, sl_icon_tag("0-circle-fill", slot: "icon")
|
43
|
+
<sl-icon name="0-circle-fill" slot="icon"></sl-icon>
|
44
|
+
HTML
|
45
|
+
end
|
46
|
+
|
47
|
+
test "#sl_avatar_tag"do
|
48
|
+
assert_dom_equal <<~HTML, sl_avatar_tag("/path/to/image.jpg")
|
49
|
+
<sl-avatar image="/path/to/image.jpg"></sl-avatar>
|
50
|
+
HTML
|
51
|
+
|
52
|
+
assert_dom_equal(<<~HTML, sl_avatar_tag("/path/to/image.jpg", slot: "trigger") { "Body" })
|
53
|
+
<sl-avatar image="/path/to/image.jpg" slot="trigger">
|
54
|
+
Body
|
55
|
+
</sl-avatar>
|
56
|
+
HTML
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shoelace-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuki Nishijima
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -98,6 +98,7 @@ files:
|
|
98
98
|
- README.md
|
99
99
|
- Rakefile
|
100
100
|
- app/helpers/shoelace/form_helper.rb
|
101
|
+
- app/helpers/shoelace/tag_helper.rb
|
101
102
|
- bin/console
|
102
103
|
- bin/setup
|
103
104
|
- dist/.keep
|
@@ -114,7 +115,7 @@ files:
|
|
114
115
|
- lib/shoelace/rails/version.rb
|
115
116
|
- lib/shoelace/railtie.rb
|
116
117
|
- lib/shoelace/testing.rb
|
117
|
-
- lib/tasks/
|
118
|
+
- lib/tasks/shoelace.rake
|
118
119
|
- package.json
|
119
120
|
- rollup.config.js
|
120
121
|
- shoelace-rails.gemspec
|
@@ -166,6 +167,7 @@ files:
|
|
166
167
|
- test/dummy_app/test/system/turbolinks_form_test.rb
|
167
168
|
- test/dummy_app/test/test_helper.rb
|
168
169
|
- test/helpers/form_helper_test.rb
|
170
|
+
- test/helpers/tag_helper_test.rb
|
169
171
|
- test/test_helper.rb
|
170
172
|
- tsconfig.json
|
171
173
|
- yarn.lock
|
@@ -191,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
193
|
- !ruby/object:Gem::Version
|
192
194
|
version: '0'
|
193
195
|
requirements: []
|
194
|
-
rubygems_version: 3.
|
196
|
+
rubygems_version: 3.4.2
|
195
197
|
signing_key:
|
196
198
|
specification_version: 4
|
197
199
|
summary: Rails view helpers Shoelace.style, the design system.
|