@citolab/qti-components 8.0.1 → 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.
Files changed (60) hide show
  1. package/cdn/index.global.js +1 -1
  2. package/cdn/index.js +103 -103
  3. package/dist/base.d.ts +3 -3
  4. package/dist/base.js +1 -1
  5. package/dist/chunk-4DB4SC5K.js +100 -0
  6. package/dist/chunk-4DB4SC5K.js.map +1 -0
  7. package/dist/{chunk-WVVMNF74.js → chunk-7AVWRQIS.js} +188 -160
  8. package/dist/{chunk-WVVMNF74.js.map → chunk-7AVWRQIS.js.map} +1 -1
  9. package/dist/{chunk-CAO4JRLY.js → chunk-BQFWCZFH.js} +2 -2
  10. package/dist/{chunk-LVBIQDPM.js → chunk-CK7AV2UJ.js} +147 -101
  11. package/dist/chunk-CK7AV2UJ.js.map +1 -0
  12. package/dist/{chunk-7HC5SMCU.js → chunk-G6GFQDVN.js} +1 -96
  13. package/dist/chunk-G6GFQDVN.js.map +1 -0
  14. package/dist/{chunk-RXGDQDOV.js → chunk-HBSWJC3B.js} +478 -392
  15. package/dist/chunk-HBSWJC3B.js.map +1 -0
  16. package/dist/chunk-HQESINXH.js +834 -0
  17. package/dist/chunk-HQESINXH.js.map +1 -0
  18. package/dist/{chunk-XU7HNT4F.js → chunk-J5SQLKNP.js} +145 -119
  19. package/dist/{chunk-XU7HNT4F.js.map → chunk-J5SQLKNP.js.map} +1 -1
  20. package/dist/{chunk-V5G7X53Y.js → chunk-NJQHUUTN.js} +2 -2
  21. package/dist/{chunk-QECOPVPO.js → chunk-RSVRS5AK.js} +59 -58
  22. package/dist/chunk-RSVRS5AK.js.map +1 -0
  23. package/dist/{chunk-F4BNJWYN.js → chunk-TWPXES3S.js} +642 -673
  24. package/dist/chunk-TWPXES3S.js.map +1 -0
  25. package/dist/{chunk-NA2N2WSG.js → chunk-VAE6HBKR.js} +176 -152
  26. package/dist/{chunk-NA2N2WSG.js.map → chunk-VAE6HBKR.js.map} +1 -1
  27. package/dist/{chunk-3AJOQCDU.js → chunk-ZII6M3SN.js} +2 -2
  28. package/dist/{computed.types.d-rKLSPvVG.d.ts → computed.types.d-DpKIYO6e.d.ts} +2 -0
  29. package/dist/corrections.d.ts +12 -29
  30. package/dist/corrections.js +8 -9
  31. package/dist/elements.d.ts +86 -86
  32. package/dist/elements.js +4 -5
  33. package/dist/index.d.ts +6 -37
  34. package/dist/index.js +13 -14
  35. package/dist/{interaction.d-D4MstYRz.d.ts → interaction.d-CJiMv8H7.d.ts} +13 -2
  36. package/dist/interactions.d.ts +11 -1299
  37. package/dist/interactions.js +4 -5
  38. package/dist/item.d.ts +3 -3
  39. package/dist/item.js +5 -5
  40. package/dist/processing.js +2 -2
  41. package/dist/qti-components-jsx.d.ts +759 -739
  42. package/dist/qti-test.d-_YAlhDbt.d.ts +702 -0
  43. package/dist/qti-text-entry-interaction.d-BGdfV9qG.d.ts +1567 -0
  44. package/dist/test.d.ts +11 -678
  45. package/dist/test.js +6 -7
  46. package/package.json +8 -7
  47. package/dist/chunk-64XSIBGO.js +0 -241
  48. package/dist/chunk-64XSIBGO.js.map +0 -1
  49. package/dist/chunk-7HC5SMCU.js.map +0 -1
  50. package/dist/chunk-F4BNJWYN.js.map +0 -1
  51. package/dist/chunk-H3J7LFRO.js +0 -2243
  52. package/dist/chunk-H3J7LFRO.js.map +0 -1
  53. package/dist/chunk-LVBIQDPM.js.map +0 -1
  54. package/dist/chunk-QECOPVPO.js.map +0 -1
  55. package/dist/chunk-RXGDQDOV.js.map +0 -1
  56. package/dist/chunk-X3E5HXG2.js +0 -20
  57. package/dist/chunk-X3E5HXG2.js.map +0 -1
  58. /package/dist/{chunk-CAO4JRLY.js.map → chunk-BQFWCZFH.js.map} +0 -0
  59. /package/dist/{chunk-V5G7X53Y.js.map → chunk-NJQHUUTN.js.map} +0 -0
  60. /package/dist/{chunk-3AJOQCDU.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