@pie-players/pie-tool-answer-eliminator 0.3.74 → 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 CHANGED
@@ -28,9 +28,14 @@ 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 { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
31
+ import {
32
+ createPackagedToolRegistry,
33
+ DEFAULT_TOOL_MODULE_LOADERS,
34
+ } from '@pie-players/pie-default-tool-loaders';
32
35
 
33
- const toolRegistry = createPackagedToolRegistry();
36
+ const toolRegistry = createPackagedToolRegistry({
37
+ toolModuleLoaders: DEFAULT_TOOL_MODULE_LOADERS,
38
+ });
34
39
  const coordinator = new ToolkitCoordinator({
35
40
  assessmentId: 'my-assessment',
36
41
  toolRegistry,
@@ -50,44 +55,47 @@ The answer eliminator is automatically integrated when using the PIE Section Pla
50
55
  The section player automatically:
51
56
  - Renders answer eliminator buttons in question toolbars
52
57
  - Generates global element IDs
53
- - Passes ElementToolStateStore to the tool
54
58
  - Manages state lifecycle
55
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
+
56
63
  ### Manual Integration (Advanced)
57
64
 
58
- For custom implementations outside the section player:
65
+ For a custom layout inside the toolkit:
59
66
 
60
67
  ```html
61
68
  <script type="module">
62
69
  import '@pie-players/pie-tool-answer-eliminator';
63
- import { ElementToolStateStore } from '@pie-players/pie-assessment-toolkit';
64
-
65
- const store = new ElementToolStateStore();
66
- const globalElementId = store.getGlobalElementId(
67
- 'my-assessment',
68
- 'section-1',
69
- 'question-1',
70
- 'mc1'
71
- );
72
70
 
73
71
  const tool = document.querySelector('pie-tool-answer-eliminator');
74
- tool.globalElementId = globalElementId;
75
- tool.elementToolStateStore = store;
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
+ };
76
77
  tool.scopeElement = document.querySelector('.question-content');
78
+ tool.visible = true; // or alwaysOn = true; the tool injects no buttons while neither is set
77
79
  </script>
78
80
 
79
- <pie-tool-answer-eliminator></pie-tool-answer-eliminator>
81
+ <pie-assessment-toolkit>
82
+ <pie-tool-answer-eliminator></pie-tool-answer-eliminator>
83
+ </pie-assessment-toolkit>
80
84
  ```
81
85
 
82
86
  ## Props/Attributes
83
87
 
84
- The web component accepts the following properties (set via JavaScript, not HTML attributes):
88
+ `elementStateKeys` and `scopeElement` are JS properties only; the others also take the attribute shown.
85
89
 
86
- | Property | Type | Required | Description |
87
- |----------|------|----------|-------------|
88
- | `globalElementId` | `string` | Yes | Composite key: `assessmentId:sectionId:itemId:elementId` |
89
- | `elementToolStateStore` | `ElementToolStateStoreApi` | Yes | Store for element-level tool state |
90
- | `scopeElement` | `HTMLElement` | No | DOM element to scope choice detection (defaults to document) |
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 |
91
99
 
92
100
  ## Global Element ID Format
93
101
 
@@ -100,7 +108,7 @@ ${assessmentId}:${sectionId}:${itemId}:${elementId}
100
108
  **Example:**
101
109
  ```typescript
102
110
  "demo-assessment:section-1:question-1:mc1"
103
- "biology-exam:section-2:genetics-q1:ebsr-part1"
111
+ "biology-exam:section-2:genetics-q1:ebsr1"
104
112
  ```
105
113
 
106
114
  ### Benefits of Composite Keys
@@ -112,16 +120,16 @@ ${assessmentId}:${sectionId}:${itemId}:${elementId}
112
120
 
113
121
  ### Why Element-Level?
114
122
 
115
- Items can contain **multiple interactive elements** (e.g., EBSR with two parts). Each element needs independent state:
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:
116
124
 
117
125
  ```typescript
118
126
  // ✅ Correct: Element-level state
119
127
  {
120
- "demo:section-1:question-1:ebsr-part1": {
121
- "answerEliminator": { "eliminatedChoices": ["choice-a", "choice-c"] }
128
+ "demo:section-1:question-1:mc1": {
129
+ "answerEliminator": { "eliminatedChoices": ["a", "c"] }
122
130
  },
123
- "demo:section-1:question-1:ebsr-part2": {
124
- "answerEliminator": { "eliminatedChoices": ["choice-b"] }
131
+ "demo:section-1:question-1:mc2": {
132
+ "answerEliminator": { "eliminatedChoices": ["a"] }
125
133
  }
126
134
  }
127
135
  ```
@@ -160,9 +168,14 @@ The answer eliminator stores state in **ElementToolStateStore** (ephemeral, clie
160
168
  To persist tool state across page refreshes:
161
169
 
162
170
  ```typescript
163
- import { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
171
+ import {
172
+ createPackagedToolRegistry,
173
+ DEFAULT_TOOL_MODULE_LOADERS,
174
+ } from '@pie-players/pie-default-tool-loaders';
164
175
 
165
- const toolRegistry = createPackagedToolRegistry();
176
+ const toolRegistry = createPackagedToolRegistry({
177
+ toolModuleLoaders: DEFAULT_TOOL_MODULE_LOADERS,
178
+ });
166
179
  const coordinator = new ToolkitCoordinator({
167
180
  assessmentId: 'my-assessment',
168
181
  toolRegistry,
@@ -194,14 +207,7 @@ The tool detects choices through an **adapter registry** (`AdapterRegistry`), no
194
207
  | `EBSRAdapter` | `ebsr` | delegates to the multiple-choice adapter for each `ebsr-multiple-choice` part (Part A/B), prefixing choice IDs with the part |
195
208
  | `InlineDropdownAdapter` | `inline-dropdown` | dropdown items with `role="option"` |
196
209
 
197
- Support more element types at runtime by registering your own adapter (any object implementing the `ChoiceAdapter` interface: `canHandle`, `findChoices`, `getChoiceId`, `getChoiceLabel`, `canEliminate`, `createChoiceRange`, `getButtonContainer`):
198
-
199
- ```typescript
200
- import { AdapterRegistry } from '@pie-players/pie-tool-answer-eliminator/adapters/adapter-registry';
201
-
202
- const registry = new AdapterRegistry();
203
- registry.registerAdapter(myCustomChoiceAdapter);
204
- ```
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`.
205
211
 
206
212
  ### 2. State Storage
207
213