classlist 0.1.0 → 1.0.0

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 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