# Results notebook

A React block (a whole screen) in [Beamline](https://beamline.io/)'s [Clinic](https://beamline.io/components/apps/clinic) app. Live demo: https://beamline.io/components/results-notebook

A notebook entry's structured results. The entry's text above a bounded results table with typed columns: a sample link, numbers in their unit with their range, text, and linked columns read from the sample (never edited here, a missing link said). A value typed wrong keeps its typing and blocks Submit in its cell, counted below; Submit sends the table's draft rows apart from the entry's text, locks them with their result ids, and a refused submit keeps them. Rows arrive by scanning or pasting barcodes (found, unknown, already in the table and not yours said apart; only found ones added), from another table (the destination and source columns, an incompatible pair said, a source that can't be read said, rows appended carrying where they came from) or by hand. A linked column is added through a sample column with a preview. Linked values that changed at the source are marked in their cells; Refresh previews how many change and which edited rows keep their entries, and a failed refresh changes nothing. The entry's plates register into inventory (barcode, location, project), the record kept apart from the live item, a change to the live item since said. With the plot prop the results are drawn beside the entry's text as they're typed: one line per linked sample through two number columns (x on a log scale when asked), named at its end, with an optional dashed guide; a value that isn't a number yet is left out. Cells read as values at rest; a cell's field shows when pointed at, typed in or wrong.

## Use it for

- Scientists recording structured results inside an experiment entry: samples scanned or pulled from a plan, measurements typed with their units, values read from linked samples, then submitted.
- Any record where a typed table sits inside a narrative and is submitted on its own (inspection reports, QA logs).

## Not for

- A large data grid to browse ([data-grid](https://beamline.io/components/data-grid)).
- Laying samples out on a plate (signature work).
- Stock and lots ([production-lots](https://beamline.io/components/production-lots)).

## Anatomy

- entry: title and text
- results block: name and schema version with the draft count; Scan or paste barcodes, Add from a table, Add a linked column
- stale bar: how many linked values changed, Refresh linked values, its preview (count, edited rows that stay), Refresh / Cancel, a failure
- table: row number, sample, number cells with unit and their problem, text, linked cells (outdated badge, No link), a submitted check or Remove
- foot: Add a row, the state (values to fix, results submitted, or that the text stays a draft), Submit results
- scan dialog: the barcodes field, each code with what it resolved to, Preview / Add n samples
- from-table dialog: into column, source table, source column, the incompatibility or how many rows append
- lookup dialog: through, show (relation → attribute), the preview per sample, Add column
- plates: each plate (recorded, wells, live change) with In inventory as … or Register in inventory; its dialog (barcode, location, project)

## States

- empty grid
- draft rows
- invalid value
- out of range
- submitting
- submitted
- submission refused
- waiting for input
- resolving
- matched
- unknown barcode
- duplicate
- not accessible
- ready
- source selection
- incompatible column
- mapping ready
- populated draft
- source unavailable
- no compatible column
- attribute selection
- preview
- linked values
- unresolved relation
- current
- outdated
- local edits
- refresh preview
- refreshing
- refresh failed
- snapshot only
- registration pending
- registered
- live item changed
- registration refused

## Keyboard

- Tab through the toolbar, then each editable cell in row order
- in the scan field, Enter resolves what was typed or pasted (Shift+Enter adds a line)
- dialogs trap focus; Escape closes them

## Motion

None beyond the parts' own; nothing moves at rest.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `entry` (required) | `{ title: string; body: ReactNode; }` | — | The entry's prose, shown above the table (read here; edited in your editor). |
| `table` | `ResultTableState` | — |  |
| `defaultTable` | `ResultTableState` | — |  |
| `onTableChange` | `((t: ResultTableState) => void)` | — |  |
| `onResolveBarcodes` | `((codes: string[]) => Promise<BarcodeMatch[]>)` | — | Resolves scanned or pasted barcodes; order follows the input. |
| `sources` | `SourceTable[]` | — | Tables rows can be added from. |
| `lookupPaths` | `LookupPath[]` | — | Relations a linked column can read through, with their attributes. |
| `onLookup` | `((q: { through: string; path: string; attribute: string; }, rows: ResultRow[]) => Promi…` | — | Reads an attribute for each row's linked sample: values by row id (null: no link). |
| `onRefreshLinked` | `(() => void \| Promise<unknown>)` | — | Confirms the refresh of outdated linked values at the source; reject with why to change nothing. |
| `onSubmit` | `((rows: ResultRow[]) => Promise<Record<string, string>>)` | — | Submits the table's draft rows: result ids by row id; reject with why to keep them as drafts. |
| `plot` | `{ title, x, y, series, xLog?, guide?: { at, label } }` | — | A live chart of the results (two number columns, one line per linked sample), beside the entry's text. |
| `plates` | `PlateRecord[]` | — |  |
| `onRegisterPlate` | `((plateId: string, details: { barcode: string; location: string; project: string; }) =>…` | — | Registers a recorded plate in inventory; resolve with its inventory id, reject with why. |
| `locations` | `string[]` | — |  |
| `projects` | `string[]` | — |  |
| `className` | `string` | — | Classes on the documented visual root; no override by default. |
| `style` | `CSSProperties` | — | Inline styles on the documented visual root; no overrides by default. |
| `ref` | `Ref<HTMLDivElement>` | — | Receives the documented native target or imperative handle; omitted by default. |

## Built from

- input
- select
- textarea
- dialog
- badge
- button
- alert

## Dependencies

`lucide-react`

## Import

```tsx
import { ResultsNotebook } from "@beamline/results-notebook";
```

## Get it

Results notebook is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in Clinic

- [Appointment book](https://beamline.io/components/appointment-book): The desk's day with the appointment editor beside it. The appointment being edited is a block on the day like any other, drawn in the accent while it is…
- [Book an appointment](https://beamline.io/components/client-booking): A client books an appointment on the practice's own site: a service (length and price beside it), who gives it or anyone free, and where; a day with…
- [Services and hours](https://beamline.io/components/booking-setup): A practice's services and the hours its practitioners can be booked, one relation seen from both ends. A service reads as values and changes on demand…
- [Patient overview](https://beamline.io/components/patient-overview): One patient's record on a page. A search finds patients by name, chart number or birth date (recent patients when empty; same names told apart by birth…
- [Patient chart](https://beamline.io/components/patient-chart): A clinic's chart for one client and their animals. The client's header (phone, email, contact preferences, the balance with what it means and as of when…
- [Health questionnaire](https://beamline.io/components/health-questionnaire): A patient's medical history as a versioned questionnaire. Every question takes Yes, No or I don't know, and one not answered says so, never read as No; a…
- [Case workspace](https://beamline.io/components/case-workspace): A patient's clinical cases and how cases work at the practice. A case shows its status, type, teeth, staff, location and start; its checklist counts…
- [Care plan](https://beamline.io/components/care-plan): A client's care plan composed beside what the client will see of it. Every field says who sees it (the care team only, or the client too) and the…
- [Treatment plan](https://beamline.io/components/treatment-plan): A patient's treatment plan in named phases. Each procedure shows its tooth, status and fee beside the patient's and the insurer's estimate (not known…
- [Plan templates](https://beamline.io/components/plan-templates): Reusable treatment-plan templates. A template reads as words at rest and changes on demand: its name edits in place; the status its procedures start as…
- [Plan acceptance](https://beamline.io/components/plan-acceptance): A treatment plan presented for acceptance, from both sides. The practice chooses the agreement (the account's default or this location's own) and how…
- [Plan follow-up](https://beamline.io/components/plan-follow-up): The practice's follow-up lists, for the person who turns accepted treatment into booked chairs. Treatment plans lead with what's at stake: the value…
- [Session notes and tasks](https://beamline.io/components/session-notes): A session's note beside its follow-up tasks, each task tied to the exact words it came from: choose a task and its words light in the note or the…
- [Note templates](https://beamline.io/components/note-templates): A practitioner's note templates in one library with three ways in. My templates lists their own by kind, favourites first, each with when it was last…
- [Probing chart](https://beamline.io/components/probing-chart): A periodontal probing chart. Six sites per tooth (three buccal, three lingual) across both arches as you face the patient, each depth in its cell and…
- [Procedure picker](https://beamline.io/components/procedure-picker): Procedures, conditions and bundles put on a patient's teeth from the chair. The mode (existing, planned, completed) is chosen before adding and each…
- [Insurance claims](https://beamline.io/components/claims-queue): Insurance claims as a queue: every claim at first, in the order a person works them (rejected by the clearinghouse, denied by the payer, partly paid, not…
- [Account ledger](https://beamline.io/components/account-ledger): A patient's account. All transactions or the ones needing attention, each dated with its type in a word, its amount and the running balance; entries that…
- [Dispensing](https://beamline.io/components/dispensing): Dispensing from the shelf by lot. A product is found with its stock and prices (consumables left out unless asked); the quantity is drawn across its…
- [Record sharing](https://beamline.io/components/record-sharing): Records sent out of a clinic. Several visits' records and their documents (record, invoice, plan, lab result, image) are chosen separately, with how much…
- [Client journal](https://beamline.io/components/client-journal): A client's journal from both ends. The client's side is their home, built around their day: today's goals with how many are done and a mark each, done…

Part of [Beamline UI: polished, editable React components and complete screens for custom applications](https://beamline.io/). [Build your own style from any look; tokens, fonts, radii, motion; not only colours](https://beamline.io/docs/customize).
