Run estimate

Pro

What a run is likely to take before it starts: cost, time and (when it makes them) API calls, as ranges with what they're based on. If the high end would go past what's left of an API allowance, that's said before you start. Without enough history it says there's no estimate rather than guessing a number.

Markdown

Preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/run-estimate

Brings in: button, locale, locked, scale, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import { RunEstimate } from "@/components/run-estimate"

export default function Example() {
  return (
    <div className="grid max-w-3xl gap-4 md:grid-cols-2">
      <RunEstimate
        title="Backfill region on 18,240 projects"
        estimate={{ kind: "estimated", cost: { low: 0.4, high: 1.1 }, time: { low: 180, high: 420 }, apiCalls: { low: 9_000, high: 21_000 }, basis: "23 similar backfills on Staging in the last 30 days" }}
        apiRemaining={13_600}
        apiLabel="Database writes"
        onStart={() => {}}
        onCancel={() => {}}
      />
      <RunEstimate title="Audit the invoices constraints" estimate={{ kind: "unknown", reason: "fewer than 5 runs like this one have finished." }} onStart={() => {}} onCancel={() => {}} />
    </div>
  )
}

<RunEstimate>

PropTypeDefaultDescription
titlerequiredstring—What the run will do, as a heading.
estimaterequiredEstimate—Cost, time and API-call ranges with what they're based on, or unknown with the reason.
apiRemainingnumber | undefined—Calls left today against the API's allowance, when known.
apiLabelstring | undefined—What the calls are, e.g. "CRM API calls". Defaults to "API calls".
onStart(() => void) | undefined—Shows a Start button; called when it's clicked.
onCancel(() => void) | undefined—Shows a Cancel button; called when it's clicked.
startLockedstring | undefined—Why Start can't be used yet. Without one, Start is enabled.
classNamestring | undefined—Extra classes for the outer element.

Strings

The fixed words, in English by default. Change any of them under runEstimate in <LocaleProvider strings={{ … }}>; the table is exported as runEstimateStrings.

KeyEnglish
apiCallsAPI calls
estimateForEstimate for {title}
beforeItStartsBefore it starts
noEstimateNo estimate yet: {reason}
modelCostModel cost
timeTime
basedOnBased on {basis}.
overAllowanceAt the high end this uses more {apiLabel} than the {remaining} left today, which other integrations share.
notNowNot now
startRunStart run

Types

Range
{ low: number; high: number }
Estimate
| { kind: "estimated" cost: Range /** The cost range as your server wrote it ("about $0.40 to $0.90"), shown instead of `cost` formatted. */ costText?: string | undefined /** Seconds. */ time: Range /** Calls against a rate-limited API, when the run makes them. */ apiCalls?: Range | undefined /** What it's based on, e.g. "23 similar runs in the last 30 days". */ basis: string } /** Too little hist