plutonium 0.50.0 → 0.52.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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +574 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +167 -302
  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 +674 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +9 -6
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +44 -2
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1010 -1214
  14. data/app/assets/plutonium.js.map +3 -3
  15. data/app/assets/plutonium.min.js +52 -51
  16. data/app/assets/plutonium.min.js.map +3 -3
  17. data/docs/.vitepress/config.ts +38 -29
  18. data/docs/.vitepress/theme/components/HomeAudienceSplit.vue +53 -0
  19. data/docs/.vitepress/theme/components/HomeCta.vue +108 -0
  20. data/docs/.vitepress/theme/components/HomeHero.vue +70 -0
  21. data/docs/.vitepress/theme/components/HomeInTheBox.vue +74 -0
  22. data/docs/.vitepress/theme/components/HomePillars.vue +42 -0
  23. data/docs/.vitepress/theme/components/HomeStopWriting.vue +49 -0
  24. data/docs/.vitepress/theme/components/HomeWalkthrough.vue +111 -0
  25. data/docs/.vitepress/theme/components/SectionLanding.vue +115 -0
  26. data/docs/.vitepress/theme/custom.css +144 -0
  27. data/docs/.vitepress/theme/index.ts +58 -1
  28. data/docs/getting-started/index.md +33 -57
  29. data/docs/getting-started/installation.md +37 -80
  30. data/docs/getting-started/tutorial/02-first-resource.md +17 -8
  31. data/docs/getting-started/tutorial/03-authentication.md +31 -23
  32. data/docs/getting-started/tutorial/05-custom-actions.md +9 -4
  33. data/docs/getting-started/tutorial/06-nested-resources.md +7 -1
  34. data/docs/getting-started/tutorial/07-author-portal.md +8 -0
  35. data/docs/getting-started/tutorial/08-customizing-ui.md +4 -0
  36. data/docs/getting-started/tutorial/index.md +4 -5
  37. data/docs/guides/adding-resources.md +66 -377
  38. data/docs/guides/authentication.md +98 -462
  39. data/docs/guides/authorization.md +124 -370
  40. data/docs/guides/creating-packages.md +93 -298
  41. data/docs/guides/custom-actions.md +126 -441
  42. data/docs/guides/customizing-ui.md +258 -0
  43. data/docs/guides/index.md +49 -52
  44. data/docs/guides/multi-tenancy.md +123 -186
  45. data/docs/guides/nested-resources.md +137 -396
  46. data/docs/guides/search-filtering.md +127 -238
  47. data/docs/guides/testing.md +10 -5
  48. data/docs/guides/theming.md +168 -405
  49. data/docs/guides/troubleshooting.md +5 -3
  50. data/docs/guides/user-invites.md +112 -425
  51. data/docs/guides/user-profile.md +82 -241
  52. data/docs/index.md +10 -219
  53. data/docs/public/asciinema/home-scaffold.cast +305 -0
  54. data/docs/public/images/guides/custom-actions-bulk.png +0 -0
  55. data/docs/public/images/guides/multi-tenancy-dashboard.png +0 -0
  56. data/docs/public/images/guides/multi-tenancy-welcome.png +0 -0
  57. data/docs/public/images/guides/nested-inputs.png +0 -0
  58. data/docs/public/images/guides/nested-resources-tab.png +0 -0
  59. data/docs/public/images/guides/search-filtering-index.png +0 -0
  60. data/docs/public/images/guides/search-filtering-panel.png +0 -0
  61. data/docs/public/images/guides/theming-after.png +0 -0
  62. data/docs/public/images/guides/theming-before.png +0 -0
  63. data/docs/public/images/guides/user-invites-landing.png +0 -0
  64. data/docs/public/images/guides/user-profile-edit.png +0 -0
  65. data/docs/public/images/guides/user-profile-show.png +0 -0
  66. data/docs/public/images/home-index.png +0 -0
  67. data/docs/public/images/home-new.png +0 -0
  68. data/docs/public/images/home-show.png +0 -0
  69. data/docs/public/images/tutorial/02-empty-index.png +0 -0
  70. data/docs/public/images/tutorial/02-index-with-posts.png +0 -0
  71. data/docs/public/images/tutorial/02-new-form-modal.png +0 -0
  72. data/docs/public/images/tutorial/02-new-form.png +0 -0
  73. data/docs/public/images/tutorial/03-create-account.png +0 -0
  74. data/docs/public/images/tutorial/03-login.png +0 -0
  75. data/docs/public/images/tutorial/04-admin-index.png +0 -0
  76. data/docs/public/images/tutorial/05-actions-menu.png +0 -0
  77. data/docs/public/images/tutorial/05-row-actions.png +0 -0
  78. data/docs/public/images/tutorial/06-comments-tab.png +0 -0
  79. data/docs/public/images/tutorial/06-post-with-comments.png +0 -0
  80. data/docs/public/images/tutorial/07-author-dashboard.png +0 -0
  81. data/docs/public/images/tutorial/07-author-portal.png +0 -0
  82. data/docs/public/images/tutorial/08-customized-index.png +0 -0
  83. data/docs/reference/app/generators.md +517 -0
  84. data/docs/reference/app/index.md +158 -0
  85. data/docs/reference/app/packages.md +146 -0
  86. data/docs/reference/app/portals.md +377 -0
  87. data/docs/reference/auth/accounts.md +229 -0
  88. data/docs/reference/auth/index.md +88 -0
  89. data/docs/reference/auth/profile.md +185 -0
  90. data/docs/reference/behavior/controllers.md +395 -0
  91. data/docs/reference/behavior/index.md +22 -0
  92. data/docs/reference/behavior/interactions.md +341 -0
  93. data/docs/reference/behavior/policies.md +417 -0
  94. data/docs/reference/index.md +67 -48
  95. data/docs/reference/resource/actions.md +423 -0
  96. data/docs/reference/resource/definition.md +508 -0
  97. data/docs/reference/resource/index.md +50 -0
  98. data/docs/reference/resource/model.md +348 -0
  99. data/docs/reference/resource/query.md +305 -0
  100. data/docs/reference/tenancy/entity-scoping.md +368 -0
  101. data/docs/reference/tenancy/index.md +36 -0
  102. data/docs/reference/tenancy/invites.md +400 -0
  103. data/docs/reference/tenancy/nested-resources.md +267 -0
  104. data/docs/reference/testing/index.md +287 -0
  105. data/docs/reference/ui/assets.md +400 -0
  106. data/docs/reference/ui/components.md +165 -0
  107. data/docs/reference/ui/displays.md +104 -0
  108. data/docs/reference/ui/forms.md +284 -0
  109. data/docs/reference/ui/index.md +30 -0
  110. data/docs/reference/ui/layouts.md +106 -0
  111. data/docs/reference/ui/pages.md +189 -0
  112. data/docs/reference/ui/tables.md +121 -0
  113. data/docs/superpowers/plans/2026-05-15-public-pages-overhaul.md +1648 -0
  114. data/docs/superpowers/plans/2026-05-15-public-pages-overhaul.md.tasks.json +109 -0
  115. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  116. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  117. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  118. data/docs/superpowers/specs/2026-05-15-public-pages-overhaul-design.md +263 -0
  119. data/gemfiles/rails_7.gemfile.lock +1 -1
  120. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  121. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  122. data/lib/generators/pu/core/assets/assets_generator.rb +10 -0
  123. data/lib/generators/pu/core/update/update_generator.rb +0 -20
  124. data/lib/generators/pu/invites/install_generator.rb +45 -0
  125. data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/user_invitations_controller.rb.tt +1 -0
  126. data/lib/generators/pu/profile/conn_generator.rb +2 -2
  127. data/lib/generators/pu/res/conn/conn_generator.rb +33 -6
  128. data/lib/generators/pu/res/model/templates/model.rb.tt +4 -0
  129. data/lib/generators/pu/rodauth/account_generator.rb +2 -1
  130. data/lib/generators/pu/rodauth/admin_generator.rb +0 -2
  131. data/lib/generators/pu/rodauth/migration_generator.rb +0 -2
  132. data/lib/generators/pu/rodauth/views_generator.rb +0 -2
  133. data/lib/generators/pu/saas/membership/USAGE +4 -1
  134. data/lib/generators/pu/saas/setup_generator.rb +16 -4
  135. data/lib/generators/pu/saas/welcome/templates/app/controllers/welcome_controller.rb.tt +1 -1
  136. data/lib/plutonium/definition/base.rb +1 -1
  137. data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
  138. data/lib/plutonium/helpers/turbo_helper.rb +30 -0
  139. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  140. data/lib/plutonium/resource/controller.rb +1 -0
  141. data/lib/plutonium/resource/controllers/crud_actions.rb +23 -5
  142. data/lib/plutonium/resource/controllers/interactive_actions.rb +3 -3
  143. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  144. data/lib/plutonium/resource/policy.rb +7 -0
  145. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  146. data/lib/plutonium/ui/component/methods.rb +5 -0
  147. data/lib/plutonium/ui/form/base.rb +23 -3
  148. data/lib/plutonium/ui/form/components/json.rb +58 -0
  149. data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
  150. data/lib/plutonium/ui/form/components/secure_association.rb +103 -22
  151. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  152. data/lib/plutonium/ui/form/interaction.rb +1 -1
  153. data/lib/plutonium/ui/form/resource.rb +0 -4
  154. data/lib/plutonium/ui/form/theme.rb +1 -1
  155. data/lib/plutonium/ui/grid/resource.rb +1 -1
  156. data/lib/plutonium/ui/layout/base.rb +1 -0
  157. data/lib/plutonium/ui/page/base.rb +0 -7
  158. data/lib/plutonium/ui/page/edit.rb +1 -1
  159. data/lib/plutonium/ui/page/index.rb +4 -4
  160. data/lib/plutonium/ui/page/new.rb +1 -1
  161. data/lib/plutonium/ui/table/components/filter_form.rb +12 -4
  162. data/lib/plutonium/ui/table/resource.rb +1 -1
  163. data/lib/plutonium/version.rb +1 -1
  164. data/lib/plutonium.rb +8 -0
  165. data/lib/tasks/release.rake +15 -1
  166. data/package.json +13 -10
  167. data/src/css/slim_select.css +4 -0
  168. data/src/js/controllers/form_controller.js +5 -4
  169. data/src/js/controllers/slim_select_controller.js +61 -0
  170. data/src/js/turbo/turbo_actions.js +33 -0
  171. data/yarn.lock +661 -544
  172. metadata +86 -33
  173. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  174. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  175. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  176. data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
  177. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  178. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  179. data/.claude/skills/plutonium-installation/SKILL.md +0 -331
  180. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  181. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  182. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  183. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  184. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  185. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  186. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  187. data/.claude/skills/plutonium-views/SKILL.md +0 -651
  188. data/docs/reference/assets/index.md +0 -496
  189. data/docs/reference/controller/index.md +0 -412
  190. data/docs/reference/definition/actions.md +0 -462
  191. data/docs/reference/definition/fields.md +0 -383
  192. data/docs/reference/definition/index.md +0 -326
  193. data/docs/reference/definition/query.md +0 -351
  194. data/docs/reference/generators/index.md +0 -648
  195. data/docs/reference/interaction/index.md +0 -449
  196. data/docs/reference/model/features.md +0 -248
  197. data/docs/reference/model/index.md +0 -218
  198. data/docs/reference/policy/index.md +0 -456
  199. data/docs/reference/portal/index.md +0 -379
  200. data/docs/reference/views/forms.md +0 -411
  201. data/docs/reference/views/index.md +0 -544
@@ -1,411 +0,0 @@
1
- # Forms Reference
2
-
3
- Complete reference for form customization using Phlexi::Form.
4
-
5
- ## Overview
6
-
7
- Plutonium forms are built on [Phlexi::Form](https://github.com/radioactive-labs/phlexi-form), providing a Ruby-first approach to form building.
8
-
9
- ## Form Class Hierarchy
10
-
11
- ```
12
- Phlexi::Form::Base
13
- └── Plutonium::UI::Form::Base # Base with Plutonium components
14
- ├── Plutonium::UI::Form::Resource # Resource CRUD forms
15
- │ └── Plutonium::UI::Form::Interaction # Interactive action forms
16
- └── Plutonium::UI::Form::Query # Search/filter forms
17
- ```
18
-
19
- ## Custom Form Template
20
-
21
- Override form rendering in your definition:
22
-
23
- ```ruby
24
- class PostDefinition < ResourceDefinition
25
- class Form < Form
26
- def form_template
27
- # Your custom layout
28
- render_fields
29
- render_actions
30
- end
31
- end
32
- end
33
- ```
34
-
35
- ### Form Template Methods
36
-
37
- | Method | Description |
38
- |--------|-------------|
39
- | `form_template` | Main template method to override |
40
- | `render_fields` | Render all permitted fields |
41
- | `render_resource_field(name)` | Render a single field by name |
42
- | `render_actions` | Render submit buttons |
43
- | `fields_wrapper { }` | Wrapper div for field grid |
44
- | `actions_wrapper { }` | Wrapper div for buttons |
45
-
46
- ### Form Attributes
47
-
48
- | Attribute | Description |
49
- |-----------|-------------|
50
- | `object` / `record` | The form object being edited |
51
- | `resource_fields` | Array of permitted field names |
52
- | `resource_definition` | The definition instance |
53
-
54
- ## Custom Layouts
55
-
56
- ### Sectioned Form
57
-
58
- ```ruby
59
- class PostDefinition < ResourceDefinition
60
- class Form < Form
61
- def form_template
62
- section("Basic Information") {
63
- render_resource_field :title
64
- render_resource_field :slug
65
- }
66
-
67
- section("Content") {
68
- render_resource_field :content
69
- render_resource_field :excerpt
70
- }
71
-
72
- render_actions
73
- end
74
-
75
- private
76
-
77
- def section(title, &)
78
- div(class: "mb-8") {
79
- h3(class: "text-lg font-semibold mb-4") { title }
80
- fields_wrapper(&)
81
- }
82
- end
83
- end
84
- end
85
- ```
86
-
87
- ### Two-Column Layout
88
-
89
- ```ruby
90
- class Form < Form
91
- def form_template
92
- div(class: "grid grid-cols-1 lg:grid-cols-3 gap-6") {
93
- # Main content - 2 columns
94
- div(class: "lg:col-span-2") {
95
- fields_wrapper {
96
- render_resource_field :title
97
- render_resource_field :content
98
- }
99
- }
100
-
101
- # Sidebar - 1 column
102
- div(class: "space-y-4") {
103
- Panel {
104
- h4(class: "font-medium mb-2") { "Settings" }
105
- render_resource_field :status
106
- render_resource_field :visibility
107
- }
108
- }
109
- }
110
-
111
- render_actions
112
- end
113
- end
114
- ```
115
-
116
- ## Field Builder
117
-
118
- When using `render_resource_field`, Plutonium applies definition configuration. For custom rendering, use the `field` method directly.
119
-
120
- ### Basic Field Usage
121
-
122
- ```ruby
123
- def form_template
124
- # Using field builder directly
125
- render field(:title).wrapped { |f| f.input_tag }
126
- render field(:content).wrapped { |f| f.easymde_tag }
127
- render field(:published).wrapped { |f| f.checkbox_tag }
128
-
129
- render_actions
130
- end
131
- ```
132
-
133
- ### Standard Tag Methods
134
-
135
- | Method | Input Type |
136
- |--------|------------|
137
- | `f.input_tag` | Text input (auto-detects type) |
138
- | `f.string_tag` | Text input |
139
- | `f.text_tag` | Textarea |
140
- | `f.number_tag` | Number input |
141
- | `f.email_tag` | Email input |
142
- | `f.password_tag` | Password input |
143
- | `f.url_tag` | URL input |
144
- | `f.phone_tag` | Telephone input |
145
- | `f.hidden_tag` | Hidden input |
146
- | `f.date_tag` | Date input |
147
- | `f.time_tag` | Time input |
148
- | `f.datetime_tag` | Datetime input |
149
- | `f.checkbox_tag` | Checkbox |
150
- | `f.boolean_tag` | Checkbox (themed as boolean) |
151
- | `f.select_tag` | Select dropdown |
152
- | `f.radio_button_tag` | Radio button |
153
- | `f.collection_radio_buttons_tag` | Radio button collection |
154
- | `f.collection_checkboxes_tag` | Checkbox collection |
155
- | `f.range_tag` | Range slider |
156
- | `f.file_input_tag` | File input |
157
-
158
- ### Plutonium-Enhanced Tags
159
-
160
- Plutonium extends the form builder with additional tags. See the [Form::Base::Builder source](https://github.com/radioactive-labs/plutonium-core/blob/master/lib/plutonium/ui/form/base.rb) for the current list.
161
-
162
- Common ones include:
163
- - `f.easymde_tag` / `f.markdown_tag` - Markdown editor
164
- - `f.slim_select_tag` - Enhanced select
165
- - `f.flatpickr_tag` - Date/time picker
166
- - `f.uppy_tag` / `f.file_tag` - File upload
167
- - `f.secure_association_tag` - Association with SGID
168
-
169
- ### Field with Options
170
-
171
- ```ruby
172
- # Select with choices
173
- render field(:status).wrapped { |f|
174
- f.select_tag(choices: %w[draft published archived])
175
- }
176
-
177
- # Date picker with options
178
- render field(:published_at).wrapped { |f|
179
- f.flatpickr_tag(min_date: Date.today, enable_time: true)
180
- }
181
-
182
- # File upload with restrictions
183
- render field(:avatar).wrapped { |f|
184
- f.uppy_tag(
185
- allowed_file_types: %w[.jpg .png .gif],
186
- max_file_size: 5.megabytes
187
- )
188
- }
189
- ```
190
-
191
- ### Wrapped vs Unwrapped
192
-
193
- ```ruby
194
- # Wrapped - includes label, hint, errors
195
- render field(:title).wrapped { |f| f.input_tag }
196
-
197
- # Unwrapped - just the input element
198
- render field(:title).input_tag
199
-
200
- # Custom wrapper options
201
- render field(:title).wrapped(class: "col-span-full") { |f|
202
- f.input_tag
203
- }
204
- ```
205
-
206
- ## Input Configuration in Definitions
207
-
208
- Define inputs in the definition, render them in the form:
209
-
210
- ```ruby
211
- class PostDefinition < ResourceDefinition
212
- # Configure inputs
213
- input :title, hint: "Be descriptive", placeholder: "Enter title"
214
- input :content, as: :markdown
215
- input :status, as: :select, choices: %w[draft published]
216
- input :published_at, as: :flatpickr
217
-
218
- # Custom input with block
219
- input :category do |f|
220
- choices = Category.active.pluck(:name, :id)
221
- f.select_tag(choices: choices)
222
- end
223
-
224
- class Form < Form
225
- def form_template
226
- # render_resource_field uses the input configuration
227
- render_resource_field :title
228
- render_resource_field :content
229
- render_resource_field :status
230
- render_resource_field :published_at
231
- render_resource_field :category
232
-
233
- render_actions
234
- end
235
- end
236
- end
237
- ```
238
-
239
- ## Nested Forms
240
-
241
- For `has_many` / `has_one` associations with `accepts_nested_attributes_for`:
242
-
243
- ### Model Setup
244
-
245
- ```ruby
246
- class Post < ResourceRecord
247
- has_many :comments
248
- accepts_nested_attributes_for :comments, allow_destroy: true
249
- end
250
- ```
251
-
252
- ### Definition Setup
253
-
254
- ```ruby
255
- class PostDefinition < ResourceDefinition
256
- nested_input :comments do |n|
257
- n.input :author_name
258
- n.input :body, as: :text
259
- end
260
-
261
- # Or reference another definition
262
- nested_input :comments, using: CommentDefinition, fields: %i[author_name body]
263
- end
264
- ```
265
-
266
- ### Rendering
267
-
268
- ```ruby
269
- class Form < Form
270
- def form_template
271
- render_resource_field :title
272
- render_resource_field :content
273
-
274
- # Nested fields are automatically handled
275
- render_resource_field :comments
276
-
277
- render_actions
278
- end
279
- end
280
- ```
281
-
282
- ## Dynamic Forms (pre_submit)
283
-
284
- Fields with `pre_submit: true` trigger form re-rendering on change:
285
-
286
- ```ruby
287
- class PostDefinition < ResourceDefinition
288
- input :post_type, as: :select,
289
- choices: %w[article video podcast],
290
- pre_submit: true
291
-
292
- input :video_url,
293
- condition: -> { object.post_type == "video" }
294
-
295
- input :podcast_url,
296
- condition: -> { object.post_type == "podcast" }
297
- end
298
- ```
299
-
300
- When `post_type` changes, the form re-renders via Turbo and shows/hides conditional fields.
301
-
302
- ## Form Actions
303
-
304
- ### Submit and Continue Button
305
-
306
- Forms include a secondary button ("Create and add another" for new records, "Update and continue editing" for existing). Control this in your definition:
307
-
308
- ```ruby
309
- class PostDefinition < ResourceDefinition
310
- # nil (default) = auto-detect (hidden for singular resources, shown for plural)
311
- # true = always show
312
- # false = always hide
313
- submit_and_continue false
314
- end
315
- ```
316
-
317
- Singular resources (e.g., `resource :profile` routes or `has_one` nested) auto-hide this button.
318
-
319
- ### Default Actions
320
-
321
- ```ruby
322
- def render_actions
323
- actions_wrapper {
324
- render submit_button
325
- }
326
- end
327
- ```
328
-
329
- ### Custom Actions
330
-
331
- ```ruby
332
- def render_actions
333
- actions_wrapper {
334
- # Cancel link
335
- a(href: resource_url_for(resource_class), class: "btn btn-secondary") {
336
- "Cancel"
337
- }
338
-
339
- # Save as draft
340
- button(type: :submit, name: "draft", value: "1", class: "btn") {
341
- "Save Draft"
342
- }
343
-
344
- # Primary submit
345
- render submit_button
346
- }
347
- end
348
- ```
349
-
350
- ## Form Context
351
-
352
- Inside form templates:
353
-
354
- ```ruby
355
- class Form < Form
356
- def form_template
357
- # Form object
358
- object # The record
359
- record # Alias for object
360
- object.new_record? # Check if creating
361
-
362
- # Request context
363
- current_user
364
- current_parent
365
- request
366
- params
367
-
368
- # Definition
369
- resource_definition
370
- resource_fields # Permitted fields
371
-
372
- # URL helpers
373
- resource_url_for(object)
374
- resource_url_for(Post, action: :new)
375
-
376
- # Rails helpers
377
- helpers.link_to(...)
378
- end
379
- end
380
- ```
381
-
382
- ## Interaction Forms
383
-
384
- Forms for interactive actions:
385
-
386
- ```ruby
387
- class PublishPostInteraction < ResourceInteraction
388
- attribute :publish_date, :date
389
- attribute :notify_subscribers, :boolean, default: true
390
-
391
- input :publish_date, as: :flatpickr
392
- input :notify_subscribers
393
-
394
- # Custom form (optional)
395
- class Form < Plutonium::UI::Form::Interaction
396
- def form_template
397
- div(class: "space-y-4") {
398
- render_resource_field :publish_date
399
- render_resource_field :notify_subscribers
400
- }
401
- render_actions
402
- end
403
- end
404
- end
405
- ```
406
-
407
- ## Related
408
-
409
- - [Fields Reference](/reference/definition/fields) - Input configuration
410
- - [Views Reference](./index) - Custom page classes
411
- - [Theming Guide](/guides/theming) - TailwindCSS and styling