@radioactive-labs/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.
- package/package.json +10 -10
- package/src/css/components.css +304 -131
- package/src/css/slim_select.css +4 -0
- package/src/css/tokens.css +101 -85
- package/src/dist/css/plutonium.css +1 -11
- package/src/dist/js/plutonium.js +1323 -1184
- package/src/dist/js/plutonium.js.map +4 -4
- package/src/dist/js/plutonium.min.js +50 -49
- package/src/dist/js/plutonium.min.js.map +4 -4
- package/src/js/controllers/autosubmit_controller.js +24 -0
- package/src/js/controllers/bulk_actions_controller.js +15 -16
- package/src/js/controllers/capture_url_controller.js +14 -0
- package/src/js/controllers/filter_panel_controller.js +77 -19
- package/src/js/controllers/frame_navigator_controller.js +34 -6
- package/src/js/controllers/icon_rail_controller.js +22 -0
- package/src/js/controllers/icon_rail_flyout_controller.js +128 -0
- package/src/js/controllers/register_controllers.js +16 -0
- package/src/js/controllers/resource_tab_list_controller.js +56 -3
- package/src/js/controllers/row_click_controller.js +21 -0
- package/src/js/controllers/slim_select_controller.js +61 -0
- package/src/js/controllers/table_column_menu_controller.js +43 -0
- package/src/js/controllers/table_header_controller.js +16 -0
- package/src/js/controllers/view_switcher_controller.js +29 -0
- package/src/js/turbo/turbo_actions.js +33 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Connects to data-controller="table-column-menu"
|
|
4
|
+
// Toggles the column ⋯ menu panel; closes on outside click and Escape.
|
|
5
|
+
export default class extends Controller {
|
|
6
|
+
static targets = ["panel"]
|
|
7
|
+
|
|
8
|
+
connect() {
|
|
9
|
+
this._onDocClick = this._onDocClick.bind(this)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
toggle(event) {
|
|
13
|
+
event.preventDefault()
|
|
14
|
+
event.stopPropagation()
|
|
15
|
+
if (this.hasPanelTarget) {
|
|
16
|
+
const isNowVisible = !this.panelTarget.classList.toggle("hidden")
|
|
17
|
+
if (isNowVisible) {
|
|
18
|
+
document.addEventListener("click", this._onDocClick)
|
|
19
|
+
this._onKey = (e) => { if (e.key === "Escape") this._close() }
|
|
20
|
+
document.addEventListener("keydown", this._onKey)
|
|
21
|
+
} else {
|
|
22
|
+
this._unbind()
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_close() {
|
|
28
|
+
if (this.hasPanelTarget) this.panelTarget.classList.add("hidden")
|
|
29
|
+
this._unbind()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_unbind() {
|
|
33
|
+
document.removeEventListener("click", this._onDocClick)
|
|
34
|
+
if (this._onKey) {
|
|
35
|
+
document.removeEventListener("keydown", this._onKey)
|
|
36
|
+
this._onKey = null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_onDocClick(event) {
|
|
41
|
+
if (!this.element.contains(event.target)) this._close()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Connects to data-controller="table-header"
|
|
4
|
+
// Routes column-header clicks: shift-click navigates to multi-href instead of href,
|
|
5
|
+
// adding the column to the existing sort stack (multi-sort).
|
|
6
|
+
// Plain click lets the default link navigation happen, which replaces all sorts.
|
|
7
|
+
export default class extends Controller {
|
|
8
|
+
headerClick(event) {
|
|
9
|
+
if (!event.shiftKey) return // plain click: let the link navigate normally
|
|
10
|
+
const link = event.currentTarget
|
|
11
|
+
const multiHref = link.dataset.tableHeaderMultiHref
|
|
12
|
+
if (!multiHref) return
|
|
13
|
+
event.preventDefault()
|
|
14
|
+
Turbo.visit(multiHref)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
// Connects to data-controller="view-switcher"
|
|
4
|
+
// Persists the user's chosen index view in a cookie so the server can
|
|
5
|
+
// render the right shape on next request. Reload after writing so the
|
|
6
|
+
// page comes back with everything (toolbar, filters, table/grid)
|
|
7
|
+
// matching the new view.
|
|
8
|
+
export default class extends Controller {
|
|
9
|
+
static values = { cookieName: String, cookiePath: { type: String, default: "/" } }
|
|
10
|
+
|
|
11
|
+
select(event) {
|
|
12
|
+
const view = event.params.view
|
|
13
|
+
if (!view || !this.cookieNameValue) return
|
|
14
|
+
|
|
15
|
+
// 1 year, scoped to the portal's mount path so different portals
|
|
16
|
+
// can hold different view preferences for the same resource.
|
|
17
|
+
// SameSite=Lax keeps it on top-level navigations but blocks
|
|
18
|
+
// cross-site requests from carrying it along.
|
|
19
|
+
const maxAge = 60 * 60 * 24 * 365
|
|
20
|
+
const path = this.cookiePathValue || "/"
|
|
21
|
+
document.cookie = `${this.cookieNameValue}=${encodeURIComponent(view)}; Path=${path}; Max-Age=${maxAge}; SameSite=Lax`
|
|
22
|
+
|
|
23
|
+
// Strip any legacy `?view=` param so the cookie is the source of
|
|
24
|
+
// truth from now on.
|
|
25
|
+
const url = new URL(window.location.href)
|
|
26
|
+
url.searchParams.delete("view")
|
|
27
|
+
window.location.href = url.toString()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -6,3 +6,36 @@ Turbo.StreamActions.redirect = function () {
|
|
|
6
6
|
const url = this.getAttribute("url")
|
|
7
7
|
Turbo.visit(url)
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
// Closes the <dialog> rendered inside the targeted turbo-frame and
|
|
11
|
+
// empties the frame so the dialog can be re-opened later. Used by the
|
|
12
|
+
// stacked-modal flow: after a successful create inside the secondary
|
|
13
|
+
// modal, the server tells the browser to dismiss it.
|
|
14
|
+
Turbo.StreamActions.close_frame = function () {
|
|
15
|
+
const frameId = this.getAttribute("target")
|
|
16
|
+
if (!frameId) return
|
|
17
|
+
|
|
18
|
+
const frame = document.getElementById(frameId)
|
|
19
|
+
if (!frame) return
|
|
20
|
+
|
|
21
|
+
const dialog = frame.querySelector("dialog")
|
|
22
|
+
if (dialog && typeof dialog.close === "function") dialog.close()
|
|
23
|
+
|
|
24
|
+
// Clearing the frame's content keeps a future visit to the same URL
|
|
25
|
+
// re-fetching (turbo would otherwise treat the frame as cached).
|
|
26
|
+
frame.innerHTML = ""
|
|
27
|
+
frame.removeAttribute("src")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Reloads the targeted turbo-frame from its current src. Used after a
|
|
31
|
+
// secondary-modal action mutates data the primary modal depends on
|
|
32
|
+
// (e.g. a newly created association option) so the primary re-renders.
|
|
33
|
+
Turbo.StreamActions.reload_frame = function () {
|
|
34
|
+
const frameId = this.getAttribute("target")
|
|
35
|
+
if (!frameId) return
|
|
36
|
+
|
|
37
|
+
const frame = document.getElementById(frameId)
|
|
38
|
+
if (!frame || typeof frame.reload !== "function") return
|
|
39
|
+
|
|
40
|
+
frame.reload()
|
|
41
|
+
}
|