LocalMode /ui
Local-First

Vector Export Panel

An export surface for vector data: per-format export actions, corpus counts, a busy state, and a last-export summary banner.

Vector Export Panel

The Vector Export Panel is the counterpart to the Vector Import Flow: a record/dimension count line, a row per export format (native JSON with vectors, CSV, JSONL — each with a label, description, and vectors-included / text-only indicator), per-format export actions emitting onExport(formatId), a busy state that disables all actions (with a spinner on the active format), a zero-records disabled state, and an optional last-export banner (format, records, human-readable size, filename).

Preview

Open in

Installation

pnpm dlx shadcn@latest add @localmode/ui/local-first/vector-export-panel
npx shadcn@latest add @localmode/ui/local-first/vector-export-panel
yarn dlx shadcn@latest add @localmode/ui/local-first/vector-export-panel
bunx --bun shadcn@latest add @localmode/ui/local-first/vector-export-panel

Data source & dependencies

Data source: renders the formats/counts/exporting/last-export state you pass and emits onExport(formatId) — works with any backend. Recommended producer: useImportExport (exportCSV, exportJSONL) from @localmode/react plus a native JSON export (on-device, optional).

  • lucide-react — icons
  • clsx + tailwind-merge — via the shared cn() util (installed automatically as a registry dependency)

Files installed

  • vector-export-panel.tsx — the VectorExportPanel component
  • lib/utils.ts — the cn() helper (if not already present)

Props

VectorExportPanel

Prop

Type

ExportFormat

Prop

Type

LastExportSummary

Prop

Type

Examples

Wiring to export functions

Works with any export backend — pass a busy format id while the export runs, then a summary when it completes:

const { exportCSV, exportJSONL } = useImportExport({ db });
const [exporting, setExporting] = useState<string | false>(false);
const [lastExport, setLastExport] = useState<LastExportSummary | null>(null);

const runExport = async (formatId: string) => {
  setExporting(formatId);
  try {
    const blob = formatId === 'csv' ? await exportCSV() : await exportJSONL();
    downloadBlob(blob, `vectors.${formatId}`);
    setLastExport({ formatId, records: count, bytes: blob.size, filename: `vectors.${formatId}` });
  } finally {
    setExporting(false);
  }
};

<VectorExportPanel
  formats={[
    { id: 'csv', label: 'CSV', vectors: false },
    { id: 'jsonl', label: 'JSONL', vectors: false },
  ]}
  recordCount={count}
  exporting={exporting}
  lastExport={lastExport}
  onExport={runExport}
/>

Disabling while other work runs

<VectorExportPanel formats={formats} recordCount={count} disabled={isImporting} onExport={runExport} />

Customization

exporting accepts true (disable everything) or a format id (also spin that format's action). The vectors-included / text-only indicator renders only when a format sets vectors; the zero-records note and disabled state kick in at recordCount === 0. The size in the last-export banner is formatted by the local formatBytes helper — edit its thresholds or units freely. Styled entirely with shadcn/ui CSS-variable utilities so it inherits your theme — because you own the copied file, every class and threshold is yours to change.

On this page