plutonium 0.34.1 → 0.35.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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/skill.md +53 -0
  3. data/.claude/skills/{assets → plutonium-assets}/SKILL.md +13 -8
  4. data/.claude/skills/{connect-resource → plutonium-connect-resource}/SKILL.md +1 -1
  5. data/.claude/skills/{controller → plutonium-controller}/SKILL.md +27 -13
  6. data/.claude/skills/{create-resource → plutonium-create-resource}/SKILL.md +1 -1
  7. data/.claude/skills/{definition → plutonium-definition}/SKILL.md +10 -10
  8. data/.claude/skills/{definition-actions → plutonium-definition-actions}/SKILL.md +34 -9
  9. data/.claude/skills/{definition-fields → plutonium-definition-fields}/SKILL.md +38 -10
  10. data/.claude/skills/plutonium-definition-query/SKILL.md +356 -0
  11. data/.claude/skills/{forms → plutonium-forms}/SKILL.md +6 -6
  12. data/.claude/skills/{installation → plutonium-installation}/SKILL.md +9 -9
  13. data/.claude/skills/{interaction → plutonium-interaction}/SKILL.md +20 -19
  14. data/.claude/skills/{model → plutonium-model}/SKILL.md +3 -3
  15. data/.claude/skills/{model-features → plutonium-model-features}/SKILL.md +3 -3
  16. data/.claude/skills/{nested-resources → plutonium-nested-resources}/SKILL.md +5 -5
  17. data/.claude/skills/{package → plutonium-package}/SKILL.md +7 -8
  18. data/.claude/skills/{policy → plutonium-policy}/SKILL.md +26 -4
  19. data/.claude/skills/{portal → plutonium-portal}/SKILL.md +33 -31
  20. data/.claude/skills/{resource → plutonium-resource}/SKILL.md +27 -27
  21. data/.claude/skills/{rodauth → plutonium-rodauth}/SKILL.md +5 -5
  22. data/.claude/skills/plutonium-theming/SKILL.md +424 -0
  23. data/.claude/skills/{views → plutonium-views}/SKILL.md +7 -7
  24. data/CHANGELOG.md +52 -0
  25. data/CLAUDE.md +215 -0
  26. data/CONTRIBUTING.md +72 -18
  27. data/README.md +100 -19
  28. data/app/assets/plutonium.css +1 -11
  29. data/app/assets/plutonium.js +1685 -1146
  30. data/app/assets/plutonium.js.map +4 -4
  31. data/app/assets/plutonium.min.js +70 -70
  32. data/app/assets/plutonium.min.js.map +4 -4
  33. data/app/views/resource/interactive_bulk_action.html.erb +1 -5
  34. data/app/views/rodauth/_email_auth_request_form.html.erb +1 -1
  35. data/app/views/rodauth/_login_form.html.erb +15 -55
  36. data/app/views/rodauth/_login_form_footer.html.erb +2 -2
  37. data/app/views/rodauth/_password_visibility.html.erb +2 -8
  38. data/app/views/rodauth/add_recovery_codes.html.erb +2 -2
  39. data/app/views/rodauth/change_login.html.erb +36 -19
  40. data/app/views/rodauth/change_password.html.erb +34 -10
  41. data/app/views/rodauth/close_account.html.erb +12 -4
  42. data/app/views/rodauth/confirm_password.html.erb +19 -17
  43. data/app/views/rodauth/create_account.html.erb +30 -109
  44. data/app/views/rodauth/email_auth.html.erb +1 -1
  45. data/app/views/rodauth/logout.html.erb +4 -4
  46. data/app/views/rodauth/otp_auth.html.erb +13 -4
  47. data/app/views/rodauth/otp_disable.html.erb +12 -4
  48. data/app/views/rodauth/otp_setup.html.erb +29 -12
  49. data/app/views/rodauth/otp_unlock.html.erb +19 -10
  50. data/app/views/rodauth/otp_unlock_not_available.html.erb +7 -7
  51. data/app/views/rodauth/recovery_auth.html.erb +12 -4
  52. data/app/views/rodauth/recovery_codes.html.erb +12 -4
  53. data/app/views/rodauth/remember.html.erb +7 -7
  54. data/app/views/rodauth/reset_password.html.erb +23 -7
  55. data/app/views/rodauth/reset_password_request.html.erb +14 -10
  56. data/app/views/rodauth/sms_auth.html.erb +13 -4
  57. data/app/views/rodauth/sms_confirm.html.erb +13 -4
  58. data/app/views/rodauth/sms_disable.html.erb +12 -4
  59. data/app/views/rodauth/sms_request.html.erb +1 -1
  60. data/app/views/rodauth/sms_setup.html.erb +23 -7
  61. data/app/views/rodauth/two_factor_auth.html.erb +2 -2
  62. data/app/views/rodauth/two_factor_disable.html.erb +12 -4
  63. data/app/views/rodauth/two_factor_manage.html.erb +7 -7
  64. data/app/views/rodauth/unlock_account.html.erb +13 -5
  65. data/app/views/rodauth/unlock_account_request.html.erb +2 -2
  66. data/app/views/rodauth/verify_account.html.erb +25 -7
  67. data/app/views/rodauth/verify_account_resend.html.erb +14 -10
  68. data/app/views/rodauth/verify_login_change.html.erb +1 -1
  69. data/app/views/rodauth/webauthn_auth.html.erb +1 -1
  70. data/app/views/rodauth/webauthn_remove.html.erb +18 -8
  71. data/app/views/rodauth/webauthn_setup.html.erb +12 -4
  72. data/docs/.vitepress/config.ts +15 -26
  73. data/docs/.vitepress/theme/custom.css +388 -29
  74. data/docs/getting-started/index.md +1 -1
  75. data/docs/getting-started/tutorial/02-first-resource.md +9 -0
  76. data/docs/getting-started/tutorial/06-nested-resources.md +2 -2
  77. data/docs/getting-started/tutorial/07-author-portal.md +191 -0
  78. data/docs/getting-started/tutorial/{07-customizing-ui.md → 08-customizing-ui.md} +7 -7
  79. data/docs/getting-started/tutorial/index.md +5 -2
  80. data/docs/guides/authorization.md +33 -0
  81. data/docs/guides/creating-packages.md +12 -16
  82. data/docs/guides/custom-actions.md +36 -0
  83. data/docs/guides/search-filtering.md +121 -42
  84. data/docs/guides/theming.md +232 -36
  85. data/docs/index.md +203 -57
  86. data/docs/public/og-image.png +0 -0
  87. data/docs/reference/controller/index.md +14 -16
  88. data/docs/reference/definition/actions.md +38 -3
  89. data/docs/reference/definition/fields.md +3 -3
  90. data/docs/reference/definition/index.md +2 -2
  91. data/docs/reference/generators/index.md +0 -1
  92. data/docs/reference/interaction/index.md +14 -10
  93. data/docs/reference/model/index.md +0 -1
  94. data/docs/reference/portal/index.md +13 -27
  95. data/gemfiles/rails_7.gemfile.lock +1 -1
  96. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  97. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  98. data/lib/generators/pu/pkg/portal/portal_generator.rb +0 -2
  99. data/lib/generators/pu/pkg/portal/templates/app/views/package/dashboard/index.html.erb +28 -72
  100. data/lib/plutonium/action/interactive.rb +2 -2
  101. data/lib/plutonium/core/controller.rb +2 -1
  102. data/lib/plutonium/definition/actions.rb +2 -2
  103. data/lib/plutonium/lib/deep_freezer.rb +3 -7
  104. data/lib/plutonium/query/filter.rb +14 -0
  105. data/lib/plutonium/query/filters/association.rb +49 -0
  106. data/lib/plutonium/query/filters/boolean.rb +35 -0
  107. data/lib/plutonium/query/filters/date.rb +97 -0
  108. data/lib/plutonium/query/filters/date_range.rb +58 -0
  109. data/lib/plutonium/query/filters/select.rb +55 -0
  110. data/lib/plutonium/resource/controllers/crud_actions.rb +24 -6
  111. data/lib/plutonium/resource/controllers/interactive_actions.rb +76 -58
  112. data/lib/plutonium/resource/controllers/queryable.rb +4 -2
  113. data/lib/plutonium/resource/query_object.rb +1 -1
  114. data/lib/plutonium/ui/action_button.rb +23 -65
  115. data/lib/plutonium/ui/actions_dropdown.rb +103 -0
  116. data/lib/plutonium/ui/block.rb +1 -1
  117. data/lib/plutonium/ui/breadcrumbs.rb +12 -19
  118. data/lib/plutonium/ui/color_mode_selector.rb +1 -1
  119. data/lib/plutonium/ui/component/kit.rb +6 -0
  120. data/lib/plutonium/ui/component_classes.rb +102 -0
  121. data/lib/plutonium/ui/display/base.rb +15 -0
  122. data/lib/plutonium/ui/display/components/attachment.rb +6 -5
  123. data/lib/plutonium/ui/display/components/boolean.rb +23 -0
  124. data/lib/plutonium/ui/display/components/color.rb +23 -0
  125. data/lib/plutonium/ui/display/resource.rb +1 -1
  126. data/lib/plutonium/ui/display/theme.rb +29 -15
  127. data/lib/plutonium/ui/empty_card.rb +3 -3
  128. data/lib/plutonium/ui/form/base.rb +20 -0
  129. data/lib/plutonium/ui/form/components/key_value_store.rb +11 -11
  130. data/lib/plutonium/ui/form/components/resource_select.rb +31 -0
  131. data/lib/plutonium/ui/form/components/secure_association.rb +1 -2
  132. data/lib/plutonium/ui/form/components/uppy.rb +5 -4
  133. data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +4 -4
  134. data/lib/plutonium/ui/form/interaction.rb +17 -1
  135. data/lib/plutonium/ui/form/query.rb +133 -80
  136. data/lib/plutonium/ui/form/theme.rb +50 -35
  137. data/lib/plutonium/ui/frame_navigator_panel.rb +2 -2
  138. data/lib/plutonium/ui/layout/base.rb +1 -1
  139. data/lib/plutonium/ui/layout/header.rb +4 -7
  140. data/lib/plutonium/ui/layout/rodauth_layout.rb +7 -7
  141. data/lib/plutonium/ui/layout/sidebar.rb +1 -1
  142. data/lib/plutonium/ui/nav_grid_menu.rb +7 -6
  143. data/lib/plutonium/ui/nav_user.rb +9 -8
  144. data/lib/plutonium/ui/page/interactive_action.rb +5 -5
  145. data/lib/plutonium/ui/page_header.rb +29 -10
  146. data/lib/plutonium/ui/panel.rb +4 -4
  147. data/lib/plutonium/ui/sidebar_menu.rb +8 -8
  148. data/lib/plutonium/ui/skeleton_table.rb +7 -8
  149. data/lib/plutonium/ui/tab_list.rb +5 -5
  150. data/lib/plutonium/ui/table/base.rb +3 -0
  151. data/lib/plutonium/ui/table/components/attachment.rb +4 -3
  152. data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +82 -0
  153. data/lib/plutonium/ui/table/components/pagy_info.rb +2 -2
  154. data/lib/plutonium/ui/table/components/pagy_pagination.rb +13 -8
  155. data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +101 -0
  156. data/lib/plutonium/ui/table/components/scopes_bar.rb +2 -2
  157. data/lib/plutonium/ui/table/components/selection_column.rb +100 -0
  158. data/lib/plutonium/ui/table/display_theme.rb +6 -6
  159. data/lib/plutonium/ui/table/resource.rb +93 -52
  160. data/lib/plutonium/ui/table/theme.rb +28 -15
  161. data/lib/plutonium/version.rb +1 -1
  162. data/package.json +2 -2
  163. data/plutonium.gemspec +5 -4
  164. data/src/css/components.css +471 -0
  165. data/src/css/intl_tel_input.css +2 -2
  166. data/src/css/plutonium.css +2 -0
  167. data/src/css/tokens.css +149 -0
  168. data/src/js/controllers/bulk_actions_controller.js +109 -0
  169. data/src/js/controllers/filter_panel_controller.js +35 -0
  170. data/src/js/controllers/register_controllers.js +5 -1
  171. data/src/js/controllers/resource_drop_down_controller.js +25 -1
  172. data/src/js/controllers/slim_select_controller.js +6 -2
  173. data/src/js/turbo/turbo_actions.js +1 -1
  174. metadata +52 -39
  175. data/.claude/skills/definition-query/SKILL.md +0 -334
  176. data/docs/concepts/architecture.md +0 -226
  177. data/docs/concepts/auto-detection.md +0 -254
  178. data/docs/concepts/index.md +0 -61
  179. data/docs/concepts/packages-portals.md +0 -304
  180. data/docs/concepts/resources.md +0 -224
  181. data/docs/cookbook/blog.md +0 -411
  182. data/docs/cookbook/index.md +0 -289
  183. data/docs/cookbook/saas.md +0 -481
  184. data/docs/public/CLAUDE.md +0 -578
  185. data/lib/generators/pu/pkg/portal/templates/app/controllers/resource_controller.rb.tt +0 -5
@@ -0,0 +1,109 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="bulk-actions"
4
+ // Manages bulk action selection in resource tables
5
+ export default class extends Controller {
6
+ static targets = ["checkbox", "checkboxAll", "toolbar", "selectedCount", "actionButton", "selectionCell"]
7
+ static values = {
8
+ hasActions: { type: Boolean, default: false }
9
+ }
10
+
11
+ connect() {
12
+ // Show selection column only if bulk actions exist
13
+ if (this.hasActionsValue) {
14
+ this.enableSelection()
15
+ }
16
+ }
17
+
18
+ enableSelection() {
19
+ // Show all selection cells (header + body cells)
20
+ this.selectionCellTargets.forEach(el => el.classList.remove("hidden"))
21
+ }
22
+
23
+ toggle() {
24
+ this.updateUI()
25
+ }
26
+
27
+ toggleAll(event) {
28
+ const checked = event.target.checked
29
+ this.checkboxTargets.forEach(cb => cb.checked = checked)
30
+ this.updateUI()
31
+ }
32
+
33
+ updateUI() {
34
+ const checked = this.checked
35
+ const total = this.checkboxTargets.length
36
+
37
+ // Update "select all" checkbox state (checked, unchecked, or indeterminate)
38
+ if (this.hasCheckboxAllTarget) {
39
+ this.checkboxAllTarget.checked = checked.length === total && total > 0
40
+ this.checkboxAllTarget.indeterminate = checked.length > 0 && checked.length < total
41
+ }
42
+
43
+ // Show toolbar only when items are selected
44
+ if (this.hasToolbarTarget) {
45
+ this.toolbarTarget.classList.toggle("hidden", checked.length === 0)
46
+ }
47
+
48
+ // Update selected count display
49
+ if (this.hasSelectedCountTarget) {
50
+ this.selectedCountTarget.textContent = checked.length
51
+ }
52
+
53
+ // Update action button URLs and visibility based on allowed actions
54
+ this.updateActionButtons()
55
+ }
56
+
57
+ updateActionButtons() {
58
+ const checked = this.checked
59
+ const ids = checked.map(cb => cb.value)
60
+ const idsParam = ids.map(id => `ids[]=${encodeURIComponent(id)}`).join("&")
61
+
62
+ // Compute intersection of allowed actions across all selected records
63
+ const allowedActions = this.computeAllowedActions(checked)
64
+
65
+ this.actionButtonTargets.forEach(button => {
66
+ const baseUrl = button.dataset.bulkActionUrl
67
+ const actionName = button.dataset.bulkActionName
68
+
69
+ // Update URL with selected IDs
70
+ if (baseUrl) {
71
+ button.href = idsParam ? `${baseUrl}?${idsParam}` : baseUrl
72
+ }
73
+
74
+ // Show/hide button based on whether action is allowed for all selected records
75
+ button.style.display = allowedActions.has(actionName) ? '' : 'none'
76
+ })
77
+ }
78
+
79
+ // Compute the intersection of allowed actions across all selected checkboxes
80
+ computeAllowedActions(checked) {
81
+ if (checked.length === 0) {
82
+ return new Set()
83
+ }
84
+
85
+ // Start with actions allowed for the first selected record
86
+ let intersection = new Set(this.getAllowedActionsForCheckbox(checked[0]))
87
+
88
+ // Intersect with actions allowed for each subsequent record
89
+ for (let i = 1; i < checked.length; i++) {
90
+ const actions = this.getAllowedActionsForCheckbox(checked[i])
91
+ intersection = new Set([...intersection].filter(a => actions.includes(a)))
92
+ }
93
+
94
+ return intersection
95
+ }
96
+
97
+ getAllowedActionsForCheckbox(checkbox) {
98
+ const allowedActions = checkbox.dataset.allowedActions
99
+ return allowedActions ? allowedActions.split(",").filter(a => a) : []
100
+ }
101
+
102
+ get checked() {
103
+ return this.checkboxTargets.filter(cb => cb.checked)
104
+ }
105
+
106
+ get unchecked() {
107
+ return this.checkboxTargets.filter(cb => !cb.checked)
108
+ }
109
+ }
@@ -0,0 +1,35 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="filter-panel"
4
+ export default class extends Controller {
5
+ clear() {
6
+ this.element.querySelectorAll('input, select, textarea').forEach(input => {
7
+ if (input.type === 'checkbox' || input.type === 'radio') {
8
+ input.checked = false
9
+ } else if (input.tagName === 'SELECT') {
10
+ input.selectedIndex = 0
11
+ } else if (input.type === 'hidden') {
12
+ // Clear hidden inputs that are filter values (e.g., flatpickr)
13
+ if (input.dataset.controller === 'flatpickr') {
14
+ input.value = ''
15
+ }
16
+ } else {
17
+ input.value = ''
18
+ }
19
+ })
20
+
21
+ // Clear flatpickr instances via Stimulus controller
22
+ this.element.querySelectorAll('[data-controller="flatpickr"]').forEach(input => {
23
+ const controller = this.application.getControllerForElementAndIdentifier(input, 'flatpickr')
24
+ if (controller?.picker) {
25
+ controller.picker.clear()
26
+ }
27
+ })
28
+
29
+ // Submit the parent form
30
+ const form = this.element.closest('form')
31
+ if (form) {
32
+ form.requestSubmit()
33
+ }
34
+ }
35
+ }
@@ -19,7 +19,9 @@ import AttachmentPreviewContainerController from "./attachment_preview_container
19
19
  import SidebarController from "./sidebar_controller.js"
20
20
  import PasswordVisibilityController from "./password_visibility_controller.js"
21
21
  import RemoteModalController from "./remote_modal_controller.js"
22
- import KeyValueStoreController from "./key_value_st\ore_controller.js"
22
+ import KeyValueStoreController from "./key_value_store_controller.js"
23
+ import BulkActionsController from "./bulk_actions_controller.js"
24
+ import FilterPanelController from "./filter_panel_controller.js"
23
25
 
24
26
  export default function (application) {
25
27
  // Register controllers here
@@ -44,4 +46,6 @@ export default function (application) {
44
46
  application.register("attachment-preview-container", AttachmentPreviewContainerController)
45
47
  application.register("remote-modal", RemoteModalController)
46
48
  application.register("key-value-store", KeyValueStoreController)
49
+ application.register("bulk-actions", BulkActionsController)
50
+ application.register("filter-panel", FilterPanelController)
47
51
  }
@@ -4,6 +4,9 @@ import { createPopper } from '@popperjs/core'
4
4
  // Connects to data-controller="resource-drop-down"
5
5
  export default class extends Controller {
6
6
  static targets = ["trigger", "menu"]
7
+ static values = {
8
+ placement: { type: String, default: 'bottom' }
9
+ }
7
10
 
8
11
  connect() {
9
12
  this.visible = false
@@ -11,7 +14,7 @@ export default class extends Controller {
11
14
 
12
15
  // Default options matching Flowbite's defaults
13
16
  this.options = {
14
- placement: 'bottom',
17
+ placement: this.placementValue,
15
18
  triggerType: 'click',
16
19
  offsetSkidding: 0,
17
20
  offsetDistance: 10,
@@ -25,7 +28,9 @@ export default class extends Controller {
25
28
  init() {
26
29
  if (this.triggerTarget && this.menuTarget && !this.initialized) {
27
30
  // Initialize popper instance
31
+ // Use 'fixed' strategy to escape overflow containers (e.g., table rows)
28
32
  this.popperInstance = createPopper(this.triggerTarget, this.menuTarget, {
33
+ strategy: 'fixed',
29
34
  placement: this.options.placement,
30
35
  modifiers: [
31
36
  {
@@ -34,6 +39,21 @@ export default class extends Controller {
34
39
  offset: [this.options.offsetSkidding, this.options.offsetDistance],
35
40
  },
36
41
  },
42
+ {
43
+ name: 'flip',
44
+ options: {
45
+ fallbackPlacements: ['left-end', 'right-start', 'right-end', 'bottom-start', 'bottom-end', 'top-start', 'top-end'],
46
+ boundary: 'clippingParents',
47
+ },
48
+ },
49
+ {
50
+ name: 'preventOverflow',
51
+ options: {
52
+ boundary: 'clippingParents',
53
+ altAxis: true,
54
+ padding: 8,
55
+ },
56
+ },
37
57
  ],
38
58
  })
39
59
 
@@ -116,11 +136,15 @@ export default class extends Controller {
116
136
  })
117
137
  }
118
138
 
139
+ // Ignore clicks on flatpickr calendars and other floating UI elements
140
+ const isFloatingUI = clickedEl.closest('.flatpickr-calendar, .ss-main, .ss-content')
141
+
119
142
  if (
120
143
  clickedEl !== this.menuTarget &&
121
144
  !this.menuTarget.contains(clickedEl) &&
122
145
  !this.triggerTarget.contains(clickedEl) &&
123
146
  !isIgnored &&
147
+ !isFloatingUI &&
124
148
  this.visible
125
149
  ) {
126
150
  this.hide()
@@ -9,8 +9,12 @@ export default class extends Controller {
9
9
 
10
10
  // Just recreate SlimSelect after morphing - the DOM will have correct selections
11
11
  this.element.addEventListener("turbo:morph-element", (event) => {
12
- if (event.target === this.element) {
13
- requestAnimationFrame(() => this.#handleMorph());
12
+ if (event.target === this.element && !this.morphing) {
13
+ this.morphing = true;
14
+ requestAnimationFrame(() => {
15
+ this.#handleMorph();
16
+ this.morphing = false;
17
+ });
14
18
  }
15
19
  });
16
20
  }
@@ -1,7 +1,7 @@
1
1
  // Add a redirect stream action
2
2
  Turbo.StreamActions.redirect = function () {
3
3
  // See: https://github.com/hotwired/turbo/issues/554
4
- Turbo.clearCache();
4
+ Turbo.cache.clear();
5
5
 
6
6
  const url = this.getAttribute("url")
7
7
  Turbo.visit(url)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plutonium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.34.1
4
+ version: 0.35.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Froelich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-01-18 00:00:00.000000000 Z
11
+ date: 2026-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - ">="
186
186
  - !ruby/object:Gem::Version
187
- version: 0.10.0
187
+ version: 0.13.0
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
- version: 0.10.0
194
+ version: 0.13.0
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: phlexi-table
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -388,9 +388,10 @@ dependencies:
388
388
  - - ">="
389
389
  - !ruby/object:Gem::Version
390
390
  version: '0'
391
- description: Plutonium extends Rails' capabilities with a powerful, generator-driven
392
- toolkit designed to supercharge your development process. It transforms the way
393
- you build applications with Rails, optimizing for rapid application development.
391
+ description: Plutonium is a Rapid Application Development toolkit for Rails. Convention-driven
392
+ and fully customizable, it adds application-level concepts like resources, policies,
393
+ definitions, and portals that make building complex apps faster. Built for the AI
394
+ era with Claude Code skills.
394
395
  email:
395
396
  - sfroelich01@gmail.com
396
397
  executables:
@@ -399,26 +400,28 @@ extensions: []
399
400
  extra_rdoc_files: []
400
401
  files:
401
402
  - "# Plutonium: The pre-alpha demo.md"
402
- - ".claude/skills/assets/SKILL.md"
403
- - ".claude/skills/connect-resource/SKILL.md"
404
- - ".claude/skills/controller/SKILL.md"
405
- - ".claude/skills/create-resource/SKILL.md"
406
- - ".claude/skills/definition-actions/SKILL.md"
407
- - ".claude/skills/definition-fields/SKILL.md"
408
- - ".claude/skills/definition-query/SKILL.md"
409
- - ".claude/skills/definition/SKILL.md"
410
- - ".claude/skills/forms/SKILL.md"
411
- - ".claude/skills/installation/SKILL.md"
412
- - ".claude/skills/interaction/SKILL.md"
413
- - ".claude/skills/model-features/SKILL.md"
414
- - ".claude/skills/model/SKILL.md"
415
- - ".claude/skills/nested-resources/SKILL.md"
416
- - ".claude/skills/package/SKILL.md"
417
- - ".claude/skills/policy/SKILL.md"
418
- - ".claude/skills/portal/SKILL.md"
419
- - ".claude/skills/resource/SKILL.md"
420
- - ".claude/skills/rodauth/SKILL.md"
421
- - ".claude/skills/views/SKILL.md"
403
+ - ".claude/skills/plutonium-assets/SKILL.md"
404
+ - ".claude/skills/plutonium-connect-resource/SKILL.md"
405
+ - ".claude/skills/plutonium-controller/SKILL.md"
406
+ - ".claude/skills/plutonium-create-resource/SKILL.md"
407
+ - ".claude/skills/plutonium-definition-actions/SKILL.md"
408
+ - ".claude/skills/plutonium-definition-fields/SKILL.md"
409
+ - ".claude/skills/plutonium-definition-query/SKILL.md"
410
+ - ".claude/skills/plutonium-definition/SKILL.md"
411
+ - ".claude/skills/plutonium-forms/SKILL.md"
412
+ - ".claude/skills/plutonium-installation/SKILL.md"
413
+ - ".claude/skills/plutonium-interaction/SKILL.md"
414
+ - ".claude/skills/plutonium-model-features/SKILL.md"
415
+ - ".claude/skills/plutonium-model/SKILL.md"
416
+ - ".claude/skills/plutonium-nested-resources/SKILL.md"
417
+ - ".claude/skills/plutonium-package/SKILL.md"
418
+ - ".claude/skills/plutonium-policy/SKILL.md"
419
+ - ".claude/skills/plutonium-portal/SKILL.md"
420
+ - ".claude/skills/plutonium-resource/SKILL.md"
421
+ - ".claude/skills/plutonium-rodauth/SKILL.md"
422
+ - ".claude/skills/plutonium-theming/SKILL.md"
423
+ - ".claude/skills/plutonium-views/SKILL.md"
424
+ - ".claude/skills/plutonium/skill.md"
422
425
  - ".cliff.toml"
423
426
  - ".node-version"
424
427
  - ".rspec"
@@ -429,6 +432,7 @@ files:
429
432
  - ".vscode/settings.json"
430
433
  - Appraisals
431
434
  - CHANGELOG.md
435
+ - CLAUDE.md
432
436
  - CONTRIBUTING.md
433
437
  - LICENSE.txt
434
438
  - README.md
@@ -516,14 +520,6 @@ files:
516
520
  - docs/.vitepress/config.ts
517
521
  - docs/.vitepress/theme/custom.css
518
522
  - docs/.vitepress/theme/index.ts
519
- - docs/concepts/architecture.md
520
- - docs/concepts/auto-detection.md
521
- - docs/concepts/index.md
522
- - docs/concepts/packages-portals.md
523
- - docs/concepts/resources.md
524
- - docs/cookbook/blog.md
525
- - docs/cookbook/index.md
526
- - docs/cookbook/saas.md
527
523
  - docs/getting-started/index.md
528
524
  - docs/getting-started/installation.md
529
525
  - docs/getting-started/tutorial/01-setup.md
@@ -532,7 +528,8 @@ files:
532
528
  - docs/getting-started/tutorial/04-authorization.md
533
529
  - docs/getting-started/tutorial/05-custom-actions.md
534
530
  - docs/getting-started/tutorial/06-nested-resources.md
535
- - docs/getting-started/tutorial/07-customizing-ui.md
531
+ - docs/getting-started/tutorial/07-author-portal.md
532
+ - docs/getting-started/tutorial/08-customizing-ui.md
536
533
  - docs/getting-started/tutorial/index.md
537
534
  - docs/guides/adding-resources.md
538
535
  - docs/guides/authentication.md
@@ -545,13 +542,13 @@ files:
545
542
  - docs/guides/search-filtering.md
546
543
  - docs/guides/theming.md
547
544
  - docs/index.md
548
- - docs/public/CLAUDE.md
549
545
  - docs/public/android-chrome-192x192.png
550
546
  - docs/public/android-chrome-512x512.png
551
547
  - docs/public/apple-touch-icon.png
552
548
  - docs/public/favicon-16x16.png
553
549
  - docs/public/favicon-32x32.png
554
550
  - docs/public/favicon.ico
551
+ - docs/public/og-image.png
555
552
  - docs/public/plutonium.png
556
553
  - docs/public/site.webmanifest
557
554
  - docs/public/templates/base.rb
@@ -669,7 +666,6 @@ files:
669
666
  - lib/generators/pu/pkg/portal/templates/app/controllers/concerns/controller.rb.tt
670
667
  - lib/generators/pu/pkg/portal/templates/app/controllers/dashboard_controller.rb.tt
671
668
  - lib/generators/pu/pkg/portal/templates/app/controllers/plutonium_controller.rb.tt
672
- - lib/generators/pu/pkg/portal/templates/app/controllers/resource_controller.rb.tt
673
669
  - lib/generators/pu/pkg/portal/templates/app/definitions/resource_definition.rb.tt
674
670
  - lib/generators/pu/pkg/portal/templates/app/policies/resource_policy.rb.tt
675
671
  - lib/generators/pu/pkg/portal/templates/app/presenters/resource_presenter.rb.tt
@@ -829,6 +825,11 @@ files:
829
825
  - lib/plutonium/query/adhoc_block.rb
830
826
  - lib/plutonium/query/base.rb
831
827
  - lib/plutonium/query/filter.rb
828
+ - lib/plutonium/query/filters/association.rb
829
+ - lib/plutonium/query/filters/boolean.rb
830
+ - lib/plutonium/query/filters/date.rb
831
+ - lib/plutonium/query/filters/date_range.rb
832
+ - lib/plutonium/query/filters/select.rb
832
833
  - lib/plutonium/query/filters/text.rb
833
834
  - lib/plutonium/query/model_scope.rb
834
835
  - lib/plutonium/railtie.rb
@@ -860,6 +861,7 @@ files:
860
861
  - lib/plutonium/support/parameters.rb
861
862
  - lib/plutonium/ui.rb
862
863
  - lib/plutonium/ui/action_button.rb
864
+ - lib/plutonium/ui/actions_dropdown.rb
863
865
  - lib/plutonium/ui/block.rb
864
866
  - lib/plutonium/ui/breadcrumbs.rb
865
867
  - lib/plutonium/ui/color_mode_selector.rb
@@ -868,9 +870,12 @@ files:
868
870
  - lib/plutonium/ui/component/kit.rb
869
871
  - lib/plutonium/ui/component/methods.rb
870
872
  - lib/plutonium/ui/component/tokens.rb
873
+ - lib/plutonium/ui/component_classes.rb
871
874
  - lib/plutonium/ui/display/base.rb
872
875
  - lib/plutonium/ui/display/components/association.rb
873
876
  - lib/plutonium/ui/display/components/attachment.rb
877
+ - lib/plutonium/ui/display/components/boolean.rb
878
+ - lib/plutonium/ui/display/components/color.rb
874
879
  - lib/plutonium/ui/display/components/markdown.rb
875
880
  - lib/plutonium/ui/display/components/phlexi_render.rb
876
881
  - lib/plutonium/ui/display/options/inferred_types.rb
@@ -884,6 +889,7 @@ files:
884
889
  - lib/plutonium/ui/form/components/flatpickr.rb
885
890
  - lib/plutonium/ui/form/components/intl_tel_input.rb
886
891
  - lib/plutonium/ui/form/components/key_value_store.rb
892
+ - lib/plutonium/ui/form/components/resource_select.rb
887
893
  - lib/plutonium/ui/form/components/secure_association.rb
888
894
  - lib/plutonium/ui/form/components/secure_polymorphic_association.rb
889
895
  - lib/plutonium/ui/form/components/uppy.rb
@@ -915,10 +921,13 @@ files:
915
921
  - lib/plutonium/ui/tab_list.rb
916
922
  - lib/plutonium/ui/table/base.rb
917
923
  - lib/plutonium/ui/table/components/attachment.rb
924
+ - lib/plutonium/ui/table/components/bulk_actions_toolbar.rb
918
925
  - lib/plutonium/ui/table/components/pagy_info.rb
919
926
  - lib/plutonium/ui/table/components/pagy_pagination.rb
927
+ - lib/plutonium/ui/table/components/row_actions_dropdown.rb
920
928
  - lib/plutonium/ui/table/components/scopes_bar.rb
921
929
  - lib/plutonium/ui/table/components/search_bar.rb
930
+ - lib/plutonium/ui/table/components/selection_column.rb
922
931
  - lib/plutonium/ui/table/display_theme.rb
923
932
  - lib/plutonium/ui/table/resource.rb
924
933
  - lib/plutonium/ui/table/theme.rb
@@ -941,6 +950,7 @@ files:
941
950
  - public/plutonium-assets/plutonium.ico
942
951
  - sig/.keep
943
952
  - src/.npmignore
953
+ - src/css/components.css
944
954
  - src/css/core.css
945
955
  - src/css/easymde.css
946
956
  - src/css/flatpickr.css
@@ -948,11 +958,14 @@ files:
948
958
  - src/css/plutonium.css
949
959
  - src/css/plutonium.entry.css
950
960
  - src/css/slim_select.css
961
+ - src/css/tokens.css
951
962
  - src/js/controllers/attachment_input_controller.js
952
963
  - src/js/controllers/attachment_preview_container_controller.js
953
964
  - src/js/controllers/attachment_preview_controller.js
965
+ - src/js/controllers/bulk_actions_controller.js
954
966
  - src/js/controllers/color_mode_controller.js
955
967
  - src/js/controllers/easymde_controller.js
968
+ - src/js/controllers/filter_panel_controller.js
956
969
  - src/js/controllers/flatpickr_controller.js
957
970
  - src/js/controllers/form_controller.js
958
971
  - src/js/controllers/frame_navigator_controller.js
@@ -1006,5 +1019,5 @@ requirements: []
1006
1019
  rubygems_version: 3.4.10
1007
1020
  signing_key:
1008
1021
  specification_version: 4
1009
- summary: The Ultimate Rapid Application Development Toolkit (RADKit) for Rails
1022
+ summary: Build production-ready Rails apps in minutes, not days
1010
1023
  test_files: []