Multi-select picker for design output sizes with a filter chip bar for Recommended / My File Sizes / My Kits / All. Fetches from a Supabase-backed API route scoped to the given account. The All tab paginates upstream 60 rows at a time and forwards the search box to the API's `query` param so it scales to thousands of rows without loading the whole catalog. Optionally narrow the catalog to a `department` (`design` | `video` | `social` | `web` | `brand`) and/or a list of `projectType` IDs. Selections snapshot the full file-size metadata (dims, fold type, bleed) and folded print sizes annotate their dimensions as unfolded with a bleed badge. Pass `kits` to surface named bundles as expandable Kit cards above the individual sizes on the Recommended tab — "Add kit" selects every member size at once.
[]npx shadcn add https://raw.githubusercontent.com/sis-thesqd/squad-sdk/main/public/r/file-size-picker-block.json## Setup
1. Set the following environment variable in your `.env.local`:
- `SQUAD_API_KEY` — your Squad API key (server-only). Used to call `https://api.thesqd.com/v1/prf/file-sizes`. Generate one at [sdk.thesqd.com/settings/api-keys](https://sdk.thesqd.com/settings/api-keys) (employees only).
2. The CLI install drops three Next.js route handlers under `app/api/file-sizes/` that proxy the Squad API with `Authorization: Bearer ${SQUAD_API_KEY}`:
| File | Method | Squad API endpoint | Purpose |
|------|--------|---------------------|---------|
| `route.ts` | `GET` | `GET /v1/prf/file-sizes` | List rows. Forwards `account`, `department`, repeating `project_type`, `query`, `recommended`, `list_defaults`, `limit`, and `offset` upstream; returns `{ rows, total }`. Rows include `foldType` (`tri-fold` / `bi-fold` / `no-fold` / `custom`) and `bleedSize` (`0.125` / `0.25`) when set upstream. The block uses `limit=60` + `offset` for the All tab, `recommended=true` for the Recommended tab, `list_defaults=false` for My File Sizes, and a single un-paginated catalog fetch for Kits. |
| `route.ts` | `POST` | `POST /v1/prf/file-sizes` | Create a new file size. The block sends `account: <currentAccount>` so the row is owned, not global. |
| `[id]/route.ts` | `PATCH` | `PATCH /v1/prf/file-sizes/{id}` | Edit an account-owned row. |
| `[id]/visibility/route.ts` | `PATCH` | `PATCH /v1/prf/file-sizes/{id}/visibility` | Hide a row for the current account (the soft-delete — Squad API has no DELETE). |
3. **Editing a global row** (`account === null`) is special: the block POSTs a new account-owned copy with the user's edits applied instead of mutating the global. That keeps the global record intact for everyone else while still feeling like an in-place edit to the user.import { FileSizePicker, type FileSize, type FileSizeKit, type FileSizeSelection } from "@/components/blocks/file-size-picker-block";"use client";
import * as React from "react";
import {
FileSizePicker,
type FileSizeSelection,
} from "@/components/blocks/file-size-picker-block";
export default function Page() {
// `account` scopes the picker to the customer's own file sizes.
// Pass `readOnly` to skip mutating fetches (useful in docs/demos).
// Pass `value` + `onChange` to control selection externally; omit both
// to let the picker manage its own selection state.
//
// Use `department` ("design" | "video" | "social" | "web" | "brand")
// and/or `projectType` (integer[]) to narrow the catalog to file sizes
// linked to those project types upstream.
//
// Each selection snapshots the full file-size metadata at selection time
// (`{ id, label, width, height, unit, foldType, bleedSize, ... }`) so
// downstream consumers (review pages, submissions, cross-field logic)
// can render and branch on it without re-fetching the catalog.
//
// In a dynamic form, gate the initial fetches on the form's prefetch
// flag via `scopeReady` (defaults to true for standalone usage).
const [selected, setSelected] = React.useState<FileSizeSelection[]>([]);
return (
<FileSizePicker
account={3728}
department="design"
projectType={[1, 7]}
value={selected}
onChange={setSelected}
/>
);
}[]Nothing matches this view yet. Try another tab or search, or create a new file size.
Nothing matches this view yet. Try another tab or search, or create a new file size.
[]Nothing matches this view yet. Try another tab or search, or create a new file size.