FillDoc
A page you can write on — headings, prose and sheets, on real A4.
A document, not a control. FillSheet is the table; this is the page it sits in. The two share a look on purpose — a real A4 sheet, real margins, square corners, and nothing drawn that is not content — and the same split between the person who makes a form and the person who fills it in.
Two modes, again
| mode | the prose | the sheets | the page |
|---|---|---|---|
edit | writable | fillable, resizable | blocks can be added and removed |
fill | plain text, not a control | fillable | fixed |
In fill a heading renders as an <h2> and a paragraph as a <p> — not as a disabled
textarea. A control sitting there that does nothing when clicked is worse than plain text.
Blocks
type FillDocBlock =
| { id: string; type: "heading"; text: string }
| { id: string; type: "text"; text: string }
| { id: string; type: "table"; columns: FillSheetColumn[]; value: string[][] }Every edit — typing, inserting, removing, filling a cell — comes back through
onBlocksChange as the whole document. A table block's cell edit carries the other blocks
through untouched, so the document is always one value you can store.
Nothing shows until you are there
A block draws no chrome at rest: no handle, no outline, no drag grip. The remove control appears in the margin beside the block the pointer is in, and the insert controls appear in the gap between two blocks. A page covered in controls stops looking like a page, which is the whole thing this is for.
Getting it out
import { docToHTML, docToMarkdown } from "@crisp-ui-kit/crisp";docToHTML gives an HTML document body — headings, paragraphs and real <table>s — which is
what Word, Google Docs and Pages read. A table block hands straight off to FillSheet's own
writer, so there is one implementation of table escaping rather than two that drift. Prose is
escaped, so a document cannot inject markup into its own export.
Installation
npm install @crisp-ui-kit/crispProps
Prop
Type