plutonium 0.61.0 → 0.62.1

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium-kanban/SKILL.md +89 -24
  3. data/CHANGELOG.md +45 -3
  4. data/SECURITY.md +57 -0
  5. data/app/assets/plutonium.css +1 -1
  6. data/app/assets/plutonium.js +315 -38
  7. data/app/assets/plutonium.js.map +4 -4
  8. data/app/assets/plutonium.min.js +31 -31
  9. data/app/assets/plutonium.min.js.map +4 -4
  10. data/app/views/resource/_kanban_move_action_form.html.erb +1 -0
  11. data/app/views/resource/kanban_move_form.html.erb +1 -0
  12. data/config/brakeman.ignore +2 -2
  13. data/docs/.vitepress/config.ts +21 -1
  14. data/docs/.vitepress/sync-skills.mjs +45 -0
  15. data/docs/ai.md +99 -0
  16. data/docs/guides/kanban.md +128 -18
  17. data/docs/reference/kanban/authorization.md +25 -5
  18. data/docs/reference/kanban/dsl.md +49 -8
  19. data/docs/reference/kanban/index.md +3 -3
  20. data/docs/reference/kanban/positioning.md +1 -1
  21. data/docs/reference/resource/definition.md +10 -1
  22. data/docs/reference/resource/model.md +26 -0
  23. data/docs/reference/ui/forms.md +41 -0
  24. data/docs/reference/wizard/dsl.md +5 -0
  25. data/docs/superpowers/plans/2026-07-02-kanban-drop-interactions.md +714 -0
  26. data/docs/superpowers/plans/2026-07-02-kanban-drop-interactions.md.tasks.json +68 -0
  27. data/docs/superpowers/specs/2026-07-03-kanban-auth-simplification.md +159 -0
  28. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  29. data/lib/generators/pu/gem/active_shrine/active_shrine_generator.rb +5 -0
  30. data/lib/plutonium/action/base.rb +8 -0
  31. data/lib/plutonium/configuration.rb +12 -0
  32. data/lib/plutonium/definition/index_views.rb +16 -0
  33. data/lib/plutonium/kanban/column.rb +80 -27
  34. data/lib/plutonium/models/has_cents.rb +30 -2
  35. data/lib/plutonium/resource/controller.rb +22 -1
  36. data/lib/plutonium/resource/controllers/crud_actions.rb +21 -1
  37. data/lib/plutonium/resource/controllers/kanban_actions.rb +489 -93
  38. data/lib/plutonium/resource/policy.rb +6 -0
  39. data/lib/plutonium/routing/mapper_extensions.rb +1 -0
  40. data/lib/plutonium/ui/display/components/currency.rb +41 -9
  41. data/lib/plutonium/ui/display/options/inferred_types.rb +2 -5
  42. data/lib/plutonium/ui/form/base.rb +6 -0
  43. data/lib/plutonium/ui/form/components/currency.rb +64 -0
  44. data/lib/plutonium/ui/form/components/intl_tel_input.rb +27 -1
  45. data/lib/plutonium/ui/form/components/uppy.rb +20 -2
  46. data/lib/plutonium/ui/form/kanban_move.rb +46 -0
  47. data/lib/plutonium/ui/form/options/inferred_types.rb +6 -0
  48. data/lib/plutonium/ui/form/resource.rb +12 -0
  49. data/lib/plutonium/ui/form/theme.rb +7 -0
  50. data/lib/plutonium/ui/grid/card.rb +40 -13
  51. data/lib/plutonium/ui/kanban/column.rb +111 -24
  52. data/lib/plutonium/ui/kanban/resource.rb +118 -11
  53. data/lib/plutonium/ui/layout/base.rb +1 -1
  54. data/lib/plutonium/ui/options/has_cents_field.rb +21 -0
  55. data/lib/plutonium/ui/page/index.rb +1 -1
  56. data/lib/plutonium/ui/page/interactive_action.rb +12 -2
  57. data/lib/plutonium/ui/page/kanban_move.rb +20 -0
  58. data/lib/plutonium/ui/page/show.rb +7 -2
  59. data/lib/plutonium/ui/table/resource.rb +1 -1
  60. data/lib/plutonium/ui/wizard/summary_display.rb +33 -0
  61. data/lib/plutonium/version.rb +1 -1
  62. data/lib/plutonium/wizard/not_anchored_error.rb +8 -0
  63. data/lib/plutonium/wizard/{errors.rb → step_error.rb} +0 -8
  64. data/lib/plutonium/wizard/unknown_wizard_error.rb +10 -0
  65. data/lib/plutonium/wizard.rb +0 -1
  66. data/lib/tasks/release.rake +16 -0
  67. data/package.json +5 -3
  68. data/plutonium.gemspec +3 -0
  69. data/src/css/components.css +5 -0
  70. data/src/js/controllers/currency_input_controller.js +39 -0
  71. data/src/js/controllers/intl_tel_input_controller.js +4 -0
  72. data/src/js/controllers/kanban_controller.js +442 -55
  73. data/src/js/controllers/register_controllers.js +2 -0
  74. data/yarn.lock +674 -4
  75. metadata +19 -3
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.61.0",
3
+ "version": "0.62.1",
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",
@@ -49,6 +49,7 @@
49
49
  "postcss-import": "^16.1.1",
50
50
  "tailwindcss": "^4.3.0",
51
51
  "vitepress": "^1.6.4",
52
+ "vitepress-plugin-llms": "^1.13.2",
52
53
  "vitepress-plugin-mermaid": "^2.0.17"
53
54
  },
54
55
  "scripts": {
@@ -59,8 +60,9 @@
59
60
  "js:dev": "node esbuild.config.js --dev",
60
61
  "css:prod": "postcss src/css/plutonium.entry.css -o app/assets/plutonium.css && postcss src/css/plutonium.entry.css -o src/dist/css/plutonium.css",
61
62
  "js:prod": "node esbuild.config.js",
62
- "docs:dev": "vitepress dev docs",
63
- "docs:build": "vitepress build docs",
63
+ "docs:sync-skills": "node docs/.vitepress/sync-skills.mjs",
64
+ "docs:dev": "yarn docs:sync-skills && vitepress dev docs",
65
+ "docs:build": "yarn docs:sync-skills && vitepress build docs",
64
66
  "docs:preview": "vitepress preview docs"
65
67
  }
66
68
  }
data/plutonium.gemspec CHANGED
@@ -15,6 +15,9 @@ Gem::Specification.new do |spec|
15
15
  spec.required_ruby_version = ">= 3.2.2"
16
16
 
17
17
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
+ # Require multi-factor auth for privileged RubyGems actions (push, yank,
19
+ # owner changes). `gem push` will prompt for an OTP at release time.
20
+ spec.metadata["rubygems_mfa_required"] = "true"
18
21
 
19
22
  spec.post_install_message = <<~MSG
20
23
  ℹ️ Plutonium — breaking change introduced in 0.49.0
@@ -635,6 +635,11 @@ select.pu-input[multiple] option {
635
635
  own pinned-right surface and intentionally does not opt in. */
636
636
  .pu-dialog {
637
637
  background-color: var(--pu-surface);
638
+ /* Pair the surface background with the theme text colour. The UA stylesheet
639
+ resets <dialog> color to CanvasText (black) and it does NOT inherit from
640
+ <body>, so without this any unstyled text inside a modal (e.g. a show page's
641
+ plain field values) renders black on the dark surface. */
642
+ color: var(--pu-text);
638
643
  border: 1px solid var(--pu-border);
639
644
  border-radius: var(--pu-radius-lg);
640
645
  }
@@ -0,0 +1,39 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="currency-input"
4
+ //
5
+ // Pads a currency input's left edge to exactly clear its overlaid unit prefix.
6
+ //
7
+ // The prefix ("$", "£", "GH₵", "USD", …) is absolutely positioned at the
8
+ // field's left edge; its width varies by symbol AND font, so any fixed padding
9
+ // is wrong for some currency — too little clips a wide prefix (digits collide
10
+ // with it, as with "GH₵"), too much wastes space on a bare "$". This measures
11
+ // the rendered prefix and sets padding-left to match, so the caret always sits
12
+ // just past the symbol regardless of currency or typeface.
13
+ //
14
+ // DOM contract:
15
+ // wrapper data-controller="currency-input"
16
+ // prefix data-currency-input-target="prefix" (the overlaid unit span)
17
+ // input data-currency-input-target="field" (the number input)
18
+ export default class extends Controller {
19
+ static targets = ["prefix", "field"]
20
+ // Space between the prefix and the first digit, in px.
21
+ static values = { gap: { type: Number, default: 6 } }
22
+
23
+ connect() {
24
+ this.#pad()
25
+ // Web fonts often load after connect; the fallback font's metrics differ,
26
+ // so re-measure once they're ready to correct the padding.
27
+ document.fonts.ready.then(() => this.#pad())
28
+ }
29
+
30
+ #pad() {
31
+ // Inline !important so it beats pu-input's own left padding (a plain class
32
+ // would lose the cascade — see the note this replaces in currency.rb).
33
+ this.fieldTarget.style.setProperty(
34
+ "padding-left",
35
+ `${this.prefixTarget.offsetWidth + this.gapValue}px`,
36
+ "important"
37
+ )
38
+ }
39
+ }
@@ -3,6 +3,7 @@ import { Controller } from "@hotwired/stimulus"
3
3
  // Connects to data-controller="intl-tel-input"
4
4
  export default class extends Controller {
5
5
  static targets = ["input"]
6
+ static values = { options: Object }
6
7
 
7
8
  connect() {
8
9
  }
@@ -49,10 +50,13 @@ export default class extends Controller {
49
50
  }
50
51
 
51
52
  #buildOptions() {
53
+ // Defaults first; the definition-supplied `options` value (e.g.
54
+ // { initialCountry: "gh", strictMode: false }) is spread last so it wins.
52
55
  return {
53
56
  strictMode: true,
54
57
  hiddenInput: () => ({ phone: this.inputTarget.attributes.name.value }),
55
58
  loadUtilsOnInit: "https://cdn.jsdelivr.net/npm/intl-tel-input@24.8.1/build/js/utils.js",
59
+ ...this.optionsValue,
56
60
  }
57
61
  }
58
62
  }