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.
- checksums.yaml +4 -4
- data/.claude/skills/plutonium/skill.md +53 -0
- data/.claude/skills/{assets → plutonium-assets}/SKILL.md +13 -8
- data/.claude/skills/{connect-resource → plutonium-connect-resource}/SKILL.md +1 -1
- data/.claude/skills/{controller → plutonium-controller}/SKILL.md +27 -13
- data/.claude/skills/{create-resource → plutonium-create-resource}/SKILL.md +1 -1
- data/.claude/skills/{definition → plutonium-definition}/SKILL.md +10 -10
- data/.claude/skills/{definition-actions → plutonium-definition-actions}/SKILL.md +34 -9
- data/.claude/skills/{definition-fields → plutonium-definition-fields}/SKILL.md +38 -10
- data/.claude/skills/plutonium-definition-query/SKILL.md +356 -0
- data/.claude/skills/{forms → plutonium-forms}/SKILL.md +6 -6
- data/.claude/skills/{installation → plutonium-installation}/SKILL.md +9 -9
- data/.claude/skills/{interaction → plutonium-interaction}/SKILL.md +20 -19
- data/.claude/skills/{model → plutonium-model}/SKILL.md +3 -3
- data/.claude/skills/{model-features → plutonium-model-features}/SKILL.md +3 -3
- data/.claude/skills/{nested-resources → plutonium-nested-resources}/SKILL.md +5 -5
- data/.claude/skills/{package → plutonium-package}/SKILL.md +7 -8
- data/.claude/skills/{policy → plutonium-policy}/SKILL.md +26 -4
- data/.claude/skills/{portal → plutonium-portal}/SKILL.md +33 -31
- data/.claude/skills/{resource → plutonium-resource}/SKILL.md +27 -27
- data/.claude/skills/{rodauth → plutonium-rodauth}/SKILL.md +5 -5
- data/.claude/skills/plutonium-theming/SKILL.md +424 -0
- data/.claude/skills/{views → plutonium-views}/SKILL.md +7 -7
- data/CHANGELOG.md +52 -0
- data/CLAUDE.md +215 -0
- data/CONTRIBUTING.md +72 -18
- data/README.md +100 -19
- data/app/assets/plutonium.css +1 -11
- data/app/assets/plutonium.js +1685 -1146
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +70 -70
- data/app/assets/plutonium.min.js.map +4 -4
- data/app/views/resource/interactive_bulk_action.html.erb +1 -5
- data/app/views/rodauth/_email_auth_request_form.html.erb +1 -1
- data/app/views/rodauth/_login_form.html.erb +15 -55
- data/app/views/rodauth/_login_form_footer.html.erb +2 -2
- data/app/views/rodauth/_password_visibility.html.erb +2 -8
- data/app/views/rodauth/add_recovery_codes.html.erb +2 -2
- data/app/views/rodauth/change_login.html.erb +36 -19
- data/app/views/rodauth/change_password.html.erb +34 -10
- data/app/views/rodauth/close_account.html.erb +12 -4
- data/app/views/rodauth/confirm_password.html.erb +19 -17
- data/app/views/rodauth/create_account.html.erb +30 -109
- data/app/views/rodauth/email_auth.html.erb +1 -1
- data/app/views/rodauth/logout.html.erb +4 -4
- data/app/views/rodauth/otp_auth.html.erb +13 -4
- data/app/views/rodauth/otp_disable.html.erb +12 -4
- data/app/views/rodauth/otp_setup.html.erb +29 -12
- data/app/views/rodauth/otp_unlock.html.erb +19 -10
- data/app/views/rodauth/otp_unlock_not_available.html.erb +7 -7
- data/app/views/rodauth/recovery_auth.html.erb +12 -4
- data/app/views/rodauth/recovery_codes.html.erb +12 -4
- data/app/views/rodauth/remember.html.erb +7 -7
- data/app/views/rodauth/reset_password.html.erb +23 -7
- data/app/views/rodauth/reset_password_request.html.erb +14 -10
- data/app/views/rodauth/sms_auth.html.erb +13 -4
- data/app/views/rodauth/sms_confirm.html.erb +13 -4
- data/app/views/rodauth/sms_disable.html.erb +12 -4
- data/app/views/rodauth/sms_request.html.erb +1 -1
- data/app/views/rodauth/sms_setup.html.erb +23 -7
- data/app/views/rodauth/two_factor_auth.html.erb +2 -2
- data/app/views/rodauth/two_factor_disable.html.erb +12 -4
- data/app/views/rodauth/two_factor_manage.html.erb +7 -7
- data/app/views/rodauth/unlock_account.html.erb +13 -5
- data/app/views/rodauth/unlock_account_request.html.erb +2 -2
- data/app/views/rodauth/verify_account.html.erb +25 -7
- data/app/views/rodauth/verify_account_resend.html.erb +14 -10
- data/app/views/rodauth/verify_login_change.html.erb +1 -1
- data/app/views/rodauth/webauthn_auth.html.erb +1 -1
- data/app/views/rodauth/webauthn_remove.html.erb +18 -8
- data/app/views/rodauth/webauthn_setup.html.erb +12 -4
- data/docs/.vitepress/config.ts +15 -26
- data/docs/.vitepress/theme/custom.css +388 -29
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/tutorial/02-first-resource.md +9 -0
- data/docs/getting-started/tutorial/06-nested-resources.md +2 -2
- data/docs/getting-started/tutorial/07-author-portal.md +191 -0
- data/docs/getting-started/tutorial/{07-customizing-ui.md → 08-customizing-ui.md} +7 -7
- data/docs/getting-started/tutorial/index.md +5 -2
- data/docs/guides/authorization.md +33 -0
- data/docs/guides/creating-packages.md +12 -16
- data/docs/guides/custom-actions.md +36 -0
- data/docs/guides/search-filtering.md +121 -42
- data/docs/guides/theming.md +232 -36
- data/docs/index.md +203 -57
- data/docs/public/og-image.png +0 -0
- data/docs/reference/controller/index.md +14 -16
- data/docs/reference/definition/actions.md +38 -3
- data/docs/reference/definition/fields.md +3 -3
- data/docs/reference/definition/index.md +2 -2
- data/docs/reference/generators/index.md +0 -1
- data/docs/reference/interaction/index.md +14 -10
- data/docs/reference/model/index.md +0 -1
- data/docs/reference/portal/index.md +13 -27
- data/gemfiles/rails_7.gemfile.lock +1 -1
- data/gemfiles/rails_8.0.gemfile.lock +1 -1
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/generators/pu/pkg/portal/portal_generator.rb +0 -2
- data/lib/generators/pu/pkg/portal/templates/app/views/package/dashboard/index.html.erb +28 -72
- data/lib/plutonium/action/interactive.rb +2 -2
- data/lib/plutonium/core/controller.rb +2 -1
- data/lib/plutonium/definition/actions.rb +2 -2
- data/lib/plutonium/lib/deep_freezer.rb +3 -7
- data/lib/plutonium/query/filter.rb +14 -0
- data/lib/plutonium/query/filters/association.rb +49 -0
- data/lib/plutonium/query/filters/boolean.rb +35 -0
- data/lib/plutonium/query/filters/date.rb +97 -0
- data/lib/plutonium/query/filters/date_range.rb +58 -0
- data/lib/plutonium/query/filters/select.rb +55 -0
- data/lib/plutonium/resource/controllers/crud_actions.rb +24 -6
- data/lib/plutonium/resource/controllers/interactive_actions.rb +76 -58
- data/lib/plutonium/resource/controllers/queryable.rb +4 -2
- data/lib/plutonium/resource/query_object.rb +1 -1
- data/lib/plutonium/ui/action_button.rb +23 -65
- data/lib/plutonium/ui/actions_dropdown.rb +103 -0
- data/lib/plutonium/ui/block.rb +1 -1
- data/lib/plutonium/ui/breadcrumbs.rb +12 -19
- data/lib/plutonium/ui/color_mode_selector.rb +1 -1
- data/lib/plutonium/ui/component/kit.rb +6 -0
- data/lib/plutonium/ui/component_classes.rb +102 -0
- data/lib/plutonium/ui/display/base.rb +15 -0
- data/lib/plutonium/ui/display/components/attachment.rb +6 -5
- data/lib/plutonium/ui/display/components/boolean.rb +23 -0
- data/lib/plutonium/ui/display/components/color.rb +23 -0
- data/lib/plutonium/ui/display/resource.rb +1 -1
- data/lib/plutonium/ui/display/theme.rb +29 -15
- data/lib/plutonium/ui/empty_card.rb +3 -3
- data/lib/plutonium/ui/form/base.rb +20 -0
- data/lib/plutonium/ui/form/components/key_value_store.rb +11 -11
- data/lib/plutonium/ui/form/components/resource_select.rb +31 -0
- data/lib/plutonium/ui/form/components/secure_association.rb +1 -2
- data/lib/plutonium/ui/form/components/uppy.rb +5 -4
- data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +4 -4
- data/lib/plutonium/ui/form/interaction.rb +17 -1
- data/lib/plutonium/ui/form/query.rb +133 -80
- data/lib/plutonium/ui/form/theme.rb +50 -35
- data/lib/plutonium/ui/frame_navigator_panel.rb +2 -2
- data/lib/plutonium/ui/layout/base.rb +1 -1
- data/lib/plutonium/ui/layout/header.rb +4 -7
- data/lib/plutonium/ui/layout/rodauth_layout.rb +7 -7
- data/lib/plutonium/ui/layout/sidebar.rb +1 -1
- data/lib/plutonium/ui/nav_grid_menu.rb +7 -6
- data/lib/plutonium/ui/nav_user.rb +9 -8
- data/lib/plutonium/ui/page/interactive_action.rb +5 -5
- data/lib/plutonium/ui/page_header.rb +29 -10
- data/lib/plutonium/ui/panel.rb +4 -4
- data/lib/plutonium/ui/sidebar_menu.rb +8 -8
- data/lib/plutonium/ui/skeleton_table.rb +7 -8
- data/lib/plutonium/ui/tab_list.rb +5 -5
- data/lib/plutonium/ui/table/base.rb +3 -0
- data/lib/plutonium/ui/table/components/attachment.rb +4 -3
- data/lib/plutonium/ui/table/components/bulk_actions_toolbar.rb +82 -0
- data/lib/plutonium/ui/table/components/pagy_info.rb +2 -2
- data/lib/plutonium/ui/table/components/pagy_pagination.rb +13 -8
- data/lib/plutonium/ui/table/components/row_actions_dropdown.rb +101 -0
- data/lib/plutonium/ui/table/components/scopes_bar.rb +2 -2
- data/lib/plutonium/ui/table/components/selection_column.rb +100 -0
- data/lib/plutonium/ui/table/display_theme.rb +6 -6
- data/lib/plutonium/ui/table/resource.rb +93 -52
- data/lib/plutonium/ui/table/theme.rb +28 -15
- data/lib/plutonium/version.rb +1 -1
- data/package.json +2 -2
- data/plutonium.gemspec +5 -4
- data/src/css/components.css +471 -0
- data/src/css/intl_tel_input.css +2 -2
- data/src/css/plutonium.css +2 -0
- data/src/css/tokens.css +149 -0
- data/src/js/controllers/bulk_actions_controller.js +109 -0
- data/src/js/controllers/filter_panel_controller.js +35 -0
- data/src/js/controllers/register_controllers.js +5 -1
- data/src/js/controllers/resource_drop_down_controller.js +25 -1
- data/src/js/controllers/slim_select_controller.js +6 -2
- data/src/js/turbo/turbo_actions.js +1 -1
- metadata +52 -39
- data/.claude/skills/definition-query/SKILL.md +0 -334
- data/docs/concepts/architecture.md +0 -226
- data/docs/concepts/auto-detection.md +0 -254
- data/docs/concepts/index.md +0 -61
- data/docs/concepts/packages-portals.md +0 -304
- data/docs/concepts/resources.md +0 -224
- data/docs/cookbook/blog.md +0 -411
- data/docs/cookbook/index.md +0 -289
- data/docs/cookbook/saas.md +0 -481
- data/docs/public/CLAUDE.md +0 -578
- 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 "./
|
|
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:
|
|
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
|
-
|
|
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
|
}
|
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.
|
|
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-
|
|
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.
|
|
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.
|
|
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
|
|
392
|
-
|
|
393
|
-
|
|
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/
|
|
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-
|
|
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:
|
|
1022
|
+
summary: Build production-ready Rails apps in minutes, not days
|
|
1010
1023
|
test_files: []
|