@lessonkit/react 0.9.2 → 1.0.0

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,13 +1,10 @@
1
- # `@lessonkit/react`
1
+ # @lessonkit/react
2
2
 
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/)
5
3
  [![npm](https://img.shields.io/npm/v/@lessonkit/react.svg)](https://www.npmjs.com/package/@lessonkit/react)
4
+ [![Documentation](https://readthedocs.org/projects/lessonkit/badge/?version=latest)](https://lessonkit.readthedocs.io/en/latest/guides/react-developers/components-and-hooks.html)
6
5
  [![License](https://img.shields.io/github/license/eddiethedean/lessonkit)](https://github.com/eddiethedean/lessonkit/blob/main/LICENSE)
7
6
 
8
- React components and hooks for building learning experiences in LessonKit.
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)
7
+ React components and hooks for authoring LessonKit courses.
11
8
 
12
9
  ## Install
13
10
 
@@ -15,98 +12,53 @@ React components and hooks for building learning experiences in LessonKit.
15
12
  npm install @lessonkit/react react react-dom
16
13
  ```
17
14
 
18
- ## Quick example
15
+ Optional: `@lessonkit/xapi`, `@lessonkit/themes`, `@lessonkit/accessibility`
16
+
17
+ ## Usage
19
18
 
20
19
  ```tsx
21
20
  import { useMemo } from "react";
22
- import type { TelemetryEvent } from "@lessonkit/core";
23
- import { Course, Lesson, Quiz, Scenario, ProgressTracker, ThemeProvider } from "@lessonkit/react";
24
- import type { XAPIStatement } from "@lessonkit/xapi";
21
+ import { Course, Lesson, Quiz, ProgressTracker, ThemeProvider } from "@lessonkit/react";
25
22
 
26
23
  export default function App() {
27
- const config = useMemo(
28
- () => ({
29
- tracking: {
30
- sink: (event: TelemetryEvent) => console.log(event),
31
- },
32
- xapi: {
33
- transport: (statement: XAPIStatement) => console.log(statement),
34
- },
35
- }),
36
- [],
37
- );
24
+ const config = useMemo(() => ({ tracking: { sink: console.log } }), []);
38
25
 
39
26
  return (
40
27
  <ThemeProvider mode="light">
41
- <Course title="Cybersecurity Basics" courseId="cyber-basics" config={config}>
42
- <ProgressTracker />
43
-
44
- <Lesson title="Phishing Awareness" lessonId="phishing-101">
45
- <Scenario>
46
- <p>You receive a suspicious email.</p>
47
- </Scenario>
48
-
49
- <Quiz
50
- checkId="first-step"
51
- question="What should you do first?"
52
- choices={["Open attachment", "Verify sender"]}
53
- answer="Verify sender"
54
- />
55
- </Lesson>
56
- </Course>
28
+ <Course title="My Course" courseId="my-course" config={config}>
29
+ <ProgressTracker />
30
+ <Lesson title="Lesson 1" lessonId="lesson-1">
31
+ <Quiz
32
+ checkId="check-1"
33
+ question="Ready?"
34
+ choices={["No", "Yes"]}
35
+ answer="Yes"
36
+ />
37
+ </Lesson>
38
+ </Course>
57
39
  </ThemeProvider>
58
40
  );
59
41
  }
60
42
  ```
61
43
 
62
- ## API (0.9.2)
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)
70
-
71
- ### Components
72
-
73
- - `Course` requires `courseId`
74
- - `Lesson` requires `lessonId`
75
- - `Scenario` — optional `blockId`
76
- - `Quiz` / `KnowledgeCheck` — require `checkId`
77
- - `Reflection` — optional `blockId`
78
- - `ProgressTracker`
79
-
80
- ### Hooks
81
-
82
- - `useProgress`
83
- - `useTracking`
84
- - `useQuizState`
85
- - `useCompletion`
86
- - `useTheme`
87
-
88
- ### Theming
89
-
90
- - `ThemeProvider` — injects `--lk-*` CSS variables ([theming reference](https://lessonkit.readthedocs.io/en/latest/reference/theming.html))
91
- - Props: `preset`, `mode` (`light` | `dark` | `system`), `theme` (partial override), `target` (`document` | `element`)
92
-
93
- ## Notes
94
-
95
- - `@lessonkit/react` ships **framework primitives**, not content. You bring your own layout/content
96
- and compose interactions as React components.
97
- - `Course` accepts a `config` prop that is passed through to `LessonkitProvider` (tracking sink,
98
- optional `xapi.transport` or custom `xapi.client`, session metadata). Hoist `config` with `useMemo`
99
- so tracking/xAPI clients are not recreated every render.
100
- - xAPI is enabled by default unless `xapi.enabled: false`. Provide `xapi.transport` or `xapi.client`
101
- or statements are queued in memory and never sent (dev warns once).
102
- - A lesson is marked complete when its `<Lesson>` unmounts (for example, wizard navigation) or when
103
- another lesson becomes active via `setActiveLesson`. Use stable `lessonId` values so completion and
104
- time-on-task telemetry stay consistent.
105
- - `<Lesson>` defers completion on unmount so React Strict Mode remounts in development do not emit
106
- spurious `lesson_completed` events; completion runs after the component leaves the tree.
107
- - If you omit `session.sessionId`, the provider reuses a tab-scoped id via `sessionStorage` so React
108
- Strict Mode remounts do not split analytics sessions in development.
109
- - In development, invalid `courseId` / `lessonId` / `checkId` values log a one-time `console.warn`.
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.
44
+ ## API
45
+
46
+ **Components:** `Course`, `Lesson`, `Scenario`, `Quiz`, `KnowledgeCheck`, `Reflection`, `ProgressTracker`, `ThemeProvider`
47
+
48
+ **Hooks:** `useProgress`, `useTracking`, `useQuizState`, `useCompletion`, `useTheme`
49
+
50
+ **Catalog:** `@lessonkit/react/block-catalog.v1.json` · `buildBlockCatalog()`, `getBlockCatalogEntry()`
51
+
52
+ ## Tips
53
+
54
+ - Hoist `config` with `useMemo` so tracking/xAPI clients are not recreated every render.
55
+ - xAPI is on by default; provide `xapi.transport` or statements queue in memory.
56
+ - Lessons complete on unmount or when another lesson becomes active via `setActiveLesson`.
57
+
58
+ ## Docs
59
+
60
+ [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) · [Theming](https://lessonkit.readthedocs.io/en/latest/reference/theming.html) · [Storybook](https://github.com/eddiethedean/lessonkit/blob/main/docs/storybook/README.md) (`npm run storybook` from repo root)
61
+
62
+ ## License
63
+
64
+ Apache-2.0
@@ -68,6 +68,12 @@
68
68
  "required": true,
69
69
  "description": "Stable lesson identifier for telemetry and packaging."
70
70
  },
71
+ {
72
+ "name": "autoCompleteOnUnmount",
73
+ "type": "boolean",
74
+ "required": false,
75
+ "description": "When false, unmount does not emit lesson_completed (default true)."
76
+ },
71
77
  {
72
78
  "name": "children",
73
79
  "type": "ReactNode",
@@ -159,6 +165,24 @@
159
165
  "required": false,
160
166
  "description": "Reflection question or instruction."
161
167
  },
168
+ {
169
+ "name": "hint",
170
+ "type": "string",
171
+ "required": false,
172
+ "description": "Optional hint linked via aria-describedby."
173
+ },
174
+ {
175
+ "name": "value",
176
+ "type": "string",
177
+ "required": false,
178
+ "description": "Controlled textarea value."
179
+ },
180
+ {
181
+ "name": "onChange",
182
+ "type": "(value: string) => void",
183
+ "required": false,
184
+ "description": "Called when the learner edits the textarea."
185
+ },
162
186
  {
163
187
  "name": "children",
164
188
  "type": "ReactNode",
@@ -188,6 +212,7 @@
188
212
  },
189
213
  "telemetry": {
190
214
  "emits": [],
215
+ "requiresActiveLesson": true,
191
216
  "manualTracking": "useTracking().track('interaction', { kind, blockId, payload }) on submit or blur"
192
217
  }
193
218
  },
@@ -256,7 +281,14 @@
256
281
  "type": "ProgressTracker",
257
282
  "category": "chrome",
258
283
  "description": "Displays count of completed lessons from runtime progress state.",
259
- "props": [],
284
+ "props": [
285
+ {
286
+ "name": "totalLessons",
287
+ "type": "number",
288
+ "required": false,
289
+ "description": "When set, renders role=progressbar with aria-valuenow/max."
290
+ }
291
+ ],
260
292
  "requiredIds": [],
261
293
  "parentConstraints": [
262
294
  "Course"