@ljoukov/sheet
v0.2.0
Published
Svelte components for paper-style worksheets, reviewed answer sheets, and question-level feedback threads.
Maintainers
Readme
@ljoukov/sheet

Paper-first Svelte components for rendering printable-style worksheets, reviewed answer sheets, rich tutor feedback cards, and reply threads.
Live gallery: sheet.ljoukov.workers.dev
What It Includes
Sheet: full worksheet renderer with interactive, readonly, review, and demo modesSheetFeedbackCard: question-level review note with optional reply flowSheetFeedbackThread: standalone tutor thread and composer surfaceMarkdown: shared markdown renderer with KaTeX maths and syntax highlighting- built-in question layouts for fill-in, multiple choice, lines, calculation, matching, and spelling prompts
- typed schemas, exported types, and seeded sample documents for local demos
Install
npm install @ljoukov/sheetImport the package stylesheet once so KaTeX and shared utility styles are available:
<script lang="ts">
import '@ljoukov/sheet/styles.css';
</script>Quick Start
<script lang="ts">
import '@ljoukov/sheet/styles.css';
import { Sheet, sampleSheets, type SheetAnswers } from '@ljoukov/sheet';
const sample = sampleSheets[0];
let answers: SheetAnswers = sample.seedAnswers ?? {};
</script>
<Sheet document={sample.document} mode="demo" mockReview={sample.mockReview} bind:answers />For live tutoring flows, pass review, feedbackThreads, feedbackState, and onReply into Sheet, or use SheetFeedbackCard and SheetFeedbackThread directly when you need those surfaces outside the full worksheet layout.
Surface Catalog
The sections below show the exported components and built-in Sheet surfaces, with the implementation file, what each surface is for, and the inputs it expects.
Sheet
Implements: Sheet
Description: Top-level worksheet surface with theme tokens, header, optional grading summary, hook/content sections, answer state, and optional tutor feedback.
Required inputs
documentdocument.iddocument.subjectdocument.leveldocument.titledocument.subtitledocument.colordocument.accentdocument.lightdocument.borderdocument.sections[]
Optional inputs
answersseedAnswersreviewmockReviewfeedbackThreadsfeedbackStatemodeallowRepliesshowFooterfooterLabelonAnswersChangeonReply
Grading summary
Rendered by Sheet, implementation in src/lib/components/sheet/paper-sheet.svelte
Description: Top-level review banner that communicates score, grading note, and whether some marks remain in teacher review.
Required inputs
review.score.gotreview.score.totalreview.labelreview.messagereview.notereview.questions
Optional inputs
review.objectiveQuestionCountreview.teacherReviewMarksreview.teacherReviewQuestionCount
Shown near the top of Sheet when review or mockReview is provided.
Feedback card
Implements: SheetFeedbackCard
Description: Per-question feedback surface that wraps a review note, optional conversation thread, and reply composer.
Required inputs
review
Optional inputs
opendraftthreadprocessingruntimeStatusthinkingTextassistantDraftTextshowComposershowFollowUpButtonresolvedFollowUpModedraftAttachmentsdraftAttachmentErrorallowAttachmentsallowTakePhotoquestionLabelonToggleonRequestFollowUponAttachFilesonRemoveDraftAttachmentonDraftChangeonReply
Feedback thread
Implements: SheetFeedbackThread
Description: Standalone tutor conversation and composer surface for embedding a feedback thread outside the full worksheet layout.
Required inputs
- none
Optional inputs
threaddraftprocessingruntimeStatusthinkingTextassistantDraftTextshowComposershowFollowUpButtonresolvedFollowUpModedraftAttachmentsdraftAttachmentErrorallowAttachmentsallowTakePhotoplaceholderquestionLabelonRequestFollowUponAttachFilesonRemoveDraftAttachmentonDraftChangeonReply
Markdown
Implements: Markdown
Description: Shared Markdown renderer with KaTeX maths, syntax-highlighted code blocks, inline rendering, and copy buttons for fenced code.
Required inputs
markdown
Optional inputs
inlineclass
Fill in the blanks
Rendered by Sheet, question layout in src/lib/components/sheet/paper-sheet.svelte
Description: Inline sentence-completion row with one or two blank fields for short factual recall and keyword retrieval.
Required inputs
question.idquestion.type = "fill"question.marksquestion.promptquestion.blanks[]question.after
Optional inputs
question.conjunctionblank.placeholderblank.minWidth
Answer payload: answers[question.id] = Record<"0" | "1", string>
Multiple choice
Rendered by Sheet, question layout in src/lib/components/sheet/paper-sheet.svelte
Description: Single-select question row with two or more markdown-capable options.
Required inputs
question.idquestion.type = "mcq"question.marksquestion.promptquestion.options[]
Optional inputs
- none
Answer payload: answers[question.id] = string
Lines / extended response
Rendered by Sheet, question layout in src/lib/components/sheet/paper-sheet.svelte
Description: Freeform longer-answer row for explanations, justifications, and worked reasoning.
Required inputs
question.idquestion.type = "lines"question.marksquestion.promptquestion.lines
Optional inputs
question.renderMode
Answer payload: answers[question.id] = string
Calculation row
Rendered by Sheet, question layout in src/lib/components/sheet/paper-sheet.svelte
Description: Compact numeric or symbolic answer row with a left label and a right-side unit.
Required inputs
question.idquestion.type = "calc"question.marksquestion.promptquestion.inputLabelquestion.unit
Optional inputs
question.hint
Answer payload: answers[question.id] = string
Match pairs
Rendered by Sheet, question layout in src/lib/components/sheet/paper-sheet.svelte
Description: Two-column matching interaction where the student connects each term to its paired meaning.
Required inputs
question.idquestion.type = "match"question.marksquestion.promptquestion.pairs[]
Optional inputs
- none
Answer payload: answers[question.id] = Record<string, string>
Spelling correction
Rendered by Sheet, question layout in src/lib/components/sheet/paper-sheet.svelte
Description: Correction list that presents a misspelled word and captures the repaired spelling inline.
Required inputs
question.idquestion.type = "spelling"question.marksquestion.promptquestion.words[]
Optional inputs
- none
Answer payload: answers[question.id] = Record<string, string>
Public API
import {
Markdown,
Sheet,
SheetFeedbackCard,
SheetFeedbackThread,
SheetAnswersSchema,
SheetDocumentSchema,
SheetFeedbackAttachmentSchema,
SheetFeedbackThreadSchema,
SheetFeedbackTurnSchema,
SheetReferencesSchema,
SheetReportSchema,
SheetReviewSchema,
sampleSheets,
type SheetAnswers,
type SheetDocument,
type SheetFeedbackState,
type SheetFeedbackStateMap,
type SheetFeedbackThreadData,
type SheetMode,
type SheetQuestion,
type SheetQuestionReview,
type SheetReplyPayload,
type SheetReview,
type SheetSample
} from '@ljoukov/sheet';Sheet accepts a document plus optional answers, seedAnswers, review, mockReview, feedbackThreads, feedbackState, mode, allowReplies, showFooter, footerLabel, onAnswersChange, and onReply.
