@mathscan/math-exercise-engine 1.1.17 → 1.2.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 +44 -11
- package/dist/index.d.ts +186 -164
- package/dist/index.js +296 -239
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +296 -239
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +84 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,18 +94,49 @@ import type { ExerciseRendererRef } from '@mathscan/math-exercise-engine';
|
|
|
94
94
|
const exerciseRef = useRef<ExerciseRendererRef>(null);
|
|
95
95
|
|
|
96
96
|
// Available methods:
|
|
97
|
-
const result = exerciseRef.current?.submit(); // Returns ValidationResult
|
|
97
|
+
const result = exerciseRef.current?.submit(); // Returns ValidationResult — LOCKS the exercise
|
|
98
98
|
exerciseRef.current?.getValues(); // Get current input values
|
|
99
|
-
exerciseRef.current?.
|
|
100
|
-
exerciseRef.current?.
|
|
99
|
+
exerciseRef.current?.getCompletion(); // How many answerable inputs are filled
|
|
100
|
+
exerciseRef.current?.revealAnswers(); // Fill in the correct answers — also LOCKS
|
|
101
|
+
exerciseRef.current?.reset(); // Clear all inputs and unlock
|
|
102
|
+
exerciseRef.current?.focusFirstInput(); // Focus first editable input field
|
|
101
103
|
```
|
|
102
104
|
|
|
103
105
|
### Method Details
|
|
104
106
|
|
|
105
|
-
- **`submit()`**: Performs validation
|
|
106
|
-
- **`getValues()`**: Returns `Record<string,
|
|
107
|
-
- **`
|
|
108
|
-
- **`
|
|
107
|
+
- **`submit()`**: Performs validation, returns `ValidationResult`, triggers `onSubmit`, and **locks the exercise** (see below). Calling it again while locked is a no-op that replays the same `ValidationResult` — no sound, no `onSubmit`
|
|
108
|
+
- **`getValues()`**: Returns `Record<string, UserAnswerValue>` of all current input values
|
|
109
|
+
- **`getCompletion()`**: Returns `{ total, filled, missing, filledIds, isComplete, isAnyFilled }` — use it to decide when to enable your submit button
|
|
110
|
+
- **`revealAnswers()`**: Fills every widget with its correct answer and **locks the exercise**. No-op for display-only exercises
|
|
111
|
+
- **`reset()`**: Clears all input fields and **unlocks** the exercise
|
|
112
|
+
- **`focusFirstInput()`**: Focuses the first editable input of *this* renderer. Skips read-only/disabled fields, so it does nothing while the exercise is locked
|
|
113
|
+
|
|
114
|
+
## 🔒 Locking After a Check
|
|
115
|
+
|
|
116
|
+
Once the answer is checked, the exercise becomes read-only until it is reset. This is the default and cannot be turned off.
|
|
117
|
+
|
|
118
|
+
**What locks it:** `submit()`, the built-in `showSubmitButton` button, and `revealAnswers()`.
|
|
119
|
+
**What unlocks it:** `reset()` — nothing else.
|
|
120
|
+
|
|
121
|
+
While locked, every widget refuses input: text inputs go `readOnly`, option/card widgets get `aria-disabled`, keypad and counter buttons get `disabled`, the built-in Check Answer button is `disabled`, drag-and-drop is disabled, and clock hands / number-line cursors stop responding. The root element gets a `.locked` class so you can style the state:
|
|
122
|
+
|
|
123
|
+
```css
|
|
124
|
+
.math-exercise-renderer.locked { /* your read-only styling */ }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Floating geometry tools (ruler, protractor, set square) stay draggable — they are instruments, not answers.
|
|
128
|
+
|
|
129
|
+
If your app shows an exercise in review mode (correction, teacher preview) and wants it read-only from the start, wrap it in your own provider:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { ExerciseLockProvider } from '@mathscan/math-exercise-engine';
|
|
133
|
+
|
|
134
|
+
<ExerciseLockProvider locked>
|
|
135
|
+
<ExerciseRenderer json={json} />
|
|
136
|
+
</ExerciseLockProvider>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The renderer ORs your value with its own state, so an outer lock is never overridden by an un-submitted exercise. Custom widgets of your own can read the same state with the `useExerciseLocked()` hook.
|
|
109
140
|
|
|
110
141
|
## 📝 DSL Syntax
|
|
111
142
|
|
|
@@ -228,10 +259,12 @@ import type {
|
|
|
228
259
|
|
|
229
260
|
// ExerciseRendererRef interface:
|
|
230
261
|
interface ExerciseRendererRef {
|
|
231
|
-
submit: () => ValidationResult; //
|
|
232
|
-
getValues: () => Record<string,
|
|
233
|
-
|
|
234
|
-
|
|
262
|
+
submit: () => ValidationResult; // Validate, return result, lock the exercise
|
|
263
|
+
getValues: () => Record<string, UserAnswerValue>; // Get current values
|
|
264
|
+
getCompletion: () => InputCompletion; // Fill status of the answerable inputs
|
|
265
|
+
revealAnswers: () => void; // Fill in correct answers, lock the exercise
|
|
266
|
+
reset: () => void; // Clear all inputs and unlock
|
|
267
|
+
focusFirstInput: () => void; // Focus first editable input
|
|
235
268
|
}
|
|
236
269
|
```
|
|
237
270
|
|