KQ-1685 · EXPORT/RECIPE
Export Recipe
An export dialog that shows the file before it exists: beside the recipe of format cards, range chips and column checkboxes sits a document glyph whose twelve marks morph from one format's layout to the next on springs.glide (comma rows, a grid, indented keys, column stripes) while its tab rolls the extension letter by letter and the size estimate and row count roll their digits on springs.snap. Large estimates glide open delivery by email; exporting folds the recipe away as the glyph fills with the host's progress and three stages tick on springs.flick, a ready file lands a check on recoil with Download, and a failure keeps every choice. Format, range and delivery are native radio groups, and the column checkboxes follow the arrow keys too.
Export readings
Gaugeworks readings · Harbour line, 60 sensors
csv · 7 days · 8 columns
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/export-recipe
Props
- formats
- ExportFormat[]
- default defaultExportFormats
- The formats offered: { id, label, ext, note, layout, factor, keyed?, gzipFactor?, header?, maxRows? }; the defaults are CSV, Spreadsheet (xlsx), JSON and a packed Columnar format.
- columns
- ExportColumn[]
- default defaultExportColumns
- The table's columns: { id, label, bytes, required? }; required ones stay checked.
- ranges
- ExportRange[]
- default defaultExportRanges
- The ranges offered, each with its row count: { id, label, rows }.
- format / defaultFormat
- string
- default — / "csv"
- The format id, controlled or initial.
- onFormatChange
- (format: string) => void
- default —
- Fires from the radio that changed the format.
- selectedColumns / defaultColumns
- string[]
- default — / every column
- The column ids, controlled or initial.
- onColumnsChange
- (columns: string[]) => void
- default —
- Fires from the checkbox that changed the columns.
- range / defaultRange
- string
- default — / "7d"
- The range id, controlled or initial.
- onRangeChange
- (range: string) => void
- default —
- Fires from the radio that changed the range.
- emailThreshold
- number
- default 200_000_000
- Estimates over this many bytes offer delivery by email and choose it.
- string
- default "ops@gaugeworks.example"
- Where an emailed export goes.
- onExport
- (recipe, report, signal) => Promise<ExportFile | void>
- default simulated
- Runs the export: report(0–1, stage?) as it goes; resolve with { name, bytes, url? } or reject with the reason; the AbortSignal fires on Cancel.
- onCancel
- (during: "recipe" | "export") => void
- default —
- Cancel on the recipe (close the dialog) or during an export (it stops and the recipe comes back intact).
- onDownload
- (file: ExportFile) => void
- default —
- Download was pressed on the ready file.
- onClose
- () => void
- default —
- Done was pressed after an emailed export.
- glyphStyle
- "paper" | "outline" | "solid"
- default "paper"
- The file glyph as a paper sheet with ink marks, a line drawing, or a solid block with the marks knocked out.
- density
- "compact" | "cozy" | "roomy"
- default "cozy"
- Option heights, card padding and the spacing between sections.
- accent
- string
- default "var(--accent-bright)"
- Chosen cards and chips, the glyph's header marks and the progress fill; filled parts take its hue at a fixed lightness.
- title
- string
- default "Export readings"
- The dialog's heading and accessible name.
- tableName
- string
- default "Gaugeworks readings · Harbour line, 60 sensors"
- The table being exported, under the heading; the part before a "·" also names the file (gaugeworks-readings-7d.csv).
- status
- "ready" | "loading" | "error"
- default "ready"
- Loading shows placeholder rows; error offers Try again.
- onReload
- () => void
- default —
- Try again was pressed after the table failed to load.
- modal
- boolean
- default false
- Trap Tab inside the dialog and set aria-modal.
- disabled
- boolean
- default false
- Every option and button is held.
- className
- string
- default —
- Classes for the dialog panel; it caps at max-h-[35rem] (its body scrolls and the file panel stays pinned), so pass another max-h-* to change that.
| Prop | Type | Default | Description |
|---|---|---|---|
| formats | ExportFormat[] | defaultExportFormats | The formats offered: { id, label, ext, note, layout, factor, keyed?, gzipFactor?, header?, maxRows? }; the defaults are CSV, Spreadsheet (xlsx), JSON and a packed Columnar format. |
| columns | ExportColumn[] | defaultExportColumns | The table's columns: { id, label, bytes, required? }; required ones stay checked. |
| ranges | ExportRange[] | defaultExportRanges | The ranges offered, each with its row count: { id, label, rows }. |
| format / defaultFormat | string | — / "csv" | The format id, controlled or initial. |
| onFormatChange | (format: string) => void | — | Fires from the radio that changed the format. |
| selectedColumns / defaultColumns | string[] | — / every column | The column ids, controlled or initial. |
| onColumnsChange | (columns: string[]) => void | — | Fires from the checkbox that changed the columns. |
| range / defaultRange | string | — / "7d" | The range id, controlled or initial. |
| onRangeChange | (range: string) => void | — | Fires from the radio that changed the range. |
| emailThreshold | number | 200_000_000 | Estimates over this many bytes offer delivery by email and choose it. |
| string | "ops@gaugeworks.example" | Where an emailed export goes. | |
| onExport | (recipe, report, signal) => Promise<ExportFile | void> | simulated | Runs the export: report(0–1, stage?) as it goes; resolve with { name, bytes, url? } or reject with the reason; the AbortSignal fires on Cancel. |
| onCancel | (during: "recipe" | "export") => void | — | Cancel on the recipe (close the dialog) or during an export (it stops and the recipe comes back intact). |
| onDownload | (file: ExportFile) => void | — | Download was pressed on the ready file. |
| onClose | () => void | — | Done was pressed after an emailed export. |
| glyphStyle | "paper" | "outline" | "solid" | "paper" | The file glyph as a paper sheet with ink marks, a line drawing, or a solid block with the marks knocked out. |
| density | "compact" | "cozy" | "roomy" | "cozy" | Option heights, card padding and the spacing between sections. |
| accent | string | "var(--accent-bright)" | Chosen cards and chips, the glyph's header marks and the progress fill; filled parts take its hue at a fixed lightness. |
| title | string | "Export readings" | The dialog's heading and accessible name. |
| tableName | string | "Gaugeworks readings · Harbour line, 60 sensors" | The table being exported, under the heading; the part before a "·" also names the file (gaugeworks-readings-7d.csv). |
| status | "ready" | "loading" | "error" | "ready" | Loading shows placeholder rows; error offers Try again. |
| onReload | () => void | — | Try again was pressed after the table failed to load. |
| modal | boolean | false | Trap Tab inside the dialog and set aria-modal. |
| disabled | boolean | false | Every option and button is held. |
| className | string | — | Classes for the dialog panel; it caps at max-h-[35rem] (its body scrolls and the file panel stays pinned), so pass another max-h-* to change that. |