@superbuilders/incept-renderer 0.1.8 → 0.1.12
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 +537 -14
- package/dist/actions/index.d.ts +4 -1
- package/dist/actions/index.js +65 -6
- package/dist/actions/index.js.map +1 -1
- package/dist/components/index.d.ts +2 -3
- package/dist/components/index.js +43 -28
- package/dist/components/index.js.map +1 -1
- package/dist/index.d.ts +6 -11
- package/dist/index.js +94 -28
- package/dist/index.js.map +1 -1
- package/dist/parser-B8n3iHSM.d.ts +29 -0
- package/dist/qti-stimulus-renderer-CSuLfoff.d.ts +178 -0
- package/dist/{schema-DZoGAQdF.d.ts → schema-DKduufCs.d.ts} +106 -128
- package/dist/styles/duolingo.css +221 -0
- package/dist/styles/duolingo.css.map +1 -0
- package/dist/styles/duolingo.d.ts +2 -0
- package/dist/styles/themes.css +573 -37
- package/dist/styles/themes.css.map +1 -1
- package/dist/types.d.ts +2 -2
- package/package.json +5 -1
- package/dist/types-B7YRTQKt.d.ts +0 -102
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { A as AssessmentItem, a as AssessmentStimulus } from './schema-DKduufCs.js';
|
|
2
|
+
|
|
3
|
+
interface NormalizedNode {
|
|
4
|
+
tagName: string;
|
|
5
|
+
attrs: Record<string, unknown>;
|
|
6
|
+
children: Array<NormalizedNode | string>;
|
|
7
|
+
}
|
|
8
|
+
declare function parseAssessmentItemXml(xml: string): AssessmentItem;
|
|
9
|
+
/**
|
|
10
|
+
* Parses a QTI 3.0 Assessment Stimulus XML document.
|
|
11
|
+
*
|
|
12
|
+
* Assessment Stimuli are standalone reading materials (articles, passages, etc.)
|
|
13
|
+
* that can be referenced by one or more assessment items.
|
|
14
|
+
*
|
|
15
|
+
* @param xml - The raw XML string of the stimulus
|
|
16
|
+
* @returns A validated AssessmentStimulus object
|
|
17
|
+
* @throws If the XML is invalid or missing required elements
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const stimulus = parseAssessmentStimulusXml(xmlString)
|
|
22
|
+
* // stimulus.identifier - unique ID
|
|
23
|
+
* // stimulus.title - human-readable title
|
|
24
|
+
* // stimulus.bodyHtml - the HTML content to render
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare function parseAssessmentStimulusXml(xml: string): AssessmentStimulus;
|
|
28
|
+
|
|
29
|
+
export { type NormalizedNode as N, parseAssessmentStimulusXml as a, parseAssessmentItemXml as p };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { e as DisplayBlock, k as DisplayItem, a as AssessmentStimulus } from './schema-DKduufCs.js';
|
|
3
|
+
|
|
4
|
+
/** Theme options for the QTI renderer */
|
|
5
|
+
type QTITheme = "duolingo" | "neobrutalist" | (string & {});
|
|
6
|
+
/** Feedback result for a single response */
|
|
7
|
+
interface ResponseFeedback {
|
|
8
|
+
isCorrect: boolean;
|
|
9
|
+
messageHtml?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Correctness info for selected choices */
|
|
12
|
+
interface ChoiceCorrectness {
|
|
13
|
+
id: string;
|
|
14
|
+
isCorrect: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Props for the QTIRenderer component.
|
|
18
|
+
*
|
|
19
|
+
* This is a **controlled, display-only component**. It renders the question
|
|
20
|
+
* and captures user input, but does NOT include submit buttons or flow logic.
|
|
21
|
+
* The consuming app is responsible for:
|
|
22
|
+
* - Providing responses state
|
|
23
|
+
* - Handling submission
|
|
24
|
+
* - Providing feedback after validation
|
|
25
|
+
* - Rendering buttons (Check, Try Again, Continue, etc.)
|
|
26
|
+
*/
|
|
27
|
+
interface QTIRendererProps {
|
|
28
|
+
/**
|
|
29
|
+
* The display-safe item to render.
|
|
30
|
+
* Use `buildDisplayModel()` to create this from a parsed AssessmentItem.
|
|
31
|
+
*/
|
|
32
|
+
item: DisplayItem;
|
|
33
|
+
/**
|
|
34
|
+
* Current user responses, keyed by response identifier.
|
|
35
|
+
* This is a controlled component - you must manage this state.
|
|
36
|
+
* @example { "RESPONSE": "A" } or { "RESPONSE": ["A", "C"] }
|
|
37
|
+
*/
|
|
38
|
+
responses: Record<string, string | string[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Callback fired when user selects/changes an answer.
|
|
41
|
+
* Update your responses state in this callback.
|
|
42
|
+
*/
|
|
43
|
+
onResponseChange: (responseId: string, value: string | string[]) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Theme to apply. Defaults to "duolingo".
|
|
46
|
+
* Available themes: "duolingo", "neobrutalist", or any custom theme
|
|
47
|
+
* defined via `[data-qti-theme="your-theme"]` CSS.
|
|
48
|
+
*/
|
|
49
|
+
theme?: QTITheme;
|
|
50
|
+
/**
|
|
51
|
+
* Whether to show feedback states (correct/incorrect styling).
|
|
52
|
+
* Set to true after validation to display results.
|
|
53
|
+
*/
|
|
54
|
+
showFeedback?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Whether to disable all interactions.
|
|
57
|
+
* Typically set to true when showFeedback is true.
|
|
58
|
+
*/
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Per-choice correctness for highlighting selected answers.
|
|
62
|
+
* Keyed by response identifier.
|
|
63
|
+
*/
|
|
64
|
+
choiceCorrectness?: Record<string, ChoiceCorrectness[]>;
|
|
65
|
+
/**
|
|
66
|
+
* Per-response feedback messages to display.
|
|
67
|
+
* Keyed by response identifier.
|
|
68
|
+
*/
|
|
69
|
+
responseFeedback?: Record<string, ResponseFeedback>;
|
|
70
|
+
/**
|
|
71
|
+
* Overall feedback to display at the end of the question.
|
|
72
|
+
*/
|
|
73
|
+
overallFeedback?: ResponseFeedback;
|
|
74
|
+
/**
|
|
75
|
+
* Additional CSS class for the container.
|
|
76
|
+
*/
|
|
77
|
+
className?: string;
|
|
78
|
+
}
|
|
79
|
+
interface ContentBlockRendererProps {
|
|
80
|
+
/** The content block to render */
|
|
81
|
+
block: DisplayBlock;
|
|
82
|
+
/** Current user responses */
|
|
83
|
+
responses?: Record<string, string | string[]>;
|
|
84
|
+
/** Callback when user selects an answer */
|
|
85
|
+
onAnswerSelect?: (responseIdentifier: string, value: string | string[]) => void;
|
|
86
|
+
/** Whether to show feedback */
|
|
87
|
+
showFeedback?: boolean;
|
|
88
|
+
/** Whether to disable interactions */
|
|
89
|
+
disabled?: boolean;
|
|
90
|
+
/** Selected-only correctness mapping for this render pass */
|
|
91
|
+
selectedChoicesByResponse?: Record<string, Array<{
|
|
92
|
+
id: string;
|
|
93
|
+
isCorrect: boolean;
|
|
94
|
+
}>>;
|
|
95
|
+
/** Optional per-response feedback messages from server */
|
|
96
|
+
perResponseFeedback?: Record<string, {
|
|
97
|
+
isCorrect: boolean;
|
|
98
|
+
messageHtml?: string;
|
|
99
|
+
}>;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Renders a single content block (stimulus or interaction)
|
|
103
|
+
*/
|
|
104
|
+
declare function ContentBlockRenderer({ block, responses, onAnswerSelect, showFeedback, disabled, selectedChoicesByResponse, perResponseFeedback }: ContentBlockRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
105
|
+
/**
|
|
106
|
+
* A controlled, display-only component for rendering QTI assessment items.
|
|
107
|
+
*
|
|
108
|
+
* **This component does NOT include buttons or submission logic.**
|
|
109
|
+
* The consuming app is responsible for:
|
|
110
|
+
* - Managing `responses` state
|
|
111
|
+
* - Rendering Check/Submit/Try Again buttons
|
|
112
|
+
* - Calling validation APIs
|
|
113
|
+
* - Providing feedback data after validation
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```tsx
|
|
117
|
+
* const [responses, setResponses] = useState({})
|
|
118
|
+
* const [feedback, setFeedback] = useState(null)
|
|
119
|
+
*
|
|
120
|
+
* <QTIRenderer
|
|
121
|
+
* item={displayItem}
|
|
122
|
+
* responses={responses}
|
|
123
|
+
* onResponseChange={(id, value) => setResponses(prev => ({ ...prev, [id]: value }))}
|
|
124
|
+
* theme="neobrutalist"
|
|
125
|
+
* showFeedback={!!feedback}
|
|
126
|
+
* responseFeedback={feedback?.perResponse}
|
|
127
|
+
* overallFeedback={feedback?.overall}
|
|
128
|
+
* disabled={!!feedback}
|
|
129
|
+
* />
|
|
130
|
+
*
|
|
131
|
+
* <button onClick={handleCheck}>Check Answer</button>
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
declare function QTIRenderer({ item, responses, onResponseChange, theme, showFeedback, disabled, choiceCorrectness, responseFeedback, overallFeedback, className }: QTIRendererProps): react_jsx_runtime.JSX.Element;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Props for the QTIStimulusRenderer component.
|
|
138
|
+
*
|
|
139
|
+
* This is a simple, display-only component for rendering QTI Assessment Stimuli
|
|
140
|
+
* (reading materials, passages, articles).
|
|
141
|
+
* It does not handle interactions.
|
|
142
|
+
*/
|
|
143
|
+
type QTIStimulusRendererProps = {
|
|
144
|
+
/**
|
|
145
|
+
* The parsed stimulus to render.
|
|
146
|
+
* Use `parseAssessmentStimulusXml()` to create this from raw XML.
|
|
147
|
+
*/
|
|
148
|
+
stimulus: AssessmentStimulus;
|
|
149
|
+
/**
|
|
150
|
+
* Additional CSS class for the container.
|
|
151
|
+
*/
|
|
152
|
+
className?: string;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Renders a QTI 3.0 Assessment Stimulus (reading material).
|
|
156
|
+
*
|
|
157
|
+
* Assessment Stimuli are standalone content (articles, passages, etc.)
|
|
158
|
+
* that provide context for assessment items. This component renders
|
|
159
|
+
* the stimulus body HTML with proper support for:
|
|
160
|
+
*
|
|
161
|
+
* - Standard HTML elements (headings, lists, paragraphs, tables)
|
|
162
|
+
* - Images with responsive sizing
|
|
163
|
+
* - MathML mathematical expressions
|
|
164
|
+
* - Figures and figcaptions
|
|
165
|
+
* - Links and text formatting
|
|
166
|
+
* - Collapsible details/summary sections
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```tsx
|
|
170
|
+
* import { parseAssessmentStimulusXml, QTIStimulusRenderer } from "@superbuilders/incept-renderer"
|
|
171
|
+
*
|
|
172
|
+
* const stimulus = parseAssessmentStimulusXml(xmlString)
|
|
173
|
+
* <QTIStimulusRenderer stimulus={stimulus} className="my-8" />
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function QTIStimulusRenderer({ stimulus, className }: QTIStimulusRendererProps): react_jsx_runtime.JSX.Element;
|
|
177
|
+
|
|
178
|
+
export { type ChoiceCorrectness as C, type QTIRendererProps as Q, type ResponseFeedback as R, type ContentBlockRendererProps as a, type QTIStimulusRendererProps as b, type QTITheme as c, ContentBlockRenderer as d, QTIRenderer as e, QTIStimulusRenderer as f };
|
|
@@ -1,138 +1,105 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { a as DisplayBlock, g as DisplayItem } from './types-B7YRTQKt.js';
|
|
3
1
|
import { z } from 'zod';
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
type QTITheme = "duolingo" | "neobrutalist" | (string & {});
|
|
7
|
-
/** Feedback result for a single response */
|
|
8
|
-
interface ResponseFeedback {
|
|
9
|
-
isCorrect: boolean;
|
|
10
|
-
messageHtml?: string;
|
|
11
|
-
}
|
|
12
|
-
/** Correctness info for selected choices */
|
|
13
|
-
interface ChoiceCorrectness {
|
|
3
|
+
type DisplayChoice = {
|
|
14
4
|
id: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
5
|
+
contentHtml: string;
|
|
6
|
+
inlineFeedbackHtml?: string;
|
|
7
|
+
};
|
|
8
|
+
type DisplayChoiceInteraction = {
|
|
9
|
+
type: "choice";
|
|
10
|
+
responseId: string;
|
|
11
|
+
cardinality: "single" | "multiple";
|
|
12
|
+
promptHtml: string;
|
|
13
|
+
choices: DisplayChoice[];
|
|
14
|
+
minChoices: number;
|
|
15
|
+
maxChoices: number;
|
|
16
|
+
};
|
|
17
|
+
type DisplayTextInteraction = {
|
|
18
|
+
type: "text";
|
|
19
|
+
responseId: string;
|
|
20
|
+
expectedLength?: number;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
patternMask?: string;
|
|
23
|
+
};
|
|
24
|
+
type DisplayTextEmbed = {
|
|
25
|
+
responseId: string;
|
|
26
|
+
expectedLength?: number;
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
patternMask?: string;
|
|
29
|
+
};
|
|
30
|
+
type DisplayOrderInteraction = {
|
|
31
|
+
type: "order";
|
|
32
|
+
responseId: string;
|
|
33
|
+
promptHtml: string;
|
|
34
|
+
choices: DisplayChoice[];
|
|
35
|
+
orientation: "vertical" | "horizontal";
|
|
36
|
+
};
|
|
37
|
+
type DisplayGapText = {
|
|
38
|
+
id: string;
|
|
39
|
+
contentHtml: string;
|
|
40
|
+
matchMax: number;
|
|
41
|
+
};
|
|
42
|
+
type DisplayGap = {
|
|
43
|
+
id: string;
|
|
44
|
+
};
|
|
45
|
+
type DisplayGapMatchInteraction = {
|
|
46
|
+
type: "gapMatch";
|
|
47
|
+
responseId: string;
|
|
48
|
+
gapTexts: DisplayGapText[];
|
|
49
|
+
gaps: DisplayGap[];
|
|
50
|
+
contentHtml: string;
|
|
51
|
+
};
|
|
52
|
+
type DisplayAssociableChoice = {
|
|
53
|
+
id: string;
|
|
54
|
+
contentHtml: string;
|
|
55
|
+
matchMax: number;
|
|
56
|
+
};
|
|
57
|
+
type DisplayMatchInteraction = {
|
|
58
|
+
type: "match";
|
|
59
|
+
responseId: string;
|
|
60
|
+
promptHtml: string;
|
|
61
|
+
maxAssociations: number;
|
|
62
|
+
sourceChoices: DisplayAssociableChoice[];
|
|
63
|
+
targetChoices: DisplayAssociableChoice[];
|
|
64
|
+
};
|
|
65
|
+
type DisplayInteraction = DisplayChoiceInteraction | DisplayTextInteraction | DisplayOrderInteraction | DisplayGapMatchInteraction | DisplayMatchInteraction;
|
|
66
|
+
type DisplayInlineEmbed = {
|
|
67
|
+
responseId: string;
|
|
68
|
+
shuffle: boolean;
|
|
69
|
+
choices: Array<Pick<DisplayChoice, "id" | "contentHtml">>;
|
|
70
|
+
};
|
|
71
|
+
type DisplayBlock = {
|
|
72
|
+
type: "stimulus";
|
|
73
|
+
html: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: "richStimulus";
|
|
76
|
+
html: string;
|
|
77
|
+
inlineEmbeds: Record<string, DisplayInlineEmbed>;
|
|
78
|
+
textEmbeds: Record<string, DisplayTextEmbed>;
|
|
79
|
+
} | {
|
|
80
|
+
type: "interaction";
|
|
81
|
+
interaction: DisplayInteraction;
|
|
82
|
+
};
|
|
83
|
+
type DisplayItem = {
|
|
84
|
+
title: string;
|
|
85
|
+
contentBlocks: DisplayBlock[];
|
|
86
|
+
};
|
|
87
|
+
type FormShape = Record<string, "single" | "multiple" | "ordered" | "directedPair">;
|
|
88
|
+
type ValidateResult = {
|
|
89
|
+
overallCorrect: boolean;
|
|
90
|
+
perResponse: Record<string, {
|
|
91
|
+
isCorrect: boolean;
|
|
92
|
+
messageHtml?: string;
|
|
93
|
+
}>;
|
|
94
|
+
selectedChoicesByResponse: Record<string, Array<{
|
|
93
95
|
id: string;
|
|
94
96
|
isCorrect: boolean;
|
|
95
97
|
}>>;
|
|
96
|
-
|
|
97
|
-
perResponseFeedback?: Record<string, {
|
|
98
|
+
overallFeedback?: {
|
|
98
99
|
isCorrect: boolean;
|
|
99
100
|
messageHtml?: string;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Renders a single content block (stimulus or interaction)
|
|
104
|
-
*/
|
|
105
|
-
declare function ContentBlockRenderer({ block, responses, onAnswerSelect, showFeedback, disabled, selectedChoicesByResponse, perResponseFeedback }: ContentBlockRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
106
|
-
/**
|
|
107
|
-
* A controlled, display-only component for rendering QTI assessment items.
|
|
108
|
-
*
|
|
109
|
-
* **This component does NOT include buttons or submission logic.**
|
|
110
|
-
* The consuming app is responsible for:
|
|
111
|
-
* - Managing `responses` state
|
|
112
|
-
* - Rendering Check/Submit/Try Again buttons
|
|
113
|
-
* - Calling validation APIs
|
|
114
|
-
* - Providing feedback data after validation
|
|
115
|
-
*
|
|
116
|
-
* @example
|
|
117
|
-
* ```tsx
|
|
118
|
-
* const [responses, setResponses] = useState({})
|
|
119
|
-
* const [feedback, setFeedback] = useState(null)
|
|
120
|
-
*
|
|
121
|
-
* <QTIRenderer
|
|
122
|
-
* item={displayItem}
|
|
123
|
-
* responses={responses}
|
|
124
|
-
* onResponseChange={(id, value) => setResponses(prev => ({ ...prev, [id]: value }))}
|
|
125
|
-
* theme="neobrutalist"
|
|
126
|
-
* showFeedback={!!feedback}
|
|
127
|
-
* responseFeedback={feedback?.perResponse}
|
|
128
|
-
* overallFeedback={feedback?.overall}
|
|
129
|
-
* disabled={!!feedback}
|
|
130
|
-
* />
|
|
131
|
-
*
|
|
132
|
-
* <button onClick={handleCheck}>Check Answer</button>
|
|
133
|
-
* ```
|
|
134
|
-
*/
|
|
135
|
-
declare function QTIRenderer({ item, responses, onResponseChange, theme, showFeedback, disabled, choiceCorrectness, responseFeedback, overallFeedback, className }: QTIRendererProps): react_jsx_runtime.JSX.Element;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
136
103
|
|
|
137
104
|
declare const ChoiceInteractionSchema: z.ZodObject<{
|
|
138
105
|
responseIdentifier: z.ZodString;
|
|
@@ -573,5 +540,16 @@ declare const AssessmentItemSchema: z.ZodObject<{
|
|
|
573
540
|
}, z.core.$strip>;
|
|
574
541
|
}, z.core.$strip>;
|
|
575
542
|
type AssessmentItem = z.infer<typeof AssessmentItemSchema>;
|
|
543
|
+
/**
|
|
544
|
+
* Represents a QTI 3.0 Assessment Stimulus.
|
|
545
|
+
* Stimuli are standalone reading materials that can be referenced by assessment items.
|
|
546
|
+
*/
|
|
547
|
+
declare const AssessmentStimulusSchema: z.ZodObject<{
|
|
548
|
+
identifier: z.ZodString;
|
|
549
|
+
title: z.ZodDefault<z.ZodString>;
|
|
550
|
+
xmlLang: z.ZodDefault<z.ZodString>;
|
|
551
|
+
bodyHtml: z.ZodString;
|
|
552
|
+
}, z.core.$strip>;
|
|
553
|
+
type AssessmentStimulus = z.infer<typeof AssessmentStimulusSchema>;
|
|
576
554
|
|
|
577
|
-
export { type
|
|
555
|
+
export { type AssessmentItem as A, type ChoiceInteraction as C, type DisplayAssociableChoice as D, type FeedbackBlock as F, type GapMatchInteraction as G, type InlineChoiceInteraction as I, type MatchInteraction as M, type OrderInteraction as O, type ResponseDeclaration as R, type TextEntryInteraction as T, type ValidateResult as V, type AssessmentStimulus as a, type AnyCondition as b, type AnyInteraction as c, type ResponseProcessing as d, type DisplayBlock as e, type DisplayChoice as f, type DisplayChoiceInteraction as g, type DisplayGap as h, type DisplayGapText as i, type DisplayInlineEmbed as j, type DisplayItem as k, type DisplayTextEmbed as l, type FormShape as m, AssessmentItemSchema as n, AssessmentStimulusSchema as o };
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/* src/styles/duolingo.css */
|
|
2
|
+
:root {
|
|
3
|
+
--duolingo-polar: oklch(0.9761 0 0);
|
|
4
|
+
--duolingo-swan: oklch(0.9219 0 0);
|
|
5
|
+
--duolingo-hare: oklch(0.754 0 0);
|
|
6
|
+
--duolingo-wolf: oklch(0.5693 0 0);
|
|
7
|
+
--duolingo-eel: oklch(0.4128 0 0);
|
|
8
|
+
--duolingo-squid: oklch(0.9221 0.0087 17.31);
|
|
9
|
+
--duolingo-walking-fish: oklch(0.9303 0.0355 15.66);
|
|
10
|
+
--duolingo-flamingo: oklch(0.8365 0.0903 19.14);
|
|
11
|
+
--duolingo-pig: oklch(0.7979 0.0965 19.42);
|
|
12
|
+
--duolingo-crab: oklch(0.7314 0.1652 21.99);
|
|
13
|
+
--duolingo-cardinal: oklch(0.6708 0.2165 25.19);
|
|
14
|
+
--duolingo-fire-ant: oklch(0.6059 0.2241 27.19);
|
|
15
|
+
--duolingo-canary: oklch(0.9693 0.0455 93.5);
|
|
16
|
+
--duolingo-duck: oklch(0.9168 0.1416 99.05);
|
|
17
|
+
--duolingo-bee: oklch(0.8575 0.1752 88.49);
|
|
18
|
+
--duolingo-lion: oklch(0.8142 0.1704 76.91);
|
|
19
|
+
--duolingo-fox: oklch(0.7669 0.1748 63.06);
|
|
20
|
+
--duolingo-cheetah: oklch(0.8801 0.098 73.41);
|
|
21
|
+
--duolingo-monkey: oklch(0.7625 0.1199 66.64);
|
|
22
|
+
--duolingo-camel: oklch(0.767 0.1586 80.31);
|
|
23
|
+
--duolingo-guinea-pig: oklch(0.6532 0.147779 63.9665);
|
|
24
|
+
--duolingo-grizzly: oklch(0.572 0.0946 48.48);
|
|
25
|
+
--duolingo-sea-sponge: oklch(0.9546 0.1012 131.98);
|
|
26
|
+
--duolingo-turtle: oklch(0.8717 0.1754 133.4);
|
|
27
|
+
--duolingo-owl: oklch(0.7478 0.2289 137.63);
|
|
28
|
+
--duolingo-tree-frog: oklch(0.6516 0.1894 134.73);
|
|
29
|
+
--duolingo-iguana: oklch(0.9536 0.0284 228.04);
|
|
30
|
+
--duolingo-anchovy: oklch(0.9066 0.02 212.55);
|
|
31
|
+
--duolingo-beluga: oklch(0.9277 0.0584 213.8);
|
|
32
|
+
--duolingo-moon-jelly: oklch(0.8875 0.1069 196.87);
|
|
33
|
+
--duolingo-blue-jay: oklch(0.8429 0.0982 229.43);
|
|
34
|
+
--duolingo-macaw: oklch(0.7181 0.1513 237.07);
|
|
35
|
+
--duolingo-whale: oklch(0.6476 0.1358 236.91);
|
|
36
|
+
--duolingo-humpback: oklch(0.5493 0.1544 256.44);
|
|
37
|
+
--duolingo-narwhal: oklch(0.4514 0.1434 256.99);
|
|
38
|
+
--duolingo-starfish: oklch(0.8359 0.1184 342.63);
|
|
39
|
+
--duolingo-beetle: oklch(0.7345 0.1876 310.63);
|
|
40
|
+
--duolingo-betta: oklch(0.604 0.1505 299.92);
|
|
41
|
+
--duolingo-butterfly: oklch(0.4981 0.1306 300.05);
|
|
42
|
+
--color-polar: var(--duolingo-polar);
|
|
43
|
+
--color-swan: var(--duolingo-swan);
|
|
44
|
+
--color-hare: var(--duolingo-hare);
|
|
45
|
+
--color-wolf: var(--duolingo-wolf);
|
|
46
|
+
--color-eel: var(--duolingo-eel);
|
|
47
|
+
--color-squid: var(--duolingo-squid);
|
|
48
|
+
--color-walking-fish: var(--duolingo-walking-fish);
|
|
49
|
+
--color-flamingo: var(--duolingo-flamingo);
|
|
50
|
+
--color-pig: var(--duolingo-pig);
|
|
51
|
+
--color-crab: var(--duolingo-crab);
|
|
52
|
+
--color-cardinal: var(--duolingo-cardinal);
|
|
53
|
+
--color-fire-ant: var(--duolingo-fire-ant);
|
|
54
|
+
--color-canary: var(--duolingo-canary);
|
|
55
|
+
--color-duck: var(--duolingo-duck);
|
|
56
|
+
--color-bee: var(--duolingo-bee);
|
|
57
|
+
--color-lion: var(--duolingo-lion);
|
|
58
|
+
--color-fox: var(--duolingo-fox);
|
|
59
|
+
--color-cheetah: var(--duolingo-cheetah);
|
|
60
|
+
--color-monkey: var(--duolingo-monkey);
|
|
61
|
+
--color-camel: var(--duolingo-camel);
|
|
62
|
+
--color-guinea-pig: var(--duolingo-guinea-pig);
|
|
63
|
+
--color-grizzly: var(--duolingo-grizzly);
|
|
64
|
+
--color-sea-sponge: var(--duolingo-sea-sponge);
|
|
65
|
+
--color-turtle: var(--duolingo-turtle);
|
|
66
|
+
--color-owl: var(--duolingo-owl);
|
|
67
|
+
--color-tree-frog: var(--duolingo-tree-frog);
|
|
68
|
+
--color-iguana: var(--duolingo-iguana);
|
|
69
|
+
--color-anchovy: var(--duolingo-anchovy);
|
|
70
|
+
--color-beluga: var(--duolingo-beluga);
|
|
71
|
+
--color-moon-jelly: var(--duolingo-moon-jelly);
|
|
72
|
+
--color-blue-jay: var(--duolingo-blue-jay);
|
|
73
|
+
--color-macaw: var(--duolingo-macaw);
|
|
74
|
+
--color-whale: var(--duolingo-whale);
|
|
75
|
+
--color-humpback: var(--duolingo-humpback);
|
|
76
|
+
--color-narwhal: var(--duolingo-narwhal);
|
|
77
|
+
--color-starfish: var(--duolingo-starfish);
|
|
78
|
+
--color-beetle: var(--duolingo-beetle);
|
|
79
|
+
--color-betta: var(--duolingo-betta);
|
|
80
|
+
--color-butterfly: var(--duolingo-butterfly);
|
|
81
|
+
--background: var(--duolingo-polar);
|
|
82
|
+
--foreground: var(--duolingo-eel);
|
|
83
|
+
--muted: var(--duolingo-swan);
|
|
84
|
+
--muted-foreground: var(--duolingo-wolf);
|
|
85
|
+
--border: var(--duolingo-swan);
|
|
86
|
+
--input: var(--duolingo-hare);
|
|
87
|
+
--accent: var(--duolingo-swan);
|
|
88
|
+
--color-background: var(--background);
|
|
89
|
+
--color-foreground: var(--foreground);
|
|
90
|
+
--color-muted: var(--muted);
|
|
91
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
92
|
+
--color-border: var(--border);
|
|
93
|
+
--color-input: var(--input);
|
|
94
|
+
--color-accent: var(--accent);
|
|
95
|
+
--radius: 1rem;
|
|
96
|
+
--radius-xs: 0.5rem;
|
|
97
|
+
--radius-sm: 0.75rem;
|
|
98
|
+
--radius-md: 0.875rem;
|
|
99
|
+
--radius-lg: 1rem;
|
|
100
|
+
}
|
|
101
|
+
.dark {
|
|
102
|
+
--background: oklch(0.2301 0.0215 228.5177);
|
|
103
|
+
--foreground: var(--duolingo-polar);
|
|
104
|
+
--muted: oklch(0.3847 0.0246 234.6115);
|
|
105
|
+
--muted-foreground: oklch(0.494 0.0263 225.3177);
|
|
106
|
+
--border: oklch(0.3847 0.0246 234.6115);
|
|
107
|
+
--input: oklch(0.494 0.0263 225.3177);
|
|
108
|
+
--accent: oklch(0.2949 0.0237 228.4373);
|
|
109
|
+
--color-background: var(--background);
|
|
110
|
+
--color-foreground: var(--foreground);
|
|
111
|
+
--color-muted: var(--muted);
|
|
112
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
113
|
+
--color-border: var(--border);
|
|
114
|
+
--color-input: var(--input);
|
|
115
|
+
--color-accent: var(--accent);
|
|
116
|
+
}
|
|
117
|
+
.qti-html-content {
|
|
118
|
+
color: inherit !important;
|
|
119
|
+
}
|
|
120
|
+
.qti-html-content *,
|
|
121
|
+
.qti-html-content p,
|
|
122
|
+
.qti-html-content div,
|
|
123
|
+
.qti-html-content span,
|
|
124
|
+
.qti-html-content li {
|
|
125
|
+
color: inherit !important;
|
|
126
|
+
}
|
|
127
|
+
.qti-html-content .qti-feedback-preamble p,
|
|
128
|
+
.qti-html-content .qti-step p,
|
|
129
|
+
.qti-html-content .qti-step-title {
|
|
130
|
+
color: inherit !important;
|
|
131
|
+
}
|
|
132
|
+
.qti-html-content .qti-step-index {
|
|
133
|
+
color: white !important;
|
|
134
|
+
}
|
|
135
|
+
.qti-html-content .qti-step {
|
|
136
|
+
background: transparent !important;
|
|
137
|
+
border-color: var(--border) !important;
|
|
138
|
+
}
|
|
139
|
+
.qti-html-content strong,
|
|
140
|
+
.qti-html-content b {
|
|
141
|
+
font-weight: 700;
|
|
142
|
+
}
|
|
143
|
+
.qti-html-content em,
|
|
144
|
+
.qti-html-content i {
|
|
145
|
+
font-style: italic;
|
|
146
|
+
}
|
|
147
|
+
.qti-html-content p {
|
|
148
|
+
margin-bottom: 0.5rem;
|
|
149
|
+
}
|
|
150
|
+
.qti-html-content ul {
|
|
151
|
+
margin-left: 1.5rem;
|
|
152
|
+
margin-bottom: 0.5rem;
|
|
153
|
+
list-style-type: disc;
|
|
154
|
+
}
|
|
155
|
+
.qti-html-content ol {
|
|
156
|
+
margin-left: 1.5rem;
|
|
157
|
+
margin-bottom: 0.5rem;
|
|
158
|
+
list-style-type: decimal;
|
|
159
|
+
}
|
|
160
|
+
.qti-html-content li {
|
|
161
|
+
margin-bottom: 0.25rem;
|
|
162
|
+
}
|
|
163
|
+
.qti-html-content math,
|
|
164
|
+
.qti-html-content math *,
|
|
165
|
+
.qti-html-content math mi,
|
|
166
|
+
.qti-html-content math mo,
|
|
167
|
+
.qti-html-content math mn,
|
|
168
|
+
.qti-html-content math mtext {
|
|
169
|
+
color: inherit !important;
|
|
170
|
+
}
|
|
171
|
+
[data-slot=choice-indicator].rounded-xs,
|
|
172
|
+
[data-slot=choice-indicator] {
|
|
173
|
+
border-radius: 12px !important;
|
|
174
|
+
min-width: 2rem !important;
|
|
175
|
+
min-height: 2rem !important;
|
|
176
|
+
width: 2rem !important;
|
|
177
|
+
height: 2rem !important;
|
|
178
|
+
}
|
|
179
|
+
[data-slot=choice-indicator][data-state=checked]:not([data-filled=true]) {
|
|
180
|
+
background: var(--background) !important;
|
|
181
|
+
border-color: var(--duolingo-macaw) !important;
|
|
182
|
+
color: var(--duolingo-macaw) !important;
|
|
183
|
+
}
|
|
184
|
+
[data-slot=choice-indicator][data-filled=true][data-state=checked] {
|
|
185
|
+
background: var(--duolingo-macaw) !important;
|
|
186
|
+
border-color: var(--duolingo-macaw) !important;
|
|
187
|
+
box-shadow: inset 0 0 0 3px var(--background) !important;
|
|
188
|
+
}
|
|
189
|
+
[data-slot=choice-indicator][data-palette=owl][data-state=checked]:not([data-filled=true]) {
|
|
190
|
+
background: var(--background) !important;
|
|
191
|
+
border-color: var(--duolingo-tree-frog) !important;
|
|
192
|
+
color: var(--duolingo-owl) !important;
|
|
193
|
+
}
|
|
194
|
+
[data-slot=choice-indicator][data-palette=owl][data-filled=true][data-state=checked] {
|
|
195
|
+
background: var(--duolingo-owl) !important;
|
|
196
|
+
border-color: var(--duolingo-tree-frog) !important;
|
|
197
|
+
box-shadow: inset 0 0 0 3px var(--background) !important;
|
|
198
|
+
}
|
|
199
|
+
[data-slot=choice-indicator][data-palette=cardinal][data-state=checked]:not([data-filled=true]) {
|
|
200
|
+
background: var(--background) !important;
|
|
201
|
+
border-color: var(--duolingo-fire-ant) !important;
|
|
202
|
+
color: var(--duolingo-cardinal) !important;
|
|
203
|
+
}
|
|
204
|
+
[data-slot=choice-indicator][data-palette=cardinal][data-filled=true][data-state=checked] {
|
|
205
|
+
background: var(--duolingo-cardinal) !important;
|
|
206
|
+
border-color: var(--duolingo-fire-ant) !important;
|
|
207
|
+
box-shadow: inset 0 0 0 3px var(--background) !important;
|
|
208
|
+
}
|
|
209
|
+
[data-slot=field-label]:has(> [data-slot=field]):has([data-state=checked]) {
|
|
210
|
+
background: oklch(0.9536 0.0284 228.04 / 0.3) !important;
|
|
211
|
+
border-color: var(--duolingo-macaw) !important;
|
|
212
|
+
}
|
|
213
|
+
[data-slot=field-label][data-palette=owl]:has(> [data-slot=field]):has([data-state=checked]) {
|
|
214
|
+
background: oklch(0.9546 0.1012 131.98 / 0.3) !important;
|
|
215
|
+
border-color: var(--duolingo-owl) !important;
|
|
216
|
+
}
|
|
217
|
+
[data-slot=field-label][data-palette=cardinal]:has(> [data-slot=field]):has([data-state=checked]) {
|
|
218
|
+
background: oklch(0.9221 0.0087 17.31 / 0.3) !important;
|
|
219
|
+
border-color: var(--duolingo-cardinal) !important;
|
|
220
|
+
}
|
|
221
|
+
/*# sourceMappingURL=duolingo.css.map */
|