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
         |