SOR Config 01 - Source mapping editor

v0.1.1

Maps a record to an external source: which connection to read, which fields identify and date it, and which source status values roll up into which outcome. Fully generic over the field and category keys the caller defines.

View as Markdown

Preview

Open full page ↗

Install & usage

npx shadcn@4.1.2 add @signalos/sor-config-01

Pulls the page source plus its widget dependencies (@signalos/tokens, @signalos/utils, @signalos/button, @signalos/input, @signalos/skeleton, @signalos/combobox, @signalos/confirm-dialog, @signalos/data-primitives, @signalos/page-header, @signalos/status-badge, @signalos/text-field) into your app - you own the copy. Requires access.

usage
// after: npx shadcn@4.1.2 add @signalos/sor-config-01
// mount the pulled page in a route, e.g. src/app/sor-config/page.tsx
import { SorConfig01 } from "@/components/blocks/sor-config-01/SorConfig01"

export default function Page() {
  return <SorConfig01 />
}

Props

SorConfig01LinkProps

PropTypeDefaultDescription
href*string-
classNamestring | undefined-
children*ReactNode-

ConnectionLike

PropTypeDefaultDescription
id*string-
name*string-

SorConfig01Check

PropTypeDefaultDescription
message*ReactNode-

SorConfig01FieldSpec

PropTypeDefaultDescription
key*TFieldKey-
label*string-
placeholderstring | undefined-
requiredboolean | undefinedfalse
helperReactNode-

SorConfig01CategorySpec

PropTypeDefaultDescription
key*TCategoryKey-
label*ReactNode-Display label, e.g. "Resolved".
reward*ReactNode-Score or weight shown beside the label, e.g. "+1.0".
tone"neutral" | "positive" | "negative" | "partial" | undefined"neutral"
placeholderstring | undefined-

SorConfig01Diff

PropTypeDefaultDescription
field*string-
label*string-
draftValue*string-
proposedValue*string-

SorConfig01ApiError

PropTypeDefaultDescription
kind*"outage" | "refused" | "absent" | "unknown"-`outage` - the source could not be reached, offers a retry. `refused` - the source was reached and rejected the request. `absent` - the requested record does not exist. `unknown` - anything else.
detail*ReactNode-

SorConfig01SaveOutcome

PropTypeDefaultDescription
ok*boolean-
droppedFieldLabels*string[]-Field labels that did not round-trip when `ok` is false.

SorConfig01Props

PropTypeDefaultDescription
recordName*ReactNode-Name of the record this mapping belongs to, e.g. a pipeline name.
isMappedboolean | undefinedfalse
savedCaptionReactNode-Pre-formatted "Last saved …" caption; omit to hide.
backHref*string-
backLabelReactNode-
LinkComponentComponentType<SorConfig01LinkProps> | undefined-Router link renderer for the back link; a plain `<a>` by default.
connections*ConnectionLike[]-
connectionId*string-
onConnectionChange*(id: string) => void-
isConnectionMissingboolean | undefinedfalse
connectionSearchPlaceholderstring | undefined-
onPropose*() => void-
isProposingboolean | undefinedfalse
canProposeboolean | undefinedfalse
proposeErrorSorConfig01ApiError | null | undefined-
isProposalWrongConnectionboolean | undefined-True once a proposal exists but points at a different connection than the form.
onClearFields(() => void) | undefined-
proposalSummaryReactNode-
isProposalUnverifiedboolean | undefinedfalse
proposalUnverifiedDetailReactNode-
isProposalBlockedboolean | undefinedfalse
proposalBlockedReasonReactNode-
proposalDiffSorConfig01Diff[] | undefined-
onUseProposal(() => void) | undefined-
fields*SorConfig01FieldSpec<TFieldKey>[]-
fieldValues*Record<TFieldKey, string>-
onFieldChange*(key: TFieldKey, value: string) => void-
fieldErrorsPartial<Record<TFieldKey, ReactNode>> | undefined-
fieldSuggestionsPartial<Record<TFieldKey, string[]>> | undefined-Catalog-derived value suggestions per field, keyed by field key.
multiValueFieldKeysTFieldKey[] | undefined-Field keys whose value is a comma-separated list, e.g. free-text search fields.
categories*SorConfig01CategorySpec<TCategoryKey>[]-
categoryValues*Record<TCategoryKey, string>-
onCategoryChange*(key: TCategoryKey, value: string) => void-
inFlightValuesByCategoryPartial<Record<TCategoryKey, string[]>> | undefined-Values that look like they mean "in progress", shown as a warning per category.
observedValuesstring[] | undefined-Every value actually observed in a sample of source records.
observedValuesCaptionReactNode-
blockingChecksSorConfig01Check[] | undefined-Local, blocking checks - shown once `onSave` has been attempted.
verifyBlockingChecksSorConfig01Check[] | undefined-Checks a verification pass ran against real records refused.
isVerifyUnverifiedboolean | undefinedfalse
verifyUnverifiedDetailReactNode-
warningChecksSorConfig01Check[] | undefined-
warningsCaptionReactNode-
unsavedFieldLabelsstring[] | undefined-Coordinates the draft has changed but not yet saved.
onSave*() => void-
isSavingboolean | undefinedfalse
isVerifyingboolean | undefinedfalse
canSaveboolean | undefinedtrue
saveErrorSorConfig01ApiError | null | undefined-
verifyErrorSorConfig01ApiError | null | undefined-
saveOutcomeSorConfig01SaveOutcome | null | undefined-
savedDetectorCountnumber | undefined-
onReset*() => void-
canResetboolean | undefinedfalse
resetLabelReactNode-
onRemove(() => void) | undefined-
isRemovingboolean | undefinedfalse
removeErrorSorConfig01ApiError | null | undefined-
removeConfirmDescriptionReactNode-
removeConfirmLabelReactNode-
isLoadingboolean | undefinedfalse
loadErrorSorConfig01ApiError | null | undefined-
classNamestring | undefined-
data-testidstring | undefined-Test identifier rendered as `data-testid` on the root element.

Changelog

sor-config-01

0.1.1

  • Initial release: a source-mapping editor page - connection picker, propose flow with a field-by-field diff against the current draft, generic field and status/category mapping cards, save/reset/remove actions, and every check and async state as a prop. Fully controlled: the caller owns the draft, the checks, and the field/category vocabulary via generic TFieldKey/TCategoryKey type parameters - no fetching, no domain types.