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 +7 -0
- data/CHANGELOG.md +17 -0
- data/LICENSE +21 -0
- data/README.md +72 -0
- data/lib/unmagic/component_partial/helper.rb +13 -0
- data/lib/unmagic/component_partial/partial.rb +30 -0
- data/lib/unmagic/component_partial/railtie.rb +14 -0
- data/lib/unmagic/component_partial/version.rb +7 -0
- data/lib/unmagic/component_partial.rb +25 -0
- data/lib/unmagic-component-partial.rb +3 -0
- metadata +99 -0
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,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
|
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: []
|