unmagic-component-partial 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fee998ec6fa5aaa504dbb90e3a3a13f772fb09fe6fbc3f62615548a955ff54ec
4
+ data.tar.gz: a981dfd0bef005c9c26d74354c4ec183dd7feef4380d7704a9a9791ad2ebfd47
5
+ SHA512:
6
+ metadata.gz: d98c0a37483bd3dd1738313d1aba3eb8a7b1c4596a8478acde7a7f2ab423ce7a6bcf3760660650c962e0eaa588238e53b7282ca93f7b0e88319bd9c0dd38b956
7
+ data.tar.gz: 14ab985618ec009ad9c75b43177cc7678ffb8c1b7fffc3615c6679d92844ad984bb534f6120d75097191e15f50123c290e670511213c97554bc46d31dfb3cbfd
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0]
11
+
12
+ ### Added
13
+ - `component_partial` view helper and the `Partial` slot handle — render a
14
+ partial as a layout, yield it a handle, and fill named slots the partial reads
15
+ back wherever it likes (a card footer, a header actions row).
16
+ - Rails integration: a railtie mixes the helper into ActionView, so every
17
+ template can call `component_partial` with no setup.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Keith Pitt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # unmagic-component-partial
2
+
3
+ Named slots for Rails partials rendered as layouts.
4
+
5
+ Rails partials have one body (the block you pass to `render layout:`). That's
6
+ fine until a component needs content in more than one place — a card with a body
7
+ *and* a footer, a panel with a header actions row *and* a body. The usual
8
+ workarounds (a second partial, a `content_for` global, a pile of locals carrying
9
+ pre-rendered HTML) all leak the component's structure to the caller.
10
+
11
+ This gem gives a partial **named slots**, after Dom Christie's
12
+ [Component partials](https://domchristie.co.uk/posts/component-partials/). The
13
+ caller fills slots inline; the partial reads them back wherever it likes.
14
+
15
+ ## Install
16
+
17
+ ```ruby
18
+ # Gemfile
19
+ gem "unmagic-component-partial"
20
+ ```
21
+
22
+ The railtie mixes the `component_partial` helper into ActionView automatically —
23
+ no initializer.
24
+
25
+ ## Usage
26
+
27
+ Render the partial as a layout. The block is the body, and is yielded a handle
28
+ you fill slots on:
29
+
30
+ ```erb
31
+ <%= render layout: "shared/card", locals: { title: "Profile" } do |card| %>
32
+ ...the card body...
33
+
34
+ <% card.content_for :footer do %>
35
+ <%= form.submit "Save" %>
36
+ <% end %>
37
+ <% end %>
38
+ ```
39
+
40
+ Inside the partial, grab a handle with `component_partial`, render the body with
41
+ `yield`, and read slots back where they belong:
42
+
43
+ ```erb
44
+ <%# app/views/shared/_card.html.erb %>
45
+ <% partial = component_partial %>
46
+ <section class="card">
47
+ <div class="card__body">
48
+ <%= yield partial %>
49
+ </div>
50
+
51
+ <% if partial.content_for(:footer) %>
52
+ <footer class="card__footer">
53
+ <%= partial.content_for(:footer) %>
54
+ </footer>
55
+ <% end %>
56
+ </section>
57
+ ```
58
+
59
+ The body block and the slot blocks are the *same* block, so the slots see the
60
+ caller's locals and helpers exactly as the body does.
61
+
62
+ ## API
63
+
64
+ - `component_partial` — returns a fresh `Partial` bound to the current view.
65
+ - `Partial#content_for(name, content = nil, &block)`:
66
+ - with a string or block, **writes** the slot (successive writes to the same
67
+ slot append), and returns `nil`;
68
+ - with no content, **reads** the slot back, or `nil` if it was never set.
69
+
70
+ ## License
71
+
72
+ MIT
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unmagic
4
+ module ComponentPartial
5
+ # The view helper. Mixed into ActionView by the railtie, so every template
6
+ # can call `component_partial`.
7
+ module Helper
8
+ def component_partial
9
+ Partial.new(self)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/output_safety"
4
+ require "active_support/core_ext/object/blank"
5
+
6
+ module Unmagic
7
+ module ComponentPartial
8
+ # A handle yielded to the block of a partial rendered as a layout. The block
9
+ # fills named slots; the partial reads them back wherever it likes — for
10
+ # content that isn't the main body, e.g. a card footer.
11
+ class Partial
12
+ def initialize(view_context)
13
+ @view_context = view_context
14
+ @contents = Hash.new { |h, k| h[k] = ActiveSupport::SafeBuffer.new }
15
+ end
16
+
17
+ # Write a slot (string or block), or read it back when called without
18
+ # content. Reading an unset slot returns nil.
19
+ def content_for(name, content = nil, &block)
20
+ if content || block
21
+ content = @view_context.capture(&block) if block
22
+ @contents[name] << content.to_s
23
+ nil
24
+ else
25
+ @contents[name].presence
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unmagic
4
+ module ComponentPartial
5
+ # Rails integration: make `component_partial` available in every template.
6
+ class Railtie < ::Rails::Railtie
7
+ initializer "unmagic.component_partial.helper" do
8
+ ActiveSupport.on_load(:action_view) do
9
+ include Unmagic::ComponentPartial::Helper
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unmagic
4
+ module ComponentPartial
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "component_partial/version"
4
+ require_relative "component_partial/partial"
5
+ require_relative "component_partial/helper"
6
+ require_relative "component_partial/railtie" if defined?(Rails::Railtie)
7
+
8
+ # Component-partial slots, after Dom Christie's "Component partials"
9
+ # (https://domchristie.co.uk/posts/component-partials/).
10
+ #
11
+ # Render a partial as a layout and yield it a Partial object. The block fills
12
+ # named slots that the partial reads back wherever it likes — handy for content
13
+ # that isn't the main body, e.g. a card footer:
14
+ #
15
+ # <%= render layout: "shared/card" do |card| %>
16
+ # ...body...
17
+ # <% card.content_for :footer do %><%= form.submit %><% end %>
18
+ # <% end %>
19
+ #
20
+ # and in the partial: `<%= partial.content_for(:footer) %>`, where
21
+ # `partial = component_partial`.
22
+ module Unmagic
23
+ module ComponentPartial
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "unmagic/component_partial"
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unmagic-component-partial
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Keith Pitt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-06-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionview
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '7.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ description: Render a partial as a layout and yield it a handle whose named slots
56
+ the block fills and the partial reads back wherever it likes — for content that
57
+ isn't the main body, like a card footer or a header actions row.
58
+ email:
59
+ - keith@unreasonable-magic.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - CHANGELOG.md
65
+ - LICENSE
66
+ - README.md
67
+ - lib/unmagic-component-partial.rb
68
+ - lib/unmagic/component_partial.rb
69
+ - lib/unmagic/component_partial/helper.rb
70
+ - lib/unmagic/component_partial/partial.rb
71
+ - lib/unmagic/component_partial/railtie.rb
72
+ - lib/unmagic/component_partial/version.rb
73
+ homepage: https://github.com/unreasonable-magic/unmagic-component-partial
74
+ licenses:
75
+ - MIT
76
+ metadata:
77
+ homepage_uri: https://github.com/unreasonable-magic/unmagic-component-partial
78
+ source_code_uri: https://github.com/unreasonable-magic/unmagic-component-partial
79
+ changelog_uri: https://github.com/unreasonable-magic/unmagic-component-partial/blob/main/CHANGELOG.md
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.5.22
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Named slots for Rails partials rendered as layouts
99
+ test_files: []