@pie-players/pie-tool-answer-eliminator 0.3.73 → 0.3.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -39
- package/dist/adapters/ebsr-adapter.js +4 -9
- package/dist/index.d.ts +7 -4
- package/dist/tool-answer-eliminator.js +1564 -6632
- package/package.json +11 -10
- package/dist/answer-eliminator-core.d.ts +0 -151
- package/dist/rolldown-runtime--eTHp1Qs.js +0 -20
- package/dist/sre-kwoc_SMV.js +0 -17637
- package/dist/strategies/elimination-strategy.d.ts +0 -40
- package/dist/strategies/mask-strategy.d.ts +0 -32
- package/dist/strategies/strikethrough-strategy.d.ts +0 -106
- package/dist/tool-answer-eliminator.svelte.d.ts +0 -1
package/README.md
CHANGED
|
@@ -28,63 +28,74 @@ The answer eliminator is automatically integrated when using the PIE Section Pla
|
|
|
28
28
|
<script type="module">
|
|
29
29
|
import '@pie-players/pie-section-player';
|
|
30
30
|
import { ToolkitCoordinator } from '@pie-players/pie-assessment-toolkit';
|
|
31
|
+
import {
|
|
32
|
+
createPackagedToolRegistry,
|
|
33
|
+
DEFAULT_TOOL_MODULE_LOADERS,
|
|
34
|
+
} from '@pie-players/pie-default-tool-loaders';
|
|
31
35
|
|
|
36
|
+
const toolRegistry = createPackagedToolRegistry({
|
|
37
|
+
toolModuleLoaders: DEFAULT_TOOL_MODULE_LOADERS,
|
|
38
|
+
});
|
|
32
39
|
const coordinator = new ToolkitCoordinator({
|
|
33
40
|
assessmentId: 'my-assessment',
|
|
41
|
+
toolRegistry,
|
|
34
42
|
tools: {
|
|
35
|
-
|
|
43
|
+
placement: { item: ['answerEliminator'] }
|
|
36
44
|
}
|
|
37
45
|
});
|
|
38
46
|
|
|
39
47
|
const player = document.getElementById('player');
|
|
40
|
-
player.
|
|
48
|
+
player.runtime = { ...(player.runtime ?? {}), coordinator };
|
|
41
49
|
player.section = mySection;
|
|
42
50
|
</script>
|
|
43
51
|
|
|
44
|
-
<pie-section-player id="player"></pie-section-player>
|
|
52
|
+
<pie-section-player-splitpane id="player"></pie-section-player-splitpane>
|
|
45
53
|
```
|
|
46
54
|
|
|
47
55
|
The section player automatically:
|
|
48
56
|
- Renders answer eliminator buttons in question toolbars
|
|
49
57
|
- Generates global element IDs
|
|
50
|
-
- Passes ElementToolStateStore to the tool
|
|
51
58
|
- Manages state lifecycle
|
|
52
59
|
|
|
60
|
+
The tool reads its coordinator and the `ElementToolStateStore` from the toolkit
|
|
61
|
+
runtime context, so it has to sit inside `<pie-assessment-toolkit>`.
|
|
62
|
+
|
|
53
63
|
### Manual Integration (Advanced)
|
|
54
64
|
|
|
55
|
-
For custom
|
|
65
|
+
For a custom layout inside the toolkit:
|
|
56
66
|
|
|
57
67
|
```html
|
|
58
68
|
<script type="module">
|
|
59
69
|
import '@pie-players/pie-tool-answer-eliminator';
|
|
60
|
-
import { ElementToolStateStore } from '@pie-players/pie-assessment-toolkit';
|
|
61
|
-
|
|
62
|
-
const store = new ElementToolStateStore();
|
|
63
|
-
const globalElementId = store.getGlobalElementId(
|
|
64
|
-
'my-assessment',
|
|
65
|
-
'section-1',
|
|
66
|
-
'question-1',
|
|
67
|
-
'mc1'
|
|
68
|
-
);
|
|
69
70
|
|
|
70
71
|
const tool = document.querySelector('pie-tool-answer-eliminator');
|
|
71
|
-
|
|
72
|
-
tool.
|
|
72
|
+
// Store key per PIE element in the question, by model id
|
|
73
|
+
tool.elementStateKeys = {
|
|
74
|
+
mc1: 'my-assessment:section-1:question-1:mc1',
|
|
75
|
+
mc2: 'my-assessment:section-1:question-1:mc2',
|
|
76
|
+
};
|
|
73
77
|
tool.scopeElement = document.querySelector('.question-content');
|
|
78
|
+
tool.visible = true; // or alwaysOn = true; the tool injects no buttons while neither is set
|
|
74
79
|
</script>
|
|
75
80
|
|
|
76
|
-
<pie-
|
|
81
|
+
<pie-assessment-toolkit>
|
|
82
|
+
<pie-tool-answer-eliminator></pie-tool-answer-eliminator>
|
|
83
|
+
</pie-assessment-toolkit>
|
|
77
84
|
```
|
|
78
85
|
|
|
79
86
|
## Props/Attributes
|
|
80
87
|
|
|
81
|
-
|
|
88
|
+
`elementStateKeys` and `scopeElement` are JS properties only; the others also take the attribute shown.
|
|
82
89
|
|
|
83
|
-
| Property | Type |
|
|
84
|
-
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
90
|
+
| Property | Attribute | Type | Default | Description |
|
|
91
|
+
|----------|-----------|------|---------|-------------|
|
|
92
|
+
| `visible` | `visible` | `boolean` | `false` | Shows the elimination buttons; the toolbar toggle sets it |
|
|
93
|
+
| `alwaysOn` | `always-on` | `boolean` | `false` | Shows the buttons regardless of `visible`, for a profile-based accommodation |
|
|
94
|
+
| `strategy` | `strategy` | `'strikethrough' \| 'mask'` | `'strikethrough'` | Elimination styling; any other value uses `strikethrough` |
|
|
95
|
+
| `buttonAlignment` | `button-alignment` | `'left' \| 'right' \| 'inline'` | `'right'` | Button placement relative to the choice |
|
|
96
|
+
| `toolId` | `tool-id` | `string` | `'answerEliminator'` | Id the tool registers with the coordinator under |
|
|
97
|
+
| `elementStateKeys` | | `Record<string, string>` | `{}` | Composite key `assessmentId:sectionId:itemId:elementId` per PIE element, by model id, into the runtime context's element tool state store. A choice is tracked under its nearest ancestor with a listed id and persists under that key; choices outside a listed element are kept in memory only |
|
|
98
|
+
| `scopeElement` | | `HTMLElement` | | Root to detect choices in. Without it the tool uses the root its enclosing `pie-item-scope` provides, and with neither it warns and injects nothing |
|
|
88
99
|
|
|
89
100
|
## Global Element ID Format
|
|
90
101
|
|
|
@@ -97,7 +108,7 @@ ${assessmentId}:${sectionId}:${itemId}:${elementId}
|
|
|
97
108
|
**Example:**
|
|
98
109
|
```typescript
|
|
99
110
|
"demo-assessment:section-1:question-1:mc1"
|
|
100
|
-
"biology-exam:section-2:genetics-q1:
|
|
111
|
+
"biology-exam:section-2:genetics-q1:ebsr1"
|
|
101
112
|
```
|
|
102
113
|
|
|
103
114
|
### Benefits of Composite Keys
|
|
@@ -109,16 +120,16 @@ ${assessmentId}:${sectionId}:${itemId}:${elementId}
|
|
|
109
120
|
|
|
110
121
|
### Why Element-Level?
|
|
111
122
|
|
|
112
|
-
Items can contain **multiple interactive elements**
|
|
123
|
+
Items can contain **multiple interactive elements** whose choice ids repeat (two multiple-choice elements both have a choice `a`). Each element needs independent state:
|
|
113
124
|
|
|
114
125
|
```typescript
|
|
115
126
|
// ✅ Correct: Element-level state
|
|
116
127
|
{
|
|
117
|
-
"demo:section-1:question-1:
|
|
118
|
-
"answerEliminator": { "eliminatedChoices": ["
|
|
128
|
+
"demo:section-1:question-1:mc1": {
|
|
129
|
+
"answerEliminator": { "eliminatedChoices": ["a", "c"] }
|
|
119
130
|
},
|
|
120
|
-
"demo:section-1:question-1:
|
|
121
|
-
"answerEliminator": { "eliminatedChoices": ["
|
|
131
|
+
"demo:section-1:question-1:mc2": {
|
|
132
|
+
"answerEliminator": { "eliminatedChoices": ["a"] }
|
|
122
133
|
}
|
|
123
134
|
}
|
|
124
135
|
```
|
|
@@ -157,9 +168,18 @@ The answer eliminator stores state in **ElementToolStateStore** (ephemeral, clie
|
|
|
157
168
|
To persist tool state across page refreshes:
|
|
158
169
|
|
|
159
170
|
```typescript
|
|
171
|
+
import {
|
|
172
|
+
createPackagedToolRegistry,
|
|
173
|
+
DEFAULT_TOOL_MODULE_LOADERS,
|
|
174
|
+
} from '@pie-players/pie-default-tool-loaders';
|
|
175
|
+
|
|
176
|
+
const toolRegistry = createPackagedToolRegistry({
|
|
177
|
+
toolModuleLoaders: DEFAULT_TOOL_MODULE_LOADERS,
|
|
178
|
+
});
|
|
160
179
|
const coordinator = new ToolkitCoordinator({
|
|
161
180
|
assessmentId: 'my-assessment',
|
|
162
|
-
|
|
181
|
+
toolRegistry,
|
|
182
|
+
tools: { placement: { item: ['answerEliminator'] } }
|
|
163
183
|
});
|
|
164
184
|
|
|
165
185
|
// Save to localStorage on change
|
|
@@ -187,14 +207,7 @@ The tool detects choices through an **adapter registry** (`AdapterRegistry`), no
|
|
|
187
207
|
| `EBSRAdapter` | `ebsr` | delegates to the multiple-choice adapter for each `ebsr-multiple-choice` part (Part A/B), prefixing choice IDs with the part |
|
|
188
208
|
| `InlineDropdownAdapter` | `inline-dropdown` | dropdown items with `role="option"` |
|
|
189
209
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
import { AdapterRegistry } from '@pie-players/pie-tool-answer-eliminator/adapters/adapter-registry';
|
|
194
|
-
|
|
195
|
-
const registry = new AdapterRegistry();
|
|
196
|
-
registry.registerAdapter(myCustomChoiceAdapter);
|
|
197
|
-
```
|
|
210
|
+
The tool builds its registry internally with these three adapters and has no injection point. The `./adapters/adapter-registry` export provides `AdapterRegistry` and `registerAdapter(...)`, and a registry a host constructs is not the one the tool reads, so supporting another element type is a change to this package. A `ChoiceAdapter` declares `elementType`, `priority`, `canHandle`, `findChoices`, `getChoiceId`, `getChoiceLabel`, `canEliminate`, `createChoiceRange` and `getButtonContainer`.
|
|
198
211
|
|
|
199
212
|
### 2. State Storage
|
|
200
213
|
|
|
@@ -259,7 +272,7 @@ store.clearAll();
|
|
|
259
272
|
Full TypeScript definitions included:
|
|
260
273
|
|
|
261
274
|
```typescript
|
|
262
|
-
import type {
|
|
275
|
+
import type { ElementToolStateStoreApi } from '@pie-players/pie-assessment-toolkit';
|
|
263
276
|
|
|
264
277
|
interface AnswerEliminatorState {
|
|
265
278
|
eliminatedChoices: string[];
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
+
import { parseVersionedTagName } from "@pie-players/pie-players-shared/pie/tag-names";
|
|
1
2
|
import { MultipleChoiceAdapter } from "./multiple-choice-adapter.js";
|
|
2
3
|
const EBSR_MULTIPLE_CHOICE_TAG = "ebsr-multiple-choice";
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
const tagName = element.tagName.toLowerCase();
|
|
9
|
-
return (tagName === EBSR_MULTIPLE_CHOICE_TAG ||
|
|
10
|
-
tagName.startsWith(EBSR_MULTIPLE_CHOICE_VERSIONED_PREFIX));
|
|
11
|
-
};
|
|
4
|
+
const isEbsrMultipleChoiceElement = (element) => element instanceof HTMLElement &&
|
|
5
|
+
parseVersionedTagName(element.tagName.toLowerCase()).baseName ===
|
|
6
|
+
EBSR_MULTIPLE_CHOICE_TAG;
|
|
12
7
|
const findEbsrMultipleChoicePart = (root, id) => Array.from(root.querySelectorAll(`[id="${id}"]`)).find(isEbsrMultipleChoiceElement) ?? null;
|
|
13
8
|
const findClosestEbsrMultipleChoicePart = (choice) => {
|
|
14
9
|
let element = choice.parentElement;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* pie-tool-answer-eliminator - PIE Assessment Tool
|
|
3
|
+
*
|
|
4
|
+
* Importing this package registers `<pie-tool-answer-eliminator>`. The build
|
|
5
|
+
* entry is the component, so this file is the type entry alone.
|
|
6
|
+
*/
|
|
7
|
+
export type {};
|