plutonium 0.49.1 → 0.51.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 (206) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +572 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +163 -300
  5. data/.claude/skills/plutonium-behavior/SKILL.md +838 -0
  6. data/.claude/skills/plutonium-resource/SKILL.md +1176 -0
  7. data/.claude/skills/plutonium-tenancy/SKILL.md +655 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +6 -5
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +37 -0
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1323 -1184
  14. data/app/assets/plutonium.js.map +4 -4
  15. data/app/assets/plutonium.min.js +50 -49
  16. data/app/assets/plutonium.min.js.map +4 -4
  17. data/app/views/plutonium/_resource_header.html.erb +4 -4
  18. data/app/views/plutonium/_resource_sidebar.html.erb +9 -9
  19. data/app/views/resource/_resource_grid.html.erb +1 -0
  20. data/config/brakeman.ignore +25 -2
  21. data/docs/.vitepress/config.ts +37 -27
  22. data/docs/getting-started/index.md +22 -29
  23. data/docs/getting-started/installation.md +37 -80
  24. data/docs/getting-started/tutorial/index.md +4 -5
  25. data/docs/guides/adding-resources.md +66 -377
  26. data/docs/guides/authentication.md +94 -463
  27. data/docs/guides/authorization.md +124 -370
  28. data/docs/guides/creating-packages.md +94 -296
  29. data/docs/guides/custom-actions.md +121 -441
  30. data/docs/guides/index.md +22 -42
  31. data/docs/guides/multi-tenancy.md +116 -187
  32. data/docs/guides/nested-resources.md +103 -431
  33. data/docs/guides/search-filtering.md +123 -240
  34. data/docs/guides/testing.md +5 -4
  35. data/docs/guides/theming.md +157 -407
  36. data/docs/guides/troubleshooting.md +5 -3
  37. data/docs/guides/user-invites.md +106 -425
  38. data/docs/guides/user-profile.md +76 -243
  39. data/docs/index.md +1 -1
  40. data/docs/reference/app/generators.md +517 -0
  41. data/docs/reference/app/index.md +158 -0
  42. data/docs/reference/app/packages.md +146 -0
  43. data/docs/reference/app/portals.md +377 -0
  44. data/docs/reference/auth/accounts.md +230 -0
  45. data/docs/reference/auth/index.md +88 -0
  46. data/docs/reference/auth/profile.md +185 -0
  47. data/docs/reference/behavior/controllers.md +395 -0
  48. data/docs/reference/behavior/index.md +22 -0
  49. data/docs/reference/behavior/interactions.md +341 -0
  50. data/docs/reference/behavior/policies.md +417 -0
  51. data/docs/reference/index.md +56 -49
  52. data/docs/reference/resource/actions.md +423 -0
  53. data/docs/reference/resource/definition.md +508 -0
  54. data/docs/reference/resource/index.md +50 -0
  55. data/docs/reference/resource/model.md +348 -0
  56. data/docs/reference/resource/query.md +305 -0
  57. data/docs/reference/tenancy/entity-scoping.md +361 -0
  58. data/docs/reference/tenancy/index.md +36 -0
  59. data/docs/reference/tenancy/invites.md +393 -0
  60. data/docs/reference/tenancy/nested-resources.md +267 -0
  61. data/docs/reference/testing/index.md +287 -0
  62. data/docs/reference/ui/assets.md +400 -0
  63. data/docs/reference/ui/components.md +165 -0
  64. data/docs/reference/ui/displays.md +104 -0
  65. data/docs/reference/ui/forms.md +284 -0
  66. data/docs/reference/ui/index.md +30 -0
  67. data/docs/reference/ui/layouts.md +106 -0
  68. data/docs/reference/ui/pages.md +189 -0
  69. data/docs/reference/ui/tables.md +117 -0
  70. data/docs/superpowers/plans/2026-05-07-ui-layout-overhaul.md +841 -0
  71. data/docs/superpowers/plans/2026-05-07-ui-layout-overhaul.md.tasks.json +103 -0
  72. data/docs/superpowers/specs/2026-05-07-ui-layout-overhaul-design.md +270 -0
  73. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  74. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  75. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  76. data/gemfiles/rails_7.gemfile.lock +1 -1
  77. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  78. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  79. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +1 -0
  80. data/lib/generators/pu/invites/install_generator.rb +1 -0
  81. data/lib/generators/pu/lite/rails_pulse/rails_pulse_generator.rb +54 -5
  82. data/lib/plutonium/action/base.rb +44 -1
  83. data/lib/plutonium/action/interactive.rb +1 -1
  84. data/lib/plutonium/configuration.rb +4 -0
  85. data/lib/plutonium/definition/actions.rb +3 -0
  86. data/lib/plutonium/definition/base.rb +8 -0
  87. data/lib/plutonium/definition/index_views.rb +95 -0
  88. data/lib/plutonium/definition/metadata.rb +40 -0
  89. data/lib/plutonium/helpers/turbo_helper.rb +12 -1
  90. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  91. data/lib/plutonium/interaction/response/redirect.rb +1 -1
  92. data/lib/plutonium/query/base.rb +8 -0
  93. data/lib/plutonium/query/filters/association.rb +30 -8
  94. data/lib/plutonium/query/filters/boolean.rb +5 -0
  95. data/lib/plutonium/resource/controller.rb +1 -0
  96. data/lib/plutonium/resource/controllers/crud_actions.rb +19 -1
  97. data/lib/plutonium/resource/controllers/presentable.rb +11 -2
  98. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  99. data/lib/plutonium/resource/definition.rb +42 -0
  100. data/lib/plutonium/resource/policy.rb +7 -0
  101. data/lib/plutonium/resource/query_object.rb +64 -6
  102. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  103. data/lib/plutonium/testing/resource_definition.rb +2 -2
  104. data/lib/plutonium/ui/action_button.rb +4 -2
  105. data/lib/plutonium/ui/component/kit.rb +12 -0
  106. data/lib/plutonium/ui/component/methods.rb +4 -0
  107. data/lib/plutonium/ui/display/base.rb +3 -1
  108. data/lib/plutonium/ui/display/resource.rb +109 -25
  109. data/lib/plutonium/ui/display/theme.rb +2 -1
  110. data/lib/plutonium/ui/dyna_frame/content.rb +8 -14
  111. data/lib/plutonium/ui/empty_card.rb +1 -1
  112. data/lib/plutonium/ui/form/base.rb +35 -3
  113. data/lib/plutonium/ui/form/components/hidden_wrapper.rb +25 -0
  114. data/lib/plutonium/ui/form/components/json.rb +58 -0
  115. data/lib/plutonium/ui/form/components/resource_select.rb +133 -1
  116. data/lib/plutonium/ui/form/components/secure_association.rb +105 -24
  117. data/lib/plutonium/ui/form/components/sticky_footer.rb +17 -0
  118. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  119. data/lib/plutonium/ui/form/resource.rb +45 -10
  120. data/lib/plutonium/ui/form/theme.rb +1 -1
  121. data/lib/plutonium/ui/frame_navigator_panel.rb +7 -4
  122. data/lib/plutonium/ui/grid/card.rb +235 -0
  123. data/lib/plutonium/ui/grid/resource.rb +149 -0
  124. data/lib/plutonium/ui/layout/base.rb +38 -1
  125. data/lib/plutonium/ui/layout/header.rb +1 -2
  126. data/lib/plutonium/ui/layout/icon_rail.rb +212 -0
  127. data/lib/plutonium/ui/layout/resource_layout.rb +10 -3
  128. data/lib/plutonium/ui/layout/sidebar.rb +12 -24
  129. data/lib/plutonium/ui/layout/topbar.rb +100 -0
  130. data/lib/plutonium/ui/modal/base.rb +109 -0
  131. data/lib/plutonium/ui/modal/centered.rb +21 -0
  132. data/lib/plutonium/ui/modal/slideover.rb +26 -0
  133. data/lib/plutonium/ui/page/base.rb +18 -6
  134. data/lib/plutonium/ui/page/edit.rb +13 -1
  135. data/lib/plutonium/ui/page/index.rb +40 -1
  136. data/lib/plutonium/ui/page/interactive_action.rb +8 -39
  137. data/lib/plutonium/ui/page/new.rb +13 -1
  138. data/lib/plutonium/ui/page/show.rb +8 -1
  139. data/lib/plutonium/ui/page_header.rb +8 -13
  140. data/lib/plutonium/ui/panel.rb +10 -19
  141. data/lib/plutonium/ui/sidebar_menu.rb +2 -25
  142. data/lib/plutonium/ui/tab_list.rb +29 -7
  143. data/lib/plutonium/ui/table/base.rb +106 -0
  144. data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +12 -4
  145. data/lib/plutonium/ui/table/components/filter_form.rb +171 -0
  146. data/lib/plutonium/ui/table/components/filter_pills.rb +89 -0
  147. data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +13 -12
  148. data/lib/plutonium/ui/table/components/scopes_pills.rb +67 -0
  149. data/lib/plutonium/ui/table/components/selection_column.rb +2 -11
  150. data/lib/plutonium/ui/table/components/toolbar.rb +104 -0
  151. data/lib/plutonium/ui/table/components/view_switcher.rb +81 -0
  152. data/lib/plutonium/ui/table/resource.rb +158 -89
  153. data/lib/plutonium/ui/table/theme.rb +14 -5
  154. data/lib/plutonium/version.rb +1 -1
  155. data/lib/plutonium.rb +14 -0
  156. data/lib/tasks/release.rake +15 -1
  157. data/package.json +10 -10
  158. data/src/css/components.css +304 -131
  159. data/src/css/slim_select.css +4 -0
  160. data/src/css/tokens.css +101 -85
  161. data/src/js/controllers/autosubmit_controller.js +24 -0
  162. data/src/js/controllers/bulk_actions_controller.js +15 -16
  163. data/src/js/controllers/capture_url_controller.js +14 -0
  164. data/src/js/controllers/filter_panel_controller.js +77 -19
  165. data/src/js/controllers/frame_navigator_controller.js +34 -6
  166. data/src/js/controllers/icon_rail_controller.js +22 -0
  167. data/src/js/controllers/icon_rail_flyout_controller.js +128 -0
  168. data/src/js/controllers/register_controllers.js +16 -0
  169. data/src/js/controllers/resource_tab_list_controller.js +56 -3
  170. data/src/js/controllers/row_click_controller.js +21 -0
  171. data/src/js/controllers/slim_select_controller.js +61 -0
  172. data/src/js/controllers/table_column_menu_controller.js +43 -0
  173. data/src/js/controllers/table_header_controller.js +16 -0
  174. data/src/js/controllers/view_switcher_controller.js +29 -0
  175. data/src/js/turbo/turbo_actions.js +33 -0
  176. data/yarn.lock +553 -543
  177. metadata +71 -32
  178. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  179. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  180. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  181. data/.claude/skills/plutonium-definition/SKILL.md +0 -1138
  182. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  183. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  184. data/.claude/skills/plutonium-installation/SKILL.md +0 -325
  185. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  186. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  187. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  188. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  189. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  190. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  191. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  192. data/.claude/skills/plutonium-views/SKILL.md +0 -592
  193. data/docs/reference/assets/index.md +0 -496
  194. data/docs/reference/controller/index.md +0 -412
  195. data/docs/reference/definition/actions.md +0 -449
  196. data/docs/reference/definition/fields.md +0 -383
  197. data/docs/reference/definition/index.md +0 -268
  198. data/docs/reference/definition/query.md +0 -351
  199. data/docs/reference/generators/index.md +0 -648
  200. data/docs/reference/interaction/index.md +0 -449
  201. data/docs/reference/model/features.md +0 -248
  202. data/docs/reference/model/index.md +0 -218
  203. data/docs/reference/policy/index.md +0 -456
  204. data/docs/reference/portal/index.md +0 -379
  205. data/docs/reference/views/forms.md +0 -411
  206. data/docs/reference/views/index.md +0 -501
@@ -1,383 +0,0 @@
1
- # Definition Fields
2
-
3
- Complete reference for field configuration in definitions.
4
-
5
- ## Core Methods
6
-
7
- | Method | Applies To | Use When |
8
- |--------|-----------|----------|
9
- | `field` | Forms + Show + Table | Universal type override |
10
- | `input` | Forms only | Form-specific options |
11
- | `display` | Show page only | Display-specific options |
12
- | `column` | Table only | Table-specific options |
13
-
14
- ## Basic Usage
15
-
16
- ```ruby
17
- class PostDefinition < Plutonium::Resource::Definition
18
- # field - changes type everywhere
19
- field :content, as: :markdown
20
-
21
- # input - form-specific
22
- input :title,
23
- label: "Article Title",
24
- hint: "Enter a descriptive title",
25
- placeholder: "e.g. Getting Started"
26
-
27
- # display - show page specific
28
- display :content,
29
- as: :markdown,
30
- description: "Published content",
31
- wrapper: {class: "col-span-full"}
32
-
33
- # column - table specific
34
- column :title, label: "Article", align: :center
35
- column :view_count, align: :end
36
- end
37
- ```
38
-
39
- ## Available Field Types
40
-
41
- ### Input Types (Forms)
42
-
43
- | Category | Types |
44
- |----------|-------|
45
- | **Text** | `:string`, `:text`, `:email`, `:url`, `:tel`, `:password` |
46
- | **Rich Text** | `:markdown` (uses EasyMDE editor) |
47
- | **Numeric** | `:number`, `:integer`, `:decimal`, `:range` |
48
- | **Boolean** | `:boolean` |
49
- | **Date/Time** | `:date`, `:time`, `:datetime` |
50
- | **Selection** | `:select`, `:slim_select`, `:radio_buttons`, `:check_boxes` |
51
- | **Files** | `:file`, `:uppy`, `:attachment` |
52
- | **Associations** | `:association`, `:secure_association`, `:belongs_to`, `:has_many`, `:has_one` |
53
- | **Special** | `:hidden`, `:color`, `:phone` |
54
-
55
- ### Display Types (Show/Index)
56
-
57
- `:string`, `:text`, `:email`, `:url`, `:phone`, `:markdown`, `:number`, `:integer`, `:decimal`, `:boolean`, `:date`, `:time`, `:datetime`, `:association`, `:attachment`
58
-
59
- ## Field Options
60
-
61
- ### Common Options
62
-
63
- ```ruby
64
- input :title,
65
- label: "Custom Label", # Custom label text
66
- hint: "Help text for forms", # Form help text
67
- placeholder: "Enter value", # Input placeholder
68
- description: "For displays" # Display description
69
- ```
70
-
71
- ### HTML Attributes
72
-
73
- ```ruby
74
- input :title,
75
- class: "custom-class", # CSS class
76
- data: {controller: "custom"}, # Data attributes
77
- required: true, # HTML required
78
- readonly: true, # HTML readonly
79
- disabled: true # HTML disabled
80
- ```
81
-
82
- ### Wrapper Options
83
-
84
- ```ruby
85
- display :content, wrapper: {class: "col-span-full"}
86
- input :notes, wrapper: {class: "bg-gray-50"}
87
- ```
88
-
89
- ## Select/Choices
90
-
91
- ### Static Choices
92
-
93
- ```ruby
94
- input :category, as: :select, choices: %w[Tech Business Lifestyle]
95
- input :status, as: :select, choices: Post.statuses.keys
96
- ```
97
-
98
- ### Dynamic Choices (requires block)
99
-
100
- ```ruby
101
- # Basic dynamic
102
- input :author do |f|
103
- choices = User.active.pluck(:name, :id)
104
- f.select_tag choices: choices
105
- end
106
-
107
- # With context access
108
- input :team_members do |f|
109
- choices = current_user.organization.users.pluck(:name, :id)
110
- f.select_tag choices: choices
111
- end
112
-
113
- # Based on object state
114
- input :related_posts do |f|
115
- choices = if object.persisted?
116
- Post.where.not(id: object.id).published.pluck(:title, :id)
117
- else
118
- []
119
- end
120
- f.select_tag choices: choices
121
- end
122
- ```
123
-
124
- ## Conditional Rendering
125
-
126
- ```ruby
127
- class PostDefinition < Plutonium::Resource::Definition
128
- # Show based on object state
129
- display :published_at, condition: -> { object.published? }
130
- display :rejection_reason, condition: -> { object.rejected? }
131
-
132
- # Show based on environment
133
- field :debug_info, condition: -> { Rails.env.development? }
134
- end
135
- ```
136
-
137
- **Note:** Use `condition` for UI state logic. Use **policies** for authorization.
138
-
139
- ## Dynamic Forms (pre_submit)
140
-
141
- Use `pre_submit: true` to create forms that dynamically show/hide fields based on other field values.
142
-
143
- ### Basic Pattern
144
-
145
- ```ruby
146
- class PostDefinition < Plutonium::Resource::Definition
147
- # Trigger field - causes form to re-render on change
148
- input :send_notifications, pre_submit: true
149
-
150
- # Dependent field - only shown when condition is true
151
- input :notification_channel,
152
- as: :select,
153
- choices: %w[Email SMS],
154
- condition: -> { object.send_notifications? }
155
- end
156
- ```
157
-
158
- ### How It Works
159
-
160
- 1. User changes a `pre_submit: true` field
161
- 2. Form submits via Turbo (no page reload)
162
- 3. Server re-renders the form with updated `object` state
163
- 4. Fields with `condition` procs are re-evaluated
164
- 5. Newly visible fields appear, hidden fields disappear
165
-
166
- ## Custom Rendering
167
-
168
- ### Block Syntax
169
-
170
- **For Display (can return any component):**
171
-
172
- ```ruby
173
- display :status do |field|
174
- StatusBadgeComponent.new(value: field.value, class: field.dom.css_class)
175
- end
176
-
177
- display :metrics do |field|
178
- if field.value.present?
179
- MetricsChartComponent.new(data: field.value)
180
- else
181
- EmptyStateComponent.new(message: "No metrics")
182
- end
183
- end
184
- ```
185
-
186
- **For Input (must use form builder methods):**
187
-
188
- ```ruby
189
- input :birth_date do |f|
190
- case object.age_category
191
- when 'adult'
192
- f.date_tag(min: 18.years.ago.to_date)
193
- when 'minor'
194
- f.date_tag(max: 18.years.ago.to_date)
195
- else
196
- f.date_tag
197
- end
198
- end
199
- ```
200
-
201
- ### phlexi_tag (Advanced Display)
202
-
203
- ```ruby
204
- # With component class
205
- display :status, as: :phlexi_tag, with: StatusBadgeComponent
206
-
207
- # With inline proc
208
- display :priority, as: :phlexi_tag, with: ->(value, attrs) {
209
- case value
210
- when 'high'
211
- span(class: "badge badge-danger") { "High" }
212
- when 'medium'
213
- span(class: "badge badge-warning") { "Medium" }
214
- else
215
- span(class: "badge badge-info") { "Low" }
216
- end
217
- }
218
- ```
219
-
220
- ### Custom Component Class
221
-
222
- ```ruby
223
- input :color_picker, as: ColorPickerComponent
224
- display :chart, as: ChartComponent
225
- ```
226
-
227
- ## Column Alignment
228
-
229
- ```ruby
230
- column :title, align: :start # Left (default)
231
- column :status, align: :center # Center
232
- column :amount, align: :end # Right
233
- ```
234
-
235
- ## Value Formatting
236
-
237
- Use `formatter` for simple value transformations without a full block:
238
-
239
- ```ruby
240
- # Truncate long text
241
- column :description, formatter: ->(value) { value&.truncate(30) }
242
-
243
- # Format numbers
244
- column :price, formatter: ->(value) { "$%.2f" % value if value }
245
-
246
- # Transform values
247
- column :status, formatter: ->(value) { value&.humanize&.upcase }
248
- ```
249
-
250
- The `formatter` option:
251
- - Receives the field value as its argument
252
- - Returns the transformed value for display
253
- - Works with `column` and `display` declarations
254
- - Is simpler than block syntax when you only need to transform the value
255
-
256
- **formatter vs block:** Use `formatter` when you only need the value. Use a block when you need access to the full record:
257
-
258
- ```ruby
259
- # formatter - receives just the value
260
- column :name, formatter: ->(value) { value&.titleize }
261
-
262
- # block - receives the full record
263
- column :full_name do |record|
264
- "#{record.first_name} #{record.last_name}"
265
- end
266
- ```
267
-
268
- ## Nested Inputs
269
-
270
- Render inline forms for associated records. Requires `accepts_nested_attributes_for` on the model.
271
-
272
- ### Model Setup
273
-
274
- ```ruby
275
- class Post < ResourceRecord
276
- has_many :comments
277
- has_one :metadata
278
-
279
- accepts_nested_attributes_for :comments, allow_destroy: true, limit: 10
280
- accepts_nested_attributes_for :metadata, update_only: true
281
- end
282
- ```
283
-
284
- ### Basic Declaration
285
-
286
- ```ruby
287
- class PostDefinition < Plutonium::Resource::Definition
288
- # Block syntax
289
- nested_input :comments do |n|
290
- n.input :body, as: :text
291
- n.input :author_name
292
- end
293
-
294
- # Using another definition
295
- nested_input :metadata, using: PostMetadataDefinition, fields: %i[seo_title seo_description]
296
- end
297
- ```
298
-
299
- ### Options
300
-
301
- | Option | Description |
302
- |--------|-------------|
303
- | `limit` | Max records (auto-detected from model, default: 10) |
304
- | `allow_destroy` | Show delete checkbox (auto-detected from model) |
305
- | `update_only` | Hide "Add" button, only edit existing |
306
- | `description` | Help text above the section |
307
- | `condition` | Proc to show/hide section |
308
- | `using` | Reference another Definition class |
309
- | `fields` | Which fields to render from the definition |
310
-
311
- ```ruby
312
- nested_input :amenities,
313
- allow_destroy: true,
314
- limit: 20,
315
- description: "Add property amenities" do |n|
316
- n.input :name
317
- n.input :icon, as: :select, choices: ICONS
318
- end
319
- ```
320
-
321
- ## File Uploads
322
-
323
- ```ruby
324
- input :avatar, as: :file
325
- input :avatar, as: :uppy
326
-
327
- input :documents, as: :file, multiple: true
328
- input :documents, as: :uppy,
329
- allowed_file_types: ['.pdf', '.doc'],
330
- max_file_size: 5.megabytes
331
- ```
332
-
333
- ## Common Patterns
334
-
335
- ### Rich Text Content
336
-
337
- ```ruby
338
- field :content, as: :markdown # Form: EasyMDE editor
339
- display :content, as: :markdown # Show: rendered markdown
340
- ```
341
-
342
- ### Money Fields
343
-
344
- ```ruby
345
- input :price, as: :decimal, class: "font-mono"
346
- display :price, class: "font-bold text-green-600"
347
- ```
348
-
349
- ### Status Badges
350
-
351
- ```ruby
352
- display :status do |field|
353
- color = case field.value
354
- when 'active' then 'green'
355
- when 'pending' then 'yellow'
356
- else 'gray'
357
- end
358
- span(class: "badge badge-#{color}") { field.value.humanize }
359
- end
360
- ```
361
-
362
- ### Hidden Fields
363
-
364
- ```ruby
365
- field :author_id, as: :hidden
366
- input :tenant_id, as: :hidden
367
- ```
368
-
369
- ## Context in Blocks
370
-
371
- Inside `condition` procs and `input` blocks:
372
- - `object` - The record being edited/displayed
373
- - `current_user` - The authenticated user
374
- - `current_parent` - Parent record for nested resources
375
- - `request`, `params` - Request information
376
- - All helper methods
377
-
378
- ## Related
379
-
380
- - [Definition Reference](./index)
381
- - [Actions Reference](./actions)
382
- - [Query Reference](./query)
383
- - [Forms Reference](/reference/views/forms)
@@ -1,268 +0,0 @@
1
- # Definition Reference
2
-
3
- Complete reference for resource definitions.
4
-
5
- ## Overview
6
-
7
- Definitions control how resources render - which fields appear in forms, how tables display data, what actions are available.
8
-
9
- ```ruby
10
- class PostDefinition < Plutonium::Resource::Definition
11
- # Field configuration
12
- field :title
13
- field :body, as: :markdown
14
-
15
- # Form-specific
16
- input :title, placeholder: "Enter title"
17
-
18
- # Display-specific
19
- display :body, as: :markdown
20
-
21
- # Table columns
22
- column :title
23
-
24
- # Custom actions
25
- action :publish, interaction: PublishPost
26
-
27
- # Search
28
- search do |scope, query|
29
- scope.where("title ILIKE ?", "%#{query}%")
30
- end
31
-
32
- # Sorting
33
- sort :title
34
- sort :created_at
35
- default_sort :created_at, :desc
36
- end
37
- ```
38
-
39
- ## Definition Files
40
-
41
- ### Location
42
-
43
- ```
44
- app/definitions/post_definition.rb
45
- packages/blogging/app/definitions/blogging/post_definition.rb
46
- ```
47
-
48
- ### Naming Convention
49
-
50
- | Model | Definition |
51
- |-------|------------|
52
- | `Post` | `PostDefinition` |
53
- | `Blogging::Post` | `Blogging::PostDefinition` |
54
-
55
- ### Portal-Specific
56
-
57
- Override for specific portals:
58
-
59
- ```ruby
60
- # packages/admin_portal/app/definitions/admin_portal/post_definition.rb
61
- module AdminPortal
62
- class PostDefinition < ::PostDefinition
63
- # Admin-specific customizations
64
- field :internal_notes
65
- end
66
- end
67
- ```
68
-
69
- ## Auto-Detection
70
-
71
- By default, Plutonium auto-detects fields from the model:
72
-
73
- ```ruby
74
- class PostDefinition < Plutonium::Resource::Definition
75
- # Empty definition = all fields auto-detected
76
- end
77
- ```
78
-
79
- Override selectively:
80
-
81
- ```ruby
82
- class PostDefinition < Plutonium::Resource::Definition
83
- # Override just body field
84
- field :body, as: :markdown
85
-
86
- # Other fields still auto-detected
87
- end
88
- ```
89
-
90
- ## Core Methods
91
-
92
- ### Field Declaration
93
-
94
- | Method | Purpose |
95
- |--------|---------|
96
- | `field` | Universal type/options for forms, displays, tables |
97
- | `input` | Form-specific configuration |
98
- | `display` | Show page configuration |
99
- | `column` | Table configuration |
100
-
101
- ### Query Configuration
102
-
103
- | Method | Purpose |
104
- |--------|---------|
105
- | `search` | Full-text search block |
106
- | `filter` | Sidebar filter inputs |
107
- | `scope` | Quick filter buttons |
108
- | `sort` / `sorts` | Sortable columns |
109
- | `default_sort` | Default sort order |
110
-
111
- ### Actions
112
-
113
- | Method | Purpose |
114
- |--------|---------|
115
- | `action` | Define custom actions |
116
- | `nested_input` | Nested forms for associations |
117
-
118
- ## Page Configuration
119
-
120
- Configure page titles and descriptions:
121
-
122
- ```ruby
123
- class PostDefinition < Plutonium::Resource::Definition
124
- index_page_title "All Posts"
125
- index_page_description "Manage your blog posts"
126
-
127
- new_page_title "Create Post"
128
- new_page_description "Add a new blog post"
129
-
130
- show_page_title { |record| record.title }
131
- show_page_description "View post details"
132
-
133
- edit_page_title { |record| "Edit: #{record.title}" }
134
- edit_page_description "Update post content"
135
- end
136
- ```
137
-
138
- ## Breadcrumbs
139
-
140
- Control breadcrumb display:
141
-
142
- ```ruby
143
- class PostDefinition < Plutonium::Resource::Definition
144
- # Disable breadcrumbs globally
145
- breadcrumbs false
146
-
147
- # Or per-page
148
- index_page_breadcrumbs true
149
- new_page_breadcrumbs true
150
- show_page_breadcrumbs true
151
- edit_page_breadcrumbs true
152
- interactive_action_page_breadcrumbs true
153
- end
154
- ```
155
-
156
- ## Form Configuration
157
-
158
- Control form behavior:
159
-
160
- ```ruby
161
- class PostDefinition < Plutonium::Resource::Definition
162
- # Controls "Save and add another" / "Update and continue editing" buttons
163
- # nil (default) = auto-detect (hidden for singular resources, shown for plural)
164
- # true = always show
165
- # false = always hide
166
- submit_and_continue false
167
- end
168
- ```
169
-
170
- Singular resources (e.g., `resource :profile` routes or `has_one` nested) auto-hide the secondary submit button since creating "another" doesn't make sense.
171
-
172
- ## Custom Page Classes
173
-
174
- Override default page components:
175
-
176
- ```ruby
177
- class PostDefinition < Plutonium::Resource::Definition
178
- # Custom page classes
179
- class IndexPage < Plutonium::UI::Page::Index
180
- def render_header
181
- # Custom header
182
- end
183
- end
184
-
185
- class Form < Plutonium::UI::Form::Resource
186
- # Custom form behavior
187
- end
188
-
189
- class Table < Plutonium::UI::Table::Resource
190
- # Custom table behavior
191
- end
192
-
193
- class Display < Plutonium::UI::Display::Resource
194
- # Custom display behavior
195
- end
196
- end
197
- ```
198
-
199
- ## Inheritance
200
-
201
- Definitions inherit from each other:
202
-
203
- ```ruby
204
- # Base definition
205
- class PostDefinition < Plutonium::Resource::Definition
206
- field :title
207
- field :body
208
- end
209
-
210
- # Extended definition
211
- class AdminPortal::PostDefinition < ::PostDefinition
212
- field :internal_notes
213
- field :moderation_status
214
- end
215
- ```
216
-
217
- ## Customization Hooks
218
-
219
- Override customization methods for dynamic configuration:
220
-
221
- ```ruby
222
- class PostDefinition < Plutonium::Resource::Definition
223
- def customize_fields
224
- field :dynamic_field if some_condition?
225
- end
226
-
227
- def customize_inputs
228
- input :special_input, as: :text
229
- end
230
-
231
- def customize_displays
232
- display :computed_value
233
- end
234
-
235
- def customize_columns
236
- column :extra_column
237
- end
238
-
239
- def customize_filters
240
- filter :status, with: Plutonium::Query::Filters::Text, predicate: :eq
241
- end
242
-
243
- def customize_scopes
244
- scope :active
245
- end
246
-
247
- def customize_sorts
248
- sort :custom_field
249
- end
250
-
251
- def customize_actions
252
- action :dynamic_action, interaction: SomeInteraction
253
- end
254
- end
255
- ```
256
-
257
- ## Sections
258
-
259
- - [Fields](./fields) - Form and display field configuration
260
- - [Actions](./actions) - Custom actions and buttons
261
- - [Query](./query) - Search, filters, scopes, and sorting
262
-
263
- ## Related
264
-
265
- - [Fields](./fields) - Field configuration
266
- - [Actions](./actions) - Custom actions
267
- - [Query](./query) - Search, filters, scopes
268
- - [Views Reference](/reference/views/)