@lessonkit/react 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # `@lessonkit/react`
2
2
 
3
3
  [![CI](https://github.com/eddiethedean/lessonkit/actions/workflows/ci.yml/badge.svg)](https://github.com/eddiethedean/lessonkit/actions/workflows/ci.yml)
4
+ [![Documentation](https://readthedocs.org/projects/lessonkit/badge/?version=latest)](https://lessonkit.readthedocs.io/en/latest/)
4
5
  [![npm](https://img.shields.io/npm/v/@lessonkit/react.svg)](https://www.npmjs.com/package/@lessonkit/react)
5
- [![License](https://img.shields.io/github/license/eddiethedean/lessonkit)](../../LICENSE)
6
+ [![License](https://img.shields.io/github/license/eddiethedean/lessonkit)](https://github.com/eddiethedean/lessonkit/blob/main/LICENSE)
6
7
 
7
8
  React components and hooks for building learning experiences in LessonKit.
8
9
 
10
+ **Docs:** [Components & hooks](https://lessonkit.readthedocs.io/en/latest/guides/react-developers/components-and-hooks.html) · [Block catalog](https://lessonkit.readthedocs.io/en/latest/reference/block-catalog.html) · [Quickstart](https://lessonkit.readthedocs.io/en/latest/guides/react-developers/quickstart.html) · [Theming & accessibility](https://lessonkit.readthedocs.io/en/latest/guides/react-developers/theming-and-accessibility.html)
11
+
9
12
  ## Install
10
13
 
11
14
  ```bash
@@ -56,7 +59,14 @@ export default function App() {
56
59
  }
57
60
  ```
58
61
 
59
- ## API (0.6.0)
62
+ ## API (0.8.1)
63
+
64
+ ### Block catalog
65
+
66
+ - **JSON:** `@lessonkit/react/block-catalog.v1.json`
67
+ - **Schema:** `@lessonkit/react/block-contract.v1.json`
68
+ - **API:** `buildBlockCatalog()`, `getBlockCatalogEntry(type)`, `BLOCK_CATALOG`, `blockCatalogVersion`
69
+ - [Block catalog reference](https://lessonkit.readthedocs.io/en/latest/reference/block-catalog.html)
60
70
 
61
71
  ### Components
62
72
 
@@ -77,7 +87,7 @@ export default function App() {
77
87
 
78
88
  ### Theming
79
89
 
80
- - `ThemeProvider` — injects `--lk-*` CSS variables (see [`docs/THEMING.md`](../../docs/THEMING.md))
90
+ - `ThemeProvider` — injects `--lk-*` CSS variables ([theming reference](https://lessonkit.readthedocs.io/en/latest/reference/theming.html))
81
91
  - Props: `preset`, `mode` (`light` | `dark` | `system`), `theme` (partial override), `target` (`document` | `element`)
82
92
 
83
93
  ## Notes
@@ -97,7 +107,6 @@ export default function App() {
97
107
  - If you omit `session.sessionId`, the provider reuses a tab-scoped id via `sessionStorage` so React
98
108
  Strict Mode remounts do not split analytics sessions in development.
99
109
  - In development, invalid `courseId` / `lessonId` / `checkId` values log a one-time `console.warn`.
100
- - Accessibility guidance lives in [`docs/ACCESSIBILITY.md`](../../docs/ACCESSIBILITY.md).
101
- - Theming and token catalog: [`docs/THEMING.md`](../../docs/THEMING.md).
102
- - Identity and telemetry: [`docs/IDENTITY.md`](../../docs/IDENTITY.md), [`docs/TELEMETRY.md`](../../docs/TELEMETRY.md).
103
-
110
+ - [Accessibility reference](https://lessonkit.readthedocs.io/en/latest/reference/accessibility.html) — keyboard and screen-reader guidance.
111
+ - [Theming reference](https://lessonkit.readthedocs.io/en/latest/reference/theming.html) token catalog and overrides.
112
+ - [Identity](https://lessonkit.readthedocs.io/en/latest/reference/identity.html) · [Telemetry](https://lessonkit.readthedocs.io/en/latest/reference/telemetry.html) · [Block catalog](https://lessonkit.readthedocs.io/en/latest/reference/block-catalog.html) — IDs, events, and supported blocks.
@@ -0,0 +1,279 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "entries": [
4
+ {
5
+ "type": "Course",
6
+ "category": "container",
7
+ "description": "Top-level course shell; wraps LessonkitProvider and emits course lifecycle telemetry.",
8
+ "props": [
9
+ {
10
+ "name": "title",
11
+ "type": "string",
12
+ "required": true,
13
+ "description": "Course title shown in the h1."
14
+ },
15
+ {
16
+ "name": "courseId",
17
+ "type": "CourseId",
18
+ "required": true,
19
+ "description": "Stable course identifier for telemetry and packaging."
20
+ },
21
+ {
22
+ "name": "config",
23
+ "type": "Omit<LessonkitConfig, 'courseId'>",
24
+ "required": false,
25
+ "description": "Runtime config (tracking, xAPI, session, lxpack bridge). courseId is merged from props."
26
+ },
27
+ {
28
+ "name": "children",
29
+ "type": "ReactNode",
30
+ "required": true,
31
+ "description": "Lessons and course chrome."
32
+ }
33
+ ],
34
+ "requiredIds": [
35
+ "courseId"
36
+ ],
37
+ "a11y": {
38
+ "element": "section",
39
+ "ariaLabel": "title prop",
40
+ "keyboard": "No block-specific keyboard behavior; focus flows to child content.",
41
+ "notes": "Renders h1 with course title. Wrap with ThemeProvider at app root for theming."
42
+ },
43
+ "theming": {
44
+ "surface": "global-inherit",
45
+ "stylingNotes": "Inherits --lk-* CSS variables from ThemeProvider on document or scoped host."
46
+ },
47
+ "telemetry": {
48
+ "emits": [
49
+ "course_started",
50
+ "course_completed"
51
+ ]
52
+ }
53
+ },
54
+ {
55
+ "type": "Lesson",
56
+ "category": "container",
57
+ "description": "Lesson container; sets active lesson on mount and completes on unmount.",
58
+ "props": [
59
+ {
60
+ "name": "title",
61
+ "type": "string",
62
+ "required": true,
63
+ "description": "Lesson title shown in the h2."
64
+ },
65
+ {
66
+ "name": "lessonId",
67
+ "type": "LessonId",
68
+ "required": true,
69
+ "description": "Stable lesson identifier for telemetry and packaging."
70
+ },
71
+ {
72
+ "name": "children",
73
+ "type": "ReactNode",
74
+ "required": true,
75
+ "description": "Scenario, Quiz, Reflection, and other blocks."
76
+ }
77
+ ],
78
+ "requiredIds": [
79
+ "lessonId"
80
+ ],
81
+ "parentConstraints": [
82
+ "Course"
83
+ ],
84
+ "a11y": {
85
+ "element": "article",
86
+ "ariaLabel": "title prop",
87
+ "keyboard": "No block-specific keyboard behavior; focus flows to child content.",
88
+ "notes": "Renders h2 with lesson title. Only one Lesson should be mounted as active at a time in typical SPA layouts."
89
+ },
90
+ "theming": {
91
+ "surface": "global-inherit",
92
+ "stylingNotes": "Inherits --lk-* CSS variables from ThemeProvider."
93
+ },
94
+ "telemetry": {
95
+ "emits": [
96
+ "lesson_started",
97
+ "lesson_completed",
98
+ "lesson_time_on_task"
99
+ ]
100
+ }
101
+ },
102
+ {
103
+ "type": "Scenario",
104
+ "category": "content",
105
+ "description": "Scenario or narrative content region for branching stories and situational context.",
106
+ "props": [
107
+ {
108
+ "name": "blockId",
109
+ "type": "BlockId",
110
+ "required": false,
111
+ "description": "Optional stable block id for interaction telemetry URNs."
112
+ },
113
+ {
114
+ "name": "children",
115
+ "type": "ReactNode",
116
+ "required": true,
117
+ "description": "Scenario narrative and custom UI."
118
+ }
119
+ ],
120
+ "requiredIds": [],
121
+ "optionalIds": [
122
+ "blockId"
123
+ ],
124
+ "parentConstraints": [
125
+ "Lesson"
126
+ ],
127
+ "a11y": {
128
+ "element": "section",
129
+ "ariaLabel": "Scenario",
130
+ "keyboard": "No block-specific keyboard behavior; custom children may define their own.",
131
+ "notes": "Use for situational framing. Pair with useTracking() for branching interactions."
132
+ },
133
+ "theming": {
134
+ "surface": "global-inherit",
135
+ "dataAttributes": [
136
+ "data-lk-block-id"
137
+ ],
138
+ "stylingNotes": "Optional data-lk-block-id when blockId is set. Style via app CSS using --lk-* tokens."
139
+ },
140
+ "telemetry": {
141
+ "emits": [],
142
+ "manualTracking": "useTracking().track('interaction', { kind, blockId, payload })"
143
+ }
144
+ },
145
+ {
146
+ "type": "Reflection",
147
+ "category": "content",
148
+ "description": "Reflection prompt with a textarea for learner free-text responses.",
149
+ "props": [
150
+ {
151
+ "name": "blockId",
152
+ "type": "BlockId",
153
+ "required": false,
154
+ "description": "Optional stable block id for interaction telemetry URNs."
155
+ },
156
+ {
157
+ "name": "prompt",
158
+ "type": "string",
159
+ "required": false,
160
+ "description": "Reflection question or instruction."
161
+ },
162
+ {
163
+ "name": "children",
164
+ "type": "ReactNode",
165
+ "required": false,
166
+ "description": "Optional content above the textarea."
167
+ }
168
+ ],
169
+ "requiredIds": [],
170
+ "optionalIds": [
171
+ "blockId"
172
+ ],
173
+ "parentConstraints": [
174
+ "Lesson"
175
+ ],
176
+ "a11y": {
177
+ "element": "section",
178
+ "ariaLabel": "Reflection",
179
+ "keyboard": "Textarea is keyboard-focusable; standard text entry.",
180
+ "notes": "When prompt is set, textarea uses aria-labelledby; otherwise aria-label='Reflection response'."
181
+ },
182
+ "theming": {
183
+ "surface": "global-inherit",
184
+ "dataAttributes": [
185
+ "data-lk-block-id"
186
+ ],
187
+ "stylingNotes": "Optional data-lk-block-id when blockId is set. Style textarea via app CSS."
188
+ },
189
+ "telemetry": {
190
+ "emits": [],
191
+ "manualTracking": "useTracking().track('interaction', { kind, blockId, payload }) on submit or blur"
192
+ }
193
+ },
194
+ {
195
+ "type": "Quiz",
196
+ "aliases": [
197
+ "KnowledgeCheck"
198
+ ],
199
+ "category": "assessment",
200
+ "description": "Single-question multiple-choice assessment with automatic answer and completion telemetry.",
201
+ "props": [
202
+ {
203
+ "name": "checkId",
204
+ "type": "CheckId",
205
+ "required": true,
206
+ "description": "Stable check identifier for telemetry and LXPack assessments."
207
+ },
208
+ {
209
+ "name": "question",
210
+ "type": "string",
211
+ "required": true,
212
+ "description": "Question text shown above choices."
213
+ },
214
+ {
215
+ "name": "choices",
216
+ "type": "string[]",
217
+ "required": true,
218
+ "description": "Radio button choice labels."
219
+ },
220
+ {
221
+ "name": "answer",
222
+ "type": "string",
223
+ "required": true,
224
+ "description": "Correct choice value (must match one choice)."
225
+ }
226
+ ],
227
+ "requiredIds": [
228
+ "checkId"
229
+ ],
230
+ "parentConstraints": [
231
+ "Lesson"
232
+ ],
233
+ "a11y": {
234
+ "element": "section",
235
+ "ariaLabel": "Quiz",
236
+ "keyboard": "Radio group navigable with arrow keys; one choice per question.",
237
+ "liveRegions": "role='status' aria-live='polite' for Correct / Try again feedback.",
238
+ "notes": "Fieldset with visually hidden legend. KnowledgeCheck is an alias that renders Quiz with identical behavior."
239
+ },
240
+ "theming": {
241
+ "surface": "global-inherit",
242
+ "dataAttributes": [
243
+ "data-lk-check-id"
244
+ ],
245
+ "stylingNotes": "data-lk-check-id set from checkId. Style labels and feedback via app CSS."
246
+ },
247
+ "telemetry": {
248
+ "emits": [
249
+ "quiz_answered",
250
+ "quiz_completed"
251
+ ],
252
+ "requiresActiveLesson": true
253
+ }
254
+ },
255
+ {
256
+ "type": "ProgressTracker",
257
+ "category": "chrome",
258
+ "description": "Displays count of completed lessons from runtime progress state.",
259
+ "props": [],
260
+ "requiredIds": [],
261
+ "parentConstraints": [
262
+ "Course"
263
+ ],
264
+ "a11y": {
265
+ "element": "aside",
266
+ "ariaLabel": "Progress",
267
+ "keyboard": "Presentational; no interactive elements.",
268
+ "notes": "Shows 'Lessons completed: N' from progress.completedLessonIds."
269
+ },
270
+ "theming": {
271
+ "surface": "global-inherit",
272
+ "stylingNotes": "Inherits --lk-* CSS variables; style via app CSS."
273
+ },
274
+ "telemetry": {
275
+ "emits": []
276
+ }
277
+ }
278
+ ]
279
+ }
@@ -0,0 +1,101 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://lessonkit.dev/schemas/block-contract.v1.json",
4
+ "title": "LessonKit Block Catalog v1",
5
+ "description": "Machine-readable runtime block catalog for @lessonkit/react primitives.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schemaVersion", "entries"],
9
+ "properties": {
10
+ "schemaVersion": { "const": 1 },
11
+ "entries": {
12
+ "type": "array",
13
+ "minItems": 1,
14
+ "items": { "$ref": "#/$defs/blockCatalogEntry" }
15
+ }
16
+ },
17
+ "$defs": {
18
+ "blockPropSpec": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "required": ["name", "type", "required", "description"],
22
+ "properties": {
23
+ "name": { "type": "string", "minLength": 1 },
24
+ "type": { "type": "string", "minLength": 1 },
25
+ "required": { "type": "boolean" },
26
+ "description": { "type": "string", "minLength": 1 }
27
+ }
28
+ },
29
+ "blockCatalogEntry": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["type", "category", "description", "props", "requiredIds", "a11y", "theming", "telemetry"],
33
+ "properties": {
34
+ "type": { "type": "string", "minLength": 1 },
35
+ "aliases": {
36
+ "type": "array",
37
+ "items": { "type": "string", "minLength": 1 }
38
+ },
39
+ "category": {
40
+ "type": "string",
41
+ "enum": ["container", "content", "assessment", "chrome"]
42
+ },
43
+ "description": { "type": "string", "minLength": 1 },
44
+ "props": {
45
+ "type": "array",
46
+ "items": { "$ref": "#/$defs/blockPropSpec" }
47
+ },
48
+ "requiredIds": {
49
+ "type": "array",
50
+ "items": { "type": "string" }
51
+ },
52
+ "optionalIds": {
53
+ "type": "array",
54
+ "items": { "type": "string", "minLength": 1 }
55
+ },
56
+ "parentConstraints": {
57
+ "type": "array",
58
+ "items": { "type": "string", "minLength": 1 }
59
+ },
60
+ "a11y": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["element", "ariaLabel", "keyboard", "notes"],
64
+ "properties": {
65
+ "element": { "type": "string", "minLength": 1 },
66
+ "ariaLabel": { "type": "string", "minLength": 1 },
67
+ "keyboard": { "type": "string", "minLength": 1 },
68
+ "liveRegions": { "type": "string" },
69
+ "notes": { "type": "string", "minLength": 1 }
70
+ }
71
+ },
72
+ "theming": {
73
+ "type": "object",
74
+ "additionalProperties": false,
75
+ "required": ["surface", "stylingNotes"],
76
+ "properties": {
77
+ "surface": { "const": "global-inherit" },
78
+ "dataAttributes": {
79
+ "type": "array",
80
+ "items": { "type": "string", "minLength": 1 }
81
+ },
82
+ "stylingNotes": { "type": "string", "minLength": 1 }
83
+ }
84
+ },
85
+ "telemetry": {
86
+ "type": "object",
87
+ "additionalProperties": false,
88
+ "required": ["emits"],
89
+ "properties": {
90
+ "emits": {
91
+ "type": "array",
92
+ "items": { "type": "string" }
93
+ },
94
+ "requiresActiveLesson": { "type": "boolean" },
95
+ "manualTracking": { "type": "string", "minLength": 1 }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }