@citolab/qti-components 8.0.0 → 8.0.2
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/cdn/index.global.js +1 -1
- package/cdn/index.js +690 -316
- package/dist/base.d.ts +135 -9
- package/dist/base.js +1 -1
- package/dist/chunk-4DB4SC5K.js +100 -0
- package/dist/chunk-4DB4SC5K.js.map +1 -0
- package/dist/{chunk-WVVMNF74.js → chunk-7AVWRQIS.js} +188 -160
- package/dist/{chunk-WVVMNF74.js.map → chunk-7AVWRQIS.js.map} +1 -1
- package/dist/{chunk-MGF5F3S2.js → chunk-BQFWCZFH.js} +2 -2
- package/dist/{chunk-5QYII4OZ.js → chunk-CK7AV2UJ.js} +147 -101
- package/dist/chunk-CK7AV2UJ.js.map +1 -0
- package/dist/chunk-G6GFQDVN.js +7 -0
- package/dist/chunk-G6GFQDVN.js.map +1 -0
- package/dist/{chunk-LZJHHZQ2.js → chunk-HBSWJC3B.js} +643 -553
- package/dist/chunk-HBSWJC3B.js.map +1 -0
- package/dist/chunk-HQESINXH.js +834 -0
- package/dist/chunk-HQESINXH.js.map +1 -0
- package/dist/{chunk-KYEZRYO6.js → chunk-J5SQLKNP.js} +145 -119
- package/dist/{chunk-KYEZRYO6.js.map → chunk-J5SQLKNP.js.map} +1 -1
- package/dist/{chunk-V5G7X53Y.js → chunk-NJQHUUTN.js} +2 -2
- package/dist/{chunk-W4QZPCNC.js → chunk-RSVRS5AK.js} +59 -58
- package/dist/chunk-RSVRS5AK.js.map +1 -0
- package/dist/{chunk-5SJS36BI.js → chunk-TWPXES3S.js} +642 -673
- package/dist/chunk-TWPXES3S.js.map +1 -0
- package/dist/{chunk-NA2N2WSG.js → chunk-VAE6HBKR.js} +176 -152
- package/dist/{chunk-NA2N2WSG.js.map → chunk-VAE6HBKR.js.map} +1 -1
- package/dist/{chunk-MJVPNN7W.js → chunk-ZII6M3SN.js} +2 -2
- package/dist/computed-item.types.d-BKZdSLLJ.d.ts +19 -0
- package/dist/computed.types.d-DpKIYO6e.d.ts +44 -0
- package/dist/config.context.d-BvU9r-Mg.d.ts +91 -0
- package/dist/corrections.d.ts +415 -1
- package/dist/corrections.js +8 -9
- package/dist/elements.d.ts +393 -1
- package/dist/elements.js +4 -5
- package/dist/index.d.ts +27 -9
- package/dist/index.js +21 -14
- package/dist/interaction.d-CJiMv8H7.d.ts +126 -0
- package/dist/interaction.interface.d-CvjHM2bi.d.ts +46 -0
- package/dist/interactions.d.ts +281 -1
- package/dist/interactions.js +4 -5
- package/dist/item.css +588 -214
- package/dist/item.d.ts +92 -1
- package/dist/item.js +5 -5
- package/dist/item.types.d-QU7LljEK.d.ts +82 -0
- package/dist/loader.d.ts +22 -1
- package/dist/processing.d.ts +730 -1
- package/dist/processing.js +2 -2
- package/dist/qti-components-jsx.d.ts +854 -844
- package/dist/qti-components-jsx.js +1 -0
- package/dist/qti-condition-expression.d-aMvBvpc6.d.ts +8 -0
- package/dist/qti-expression.d-BietT_8b.d.ts +31 -0
- package/dist/qti-feedback.d-DZbad0RN.d.ts +21 -0
- package/dist/qti-rule-base.d-ajOnfGXY.d.ts +16 -0
- package/dist/qti-test.d-_YAlhDbt.d.ts +702 -0
- package/dist/qti-text-entry-interaction.d-BGdfV9qG.d.ts +1567 -0
- package/dist/qti-transform-test.d-BL7GGFJj.d.ts +70 -0
- package/dist/qti.context.d-CejJMlfZ.d.ts +50 -0
- package/dist/response.d-_8y4kjGP.d.ts +106 -0
- package/dist/test.d.ts +32 -1
- package/dist/test.js +14 -7
- package/dist/transformers.d.ts +18 -1
- package/package.json +15 -11
- package/dist/chunk-5QYII4OZ.js.map +0 -1
- package/dist/chunk-5SJS36BI.js.map +0 -1
- package/dist/chunk-64XSIBGO.js +0 -241
- package/dist/chunk-64XSIBGO.js.map +0 -1
- package/dist/chunk-H3J7LFRO.js +0 -2243
- package/dist/chunk-H3J7LFRO.js.map +0 -1
- package/dist/chunk-LZJHHZQ2.js.map +0 -1
- package/dist/chunk-W4QZPCNC.js.map +0 -1
- package/dist/chunk-WCQ26LV7.js +0 -102
- package/dist/chunk-WCQ26LV7.js.map +0 -1
- package/dist/chunk-X3E5HXG2.js +0 -20
- package/dist/chunk-X3E5HXG2.js.map +0 -1
- /package/dist/{chunk-MGF5F3S2.js.map → chunk-BQFWCZFH.js.map} +0 -0
- /package/dist/{chunk-V5G7X53Y.js.map → chunk-NJQHUUTN.js.map} +0 -0
- /package/dist/{chunk-MJVPNN7W.js.map → chunk-ZII6M3SN.js.map} +0 -0
|
@@ -0,0 +1,834 @@
|
|
|
1
|
+
// ../qti-base/dist/context/computed-item.context.js
|
|
2
|
+
import { createContext } from "@lit/context";
|
|
3
|
+
var computedItemContext = createContext(/* @__PURE__ */ Symbol("computedItemContext"));
|
|
4
|
+
|
|
5
|
+
// ../qti-base/dist/context/computed.context.js
|
|
6
|
+
import { createContext as createContext2 } from "@lit/context";
|
|
7
|
+
var computedContext = createContext2(/* @__PURE__ */ Symbol("computedContext"));
|
|
8
|
+
|
|
9
|
+
// ../qti-base/dist/context/config.context.js
|
|
10
|
+
import { createContext as createContext3 } from "@lit/context";
|
|
11
|
+
var configContext = createContext3(/* @__PURE__ */ Symbol("configContext"));
|
|
12
|
+
|
|
13
|
+
// ../qti-base/dist/context/interaction.context.js
|
|
14
|
+
import { createContext as createContext4 } from "@lit/context";
|
|
15
|
+
var interactionContext = createContext4(/* @__PURE__ */ Symbol("interactionContext"));
|
|
16
|
+
|
|
17
|
+
// ../qti-base/dist/context/item.context.js
|
|
18
|
+
import { createContext as createContext5 } from "@lit/context";
|
|
19
|
+
var itemContext = createContext5(/* @__PURE__ */ Symbol("item"));
|
|
20
|
+
|
|
21
|
+
// ../qti-base/dist/context/types/item.types.js
|
|
22
|
+
var itemContextVariables = [
|
|
23
|
+
{
|
|
24
|
+
identifier: "completionStatus",
|
|
25
|
+
cardinality: "single",
|
|
26
|
+
baseType: "string",
|
|
27
|
+
value: "unknown",
|
|
28
|
+
type: "outcome"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
identifier: "numAttempts",
|
|
32
|
+
cardinality: "single",
|
|
33
|
+
baseType: "integer",
|
|
34
|
+
value: "0",
|
|
35
|
+
type: "response"
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// ../qti-base/dist/context/qti.context.js
|
|
40
|
+
import { createContext as createContext6 } from "@lit/context";
|
|
41
|
+
var SEED_PATTERN = /^[A-Za-z0-9-]+$/;
|
|
42
|
+
var isSeed = (value) => typeof value === "string" && SEED_PATTERN.test(value);
|
|
43
|
+
var asSeed = (value) => isSeed(value) ? value : void 0;
|
|
44
|
+
var qtiContext = createContext6(/* @__PURE__ */ Symbol("qtiContext"));
|
|
45
|
+
|
|
46
|
+
// ../qti-base/dist/context/session.context.js
|
|
47
|
+
import { createContext as createContext7 } from "@lit/context";
|
|
48
|
+
var INITIAL_SESSION_CONTEXT = { view: "candidate" };
|
|
49
|
+
var sessionContext = createContext7(/* @__PURE__ */ Symbol("testContext"));
|
|
50
|
+
|
|
51
|
+
// ../qti-base/dist/context/test.context.js
|
|
52
|
+
import { createContext as createContext8 } from "@lit/context";
|
|
53
|
+
var INITIAL_TEST_CONTEXT = { items: [], testOutcomeVariables: [] };
|
|
54
|
+
var testContext = createContext8(/* @__PURE__ */ Symbol("testContext"));
|
|
55
|
+
|
|
56
|
+
// ../qti-base/dist/styles/box-sizing.styles.js
|
|
57
|
+
import { css } from "lit";
|
|
58
|
+
var boxSizing = css`
|
|
59
|
+
:host {
|
|
60
|
+
box-sizing: border-box;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
*,
|
|
64
|
+
*::before,
|
|
65
|
+
*::after {
|
|
66
|
+
box-sizing: inherit;
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
// ../qti-base/dist/styles/drop-region.styles.js
|
|
71
|
+
import { css as css2 } from "lit";
|
|
72
|
+
var dropRegion = css2`
|
|
73
|
+
[part~='drop'] {
|
|
74
|
+
/*
|
|
75
|
+
* The one deliberate opt-out from the border-box reset.
|
|
76
|
+
*
|
|
77
|
+
* --qti-dropzone-min-* is the border-box of the largest chip, and what has to hold that chip is
|
|
78
|
+
* this region's *content* area. Under border-box a theme's dashed drop border is subtracted
|
|
79
|
+
* from the chip's own size, the content comes up short, and the drop grows the moment a chip
|
|
80
|
+
* lands in it. Order's drop did exactly that: 64px empty, 66px full, for a 1px border.
|
|
81
|
+
*/
|
|
82
|
+
box-sizing: content-box;
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* No padding, and no token for one.
|
|
86
|
+
*
|
|
87
|
+
* A drop reserves --qti-dropzone-min-*, which is the chip's BORDER-box, as this region's CONTENT
|
|
88
|
+
* area — so the chip already fits exactly, with nothing to spare and nothing squeezed. An inset
|
|
89
|
+
* on top would only make the drop bigger than the thing it holds.
|
|
90
|
+
*
|
|
91
|
+
* There was a 1px one, to make the drop read as a frame a hair outside the chip. It never painted:
|
|
92
|
+
* an EMPTY slot has nothing inside the inset to separate from, and a FILLED one hides its edge
|
|
93
|
+
* (DROP-SIZING.md §4), so both states spent 2px on an invisible ring. The one drop that genuinely
|
|
94
|
+
* wants breathing room — match's category card — declares padding on its own rule, which a
|
|
95
|
+
* theme reaches with ::part(drop). A token in between bought nothing.
|
|
96
|
+
*/
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-wrap: wrap;
|
|
99
|
+
align-items: flex-start;
|
|
100
|
+
justify-content: flex-start;
|
|
101
|
+
/* No gap either: 0 is the flex initial value, so the declaration only existed to host a token.
|
|
102
|
+
A drop that wants space between chips sets gap on its own rule. */
|
|
103
|
+
/* Containing block for anything a theme draws over the drop. Was 'position: relative' in the
|
|
104
|
+
theme's 'drop' mixin, which put a document stylesheet in charge of a shadow node's position. */
|
|
105
|
+
position: relative;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
[part~='drop'] > * {
|
|
109
|
+
flex: 0 1 auto;
|
|
110
|
+
align-self: flex-start;
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
// ../qti-base/dist/styles/validation-message.styles.js
|
|
115
|
+
import { css as css3 } from "lit";
|
|
116
|
+
var validationMessage = css3`
|
|
117
|
+
[part~='message'] {
|
|
118
|
+
display: none;
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
121
|
+
|
|
122
|
+
// ../qti-base/dist/abstract/interaction.js
|
|
123
|
+
import { consume, provide } from "@lit/context";
|
|
124
|
+
import { LitElement } from "lit";
|
|
125
|
+
import { property } from "lit/decorators.js";
|
|
126
|
+
var __decorate = function(decorators, target, key, desc) {
|
|
127
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
128
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
129
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
130
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
131
|
+
};
|
|
132
|
+
var Interaction = class extends LitElement {
|
|
133
|
+
#didLogDisableAfterIfMaxChoicesReachedDeprecation;
|
|
134
|
+
static {
|
|
135
|
+
this.formAssociated = true;
|
|
136
|
+
}
|
|
137
|
+
get internals() {
|
|
138
|
+
return this._internals;
|
|
139
|
+
}
|
|
140
|
+
/** Extension point used by wrappers that should not register as candidate inputs. */
|
|
141
|
+
get registersWithItem() {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
get isInline() {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
get responseVariable() {
|
|
148
|
+
if (!this._context?.variables) {
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
const responseVariables = this._context.variables.filter((v) => v.type === "response");
|
|
152
|
+
const responseIdentifier = this.getAttribute("response-identifier");
|
|
153
|
+
return responseVariables.find((v) => v.identifier === responseIdentifier);
|
|
154
|
+
}
|
|
155
|
+
get value() {
|
|
156
|
+
return JSON.stringify(this.response);
|
|
157
|
+
}
|
|
158
|
+
set value(val) {
|
|
159
|
+
this.response = val ? JSON.parse(val) : null;
|
|
160
|
+
}
|
|
161
|
+
reportValidity() {
|
|
162
|
+
const isValid = this._internals.validity.valid;
|
|
163
|
+
const mode = this.validationDisplayMode;
|
|
164
|
+
if (mode === "native" || mode === "both") {
|
|
165
|
+
this._internals.reportValidity();
|
|
166
|
+
}
|
|
167
|
+
if (mode === "inline" || mode === "both") {
|
|
168
|
+
this.updateInlineValidationMessage();
|
|
169
|
+
} else {
|
|
170
|
+
this.clearInlineValidationMessage();
|
|
171
|
+
}
|
|
172
|
+
if (mode === "none") {
|
|
173
|
+
this.clearInlineValidationMessage();
|
|
174
|
+
}
|
|
175
|
+
return isValid;
|
|
176
|
+
}
|
|
177
|
+
get validationDisplayMode() {
|
|
178
|
+
return this.configContext?.validationDisplayMode ?? "inline";
|
|
179
|
+
}
|
|
180
|
+
resolveAllowReorder(options) {
|
|
181
|
+
const defaultWhenUnset = options?.defaultWhenUnset ?? true;
|
|
182
|
+
const config = this.configContext;
|
|
183
|
+
if (!config) {
|
|
184
|
+
return defaultWhenUnset;
|
|
185
|
+
}
|
|
186
|
+
if (config.allowReorder !== void 0) {
|
|
187
|
+
return config.allowReorder;
|
|
188
|
+
}
|
|
189
|
+
return defaultWhenUnset;
|
|
190
|
+
}
|
|
191
|
+
resolveDisableAfterMaxReached(options) {
|
|
192
|
+
const defaultWhenUnset = options?.defaultWhenUnset ?? false;
|
|
193
|
+
const config = this.configContext;
|
|
194
|
+
if (!config) {
|
|
195
|
+
return defaultWhenUnset;
|
|
196
|
+
}
|
|
197
|
+
if (config.disableAfterMaxReached !== void 0) {
|
|
198
|
+
return config.disableAfterMaxReached;
|
|
199
|
+
}
|
|
200
|
+
if (config.disableAfterIfMaxChoicesReached !== void 0) {
|
|
201
|
+
if (!this.#didLogDisableAfterIfMaxChoicesReachedDeprecation) {
|
|
202
|
+
this.#didLogDisableAfterIfMaxChoicesReachedDeprecation = true;
|
|
203
|
+
console.log("[QTI Config] `disableAfterIfMaxChoicesReached` is deprecated. Use `disableAfterMaxReached` instead.");
|
|
204
|
+
}
|
|
205
|
+
return config.disableAfterIfMaxChoicesReached;
|
|
206
|
+
}
|
|
207
|
+
return defaultWhenUnset;
|
|
208
|
+
}
|
|
209
|
+
setInteractionValidity(isValid, validityMessage = "", anchor, options) {
|
|
210
|
+
const validityAnchor = anchor ?? this;
|
|
211
|
+
this._internals.setValidity(isValid ? {} : { customError: true }, validityMessage, validityAnchor);
|
|
212
|
+
if (options?.suppressInline !== true && (this.validationDisplayMode === "inline" || this.validationDisplayMode === "both")) {
|
|
213
|
+
this.updateInlineValidationMessage();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
updateInlineValidationMessage() {
|
|
217
|
+
const validationMessageElement = this.getValidationMessageElement();
|
|
218
|
+
if (!validationMessageElement) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (!this._internals.validity.valid) {
|
|
222
|
+
validationMessageElement.textContent = this._internals.validationMessage;
|
|
223
|
+
validationMessageElement.style.setProperty("display", "block", "important");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
validationMessageElement.textContent = "";
|
|
227
|
+
validationMessageElement.style.display = "none";
|
|
228
|
+
}
|
|
229
|
+
clearInlineValidationMessage() {
|
|
230
|
+
const validationMessageElement = this.getValidationMessageElement();
|
|
231
|
+
if (!validationMessageElement) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
validationMessageElement.textContent = "";
|
|
235
|
+
validationMessageElement.style.display = "none";
|
|
236
|
+
}
|
|
237
|
+
getValidationMessageElement() {
|
|
238
|
+
return this.shadowRoot?.querySelector("#validation-message");
|
|
239
|
+
}
|
|
240
|
+
reset() {
|
|
241
|
+
this.response = null;
|
|
242
|
+
}
|
|
243
|
+
formResetCallback() {
|
|
244
|
+
this.reset();
|
|
245
|
+
}
|
|
246
|
+
connectedCallback() {
|
|
247
|
+
super.connectedCallback();
|
|
248
|
+
if (!this.registersWithItem) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
this.dispatchEvent(new CustomEvent("qti-register-interaction", {
|
|
252
|
+
bubbles: true,
|
|
253
|
+
composed: true,
|
|
254
|
+
cancelable: false,
|
|
255
|
+
detail: {
|
|
256
|
+
interactionElement: this,
|
|
257
|
+
responseIdentifier: this.responseIdentifier
|
|
258
|
+
}
|
|
259
|
+
}));
|
|
260
|
+
}
|
|
261
|
+
saveResponse(value, state3) {
|
|
262
|
+
this.dispatchEvent(new CustomEvent("qti-interaction-response", {
|
|
263
|
+
bubbles: true,
|
|
264
|
+
composed: true,
|
|
265
|
+
cancelable: false,
|
|
266
|
+
detail: {
|
|
267
|
+
responseIdentifier: this.responseIdentifier,
|
|
268
|
+
response: Array.isArray(value) ? [...value] : value,
|
|
269
|
+
...state3 !== void 0 ? { state: state3 } : {}
|
|
270
|
+
}
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
constructor() {
|
|
274
|
+
super();
|
|
275
|
+
this.#didLogDisableAfterIfMaxChoicesReachedDeprecation = false;
|
|
276
|
+
this._interactionContext = { choiceRole: null, draggablesSelector: null };
|
|
277
|
+
this.disabled = false;
|
|
278
|
+
this.readonly = false;
|
|
279
|
+
this._internals = this.attachInternals();
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Optional lifecycle bridge for interaction subclasses that do not need changed-property data.
|
|
283
|
+
*
|
|
284
|
+
* The parameter is `PropertyValues`, matching LitElement, and NOT `PropertyValues<this>`.
|
|
285
|
+
* The polymorphic `this` narrowed the parameter per subclass, which made every interaction
|
|
286
|
+
* class structurally incompatible with `LitElement` — so `Constructor<LitElement>`, the
|
|
287
|
+
* standard constraint for a Lit mixin, rejected all of them and consumers could not wrap an
|
|
288
|
+
* interaction in a mixin without casting. `this` buys nothing in a parameter position and
|
|
289
|
+
* costs contravariant compatibility with the base class.
|
|
290
|
+
*
|
|
291
|
+
* Still optional, so subclasses that ignore the argument can override with `firstUpdated()`.
|
|
292
|
+
*/
|
|
293
|
+
firstUpdated(_changedProperties) {
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
__decorate([
|
|
297
|
+
consume({ context: itemContext, subscribe: true })
|
|
298
|
+
], Interaction.prototype, "_context", void 0);
|
|
299
|
+
__decorate([
|
|
300
|
+
consume({ context: configContext, subscribe: true })
|
|
301
|
+
], Interaction.prototype, "configContext", void 0);
|
|
302
|
+
__decorate([
|
|
303
|
+
provide({ context: interactionContext })
|
|
304
|
+
], Interaction.prototype, "_interactionContext", void 0);
|
|
305
|
+
__decorate([
|
|
306
|
+
property({ type: String, attribute: "response-identifier" })
|
|
307
|
+
], Interaction.prototype, "responseIdentifier", void 0);
|
|
308
|
+
__decorate([
|
|
309
|
+
property({ reflect: true, type: Boolean })
|
|
310
|
+
], Interaction.prototype, "disabled", void 0);
|
|
311
|
+
__decorate([
|
|
312
|
+
property({ reflect: true, type: Boolean })
|
|
313
|
+
], Interaction.prototype, "readonly", void 0);
|
|
314
|
+
__decorate([
|
|
315
|
+
property({ type: String })
|
|
316
|
+
], Interaction.prototype, "name", void 0);
|
|
317
|
+
|
|
318
|
+
// ../qti-base/dist/abstract/qti-variable-declaration.js
|
|
319
|
+
import { html, LitElement as LitElement2 } from "lit";
|
|
320
|
+
var QtiVariableDeclaration = class extends LitElement2 {
|
|
321
|
+
render() {
|
|
322
|
+
return html`<slot></slot>`;
|
|
323
|
+
}
|
|
324
|
+
defaultValues(cardinality) {
|
|
325
|
+
const htmlValues = Array.from(this.querySelectorAll("qti-default-value > qti-value"));
|
|
326
|
+
if (htmlValues.length === 0) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const defaultValues = htmlValues.map((n) => n.innerHTML.trim());
|
|
330
|
+
if (defaultValues.length > 1 || cardinality === "multiple" || cardinality === "ordered") {
|
|
331
|
+
return defaultValues;
|
|
332
|
+
}
|
|
333
|
+
return defaultValues[0];
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// ../qti-base/dist/abstract/qti-expression.js
|
|
338
|
+
import { consume as consume2 } from "@lit/context";
|
|
339
|
+
import { css as css4, html as html2, LitElement as LitElement3 } from "lit";
|
|
340
|
+
import { state } from "lit/decorators.js";
|
|
341
|
+
var __decorate2 = function(decorators, target, key, desc) {
|
|
342
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
343
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
344
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
345
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
346
|
+
};
|
|
347
|
+
var QtiExpression = class extends LitElement3 {
|
|
348
|
+
constructor() {
|
|
349
|
+
super(...arguments);
|
|
350
|
+
this.getVariables = () => (
|
|
351
|
+
// FIXME: if this itself is multiple, this will never enter the qti-multiple switch
|
|
352
|
+
// See this example here: https://github.com/1EdTech/qti-examples/blob/master/qtiv3-examples/packaging/items/Example05-feedbackBlock-adaptive.xml
|
|
353
|
+
Array.from(this.children).map((e) => {
|
|
354
|
+
console.debug("getVariables", e.tagName.toLowerCase());
|
|
355
|
+
switch (e.tagName.toLowerCase()) {
|
|
356
|
+
case "qti-base-value": {
|
|
357
|
+
return {
|
|
358
|
+
baseType: e.getAttribute("base-type"),
|
|
359
|
+
value: e.textContent.trim(),
|
|
360
|
+
cardinality: "single"
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
case "qti-variable": {
|
|
364
|
+
const identifier = e.getAttribute("identifier") || "";
|
|
365
|
+
if (identifier === "QTI_CONTEXT") {
|
|
366
|
+
if (!this.qtiContext?.QTI_CONTEXT) {
|
|
367
|
+
console.warn("QTI_CONTEXT not available");
|
|
368
|
+
return {
|
|
369
|
+
identifier: "QTI_CONTEXT",
|
|
370
|
+
baseType: "record",
|
|
371
|
+
value: this.qtiContext.QTI_CONTEXT,
|
|
372
|
+
cardinality: "record",
|
|
373
|
+
type: "context"
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
identifier: "QTI_CONTEXT",
|
|
378
|
+
baseType: "record",
|
|
379
|
+
value: this.qtiContext.QTI_CONTEXT,
|
|
380
|
+
cardinality: "record",
|
|
381
|
+
type: "context"
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const variable = this.context.variables.find((v) => v.identifier === identifier) || null;
|
|
385
|
+
return variable;
|
|
386
|
+
}
|
|
387
|
+
case "qti-multiple": {
|
|
388
|
+
const multiple = e;
|
|
389
|
+
const values = multiple.getResult();
|
|
390
|
+
console.debug("values", values);
|
|
391
|
+
if (values?.length > 0) {
|
|
392
|
+
return {
|
|
393
|
+
identifier: "",
|
|
394
|
+
baseType: values[0].baseType,
|
|
395
|
+
value: values.map((v) => v.value),
|
|
396
|
+
cardinality: "multiple",
|
|
397
|
+
type: "response"
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
case "qti-ordered": {
|
|
403
|
+
const multiple = e;
|
|
404
|
+
const values = multiple.getResult();
|
|
405
|
+
if (values?.length > 0) {
|
|
406
|
+
return {
|
|
407
|
+
identifier: "",
|
|
408
|
+
baseType: values[0].baseType,
|
|
409
|
+
value: values.map((v) => v.value),
|
|
410
|
+
cardinality: "ordered",
|
|
411
|
+
type: "response"
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
case "qti-repeat": {
|
|
417
|
+
const repeat = e;
|
|
418
|
+
const values = repeat.getResult();
|
|
419
|
+
if (values?.length > 0) {
|
|
420
|
+
return values;
|
|
421
|
+
}
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
case "qti-correct": {
|
|
425
|
+
const identifier = e.getAttribute("identifier") || "";
|
|
426
|
+
const responseVariable = this.context?.variables?.find((v) => v.identifier === identifier) || null;
|
|
427
|
+
return {
|
|
428
|
+
baseType: responseVariable.baseType,
|
|
429
|
+
value: responseVariable.correctResponse,
|
|
430
|
+
cardinality: responseVariable.cardinality
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
default: {
|
|
434
|
+
try {
|
|
435
|
+
const expression = e;
|
|
436
|
+
const value = expression.getResult();
|
|
437
|
+
return {
|
|
438
|
+
baseType: "integer",
|
|
439
|
+
value: value?.toString() || null,
|
|
440
|
+
cardinality: "single"
|
|
441
|
+
};
|
|
442
|
+
} catch (error) {
|
|
443
|
+
console.warn("default not sufficient");
|
|
444
|
+
}
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}).flatMap((v) => Array.isArray(v) ? v : [v]).filter((v) => v !== null)
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
static {
|
|
452
|
+
this.styles = css4`
|
|
453
|
+
slot {
|
|
454
|
+
display: none;
|
|
455
|
+
}
|
|
456
|
+
`;
|
|
457
|
+
}
|
|
458
|
+
render() {
|
|
459
|
+
return html2`<pre>${JSON.stringify(this.result, null, 2)}</pre>
|
|
460
|
+
<slot></slot>`;
|
|
461
|
+
}
|
|
462
|
+
calculate() {
|
|
463
|
+
this.result = this.getResult();
|
|
464
|
+
return this.result;
|
|
465
|
+
}
|
|
466
|
+
getResult() {
|
|
467
|
+
throw new Error("Not implemented");
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
__decorate2([
|
|
471
|
+
state()
|
|
472
|
+
], QtiExpression.prototype, "result", void 0);
|
|
473
|
+
__decorate2([
|
|
474
|
+
consume2({ context: itemContext, subscribe: true }),
|
|
475
|
+
state()
|
|
476
|
+
], QtiExpression.prototype, "context", void 0);
|
|
477
|
+
__decorate2([
|
|
478
|
+
consume2({ context: qtiContext, subscribe: true }),
|
|
479
|
+
state()
|
|
480
|
+
], QtiExpression.prototype, "qtiContext", void 0);
|
|
481
|
+
|
|
482
|
+
// ../qti-base/dist/abstract/qti-condition-expression.js
|
|
483
|
+
var QtiConditionExpression = class extends QtiExpression {
|
|
484
|
+
calculate() {
|
|
485
|
+
this.result = this.getResult();
|
|
486
|
+
return this.result;
|
|
487
|
+
}
|
|
488
|
+
getResult() {
|
|
489
|
+
throw new Error("Not implemented");
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// ../qti-base/dist/utils/utils.js
|
|
494
|
+
var decimalSeparator = () => {
|
|
495
|
+
return new Intl.NumberFormat().format(0.1).replace(/\d/g, "");
|
|
496
|
+
};
|
|
497
|
+
var convertNumberToUniversalFormat = (number) => {
|
|
498
|
+
if (typeof number === "string") {
|
|
499
|
+
return number;
|
|
500
|
+
}
|
|
501
|
+
const dSep = decimalSeparator();
|
|
502
|
+
if (dSep === ".") {
|
|
503
|
+
return number.toLocaleString();
|
|
504
|
+
} else {
|
|
505
|
+
return number.toString().replace(".", "").replace(dSep, ".");
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
function IsNullOrUndefined(value) {
|
|
509
|
+
return value === null || value === void 0;
|
|
510
|
+
}
|
|
511
|
+
function removeDoubleSlashes(str) {
|
|
512
|
+
const singleForwardSlashes = str.replace(/([^:]\/)\/+/g, "$1").replace(/\/\//g, "/").replace("http:/", "http://").replace("https:/", "https://");
|
|
513
|
+
return singleForwardSlashes;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// ../qti-base/dist/abstract/qti-feedback.js
|
|
517
|
+
import { consume as consume3 } from "@lit/context";
|
|
518
|
+
import { LitElement as LitElement4 } from "lit";
|
|
519
|
+
import { property as property2, state as state2 } from "lit/decorators.js";
|
|
520
|
+
var __decorate3 = function(decorators, target, key, desc) {
|
|
521
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
522
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
523
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
524
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
525
|
+
};
|
|
526
|
+
var QtiFeedback = class extends LitElement4 {
|
|
527
|
+
constructor() {
|
|
528
|
+
super(...arguments);
|
|
529
|
+
this.showHide = "show";
|
|
530
|
+
}
|
|
531
|
+
connectedCallback() {
|
|
532
|
+
super.connectedCallback();
|
|
533
|
+
this.dispatchEvent(new CustomEvent("qti-register-feedback", {
|
|
534
|
+
bubbles: true,
|
|
535
|
+
composed: true,
|
|
536
|
+
detail: this
|
|
537
|
+
}));
|
|
538
|
+
}
|
|
539
|
+
checkShowFeedback(outcomeIdentifier) {
|
|
540
|
+
const outcomeVariable = this._context.variables.find((v) => v.identifier === outcomeIdentifier) || null;
|
|
541
|
+
if (this.outcomeIdentifier !== outcomeIdentifier || !outcomeVariable)
|
|
542
|
+
return;
|
|
543
|
+
let isFound = false;
|
|
544
|
+
if (Array.isArray(outcomeVariable.value)) {
|
|
545
|
+
isFound = outcomeVariable.value.includes(this.identifier);
|
|
546
|
+
} else {
|
|
547
|
+
isFound = !IsNullOrUndefined(this.identifier) && !IsNullOrUndefined(outcomeVariable?.value) && this.identifier === outcomeVariable.value || false;
|
|
548
|
+
}
|
|
549
|
+
this.#showFeedback(isFound);
|
|
550
|
+
}
|
|
551
|
+
#showFeedback(value) {
|
|
552
|
+
this.showStatus = value && this.showHide === "show" || !value && this.showHide === "hide" ? "on" : "off";
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
__decorate3([
|
|
556
|
+
property2({ type: String, attribute: "show-hide" })
|
|
557
|
+
], QtiFeedback.prototype, "showHide", void 0);
|
|
558
|
+
__decorate3([
|
|
559
|
+
property2({ type: String, attribute: "outcome-identifier" })
|
|
560
|
+
], QtiFeedback.prototype, "outcomeIdentifier", void 0);
|
|
561
|
+
__decorate3([
|
|
562
|
+
property2({ type: String })
|
|
563
|
+
], QtiFeedback.prototype, "identifier", void 0);
|
|
564
|
+
__decorate3([
|
|
565
|
+
property2({ type: String, attribute: false })
|
|
566
|
+
], QtiFeedback.prototype, "showStatus", void 0);
|
|
567
|
+
__decorate3([
|
|
568
|
+
consume3({ context: itemContext, subscribe: true }),
|
|
569
|
+
state2()
|
|
570
|
+
], QtiFeedback.prototype, "_context", void 0);
|
|
571
|
+
|
|
572
|
+
// ../qti-base/dist/lib/response.js
|
|
573
|
+
function parseResponseAttribute(raw) {
|
|
574
|
+
if (raw == null)
|
|
575
|
+
return null;
|
|
576
|
+
if (!raw.includes(",")) {
|
|
577
|
+
const trimmed = raw.trim();
|
|
578
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
579
|
+
}
|
|
580
|
+
const tokens = raw.split(",").map((token) => token.trim()).filter((token) => token.length > 0);
|
|
581
|
+
if (tokens.length === 0)
|
|
582
|
+
return null;
|
|
583
|
+
if (tokens.length === 1)
|
|
584
|
+
return tokens[0];
|
|
585
|
+
return tokens;
|
|
586
|
+
}
|
|
587
|
+
function serializeResponseAttribute(value) {
|
|
588
|
+
if (value == null)
|
|
589
|
+
return null;
|
|
590
|
+
if (Array.isArray(value)) {
|
|
591
|
+
const tokens = value.map((token) => token.trim()).filter((token) => token.length > 0);
|
|
592
|
+
return tokens.length > 0 ? tokens.join(",") : null;
|
|
593
|
+
}
|
|
594
|
+
const trimmed = value.trim();
|
|
595
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
596
|
+
}
|
|
597
|
+
function* iterResponseValues(raw) {
|
|
598
|
+
if (raw == null)
|
|
599
|
+
return;
|
|
600
|
+
if (Array.isArray(raw)) {
|
|
601
|
+
for (const v of raw) {
|
|
602
|
+
const t = v.trim();
|
|
603
|
+
if (t)
|
|
604
|
+
yield t;
|
|
605
|
+
}
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
if (!raw.includes(",")) {
|
|
609
|
+
const t = raw.trim();
|
|
610
|
+
if (t)
|
|
611
|
+
yield t;
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
for (const v of raw.split(",")) {
|
|
615
|
+
const t = v.trim();
|
|
616
|
+
if (t)
|
|
617
|
+
yield t;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
function parsePair(value) {
|
|
621
|
+
const [source, target, ...rest] = value.trim().split(/\s+/);
|
|
622
|
+
if (!source || !target || rest.length > 0) {
|
|
623
|
+
throw new Error(`malformed directed-pair value: "${value}" (expected "source target")`);
|
|
624
|
+
}
|
|
625
|
+
return { source, target };
|
|
626
|
+
}
|
|
627
|
+
function serializePair(source, target) {
|
|
628
|
+
return `${source} ${target}`;
|
|
629
|
+
}
|
|
630
|
+
function parsePoint(value) {
|
|
631
|
+
const [xStr, yStr, ...rest] = value.trim().split(/\s+/);
|
|
632
|
+
const x = Number(xStr);
|
|
633
|
+
const y = Number(yStr);
|
|
634
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || rest.length > 0) {
|
|
635
|
+
throw new Error(`malformed point value: "${value}" (expected "x y" numeric coords)`);
|
|
636
|
+
}
|
|
637
|
+
return { x, y };
|
|
638
|
+
}
|
|
639
|
+
function serializePoint(x, y) {
|
|
640
|
+
return `${x} ${y}`;
|
|
641
|
+
}
|
|
642
|
+
function responseAttributeConverter(opts) {
|
|
643
|
+
const { emptyAs } = opts;
|
|
644
|
+
const isEmptySentinel = (value) => value === emptyAs || value == null || value === "" || Array.isArray(value) && value.length === 0;
|
|
645
|
+
return {
|
|
646
|
+
fromAttribute: (value) => {
|
|
647
|
+
const parsed = parseResponseAttribute(value);
|
|
648
|
+
return parsed === null ? emptyAs : parsed;
|
|
649
|
+
},
|
|
650
|
+
toAttribute: (value) => {
|
|
651
|
+
if (isEmptySentinel(value))
|
|
652
|
+
return null;
|
|
653
|
+
return serializeResponseAttribute(value);
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// ../qti-base/dist/lib/qti-rule-base.js
|
|
659
|
+
import { LitElement as LitElement5 } from "lit";
|
|
660
|
+
var QtiRuleElement = class extends LitElement5 {
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
// ../qti-base/dist/utils/scoring-helper.js
|
|
664
|
+
var ScoringHelper = class {
|
|
665
|
+
/**
|
|
666
|
+
* Checks if a given point is within a specified area.
|
|
667
|
+
* @param point The point to test, represented as a string "x y" (e.g., "102 113").
|
|
668
|
+
* @param areaKey The area definition, including shape and coordinates (e.g., "circle,102,113,16").
|
|
669
|
+
* @param baseType The base type of the response, must be "point" for this method to proceed.
|
|
670
|
+
* @returns True if the point is within the area; false otherwise.
|
|
671
|
+
*/
|
|
672
|
+
static isPointInArea(point, areaKey, baseType) {
|
|
673
|
+
if (baseType !== "point") {
|
|
674
|
+
console.warn(`Base type ${baseType} is not supported for point area mapping.`);
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
677
|
+
const [px, py] = point.split(" ").map(Number);
|
|
678
|
+
const [shape, ...coords] = areaKey.split(",");
|
|
679
|
+
const coordinates = coords.map(Number);
|
|
680
|
+
switch (shape.toLowerCase()) {
|
|
681
|
+
case "circle":
|
|
682
|
+
case "default": {
|
|
683
|
+
const [cx, cy, radius] = coordinates;
|
|
684
|
+
if (coordinates.length !== 3) {
|
|
685
|
+
console.warn(`Invalid circle definition: ${areaKey}`);
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
const distance = Math.sqrt((px - cx) ** 2 + (py - cy) ** 2);
|
|
689
|
+
return distance <= radius;
|
|
690
|
+
}
|
|
691
|
+
case "rect": {
|
|
692
|
+
const [x1, y1, x2, y2] = coordinates;
|
|
693
|
+
if (coordinates.length !== 4) {
|
|
694
|
+
console.warn(`Invalid rectangle definition: ${areaKey}`);
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
return px >= x1 && px <= x2 && py >= y1 && py <= y2;
|
|
698
|
+
}
|
|
699
|
+
case "ellipse": {
|
|
700
|
+
const [cx, cy, rx, ry] = coordinates;
|
|
701
|
+
if (coordinates.length !== 4) {
|
|
702
|
+
console.warn(`Invalid ellipse definition: ${areaKey}`);
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
const normalizedX = (px - cx) ** 2 / rx ** 2;
|
|
706
|
+
const normalizedY = (py - cy) ** 2 / ry ** 2;
|
|
707
|
+
return normalizedX + normalizedY <= 1;
|
|
708
|
+
}
|
|
709
|
+
case "poly": {
|
|
710
|
+
if (coordinates.length < 6 || coordinates.length % 2 !== 0) {
|
|
711
|
+
console.warn(`Invalid polygon definition: ${areaKey}`);
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
const vertices = [];
|
|
715
|
+
for (let i = 0; i < coordinates.length; i += 2) {
|
|
716
|
+
vertices.push({ x: coordinates[i], y: coordinates[i + 1] });
|
|
717
|
+
}
|
|
718
|
+
return this.isPointInPolygon({ x: px, y: py }, vertices);
|
|
719
|
+
}
|
|
720
|
+
default:
|
|
721
|
+
console.warn(`Unsupported shape type: ${shape}`);
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Checks if a point is inside a polygon using the ray-casting algorithm.
|
|
727
|
+
* @param point The point to test.
|
|
728
|
+
* @param vertices The vertices of the polygon in order (array of {x, y} objects).
|
|
729
|
+
* @returns True if the point is inside the polygon; false otherwise.
|
|
730
|
+
*/
|
|
731
|
+
static isPointInPolygon(point, vertices) {
|
|
732
|
+
let inside = false;
|
|
733
|
+
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
|
|
734
|
+
const xi = vertices[i].x, yi = vertices[i].y;
|
|
735
|
+
const xj = vertices[j].x, yj = vertices[j].y;
|
|
736
|
+
const intersect = yi > point.y !== yj > point.y && point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi;
|
|
737
|
+
if (intersect)
|
|
738
|
+
inside = !inside;
|
|
739
|
+
}
|
|
740
|
+
return inside;
|
|
741
|
+
}
|
|
742
|
+
static compareSingleValues(value1, value2, baseType) {
|
|
743
|
+
switch (baseType) {
|
|
744
|
+
case "identifier":
|
|
745
|
+
case "string":
|
|
746
|
+
return value1 === value2;
|
|
747
|
+
case "integer": {
|
|
748
|
+
const int1 = parseInt(value1, 10);
|
|
749
|
+
const int2 = parseInt(value2, 10);
|
|
750
|
+
if (!isNaN(int1) && !isNaN(int2)) {
|
|
751
|
+
return int1 === int2;
|
|
752
|
+
} else {
|
|
753
|
+
console.error(`Cannot convert ${value1} and/or ${value2} to int.`);
|
|
754
|
+
}
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
case "float": {
|
|
758
|
+
const float1 = parseFloat(value1);
|
|
759
|
+
const float2 = parseFloat(value2);
|
|
760
|
+
if (!isNaN(float1) && !isNaN(float2)) {
|
|
761
|
+
return float1 === float2;
|
|
762
|
+
} else {
|
|
763
|
+
console.error(`couldn't convert ${value1} and/or ${value2} to float.`);
|
|
764
|
+
}
|
|
765
|
+
break;
|
|
766
|
+
}
|
|
767
|
+
case "pair":
|
|
768
|
+
case "directedPair": {
|
|
769
|
+
const pair1 = value1.split(" ").sort();
|
|
770
|
+
const pair2 = value2.split(" ").sort();
|
|
771
|
+
if (pair1.length === 2 && pair2.length === 2) {
|
|
772
|
+
if (baseType === "pair") {
|
|
773
|
+
pair1.sort();
|
|
774
|
+
pair2.sort();
|
|
775
|
+
}
|
|
776
|
+
return pair1.join(" ") === pair2.join(" ");
|
|
777
|
+
} else {
|
|
778
|
+
console.error(`compared two pair but one of the values does not have 2 values: 1: ${value1} 2: ${value2}`);
|
|
779
|
+
}
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
// ../qti-base/dist/elements.js
|
|
788
|
+
var qtiBaseElements = [];
|
|
789
|
+
|
|
790
|
+
// ../qti-base/dist/register.js
|
|
791
|
+
for (const { tag, ctor } of qtiBaseElements) {
|
|
792
|
+
if (!customElements.get(tag)) {
|
|
793
|
+
customElements.define(tag, ctor);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
export {
|
|
798
|
+
computedItemContext,
|
|
799
|
+
computedContext,
|
|
800
|
+
configContext,
|
|
801
|
+
interactionContext,
|
|
802
|
+
itemContext,
|
|
803
|
+
itemContextVariables,
|
|
804
|
+
isSeed,
|
|
805
|
+
asSeed,
|
|
806
|
+
qtiContext,
|
|
807
|
+
INITIAL_SESSION_CONTEXT,
|
|
808
|
+
sessionContext,
|
|
809
|
+
INITIAL_TEST_CONTEXT,
|
|
810
|
+
testContext,
|
|
811
|
+
boxSizing,
|
|
812
|
+
dropRegion,
|
|
813
|
+
validationMessage,
|
|
814
|
+
Interaction,
|
|
815
|
+
QtiVariableDeclaration,
|
|
816
|
+
QtiExpression,
|
|
817
|
+
QtiConditionExpression,
|
|
818
|
+
decimalSeparator,
|
|
819
|
+
convertNumberToUniversalFormat,
|
|
820
|
+
IsNullOrUndefined,
|
|
821
|
+
removeDoubleSlashes,
|
|
822
|
+
QtiFeedback,
|
|
823
|
+
parseResponseAttribute,
|
|
824
|
+
serializeResponseAttribute,
|
|
825
|
+
iterResponseValues,
|
|
826
|
+
parsePair,
|
|
827
|
+
serializePair,
|
|
828
|
+
parsePoint,
|
|
829
|
+
serializePoint,
|
|
830
|
+
responseAttributeConverter,
|
|
831
|
+
QtiRuleElement,
|
|
832
|
+
ScoringHelper
|
|
833
|
+
};
|
|
834
|
+
//# sourceMappingURL=chunk-HQESINXH.js.map
|