@pie-players/pie-tool-answer-eliminator 1.0.0-beta.0 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -182,15 +182,46 @@ const coordinator = new ToolkitCoordinator({
182
182
 
183
183
  ### 1. Choice Detection
184
184
 
185
- The tool detects choices through an **adapter registry** (`AdapterRegistry`), not a fixed selector list. Each adapter knows how to find and operate on choices for a specific PIE element type, and the registry runs them in priority order (`canHandle()`, then `findChoices()`), so a single question can mix element types:
185
+ Elements supply their own choices. An element takes the eliminator by declaring the AfA PNP 3.0 support term `answer-masking` on its class and answering `pieSupportTargets('answer-masking')` on its instances:
186
186
 
187
- | Adapter | Element type | How it finds choices |
188
- | --- | --- | --- |
189
- | `MultipleChoiceAdapter` | `multiple-choice` (single- or multi-select) | `.corespring-checkbox` / `.corespring-radio-button` choices |
190
- | `EBSRAdapter` | `ebsr` | delegates to the multiple-choice adapter for each `ebsr-multiple-choice` part (Part A/B), prefixing choice IDs with the part |
191
- | `InlineDropdownAdapter` | `inline-dropdown` | dropdown items with `role="option"` |
187
+ ```typescript
188
+ class ChoiceGrid extends HTMLElement {
189
+ static pieSupports = ['answer-masking'];
190
+
191
+ pieSupportTargets(term: string) {
192
+ if (term !== 'answer-masking') return [];
193
+ return this.rows.map((row) => ({
194
+ id: row.value,
195
+ label: row.text,
196
+ container: row.element,
197
+ content: row.labelElement,
198
+ isSelected: () => this.isChosen(row.value),
199
+ isEliminable: () => this.mode === 'gather' && !this.isChosen(row.value),
200
+ setEliminated: (eliminated: boolean) => this.block(row.value, eliminated),
201
+ }));
202
+ }
203
+ }
204
+ ```
205
+
206
+ Every field is required, and a choice missing one is skipped with a console warning:
207
+
208
+ | Field | Contract |
209
+ | --- | --- |
210
+ | `id` | Unique within the element and stable across renders: eliminations persist by it. |
211
+ | `label` | The choice's accessible name; the toggle is announced as "Toggle elimination for `label`". |
212
+ | `container` | Receives the toggle and the eliminated state. The tool sets `position: relative` on it. An inline container, such as a token in running text, takes the toggle in the line. |
213
+ | `content` | The part that is struck through or masked. It must be inside `container`. |
214
+ | `isSelected()` | Whether the learner has chosen it. A selected choice hides its toggle and is never eliminated. |
215
+ | `isEliminable()` | False in evaluate and view modes, and for disabled or selected choices. |
216
+ | `setEliminated(eliminated)` | Blocks or restores the learner's selection of the choice. The element owns this: the tool never disables controls it did not render. A call with the value the choice already has changes nothing. |
217
+
218
+ The toolbar reads the same `static pieSupports` declaration to decide whether to offer the eliminator, so an element built outside this repository needs no change here. A declaration that omits `answer-masking`, including `[]`, means the element takes no eliminator.
219
+
220
+ An element may replace its choices' markup on any render, as select-text does. When a container leaves the document, the tool asks for the choices again and keeps their eliminations by id, moving focus to the replacement toggle. It does not call `setEliminated` again on the same element instance, so an element that re-renders from `setEliminated` settles; a new instance is asked to block its eliminated choices, and a choice no longer supplied is restored.
221
+
222
+ The outermost declaring element under the item owns its subtree: an element composed of declaring parts answers for them, prefixing ids with the part where they would collide, as EBSR does with `a-` and `b-`. Eliminations persist under the key of the nearest element listed in `elementStateKeys`, starting from the declaring element.
192
223
 
193
- 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`.
224
+ Elements that declare nothing fall back to the multiple-choice and EBSR markup this package reads (`.corespring-checkbox` and `.corespring-radio-button` choices, and the `ebsr-multiple-choice` parts with ids `a` and `b`). That fallback serves legacy pie-elements and pie-elements-ng releases from before elements declared their supports, and never runs inside a declaring element.
194
225
 
195
226
  ### 2. State Storage
196
227
 
@@ -230,7 +261,7 @@ For browsers without the Highlight API, each strategy falls back to a class on t
230
261
 
231
262
  ### 4. Toggle Behavior
232
263
 
233
- Each detected choice gets its own elimination toggle button (class `pie-answer-eliminator-toggle`, rendered as `⊗`) placed via the adapter's `getButtonContainer()`. Clicking the button toggles that choice through the active strategy. Eliminating is blocked when the adapter's `canEliminate()` returns false — for example when the choice is already selected, disabled, or the item is in evaluate/view mode. An active button is marked with `pie-answer-eliminator-toggle--active` and `aria-pressed="true"`; clicking again restores the choice.
264
+ Each choice gets its own elimination toggle button (class `pie-answer-eliminator-toggle`, rendered as `⊗`) appended to its `container`. Clicking the button toggles that choice through the active strategy and calls `setEliminated`. Eliminating is blocked while `isEliminable()` returns false. An active button is marked with `pie-answer-eliminator-toggle--active` and `aria-pressed="true"`; clicking again restores the choice.
234
265
 
235
266
  ## Cleanup
236
267
 
@@ -7,7 +7,7 @@
7
7
  "declarations": [
8
8
  {
9
9
  "kind": "class",
10
- "description": "Process-of-elimination tool for the item in its enclosing `<pie-item-scope>`: it adds a toggle beside each multiple-choice, EBSR and inline-dropdown choice that strikes the choice through or masks it, per `strategy`. It renders nothing of its own and is active while `visible` or `always-on` is set. Eliminations persist in the runtime context's element tool state store, under the key `elementStateKeys` gives each PIE element.",
10
+ "description": "Process-of-elimination tool for the item in its enclosing `<pie-item-scope>`: it adds a toggle beside each choice an element supplies for `answer-masking` that strikes the choice through or masks it, per `strategy`. It renders nothing of its own and is active while `visible` or `always-on` is set. Eliminations persist in the runtime context's element tool state store, under the key `elementStateKeys` gives each PIE element.",
11
11
  "name": "ToolAnswerEliminator",
12
12
  "tagName": "pie-tool-answer-eliminator",
13
13
  "customElement": true,