plutonium 0.55.0 → 0.56.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium-resource/SKILL.md +21 -2
  3. data/.claude/skills/plutonium-ui/SKILL.md +15 -2
  4. data/CHANGELOG.md +31 -0
  5. data/app/assets/plutonium.css +1 -1
  6. data/app/assets/plutonium.js +94 -26
  7. data/app/assets/plutonium.js.map +2 -2
  8. data/app/assets/plutonium.min.js +9 -9
  9. data/app/assets/plutonium.min.js.map +3 -3
  10. data/config/initializers/rabl.rb +16 -0
  11. data/docs/.vitepress/config.ts +1 -0
  12. data/docs/public/templates/lite.rb +10 -0
  13. data/docs/reference/generators/lite.md +65 -0
  14. data/docs/reference/resource/definition.md +18 -2
  15. data/docs/reference/ui/assets.md +14 -0
  16. data/docs/reference/ui/displays.md +27 -1
  17. data/docs/reference/ui/forms.md +2 -1
  18. data/docs/reference/ui/layouts.md +33 -0
  19. data/docs/superpowers/plans/2026-06-04-sqlite-tune-maintenance-generators.md +857 -0
  20. data/docs/superpowers/plans/2026-06-04-sqlite-tune-maintenance-generators.md.tasks.json +45 -0
  21. data/docs/superpowers/specs/2026-06-04-sqlite-tune-maintenance-generators-design.md +238 -0
  22. data/gemfiles/rails_7.gemfile.lock +1 -1
  23. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  24. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  25. data/lib/generators/pu/core/update/update_generator.rb +4 -1
  26. data/lib/generators/pu/lib/plutonium_generators/concerns/configures_recurring.rb +89 -0
  27. data/lib/generators/pu/lite/maintenance/maintenance_generator.rb +45 -0
  28. data/lib/generators/pu/lite/maintenance/templates/app/jobs/sqlite_maintenance_job.rb.tt +60 -0
  29. data/lib/generators/pu/lite/rails_pulse/rails_pulse_generator.rb +4 -51
  30. data/lib/generators/pu/lite/rails_pulse/templates/config/initializers/rails_pulse.rb.tt +1 -1
  31. data/lib/generators/pu/lite/tune/tune_generator.rb +105 -0
  32. data/lib/plutonium/models/has_cents.rb +10 -0
  33. data/lib/plutonium/resource/controllers/interactive_actions.rb +19 -2
  34. data/lib/plutonium/routing/mapper_extensions.rb +5 -0
  35. data/lib/plutonium/ui/display/base.rb +9 -0
  36. data/lib/plutonium/ui/display/components/badge.rb +83 -0
  37. data/lib/plutonium/ui/display/components/boolean.rb +28 -6
  38. data/lib/plutonium/ui/display/components/currency.rb +50 -0
  39. data/lib/plutonium/ui/display/options/inferred_types.rb +13 -0
  40. data/lib/plutonium/ui/display/theme.rb +5 -0
  41. data/lib/plutonium/ui/form/base.rb +5 -0
  42. data/lib/plutonium/ui/form/components/toggle.rb +14 -0
  43. data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +14 -25
  44. data/lib/plutonium/ui/form/concerns/renders_repeater_row_controls.rb +67 -0
  45. data/lib/plutonium/ui/form/concerns/renders_structured_inputs.rb +5 -38
  46. data/lib/plutonium/ui/form/interaction.rb +7 -2
  47. data/lib/plutonium/ui/form/options/inferred_types.rb +2 -0
  48. data/lib/plutonium/ui/form/resource.rb +1 -0
  49. data/lib/plutonium/ui/form/theme.rb +12 -0
  50. data/lib/plutonium/ui/grid/card.rb +58 -21
  51. data/lib/plutonium/ui/layout/icon_rail.rb +29 -9
  52. data/lib/plutonium/ui/sidebar_menu.rb +29 -0
  53. data/lib/plutonium/version.rb +1 -1
  54. data/package.json +1 -1
  55. data/plutonium.gemspec +5 -4
  56. data/src/css/components.css +126 -0
  57. data/src/js/controllers/dirty_form_guard_controller.js +55 -4
  58. data/src/js/controllers/nested_resource_form_fields_controller.js +35 -12
  59. data/src/js/controllers/resource_drop_down_controller.js +49 -14
  60. metadata +19 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecf3e56a7d08f87ee2e77af368b4059655aeea666fcfefcf238256ae8564a9e8
4
- data.tar.gz: d70895506dda46cafc6933b9a972261365cdbddaff728e6eb8ad84bb3857ce0a
3
+ metadata.gz: fdb3a70cfc50828cc986040543d72e8e576497deffb3304aac601b113c507370
4
+ data.tar.gz: 7901dd81e5a9f11519224695071e1fe76c3121e8d311d1b1d6d7445fb2179667
5
5
  SHA512:
6
- metadata.gz: d8e6d17854893f67732bfb97ecc7cf744501d5469df99bfd0c3e5c9b8f39d16818c93c270e586f6cd486c4559465db33e4e3cdfb6fff0fa9dfb7d3cf027678ef
7
- data.tar.gz: af4b9df9e92dd343c6db4d73d39d3cfcad6a08fc3a9ce74ad47afabfb25056c0bccc7e8a924ac3a6070e4767a7e05e69d012cff6073732c04bae425bc33dd894
6
+ metadata.gz: 3d89dc0f91a27bb0e0e1ac5503cb11059d35309767fa006c200216819e0c123d6d2a558a03ac162964527b992fabc974184d5f357f3b0389405f2c63a13bdfed
7
+ data.tar.gz: 584146030273aeac56b898049f4f9e6a05f364c1b334bdca4ef2e044288548f1277c4d419cf7051504d36e0fd32ffbe48a4540c03f7b80f08405f43b4a0313ab
@@ -484,7 +484,7 @@ end
484
484
  | Text | `:string`, `:text`, `:email`, `:url`, `:tel`, `:password` |
485
485
  | Rich Text | `:markdown` (EasyMDE) |
486
486
  | Numeric | `:number`, `:integer`, `:decimal`, `:range` |
487
- | Boolean | `:boolean` |
487
+ | Boolean | `:toggle` / `:switch` (switch — **default** for boolean columns), `:boolean` (plain checkbox) |
488
488
  | Date/Time | `:date`, `:time`, `:datetime` |
489
489
  | Selection | `:select`, `:slim_select`, `:radio_buttons`, `:check_boxes` |
490
490
  | Files | `:file`, `:uppy`, `:attachment` |
@@ -493,7 +493,26 @@ end
493
493
 
494
494
  ### Display Types (show / index)
495
495
 
496
- `:string`, `:text`, `:email`, `:url`, `:phone`, `:markdown`, `:number`, `:integer`, `:decimal`, `:boolean`, `:date`, `:time`, `:datetime`, `:association`, `:attachment`
496
+ `:string`, `:text`, `:email`, `:url`, `:phone`, `:markdown`, `:number`, `:integer`, `:decimal`, `:boolean`, `:badge`, `:currency`, `:color`, `:date`, `:time`, `:datetime`, `:association`, `:attachment`
497
+
498
+ #### Auto-inferred display formatting
499
+
500
+ These render automatically — declare an `as:` only to override or pass options:
501
+
502
+ | Column | Renders as | Notes |
503
+ |--------|-----------|-------|
504
+ | `boolean` | Yes/No pill (`:boolean`) | green "Yes" / neutral "No". Override labels: `true_label:`, `false_label:` |
505
+ | `enum` | colored status badge (`:badge`) | known statuses (active, pending, failed…) auto-colored; unknown values get a stable decorative color |
506
+ | `has_cents` decimal | currency (`:currency`) | delimited, 2 decimals, **no symbol** unless you add `unit:` |
507
+
508
+ ```ruby
509
+ display :status, as: :badge, colors: {archived: :neutral, vip: :accent} # override per-value color
510
+ display :price, as: :currency, unit: "£" # literal symbol
511
+ display :price, as: :currency, unit: :currency_symbol # Symbol → read off the record (per-row)
512
+ display :active, as: :boolean, true_label: "Live", false_label: "Off"
513
+ ```
514
+
515
+ Badge color keys: `:neutral`, `:primary`, `:secondary`, `:success`, `:danger`, `:warning`, `:info`, `:accent`.
497
516
 
498
517
  ## Field Options
499
518
 
@@ -252,6 +252,7 @@ render field(:title).wrapped(class: "col-span-full") { |f| f.input_tag }
252
252
  | `input_tag` | text (auto-detected type) |
253
253
  | `string_tag`, `text_tag`, `number_tag`, `email_tag`, `password_tag`, `url_tag`, `tel_tag`, `hidden_tag` | standard HTML inputs |
254
254
  | `checkbox_tag`, `select_tag`, `radio_button_tag` | standard |
255
+ | `toggle_tag` / `switch_tag` | switch-styled boolean (`as: :toggle` / `:switch`) — default for boolean columns; `as: :boolean` for a plain checkbox |
255
256
 
256
257
  ### Plutonium-enhanced tags
257
258
 
@@ -513,6 +514,16 @@ rails generate pu:eject:layout
513
514
 
514
515
  These copy `_resource_header.html.erb`, `_resource_sidebar.html.erb`, and `layouts/resource.html.erb` into the portal so you can edit them directly.
515
516
 
517
+ ## Navigation menu items
518
+
519
+ The sidebar/icon-rail menu is built with `Phlexi::Menu::Builder` in `_resource_sidebar.html.erb`. Extra options on `item` are spread onto the rendered `<a>`, so an item can opt into `target` / `rel` / `data:` / `aria:`:
520
+
521
+ ```ruby
522
+ m.item "Inbox", url: inbox_path, icon: Icon, target: "_blank", rel: "noopener", data: {turbo_frame: "_top"}
523
+ ```
524
+
525
+ Applies to both shells (icon-rail leaf, parent flyout trigger, and flyout children; classic sidebar). Framework `class`/`data`/`aria` win on conflict — `class:` merges with the base classes, and on a parent trigger `data:`/`aria:` merge with the flyout wiring so options can't break the toggle. Phlexi's reserved `:active` key is never emitted as an attribute.
526
+
516
527
  ## Custom layout class (Phlex)
517
528
 
518
529
  ```ruby
@@ -733,7 +744,8 @@ Ready-to-use styled components in `src/css/components.css`. **Prefer these over
733
744
  ### Inputs, cards, panels, tables, toolbars, empty states
734
745
 
735
746
  ```
736
- .pu-input / -invalid / -valid .pu-label / -required .pu-hint / .pu-error .pu-checkbox
747
+ .pu-input / -invalid / -valid .pu-label / -required .pu-hint / .pu-error .pu-checkbox / .pu-toggle
748
+ .pu-badge / -neutral / -primary / -secondary / -success / -danger / -warning / -info / -accent
737
749
  .pu-card / .pu-card-body
738
750
  .pu-panel-header / -title / -description
739
751
  .pu-table-wrapper / .pu-table / -header / -header-cell / -body-row / -body-row-selected / -body-cell / .pu-selection-cell
@@ -845,7 +857,7 @@ end
845
857
 
846
858
  ### Display theme keys
847
859
 
848
- `fields_wrapper`, `label`, `description`, `string`, `text`, `link`, `email`, `phone`, `markdown`, `json`.
860
+ `fields_wrapper`, `label`, `description`, `string`, `text`, `link`, `email`, `phone`, `markdown`, `json`, `boolean`, `badge`, `currency`, `color`.
849
861
 
850
862
  ## Table theme
851
863
 
@@ -914,6 +926,7 @@ end
914
926
  - **Dark mode is `selector`, not `class`.** Toggle via `document.documentElement.classList.toggle('dark')`.
915
927
  - **Tokens are CSS variables, not Tailwind keys** — `bg-[var(--pu-surface)]`, not `bg-pu-surface`.
916
928
  - **`render_actions` is mandatory in custom `form_template`** — otherwise no submit button.
929
+ - **Dropdowns (`resource-drop-down`) teleport their menu to `<body>` while open.** popper's `fixed` strategy alone is still clipped by a transformed + `overflow:hidden` ancestor (e.g. grid cards, app shells), so the controller reparents the open menu to `<body>` and restores it on close. Don't rely on the menu being a DOM child of its trigger while open.
917
930
 
918
931
  ---
919
932
 
data/CHANGELOG.md CHANGED
@@ -1,3 +1,34 @@
1
+ ## [0.56.0] - 2026-06-05
2
+
3
+ ### 🚀 Features
4
+
5
+ - *(ui)* Auto-rendered components for boolean, enum & money fields
6
+ - *(generators/lite)* Add pu:lite:tune and pu:lite:maintenance for SQLite tuning + maintenance
7
+ - *(ui)* Sidebar menu items accept arbitrary link attributes
8
+ - *(ui)* Restore deleted nested rows + shared, polished removed bar
9
+ - *(ui)* Type-aware grid cards + overhaul KitchenSink dummy resource
10
+
11
+ ### 🐛 Bug Fixes
12
+
13
+ - *(generators/update)* Sync skills in a fresh process; pin post-install notice to 0.49.0
14
+ - *(ui)* Native multi-selects render at a usable height
15
+ - *(ui)* Dropdown menu teleports to <body> to escape overflow clipping
16
+ - *(routing)* Force :resources route_type for has_many nested routes
17
+ - *(ui)* Record-scoped commit URL for actions with record_action: false
18
+ - *(api)* Serialize JSON values via as_json (ISO 8601 datetimes)
19
+ - *(generators)* Add reading role to Rails Pulse connects_to config
20
+ - *(actions)* Bind subject during interaction param extraction
21
+ - *(ui)* Dirty-form-guard tracks edits via first-interaction baseline
22
+ - *(ui)* Give the JSON form input dark-mode styling
23
+
24
+ ### 🧪 Testing
25
+
26
+ - Fix stale generator assertions and drop committed dummy schema
27
+ - *(dummy)* Add KitchenSink resource exercising every input/display type
28
+
29
+ ### ⚙️ Miscellaneous Tasks
30
+
31
+ - Sync appraisal gemfile.lock files to v0.55.0
1
32
  ## [0.55.0] - 2026-06-03
2
33
 
3
34
  ### 🚀 Features