classlist 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0623abc0509ba65bd66bc3147ee059f7d6424f082e21867031998fa66469b1f7
4
- data.tar.gz: b9c6713cebf59a58ab5a436db88249601e04fe24b8bc553775675ffdebb44361
3
+ metadata.gz: 3b46ec60d2055c6c957a429f49af57adf78b063f933334cdac92d9b62a669f6f
4
+ data.tar.gz: b1ead5e0df053f41a9faf85d4b02345910e9efe5479ec5cb483eba116aae0975
5
5
  SHA512:
6
- metadata.gz: 4fec82f539a407cf44e97beb4b83d60caf72c48ed3818e56c3900e19d53a31497729887a1f14f62fe4ffd68a7e7bb32665893d15d2fe2d9777b7469f7f9fcbb1
7
- data.tar.gz: c8bc4baae23c82f8291fb78ed0da3a251aace747016a510304021413b8e6855bcf192fe38703eb47fd213107ae6dd82b02509b3be2bf6ebf34346c963a773af7
6
+ metadata.gz: 2012cbfeea055153c58050c0e6061157bca4228c97372cddb5b7c0072abac3969c9fb20be3ef8e30c56d58845aa9c521e2b4f2b787d3c0a9c8d3bfc7afa28a41
7
+ data.tar.gz: 84a6d60146e626e2e0cef6cc6b4b31a72e459d1dcbe01848ebeb5bf4907d0eb04c78c50564c10dfdab53099aecd18a9055b447f13c88be9aaa890c1c36cfdc21
data/CHANGELOG.md CHANGED
@@ -9,4 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
 
12
- - Everything :)
12
+ -
13
+
14
+ ## [1.0.0]
15
+
16
+ ### Added
17
+
18
+ - Classlist::Reset that replaces all entries when merged
19
+ - Classlist::Remove that removes entries when merged
20
+ - DOMTokenList compatible Classlist class.
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Classlist
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/classlist`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Serverside manipulation of CSS class lists. Works especially well with Tailwind and View Components.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,7 +20,93 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- TODO: Write usage instructions here
23
+ Imagine having a component that outputs the following markup when you render it:
24
+
25
+ ```erb
26
+ <%= render(CardComponent.new) %>
27
+ ```
28
+
29
+ ```html
30
+ <div class="card float-left">...</div>
31
+ ```
32
+
33
+ Now you're tasked with implementing a card with another background color. That's easy, you think, I'll just add an option that adds more classes to the component:
34
+
35
+ ```erb
36
+ <%= render(CardComponent.new(:classes => "bg-grey")) %>
37
+ <!-- card.html.erb -->
38
+ <div class="card float-left <%= classes %>">
39
+ ```
40
+
41
+ That works and all is well. But next day the task is to make a card that isn't floated left. You could remove `float-left` from the template and move it to all calls to render:
42
+
43
+ ```erb
44
+ <%= render(CardComponent.new(:classes => "float-left bg-grey")) %>
45
+ <!-- card.html.erb -->
46
+ <div class="card <%= classes %>">
47
+ ```
48
+
49
+ Depending on the number of classes and the number of render calls that could work. But how about if you were able to write
50
+
51
+ ```erb
52
+ <%= render(CardComponent.new(:classes => Classlist::Remove.new("float-left"))) %>
53
+ ```
54
+
55
+ With Classlist you can:
56
+
57
+ ```ruby
58
+ # card_component.rb
59
+ def classes
60
+ Classlist.new("card float-left") + @classes
61
+ end
62
+ ```
63
+
64
+ ```erb
65
+ <!-- card.html.erb -->
66
+ <div class="<%= classes %>">
67
+ ```
68
+
69
+ The resulting markup will be
70
+
71
+ ```html
72
+ <div class="card">
73
+ ```
74
+
75
+ because
76
+
77
+ ```ruby
78
+ Classlist.new("card float-left") + Classlist::Remove.new("float-left") == Classlist.new("card")
79
+ ```
80
+
81
+ ### Basic usage
82
+
83
+ ```ruby
84
+ # Create a new classlist - these are equivalent:
85
+ classes = Classlist.new("pt-6 space-y-4")
86
+ classes = Classlist.new(["pt-6", "space-y-4"])
87
+
88
+ # Add classes
89
+ classes.add("md:p-8 text-center")
90
+ classes.to_s #=> "pt-6 space-y-4 md:p-8 text-center"
91
+
92
+ # Remove classes
93
+ classes.remove("md:p-8")
94
+ classes.to_s #=> "pt-6 space-y-4 text-center"
95
+
96
+ # Toggle classes
97
+ classes.toggle("hidden")
98
+ classes.to_s #=> "pt-6 space-y-4 text-center hidden"
99
+ classes.toggle("text-center")
100
+ classes.to_s #=> "pt-6 space-y-4 hidden"
101
+
102
+ # Replace classes
103
+ classes.replace("hidden", "block")
104
+ classes.to_s #=> "pt-6 space-y-4 block"
105
+ ```
106
+
107
+ ## DOM compatibility
108
+
109
+ While Classlist aims to be a feature-compatible version of [`DOMTokenList`](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList) that doesn't always make for particularily Ruby'esque methods. In cases where Ruby has similar methods named differently than the DOM, we'll prefer Ruby-style method names while keeping aliases with the names from `DOMTokenList`.
26
110
 
27
111
  ## Development
28
112
 
@@ -32,4 +116,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
116
 
33
117
  ## Contributing
34
118
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/koppen/classlist.
119
+ Bug reports and pull requests are welcome on GitHub at https://github.com/substancelab/classlist.
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "classlist"
4
+
5
+ # Classlist::Remove is a classlist that removes tokens from the original
6
+ # classlist when added to it.
7
+ class Classlist::Remove < Classlist
8
+ def merge(original)
9
+ original.entries - entries
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "classlist"
4
+
5
+ # Classlist::Reset is a classlist that removes all tokens from the original
6
+ # classlist when merged.
7
+ class Classlist::Reset < Classlist
8
+ def merge(original)
9
+ original.entries.replace(entries)
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Classlist
4
- VERSION = "0.1.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/classlist.rb CHANGED
@@ -1,12 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "forwardable"
4
+
3
5
  require_relative "classlist/version"
4
6
 
5
7
  class Classlist
8
+ class ArgumentError < ::ArgumentError; end
9
+
6
10
  class Error < StandardError; end
7
11
 
12
+ extend Forwardable
13
+ def_delegators :@entries, :each
14
+
8
15
  attr_reader :entries
9
16
 
17
+ # Returns the Classlist resulting from adding other to this classlist.
18
+ def +(other)
19
+ result = if other.is_a?(Classlist)
20
+ other.merge(self)
21
+ else
22
+ entries + build_entries(other)
23
+ end
24
+
25
+ Classlist.new(result)
26
+ end
27
+
28
+ def ==(other)
29
+ return false unless other.is_a?(self.class)
30
+
31
+ entries == other.entries
32
+ end
33
+
10
34
  # Adds the given tokens to the list, omitting any that are already present.
11
35
  def add(tokens)
12
36
  entries = build_entries(tokens)
@@ -15,10 +39,33 @@ class Classlist
15
39
  end
16
40
  end
17
41
 
42
+ def include?(token)
43
+ entries.include?(token)
44
+ end
45
+ alias_method :contains, :include?
46
+
18
47
  def initialize(entries = [])
19
48
  @entries = build_entries(entries)
20
49
  end
21
50
 
51
+ # Returns the item in the list by its index, or null if the index is greater
52
+ # than or equal to the list's length.
53
+ def item(index)
54
+ return nil if index.negative?
55
+
56
+ entries[index]
57
+ end
58
+
59
+ # An integer representing the number of objects stored in the object.
60
+ def length
61
+ entries.length
62
+ end
63
+
64
+ # Returns a list of tokens in this classlist merged with the given classlist.
65
+ def merge(classlist)
66
+ (classlist.entries + entries).uniq
67
+ end
68
+
22
69
  # Removes the specified tokens from the classlist, ignoring any that are not
23
70
  # present.
24
71
  def remove(tokens)
@@ -32,10 +79,10 @@ class Classlist
32
79
  # exist, #replace returns false immediately, without adding the new token to
33
80
  # the token list.
34
81
  def replace(old_token, new_token)
35
- return false unless entries.include?(old_token)
82
+ return false unless include?(old_token)
36
83
 
37
- if entries.include?(new_token)
38
- entries.delete(old_token)
84
+ if include?(new_token)
85
+ remove(old_token)
39
86
  else
40
87
  index = entries.index(old_token)
41
88
  entries[index] = new_token
@@ -51,6 +98,7 @@ class Classlist
51
98
  def to_s
52
99
  entries.join(" ")
53
100
  end
101
+ alias_method :value, :to_s
54
102
 
55
103
  # Removes an existing token from the list and returns false. If the token
56
104
  # doesn't exist it's added and the function returns true.
@@ -59,11 +107,13 @@ class Classlist
59
107
  # set to false, then token will only be removed, but not added. If set to
60
108
  # true, then token will only be added, but not removed.
61
109
  def toggle(token, force = nil)
110
+ raise ArgumentError, "The token can not contain whitespace." if token.to_s.include?(" ")
111
+
62
112
  if entries.include?(token)
63
- entries.delete(token) unless force == true
113
+ remove(token) unless force == true
64
114
  result = false
65
115
  else
66
- entries.push(token) unless force == false
116
+ add(token) unless force == false
67
117
  result = true
68
118
  end
69
119
 
@@ -90,6 +140,6 @@ class Classlist
90
140
  entries.split(" ")
91
141
  else
92
142
  raise Error, "Invalid entries: #{entries.inspect}"
93
- end
143
+ end.uniq
94
144
  end
95
145
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: classlist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakob Skjerning
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-29 00:00:00.000000000 Z
11
+ date: 2022-11-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Serverside manipulation of lists of CSS classnames that play nicely with
14
14
  View Components.
@@ -28,6 +28,8 @@ files:
28
28
  - bin/setup
29
29
  - classlist.gemspec
30
30
  - lib/classlist.rb
31
+ - lib/classlist/remove.rb
32
+ - lib/classlist/reset.rb
31
33
  - lib/classlist/version.rb
32
34
  - sig/classlist.rbs
33
35
  homepage: https://github.com/substancelab/classlist