@qti-components/elements 1.10.1 → 2.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/qti-assessment-item/qti-assessment-item.d.ts +10 -10
- package/dist/components/qti-assessment-item/qti-assessment-item.js +148 -94
- package/dist/components/qti-assessment-item/qti-assessment-item.js.map +1 -1
- package/dist/components/qti-custom-operator/qti-custom-operator.js +0 -10
- package/dist/components/qti-custom-operator/qti-custom-operator.js.map +1 -1
- package/dist/components/qti-feedback-block/qti-feedback-block.d.ts +3 -0
- package/dist/components/qti-feedback-block/qti-feedback-block.js +8 -0
- package/dist/components/qti-feedback-block/qti-feedback-block.js.map +1 -1
- package/dist/components/qti-feedback-inline/qti-feedback-inline.d.ts +3 -0
- package/dist/components/qti-feedback-inline/qti-feedback-inline.js +8 -0
- package/dist/components/qti-feedback-inline/qti-feedback-inline.js.map +1 -1
- package/dist/components/qti-modal-feedback/qti-modal-feedback.d.ts +3 -0
- package/dist/components/qti-modal-feedback/qti-modal-feedback.js +8 -0
- package/dist/components/qti-modal-feedback/qti-modal-feedback.js.map +1 -1
- package/dist/components/qti-response-processing/qti-response-processing.d.ts +17 -1
- package/dist/components/qti-response-processing/qti-response-processing.js +75 -4
- package/dist/components/qti-response-processing/qti-response-processing.js.map +1 -1
- package/dist/internal/event-types.d.ts +18 -0
- package/dist/internal/event-types.js.map +1 -1
- package/dist/internal/feedback-events.d.ts +10 -0
- package/dist/internal/feedback-events.js +17 -0
- package/dist/internal/feedback-events.js.map +1 -0
- package/dist/public-events.d.ts +28 -1
- package/dist/public-events.js +5 -1
- package/dist/public-events.js.map +1 -1
- package/package.json +3 -3
|
@@ -5,16 +5,6 @@ import type { RegisteredInteraction } from '@qti-components/base';
|
|
|
5
5
|
import type { VariableDeclaration, VariableValue } from '@qti-components/base';
|
|
6
6
|
import type { OutcomeVariable, ResponseVariable } from '@qti-components/base';
|
|
7
7
|
import type { ItemContext } from '@qti-components/base';
|
|
8
|
-
/**
|
|
9
|
-
* @summary The qti-assessment-item element contains all the other QTI 3 item structures.
|
|
10
|
-
* @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.dltnnj87l0yj
|
|
11
|
-
*
|
|
12
|
-
* @dependency qti-feedback
|
|
13
|
-
* @dependency qti-responseprocessing
|
|
14
|
-
*
|
|
15
|
-
* @event qti-item-context-updated - Emitted when through a user action the itemContext is updated,
|
|
16
|
-
* typically on interaction with the interactions, or calling response processing.
|
|
17
|
-
*/
|
|
18
8
|
export declare class QtiAssessmentItem extends LitElement {
|
|
19
9
|
#private;
|
|
20
10
|
identifier: string;
|
|
@@ -57,6 +47,16 @@ export declare class QtiAssessmentItem extends LitElement {
|
|
|
57
47
|
render(): import("lit").TemplateResult<1>;
|
|
58
48
|
connectedCallback(): void;
|
|
59
49
|
disconnectedCallback(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Scores the attempt. The item does not score itself: its response processing does, like a
|
|
52
|
+
* backend, and sends the outcomes back in `cito-item-set-outcomes`, which the item applies in one
|
|
53
|
+
* update. The item keeps the attempt count (QTI info model §2.2.2: the delivery engine maintains
|
|
54
|
+
* numAttempts) and hands the new count to the run, whose rules may read it. Without response
|
|
55
|
+
* processing the item only counts the attempt. A run that throws still counts the attempt and applies
|
|
56
|
+
* no outcomes.
|
|
57
|
+
*
|
|
58
|
+
* @returns whether the item has response processing.
|
|
59
|
+
*/
|
|
60
60
|
processResponse(countNumAttempts?: boolean, reportValidityAfterScoring?: boolean): boolean;
|
|
61
61
|
resetResponses(): void;
|
|
62
62
|
protected getResponse(identifier: string): Readonly<ResponseVariable>;
|
|
@@ -9,16 +9,6 @@ import { LitElement, html } from 'lit';
|
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { itemContext, itemContextVariables } from '@qti-components/base';
|
|
11
11
|
import { dispatchPublic } from '../../public-events';
|
|
12
|
-
/**
|
|
13
|
-
* @summary The qti-assessment-item element contains all the other QTI 3 item structures.
|
|
14
|
-
* @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.dltnnj87l0yj
|
|
15
|
-
*
|
|
16
|
-
* @dependency qti-feedback
|
|
17
|
-
* @dependency qti-responseprocessing
|
|
18
|
-
*
|
|
19
|
-
* @event qti-item-context-updated - Emitted when through a user action the itemContext is updated,
|
|
20
|
-
* typically on interaction with the interactions, or calling response processing.
|
|
21
|
-
*/
|
|
22
12
|
export class QtiAssessmentItem extends LitElement {
|
|
23
13
|
constructor() {
|
|
24
14
|
super(...arguments);
|
|
@@ -64,13 +54,38 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
64
54
|
const { responseIdentifier, countAttempt } = e.detail;
|
|
65
55
|
this.validate();
|
|
66
56
|
this.updateResponseVariable(responseIdentifier, 'true');
|
|
67
|
-
this
|
|
57
|
+
this.#processResponse(countAttempt, true, responseIdentifier);
|
|
68
58
|
};
|
|
69
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Applies the outcomes of a processing run, ours or a backend's, in one update, with the
|
|
61
|
+
* interactions' validity.
|
|
62
|
+
*
|
|
63
|
+
* completionStatus is response processing's to set (QTI info model §2.2.2). When an attempt of a
|
|
64
|
+
* non-adaptive item ends and processing left it `unknown`, the item marks it `completed`: the
|
|
65
|
+
* attempt is done. TAO does the same, and the 1EdTech results-reporting reference results expect
|
|
66
|
+
* it. An adaptive item is completed only by its own processing.
|
|
67
|
+
*/
|
|
68
|
+
this.#handleSetOutcomes = (e) => {
|
|
70
69
|
e.stopImmediatePropagation();
|
|
71
|
-
const {
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
const { outcomes = [], responseProcessed = false } = e.detail ?? {};
|
|
71
|
+
const completion = [];
|
|
72
|
+
if (responseProcessed && this.adaptive === 'false') {
|
|
73
|
+
const sent = outcomes.find(o => o.identifier === 'completionStatus')?.value;
|
|
74
|
+
if ((sent ?? this.getVariable('completionStatus')?.value) === 'unknown') {
|
|
75
|
+
completion.push({ identifier: 'completionStatus', value: 'completed' });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
this.#applyOutcomes([...outcomes, ...completion], this.#checkValidity(false));
|
|
79
|
+
if (responseProcessed) {
|
|
80
|
+
// `responseProcessed` marks this as the end of an attempt (vs. a plain
|
|
81
|
+
// selection, which fires the same event without the flag). Lets listeners
|
|
82
|
+
// react only when an attempt actually ends.
|
|
83
|
+
this.dispatchEvent(new CustomEvent('qti-item-context-updated', {
|
|
84
|
+
bubbles: true,
|
|
85
|
+
composed: true,
|
|
86
|
+
detail: { itemContext: this._context, responseProcessed: true }
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
74
89
|
};
|
|
75
90
|
this.#handleSetTemplateValue = (e) => {
|
|
76
91
|
e.stopImmediatePropagation();
|
|
@@ -196,6 +211,8 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
196
211
|
// The interactions take the answers over from the context, some of them a moment from now, and
|
|
197
212
|
// a different answer can mean a different verdict. Look once they have.
|
|
198
213
|
void this.updateComplete.then(() => this.#revalidate());
|
|
214
|
+
if (this.isConnected)
|
|
215
|
+
this.#beginFirstAttempt();
|
|
199
216
|
}
|
|
200
217
|
get state() {
|
|
201
218
|
return this._context.state;
|
|
@@ -238,6 +255,7 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
238
255
|
this.updateComplete.then(() => {
|
|
239
256
|
// The verdict goes in first, so whoever hears the item connect reads it with the rest.
|
|
240
257
|
this.validate(false);
|
|
258
|
+
this.#beginFirstAttempt();
|
|
241
259
|
dispatchPublic(this, 'cito-item-rendered', this);
|
|
242
260
|
// Internal plumbing: the test and the item container listen for this name.
|
|
243
261
|
this.dispatchEvent(new CustomEvent('qti-assessment-item-connected', {
|
|
@@ -256,7 +274,7 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
256
274
|
this.addEventListener('qti-register-variable', this.#handleRegisterVariable);
|
|
257
275
|
this.addEventListener('qti-register-interaction', this.#handleRegisterInteraction);
|
|
258
276
|
this.addEventListener('end-attempt', this.#handleEndAttempt);
|
|
259
|
-
this.addEventListener('
|
|
277
|
+
this.addEventListener('cito-item-set-outcomes', this.#handleSetOutcomes);
|
|
260
278
|
this.addEventListener('qti-set-template-value', this.#handleSetTemplateValue);
|
|
261
279
|
this.addEventListener('qti-set-correct-response', this.#handleSetCorrectResponse);
|
|
262
280
|
this.addEventListener('qti-interaction-response', this.#handleUpdateResponseVariable);
|
|
@@ -265,7 +283,7 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
265
283
|
this.removeEventListener('qti-register-variable', this.#handleRegisterVariable);
|
|
266
284
|
this.removeEventListener('qti-register-interaction', this.#handleRegisterInteraction);
|
|
267
285
|
this.removeEventListener('end-attempt', this.#handleEndAttempt);
|
|
268
|
-
this.removeEventListener('
|
|
286
|
+
this.removeEventListener('cito-item-set-outcomes', this.#handleSetOutcomes);
|
|
269
287
|
this.removeEventListener('qti-set-template-value', this.#handleSetTemplateValue);
|
|
270
288
|
this.removeEventListener('qti-set-correct-response', this.#handleSetCorrectResponse);
|
|
271
289
|
this.removeEventListener('qti-interaction-response', this.#handleUpdateResponseVariable);
|
|
@@ -273,7 +291,16 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
273
291
|
#handleRegisterVariable;
|
|
274
292
|
#handleRegisterInteraction;
|
|
275
293
|
#handleEndAttempt;
|
|
276
|
-
|
|
294
|
+
/**
|
|
295
|
+
* Applies the outcomes of a processing run, ours or a backend's, in one update, with the
|
|
296
|
+
* interactions' validity.
|
|
297
|
+
*
|
|
298
|
+
* completionStatus is response processing's to set (QTI info model §2.2.2). When an attempt of a
|
|
299
|
+
* non-adaptive item ends and processing left it `unknown`, the item marks it `completed`: the
|
|
300
|
+
* attempt is done. TAO does the same, and the 1EdTech results-reporting reference results expect
|
|
301
|
+
* it. An adaptive item is completed only by its own processing.
|
|
302
|
+
*/
|
|
303
|
+
#handleSetOutcomes;
|
|
277
304
|
#handleSetTemplateValue;
|
|
278
305
|
#handleSetCorrectResponse;
|
|
279
306
|
#handleUpdateResponseVariable;
|
|
@@ -294,35 +321,72 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
294
321
|
this.#templateProcessing.process();
|
|
295
322
|
this.#initialContext = { ...this._context, variables: this._context.variables };
|
|
296
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Scores the attempt. The item does not score itself: its response processing does, like a
|
|
326
|
+
* backend, and sends the outcomes back in `cito-item-set-outcomes`, which the item applies in one
|
|
327
|
+
* update. The item keeps the attempt count (QTI info model §2.2.2: the delivery engine maintains
|
|
328
|
+
* numAttempts) and hands the new count to the run, whose rules may read it. Without response
|
|
329
|
+
* processing the item only counts the attempt. A run that throws still counts the attempt and applies
|
|
330
|
+
* no outcomes.
|
|
331
|
+
*
|
|
332
|
+
* @returns whether the item has response processing.
|
|
333
|
+
*/
|
|
297
334
|
processResponse(countNumAttempts = true, reportValidityAfterScoring = true) {
|
|
298
|
-
this
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
335
|
+
return this.#processResponse(countNumAttempts, reportValidityAfterScoring);
|
|
336
|
+
}
|
|
337
|
+
#processResponse(countNumAttempts, reportValidity, endedBy) {
|
|
338
|
+
this.#checkValidity(reportValidity);
|
|
339
|
+
this.#resetOtherEndAttempts(endedBy);
|
|
340
|
+
const numAttempts = +this.getVariable('numAttempts')?.value + (countNumAttempts ? 1 : 0);
|
|
341
|
+
const processor = this.querySelector('qti-response-processing');
|
|
342
|
+
if (typeof processor?.processResponse === 'function') {
|
|
343
|
+
try {
|
|
344
|
+
processor.processResponse({ numAttempts });
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
// The attempt started, so it counts (QTI info model §2.2.2), as in TAO and Amp-up; the
|
|
348
|
+
// outcomes of a run that failed are not applied.
|
|
349
|
+
this.#applyOutcomes([{ identifier: 'numAttempts', value: String(numAttempts) }]);
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
return true;
|
|
313
353
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
354
|
+
dispatchPublic(this, 'cito-item-set-outcomes', {
|
|
355
|
+
outcomes: [{ identifier: 'numAttempts', value: String(numAttempts) }],
|
|
356
|
+
responseProcessed: true
|
|
357
|
+
});
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* QTI info model §2.4.5: when an attempt ends any other way than through an end-attempt
|
|
362
|
+
* interaction, that interaction's response is `false`.
|
|
363
|
+
*/
|
|
364
|
+
#resetOtherEndAttempts(endedBy) {
|
|
365
|
+
const others = Array.from(this.querySelectorAll('qti-end-attempt-interaction'), el => el.getAttribute('response-identifier')).filter(id => id && id !== endedBy);
|
|
366
|
+
if (others.length === 0)
|
|
367
|
+
return;
|
|
368
|
+
this._context = {
|
|
369
|
+
...this._context,
|
|
370
|
+
variables: this._context.variables.map(v => (others.includes(v.identifier) ? { ...v, value: 'false' } : v))
|
|
371
|
+
};
|
|
323
372
|
}
|
|
324
373
|
resetResponses() {
|
|
325
374
|
this._context = this.#initialContext;
|
|
375
|
+
if (this.isConnected)
|
|
376
|
+
this.#beginFirstAttempt();
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* QTI info model §2.2.2: completionStatus is `not_attempted` until the first attempt starts, then
|
|
380
|
+
* `unknown`. The attempt starts when the candidate gets the item, so an item on screen is never
|
|
381
|
+
* `not_attempted` — also not after a reset or a restore that says so.
|
|
382
|
+
*/
|
|
383
|
+
#beginFirstAttempt() {
|
|
384
|
+
if (this.getVariable('completionStatus')?.value !== 'not_attempted')
|
|
385
|
+
return;
|
|
386
|
+
this._context = {
|
|
387
|
+
...this._context,
|
|
388
|
+
variables: this._context.variables.map(v => v.identifier === 'completionStatus' ? { ...v, value: 'unknown' } : v)
|
|
389
|
+
};
|
|
326
390
|
}
|
|
327
391
|
getResponse(identifier) {
|
|
328
392
|
return this.getVariable(identifier);
|
|
@@ -358,10 +422,8 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
358
422
|
responseIdentifier: identifier,
|
|
359
423
|
response: Array.isArray(value) ? [...value] : value
|
|
360
424
|
});
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
this.updateOutcomeVariable('completionStatus', this.#getCompletionStatus());
|
|
364
|
-
}
|
|
425
|
+
// A different answer can mean a different verdict.
|
|
426
|
+
this.validate(false);
|
|
365
427
|
}
|
|
366
428
|
/**
|
|
367
429
|
* Updates the template variable with the specified identifier to the given value.
|
|
@@ -449,32 +511,53 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
449
511
|
* @param value - The new value for the response variable.
|
|
450
512
|
*/
|
|
451
513
|
updateOutcomeVariable(identifier, value) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
514
|
+
this.#applyOutcomes([{ identifier, value }]);
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Publishes the outcomes (and the validity) in one update, then a `cito-item-outcome-changed` per
|
|
518
|
+
* outcome with its final value and one `cito-item-outcomes-changed` with all of them.
|
|
519
|
+
* An identifier the item does not declare is skipped with a warning; a later entry for the same
|
|
520
|
+
* identifier wins.
|
|
521
|
+
*/
|
|
522
|
+
#applyOutcomes(outcomes, valid) {
|
|
523
|
+
const values = new Map();
|
|
524
|
+
for (const { identifier, value } of outcomes) {
|
|
525
|
+
const variable = this.getVariable(identifier);
|
|
526
|
+
if (!variable) {
|
|
527
|
+
console.warn(`Can not set qti-outcome-identifier: ${identifier}, it is not available`);
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
values.set(identifier, variable.cardinality === 'single' ? value : Array.isArray(value) ? value : [value]);
|
|
456
531
|
}
|
|
532
|
+
const validChanged = valid !== undefined && valid !== this._context.valid;
|
|
533
|
+
if (values.size === 0 && !validChanged)
|
|
534
|
+
return;
|
|
457
535
|
this._context = {
|
|
458
536
|
...this._context,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
return v;
|
|
462
|
-
}
|
|
463
|
-
return {
|
|
464
|
-
...v,
|
|
465
|
-
value: outcomeVariable.cardinality === 'single' ? value : Array.isArray(value) ? value : [value]
|
|
466
|
-
};
|
|
467
|
-
})
|
|
537
|
+
...(validChanged ? { valid } : {}),
|
|
538
|
+
variables: this._context.variables.map(v => values.has(v.identifier) ? { ...v, value: values.get(v.identifier) } : v)
|
|
468
539
|
};
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
540
|
+
if (values.size > 0) {
|
|
541
|
+
for (const [outcomeIdentifier, value] of values) {
|
|
542
|
+
dispatchPublic(this, 'cito-item-outcome-changed', {
|
|
543
|
+
item: this.identifier,
|
|
544
|
+
outcomeIdentifier,
|
|
545
|
+
value: value
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
dispatchPublic(this, 'cito-item-outcomes-changed', {
|
|
549
|
+
item: this.identifier,
|
|
550
|
+
outcomes: [...values].map(([identifier, value]) => ({ identifier, value }))
|
|
551
|
+
});
|
|
552
|
+
}
|
|
474
553
|
}
|
|
475
554
|
validate(reportValidity = true) {
|
|
476
|
-
const isValid = this
|
|
555
|
+
const isValid = this.#checkValidity(reportValidity);
|
|
477
556
|
this.#publishValidity(isValid);
|
|
557
|
+
return isValid;
|
|
558
|
+
}
|
|
559
|
+
#checkValidity(reportValidity) {
|
|
560
|
+
const isValid = this.interactionElements.every(interactionElement => interactionElement.validate());
|
|
478
561
|
if (reportValidity) {
|
|
479
562
|
this.reportValidity();
|
|
480
563
|
}
|
|
@@ -506,35 +589,6 @@ export class QtiAssessmentItem extends LitElement {
|
|
|
506
589
|
interactionElement.reportValidity();
|
|
507
590
|
}
|
|
508
591
|
}
|
|
509
|
-
#getCompletionStatus() {
|
|
510
|
-
const valid = this.validate(false);
|
|
511
|
-
if (valid === true)
|
|
512
|
-
return 'completed';
|
|
513
|
-
if (valid === false)
|
|
514
|
-
return 'incomplete';
|
|
515
|
-
return 'not_attempted';
|
|
516
|
-
}
|
|
517
|
-
#resetOutcomeVariablesBeforeResponseProcessing() {
|
|
518
|
-
this._context = {
|
|
519
|
-
...this._context,
|
|
520
|
-
variables: this._context.variables.map(variable => {
|
|
521
|
-
if (variable.type !== 'outcome') {
|
|
522
|
-
return variable;
|
|
523
|
-
}
|
|
524
|
-
const hasDefaultValue = 'defaultValue' in variable;
|
|
525
|
-
const declaredDefault = hasDefaultValue ? variable.defaultValue : null;
|
|
526
|
-
let value = declaredDefault ?? null;
|
|
527
|
-
if ((value === null || value === undefined) &&
|
|
528
|
-
(variable.baseType === 'integer' || variable.baseType === 'float')) {
|
|
529
|
-
value = '0';
|
|
530
|
-
}
|
|
531
|
-
return {
|
|
532
|
-
...variable,
|
|
533
|
-
value
|
|
534
|
-
};
|
|
535
|
-
})
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
592
|
}
|
|
539
593
|
__decorate([
|
|
540
594
|
property({ type: String })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qti-assessment-item.js","sourceRoot":"","sources":["../../../src/components/qti-assessment-item/qti-assessment-item.ts"],"names":[],"mappings":"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","sourcesContent":["import { provide } from '@lit/context';\nimport { LitElement, html } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { itemContext, itemContextVariables } from '@qti-components/base';\n\nimport { dispatchPublic } from '../../public-events';\n\nimport type { PropertyValues } from 'lit';\nimport type { QtiTemplateProcessing } from '../qti-template-processing/qti-template-processing.js';\nimport type { InteractionChangedDetails, OutcomeChangedDetails } from '../../internal/event-types.ts';\nimport type { ResponseInteraction } from '@qti-components/base';\nimport type { RegisteredInteraction } from '@qti-components/base';\nimport type { VariableDeclaration, VariableValue } from '@qti-components/base';\nimport type { OutcomeVariable, ResponseVariable, TemplateVariable } from '@qti-components/base';\nimport type { QtiResponseProcessing } from '../qti-response-processing/qti-response-processing.ts';\nimport type QtiRegisterVariable from '../../internal/events/qti-register-variable.ts';\nimport type { ItemContext } from '@qti-components/base';\n\n/**\n * @summary The qti-assessment-item element contains all the other QTI 3 item structures.\n * @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.dltnnj87l0yj\n *\n * @dependency qti-feedback\n * @dependency qti-responseprocessing\n *\n * @event qti-item-context-updated - Emitted when through a user action the itemContext is updated,\n * typically on interaction with the interactions, or calling response processing.\n */\n\nexport class QtiAssessmentItem extends LitElement {\n #itemTitle: string | undefined;\n #templateProcessing: QtiTemplateProcessing | null = null;\n\n @property({ type: String }) identifier: string = '';\n @property({ type: String }) adaptive: 'true' | 'false' = 'false';\n /*\n * `attribute` spelled out: Lit derives `timedependent` from the property\n * name, while QTI writes `time-dependent`. Without it the attribute never\n * reached the property, so an item declaring `time-dependent=\"true\"` still\n * reported false to `test-navigation`, which reads this to build the computed\n * item context.\n */\n @property({ type: String, attribute: 'time-dependent' }) timeDependent: 'true' | 'false' | null = null;\n\n @property({ type: String })\n override get title(): string {\n return this.#itemTitle;\n }\n override set title(value: string) {\n this.#itemTitle = value;\n this.removeAttribute('title');\n this.setAttribute('data-title', value);\n }\n\n /**\n * Locks the item, for example once it is submitted. Published in the item context, which the\n * interactions inside follow, so the item keeps no list of them to set it on.\n */\n @property({ type: Boolean }) disabled: boolean;\n\n /**\n * Shows the item for reading only. Published in the item context, which the interactions inside\n * follow, so the item keeps no list of them to set it on.\n */\n @property({ type: Boolean }) readonly: boolean;\n\n protected override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n const readonlyChanged = changed.has('readonly') && (this.readonly ?? false) !== (this._context.readonly ?? false);\n const disabledChanged = changed.has('disabled') && (this.disabled ?? false) !== (this._context.disabled ?? false);\n if (readonlyChanged || disabledChanged) {\n this._context = {\n ...this._context,\n ...(readonlyChanged ? { readonly: !!this.readonly } : {}),\n ...(disabledChanged ? { disabled: !!this.disabled } : {})\n };\n }\n }\n\n @provide({ context: itemContext })\n private _context: ItemContext = {\n variables: itemContextVariables\n };\n\n /**\n * Sets the identifier for the assessment item reference if this item is in a test.\n *\n * @param identifier - The identifier for the assessment item reference.\n */\n public set assessmentItemRefId(identifier: string) {\n this._context = { ...this._context, identifier };\n }\n\n public get assessmentItemRefId(): string {\n return this._context.identifier;\n }\n\n /**\n * The item's whole context, declarations included, for reading. `variables` is the trimmed view\n * for hosts; the test needs the declarations too, and used to reach for the private field.\n */\n public get itemContext(): Readonly<ItemContext> {\n return this._context;\n }\n\n public get variables(): VariableValue<string | string[] | null>[] {\n return this._context.variables.map(v => ({\n identifier: v.identifier,\n value: v.value,\n type: v.type,\n // add externalscored, a fixed prop to the test, so the testcontext can read and decide how to score this item\n ...(v.type === 'outcome' && v.identifier === 'SCORE'\n ? { externalScored: (v as OutcomeVariable).externalScored }\n : {})\n }));\n }\n\n public set variables(value: VariableValue<string | string[] | null>[]) {\n if (!Array.isArray(value) || value.some(v => !('identifier' in v))) {\n console.warn('variables property should be an array of VariableDeclaration');\n return;\n }\n const previous = this._context.variables;\n // Recognised by their declaration, or by their own type: a template declaration registers after\n // its first render, so a test restoring on connect can get here before it has.\n const restoredTemplates = value.filter(\n v =>\n v.value !== null &&\n v.value !== undefined &&\n (v.type === 'template' ||\n previous.some(declared => declared.identifier === v.identifier && declared.type === 'template'))\n );\n restoredTemplates.forEach(v =>\n this.#restoredTemplateValues.set(v.identifier, v.value as Readonly<string | string[]>)\n );\n const templatesChanged = restoredTemplates.some(\n v =>\n JSON.stringify(previous.find(declared => declared.identifier === v.identifier)?.value) !==\n JSON.stringify(v.value)\n );\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(variable => {\n const matchingValue = value.find(v => v.identifier === variable.identifier);\n if (matchingValue) {\n return {\n ...variable,\n ...matchingValue,\n interpolationTable: (variable as OutcomeVariable).interpolationTable,\n matchTable: (variable as OutcomeVariable).matchTable\n };\n }\n return variable;\n })\n };\n\n // Restored after the first processing run: correct responses still follow the values it drew.\n if (this.#templatesProcessed && templatesChanged) {\n this.#runTemplateProcessing();\n }\n\n // The interactions take the answers over from the context, some of them a moment from now, and\n // a different answer can mean a different verdict. Look once they have.\n void this.updateComplete.then(() => this.#revalidate());\n }\n\n public get state(): ItemContext['state'] {\n return this._context.state;\n }\n\n public set state(value: ItemContext['state']) {\n this._context = {\n ...this._context,\n state: value ? { ...value } : undefined\n };\n }\n\n #initialContext: Readonly<ItemContext> = { ...this._context, variables: this._context.variables };\n /**\n * Template values handed in through `variables` — drawn in an earlier visit or session. Template\n * processing keeps them instead of drawing again, so the candidate sees the question they\n * answered, and still runs, so correct responses are derived from them.\n */\n #restoredTemplateValues = new Map<string, Readonly<string | string[]>>();\n #templatesProcessed = false;\n /** Registered candidate-input interactions. Correction packages may extend their presentation behavior. */\n protected interactionElements: RegisteredInteraction[] = [];\n\n /** @deprecated use variables property instead */\n set responses(myResponses: ResponseInteraction[]) {\n if (myResponses) {\n for (const response of myResponses) {\n const responseVariable = this.getResponse(response.responseIdentifier);\n if (responseVariable) {\n this.updateResponseVariable(response.responseIdentifier, response.response);\n }\n\n const interaction: RegisteredInteraction | undefined = this.interactionElements.find(\n i => i.getAttribute('response-identifier') === response.responseIdentifier\n );\n if (interaction) {\n interaction.response = response.response;\n }\n }\n }\n }\n\n override render() {\n return html`<slot></slot>`;\n }\n\n override connectedCallback(): void {\n this.#attachEventListeners();\n super.connectedCallback();\n this.updateComplete.then(() => {\n // The verdict goes in first, so whoever hears the item connect reads it with the rest.\n this.validate(false);\n dispatchPublic(this, 'cito-item-rendered', this);\n // Internal plumbing: the test and the item container listen for this name.\n this.dispatchEvent(\n new CustomEvent<QtiAssessmentItem>('qti-assessment-item-connected', {\n bubbles: true,\n composed: true,\n detail: this\n })\n );\n this.#processTemplates();\n });\n }\n\n override disconnectedCallback(): void {\n this.#removeEventListeners();\n super.disconnectedCallback();\n }\n\n #attachEventListeners() {\n this.addEventListener('qti-register-variable', this.#handleRegisterVariable);\n this.addEventListener('qti-register-interaction', this.#handleRegisterInteraction);\n this.addEventListener('end-attempt', this.#handleEndAttempt);\n this.addEventListener('qti-set-outcome-value', this.#handleSetOutcomeValue);\n this.addEventListener('qti-set-template-value', this.#handleSetTemplateValue);\n this.addEventListener('qti-set-correct-response', this.#handleSetCorrectResponse);\n this.addEventListener('qti-interaction-response', this.#handleUpdateResponseVariable);\n }\n\n #removeEventListeners() {\n this.removeEventListener('qti-register-variable', this.#handleRegisterVariable);\n this.removeEventListener('qti-register-interaction', this.#handleRegisterInteraction);\n this.removeEventListener('end-attempt', this.#handleEndAttempt);\n this.removeEventListener('qti-set-outcome-value', this.#handleSetOutcomeValue);\n this.removeEventListener('qti-set-template-value', this.#handleSetTemplateValue);\n this.removeEventListener('qti-set-correct-response', this.#handleSetCorrectResponse);\n this.removeEventListener('qti-interaction-response', this.#handleUpdateResponseVariable);\n }\n\n #handleRegisterVariable = (e: QtiRegisterVariable) => {\n e.stopImmediatePropagation();\n const { variable } = e.detail;\n const restored = variable.type === 'template' ? this.#restoredTemplateValues.get(variable.identifier) : undefined;\n const registered = restored !== undefined ? { ...variable, value: restored } : variable;\n this._context = { ...this._context, variables: [...this._context.variables, registered] };\n this.#initialContext = this._context;\n e.stopPropagation();\n };\n\n #handleRegisterInteraction = (e: CustomEvent<{ interaction: string; interactionElement: RegisteredInteraction }>) => {\n e.stopImmediatePropagation();\n this.interactionElements.push(e.detail.interactionElement);\n };\n\n #handleEndAttempt = (e: CustomEvent<{ responseIdentifier: string; countAttempt: boolean }>) => {\n e.stopImmediatePropagation();\n const { responseIdentifier, countAttempt } = e.detail;\n this.validate();\n this.updateResponseVariable(responseIdentifier, 'true');\n this.processResponse(countAttempt);\n };\n\n #handleSetOutcomeValue = (e: CustomEvent<{ outcomeIdentifier: string; value: string | string[] }>) => {\n e.stopImmediatePropagation();\n const { outcomeIdentifier, value } = e.detail;\n this.updateOutcomeVariable(outcomeIdentifier, value);\n e.stopPropagation();\n };\n\n #handleSetTemplateValue = (e: CustomEvent<{ templateIdentifier: string; value: string | string[] | null }>) => {\n e.stopImmediatePropagation();\n const { templateIdentifier, value } = e.detail;\n if (!this.#restoredTemplateValues.has(templateIdentifier)) {\n this.updateTemplateVariable(templateIdentifier, value ?? undefined);\n }\n e.stopPropagation();\n };\n\n #handleSetCorrectResponse = (e: CustomEvent<{ responseIdentifier: string; value: string | string[] | null }>) => {\n e.stopImmediatePropagation();\n const { responseIdentifier, value } = e.detail;\n this.updateCorrectResponse(responseIdentifier, value ?? undefined);\n e.stopPropagation();\n };\n\n #handleUpdateResponseVariable = (e: CustomEvent<ResponseInteraction>) => {\n e.stopImmediatePropagation();\n\n const { responseIdentifier, response, state } = e.detail;\n this.updateResponseVariable(responseIdentifier, response);\n if (state !== undefined) {\n this._context = {\n ...this._context,\n state: {\n ...(this._context.state || {}),\n [responseIdentifier]: state\n }\n };\n }\n\n // The interaction has updated its own validity by now; publish the verdict with the answer.\n this.validate(false);\n\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n };\n\n async #processTemplates(): Promise<void> {\n const templateDeclarations = Array.from(this.querySelectorAll<LitElement>('qti-template-declaration'));\n if (templateDeclarations.length > 0) {\n await Promise.all(templateDeclarations.map(declaration => declaration.updateComplete));\n await Promise.resolve();\n }\n\n this.#templateProcessing = this.querySelector<QtiTemplateProcessing>('qti-template-processing');\n this.#templatesProcessed = true;\n // Run template processing before first presentation\n this.#runTemplateProcessing();\n }\n\n #runTemplateProcessing(): void {\n if (!this.#templateProcessing) return;\n this.#templateProcessing.process();\n this.#initialContext = { ...this._context, variables: this._context.variables };\n }\n\n public processResponse(countNumAttempts = true, reportValidityAfterScoring = true): boolean {\n this.validate(reportValidityAfterScoring);\n\n if (countNumAttempts) {\n this.updateOutcomeVariable(\n 'numAttempts',\n (+this._context.variables.find(v => v.identifier === 'numAttempts')?.value + 1).toString()\n );\n }\n\n if (this.adaptive === 'false') {\n this.#resetOutcomeVariablesBeforeResponseProcessing();\n }\n\n const responseProcessor = this.querySelector<QtiResponseProcessing>('qti-response-processing');\n const canProcess = !!(responseProcessor && typeof responseProcessor.process === 'function');\n if (canProcess) {\n responseProcessor.process();\n }\n if (this.adaptive === 'false') {\n // if adaptive, completionStatus is set by the processing template\n this.updateOutcomeVariable('completionStatus', this.#getCompletionStatus());\n }\n\n // `responseProcessed` marks this as the end of an attempt (vs. a plain\n // selection, which fires the same event without the flag). Lets listeners\n // react only when an attempt actually ends.\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext; responseProcessed: boolean }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context, responseProcessed: true }\n })\n );\n\n return canProcess;\n }\n\n public resetResponses() {\n this._context = this.#initialContext;\n }\n\n protected getResponse(identifier: string): Readonly<ResponseVariable> {\n return this.getVariable(identifier) as ResponseVariable;\n }\n\n public getOutcome(identifier: string): Readonly<OutcomeVariable> {\n return this.getVariable(identifier) as OutcomeVariable;\n }\n\n protected getVariable(identifier: string): Readonly<VariableDeclaration<string | string[] | null>> {\n return this._context.variables.find(v => v.identifier === identifier) || null;\n }\n\n /** Extension point for presentation packages reacting to a candidate response change. */\n protected afterResponseVariableUpdated(): void {}\n\n // saving privates here: ------------------------------------------------------------------------------\n\n /**\n * Updates the response variable with the specified identifier to the given value.\n *\n * @protected\n *\n * This method is intended for internal use within the class and subclasses.\n * It should not be called externally by third parties.\n *\n * @param identifier - The identifier of the response variable to update.\n * @param value - The new value for the response variable.\n */\n public updateResponseVariable(identifier: string, value: string | string[] | undefined) {\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v => (v.identifier !== identifier ? v : { ...v, value: value }))\n };\n\n this.afterResponseVariableUpdated();\n\n dispatchPublic(this, 'cito-item-response-changed', {\n item: this.identifier,\n responseIdentifier: identifier,\n response: Array.isArray(value) ? [...value] : value\n });\n\n if (this.adaptive === 'false') {\n // if adaptive, completionStatus is set by the processing template\n this.updateOutcomeVariable('completionStatus', this.#getCompletionStatus());\n }\n }\n\n /**\n * Updates the template variable with the specified identifier to the given value.\n */\n public updateTemplateVariable(identifier: string, value: string | string[] | undefined) {\n const templateVariable = this._context.variables.find(v => v.identifier === identifier && v.type === 'template') as\n | TemplateVariable\n | undefined;\n\n if (!templateVariable) {\n console.warn(`Can not set qti-template-identifier: ${identifier}, it is not available`);\n return;\n }\n\n const normalizedValue =\n templateVariable.cardinality === 'single'\n ? Array.isArray(value)\n ? value[0]\n : (value ?? null)\n : value === undefined || value === null\n ? null\n : Array.isArray(value)\n ? value\n : [value];\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v =>\n v.identifier !== identifier\n ? v\n : {\n ...v,\n value: normalizedValue\n }\n )\n };\n\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n\n /**\n * Updates the correct response for the specified response variable.\n */\n public updateCorrectResponse(identifier: string, value: string | string[] | undefined) {\n const responseVariable = this.getResponse(identifier);\n\n if (!responseVariable) {\n console.warn(`Can not set correct response for identifier: ${identifier}, it is not available`);\n return;\n }\n\n const normalizedValue =\n responseVariable.cardinality === 'single'\n ? Array.isArray(value)\n ? value[0]\n : (value ?? null)\n : value === undefined || value === null\n ? null\n : Array.isArray(value)\n ? value\n : [value];\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v =>\n v.identifier !== identifier\n ? v\n : {\n ...v,\n correctResponse: normalizedValue\n }\n )\n };\n\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n\n public setOutcomeVariable(identifier: string, value: string | string[] | undefined) {\n this.updateOutcomeVariable(identifier, value);\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n\n /**\n * Updates the outcome variable with the specified identifier to the given value.\n *\n * @protected\n *\n * This method is intended for internal use within the class and subclasses.\n * It should not be called externally by third parties.\n *\n * @param identifier - The identifier of the response variable to update.\n * @param value - The new value for the response variable.\n */\n public updateOutcomeVariable(identifier: string, value: string | string[] | undefined) {\n const outcomeVariable = this.getOutcome(identifier);\n\n if (!outcomeVariable) {\n console.warn(`Can not set qti-outcome-identifier: ${identifier}, it is not available`);\n return;\n }\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v => {\n if (v.identifier !== identifier) {\n return v;\n }\n return {\n ...v,\n value: outcomeVariable.cardinality === 'single' ? value : Array.isArray(value) ? value : [value]\n };\n })\n };\n\n dispatchPublic(this, 'cito-item-outcome-changed', {\n item: this.identifier,\n outcomeIdentifier: identifier,\n value: this._context.variables.find(v => v.identifier === identifier)?.value\n });\n }\n\n public validate(reportValidity = true): boolean {\n const isValid = this.interactionElements.every(interactionElement => interactionElement.validate());\n this.#publishValidity(isValid);\n\n if (reportValidity) {\n this.reportValidity();\n }\n\n return isValid;\n }\n\n /** Puts the verdict in the item context, where the test and anything else can read it. */\n #publishValidity(valid: boolean): void {\n if (this._context.valid !== valid) {\n this._context = { ...this._context, valid };\n }\n }\n\n /**\n * Checks again after something the interactions' validity depends on changed without them saying\n * so (an answer handed in through `variables`), and tells the test if the verdict moved.\n */\n #revalidate(): void {\n const before = this._context.valid;\n this.validate(false);\n if (this._context.valid !== before) {\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n }\n\n public reportValidity() {\n for (const interactionElement of this.interactionElements) {\n interactionElement.reportValidity();\n }\n }\n\n #getCompletionStatus(): 'completed' | 'incomplete' | 'not_attempted' | 'unknown' {\n const valid = this.validate(false);\n if (valid === true) return 'completed';\n if (valid === false) return 'incomplete';\n return 'not_attempted';\n }\n\n #resetOutcomeVariablesBeforeResponseProcessing(): void {\n this._context = {\n ...this._context,\n variables: this._context.variables.map(variable => {\n if (variable.type !== 'outcome') {\n return variable;\n }\n\n const hasDefaultValue = 'defaultValue' in variable;\n const declaredDefault = hasDefaultValue ? variable.defaultValue : null;\n\n let value = declaredDefault ?? null;\n if (\n (value === null || value === undefined) &&\n (variable.baseType === 'integer' || variable.baseType === 'float')\n ) {\n value = '0';\n }\n\n return {\n ...variable,\n value\n };\n })\n };\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-assessment-item': QtiAssessmentItem;\n }\n}\n\ndeclare module '../../public-events' {\n interface PublicItemEventMap {\n /** The item rendered: its interactions are in the DOM and its validity is known. */\n 'cito-item-rendered': CustomEvent<QtiAssessmentItem>;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"qti-assessment-item.js","sourceRoot":"","sources":["../../../src/components/qti-assessment-item/qti-assessment-item.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA+BrD,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IAAjD;;QAEE,wBAAmB,GAAiC,IAAI,CAAC;QAE7B,eAAU,GAAW,EAAE,CAAC;QACxB,aAAQ,GAAqB,OAAO,CAAC;QACjE;;;;;;WAMG;QACsD,kBAAa,GAA4B,IAAI,CAAC;QAsC/F,aAAQ,GAAgB;YAC9B,SAAS,EAAE,oBAAoB;SAChC,CAAC;QAiGF,oBAAe,GAA0B,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QAClG;;;;WAIG;QACH,4BAAuB,GAAG,IAAI,GAAG,EAAuC,CAAC;QACzE,wBAAmB,GAAG,KAAK,CAAC;QAC5B,2GAA2G;QACjG,wBAAmB,GAA4B,EAAE,CAAC;QAsE5D,4BAAuB,GAAG,CAAC,CAAsB,EAAE,EAAE;YACnD,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;YAC9B,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAClH,MAAM,UAAU,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YACxF,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;YAC1F,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC;YACrC,CAAC,CAAC,eAAe,EAAE,CAAC;QACtB,CAAC,CAAC;QAEF,+BAA0B,GAAG,CAAC,CAAkF,EAAE,EAAE;YAClH,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC7D,CAAC,CAAC;QAEF,sBAAiB,GAAG,CAAC,CAAqE,EAAE,EAAE;YAC5F,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;YACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;YACxD,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAChE,CAAC,CAAC;QAEF;;;;;;;;WAQG;QACH,uBAAkB,GAAG,CAAC,CAAkC,EAAE,EAAE;YAC1D,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,iBAAiB,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;YACpE,MAAM,UAAU,GAAmB,EAAE,CAAC;YACtC,IAAI,iBAAiB,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,kBAAkB,CAAC,EAAE,KAAK,CAAC;gBAC5E,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;oBACxE,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;gBAC1E,CAAC;YACH,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;YAE9E,IAAI,iBAAiB,EAAE,CAAC;gBACtB,uEAAuE;gBACvE,0EAA0E;gBAC1E,4CAA4C;gBAC5C,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA2D,0BAA0B,EAAE;oBACpG,OAAO,EAAE,IAAI;oBACb,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE;iBAChE,CAAC,CACH,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,4BAAuB,GAAG,CAAC,CAA+E,EAAE,EAAE;YAC5G,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC1D,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,KAAK,IAAI,SAAS,CAAC,CAAC;YACtE,CAAC;YACD,CAAC,CAAC,eAAe,EAAE,CAAC;QACtB,CAAC,CAAC;QAEF,8BAAyB,GAAG,CAAC,CAA+E,EAAE,EAAE;YAC9G,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAC7B,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;YAC/C,IAAI,CAAC,qBAAqB,CAAC,kBAAkB,EAAE,KAAK,IAAI,SAAS,CAAC,CAAC;YACnE,CAAC,CAAC,eAAe,EAAE,CAAC;QACtB,CAAC,CAAC;QAEF,kCAA6B,GAAG,CAAC,CAAmC,EAAE,EAAE;YACtE,CAAC,CAAC,wBAAwB,EAAE,CAAC;YAE7B,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC;YACzD,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;YAC1D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,CAAC,QAAQ,GAAG;oBACd,GAAG,IAAI,CAAC,QAAQ;oBAChB,KAAK,EAAE;wBACL,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;wBAC9B,CAAC,kBAAkB,CAAC,EAAE,KAAK;qBAC5B;iBACF,CAAC;YACJ,CAAC;YAED,4FAA4F;YAC5F,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAErB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA+B,0BAA0B,EAAE;gBACxE,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;aACvC,CAAC,CACH,CAAC;QACJ,CAAC,CAAC;IAoVJ,CAAC;IA3pBC,UAAU,CAAqB;IAC/B,mBAAmB,CAAsC;IAczD,IAAa,KAAK;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,IAAa,KAAK,CAAC,KAAa;QAC9B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAckB,UAAU,CAAC,OAAuB;QACnD,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC1B,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;QAClH,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;QAClH,IAAI,eAAe,IAAI,eAAe,EAAE,CAAC;YACvC,IAAI,CAAC,QAAQ,GAAG;gBACd,GAAG,IAAI,CAAC,QAAQ;gBAChB,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAOD;;;;OAIG;IACH,IAAW,mBAAmB,CAAC,UAAkB;QAC/C,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;IACnD,CAAC;IAED,IAAW,mBAAmB;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;IAClC,CAAC;IAED;;;OAGG;IACH,IAAW,WAAW;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvC,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,8GAA8G;YAC9G,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,KAAK,OAAO;gBAClD,CAAC,CAAC,EAAE,cAAc,EAAG,CAAqB,CAAC,cAAc,EAAE;gBAC3D,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC,CAAC;IACN,CAAC;IAED,IAAW,SAAS,CAAC,KAAgD;QACnE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzC,gGAAgG;QAChG,+EAA+E;QAC/E,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,KAAK,KAAK,IAAI;YAChB,CAAC,CAAC,KAAK,KAAK,SAAS;YACrB,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU;gBACpB,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CACrG,CAAC;QACF,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC5B,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,KAAoC,CAAC,CACvF,CAAC;QACF,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,IAAI,CAC7C,CAAC,CAAC,EAAE,CACF,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;YACtF,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAC1B,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;gBAChD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU,CAAC,CAAC;gBAC5E,IAAI,aAAa,EAAE,CAAC;oBAClB,OAAO;wBACL,GAAG,QAAQ;wBACX,GAAG,aAAa;wBAChB,kBAAkB,EAAG,QAA4B,CAAC,kBAAkB;wBACpE,UAAU,EAAG,QAA4B,CAAC,UAAU;qBACrD,CAAC;gBACJ,CAAC;gBACD,OAAO,QAAQ,CAAC;YAClB,CAAC,CAAC;SACH,CAAC;QAEF,8FAA8F;QAC9F,IAAI,IAAI,CAAC,mBAAmB,IAAI,gBAAgB,EAAE,CAAC;YACjD,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC;QAED,+FAA+F;QAC/F,wEAAwE;QACxE,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACxD,IAAI,IAAI,CAAC,WAAW;YAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAClD,CAAC;IAED,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;IAC7B,CAAC;IAED,IAAW,KAAK,CAAC,KAA2B;QAC1C,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;SACxC,CAAC;IACJ,CAAC;IAED,eAAe,CAAmF;IAClG;;;;OAIG;IACH,uBAAuB,CAAkD;IACzE,mBAAmB,CAAS;IAI5B,iDAAiD;IACjD,IAAI,SAAS,CAAC,WAAkC;QAC9C,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;gBACnC,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;gBACvE,IAAI,gBAAgB,EAAE,CAAC;oBACrB,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC9E,CAAC;gBAED,MAAM,WAAW,GAAsC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAClF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,qBAAqB,CAAC,KAAK,QAAQ,CAAC,kBAAkB,CAC3E,CAAC;gBACF,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;gBAC3C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA,eAAe,CAAC;IAC7B,CAAC;IAEQ,iBAAiB;QACxB,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE;YAC5B,uFAAuF;YACvF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACrB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,cAAc,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,CAAC,CAAC;YACjD,2EAA2E;YAC3E,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAoB,+BAA+B,EAAE;gBAClE,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,IAAI;aACb,CAAC,CACH,CAAC;YACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAEQ,oBAAoB;QAC3B,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,KAAK,CAAC,oBAAoB,EAAE,CAAC;IAC/B,CAAC;IAED,qBAAqB;QACnB,IAAI,CAAC,gBAAgB,CAAC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC7E,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,EAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACnF,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7D,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACzE,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC9E,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAClF,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,EAAE,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACxF,CAAC;IAED,qBAAqB;QACnB,IAAI,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAChF,IAAI,CAAC,mBAAmB,CAAC,0BAA0B,EAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACtF,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChE,IAAI,CAAC,mBAAmB,CAAC,wBAAwB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC5E,IAAI,CAAC,mBAAmB,CAAC,wBAAwB,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACjF,IAAI,CAAC,mBAAmB,CAAC,0BAA0B,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACrF,IAAI,CAAC,mBAAmB,CAAC,0BAA0B,EAAE,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC3F,CAAC;IAED,uBAAuB,CAQrB;IAEF,0BAA0B,CAGxB;IAEF,iBAAiB,CAMf;IAEF;;;;;;;;OAQG;IACH,kBAAkB,CAwBhB;IAEF,uBAAuB,CAOrB;IAEF,yBAAyB,CAKvB;IAEF,6BAA6B,CAyB3B;IAEF,KAAK,CAAC,iBAAiB;QACrB,MAAM,oBAAoB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAa,0BAA0B,CAAC,CAAC,CAAC;QACvG,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;YACvF,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,aAAa,CAAwB,yBAAyB,CAAC,CAAC;QAChG,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,oDAAoD;QACpD,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAED,sBAAsB;QACpB,IAAI,CAAC,IAAI,CAAC,mBAAmB;YAAE,OAAO;QACtC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC,eAAe,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;IAClF,CAAC;IAED;;;;;;;;;OASG;IACI,eAAe,CAAC,gBAAgB,GAAG,IAAI,EAAE,0BAA0B,GAAG,IAAI;QAC/E,OAAO,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,0BAA0B,CAAC,CAAC;IAC7E,CAAC;IAED,gBAAgB,CAAC,gBAAyB,EAAE,cAAuB,EAAE,OAAgB;QACnF,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACpC,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAErC,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,KAAK,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzF,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAA2C,yBAAyB,CAAC,CAAC;QAC1G,IAAI,OAAO,SAAS,EAAE,eAAe,KAAK,UAAU,EAAE,CAAC;YACrD,IAAI,CAAC;gBACH,SAAS,CAAC,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,uFAAuF;gBACvF,iDAAiD;gBACjD,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;gBACjF,MAAM,KAAK,CAAC;YACd,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,cAAc,CAAC,IAAI,EAAE,wBAAwB,EAAE;YAC7C,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YACrE,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,sBAAsB,CAAC,OAA2B;QAChD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,6BAA6B,CAAC,EAAE,EAAE,CAAC,EAAE,CACnF,EAAE,CAAC,YAAY,CAAC,qBAAqB,CAAC,CACvC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAChC,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAC5G,CAAC;IACJ,CAAC;IAEM,cAAc;QACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC;QACrC,IAAI,IAAI,CAAC,WAAW;YAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACH,kBAAkB;QAChB,IAAI,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,KAAK,KAAK,eAAe;YAAE,OAAO;QAC5E,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC,CAAC,UAAU,KAAK,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CACrE;SACF,CAAC;IACJ,CAAC;IAES,WAAW,CAAC,UAAkB;QACtC,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAqB,CAAC;IAC1D,CAAC;IAEM,UAAU,CAAC,UAAkB;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAoB,CAAC;IACzD,CAAC;IAES,WAAW,CAAC,UAAkB;QACtC,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC;IAChF,CAAC;IAED,yFAAyF;IAC/E,4BAA4B,KAAU,CAAC;IAEjD,uGAAuG;IAEvG;;;;;;;;;;OAUG;IACI,sBAAsB,CAAC,UAAkB,EAAE,KAAoC;QACpF,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;SACxG,CAAC;QAEF,IAAI,CAAC,4BAA4B,EAAE,CAAC;QAEpC,cAAc,CAAC,IAAI,EAAE,4BAA4B,EAAE;YACjD,IAAI,EAAE,IAAI,CAAC,UAAU;YACrB,kBAAkB,EAAE,UAAU;YAC9B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;SACpD,CAAC,CAAC;QAEH,mDAAmD;QACnD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAED;;OAEG;IACI,sBAAsB,CAAC,UAAkB,EAAE,KAAoC;QACpF,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAElG,CAAC;QAEd,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,wCAAwC,UAAU,uBAAuB,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GACnB,gBAAgB,CAAC,WAAW,KAAK,QAAQ;YACvC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACpB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACV,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;YACnB,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBACrC,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;oBACpB,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAElB,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC;oBACE,GAAG,CAAC;oBACJ,KAAK,EAAE,eAAe;iBACvB,CACN;SACF,CAAC;QAEF,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA+B,0BAA0B,EAAE;YACxE,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;SACvC,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,UAAkB,EAAE,KAAoC;QACnF,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAEtD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,gDAAgD,UAAU,uBAAuB,CAAC,CAAC;YAChG,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GACnB,gBAAgB,CAAC,WAAW,KAAK,QAAQ;YACvC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACpB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACV,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;YACnB,CAAC,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBACrC,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;oBACpB,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAElB,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC;oBACE,GAAG,CAAC;oBACJ,eAAe,EAAE,eAAe;iBACjC,CACN;SACF,CAAC;QAEF,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA+B,0BAA0B,EAAE;YACxE,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;SACvC,CAAC,CACH,CAAC;IACJ,CAAC;IAEM,kBAAkB,CAAC,UAAkB,EAAE,KAAoC;QAChF,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA+B,0BAA0B,EAAE;YACxE,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;SACvC,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACI,qBAAqB,CAAC,UAAkB,EAAE,KAAoC;QACnF,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,QAAiC,EAAE,KAAe;QAC/D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAC;QACxD,KAAK,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,uCAAuC,UAAU,uBAAuB,CAAC,CAAC;gBACvF,SAAS;YACX,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7G,CAAC;QACD,MAAM,YAAY,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC1E,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO;QAE/C,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,IAAI,CAAC,QAAQ;YAChB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACzC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAA6B,EAAE,CAAC,CAAC,CAAC,CAAC,CACrG;SACF,CAAC;QAEF,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC,iBAAiB,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;gBAChD,cAAc,CAAC,IAAI,EAAE,2BAA2B,EAAE;oBAChD,IAAI,EAAE,IAAI,CAAC,UAAU;oBACrB,iBAAiB;oBACjB,KAAK,EAAE,KAA0B;iBAClC,CAAC,CAAC;YACL,CAAC;YACD,cAAc,CAAC,IAAI,EAAE,4BAA4B,EAAE;gBACjD,IAAI,EAAE,IAAI,CAAC,UAAU;gBACrB,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;aAC5E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEM,QAAQ,CAAC,cAAc,GAAG,IAAI;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,cAAc,CAAC,cAAuB;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpG,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,0FAA0F;IAC1F,gBAAgB,CAAC,KAAc;QAC7B,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC9C,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,WAAW;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA+B,0BAA0B,EAAE;gBACxE,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE;aACvC,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;IAEM,cAAc;QACnB,KAAK,MAAM,kBAAkB,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1D,kBAAkB,CAAC,cAAc,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;CACF;AAxpB6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;qDAAyB;AACxB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;mDAAsC;AAQR;IAAxD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;wDAA+C;AAGvG;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAG1B;AAW4B;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;mDAAmB;AAMlB;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;mDAAmB;AAgBvC;IADP,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;mDAGhC","sourcesContent":["import { provide } from '@lit/context';\nimport { LitElement, html } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { itemContext, itemContextVariables } from '@qti-components/base';\n\nimport { dispatchPublic } from '../../public-events';\n\nimport type { PropertyValues } from 'lit';\nimport type { QtiTemplateProcessing } from '../qti-template-processing/qti-template-processing.js';\nimport type { InteractionChangedDetails, OutcomeEntry, SetOutcomesDetails } from '../../internal/event-types.ts';\nimport type { ResponseInteraction } from '@qti-components/base';\nimport type { RegisteredInteraction } from '@qti-components/base';\nimport type { VariableDeclaration, VariableValue } from '@qti-components/base';\nimport type { OutcomeVariable, ResponseVariable, TemplateVariable } from '@qti-components/base';\nimport type QtiRegisterVariable from '../../internal/events/qti-register-variable.ts';\nimport type { ItemContext } from '@qti-components/base';\n\n/**\n * @summary The qti-assessment-item element contains all the other QTI 3 item structures.\n * @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.dltnnj87l0yj\n *\n * @dependency qti-feedback\n * @dependency qti-responseprocessing\n *\n * @event qti-item-context-updated - Emitted when through a user action the itemContext is updated,\n * typically on interaction with the interactions, or calling response processing.\n */\n\n/**\n * What the item needs of its response processing: start a run for an attempt. The result comes\n * back as an event.\n */\ninterface ResponseProcessor {\n processResponse(options: { numAttempts: number }): void;\n}\n\nexport class QtiAssessmentItem extends LitElement {\n #itemTitle: string | undefined;\n #templateProcessing: QtiTemplateProcessing | null = null;\n\n @property({ type: String }) identifier: string = '';\n @property({ type: String }) adaptive: 'true' | 'false' = 'false';\n /*\n * `attribute` spelled out: Lit derives `timedependent` from the property\n * name, while QTI writes `time-dependent`. Without it the attribute never\n * reached the property, so an item declaring `time-dependent=\"true\"` still\n * reported false to `test-navigation`, which reads this to build the computed\n * item context.\n */\n @property({ type: String, attribute: 'time-dependent' }) timeDependent: 'true' | 'false' | null = null;\n\n @property({ type: String })\n override get title(): string {\n return this.#itemTitle;\n }\n override set title(value: string) {\n this.#itemTitle = value;\n this.removeAttribute('title');\n this.setAttribute('data-title', value);\n }\n\n /**\n * Locks the item, for example once it is submitted. Published in the item context, which the\n * interactions inside follow, so the item keeps no list of them to set it on.\n */\n @property({ type: Boolean }) disabled: boolean;\n\n /**\n * Shows the item for reading only. Published in the item context, which the interactions inside\n * follow, so the item keeps no list of them to set it on.\n */\n @property({ type: Boolean }) readonly: boolean;\n\n protected override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n const readonlyChanged = changed.has('readonly') && (this.readonly ?? false) !== (this._context.readonly ?? false);\n const disabledChanged = changed.has('disabled') && (this.disabled ?? false) !== (this._context.disabled ?? false);\n if (readonlyChanged || disabledChanged) {\n this._context = {\n ...this._context,\n ...(readonlyChanged ? { readonly: !!this.readonly } : {}),\n ...(disabledChanged ? { disabled: !!this.disabled } : {})\n };\n }\n }\n\n @provide({ context: itemContext })\n private _context: ItemContext = {\n variables: itemContextVariables\n };\n\n /**\n * Sets the identifier for the assessment item reference if this item is in a test.\n *\n * @param identifier - The identifier for the assessment item reference.\n */\n public set assessmentItemRefId(identifier: string) {\n this._context = { ...this._context, identifier };\n }\n\n public get assessmentItemRefId(): string {\n return this._context.identifier;\n }\n\n /**\n * The item's whole context, declarations included, for reading. `variables` is the trimmed view\n * for hosts; the test needs the declarations too, and used to reach for the private field.\n */\n public get itemContext(): Readonly<ItemContext> {\n return this._context;\n }\n\n public get variables(): VariableValue<string | string[] | null>[] {\n return this._context.variables.map(v => ({\n identifier: v.identifier,\n value: v.value,\n type: v.type,\n // add externalscored, a fixed prop to the test, so the testcontext can read and decide how to score this item\n ...(v.type === 'outcome' && v.identifier === 'SCORE'\n ? { externalScored: (v as OutcomeVariable).externalScored }\n : {})\n }));\n }\n\n public set variables(value: VariableValue<string | string[] | null>[]) {\n if (!Array.isArray(value) || value.some(v => !('identifier' in v))) {\n console.warn('variables property should be an array of VariableDeclaration');\n return;\n }\n const previous = this._context.variables;\n // Recognised by their declaration, or by their own type: a template declaration registers after\n // its first render, so a test restoring on connect can get here before it has.\n const restoredTemplates = value.filter(\n v =>\n v.value !== null &&\n v.value !== undefined &&\n (v.type === 'template' ||\n previous.some(declared => declared.identifier === v.identifier && declared.type === 'template'))\n );\n restoredTemplates.forEach(v =>\n this.#restoredTemplateValues.set(v.identifier, v.value as Readonly<string | string[]>)\n );\n const templatesChanged = restoredTemplates.some(\n v =>\n JSON.stringify(previous.find(declared => declared.identifier === v.identifier)?.value) !==\n JSON.stringify(v.value)\n );\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(variable => {\n const matchingValue = value.find(v => v.identifier === variable.identifier);\n if (matchingValue) {\n return {\n ...variable,\n ...matchingValue,\n interpolationTable: (variable as OutcomeVariable).interpolationTable,\n matchTable: (variable as OutcomeVariable).matchTable\n };\n }\n return variable;\n })\n };\n\n // Restored after the first processing run: correct responses still follow the values it drew.\n if (this.#templatesProcessed && templatesChanged) {\n this.#runTemplateProcessing();\n }\n\n // The interactions take the answers over from the context, some of them a moment from now, and\n // a different answer can mean a different verdict. Look once they have.\n void this.updateComplete.then(() => this.#revalidate());\n if (this.isConnected) this.#beginFirstAttempt();\n }\n\n public get state(): ItemContext['state'] {\n return this._context.state;\n }\n\n public set state(value: ItemContext['state']) {\n this._context = {\n ...this._context,\n state: value ? { ...value } : undefined\n };\n }\n\n #initialContext: Readonly<ItemContext> = { ...this._context, variables: this._context.variables };\n /**\n * Template values handed in through `variables` — drawn in an earlier visit or session. Template\n * processing keeps them instead of drawing again, so the candidate sees the question they\n * answered, and still runs, so correct responses are derived from them.\n */\n #restoredTemplateValues = new Map<string, Readonly<string | string[]>>();\n #templatesProcessed = false;\n /** Registered candidate-input interactions. Correction packages may extend their presentation behavior. */\n protected interactionElements: RegisteredInteraction[] = [];\n\n /** @deprecated use variables property instead */\n set responses(myResponses: ResponseInteraction[]) {\n if (myResponses) {\n for (const response of myResponses) {\n const responseVariable = this.getResponse(response.responseIdentifier);\n if (responseVariable) {\n this.updateResponseVariable(response.responseIdentifier, response.response);\n }\n\n const interaction: RegisteredInteraction | undefined = this.interactionElements.find(\n i => i.getAttribute('response-identifier') === response.responseIdentifier\n );\n if (interaction) {\n interaction.response = response.response;\n }\n }\n }\n }\n\n override render() {\n return html`<slot></slot>`;\n }\n\n override connectedCallback(): void {\n this.#attachEventListeners();\n super.connectedCallback();\n this.updateComplete.then(() => {\n // The verdict goes in first, so whoever hears the item connect reads it with the rest.\n this.validate(false);\n this.#beginFirstAttempt();\n dispatchPublic(this, 'cito-item-rendered', this);\n // Internal plumbing: the test and the item container listen for this name.\n this.dispatchEvent(\n new CustomEvent<QtiAssessmentItem>('qti-assessment-item-connected', {\n bubbles: true,\n composed: true,\n detail: this\n })\n );\n this.#processTemplates();\n });\n }\n\n override disconnectedCallback(): void {\n this.#removeEventListeners();\n super.disconnectedCallback();\n }\n\n #attachEventListeners() {\n this.addEventListener('qti-register-variable', this.#handleRegisterVariable);\n this.addEventListener('qti-register-interaction', this.#handleRegisterInteraction);\n this.addEventListener('end-attempt', this.#handleEndAttempt);\n this.addEventListener('cito-item-set-outcomes', this.#handleSetOutcomes);\n this.addEventListener('qti-set-template-value', this.#handleSetTemplateValue);\n this.addEventListener('qti-set-correct-response', this.#handleSetCorrectResponse);\n this.addEventListener('qti-interaction-response', this.#handleUpdateResponseVariable);\n }\n\n #removeEventListeners() {\n this.removeEventListener('qti-register-variable', this.#handleRegisterVariable);\n this.removeEventListener('qti-register-interaction', this.#handleRegisterInteraction);\n this.removeEventListener('end-attempt', this.#handleEndAttempt);\n this.removeEventListener('cito-item-set-outcomes', this.#handleSetOutcomes);\n this.removeEventListener('qti-set-template-value', this.#handleSetTemplateValue);\n this.removeEventListener('qti-set-correct-response', this.#handleSetCorrectResponse);\n this.removeEventListener('qti-interaction-response', this.#handleUpdateResponseVariable);\n }\n\n #handleRegisterVariable = (e: QtiRegisterVariable) => {\n e.stopImmediatePropagation();\n const { variable } = e.detail;\n const restored = variable.type === 'template' ? this.#restoredTemplateValues.get(variable.identifier) : undefined;\n const registered = restored !== undefined ? { ...variable, value: restored } : variable;\n this._context = { ...this._context, variables: [...this._context.variables, registered] };\n this.#initialContext = this._context;\n e.stopPropagation();\n };\n\n #handleRegisterInteraction = (e: CustomEvent<{ interaction: string; interactionElement: RegisteredInteraction }>) => {\n e.stopImmediatePropagation();\n this.interactionElements.push(e.detail.interactionElement);\n };\n\n #handleEndAttempt = (e: CustomEvent<{ responseIdentifier: string; countAttempt: boolean }>) => {\n e.stopImmediatePropagation();\n const { responseIdentifier, countAttempt } = e.detail;\n this.validate();\n this.updateResponseVariable(responseIdentifier, 'true');\n this.#processResponse(countAttempt, true, responseIdentifier);\n };\n\n /**\n * Applies the outcomes of a processing run, ours or a backend's, in one update, with the\n * interactions' validity.\n *\n * completionStatus is response processing's to set (QTI info model §2.2.2). When an attempt of a\n * non-adaptive item ends and processing left it `unknown`, the item marks it `completed`: the\n * attempt is done. TAO does the same, and the 1EdTech results-reporting reference results expect\n * it. An adaptive item is completed only by its own processing.\n */\n #handleSetOutcomes = (e: CustomEvent<SetOutcomesDetails>) => {\n e.stopImmediatePropagation();\n const { outcomes = [], responseProcessed = false } = e.detail ?? {};\n const completion: OutcomeEntry[] = [];\n if (responseProcessed && this.adaptive === 'false') {\n const sent = outcomes.find(o => o.identifier === 'completionStatus')?.value;\n if ((sent ?? this.getVariable('completionStatus')?.value) === 'unknown') {\n completion.push({ identifier: 'completionStatus', value: 'completed' });\n }\n }\n this.#applyOutcomes([...outcomes, ...completion], this.#checkValidity(false));\n\n if (responseProcessed) {\n // `responseProcessed` marks this as the end of an attempt (vs. a plain\n // selection, which fires the same event without the flag). Lets listeners\n // react only when an attempt actually ends.\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext; responseProcessed: boolean }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context, responseProcessed: true }\n })\n );\n }\n };\n\n #handleSetTemplateValue = (e: CustomEvent<{ templateIdentifier: string; value: string | string[] | null }>) => {\n e.stopImmediatePropagation();\n const { templateIdentifier, value } = e.detail;\n if (!this.#restoredTemplateValues.has(templateIdentifier)) {\n this.updateTemplateVariable(templateIdentifier, value ?? undefined);\n }\n e.stopPropagation();\n };\n\n #handleSetCorrectResponse = (e: CustomEvent<{ responseIdentifier: string; value: string | string[] | null }>) => {\n e.stopImmediatePropagation();\n const { responseIdentifier, value } = e.detail;\n this.updateCorrectResponse(responseIdentifier, value ?? undefined);\n e.stopPropagation();\n };\n\n #handleUpdateResponseVariable = (e: CustomEvent<ResponseInteraction>) => {\n e.stopImmediatePropagation();\n\n const { responseIdentifier, response, state } = e.detail;\n this.updateResponseVariable(responseIdentifier, response);\n if (state !== undefined) {\n this._context = {\n ...this._context,\n state: {\n ...(this._context.state || {}),\n [responseIdentifier]: state\n }\n };\n }\n\n // The interaction has updated its own validity by now; publish the verdict with the answer.\n this.validate(false);\n\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n };\n\n async #processTemplates(): Promise<void> {\n const templateDeclarations = Array.from(this.querySelectorAll<LitElement>('qti-template-declaration'));\n if (templateDeclarations.length > 0) {\n await Promise.all(templateDeclarations.map(declaration => declaration.updateComplete));\n await Promise.resolve();\n }\n\n this.#templateProcessing = this.querySelector<QtiTemplateProcessing>('qti-template-processing');\n this.#templatesProcessed = true;\n // Run template processing before first presentation\n this.#runTemplateProcessing();\n }\n\n #runTemplateProcessing(): void {\n if (!this.#templateProcessing) return;\n this.#templateProcessing.process();\n this.#initialContext = { ...this._context, variables: this._context.variables };\n }\n\n /**\n * Scores the attempt. The item does not score itself: its response processing does, like a\n * backend, and sends the outcomes back in `cito-item-set-outcomes`, which the item applies in one\n * update. The item keeps the attempt count (QTI info model §2.2.2: the delivery engine maintains\n * numAttempts) and hands the new count to the run, whose rules may read it. Without response\n * processing the item only counts the attempt. A run that throws still counts the attempt and applies\n * no outcomes.\n *\n * @returns whether the item has response processing.\n */\n public processResponse(countNumAttempts = true, reportValidityAfterScoring = true): boolean {\n return this.#processResponse(countNumAttempts, reportValidityAfterScoring);\n }\n\n #processResponse(countNumAttempts: boolean, reportValidity: boolean, endedBy?: string): boolean {\n this.#checkValidity(reportValidity);\n this.#resetOtherEndAttempts(endedBy);\n\n const numAttempts = +this.getVariable('numAttempts')?.value + (countNumAttempts ? 1 : 0);\n const processor = this.querySelector<HTMLElement & Partial<ResponseProcessor>>('qti-response-processing');\n if (typeof processor?.processResponse === 'function') {\n try {\n processor.processResponse({ numAttempts });\n } catch (error) {\n // The attempt started, so it counts (QTI info model §2.2.2), as in TAO and Amp-up; the\n // outcomes of a run that failed are not applied.\n this.#applyOutcomes([{ identifier: 'numAttempts', value: String(numAttempts) }]);\n throw error;\n }\n return true;\n }\n dispatchPublic(this, 'cito-item-set-outcomes', {\n outcomes: [{ identifier: 'numAttempts', value: String(numAttempts) }],\n responseProcessed: true\n });\n return false;\n }\n\n /**\n * QTI info model §2.4.5: when an attempt ends any other way than through an end-attempt\n * interaction, that interaction's response is `false`.\n */\n #resetOtherEndAttempts(endedBy: string | undefined): void {\n const others = Array.from(this.querySelectorAll('qti-end-attempt-interaction'), el =>\n el.getAttribute('response-identifier')\n ).filter(id => id && id !== endedBy);\n if (others.length === 0) return;\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v => (others.includes(v.identifier) ? { ...v, value: 'false' } : v))\n };\n }\n\n public resetResponses() {\n this._context = this.#initialContext;\n if (this.isConnected) this.#beginFirstAttempt();\n }\n\n /**\n * QTI info model §2.2.2: completionStatus is `not_attempted` until the first attempt starts, then\n * `unknown`. The attempt starts when the candidate gets the item, so an item on screen is never\n * `not_attempted` — also not after a reset or a restore that says so.\n */\n #beginFirstAttempt(): void {\n if (this.getVariable('completionStatus')?.value !== 'not_attempted') return;\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v =>\n v.identifier === 'completionStatus' ? { ...v, value: 'unknown' } : v\n )\n };\n }\n\n protected getResponse(identifier: string): Readonly<ResponseVariable> {\n return this.getVariable(identifier) as ResponseVariable;\n }\n\n public getOutcome(identifier: string): Readonly<OutcomeVariable> {\n return this.getVariable(identifier) as OutcomeVariable;\n }\n\n protected getVariable(identifier: string): Readonly<VariableDeclaration<string | string[] | null>> {\n return this._context.variables.find(v => v.identifier === identifier) || null;\n }\n\n /** Extension point for presentation packages reacting to a candidate response change. */\n protected afterResponseVariableUpdated(): void {}\n\n // saving privates here: ------------------------------------------------------------------------------\n\n /**\n * Updates the response variable with the specified identifier to the given value.\n *\n * @protected\n *\n * This method is intended for internal use within the class and subclasses.\n * It should not be called externally by third parties.\n *\n * @param identifier - The identifier of the response variable to update.\n * @param value - The new value for the response variable.\n */\n public updateResponseVariable(identifier: string, value: string | string[] | undefined) {\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v => (v.identifier !== identifier ? v : { ...v, value: value }))\n };\n\n this.afterResponseVariableUpdated();\n\n dispatchPublic(this, 'cito-item-response-changed', {\n item: this.identifier,\n responseIdentifier: identifier,\n response: Array.isArray(value) ? [...value] : value\n });\n\n // A different answer can mean a different verdict.\n this.validate(false);\n }\n\n /**\n * Updates the template variable with the specified identifier to the given value.\n */\n public updateTemplateVariable(identifier: string, value: string | string[] | undefined) {\n const templateVariable = this._context.variables.find(v => v.identifier === identifier && v.type === 'template') as\n | TemplateVariable\n | undefined;\n\n if (!templateVariable) {\n console.warn(`Can not set qti-template-identifier: ${identifier}, it is not available`);\n return;\n }\n\n const normalizedValue =\n templateVariable.cardinality === 'single'\n ? Array.isArray(value)\n ? value[0]\n : (value ?? null)\n : value === undefined || value === null\n ? null\n : Array.isArray(value)\n ? value\n : [value];\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v =>\n v.identifier !== identifier\n ? v\n : {\n ...v,\n value: normalizedValue\n }\n )\n };\n\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n\n /**\n * Updates the correct response for the specified response variable.\n */\n public updateCorrectResponse(identifier: string, value: string | string[] | undefined) {\n const responseVariable = this.getResponse(identifier);\n\n if (!responseVariable) {\n console.warn(`Can not set correct response for identifier: ${identifier}, it is not available`);\n return;\n }\n\n const normalizedValue =\n responseVariable.cardinality === 'single'\n ? Array.isArray(value)\n ? value[0]\n : (value ?? null)\n : value === undefined || value === null\n ? null\n : Array.isArray(value)\n ? value\n : [value];\n\n this._context = {\n ...this._context,\n variables: this._context.variables.map(v =>\n v.identifier !== identifier\n ? v\n : {\n ...v,\n correctResponse: normalizedValue\n }\n )\n };\n\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n\n public setOutcomeVariable(identifier: string, value: string | string[] | undefined) {\n this.updateOutcomeVariable(identifier, value);\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n\n /**\n * Updates the outcome variable with the specified identifier to the given value.\n *\n * @protected\n *\n * This method is intended for internal use within the class and subclasses.\n * It should not be called externally by third parties.\n *\n * @param identifier - The identifier of the response variable to update.\n * @param value - The new value for the response variable.\n */\n public updateOutcomeVariable(identifier: string, value: string | string[] | undefined) {\n this.#applyOutcomes([{ identifier, value }]);\n }\n\n /**\n * Publishes the outcomes (and the validity) in one update, then a `cito-item-outcome-changed` per\n * outcome with its final value and one `cito-item-outcomes-changed` with all of them.\n * An identifier the item does not declare is skipped with a warning; a later entry for the same\n * identifier wins.\n */\n #applyOutcomes(outcomes: readonly OutcomeEntry[], valid?: boolean) {\n const values = new Map<string, OutcomeEntry['value']>();\n for (const { identifier, value } of outcomes) {\n const variable = this.getVariable(identifier);\n if (!variable) {\n console.warn(`Can not set qti-outcome-identifier: ${identifier}, it is not available`);\n continue;\n }\n values.set(identifier, variable.cardinality === 'single' ? value : Array.isArray(value) ? value : [value]);\n }\n const validChanged = valid !== undefined && valid !== this._context.valid;\n if (values.size === 0 && !validChanged) return;\n\n this._context = {\n ...this._context,\n ...(validChanged ? { valid } : {}),\n variables: this._context.variables.map(v =>\n values.has(v.identifier) ? { ...v, value: values.get(v.identifier) as string | string[] | null } : v\n )\n };\n\n if (values.size > 0) {\n for (const [outcomeIdentifier, value] of values) {\n dispatchPublic(this, 'cito-item-outcome-changed', {\n item: this.identifier,\n outcomeIdentifier,\n value: value as string | string[]\n });\n }\n dispatchPublic(this, 'cito-item-outcomes-changed', {\n item: this.identifier,\n outcomes: [...values].map(([identifier, value]) => ({ identifier, value }))\n });\n }\n }\n\n public validate(reportValidity = true): boolean {\n const isValid = this.#checkValidity(reportValidity);\n this.#publishValidity(isValid);\n return isValid;\n }\n\n #checkValidity(reportValidity: boolean): boolean {\n const isValid = this.interactionElements.every(interactionElement => interactionElement.validate());\n if (reportValidity) {\n this.reportValidity();\n }\n return isValid;\n }\n\n /** Puts the verdict in the item context, where the test and anything else can read it. */\n #publishValidity(valid: boolean): void {\n if (this._context.valid !== valid) {\n this._context = { ...this._context, valid };\n }\n }\n\n /**\n * Checks again after something the interactions' validity depends on changed without them saying\n * so (an answer handed in through `variables`), and tells the test if the verdict moved.\n */\n #revalidate(): void {\n const before = this._context.valid;\n this.validate(false);\n if (this._context.valid !== before) {\n this.dispatchEvent(\n new CustomEvent<{ itemContext: ItemContext }>('qti-item-context-updated', {\n bubbles: true,\n composed: true,\n detail: { itemContext: this._context }\n })\n );\n }\n }\n\n public reportValidity() {\n for (const interactionElement of this.interactionElements) {\n interactionElement.reportValidity();\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-assessment-item': QtiAssessmentItem;\n }\n}\n\ndeclare module '../../public-events' {\n interface PublicItemEventMap {\n /** The item rendered: its interactions are in the DOM and its validity is known. */\n 'cito-item-rendered': CustomEvent<QtiAssessmentItem>;\n }\n}\n"]}
|
|
@@ -75,16 +75,6 @@ export class QtiCustomOperator extends LitElement {
|
|
|
75
75
|
value
|
|
76
76
|
}
|
|
77
77
|
}));
|
|
78
|
-
},
|
|
79
|
-
updateResponseVariable: (responseIdentifier, response) => {
|
|
80
|
-
this.dispatchEvent(new CustomEvent('qti-interaction-response', {
|
|
81
|
-
bubbles: true,
|
|
82
|
-
composed: true,
|
|
83
|
-
detail: {
|
|
84
|
-
responseIdentifier,
|
|
85
|
-
response
|
|
86
|
-
}
|
|
87
|
-
}));
|
|
88
78
|
}
|
|
89
79
|
};
|
|
90
80
|
return this.#operatorFunction(this._context, fn, item);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qti-custom-operator.js","sourceRoot":"","sources":["../../../src/components/qti-custom-operator/qti-custom-operator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IAC/C,sEAAsE;IACtE,iBAAiB,CAAW;IAMnB,MAAM;QACb,OAAO,IAAI,CAAA,qBAAqB,IAAI,CAAC,gBAAgB,UAAU,CAAC;IAClE,CAAC;IAED,gBAAgB;QACd,gGAAgG;QAChG,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAC3E,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,YAAY,CAC5C,CAAC;QACF,IAAI,CAAC;YACH,IAAI,CAAC,iBAAiB,GAAG,IAAI,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QACjG,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,kDAAkD,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAEM,SAAS;QACd,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACnD,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,EAAE,GAAG;YACT,QAAQ,EAAE,CAAC,kBAA0B,EAAE,EAAE,CACvC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,kBAAkB,CAAC,EAAE,KAAK,IAAI,EAAE;YACtF,OAAO,EAAE,CAAC,kBAA0B,EAAE,EAAE,CACrC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,kBAAkB,CAAsB;gBAC3F,EAAE,eAAe,IAAI,EAAE;SAC5B,CAAC;QACF,MAAM,IAAI,GAAG;YACX,WAAW,EAAE,CAAC,kBAA0B,EAAE,EAAE,CAC1C,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,kBAAkB,CAAC;YACzE,qBAAqB,EAAE,CAAC,iBAAyB,EAAE,KAAwB,EAAE,EAAE;gBAC7E,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAA0D,uBAAuB,EAAE;oBAChG,OAAO,EAAE,IAAI;oBACb,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE;wBACN,iBAAiB;wBACjB,KAAK;qBACN;iBACF,CAAC,CACH,CAAC;YACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"qti-custom-operator.js","sourceRoot":"","sources":["../../../src/components/qti-custom-operator/qti-custom-operator.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { LitElement, html } from 'lit';\nimport { state } from 'lit/decorators.js';\n\nimport { getCustomOperator, itemContext } from '@qti-components/base';\n\nimport type { CustomOperatorValue, ResponseVariable } from '@qti-components/base';\nimport type { Calculate } from '@qti-components/base';\nimport type { ItemContext } from '@qti-components/base';\n\n/**\n * https://www.imsglobal.org/spec/qti/v3p0/impl#h.fi29q8dubjgw\n *\n * A custom operator is outside the QTI vocabulary, so what it does is supplied\n * by the delivery engine rather than by the item. Two ways to supply it:\n *\n * `definition` names an operator the host registered with\n * `registerCustomOperator`, or one of the built-ins (`Trim`, `ToAscii`,\n * `ParseCommaDecimal` under the `depcp:`, `questify:` and `qade:` prefixes).\n * The operator is handed the calculated values of the child expressions:\n *\n * ```xml\n * <qti-custom-operator definition=\"depcp:Trim\">\n * <qti-variable identifier=\"RESPONSE\"/>\n * </qti-custom-operator>\n * ```\n *\n * `class=\"js.org\"` instead runs inline JavaScript out of a CDATA section:\n *\n * ```xml\n * <qti-custom-operator class=\"js.org\">\n * <qti-base-value base-type=\"string\"><![CDATA[\n * console.log(context.variables);\n * return 'B'\n * ]]></qti-base-value>\n * </qti-custom-operator>\n * ```\n *\n * `definition` is checked first; the two do not interact.\n */\n\nexport class QtiCustomOperator extends LitElement implements Calculate {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n #operatorFunction: Function;\n\n @consume({ context: itemContext, subscribe: true })\n @state()\n private _context?: ItemContext;\n\n override render() {\n return html`<slot @slotchange=${this.handleSlotChange}></slot>`;\n }\n\n handleSlotChange() {\n // expecting <[!CDATA[ ... ]]> is converted into <!-- ... --> with qti-transform: cDataToComment\n const commentNode = Array.from(this.firstElementChild?.childNodes ?? []).find(\n node => node.nodeType === Node.COMMENT_NODE\n );\n try {\n this.#operatorFunction = new Function('context', 'fn', 'item', commentNode?.textContent ?? '');\n } catch (e) {\n console.error('custom-operator contains invalid javascript code', e);\n }\n }\n\n public calculate() {\n const definition = this.getAttribute('definition');\n if (definition) {\n return this.#applyDefinedOperator(definition);\n }\n\n const fn = {\n variable: (responseIdentifier: string) =>\n this._context?.variables.find(v => v.identifier === responseIdentifier)?.value ?? '',\n correct: (responseIdentifier: string) =>\n (this._context?.variables.find(v => v.identifier === responseIdentifier) as ResponseVariable)\n ?.correctResponse ?? ''\n };\n const item = {\n getVariable: (variableIdentifier: string) =>\n this._context?.variables.find(v => v.identifier === variableIdentifier),\n updateOutcomeVariable: (outcomeIdentifier: string, value: string | string[]) => {\n this.dispatchEvent(\n new CustomEvent<{ outcomeIdentifier: string; value: string | string[] }>('qti-set-outcome-value', {\n bubbles: true,\n composed: true,\n detail: {\n outcomeIdentifier,\n value\n }\n })\n );\n }\n };\n\n return this.#operatorFunction(this._context, fn, item);\n }\n\n /**\n * An operator the host registered, or a built-in. An unknown `definition` is\n * NULL rather than an error: the item names an operator this engine does not\n * provide, which the surrounding expression can still test with\n * `qti-is-null`.\n */\n #applyDefinedOperator(definition: string) {\n const operator = getCustomOperator(definition);\n if (!operator) {\n console.warn(`qti-custom-operator: no operator registered for definition \"${definition}\"`);\n return null;\n }\n\n const values = Array.from(this.children).map(child => {\n const calculate = (child as Partial<Calculate>).calculate;\n return typeof calculate === 'function' ? (calculate.call(child) as CustomOperatorValue) : null;\n });\n\n return operator(values);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-custom-operator': QtiCustomOperator;\n }\n}\n"]}
|
|
@@ -2,6 +2,9 @@ import { QtiFeedback } from '@qti-components/base';
|
|
|
2
2
|
export declare class QtiFeedbackBlock extends QtiFeedback {
|
|
3
3
|
static styles: import("lit").CSSResult;
|
|
4
4
|
render(): import("lit").TemplateResult<1>;
|
|
5
|
+
/** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */
|
|
6
|
+
protected feedbackShowing(): boolean;
|
|
7
|
+
protected feedbackHiding(): boolean;
|
|
5
8
|
connectedCallback(): void;
|
|
6
9
|
}
|
|
7
10
|
declare global {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { css, html } from 'lit';
|
|
2
2
|
import { QtiFeedback } from '@qti-components/base';
|
|
3
|
+
import { dispatchFeedback } from '../../internal/feedback-events';
|
|
3
4
|
export class QtiFeedbackBlock extends QtiFeedback {
|
|
4
5
|
static { this.styles = css `
|
|
5
6
|
:host {
|
|
@@ -15,6 +16,13 @@ export class QtiFeedbackBlock extends QtiFeedback {
|
|
|
15
16
|
render() {
|
|
16
17
|
return html ` <slot part="feedback" class="feedback ${this.showStatus}"></slot> `;
|
|
17
18
|
}
|
|
19
|
+
/** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */
|
|
20
|
+
feedbackShowing() {
|
|
21
|
+
return dispatchFeedback(this, 'cito-feedback-show', 'block', this.identifier);
|
|
22
|
+
}
|
|
23
|
+
feedbackHiding() {
|
|
24
|
+
return dispatchFeedback(this, 'cito-feedback-hide', 'block', this.identifier);
|
|
25
|
+
}
|
|
18
26
|
connectedCallback() {
|
|
19
27
|
super.connectedCallback();
|
|
20
28
|
this.checkShowFeedback(this.outcomeIdentifier);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qti-feedback-block.js","sourceRoot":"","sources":["../../../src/components/qti-feedback-block/qti-feedback-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,OAAO,gBAAiB,SAAQ,WAAW;aAC/B,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;GAU3B,CAAC;IAEO,MAAM;QACb,OAAO,IAAI,CAAA,0CAA0C,IAAI,CAAC,UAAU,YAAY,CAAC;IACnF,CAAC;IAEe,iBAAiB;QAC/B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACjD,CAAC","sourcesContent":["import { css, html } from 'lit';\n\nimport { QtiFeedback } from '@qti-components/base';\n\nexport class QtiFeedbackBlock extends QtiFeedback {\n static override styles = css`\n :host {\n display: block;\n }\n .on {\n display: block;\n }\n .off {\n display: none;\n }\n `;\n\n override render() {\n return html` <slot part=\"feedback\" class=\"feedback ${this.showStatus}\"></slot> `;\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.checkShowFeedback(this.outcomeIdentifier);\n }\n}\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-feedback-block': QtiFeedbackBlock;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"qti-feedback-block.js","sourceRoot":"","sources":["../../../src/components/qti-feedback-block/qti-feedback-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,MAAM,OAAO,gBAAiB,SAAQ,WAAW;aAC/B,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;GAU3B,CAAC;IAEO,MAAM;QACb,OAAO,IAAI,CAAA,0CAA0C,IAAI,CAAC,UAAU,YAAY,CAAC;IACnF,CAAC;IAED,4GAA4G;IACzF,eAAe;QAChC,OAAO,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAChF,CAAC;IAEkB,cAAc;QAC/B,OAAO,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAChF,CAAC;IAEe,iBAAiB;QAC/B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACjD,CAAC","sourcesContent":["import { css, html } from 'lit';\n\nimport { QtiFeedback } from '@qti-components/base';\n\nimport { dispatchFeedback } from '../../internal/feedback-events';\n\nexport class QtiFeedbackBlock extends QtiFeedback {\n static override styles = css`\n :host {\n display: block;\n }\n .on {\n display: block;\n }\n .off {\n display: none;\n }\n `;\n\n override render() {\n return html` <slot part=\"feedback\" class=\"feedback ${this.showStatus}\"></slot> `;\n }\n\n /** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */\n protected override feedbackShowing(): boolean {\n return dispatchFeedback(this, 'cito-feedback-show', 'block', this.identifier);\n }\n\n protected override feedbackHiding(): boolean {\n return dispatchFeedback(this, 'cito-feedback-hide', 'block', this.identifier);\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.checkShowFeedback(this.outcomeIdentifier);\n }\n}\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-feedback-block': QtiFeedbackBlock;\n }\n}\n"]}
|
|
@@ -2,6 +2,9 @@ import { QtiFeedback } from '@qti-components/base';
|
|
|
2
2
|
export declare class QtiFeedbackInline extends QtiFeedback {
|
|
3
3
|
static styles: import("lit").CSSResult;
|
|
4
4
|
render: () => import("lit").TemplateResult<1>;
|
|
5
|
+
/** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */
|
|
6
|
+
protected feedbackShowing(): boolean;
|
|
7
|
+
protected feedbackHiding(): boolean;
|
|
5
8
|
connectedCallback(): void;
|
|
6
9
|
}
|
|
7
10
|
declare global {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { css, html } from 'lit';
|
|
2
2
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
3
3
|
import { QtiFeedback } from '@qti-components/base';
|
|
4
|
+
import { dispatchFeedback } from '../../internal/feedback-events';
|
|
4
5
|
export class QtiFeedbackInline extends QtiFeedback {
|
|
5
6
|
constructor() {
|
|
6
7
|
super(...arguments);
|
|
@@ -14,6 +15,13 @@ export class QtiFeedbackInline extends QtiFeedback {
|
|
|
14
15
|
display: none;
|
|
15
16
|
}
|
|
16
17
|
`; }
|
|
18
|
+
/** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */
|
|
19
|
+
feedbackShowing() {
|
|
20
|
+
return dispatchFeedback(this, 'cito-feedback-show', 'inline', this.identifier);
|
|
21
|
+
}
|
|
22
|
+
feedbackHiding() {
|
|
23
|
+
return dispatchFeedback(this, 'cito-feedback-hide', 'inline', this.identifier);
|
|
24
|
+
}
|
|
17
25
|
connectedCallback() {
|
|
18
26
|
super.connectedCallback();
|
|
19
27
|
this.checkShowFeedback(this.outcomeIdentifier);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qti-feedback-inline.js","sourceRoot":"","sources":["../../../src/components/qti-feedback-inline/qti-feedback-inline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAAlD;;QAUW,WAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAA,iCAAiC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"qti-feedback-inline.js","sourceRoot":"","sources":["../../../src/components/qti-feedback-inline/qti-feedback-inline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAAlD;;QAUW,WAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAA,iCAAiC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;IAetG,CAAC;aAxBiB,WAAM,GAAG,GAAG,CAAA;;;;;;;GAO3B,AAPqB,CAOpB;IAIF,4GAA4G;IACzF,eAAe;QAChC,OAAO,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACjF,CAAC;IAEkB,cAAc;QAC/B,OAAO,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACjF,CAAC;IAEe,iBAAiB;QAC/B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACjD,CAAC","sourcesContent":["import { css, html } from 'lit';\nimport { ifDefined } from 'lit/directives/if-defined.js';\n\nimport { QtiFeedback } from '@qti-components/base';\n\nimport { dispatchFeedback } from '../../internal/feedback-events';\n\nexport class QtiFeedbackInline extends QtiFeedback {\n static override styles = css`\n .on {\n display: inline-block;\n }\n .off {\n display: none;\n }\n `;\n\n override render = () => html` <slot part=\"feedback\" class=\"${ifDefined(this.showStatus)}\"></slot> `;\n\n /** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */\n protected override feedbackShowing(): boolean {\n return dispatchFeedback(this, 'cito-feedback-show', 'inline', this.identifier);\n }\n\n protected override feedbackHiding(): boolean {\n return dispatchFeedback(this, 'cito-feedback-hide', 'inline', this.identifier);\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.checkShowFeedback(this.outcomeIdentifier);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-feedback-inline': QtiFeedbackInline;\n }\n}\n"]}
|
|
@@ -4,6 +4,9 @@ export declare class QtiModalFeedback extends QtiFeedback {
|
|
|
4
4
|
render(): import("lit").TemplateResult<1>;
|
|
5
5
|
openFeedback(): void;
|
|
6
6
|
closeFeedback(): void;
|
|
7
|
+
/** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */
|
|
8
|
+
protected feedbackShowing(): boolean;
|
|
9
|
+
protected feedbackHiding(): boolean;
|
|
7
10
|
connectedCallback(): void;
|
|
8
11
|
protected updated(changedProperties: Map<string | number | symbol, unknown>): void;
|
|
9
12
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { css, html } from 'lit';
|
|
2
2
|
import { QtiFeedback } from '@qti-components/base';
|
|
3
|
+
import { dispatchFeedback } from '../../internal/feedback-events';
|
|
3
4
|
export class QtiModalFeedback extends QtiFeedback {
|
|
4
5
|
static { this.styles = css `
|
|
5
6
|
.cito-dialog {
|
|
@@ -63,6 +64,13 @@ export class QtiModalFeedback extends QtiFeedback {
|
|
|
63
64
|
this.showStatus = 'off';
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
/** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */
|
|
68
|
+
feedbackShowing() {
|
|
69
|
+
return dispatchFeedback(this, 'cito-feedback-show', 'modal', this.identifier);
|
|
70
|
+
}
|
|
71
|
+
feedbackHiding() {
|
|
72
|
+
return dispatchFeedback(this, 'cito-feedback-hide', 'modal', this.identifier);
|
|
73
|
+
}
|
|
66
74
|
connectedCallback() {
|
|
67
75
|
super.connectedCallback();
|
|
68
76
|
if (this.showStatus === 'on') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qti-modal-feedback.js","sourceRoot":"","sources":["../../../src/components/qti-modal-feedback/qti-modal-feedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,OAAO,gBAAiB,SAAQ,WAAW;aAC/B,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsC3B,CAAC;IAEO,MAAM;QACb,OAAO,IAAI,CAAA;2DAC4C,IAAI,CAAC,UAAU,KAAK,IAAI;;;wDAG3B,IAAI,CAAC,aAAa;;;KAGrE,CAAC;IACJ,CAAC;IAED,YAAY;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,QAAQ,CAA6B,CAAC;QACpF,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,aAAa;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,QAAQ,CAA6B,CAAC;QACpF,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAEe,iBAAiB;QAC/B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAEkB,OAAO,CAAC,iBAAyD;QAClF,IAAI,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC","sourcesContent":["import { css, html } from 'lit';\n\nimport { QtiFeedback } from '@qti-components/base';\n\nexport class QtiModalFeedback extends QtiFeedback {\n static override styles = css`\n .cito-dialog {\n background: var(--qti-bg);\n border: var(--qti-border-thickness) var(--qti-border-style) var(--qti-border-color);\n border-radius: var(--qti-border-radius);\n padding: var(--qti-padding-box);\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 1000;\n width: auto;\n max-width: 90%;\n }\n\n .button {\n border-radius: var(--qti-border-radius);\n padding: var(--qti-padding-box);\n background-color: var(--qti-bg-active);\n border: var(--qti-border-active);\n cursor: pointer;\n position: relative;\n display: inline-block;\n }\n\n /* Inlined from --qti-disabled-bg / --qti-disabled-color, which this button was the only reader\n of anywhere in the repo. They were named as a global disabled vocabulary but no interaction\n ever used them: the theme's disabled treatment is cursor only (see the note in qti-mixins.css). */\n .button:disabled {\n background-color: transparent;\n color: var(--qti-fg);\n cursor: not-allowed;\n }\n\n .button:focus {\n outline: var(--qti-focus-border-width) solid var(--qti-focus-color);\n }\n `;\n\n override render() {\n return html`\n <dialog class=\"cito-dialog\" part=\"feedback\" ?open=\"${this.showStatus === 'on'}\">\n <slot></slot>\n <div style=\"margin-top: var(--qti-gap); text-align: center;\">\n <button class=\"button close-button\" @click=\"${this.closeFeedback}\">Close</button>\n </div>\n </dialog>\n `;\n }\n\n openFeedback() {\n const dialog = this.shadowRoot?.querySelector('dialog') as HTMLDialogElement | null;\n if (dialog && !dialog.open) {\n dialog.showModal();\n }\n }\n\n closeFeedback() {\n const dialog = this.shadowRoot?.querySelector('dialog') as HTMLDialogElement | null;\n if (dialog && dialog.open) {\n dialog.close();\n this.showStatus = 'off';\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n if (this.showStatus === 'on') {\n this.openFeedback();\n }\n }\n\n protected override updated(changedProperties: Map<string | number | symbol, unknown>): void {\n if (changedProperties.has('showStatus')) {\n if (this.showStatus === 'on') {\n this.openFeedback();\n } else {\n this.closeFeedback();\n }\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-modal-feedback': QtiModalFeedback;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"qti-modal-feedback.js","sourceRoot":"","sources":["../../../src/components/qti-modal-feedback/qti-modal-feedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,MAAM,OAAO,gBAAiB,SAAQ,WAAW;aAC/B,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsC3B,CAAC;IAEO,MAAM;QACb,OAAO,IAAI,CAAA;2DAC4C,IAAI,CAAC,UAAU,KAAK,IAAI;;;wDAG3B,IAAI,CAAC,aAAa;;;KAGrE,CAAC;IACJ,CAAC;IAED,YAAY;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,QAAQ,CAA6B,CAAC;QACpF,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,aAAa;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,QAAQ,CAA6B,CAAC;QACpF,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,4GAA4G;IACzF,eAAe;QAChC,OAAO,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAChF,CAAC;IAEkB,cAAc;QAC/B,OAAO,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAChF,CAAC;IAEe,iBAAiB;QAC/B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAEkB,OAAO,CAAC,iBAAyD;QAClF,IAAI,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC","sourcesContent":["import { css, html } from 'lit';\n\nimport { QtiFeedback } from '@qti-components/base';\n\nimport { dispatchFeedback } from '../../internal/feedback-events';\n\nexport class QtiModalFeedback extends QtiFeedback {\n static override styles = css`\n .cito-dialog {\n background: var(--qti-bg);\n border: var(--qti-border-thickness) var(--qti-border-style) var(--qti-border-color);\n border-radius: var(--qti-border-radius);\n padding: var(--qti-padding-box);\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 1000;\n width: auto;\n max-width: 90%;\n }\n\n .button {\n border-radius: var(--qti-border-radius);\n padding: var(--qti-padding-box);\n background-color: var(--qti-bg-active);\n border: var(--qti-border-active);\n cursor: pointer;\n position: relative;\n display: inline-block;\n }\n\n /* Inlined from --qti-disabled-bg / --qti-disabled-color, which this button was the only reader\n of anywhere in the repo. They were named as a global disabled vocabulary but no interaction\n ever used them: the theme's disabled treatment is cursor only (see the note in qti-mixins.css). */\n .button:disabled {\n background-color: transparent;\n color: var(--qti-fg);\n cursor: not-allowed;\n }\n\n .button:focus {\n outline: var(--qti-focus-border-width) solid var(--qti-focus-color);\n }\n `;\n\n override render() {\n return html`\n <dialog class=\"cito-dialog\" part=\"feedback\" ?open=\"${this.showStatus === 'on'}\">\n <slot></slot>\n <div style=\"margin-top: var(--qti-gap); text-align: center;\">\n <button class=\"button close-button\" @click=\"${this.closeFeedback}\">Close</button>\n </div>\n </dialog>\n `;\n }\n\n openFeedback() {\n const dialog = this.shadowRoot?.querySelector('dialog') as HTMLDialogElement | null;\n if (dialog && !dialog.open) {\n dialog.showModal();\n }\n }\n\n closeFeedback() {\n const dialog = this.shadowRoot?.querySelector('dialog') as HTMLDialogElement | null;\n if (dialog && dialog.open) {\n dialog.close();\n this.showStatus = 'off';\n }\n }\n\n /** `cito-feedback-show`: a listener that calls `preventDefault()` keeps this hidden and shows it itself. */\n protected override feedbackShowing(): boolean {\n return dispatchFeedback(this, 'cito-feedback-show', 'modal', this.identifier);\n }\n\n protected override feedbackHiding(): boolean {\n return dispatchFeedback(this, 'cito-feedback-hide', 'modal', this.identifier);\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n if (this.showStatus === 'on') {\n this.openFeedback();\n }\n }\n\n protected override updated(changedProperties: Map<string | number | symbol, unknown>): void {\n if (changedProperties.has('showStatus')) {\n if (this.showStatus === 'on') {\n this.openFeedback();\n } else {\n this.closeFeedback();\n }\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-modal-feedback': QtiModalFeedback;\n }\n}\n"]}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
import type { PropertyValueMap } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* Response processing as the item's own backend: it reads the item context, runs its rules once and
|
|
5
|
+
* sends the outcomes and the attempt count back in one `cito-item-set-outcomes`. The item applies
|
|
6
|
+
* them; a host that scores elsewhere sends the same event instead.
|
|
7
|
+
*/
|
|
3
8
|
export declare class QtiResponseProcessing extends LitElement {
|
|
9
|
+
#private;
|
|
4
10
|
static styles: import("lit").CSSResult[];
|
|
11
|
+
constructor();
|
|
5
12
|
render(): import("lit").TemplateResult<1>;
|
|
6
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Scores the attempt on the copy: sets `numAttempts` to the count the item hands over, resets a
|
|
15
|
+
* non-adaptive item's outcomes to their defaults (QTI info model §2.5), runs the rules and sends
|
|
16
|
+
* every outcome and `numAttempts` in one `cito-item-set-outcomes`. The item applies them and publishes, which gives this element a
|
|
17
|
+
* fresh copy. A rule that throws ends the run and the error propagates; nothing is sent, and the
|
|
18
|
+
* run's writes stay in the copy until the item's next update.
|
|
19
|
+
*/
|
|
20
|
+
processResponse({ numAttempts }: {
|
|
21
|
+
numAttempts: number;
|
|
22
|
+
}): void;
|
|
7
23
|
firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
8
24
|
}
|
|
9
25
|
declare global {
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import { ContextConsumer, ContextProvider } from '@lit/context';
|
|
1
2
|
import { css, html, LitElement } from 'lit';
|
|
2
|
-
import { QtiExitResponseSignal } from '@qti-components/base';
|
|
3
|
+
import { itemContext, QtiExitResponseSignal } from '@qti-components/base';
|
|
3
4
|
import { mapResponse, mapResponsePoint, matchCorrect } from '../../internal/template-strings';
|
|
5
|
+
import { dispatchPublic } from '../../public-events';
|
|
4
6
|
/** The response processing templates we substitute for, keyed by the file name in `template`. */
|
|
5
7
|
const responseProcessingTemplates = {
|
|
6
8
|
map_response: mapResponse,
|
|
7
9
|
map_response_point: mapResponsePoint,
|
|
8
10
|
match_correct: matchCorrect
|
|
9
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Response processing as the item's own backend: it reads the item context, runs its rules once and
|
|
14
|
+
* sends the outcomes and the attempt count back in one `cito-item-set-outcomes`. The item applies
|
|
15
|
+
* them; a host that scores elsewhere sends the same event instead.
|
|
16
|
+
*/
|
|
10
17
|
export class QtiResponseProcessing extends LitElement {
|
|
11
18
|
static { this.styles = [
|
|
12
19
|
css `
|
|
@@ -15,13 +22,70 @@ export class QtiResponseProcessing extends LitElement {
|
|
|
15
22
|
}
|
|
16
23
|
`
|
|
17
24
|
]; }
|
|
25
|
+
/**
|
|
26
|
+
* The rules inside read and write this element's copy of the item context, never the item's. It
|
|
27
|
+
* is provided under the same `itemContext`: the nearest provider wins, so every expression in
|
|
28
|
+
* here gets the copy without knowing about it.
|
|
29
|
+
*/
|
|
30
|
+
#provider = new ContextProvider(this, { context: itemContext });
|
|
31
|
+
#copy;
|
|
32
|
+
constructor() {
|
|
33
|
+
super();
|
|
34
|
+
new ContextConsumer(this, {
|
|
35
|
+
context: itemContext,
|
|
36
|
+
subscribe: true,
|
|
37
|
+
// Every variable its own object, so a write changes the copy and not the item's context.
|
|
38
|
+
callback: context => {
|
|
39
|
+
this.#copy = { ...context, variables: context.variables.map(v => ({ ...v })) };
|
|
40
|
+
this.#provider.setValue(this.#copy);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// Every rule that sets an outcome sits in here: the write lands in the copy, so a later rule
|
|
44
|
+
// reads it, and never reaches the item (or the test above it, whose outcome processing listens
|
|
45
|
+
// for the same name).
|
|
46
|
+
this.addEventListener('qti-set-outcome-value', (e) => {
|
|
47
|
+
e.stopImmediatePropagation();
|
|
48
|
+
const variable = this.#copy?.variables.find(v => v.identifier === e.detail.outcomeIdentifier);
|
|
49
|
+
if (!variable) {
|
|
50
|
+
console.warn(`Can not set qti-outcome-identifier: ${e.detail.outcomeIdentifier}, it is not available`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const { value } = e.detail;
|
|
54
|
+
variable.value = variable.cardinality === 'single' ? value : Array.isArray(value) ? value : [value];
|
|
55
|
+
});
|
|
56
|
+
}
|
|
18
57
|
render() {
|
|
19
58
|
return html `<slot></slot>`;
|
|
20
59
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Scores the attempt on the copy: sets `numAttempts` to the count the item hands over, resets a
|
|
62
|
+
* non-adaptive item's outcomes to their defaults (QTI info model §2.5), runs the rules and sends
|
|
63
|
+
* every outcome and `numAttempts` in one `cito-item-set-outcomes`. The item applies them and publishes, which gives this element a
|
|
64
|
+
* fresh copy. A rule that throws ends the run and the error propagates; nothing is sent, and the
|
|
65
|
+
* run's writes stay in the copy until the item's next update.
|
|
66
|
+
*/
|
|
67
|
+
processResponse({ numAttempts }) {
|
|
68
|
+
const copy = this.#copy;
|
|
69
|
+
if (!copy)
|
|
24
70
|
return;
|
|
71
|
+
const reset = this.closest('qti-assessment-item')?.getAttribute('adaptive') !== 'true';
|
|
72
|
+
for (const variable of copy.variables) {
|
|
73
|
+
if (variable.identifier === 'numAttempts')
|
|
74
|
+
variable.value = String(numAttempts);
|
|
75
|
+
// completionStatus is built in: it has no default to reset to, and keeps its value (as in TAO).
|
|
76
|
+
if (variable.type === 'outcome' && reset && variable.identifier !== 'completionStatus') {
|
|
77
|
+
variable.value = defaultValueOf(variable);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.#runRules();
|
|
81
|
+
dispatchPublic(this, 'cito-item-set-outcomes', {
|
|
82
|
+
outcomes: copy.variables
|
|
83
|
+
.filter(v => v.type === 'outcome' || v.identifier === 'numAttempts')
|
|
84
|
+
.map(({ identifier, value }) => ({ identifier, value })),
|
|
85
|
+
responseProcessed: true
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
#runRules() {
|
|
25
89
|
const rules = [...this.children];
|
|
26
90
|
try {
|
|
27
91
|
for (const rule of rules) {
|
|
@@ -53,4 +117,11 @@ export class QtiResponseProcessing extends LitElement {
|
|
|
53
117
|
this.innerHTML = rules;
|
|
54
118
|
}
|
|
55
119
|
}
|
|
120
|
+
/** The declared default; a numeric outcome without one starts at 0. */
|
|
121
|
+
function defaultValueOf(variable) {
|
|
122
|
+
const value = ('defaultValue' in variable ? variable.defaultValue : null) ?? null;
|
|
123
|
+
if (value === null && (variable.baseType === 'integer' || variable.baseType === 'float'))
|
|
124
|
+
return '0';
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
56
127
|
//# sourceMappingURL=qti-response-processing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qti-response-processing.js","sourceRoot":"","sources":["../../../src/components/qti-response-processing/qti-response-processing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAE5C,OAAO,EAAE,qBAAqB,EAAoB,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAI9F,iGAAiG;AACjG,MAAM,2BAA2B,GAA2B;IAC1D,YAAY,EAAE,WAAW;IACzB,kBAAkB,EAAE,gBAAgB;IACpC,aAAa,EAAE,YAAY;CAC5B,CAAC;AAEF,MAAM,OAAO,qBAAsB,SAAQ,UAAU;aACnC,WAAM,GAAG;QACvB,GAAG,CAAA;;;;KAIF;KACF,CAAC;IAEO,MAAM;QACb,OAAO,IAAI,CAAA,eAAe,CAAC;IAC7B,CAAC;IAEM,OAAO;QACZ,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAC3D,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAA6B,CAAC;QAC7D,IAAI,CAAC;YACH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qEAAqE;YACrE,wEAAwE;YACxE,yEAAyE;YACzE,IAAI,CAAC,CAAC,KAAK,YAAY,qBAAqB,CAAC;gBAAE,MAAM,KAAK,CAAC;QAC7D,CAAC;IACH,CAAC;IAEe,YAAY,CAAC,kBAAqE;QAChG,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,2BAA2B,CAAC,YAAY,CAAC,CAAC;QACxD,uFAAuF;QACvF,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,+FAA+F;QAC/F,yFAAyF;QACzF,8FAA8F;QAC9F,6FAA6F;QAC7F,4EAA4E;QAC5E,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC","sourcesContent":["import { css, html, LitElement } from 'lit';\n\nimport { QtiExitResponseSignal, type QtiRuleBase } from '@qti-components/base';\n\nimport { mapResponse, mapResponsePoint, matchCorrect } from '../../internal/template-strings';\n\nimport type { PropertyValueMap } from 'lit';\n\n/** The response processing templates we substitute for, keyed by the file name in `template`. */\nconst responseProcessingTemplates: Record<string, string> = {\n map_response: mapResponse,\n map_response_point: mapResponsePoint,\n match_correct: matchCorrect\n};\n\nexport class QtiResponseProcessing extends LitElement {\n static override styles = [\n css`\n :host {\n display: none;\n }\n `\n ];\n\n override render() {\n return html`<slot></slot>`;\n }\n\n public process() {\n const assessmentItem = this.closest('qti-assessment-item');\n if (!assessmentItem) return;\n const rules = [...this.children] as unknown as QtiRuleBase[];\n try {\n for (const rule of rules) {\n rule.process();\n }\n } catch (error) {\n // `qti-exit-response` ends the attempt's processing from wherever it\n // sits, however deeply nested. Reaching here is the rule doing its job,\n // so the run simply stops; anything else is a real failure and rethrows.\n if (!(error instanceof QtiExitResponseSignal)) throw error;\n }\n }\n\n public override firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {\n const template = this.getAttribute('template');\n if (!template) return;\n\n const templateName = template.split('/').pop()!.replace('.xml', '');\n const rules = responseProcessingTemplates[templateName];\n // Leave an unknown template's authored children alone; there is nothing to substitute.\n if (!rules) return;\n\n // Parsed through this element's own `innerHTML` rather than a fragment created off `document`:\n // the HTML fragment parsing algorithm takes its custom element registry from the context\n // element, so the rules are upgraded with the registry this element lives in. A fragment from\n // `document.createRange()` is parsed against the global registry, which leaves every rule an\n // unupgraded HTMLElement when the item was rendered into a scoped registry.\n this.innerHTML = rules;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-response-processing': QtiResponseProcessing;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"qti-response-processing.js","sourceRoot":"","sources":["../../../src/components/qti-response-processing/qti-response-processing.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContextConsumer, ContextProvider } from '@lit/context';\nimport { css, html, LitElement } from 'lit';\n\nimport { itemContext, QtiExitResponseSignal, type QtiRuleBase } from '@qti-components/base';\n\nimport { mapResponse, mapResponsePoint, matchCorrect } from '../../internal/template-strings';\nimport { dispatchPublic } from '../../public-events';\n\nimport type { ItemContext, OutcomeVariable } from '@qti-components/base';\nimport type { PropertyValueMap } from 'lit';\n\ntype OutcomeValue = string | string[] | null | undefined;\n\n/** The response processing templates we substitute for, keyed by the file name in `template`. */\nconst responseProcessingTemplates: Record<string, string> = {\n map_response: mapResponse,\n map_response_point: mapResponsePoint,\n match_correct: matchCorrect\n};\n\n/**\n * Response processing as the item's own backend: it reads the item context, runs its rules once and\n * sends the outcomes and the attempt count back in one `cito-item-set-outcomes`. The item applies\n * them; a host that scores elsewhere sends the same event instead.\n */\nexport class QtiResponseProcessing extends LitElement {\n static override styles = [\n css`\n :host {\n display: none;\n }\n `\n ];\n\n /**\n * The rules inside read and write this element's copy of the item context, never the item's. It\n * is provided under the same `itemContext`: the nearest provider wins, so every expression in\n * here gets the copy without knowing about it.\n */\n #provider = new ContextProvider(this, { context: itemContext });\n #copy?: ItemContext;\n\n constructor() {\n super();\n new ContextConsumer(this, {\n context: itemContext,\n subscribe: true,\n // Every variable its own object, so a write changes the copy and not the item's context.\n callback: context => {\n this.#copy = { ...context, variables: context.variables.map(v => ({ ...v })) };\n this.#provider.setValue(this.#copy);\n }\n });\n // Every rule that sets an outcome sits in here: the write lands in the copy, so a later rule\n // reads it, and never reaches the item (or the test above it, whose outcome processing listens\n // for the same name).\n this.addEventListener(\n 'qti-set-outcome-value',\n (e: CustomEvent<{ outcomeIdentifier: string; value: OutcomeValue }>) => {\n e.stopImmediatePropagation();\n const variable = this.#copy?.variables.find(v => v.identifier === e.detail.outcomeIdentifier);\n if (!variable) {\n console.warn(`Can not set qti-outcome-identifier: ${e.detail.outcomeIdentifier}, it is not available`);\n return;\n }\n const { value } = e.detail;\n variable.value = variable.cardinality === 'single' ? value : Array.isArray(value) ? value : [value];\n }\n );\n }\n\n override render() {\n return html`<slot></slot>`;\n }\n\n /**\n * Scores the attempt on the copy: sets `numAttempts` to the count the item hands over, resets a\n * non-adaptive item's outcomes to their defaults (QTI info model §2.5), runs the rules and sends\n * every outcome and `numAttempts` in one `cito-item-set-outcomes`. The item applies them and publishes, which gives this element a\n * fresh copy. A rule that throws ends the run and the error propagates; nothing is sent, and the\n * run's writes stay in the copy until the item's next update.\n */\n public processResponse({ numAttempts }: { numAttempts: number }): void {\n const copy = this.#copy;\n if (!copy) return;\n const reset = this.closest('qti-assessment-item')?.getAttribute('adaptive') !== 'true';\n for (const variable of copy.variables) {\n if (variable.identifier === 'numAttempts') variable.value = String(numAttempts);\n // completionStatus is built in: it has no default to reset to, and keeps its value (as in TAO).\n if (variable.type === 'outcome' && reset && variable.identifier !== 'completionStatus') {\n variable.value = defaultValueOf(variable as OutcomeVariable);\n }\n }\n\n this.#runRules();\n\n dispatchPublic(this, 'cito-item-set-outcomes', {\n outcomes: copy.variables\n .filter(v => v.type === 'outcome' || v.identifier === 'numAttempts')\n .map(({ identifier, value }) => ({ identifier, value })),\n responseProcessed: true\n });\n }\n\n #runRules() {\n const rules = [...this.children] as unknown as QtiRuleBase[];\n try {\n for (const rule of rules) {\n rule.process();\n }\n } catch (error) {\n // `qti-exit-response` ends the attempt's processing from wherever it\n // sits, however deeply nested. Reaching here is the rule doing its job,\n // so the run simply stops; anything else is a real failure and rethrows.\n if (!(error instanceof QtiExitResponseSignal)) throw error;\n }\n }\n\n public override firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {\n const template = this.getAttribute('template');\n if (!template) return;\n\n const templateName = template.split('/').pop()!.replace('.xml', '');\n const rules = responseProcessingTemplates[templateName];\n // Leave an unknown template's authored children alone; there is nothing to substitute.\n if (!rules) return;\n\n // Parsed through this element's own `innerHTML` rather than a fragment created off `document`:\n // the HTML fragment parsing algorithm takes its custom element registry from the context\n // element, so the rules are upgraded with the registry this element lives in. A fragment from\n // `document.createRange()` is parsed against the global registry, which leaves every rule an\n // unupgraded HTMLElement when the item was rendered into a scoped registry.\n this.innerHTML = rules;\n }\n}\n\n/** The declared default; a numeric outcome without one starts at 0. */\nfunction defaultValueOf(variable: OutcomeVariable): OutcomeValue {\n const value = ('defaultValue' in variable ? variable.defaultValue : null) ?? null;\n if (value === null && (variable.baseType === 'integer' || variable.baseType === 'float')) return '0';\n return value;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-response-processing': QtiResponseProcessing;\n }\n}\n"]}
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import type { ResponseInteraction } from '@qti-components/base';
|
|
2
|
+
export interface OutcomeEntry {
|
|
3
|
+
identifier: string;
|
|
4
|
+
value: Readonly<string | string[] | null | undefined>;
|
|
5
|
+
}
|
|
6
|
+
/** One outcome an update applied, with its final value. */
|
|
2
7
|
export interface OutcomeChangedDetails {
|
|
3
8
|
item: string;
|
|
4
9
|
outcomeIdentifier: string;
|
|
5
10
|
value: Readonly<string | string[]>;
|
|
6
11
|
}
|
|
12
|
+
/** The outcomes one update applied, sent after the item context is published. */
|
|
13
|
+
export interface OutcomesChangedDetails {
|
|
14
|
+
item: string;
|
|
15
|
+
outcomes: OutcomeEntry[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Outcomes for the item to apply in one update: the result of its own response processing, or what
|
|
19
|
+
* a backend returned. `responseProcessed` says an attempt ended, as it does after `processResponse`.
|
|
20
|
+
*/
|
|
21
|
+
export interface SetOutcomesDetails {
|
|
22
|
+
outcomes: OutcomeEntry[];
|
|
23
|
+
responseProcessed?: boolean;
|
|
24
|
+
}
|
|
7
25
|
export type InteractionChangedDetails = ResponseInteraction & {
|
|
8
26
|
item: string;
|
|
9
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-types.js","sourceRoot":"","sources":["../../src/internal/event-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ResponseInteraction } from '@qti-components/base';\n\nexport interface OutcomeChangedDetails {\n item: string;\n outcomeIdentifier: string;\n value: Readonly<string | string[]>;\n}\nexport type InteractionChangedDetails = ResponseInteraction & { item: string };\n"]}
|
|
1
|
+
{"version":3,"file":"event-types.js","sourceRoot":"","sources":["../../src/internal/event-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ResponseInteraction } from '@qti-components/base';\n\nexport interface OutcomeEntry {\n identifier: string;\n value: Readonly<string | string[] | null | undefined>;\n}\n\n/** One outcome an update applied, with its final value. */\nexport interface OutcomeChangedDetails {\n item: string;\n outcomeIdentifier: string;\n value: Readonly<string | string[]>;\n}\n\n/** The outcomes one update applied, sent after the item context is published. */\nexport interface OutcomesChangedDetails {\n item: string;\n outcomes: OutcomeEntry[];\n}\n\n/**\n * Outcomes for the item to apply in one update: the result of its own response processing, or what\n * a backend returned. `responseProcessed` says an attempt ended, as it does after `processResponse`.\n */\nexport interface SetOutcomesDetails {\n outcomes: OutcomeEntry[];\n responseProcessed?: boolean;\n}\nexport type InteractionChangedDetails = ResponseInteraction & { item: string };\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FeedbackEventDetail } from '../public-events';
|
|
2
|
+
interface FeedbackElement extends Element {
|
|
3
|
+
outcomeIdentifier: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Send `cito-feedback-show` or `cito-feedback-hide` from a feedback element, just before it shows or
|
|
7
|
+
* hides. Both are cancelable; this returns `false` when the host cancels, i.e. takes over.
|
|
8
|
+
*/
|
|
9
|
+
export declare function dispatchFeedback(element: FeedbackElement, name: 'cito-feedback-show' | 'cito-feedback-hide', kind: FeedbackEventDetail['kind'], identifier: string): boolean;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { dispatchPublic } from '../public-events';
|
|
2
|
+
/**
|
|
3
|
+
* Send `cito-feedback-show` or `cito-feedback-hide` from a feedback element, just before it shows or
|
|
4
|
+
* hides. Both are cancelable; this returns `false` when the host cancels, i.e. takes over.
|
|
5
|
+
*/
|
|
6
|
+
export function dispatchFeedback(element, name, kind, identifier) {
|
|
7
|
+
const itemIdentifier = element.closest('qti-assessment-item')?.getAttribute('identifier') ?? undefined;
|
|
8
|
+
const detail = {
|
|
9
|
+
kind,
|
|
10
|
+
identifier,
|
|
11
|
+
outcomeIdentifier: element.outcomeIdentifier,
|
|
12
|
+
element,
|
|
13
|
+
...(itemIdentifier ? { itemIdentifier } : {})
|
|
14
|
+
};
|
|
15
|
+
return dispatchPublic(element, name, detail, true);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=feedback-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback-events.js","sourceRoot":"","sources":["../../src/internal/feedback-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAQlD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAwB,EACxB,IAAiD,EACjD,IAAiC,EACjC,UAAkB;IAElB,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC;IACvG,MAAM,MAAM,GAAwB;QAClC,IAAI;QACJ,UAAU;QACV,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,OAAO;QACP,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAC;IACF,OAAO,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACrD,CAAC","sourcesContent":["import { dispatchPublic } from '../public-events';\n\nimport type { FeedbackEventDetail } from '../public-events';\n\ninterface FeedbackElement extends Element {\n outcomeIdentifier: string;\n}\n\n/**\n * Send `cito-feedback-show` or `cito-feedback-hide` from a feedback element, just before it shows or\n * hides. Both are cancelable; this returns `false` when the host cancels, i.e. takes over.\n */\nexport function dispatchFeedback(\n element: FeedbackElement,\n name: 'cito-feedback-show' | 'cito-feedback-hide',\n kind: FeedbackEventDetail['kind'],\n identifier: string\n): boolean {\n const itemIdentifier = element.closest('qti-assessment-item')?.getAttribute('identifier') ?? undefined;\n const detail: FeedbackEventDetail = {\n kind,\n identifier,\n outcomeIdentifier: element.outcomeIdentifier,\n element,\n ...(itemIdentifier ? { itemIdentifier } : {})\n };\n return dispatchPublic(element, name, detail, true);\n}\n"]}
|
package/dist/public-events.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InteractionChangedDetails, OutcomeChangedDetails } from './internal/event-types';
|
|
1
|
+
import type { InteractionChangedDetails, OutcomeChangedDetails, OutcomesChangedDetails, SetOutcomesDetails } from './internal/event-types';
|
|
2
2
|
/**
|
|
3
3
|
* The public events of the item. The name tells you it is public: everything declared here starts
|
|
4
4
|
* with `cito-`; every other event is internal plumbing and may change in any release.
|
|
@@ -18,11 +18,38 @@ export interface RubricPlacement {
|
|
|
18
18
|
className: string;
|
|
19
19
|
element: Element;
|
|
20
20
|
}
|
|
21
|
+
/** The detail of `cito-feedback-show` and `cito-feedback-hide`. */
|
|
22
|
+
export interface FeedbackEventDetail {
|
|
23
|
+
kind: 'block' | 'inline' | 'modal';
|
|
24
|
+
/** The feedback's `identifier`. */
|
|
25
|
+
identifier: string;
|
|
26
|
+
/** The outcome it follows (`outcome-identifier`). */
|
|
27
|
+
outcomeIdentifier: string;
|
|
28
|
+
/** The feedback element itself: read or clone its content (it stays in the DOM, hidden). */
|
|
29
|
+
element: Element;
|
|
30
|
+
/** The identifier of the item it is in, when it is in one. */
|
|
31
|
+
itemIdentifier?: string;
|
|
32
|
+
}
|
|
21
33
|
export interface PublicItemEventMap {
|
|
22
34
|
'cito-item-response-changed': CustomEvent<InteractionChangedDetails>;
|
|
35
|
+
/**
|
|
36
|
+
* Request: the item applies these outcomes in one update. Response processing sends it; a host
|
|
37
|
+
* that scores on a backend sends it on the item with the outcomes the backend returned.
|
|
38
|
+
*/
|
|
39
|
+
'cito-item-set-outcomes': CustomEvent<SetOutcomesDetails>;
|
|
40
|
+
/** One per outcome an update applied, with its final value, after the item context is published. */
|
|
23
41
|
'cito-item-outcome-changed': CustomEvent<OutcomeChangedDetails>;
|
|
42
|
+
/** All the outcomes one update applied, after the item context is published. */
|
|
43
|
+
'cito-item-outcomes-changed': CustomEvent<OutcomesChangedDetails>;
|
|
24
44
|
/** Cancelable: `preventDefault()` keeps the rubric block where it is. */
|
|
25
45
|
'cito-item-rubric-placement': CustomEvent<RubricPlacement>;
|
|
46
|
+
/**
|
|
47
|
+
* Cancelable: the feedback element is about to show (its condition turned true). `preventDefault()`
|
|
48
|
+
* keeps it hidden, so the host can show the content itself. Sent once per showing.
|
|
49
|
+
*/
|
|
50
|
+
'cito-feedback-show': CustomEvent<FeedbackEventDetail>;
|
|
51
|
+
/** The condition of a feedback that was shown (or taken over by the host) turned false again. */
|
|
52
|
+
'cito-feedback-hide': CustomEvent<FeedbackEventDetail>;
|
|
26
53
|
}
|
|
27
54
|
export type PublicItemEventName = keyof PublicItemEventMap;
|
|
28
55
|
export declare const PUBLIC_ITEM_EVENTS: Record<PublicItemEventName, PublicEventDeclaration>;
|
package/dist/public-events.js
CHANGED
|
@@ -2,12 +2,16 @@ export const PUBLIC_ITEM_EVENTS = {
|
|
|
2
2
|
// The old name `qti-assessment-item-connected` stays as internal plumbing: it is sent separately.
|
|
3
3
|
'cito-item-rendered': { kind: 'notification', scope: 'item' },
|
|
4
4
|
'cito-item-response-changed': { kind: 'notification', scope: 'item', deprecated: 'qti-interaction-changed' },
|
|
5
|
+
'cito-item-set-outcomes': { kind: 'request', scope: 'item' },
|
|
5
6
|
'cito-item-outcome-changed': { kind: 'notification', scope: 'item', deprecated: 'qti-outcome-changed' },
|
|
7
|
+
'cito-item-outcomes-changed': { kind: 'notification', scope: 'item' },
|
|
6
8
|
'cito-item-rubric-placement': {
|
|
7
9
|
kind: 'notification',
|
|
8
10
|
scope: 'item',
|
|
9
11
|
deprecated: 'qti-rubric:discretionary-placement'
|
|
10
|
-
}
|
|
12
|
+
},
|
|
13
|
+
'cito-feedback-show': { kind: 'notification', scope: 'item' },
|
|
14
|
+
'cito-feedback-hide': { kind: 'notification', scope: 'item' }
|
|
11
15
|
};
|
|
12
16
|
/**
|
|
13
17
|
* Dispatch `name` and its deprecated name with the same `detail` object, new name first. Returns
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-events.js","sourceRoot":"","sources":["../src/public-events.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"public-events.js","sourceRoot":"","sources":["../src/public-events.ts"],"names":[],"mappings":"AAmEA,MAAM,CAAC,MAAM,kBAAkB,GAAwD;IACrF,kGAAkG;IAClG,oBAAoB,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE;IAC7D,4BAA4B,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,yBAAyB,EAAE;IAC5G,wBAAwB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE;IAC5D,2BAA2B,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,qBAAqB,EAAE;IACvG,4BAA4B,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE;IACrE,4BAA4B,EAAE;QAC5B,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,oCAAoC;KACjD;IACD,oBAAoB,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE;IAC7D,oBAAoB,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE;CAC9D,CAAC;AAMF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,YAAoD,EACpD,IAAY,EACZ,MAAe,EACf,UAAU,GAAG,KAAK;IAElB,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACjF,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACvE,MAAM,EAAE,UAAU,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU;QAAE,OAAO,YAAY,CAAC;IACrC,OAAO,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,IAAI,YAAY,CAAC;AACjF,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;AAEjC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,YAAoD,EACpD,IAAY,EACZ,OAA2B;IAE3B,IAAI,WAAoB,CAAC;IACzB,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE;QAChC,WAAW,GAAI,CAAiB,CAAC,MAAM,CAAC;QACxC,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC;QAChD,OAAO,CAAC,CAAC,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;IACH,MAAM,EAAE,UAAU,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE;YACtC,IAAI,WAAW,KAAK,SAAS,IAAK,CAAiB,CAAC,MAAM,KAAK,WAAW;gBAAE,OAAO;YACnF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,+BAA+B,UAAU,8BAA8B,IAAI,YAAY,CAAC,CAAC;YACxG,CAAC;YACD,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,IAAO,EACP,MAAsE,EACtE,UAAU,GAAG,KAAK;IAElB,OAAO,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAmB,EACnB,IAAO,EACP,OAA2C;IAE3C,cAAc,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,OAA6B,CAAC,CAAC;AAClF,CAAC","sourcesContent":["import type {\n InteractionChangedDetails,\n OutcomeChangedDetails,\n OutcomesChangedDetails,\n SetOutcomesDetails\n} from './internal/event-types';\n\n/**\n * The public events of the item. The name tells you it is public: everything declared here starts\n * with `cito-`; every other event is internal plumbing and may change in any release.\n *\n * Requests are verbs, notifications are past tense. All bubble and are composed.\n *\n * `deprecated` is the name the event had before it became public. `dispatchPublic` sends and\n * `listenPublic` handles both until the next major, then the field goes.\n */\nexport interface PublicEventDeclaration {\n kind: 'request' | 'notification';\n scope: 'test' | 'item';\n /** The name before it was public. Dispatched and handled alongside the new one. */\n deprecated?: string;\n}\n\nexport interface RubricPlacement {\n className: string;\n element: Element;\n}\n\n/** The detail of `cito-feedback-show` and `cito-feedback-hide`. */\nexport interface FeedbackEventDetail {\n kind: 'block' | 'inline' | 'modal';\n /** The feedback's `identifier`. */\n identifier: string;\n /** The outcome it follows (`outcome-identifier`). */\n outcomeIdentifier: string;\n /** The feedback element itself: read or clone its content (it stays in the DOM, hidden). */\n element: Element;\n /** The identifier of the item it is in, when it is in one. */\n itemIdentifier?: string;\n}\n\nexport interface PublicItemEventMap {\n // `cito-item-rendered` (detail: the `QtiAssessmentItem`) is added by qti-assessment-item.ts, so this\n // module imports no element: that import would be a cycle.\n 'cito-item-response-changed': CustomEvent<InteractionChangedDetails>;\n /**\n * Request: the item applies these outcomes in one update. Response processing sends it; a host\n * that scores on a backend sends it on the item with the outcomes the backend returned.\n */\n 'cito-item-set-outcomes': CustomEvent<SetOutcomesDetails>;\n /** One per outcome an update applied, with its final value, after the item context is published. */\n 'cito-item-outcome-changed': CustomEvent<OutcomeChangedDetails>;\n /** All the outcomes one update applied, after the item context is published. */\n 'cito-item-outcomes-changed': CustomEvent<OutcomesChangedDetails>;\n /** Cancelable: `preventDefault()` keeps the rubric block where it is. */\n 'cito-item-rubric-placement': CustomEvent<RubricPlacement>;\n /**\n * Cancelable: the feedback element is about to show (its condition turned true). `preventDefault()`\n * keeps it hidden, so the host can show the content itself. Sent once per showing.\n */\n 'cito-feedback-show': CustomEvent<FeedbackEventDetail>;\n /** The condition of a feedback that was shown (or taken over by the host) turned false again. */\n 'cito-feedback-hide': CustomEvent<FeedbackEventDetail>;\n}\n\nexport type PublicItemEventName = keyof PublicItemEventMap;\n\nexport const PUBLIC_ITEM_EVENTS: Record<PublicItemEventName, PublicEventDeclaration> = {\n // The old name `qti-assessment-item-connected` stays as internal plumbing: it is sent separately.\n 'cito-item-rendered': { kind: 'notification', scope: 'item' },\n 'cito-item-response-changed': { kind: 'notification', scope: 'item', deprecated: 'qti-interaction-changed' },\n 'cito-item-set-outcomes': { kind: 'request', scope: 'item' },\n 'cito-item-outcome-changed': { kind: 'notification', scope: 'item', deprecated: 'qti-outcome-changed' },\n 'cito-item-outcomes-changed': { kind: 'notification', scope: 'item' },\n 'cito-item-rubric-placement': {\n kind: 'notification',\n scope: 'item',\n deprecated: 'qti-rubric:discretionary-placement'\n },\n 'cito-feedback-show': { kind: 'notification', scope: 'item' },\n 'cito-feedback-hide': { kind: 'notification', scope: 'item' }\n};\n\ndeclare global {\n interface HTMLElementEventMap extends PublicItemEventMap {}\n}\n\n/**\n * Dispatch `name` and its deprecated name with the same `detail` object, new name first. Returns\n * `false` when a listener of either cancelled the event. The detail is always an object.\n * Shared by the item and test tiers; use `dispatchPublic` (item) or the test's own wrapper.\n */\nexport function dispatchDeclared(\n target: EventTarget,\n declarations: Record<string, PublicEventDeclaration>,\n name: string,\n detail: unknown,\n cancelable = false\n): boolean {\n const init = { detail: detail ?? {}, bubbles: true, composed: true, cancelable };\n const notCancelled = target.dispatchEvent(new CustomEvent(name, init));\n const { deprecated } = declarations[name];\n if (!deprecated) return notCancelled;\n return target.dispatchEvent(new CustomEvent(deprecated, init)) && notCancelled;\n}\n\nconst warned = new Set<string>();\n\n/**\n * Listen for `name` and its deprecated name. `dispatchDeclared` sends the old name straight after\n * the new one, synchronously, with the same `detail`: that one is skipped, so the handler runs\n * once. A host that sends only the old name is handled too, and warned once per name in the\n * console: only a sender outside our own components gets here without the new name before it.\n */\nexport function listenDeclared(\n target: EventTarget,\n declarations: Record<string, PublicEventDeclaration>,\n name: string,\n handler: (e: Event) => void\n): void {\n let justHandled: unknown;\n target.addEventListener(name, e => {\n justHandled = (e as CustomEvent).detail;\n queueMicrotask(() => (justHandled = undefined));\n handler(e);\n });\n const { deprecated } = declarations[name];\n if (deprecated) {\n target.addEventListener(deprecated, e => {\n if (justHandled !== undefined && (e as CustomEvent).detail === justHandled) return;\n if (!warned.has(deprecated)) {\n warned.add(deprecated);\n console.warn(`[qti-components] The event \"${deprecated}\" is deprecated; dispatch \"${name}\" instead.`);\n }\n handler(e);\n });\n }\n}\n\nexport function dispatchPublic<K extends PublicItemEventName>(\n target: EventTarget,\n name: K,\n detail: PublicItemEventMap[K] extends CustomEvent<infer D> ? D : never,\n cancelable = false\n): boolean {\n return dispatchDeclared(target, PUBLIC_ITEM_EVENTS, name, detail, cancelable);\n}\n\nexport function listenPublic<K extends PublicItemEventName>(\n target: EventTarget,\n name: K,\n handler: (e: PublicItemEventMap[K]) => void\n): void {\n listenDeclared(target, PUBLIC_ITEM_EVENTS, name, handler as (e: Event) => void);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qti-components/elements",
|
|
3
3
|
"description": "QTI elements utilities",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0-next.6",
|
|
5
5
|
"author": "",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@qti-components/base": "^
|
|
8
|
-
"@qti-components/transformers": "^1.
|
|
7
|
+
"@qti-components/base": "^3.0.0-next.5",
|
|
8
|
+
"@qti-components/transformers": "^1.8.0-next.0",
|
|
9
9
|
"@qti-components/utilities": "^1.3.3"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|