tessera-learn 0.0.8 → 0.0.10
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/dist/plugin/cli.js +1 -1
- package/dist/plugin/index.js +147 -11
- package/dist/plugin/index.js.map +1 -1
- package/dist/{validation-B4UhCY5y.js → validation-BxWAMMnJ.js} +4 -7
- package/dist/validation-BxWAMMnJ.js.map +1 -0
- package/package.json +9 -6
- package/src/components/DefaultLayout.svelte +2 -0
- package/src/components/FillInTheBlank.svelte +32 -37
- package/src/components/Matching.svelte +35 -68
- package/src/components/MultipleChoice.svelte +25 -38
- package/src/components/Quiz.svelte +22 -26
- package/src/components/Sorting.svelte +40 -42
- package/src/index.ts +1 -0
- package/src/plugin/index.ts +184 -9
- package/src/plugin/validation.ts +7 -2
- package/src/runtime/App.svelte +53 -39
- package/src/runtime/LoadingBar.svelte +47 -0
- package/src/runtime/Sidebar.svelte +2 -0
- package/src/runtime/adapters/cmi5.ts +44 -14
- package/src/runtime/hooks.svelte.ts +269 -227
- package/src/runtime/interaction-format.ts +40 -8
- package/src/runtime/interaction.ts +3 -3
- package/src/runtime/navigation.svelte.ts +38 -5
- package/src/runtime/persistence.ts +5 -0
- package/src/runtime/progress.svelte.ts +16 -10
- package/src/runtime/quiz-policy.ts +16 -16
- package/src/runtime/types.ts +1 -2
- package/src/virtual.d.ts +13 -0
- package/styles/layout.css +34 -24
- package/dist/validation-B4UhCY5y.js.map +0 -1
- package/src/components/quiz-payload.ts +0 -71
- package/src/runtime/LoadingSkeleton.svelte +0 -26
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { Interaction } from '../runtime/interaction.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shape contributed by a question component when it registers with a `<Quiz>`.
|
|
5
|
-
* `useQuestion` always supplies both `id` and `interaction`; custom widgets
|
|
6
|
-
* may omit `interaction` (presentational steps that don't report to the LMS),
|
|
7
|
-
* in which case they're skipped by `buildQuizInteractions`.
|
|
8
|
-
*/
|
|
9
|
-
export interface QuizQuestionApi {
|
|
10
|
-
id: string;
|
|
11
|
-
/** Optional weight for the score rollup. Default 1 — `Σ(w·correct)/Σ(w)*100`. */
|
|
12
|
-
weight?: number;
|
|
13
|
-
checkAnswer: (answer: unknown) => boolean;
|
|
14
|
-
reset?: () => void;
|
|
15
|
-
render?: unknown;
|
|
16
|
-
interaction?: () => Interaction;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Reactive context published by `<Quiz>` (and `useQuiz`) under the
|
|
21
|
-
* `'tessera-quiz'` Svelte context key. Question widgets read this through
|
|
22
|
-
* `getContext<QuizContext>('tessera-quiz')` to coordinate with their host.
|
|
23
|
-
*
|
|
24
|
-
* All accessors are getters so the consumer re-runs when the underlying rune
|
|
25
|
-
* state changes — destructuring the object will break reactivity.
|
|
26
|
-
*/
|
|
27
|
-
export interface QuizContext {
|
|
28
|
-
registerQuestion(api: QuizQuestionApi): number;
|
|
29
|
-
setRender(index: number, render: unknown): void;
|
|
30
|
-
setAnswer(index: number, answer: unknown): void;
|
|
31
|
-
getAnswer(index: number): unknown;
|
|
32
|
-
readonly submitted: boolean;
|
|
33
|
-
readonly reviewing: boolean;
|
|
34
|
-
readonly showFeedback: boolean;
|
|
35
|
-
feedbackVisible(index: number): boolean;
|
|
36
|
-
isAnswerLocked(index: number): boolean;
|
|
37
|
-
isLockedCorrect(index: number): boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface QuizInteractionEntry {
|
|
41
|
-
id: string;
|
|
42
|
-
interaction: Interaction;
|
|
43
|
-
correct: boolean;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Build the per-question payload included in `tessera-quiz-complete`.
|
|
48
|
-
*
|
|
49
|
-
* Skips questions whose `interaction` is missing or returns nullish — custom
|
|
50
|
-
* widgets may register without an interaction reporter (e.g. presentational
|
|
51
|
-
* "press to continue" steps), and those simply don't contribute to the
|
|
52
|
-
* `cmi.interactions` / xAPI Answered stream.
|
|
53
|
-
*/
|
|
54
|
-
export function buildQuizInteractions(
|
|
55
|
-
questions: QuizQuestionApi[],
|
|
56
|
-
answers: Map<number, unknown>
|
|
57
|
-
): QuizInteractionEntry[] {
|
|
58
|
-
const entries: QuizInteractionEntry[] = [];
|
|
59
|
-
for (let i = 0; i < questions.length; i++) {
|
|
60
|
-
const q = questions[i];
|
|
61
|
-
if (typeof q.interaction !== 'function') continue;
|
|
62
|
-
const interaction = q.interaction();
|
|
63
|
-
if (!interaction) continue;
|
|
64
|
-
entries.push({
|
|
65
|
-
id: q.id,
|
|
66
|
-
interaction,
|
|
67
|
-
correct: q.checkAnswer(answers.get(i)),
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
return entries;
|
|
71
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
|
|
4
|
-
let showSlowMessage = $state(false);
|
|
5
|
-
let timer;
|
|
6
|
-
|
|
7
|
-
onMount(() => {
|
|
8
|
-
timer = setTimeout(() => {
|
|
9
|
-
showSlowMessage = true;
|
|
10
|
-
}, 5000);
|
|
11
|
-
|
|
12
|
-
return () => clearTimeout(timer);
|
|
13
|
-
});
|
|
14
|
-
</script>
|
|
15
|
-
|
|
16
|
-
<div class="tessera-skeleton" aria-busy="true" aria-label="Loading page content">
|
|
17
|
-
<div class="tessera-skeleton-line"></div>
|
|
18
|
-
<div class="tessera-skeleton-line"></div>
|
|
19
|
-
<div class="tessera-skeleton-line"></div>
|
|
20
|
-
<div class="tessera-skeleton-line"></div>
|
|
21
|
-
<div class="tessera-skeleton-line"></div>
|
|
22
|
-
<div class="tessera-skeleton-line"></div>
|
|
23
|
-
{#if showSlowMessage}
|
|
24
|
-
<p class="tessera-skeleton-message">Still loading…</p>
|
|
25
|
-
{/if}
|
|
26
|
-
</div>
|