phlex-slotable 0.1.0 → 0.2.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: a1aa68f30783948c69ae6e3a9018e3e0fe828b8d1e3392208bbd926dead27761
4
- data.tar.gz: f60047a296679c099258024d72e23d13a252bd4f5fd38576769716218785d962
3
+ metadata.gz: '09e928c0d1e4cec5220e01d3e6b06ebc5fef4b50ed8f43bdf3634e89f91d201f'
4
+ data.tar.gz: 726cadd0901159f4cdb083d80300658b44b00da06515946f38fc3701b2ea019b
5
5
  SHA512:
6
- metadata.gz: cf5b19581bab8cb2ba50e91e44f9489b40cbdae7c0873310a98637be51cbac6212e8621a95f67bd8d5d1ad1286533b66023847c4ac4eacbe2a7f867635b2bfaa
7
- data.tar.gz: d1e6a2cb591541105802d4338b857baf99ef5817aacbdd644f5a6ad3e77a4ac60669c8b5f0d9f7bdae63565e05f6fe7cbe6852e29aac88aa31366def63a5ac01
6
+ metadata.gz: 42f10716289705dd92edc63b31637781f490eb02348a6f17911229a5798a31e7a7bc905c990c6b3770cbf5b1bd31110279c509649ac25f16c1b449bc757a4cdf
7
+ data.tar.gz: 9c050854b88de83f4a4edbbf2ea8c05cf34938d89c5bb0a8b9c4a056c84363c93582091afa3b6f2a91f393dffcf262a6f8f81a936d229c4edfff2ad779724533
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.0] - 2024-02-13
4
+
5
+ - Allow view slots using string as class name
6
+
7
+ *stephannv*
8
+
9
+ - Allow lambda slots
10
+
11
+ *stephannv*
12
+
3
13
  ## [0.1.0] - 2024-02-12
14
+ - Add single and multi slots
15
+
16
+ *stephannv*
17
+
18
+ - Add generic slots
19
+
20
+ *stephannv*
21
+
22
+ - Add view slots
4
23
 
5
- - Initial release
24
+ *stephannv*
data/README.md CHANGED
@@ -1,25 +1,28 @@
1
+ > [!WARNING]
2
+ > Please note that Phlex::Slotable is currently under development and may undergo changes to its API before reaching the stable release (1.0.0). As a result, there may be breaking changes that affect its usage.
3
+
1
4
  # Phlex::Slotable
2
5
 
3
- Phlex::Slotable enables slots feature to Phlex views. Inspired by ViewComponent.
6
+ Phlex::Slotable enables slots feature to [Phlex](https://www.phlex.fun/) views. Inspired by ViewComponent.
4
7
 
5
8
  ## Installation
6
9
 
7
10
  Install the gem and add to the application's Gemfile by executing:
8
11
 
9
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
12
+ $ bundle add phlex-slotable
10
13
 
11
14
  If bundler is not being used to manage dependencies, install the gem by executing:
12
15
 
13
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
16
+ $ gem install phlex-slotable
14
17
 
15
18
  ## Usage
16
19
 
17
20
  #### Basic
18
21
 
19
- Include `Phlex::Slotable` to your Phlex view and use `slot` class method to define slots.
22
+ To incorportate slots into your Phlex views, include `Phlex::Slotable` and utilize `slot` class method to define them.
20
23
 
21
- - `slot :slot_name` defines a single slot that will be rendered at most once per component
22
- - `slot :slot_name, many: true` defines a slot that can be rendered multiple times per component
24
+ - `slot :slot_name` declaration establishes a single slot intended for rendering once within a view
25
+ - `slot :slot_name, many: true` denotes a slot capable of being rendered multiple times within a view
23
26
 
24
27
  ```ruby
25
28
  class BlogComponent < Phlex::HTML
@@ -32,9 +35,9 @@ class BlogComponent < Phlex::HTML
32
35
  end
33
36
  ```
34
37
 
35
- To render a single slot, render `{slot_name}_slot`, eg. `render header_slot`.
38
+ To render a single slot, utilize the `{slot_name}_slot` method. For example, you can render the `header_slot` using `render header_slot`.
36
39
 
37
- To render a multi slot, iterate over `{slot_name}_slots` and render each element, eg. `post_slots.each { |s| render s }`
40
+ For multi-slot rendering, iterate over the `{slot_name}_slots` collection and and render each slot individually, eg. `post_slots.each { |s| render s }`.
38
41
 
39
42
  ```ruby
40
43
  class BlogComponent < Phlex::HTML
@@ -44,11 +47,11 @@ class BlogComponent < Phlex::HTML
44
47
  slot :post, many: true
45
48
 
46
49
  def template
47
- div id: "header" do
50
+ div id: "header" do
48
51
  render header_slot
49
52
  end
50
53
 
51
- div id: "main" do
54
+ div id: "main" do
52
55
  post_slots.each do |slot|
53
56
  p { render slot }
54
57
  end
@@ -59,7 +62,7 @@ class BlogComponent < Phlex::HTML
59
62
  end
60
63
  ```
61
64
 
62
- To set slot content, you need to use `with_{slot_name}` when rendering the view:
65
+ When setting slot content, ensure to utilize the `with_{slot_name}` method while rendering the view:
63
66
 
64
67
  ```ruby
65
68
  class MyPage < Phlex::HTML
@@ -96,7 +99,7 @@ This will output:
96
99
 
97
100
  #### Predicate methods
98
101
 
99
- You can check if a slot has been passed to the component using `{slot_name}_slot?` when it is a single slot, or `{slot_name}_slots?` when it is a multi slot.
102
+ You can verify whether a slot has been provided to the view using `{slot_name}_slot?` for single slots or `{slot_name}_slots?` when for multi-slots.
100
103
 
101
104
  ```ruby
102
105
  class BlogComponent < Phlex::HTML
@@ -106,13 +109,13 @@ class BlogComponent < Phlex::HTML
106
109
  slot :post, many: true
107
110
 
108
111
  def template
109
- if header_slot?
112
+ if header_slot?
110
113
  div id: "header" do
111
114
  render header_slot
112
115
  end
113
116
  end
114
117
 
115
- div id: "main" do
118
+ div id: "main" do
116
119
  if post_slots?
117
120
  post_slots.each do |slot|
118
121
  p { render slot }
@@ -129,11 +132,11 @@ end
129
132
 
130
133
  #### View slot
131
134
 
132
- Slots can render other views, you just need to pass the view class name to `slot` method.
135
+ Slots have the capability to render other views, Simply pass the view class name to the `slot` method.
133
136
 
134
137
  ```ruby
135
138
  class HeaderComponent < Phlex::HTML
136
- def initialize(size:)
139
+ def initialize(size:)
137
140
  @size = size
138
141
  end
139
142
 
@@ -143,7 +146,7 @@ class HeaderComponent < Phlex::HTML
143
146
  end
144
147
 
145
148
  class PostComponent < Phlex::HTML
146
- def initialize(featured:)
149
+ def initialize(featured:)
147
150
  @featured = featured
148
151
  end
149
152
 
@@ -159,13 +162,13 @@ class BlogComponent < Phlex::HTML
159
162
  slot :post, PostComponent, many: true
160
163
 
161
164
  def template
162
- if header_slot?
165
+ if header_slot?
163
166
  div id: "header" do
164
167
  render header_slot
165
168
  end
166
169
  end
167
170
 
168
- div id: "main" do
171
+ div id: "main" do
169
172
  if post_slots?
170
173
  post_slots.each { render slot }
171
174
 
@@ -207,11 +210,73 @@ The output:
207
210
  </div>
208
211
  ```
209
212
 
210
- ## Roadmap
213
+ You can pass the class name as a string for cases where the class isn't evaluated yet, such as with inner classes. For example:
214
+ ```ruby
215
+ class BlogComponent < Phlex::HTML
216
+ include Phlex::Slotable
217
+
218
+ # This will not work
219
+ slot :header, HeaderComponent # uninitialized constant BlogComponent::HeaderComponent
220
+ # You should do this
221
+ slot :header, "HeaderComponent"
222
+
223
+ private
224
+
225
+ class HeaderComponent < Phlex::HTML
226
+ # ...
227
+ end
228
+ end
229
+ ```
230
+
231
+ #### Lambda slots
232
+ Lambda slots are valuable when you prefer not to create another component for straightforward structures or when you need to render another view with specific parameters
233
+ ```ruby
234
+
235
+ class BlogComponent < Phlex::HTML
236
+ include Phlex::Slotable
237
+
238
+ slot :header, ->(size:, &content) { render HeaderComponent.new(size: size, color: "blue"), &content }
239
+ slot :post, ->(featured:, &content) { span(class: featured ? "featured" : nil, &content) }, many: true
240
+ end
241
+
242
+ class MyPage < Phlex::HTML
243
+ def template
244
+ render BlogComponent.new do |blog|
245
+ blog.with_header(size: :lg) { "Hello World!" }
246
+
247
+ blog.with_post(featured: true) { "Post A" }
248
+ blog.with_post { "Post B" }
249
+ blog.with_post { "Post C" }
250
+ end
251
+ end
252
+ end
253
+ ```
254
+
255
+ You can access the internal view state within lambda slots.For example:
256
+ ```ruby
257
+ class BlogComponent < Phlex::HTML
258
+ include Phlex::Slotable
259
+
260
+ slot :header, ->(size:, &content) { render HeaderComponent.new(size: size, color: @header_color), &content }
211
261
 
212
- [] Accepts Strings as view class name
213
- [] Allow lambda slots
214
- [] Allow polymorphic slots
262
+ def initialize(header_color:)
263
+ @header_color = header_color
264
+ end
265
+ end
266
+
267
+ class MyPage < Phlex::HTML
268
+ def template
269
+ render BlogComponent.new(header_color: "red") do |blog|
270
+ blog.with_header(size: :lg) { "Hello World!" }
271
+ end
272
+ end
273
+ end
274
+ ```
275
+
276
+ ## Roadmap
277
+ - ✅ ~~Accept Strings as view class name~~
278
+ - ✅ ~~Allow lambda slots~~
279
+ - 🕐 Allow polymorphic slots
215
280
 
216
281
  ## Development
217
282
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlex
4
4
  module Slotable
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -12,6 +12,11 @@ module Phlex
12
12
  def slot(slot_name, callable = nil, many: false)
13
13
  include Phlex::DeferredRender
14
14
 
15
+ if callable.is_a?(Proc)
16
+ define_method :"__call_#{slot_name}__", &callable
17
+ private :"__call_#{slot_name}__"
18
+ end
19
+
15
20
  if many
16
21
  define_method :"with_#{slot_name}" do |*args, **kwargs, &block|
17
22
  instance_variable_set(:"@#{slot_name}_slots", []) unless instance_variable_defined?(:"@#{slot_name}_slots")
@@ -19,6 +24,10 @@ module Phlex
19
24
  value = case callable
20
25
  when nil
21
26
  block
27
+ when String
28
+ self.class.const_get(callable).new(*args, **kwargs, &block)
29
+ when Proc
30
+ -> { self.class.instance_method(:"__call_#{slot_name}__").bind_call(self, *args, **kwargs, &block) }
22
31
  else
23
32
  callable.new(*args, **kwargs, &block)
24
33
  end
@@ -40,6 +49,10 @@ module Phlex
40
49
  value = case callable
41
50
  when nil
42
51
  block
52
+ when String
53
+ self.class.const_get(callable).new(*args, **kwargs, &block)
54
+ when Proc
55
+ -> { self.class.instance_method(:"__call_#{slot_name}__").bind_call(self, *args, **kwargs, &block) }
43
56
  else
44
57
  callable.new(*args, **kwargs, &block)
45
58
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex-slotable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - stephann
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-12 00:00:00.000000000 Z
11
+ date: 2024-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex