@citolab/qti-components 8.0.1 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cdn/index.global.js +1 -1
- package/cdn/index.js +648 -816
- package/dist/base.d.ts +61 -4
- package/dist/base.js +7 -1
- package/dist/{chunk-V5G7X53Y.js → chunk-3IACYIU2.js} +2 -2
- package/dist/chunk-4DB4SC5K.js +100 -0
- package/dist/chunk-4DB4SC5K.js.map +1 -0
- package/dist/{chunk-F4BNJWYN.js → chunk-4XR2JHCP.js} +646 -677
- package/dist/chunk-4XR2JHCP.js.map +1 -0
- package/dist/{chunk-7V4HJFHW.js → chunk-6ITD55QE.js} +2 -2
- package/dist/{chunk-3AJOQCDU.js → chunk-6V3A7NQP.js} +2 -2
- package/dist/{chunk-WVVMNF74.js → chunk-6XJUP55A.js} +248 -234
- package/dist/chunk-6XJUP55A.js.map +1 -0
- package/dist/{chunk-XU7HNT4F.js → chunk-CF3DXJWM.js} +145 -119
- package/dist/{chunk-XU7HNT4F.js.map → chunk-CF3DXJWM.js.map} +1 -1
- package/dist/chunk-EKXZI26R.js +917 -0
- package/dist/chunk-EKXZI26R.js.map +1 -0
- package/dist/{chunk-IJD53WY6.js → chunk-HDEG6BAZ.js} +15 -15
- package/dist/{chunk-IJD53WY6.js.map → chunk-HDEG6BAZ.js.map} +1 -1
- package/dist/{chunk-LVBIQDPM.js → chunk-IXPDMYKH.js} +147 -101
- package/dist/chunk-IXPDMYKH.js.map +1 -0
- package/dist/chunk-IYC7LZV6.js +7 -0
- package/dist/chunk-IYC7LZV6.js.map +1 -0
- package/dist/{chunk-NA2N2WSG.js → chunk-MK2I3MQB.js} +244 -193
- package/dist/chunk-MK2I3MQB.js.map +1 -0
- package/dist/{chunk-CAO4JRLY.js → chunk-NZLW6EX7.js} +2 -2
- package/dist/{chunk-RXGDQDOV.js → chunk-Q52IJELT.js} +479 -393
- package/dist/chunk-Q52IJELT.js.map +1 -0
- package/dist/{chunk-QECOPVPO.js → chunk-TXIB3SKC.js} +60 -59
- package/dist/chunk-TXIB3SKC.js.map +1 -0
- package/dist/{computed.types.d-rKLSPvVG.d.ts → computed.types.d-DpKIYO6e.d.ts} +2 -0
- package/dist/corrections.d.ts +12 -29
- package/dist/corrections.js +9 -10
- package/dist/elements.d.ts +86 -87
- package/dist/elements.js +5 -6
- package/dist/index.d.ts +8 -39
- package/dist/index.js +29 -16
- package/dist/{interaction.d-D4MstYRz.d.ts → interaction.d-CJiMv8H7.d.ts} +13 -2
- package/dist/interactions.d.ts +11 -1299
- package/dist/interactions.js +4 -5
- package/dist/item.css +370 -532
- package/dist/item.d.ts +3 -3
- package/dist/item.js +6 -6
- package/dist/loader.js +2 -2
- package/dist/processing.d.ts +61 -11
- package/dist/processing.js +10 -2
- package/dist/qti-components-jsx.d.ts +293 -69
- package/dist/qti-test.d-_YAlhDbt.d.ts +702 -0
- package/dist/qti-text-entry-interaction.d-BGdfV9qG.d.ts +1567 -0
- package/dist/test.d.ts +11 -678
- package/dist/test.js +7 -8
- package/dist/transformers.d.ts +1 -1
- package/dist/transformers.js +1 -1
- package/package.json +11 -10
- package/dist/chunk-64XSIBGO.js +0 -241
- package/dist/chunk-64XSIBGO.js.map +0 -1
- package/dist/chunk-7HC5SMCU.js +0 -102
- package/dist/chunk-7HC5SMCU.js.map +0 -1
- package/dist/chunk-F4BNJWYN.js.map +0 -1
- package/dist/chunk-H3J7LFRO.js +0 -2243
- package/dist/chunk-H3J7LFRO.js.map +0 -1
- package/dist/chunk-LVBIQDPM.js.map +0 -1
- package/dist/chunk-NA2N2WSG.js.map +0 -1
- package/dist/chunk-QECOPVPO.js.map +0 -1
- package/dist/chunk-RXGDQDOV.js.map +0 -1
- package/dist/chunk-WVVMNF74.js.map +0 -1
- package/dist/chunk-X3E5HXG2.js +0 -20
- package/dist/chunk-X3E5HXG2.js.map +0 -1
- /package/dist/{chunk-V5G7X53Y.js.map → chunk-3IACYIU2.js.map} +0 -0
- /package/dist/{chunk-7V4HJFHW.js.map → chunk-6ITD55QE.js.map} +0 -0
- /package/dist/{chunk-3AJOQCDU.js.map → chunk-6V3A7NQP.js.map} +0 -0
- /package/dist/{chunk-CAO4JRLY.js.map → chunk-NZLW6EX7.js.map} +0 -0
package/dist/base.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { C as ComputedItemContext } from './computed-item.types.d-BKZdSLLJ.js';
|
|
2
|
-
import { C as ComputedContext } from './computed.types.d-
|
|
3
|
-
export { a as ComputedItem, I as INITIAL_SESSION_CONTEXT, S as SessionContext, V as View, s as sessionContext } from './computed.types.d-
|
|
2
|
+
import { C as ComputedContext } from './computed.types.d-DpKIYO6e.js';
|
|
3
|
+
export { a as ComputedItem, I as INITIAL_SESSION_CONTEXT, S as SessionContext, V as View, s as sessionContext } from './computed.types.d-DpKIYO6e.js';
|
|
4
4
|
export { C as ConfigContext, V as ValidationDisplayMode, c as configContext } from './config.context.d-BvU9r-Mg.js';
|
|
5
|
-
export { C as ChoiceRole, I as Interaction, a as InteractionContext, i as interactionContext } from './interaction.d-
|
|
5
|
+
export { C as ChoiceRole, I as Interaction, a as InteractionContext, i as interactionContext } from './interaction.d-CJiMv8H7.js';
|
|
6
6
|
import { I as ItemContext, B as BaseType } from './item.types.d-QU7LljEK.js';
|
|
7
7
|
export { C as Calculate, a as Cardinality, M as Multiple, O as Ordered, b as OutcomeVariable, Q as QtiAreaMapEntry, c as QtiAreaMapping, d as QtiMapEntry, e as QtiMapping, R as ResponseInteraction, f as ResponseVariable, T as TemplateVariable, V as VariableDeclaration, g as VariableValue, h as areaShape, i as directedPair, j as float, k as integer, l as itemContextVariables } from './item.types.d-QU7LljEK.js';
|
|
8
8
|
export { Q as QtiContext, a as QtiContextType, S as Seed, b as asSeed, i as isSeed, q as qtiContext } from './qti.context.d-CejJMlfZ.js';
|
|
@@ -102,6 +102,63 @@ declare const dropRegion: lit.CSSResult;
|
|
|
102
102
|
*/
|
|
103
103
|
declare const validationMessage: lit.CSSResult;
|
|
104
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Custom-state support shim for browsers this library cannot use natively.
|
|
107
|
+
*
|
|
108
|
+
* Interactions track selection and correct/incorrect marking through
|
|
109
|
+
* `internals.states`, with bare state names (`checked`, `radio`,
|
|
110
|
+
* `correct-response`, …). Two browser profiles cannot service that:
|
|
111
|
+
*
|
|
112
|
+
* - Safari 16.4–17.3 implement `ElementInternals` but not `CustomStateSet`, so
|
|
113
|
+
* `internals.states` is `undefined` and reading it throws — "undefined is not
|
|
114
|
+
* an object (evaluating 'internals.states.has')".
|
|
115
|
+
* - Chrome and Edge before the CSS custom-state spec change expose `states` but
|
|
116
|
+
* reject names that do not start with `--`, so `states.add('radio')` throws
|
|
117
|
+
* "The specified value 'radio' must start with '--'".
|
|
118
|
+
*
|
|
119
|
+
* On both, picking a choice throws rather than registering. `attachInternals`
|
|
120
|
+
* itself is unguarded throughout the interaction base classes, which puts the
|
|
121
|
+
* hard support floor at Safari 16.4 — inside the range that breaks.
|
|
122
|
+
*
|
|
123
|
+
* The shim replaces `states` with a permissive `Set` and mirrors its contents to
|
|
124
|
+
* a space-separated `data-state` attribute on the host, because these browsers'
|
|
125
|
+
* CSS parsers also drop any selector list containing `:state()`. The theme's
|
|
126
|
+
* built stylesheets pair every `:state(x)` with a `[data-state~='x']` arm (see
|
|
127
|
+
* `tools/postcss/custom-state-fallback.mjs`), so styling survives too.
|
|
128
|
+
*
|
|
129
|
+
* Support is classified by behaviour rather than by browser version, and the
|
|
130
|
+
* shim is not installed at all where `states` works.
|
|
131
|
+
*/
|
|
132
|
+
/** A permissive `CustomStateSet` that mirrors its contents to `data-state`. */
|
|
133
|
+
declare class CustomStateSetShim extends Set<string> {
|
|
134
|
+
#private;
|
|
135
|
+
constructor(host: HTMLElement);
|
|
136
|
+
add(state: string): this;
|
|
137
|
+
delete(state: string): boolean;
|
|
138
|
+
clear(): void;
|
|
139
|
+
}
|
|
140
|
+
type CustomStateSupport = 'missing' | 'legacy' | 'modern';
|
|
141
|
+
/**
|
|
142
|
+
* Classify native custom-state support by behaviour:
|
|
143
|
+
*
|
|
144
|
+
* - `missing`: `ElementInternals` carries no `states` at all.
|
|
145
|
+
* - `legacy`: `states` exists but rejects a bare name.
|
|
146
|
+
* - `modern`: `states` exists and accepts a bare name — no shim wanted.
|
|
147
|
+
*
|
|
148
|
+
* `attachInternals` only works on a custom element, so the probe registers a
|
|
149
|
+
* throwaway one. That happens solely when `states` is present, so the `missing`
|
|
150
|
+
* path never defines anything.
|
|
151
|
+
*/
|
|
152
|
+
declare function classifyCustomStateSupport(attachInternals: (this: HTMLElement) => ElementInternals): CustomStateSupport;
|
|
153
|
+
/**
|
|
154
|
+
* Patch `HTMLElement.prototype.attachInternals` so every element's `states` is
|
|
155
|
+
* the shim, on the two profiles that need it. Idempotent, and a no-op where
|
|
156
|
+
* native support is usable.
|
|
157
|
+
*
|
|
158
|
+
* Returns the classification that was acted on, which is what the tests assert.
|
|
159
|
+
*/
|
|
160
|
+
declare function installCustomStateSetFallback(): CustomStateSupport | 'already-installed';
|
|
161
|
+
|
|
105
162
|
declare class ScoringHelper {
|
|
106
163
|
/**
|
|
107
164
|
* Checks if a given point is within a specified area.
|
|
@@ -132,4 +189,4 @@ declare const convertNumberToUniversalFormat: (number: number | string) => strin
|
|
|
132
189
|
declare function IsNullOrUndefined(value: unknown): boolean;
|
|
133
190
|
declare function removeDoubleSlashes(str: string): string;
|
|
134
191
|
|
|
135
|
-
export { BaseType, ComputedContext, ComputedItemContext, IsNullOrUndefined, ItemContext, ScoringHelper, boxSizing, computedContext, computedItemContext, convertNumberToUniversalFormat, decimalSeparator, dropRegion, itemContext, removeDoubleSlashes, validationMessage };
|
|
192
|
+
export { BaseType, ComputedContext, ComputedItemContext, CustomStateSetShim, type CustomStateSupport, IsNullOrUndefined, ItemContext, ScoringHelper, boxSizing, classifyCustomStateSupport, computedContext, computedItemContext, convertNumberToUniversalFormat, decimalSeparator, dropRegion, installCustomStateSetFallback, itemContext, removeDoubleSlashes, validationMessage };
|
package/dist/base.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CustomStateSetShim,
|
|
2
3
|
INITIAL_SESSION_CONTEXT,
|
|
3
4
|
INITIAL_TEST_CONTEXT,
|
|
4
5
|
Interaction,
|
|
@@ -11,12 +12,14 @@ import {
|
|
|
11
12
|
ScoringHelper,
|
|
12
13
|
asSeed,
|
|
13
14
|
boxSizing,
|
|
15
|
+
classifyCustomStateSupport,
|
|
14
16
|
computedContext,
|
|
15
17
|
computedItemContext,
|
|
16
18
|
configContext,
|
|
17
19
|
convertNumberToUniversalFormat,
|
|
18
20
|
decimalSeparator,
|
|
19
21
|
dropRegion,
|
|
22
|
+
installCustomStateSetFallback,
|
|
20
23
|
interactionContext,
|
|
21
24
|
isSeed,
|
|
22
25
|
itemContext,
|
|
@@ -34,8 +37,9 @@ import {
|
|
|
34
37
|
sessionContext,
|
|
35
38
|
testContext,
|
|
36
39
|
validationMessage
|
|
37
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-EKXZI26R.js";
|
|
38
41
|
export {
|
|
42
|
+
CustomStateSetShim,
|
|
39
43
|
INITIAL_SESSION_CONTEXT,
|
|
40
44
|
INITIAL_TEST_CONTEXT,
|
|
41
45
|
Interaction,
|
|
@@ -48,12 +52,14 @@ export {
|
|
|
48
52
|
ScoringHelper,
|
|
49
53
|
asSeed,
|
|
50
54
|
boxSizing,
|
|
55
|
+
classifyCustomStateSupport,
|
|
51
56
|
computedContext,
|
|
52
57
|
computedItemContext,
|
|
53
58
|
configContext,
|
|
54
59
|
convertNumberToUniversalFormat,
|
|
55
60
|
decimalSeparator,
|
|
56
61
|
dropRegion,
|
|
62
|
+
installCustomStateSetFallback,
|
|
57
63
|
interactionContext,
|
|
58
64
|
isSeed,
|
|
59
65
|
itemContext,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
qtiContentElements
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6XJUP55A.js";
|
|
4
4
|
|
|
5
5
|
// ../qti-elements/dist/register.js
|
|
6
6
|
for (const { tag, ctor } of qtiContentElements) {
|
|
@@ -8,4 +8,4 @@ for (const { tag, ctor } of qtiContentElements) {
|
|
|
8
8
|
customElements.define(tag, ctor);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
//# sourceMappingURL=chunk-
|
|
11
|
+
//# sourceMappingURL=chunk-3IACYIU2.js.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// ../qti-utilities/dist/decorators/watch.js
|
|
2
|
+
function watch(propertyName, options) {
|
|
3
|
+
const resolvedOptions = {
|
|
4
|
+
waitUntilFirstUpdate: false,
|
|
5
|
+
...options
|
|
6
|
+
};
|
|
7
|
+
return (proto, decoratedFnName) => {
|
|
8
|
+
const { update } = proto;
|
|
9
|
+
const watchedProperties = Array.isArray(propertyName) ? propertyName : [propertyName];
|
|
10
|
+
proto.update = function(changedProps) {
|
|
11
|
+
watchedProperties.forEach((property) => {
|
|
12
|
+
const key = property;
|
|
13
|
+
if (changedProps.has(key)) {
|
|
14
|
+
const oldValue = changedProps.get(key);
|
|
15
|
+
const newValue = this[key];
|
|
16
|
+
if (oldValue !== newValue) {
|
|
17
|
+
if (!resolvedOptions.waitUntilFirstUpdate || this.hasUpdated) {
|
|
18
|
+
this[decoratedFnName](oldValue, newValue);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
update.call(this, changedProps);
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ../qti-utilities/dist/directives/spread-args.js
|
|
29
|
+
import { nothing } from "lit/html.js";
|
|
30
|
+
import { directive } from "lit/directive.js";
|
|
31
|
+
import { AsyncDirective } from "lit/async-directive.js";
|
|
32
|
+
var SpreadArgsDirective = class extends AsyncDirective {
|
|
33
|
+
constructor() {
|
|
34
|
+
super(...arguments);
|
|
35
|
+
this.prevData = {};
|
|
36
|
+
}
|
|
37
|
+
render(_spreadData) {
|
|
38
|
+
return nothing;
|
|
39
|
+
}
|
|
40
|
+
update(part, [spreadData]) {
|
|
41
|
+
if (this.element !== part.element) {
|
|
42
|
+
this.element = part.element;
|
|
43
|
+
}
|
|
44
|
+
this.host = part.options?.host || this.element;
|
|
45
|
+
this.apply(spreadData);
|
|
46
|
+
this.groom(spreadData);
|
|
47
|
+
this.prevData = { ...spreadData };
|
|
48
|
+
return nothing;
|
|
49
|
+
}
|
|
50
|
+
apply(data) {
|
|
51
|
+
const filteredData = this.#filterArgs(data);
|
|
52
|
+
const { prevData, element } = this;
|
|
53
|
+
for (const key in filteredData) {
|
|
54
|
+
const value = filteredData[key];
|
|
55
|
+
if (value === prevData[key]) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (value === true) {
|
|
59
|
+
element.setAttribute(key, "");
|
|
60
|
+
} else if (value === false) {
|
|
61
|
+
element.removeAttribute(key);
|
|
62
|
+
} else if (value != null) {
|
|
63
|
+
element.setAttribute(key, String(value));
|
|
64
|
+
} else {
|
|
65
|
+
element.removeAttribute(key);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
groom(data) {
|
|
70
|
+
const { prevData, element } = this;
|
|
71
|
+
if (!prevData)
|
|
72
|
+
return;
|
|
73
|
+
const filteredData = data ? this.#filterArgs(data) : {};
|
|
74
|
+
for (const key in prevData) {
|
|
75
|
+
if (!filteredData || !(key in filteredData)) {
|
|
76
|
+
element.removeAttribute(key);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
#filterArgs(args) {
|
|
81
|
+
return Object.fromEntries(Object.entries(args).filter(([key, value]) => {
|
|
82
|
+
if (typeof value === "function") {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (key === "max-choices" && value === 0) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
if (value === "" || value === null || value === void 0) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var spreadArgs = directive(SpreadArgsDirective);
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
watch
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=chunk-4DB4SC5K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../qti-utilities/src/decorators/watch.ts","../../qti-utilities/src/directives/spread-args.ts"],"sourcesContent":["import type { LitElement } from 'lit';\n\ntype UpdateHandler = (prev?: unknown, next?: unknown) => void;\n\ntype NonUndefined<A> = A extends undefined ? never : A;\n\nexport type UpdateHandlerFunctionKeys<T extends object> = {\n [K in keyof T]-?: NonUndefined<T[K]> extends UpdateHandler ? K : never;\n}[keyof T];\n\ninterface WatchOptions {\n /**\n * If true, will only start watching after the initial update/render\n */\n waitUntilFirstUpdate?: boolean;\n}\n\n/**\n * Runs when observed properties change, e.g. @property or @state, but before the component updates. To wait for an\n * update to complete after a change occurs, use `await this.updateComplete` in the handler. To start watching after the\n * initial update/render, use `{ waitUntilFirstUpdate: true }` or `this.hasUpdated` in the handler.\n *\n * Usage:\n *\n * @watch('propName')\n * handlePropChange(oldValue, newValue) {\n * ...\n * }\n */\nexport function watch(propertyName: string | string[], options?: WatchOptions) {\n const resolvedOptions: Required<WatchOptions> = {\n waitUntilFirstUpdate: false,\n ...options\n };\n return <ElemClass extends LitElement>(\n proto: ElemClass,\n decoratedFnName: UpdateHandlerFunctionKeys<ElemClass> | any\n ) => {\n // @ts-expect-error - update is a protected property\n const { update } = proto;\n const watchedProperties = Array.isArray(propertyName) ? propertyName : [propertyName];\n\n // @ts-expect-error - update is a protected property\n proto.update = function (this: ElemClass, changedProps: Map<keyof ElemClass, ElemClass[keyof ElemClass]>) {\n watchedProperties.forEach(property => {\n const key = property as keyof ElemClass;\n if (changedProps.has(key)) {\n const oldValue = changedProps.get(key);\n const newValue = this[key];\n\n if (oldValue !== newValue) {\n if (!resolvedOptions.waitUntilFirstUpdate || this.hasUpdated) {\n ((this as any)[decoratedFnName] as unknown as UpdateHandler)(oldValue, newValue);\n }\n }\n }\n });\n\n update.call(this, changedProps);\n };\n };\n}\n","import { nothing } from 'lit/html.js';\nimport { directive } from 'lit/directive.js';\nimport { AsyncDirective } from 'lit/async-directive.js';\n\nimport type { ElementPart, Part } from 'lit';\n\n/**\n * A directive that spreads arguments to HTML attributes with intelligent filtering.\n *\n * Features:\n * - Includes `max-choices=\"0\"` even though 0 is falsy\n * - Excludes boolean attributes with no value, empty string, null, or undefined\n * - Excludes event handlers and functions\n *\n * Based on the @open-wc/lit-helpers spread directive implementation.\n */\nexport class SpreadArgsDirective extends AsyncDirective {\n host!: EventTarget | object | Element;\n element!: Element;\n prevData: { [key: string]: unknown } = {};\n\n render(_spreadData: { [key: string]: unknown }) {\n return nothing;\n }\n\n update(part: Part, [spreadData]: Parameters<this['render']>) {\n if (this.element !== (part as ElementPart).element) {\n this.element = (part as ElementPart).element;\n }\n this.host = part.options?.host || this.element;\n this.apply(spreadData);\n this.groom(spreadData);\n this.prevData = { ...spreadData };\n return nothing;\n }\n\n apply(data: { [key: string]: unknown }) {\n // Filter the data according to our rules\n const filteredData = this.#filterArgs(data);\n\n const { prevData, element } = this;\n for (const key in filteredData) {\n const value = filteredData[key];\n if (value === prevData[key]) {\n continue;\n }\n\n // Handle different attribute types\n if (value === true) {\n // Boolean attribute - just set the attribute name\n element.setAttribute(key, '');\n } else if (value === false) {\n // Remove false boolean attributes\n element.removeAttribute(key);\n } else if (value != null) {\n // Standard attribute with value\n element.setAttribute(key, String(value));\n } else {\n // Remove null/undefined attributes\n element.removeAttribute(key);\n }\n }\n }\n\n groom(data: { [key: string]: unknown }) {\n const { prevData, element } = this;\n if (!prevData) return;\n\n // Filter the current data to see what we should have\n const filteredData = data ? this.#filterArgs(data) : {};\n\n for (const key in prevData) {\n if (!filteredData || !(key in filteredData)) {\n // Remove attributes that are no longer present in filtered data\n element.removeAttribute(key);\n }\n }\n }\n\n #filterArgs(args: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(args).filter(([key, value]) => {\n // Always exclude functions (events/functions)\n if (typeof value === 'function') {\n return false;\n }\n\n // Special case for max-choices: include when value is 0\n if (key === 'max-choices' && value === 0) {\n return true;\n }\n\n // Exclude empty strings, null, and undefined\n if (value === '' || value === null || value === undefined) {\n return false;\n }\n\n // Include all other truthy values\n return true;\n })\n );\n }\n}\n\n/**\n * A directive that spreads arguments to HTML attributes with intelligent filtering.\n *\n * @param args - Object containing key-value pairs to spread as attributes\n *\n * @example\n * ```typescript\n * import { spreadArgs } from '@qti-components/utilities';\n *\n * const args = {\n * 'max-choices': 0, // Will be included\n * disabled: true, // Will be included as disabled=\"\"\n * hidden: false, // Will be excluded\n * title: '', // Will be excluded\n * onClick: () => {}, // Will be excluded\n * id: 'my-element' // Will be included as id=\"my-element\"\n * };\n *\n * html`<my-element ${spreadArgs(args)}></my-element>`;\n * ```\n */\nexport const spreadArgs = directive(SpreadArgsDirective);\n\n/**\n * Helper function version that works with @open-wc/lit-helpers spread directive.\n * @deprecated Use the spreadArgs directive directly instead.\n */\nexport function filterArgsForSpread(args: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(args).filter(([, value]) => {\n if (typeof value === 'function') return false;\n if (value === '' || value === null || value === undefined) return false;\n return true;\n })\n );\n}\n"],"mappings":";AA6BM,SAAU,MAAM,cAAiC,SAAsB;AAC3E,QAAM,kBAA0C;IAC9C,sBAAsB;IACtB,GAAG;;AAEL,SAAO,CACL,OACA,oBACE;AAEF,UAAM,EAAE,OAAM,IAAK;AACnB,UAAM,oBAAoB,MAAM,QAAQ,YAAY,IAAI,eAAe,CAAC,YAAY;AAGpF,UAAM,SAAS,SAA2B,cAA8D;AACtG,wBAAkB,QAAQ,cAAW;AACnC,cAAM,MAAM;AACZ,YAAI,aAAa,IAAI,GAAG,GAAG;AACzB,gBAAM,WAAW,aAAa,IAAI,GAAG;AACrC,gBAAM,WAAW,KAAK,GAAG;AAEzB,cAAI,aAAa,UAAU;AACzB,gBAAI,CAAC,gBAAgB,wBAAwB,KAAK,YAAY;AAC1D,mBAAa,eAAe,EAA+B,UAAU,QAAQ;YACjF;UACF;QACF;MACF,CAAC;AAED,aAAO,KAAK,MAAM,YAAY;IAChC;EACF;AACF;;;AC7DA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAczB,IAAO,sBAAP,cAAmC,eAAc;EAAvD,cAAA;;AAGE,SAAA,WAAuC,CAAA;EAmFzC;EAjFE,OAAO,aAAuC;AAC5C,WAAO;EACT;EAEA,OAAO,MAAY,CAAC,UAAU,GAA6B;AACzD,QAAI,KAAK,YAAa,KAAqB,SAAS;AAClD,WAAK,UAAW,KAAqB;IACvC;AACA,SAAK,OAAO,KAAK,SAAS,QAAQ,KAAK;AACvC,SAAK,MAAM,UAAU;AACrB,SAAK,MAAM,UAAU;AACrB,SAAK,WAAW,EAAE,GAAG,WAAU;AAC/B,WAAO;EACT;EAEA,MAAM,MAAgC;AAEpC,UAAM,eAAe,KAAK,YAAY,IAAI;AAE1C,UAAM,EAAE,UAAU,QAAO,IAAK;AAC9B,eAAW,OAAO,cAAc;AAC9B,YAAM,QAAQ,aAAa,GAAG;AAC9B,UAAI,UAAU,SAAS,GAAG,GAAG;AAC3B;MACF;AAGA,UAAI,UAAU,MAAM;AAElB,gBAAQ,aAAa,KAAK,EAAE;MAC9B,WAAW,UAAU,OAAO;AAE1B,gBAAQ,gBAAgB,GAAG;MAC7B,WAAW,SAAS,MAAM;AAExB,gBAAQ,aAAa,KAAK,OAAO,KAAK,CAAC;MACzC,OAAO;AAEL,gBAAQ,gBAAgB,GAAG;MAC7B;IACF;EACF;EAEA,MAAM,MAAgC;AACpC,UAAM,EAAE,UAAU,QAAO,IAAK;AAC9B,QAAI,CAAC;AAAU;AAGf,UAAM,eAAe,OAAO,KAAK,YAAY,IAAI,IAAI,CAAA;AAErD,eAAW,OAAO,UAAU;AAC1B,UAAI,CAAC,gBAAgB,EAAE,OAAO,eAAe;AAE3C,gBAAQ,gBAAgB,GAAG;MAC7B;IACF;EACF;EAEA,YAAY,MAA6B;AACvC,WAAO,OAAO,YACZ,OAAO,QAAQ,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,MAAK;AAE3C,UAAI,OAAO,UAAU,YAAY;AAC/B,eAAO;MACT;AAGA,UAAI,QAAQ,iBAAiB,UAAU,GAAG;AACxC,eAAO;MACT;AAGA,UAAI,UAAU,MAAM,UAAU,QAAQ,UAAU,QAAW;AACzD,eAAO;MACT;AAGA,aAAO;IACT,CAAC,CAAC;EAEN;;AAwBK,IAAM,aAAa,UAAU,mBAAmB;","names":[]}
|