app/components/admin/media-bulk-bar.tsx
69 lines and 11 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| BulkBar | 11 to 72 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:32> | 32 to 32 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:33> | 33 to 33 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:42> | 42 to 52 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:44> | 44 to 44 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:45> | 45 to 45 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:48> | 48 to 49 | 2 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:51> | 51 to 51 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:56> | 56 to 56 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:58> | 58 to 58 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:66> | 66 to 66 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
Imports
It imports app/components/admin/bulk-tag-controls.tsx, app/components/admin/toast.tsx, app/lib/clipboard.ts, app/lib/media/byte-size.mjs. Imported by app/components/admin/media-grid.tsx.
Source
import { BulkTagControls } from "~/components/admin/bulk-tag-controls";
import { toast } from "~/components/admin/toast";
import { copyText } from "~/lib/clipboard";
import { byteSize } from "~/lib/media/byte-size.mjs";
import type { Route } from "../../routes/+types/admin.media._index";
type Listing = Extract<Route.ComponentProps["loaderData"], { detail: unknown }>;
/** The bar over a selection: count and size, copy addresses, bulk tags, trash, clear. */
export function BulkBar({
objects,
chosen,
setSelected,
setConfirmingTrash,
tagCounts,
}: {
objects: Listing["objects"];
chosen: string[];
setSelected: (keys: string[]) => void;
setConfirmingTrash: (value: boolean) => void;
tagCounts: Listing["tagCounts"];
}) {
return (
<div className="cap-bulk" role="group" aria-label="Bulk actions">
{/* Not a live region: it mounts with its number, and the grid's own status region announces it. */}
<p className="cap-bulk-count">
{chosen.length} selected{" "}
<span className="cap-bulk-detail">
{byteSize(
objects
.filter((o) => chosen.includes(o.key))
.reduce((sum, o) => sum + o.size, 0),
)}
</span>
</p>
<div className="cap-bulk-actions">
{/* `type="button"` so it never submits the form it sits in. One address per line: that pastes usefully. */}
<button
type="button"
className="cap-btn"
onClick={() => {
const addresses = objects
.filter((o) => chosen.includes(o.key))
.map((o) => o.url)
.join("\n");
copyText(addresses)
.then(() =>
toast(`Copied ${chosen.length} address${chosen.length === 1 ? "" : "es"}`),
)
.catch(() => toast("The clipboard refused. Open a file to copy its address."));
}}
>
Copy addresses
</button>
<BulkTagControls listId="media-bulk-tags" options={tagCounts.map((t) => t.tag)} />
{/* A `type="button"` opens the modal, because submitting from here would skip it. */}
<button type="button" className="cap-btn" onClick={() => setConfirmingTrash(true)}>
Move to trash
</button>
</div>
<button
type="button"
className="cap-btn cap-bulk-clear"
data-variant="quiet"
onClick={() => setSelected([])}
>
Clear
</button>
</div>
);
}