Hooks
Use them anywhere inside <Workflow>. All from @clipless/react.
useWorkflowState()
ts
{
answers, // current answers, as this viewer may read them
status, // 'draft' | 'in_progress' | 'waiting_action' | 'completed'
currentStage, // the active stage (manifest), or null
currentStep,
visibleSteps, // steps of the current stage that pass showIf
lockedStages, // ids of submitted stages
isComplete,
isStageReadOnly, // the viewer cannot edit the active stage
isSubmitting,
manifest,
}useWorkflowNav()
For your stepper and buttons.
ts
{ steps, currentStep, goToStep(name), next(), prev(), canGoNext, isSubmitting }next() goes to the next step, and on the last one submits the stage. canGoNext is false while the current step is invalid, the viewer does not own the stage, or an action is pending.
useField(name?)
Inside a <Field>, with no argument, the enclosing field; otherwise the one named.
ts
{ name, value, setValue(v), onChange(eventOrValue), onBlur(), error, touched,
required, disabled, isReadOnly, bindings }bindings is { name, value, onChange, onBlur, disabled, 'aria-invalid' } — spread it on an input. Errors show once a field is touched or its stage was submitted.
useFiles(name?)
A file field's files — see File uploads.
ts
{ files: [{ pid, name, type, size, sha256 }], upload(fileList), remove(pid), url(pid),
uploading, error, disabled }upload resolves to the error or null; url gives a short-lived link.
useFieldGroup(name, limits?)
ts
{ items: [{ id, index, invalid }], add(), remove(id), canAdd, canRemove, path }add() returns the new item's id, so you can open it for editing while the others show as previews. invalid is true while one of the item's fields has an error, so a collapsed item can still be flagged.
useFieldMeta(name)
ts
{ lastEditedBy, lastEditedAt }Who last changed a field and when, from the ledger.
useRemarks(name)
ts
{ field, remarks: [{ text, by, at, stage, audience }], canAdd, audience, add(text) }The remarks on a field that this viewer can read, oldest first. canAdd is true while the viewer owns the active stage and that stage declares <Remarks> on the field. audience lists who besides the author reads a remark (null: whoever can read the field). What <Remarks> renders by default is built on this hook.
useAction(id)
ts
{ status, result, error, download, run, stale }status is idle → running → done | failed, or waiting for an action that finishes later — then result is what it published meanwhile (a verification url). download() fetches the document a pdf action produced. For a field action, run() asks for it now, retrying a failure on the same value (null when the viewer may not), and stale is true while the last result belongs to an earlier value of the field.
useStages()
Every stage of the workflow, for a progress bar or a handoff notice ("with the underwriter").
ts
[{ id, label, actor, mine, status, conditional, answers }]status is done, processing (submitted, actions running), active, upcoming or skipped. answers holds only what the viewer may read. A role's bundle ships only its own stages; this is how it knows the rest.
useRounds()
The session's history, one entry per entry into a stage — see Loop-backs and rounds.
ts
[{ stage, label, actor, mine, round, status, answers }]useCarriedChanges()
For a run started from an earlier one — see Recurring workflows.
ts
{ from, changes: [{ field, before, after }] }from is null when nothing was carried.
Helpers
carryAnswers(manifest, { manifest, answers, erased? })— what of an earlier run a new one starts with, and what was dropped and why.carriedChanges(events, answers)— the pure function behinduseCarriedChanges.fileProblem(field, file),acceptsFile(accept, name, type),formatBytes(n)— the file rules the engine applies, to check before uploading.extractWorkflowManifest(id, version, children)— the manifest from a JSX tree (the CLI uses it).