clsx-rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8f910e1aa08bd5f0ed39ae1e8b6472cc5c2c7872fbccdbb11ad8269cfb8ac5ff
4
+ data.tar.gz: fb198c1b483216c51529869c66ed7d30b6ea4263ad7c97e9a7d9c9a077c2d8a4
5
+ SHA512:
6
+ metadata.gz: 7cea9003c893fbc6cd5de38f42767a4b06156176fea6fbf2c5be67aa90452546d9a9c8f53f66db2ea77c69cc98abcdeddd2814311cf5daf834b11f0c11245bf0
7
+ data.tar.gz: 74be5e9a20bf2e34d1e295d71ba249a8dfadcb7a9b74704de908e4289a6fc28a31f838053d13be6f29336d69981888fc8bb27c505ca5985ee9a307ac8fd12b4e
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [1.0.0] - 2024-03-03
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Leonid Svyatov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # clsx-rails
2
+
3
+ > A tiny Rails view helper for constructing CSS class strings conditionally.
4
+
5
+ This gem is essentially a clone if the [clsx](https://github.com/lukeed/clsx) npm package.
6
+ It provides a simple way to conditionally apply classes to HTML elements in Rails views.
7
+ It is especially useful when you have a lot of conditional classes and you want to keep your views clean and readable.
8
+
9
+ ## Installation
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add clsx-rails
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install clsx-rails
18
+
19
+ ## Usage
20
+
21
+ The `clsx` method can be used in views to conditionally apply classes to HTML elements.
22
+ You can also use a slightly more conise `cn` alias.
23
+ It accepts a variety of arguments and returns a string of classes.
24
+
25
+ ```ruby
26
+ # Strings (variadic)
27
+ clsx('foo', true && 'bar', 'baz')
28
+ # => 'foo bar baz'
29
+
30
+ # Hashes
31
+ cn({ foo: true, bar: false, baz: a_method_that_returns_true })
32
+ # => 'foo baz'
33
+
34
+ # Hashes (variadic)
35
+ clsx({ foo: true }, { bar: false }, nil, { '--foobar': 'hello' })
36
+ # => 'foo --foobar'
37
+
38
+ # Arrays
39
+ cn(['foo', nil, false, 'bar'])
40
+ # => 'foo bar'
41
+
42
+ # Arrays (variadic)
43
+ clsx(['foo'], ['', nil, false, 'bar'], [['baz', [['hello'], 'there']]])
44
+ # => 'foo bar baz hello there'
45
+
46
+ # Kitchen sink (with nesting)
47
+ cn('foo', ['bar', { baz: false, bat: nil }, ['hello', ['world']]], 'cya');
48
+ # => 'foo bar hello world cya'
49
+ ```
50
+
51
+ ```erb
52
+ <%= tag.div class: clsx('foo', 'baz', 'is-active' => @active) do %>
53
+ Hello, world!
54
+ <% end %>
55
+
56
+ <div class="<%= clsx('foo', 'baz', 'is-active' => @active) %>">
57
+ Hello, world!
58
+ </div>
59
+ ```
60
+
61
+ ```haml
62
+ %div{class: clsx('foo', 'baz', 'is-active' => @active)}
63
+ Hello, world!
64
+ ```
65
+
66
+ ```slim
67
+ div class=clsx('foo', 'baz', 'is-active' => @active)
68
+ | Hello, world!
69
+ ```
70
+
71
+ So the basic idea is to get rid of constructions like this in your views:
72
+
73
+ ```erb
74
+ <% classes = ['foo', 'baz'] %>
75
+ <% classes << 'is-active' if @active %>
76
+
77
+ <div class="<%= classes.join(' ') %>">
78
+ Hello, world!
79
+ </div>
80
+ ```
81
+
82
+ or like this:
83
+
84
+ ```erb
85
+ <div class="<%= ['foo', 'baz', @active ? 'is-active' : nil].compact.join(' ') %>">
86
+ Hello, world!
87
+ </div>
88
+ ```
89
+
90
+ or like this:
91
+
92
+ ```erb
93
+ <div class="foo bar <%= 'is-active' if @active %>">
94
+ Hello, world!
95
+ </div>
96
+ ```
97
+
98
+ ## Differences from the original `clsx` package
99
+
100
+ This gem reproduces the functionality of the original `clsx` package, but with nuances of Ruby and Rails in mind.
101
+
102
+ The main differences are:
103
+
104
+ 1. falsy values in Ruby are only `false` and `nil`, so the `clsx` method will not accept `0`, `''`, `[]`, `{}`, etc. as falsy values.
105
+ ```ruby
106
+ clsx('foo' => 0, bar: []) # => 'foo bar'
107
+ ```
108
+
109
+ 2. `clsx-rails` supports complex hash keys, like `{ %[foo bar] => true }`, which will be converted to `foo bar` in the resulting string.
110
+ Meaning, if it's a valid input for the `clsx-rails`, it's a valid hash key.
111
+ ```ruby
112
+ clsx([{ foo: true }, 'bar'] => true) # => 'foo bar'
113
+ ```
114
+
115
+ 3. `clsx-rails` will ignore objects that are `blank?`, boolean (`true` or `false`), or an instance of `Proc` (so, procs and lambdas).
116
+ ```ruby
117
+ clsx('', [], {}, proc {}, -> {}, nil, false, true) # => nil
118
+ ```
119
+
120
+ 4. `clsx-rails` returns `nil` if there are no classes to apply, instead of an empty string.
121
+ The reason for that is not to pollute the HTML with empty `class` attributes when using Rails tag helpers: Rails will not render the `class` attribute if it's `nil`.
122
+ ```ruby
123
+ clsx(nil, false) # => nil
124
+ ```
125
+ Although, it won't help if you're using it directly in erb:
126
+ ```erb
127
+ <div class="<%= clsx(nil, false) %>">
128
+ Hello, world!
129
+ </div>
130
+ ```
131
+ This code will render `<div class="">Hello, world!</div>` anyway.
132
+
133
+ 5. `clsx-rails` eliminates duplicate classes:
134
+ ```ruby
135
+ clsx('foo', 'foo') # => 'foo'
136
+ ```
137
+
138
+ ## Development
139
+
140
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
141
+ `rake test` to run the tests. You can also run `bin/console` for an interactive
142
+ prompt that will allow you to experiment.
143
+
144
+ To install this gem onto your local machine, run `bundle exec rake install`. To
145
+ release a new version, update the version number in `version.rb`, and then run
146
+ `bundle exec rake release`, which will create a git tag for the version, push
147
+ git commits and the created tag, and push the `.gem` file to
148
+ [rubygems.org](https://rubygems.org).
149
+
150
+ There is a simple benchmark script in the `benchmark` directory.
151
+ You can run it with `bundle exec ruby benchmark/run.rb`.
152
+ I've added it for easier performance testing when making changes to the gem.
153
+
154
+ ## Contributing
155
+
156
+ Bug reports and pull requests are welcome on GitHub at https://github.com/svyatov/clsx-rails.
157
+
158
+ ## License
159
+
160
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+ require 'action_view'
5
+
6
+ # :nodoc:
7
+ module Clsx
8
+ # :nodoc:
9
+ module Helper
10
+ # The clsx function can take any number of arguments,
11
+ # each of which can be an Hash, Array, Boolean, String, or Symbol.
12
+ #
13
+ # **Important**: Any falsy values are discarded! Standalone Boolean values are discarded as well.
14
+ #
15
+ # @param [Mixed] args
16
+ #
17
+ # @return [String] the joined class names
18
+ #
19
+ # @example
20
+ # clsx('foo', 'bar') # => 'foo bar'
21
+ # clsx(true, { bar: true }) # => 'bar'
22
+ # clsx('foo', { bar: false }) # => 'foo'
23
+ # clsx({ bar: true }, 'baz', { bat: false }) # => 'bar baz'
24
+ #
25
+ # @example within a view
26
+ # <div class="<%= clsx('foo', 'bar') %>">
27
+ # <div class="<%= clsx('foo', active: @is_active, 'another-class' => @condition) %>">
28
+ # <%= tag.div class: clsx(%w[foo bar], hidden: @condition) do ... end %>
29
+ def clsx(*args)
30
+ clsx_args_processor(*args).join(' ').presence
31
+ end
32
+ alias cn clsx
33
+
34
+ private
35
+
36
+ # @param [Mixed] args
37
+ #
38
+ # @return [Set]
39
+ def clsx_args_processor(*args) # rubocop:disable Metrics/CyclomaticComplexity
40
+ result = Set.new
41
+ args.flatten!
42
+
43
+ args.each do |arg|
44
+ next if arg.blank? || arg.is_a?(TrueClass) || arg.is_a?(Proc)
45
+ next result << arg.to_s unless arg.is_a?(Hash)
46
+
47
+ arg.each { |k, v| result += clsx_args_processor(k) if v }
48
+ end
49
+
50
+ result
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clsx
4
+ VERSION = '1.0.0'
5
+ end
data/lib/clsx-rails.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ require_relative 'clsx/version'
6
+ require_relative 'clsx/helper'
7
+
8
+ # :nodoc:
9
+ module Clsx
10
+ ActiveSupport.on_load(:action_view) { include Helper }
11
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clsx-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Leonid Svyatov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-03-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionview
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ description: A tiny Rails view helper for constructing CSS class strings conditionally
28
+ email:
29
+ - leonid@svyatov.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CHANGELOG.md
35
+ - LICENSE.txt
36
+ - README.md
37
+ - lib/clsx-rails.rb
38
+ - lib/clsx/helper.rb
39
+ - lib/clsx/version.rb
40
+ homepage: https://github.com/svyatov/clsx-rails
41
+ licenses:
42
+ - MIT
43
+ metadata:
44
+ homepage_uri: https://github.com/svyatov/clsx-rails
45
+ source_code_uri: https://github.com/svyatov/clsx-rails
46
+ changelog_uri: https://github.com/svyatov/clsx-rails/blob/main/CHANGELOG.md
47
+ rubygems_mfa_required: 'true'
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 3.1.0
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.5.6
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: clsx / classnames for Rails views
67
+ test_files: []