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 +4 -4
- data/CHANGELOG.md +20 -1
- data/README.md +88 -23
- data/lib/phlex/slotable/version.rb +1 -1
- data/lib/phlex/slotable.rb +13 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09e928c0d1e4cec5220e01d3e6b06ebc5fef4b50ed8f43bdf3634e89f91d201f'
|
4
|
+
data.tar.gz: 726cadd0901159f4cdb083d80300658b44b00da06515946f38fc3701b2ea019b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
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
|
16
|
+
$ gem install phlex-slotable
|
14
17
|
|
15
18
|
## Usage
|
16
19
|
|
17
20
|
#### Basic
|
18
21
|
|
19
|
-
|
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`
|
22
|
-
- `slot :slot_name, many: true`
|
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,
|
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
|
-
|
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
|
-
|
50
|
+
div id: "header" do
|
48
51
|
render header_slot
|
49
52
|
end
|
50
53
|
|
51
|
-
|
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
|
-
|
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
|
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
|
-
|
112
|
+
if header_slot?
|
110
113
|
div id: "header" do
|
111
114
|
render header_slot
|
112
115
|
end
|
113
116
|
end
|
114
117
|
|
115
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
165
|
+
if header_slot?
|
163
166
|
div id: "header" do
|
164
167
|
render header_slot
|
165
168
|
end
|
166
169
|
end
|
167
170
|
|
168
|
-
|
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
|
-
|
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
|
-
|
213
|
-
|
214
|
-
|
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
|
|
data/lib/phlex/slotable.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2024-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: phlex
|