plutonium 0.60.1 → 0.60.2

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: 371d9fea402116abc683c5a86c2a23ff54d6e093a5d5d64860a905cd2fb64b72
4
- data.tar.gz: 6fc951e3e6ab822ee42c17ee843b0373b185e9e2d54b63c68906391bae04d07b
3
+ metadata.gz: bf3e52945d9a07683b9af721fd0c00f25d8850a63d7631a8a304135e13484232
4
+ data.tar.gz: 292591ab6eacc2f3565c9e959d62510e12b6e56d609ede2002372c2869b12cf5
5
5
  SHA512:
6
- metadata.gz: e3b2bbce710220fe7cdaab63cb0b35c5b271cf4c07fe246fbc6a5a96cc178b1b223947150e547bc763c5adb59454d685e50984e6978a7427813d2f8182f72fdc
7
- data.tar.gz: c243e2aa38c0ca4942655791b6a9ed8efc1e037d90ec63c1f07e1051ef4fe7fc8abf1b12af5dcb916632c301eb3eb9bdb3c7d7f4818a347992fac3a5ecc142e2
6
+ metadata.gz: 0f69cf663aa031cc3073717587c589a74bad312d9a2dad5088cb0798b07d5c3adef879f82f9cf6a25fc0a64a7d0fc996feef5f49048b26c63c6fe6b1178ae23f
7
+ data.tar.gz: 57495b760f039d03363fab2035726e00f972c581610e1d36048f6610c0a83c6777eaf22a8630d91e8c0fd24c71e171d0604b62fe1bd773f76c66cdd2f0ea4dce
@@ -506,7 +506,15 @@ Plutonium.configure do |config|
506
506
  end
507
507
  ```
508
508
 
509
- `:plain` keeps the Topbar but drops the icon rail. Override per-controller (and so per-portal, since it's an inherited `class_attribute`) with the `rail` DSL `rail false` / `rail true`; `rail nil` (default) inherits the shell default, `rail?` reads the resolved value:
509
+ `:plain` keeps the Topbar but drops the icon rail. **Shell resolves global engine controller**, each overriding the one above (`nil` falls through); read it with `controller.shell`:
510
+
511
+ ```ruby
512
+ config.shell = :plain # 1. global default
513
+ class CustomerPortal::Engine; shell :plain; # 2. per-engine (lib/engine.rb)
514
+ class DashboardController; shell :modern; # 3. per-controller (overrides engine/global)
515
+ ```
516
+
517
+ Alongside `shell`, the controller-only `rail` DSL flips just the rail (inherited `class_attribute`, so a portal opts in/out once in its concern) — `rail false` / `rail true`; `rail nil` (default) inherits the resolved shell, `rail?` reads the resolved value:
510
518
 
511
519
  ```ruby
512
520
  module CustomerPortal::Concerns::Controller
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.60.2] - 2026-06-15
2
+
3
+ ### 🚀 Features
4
+
5
+ - *(layout)* Resolve shell across global, engine, and controller tiers
1
6
  ## [0.60.1] - 2026-06-15
2
7
 
3
8
  ### 🚀 Features
@@ -18,15 +18,39 @@ If you're starting fresh, use `:modern`. `:classic` exists so apps upgrading fro
18
18
 
19
19
  ## Shell variants & the icon rail
20
20
 
21
- `config.shell` selects the chrome for the whole app:
21
+ The shell variant selects the page chrome:
22
22
 
23
23
  - `:modern` (default) — Topbar plus the desktop icon rail.
24
- - `:plain` — Topbar but **no** icon rail. The Topbar is kept; only the rail is removed, so the whole app is rail-less.
24
+ - `:plain` — Topbar but **no** icon rail. The Topbar is kept; only the rail is removed, so the surface is rail-less.
25
25
  - `:classic` — legacy Header/Sidebar (upgrade paths only).
26
26
 
27
- ### Per-controller / per-portal override
27
+ ### Resolving the shell (global → engine → controller)
28
28
 
29
- Any Plutonium resource controller exposes a class-level `rail` DSL that overrides the shell default. It's a `class_attribute`, so it's inherited: a portal opts its entire surface in or out by calling `rail false` (or `rail true`) once in its controller concern.
29
+ The shell resolves across three layers, each overriding the one above it:
30
+
31
+ ```ruby
32
+ # 1. Global default (config/initializers/plutonium.rb)
33
+ Plutonium.configure { |config| config.shell = :modern }
34
+
35
+ # 2. Per-engine — set it on a portal/package engine (lib/engine.rb)
36
+ module CustomerPortal
37
+ class Engine < Rails::Engine
38
+ include Plutonium::Portal::Engine
39
+ shell :plain # this whole portal is rail-less
40
+ end
41
+ end
42
+
43
+ # 3. Per-controller — overrides the engine/global default for one controller (and subclasses)
44
+ class DashboardController < ResourceController
45
+ shell :modern # opt this controller back into the rail
46
+ end
47
+ ```
48
+
49
+ An unset engine/controller value (`nil`) falls through to the next layer. Read the resolved value with the `shell` helper (`controller.shell`).
50
+
51
+ ### `rail` — a controller-level rail toggle
52
+
53
+ Alongside `shell`, any resource controller exposes a class-level `rail` DSL that flips just the icon rail without changing the shell. It's a `class_attribute`, so it's inherited — a portal opts its entire surface in or out by calling `rail false` (or `rail true`) once in its controller concern:
30
54
 
31
55
  ```ruby
32
56
  module CustomerPortal
@@ -39,7 +63,7 @@ module CustomerPortal
39
63
  end
40
64
  ```
41
65
 
42
- `rail nil` (the default) inherits the shell default — the rail shows when `config.shell == :modern`. Read the resolved value with the `rail?` predicate.
66
+ `rail nil` (the default) inherits the resolved shell — the rail shows when the resolved `shell == :modern`. Read the resolved value with the `rail?` predicate.
43
67
 
44
68
  ### Stable CSS hooks
45
69
 
@@ -47,7 +47,8 @@ module Plutonium
47
47
  helper_method :registered_resources
48
48
 
49
49
  class_attribute :_rail_enabled, instance_writer: false, default: nil
50
- helper_method :rail?
50
+ class_attribute :_shell, instance_writer: false, default: nil
51
+ helper_method :rail?, :shell
51
52
  end
52
53
 
53
54
  class_methods do
@@ -56,6 +57,12 @@ module Plutonium
56
57
  def rail(enabled)
57
58
  self._rail_enabled = enabled
58
59
  end
60
+
61
+ # Set the shell variant for this controller and its subclasses,
62
+ # overriding the engine/global default. nil (default) inherits.
63
+ def shell(value)
64
+ self._shell = value
65
+ end
59
66
  end
60
67
 
61
68
  # Whether the modern icon rail is active for this request. Resolves the
@@ -63,7 +70,19 @@ module Plutonium
63
70
  # Public: the resource layout calls `controller.rail?`.
64
71
  def rail?
65
72
  return _rail_enabled unless _rail_enabled.nil?
66
- Plutonium.configuration.shell == :modern
73
+ shell == :modern
74
+ end
75
+
76
+ # Resolved shell variant for this request: controller override, else the
77
+ # engine's shell, else the global Plutonium.configuration.shell.
78
+ def shell
79
+ return _shell unless _shell.nil?
80
+
81
+ engine = current_engine
82
+ engine_shell = engine.shell unless engine == Rails.application.class
83
+ return engine_shell unless engine_shell.nil?
84
+
85
+ Plutonium.configuration.shell
67
86
  end
68
87
 
69
88
  private
@@ -35,6 +35,16 @@ module Plutonium
35
35
  end
36
36
  end
37
37
  end
38
+
39
+ class_methods do
40
+ # Shell variant for this engine's controllers (:modern / :plain /
41
+ # :classic). Overrides the global Plutonium.configuration.shell and is
42
+ # itself overridden by a controller's own `shell`. Unset (nil) inherits.
43
+ def shell(value = nil)
44
+ @shell = value unless value.nil?
45
+ @shell
46
+ end
47
+ end
38
48
  end
39
49
  end
40
50
  end
@@ -52,7 +52,7 @@ module Plutonium
52
52
  # signal) for non-classic shells, since Turbo Drive does not update
53
53
  # <html> attributes across cross-URL visits.
54
54
  def render_pre_paint_scripts
55
- manage_no_rail = Plutonium.configuration.shell != :classic
55
+ manage_no_rail = pre_paint_shell != :classic
56
56
  script do
57
57
  raw(safe(<<~JS))
58
58
  (function () {
@@ -80,6 +80,11 @@ module Plutonium
80
80
  end
81
81
  end
82
82
 
83
+ # Shell variant used by pre-paint scripts. Base uses the global config
84
+ # (safe for non-resource layouts whose controllers lack #shell);
85
+ # ResourceLayout overrides this to the resolved shell.
86
+ def pre_paint_shell = Plutonium.configuration.shell
87
+
83
88
  def render_body(&)
84
89
  body(**body_attributes) {
85
90
  render_before_main
@@ -8,6 +8,12 @@ module Plutonium
8
8
  # the controller's resolution (shell default + per-controller `rail`).
9
9
  def rail? = controller.rail?
10
10
 
11
+ def shell = controller.shell
12
+
13
+ # Override Base's seam so all pre-paint shell logic uses the resolved
14
+ # (controller/engine/global) shell rather than only the global config.
15
+ def pre_paint_shell = shell
16
+
11
17
  # Sets pu-rail-pinned immediately on initial page load so the rail
12
18
  # renders in its pinned state from the first frame. Turbo navigations
13
19
  # are handled by the turbo:before-render listener in Base. Skipped
@@ -34,13 +40,13 @@ module Plutonium
34
40
  # Scoped to the modern family — :classic keeps its own offsets.
35
41
  def html_attributes
36
42
  attrs = super
37
- return attrs if Plutonium.configuration.shell == :classic
43
+ return attrs if shell == :classic
38
44
 
39
45
  rail? ? attrs : mix(attrs, {class: "pu-no-rail"})
40
46
  end
41
47
 
42
48
  def main_attributes
43
- classes = if Plutonium.configuration.shell == :classic
49
+ classes = if shell == :classic
44
50
  "pt-20 lg:ml-64"
45
51
  else
46
52
  rail? ? "pt-16 pb-6 px-6 lg:pl-20" : "pt-16 pb-6 px-6"
@@ -1,5 +1,5 @@
1
1
  module Plutonium
2
- VERSION = "0.60.1"
2
+ VERSION = "0.60.2"
3
3
  NEXT_MAJOR_VERSION = VERSION.split(".").tap { |v|
4
4
  v[1] = v[1].to_i + 1
5
5
  v[2] = 0
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.60.1",
3
+ "version": "0.60.2",
4
4
  "description": "Build production-ready Rails apps in minutes, not days. Convention-driven, fully customizable, AI-ready.",
5
5
  "type": "module",
6
6
  "main": "src/js/core.js",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plutonium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.60.1
4
+ version: 0.60.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Froelich