@pie-players/pie-tool-answer-eliminator 0.2.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.
Files changed (38) hide show
  1. package/README.md +282 -0
  2. package/adapters/adapter-registry.ts +64 -0
  3. package/adapters/choice-adapter.ts +50 -0
  4. package/adapters/ebsr-adapter.ts +61 -0
  5. package/adapters/inline-dropdown-adapter.ts +46 -0
  6. package/adapters/multiple-choice-adapter.ts +96 -0
  7. package/answer-eliminator-core.ts +465 -0
  8. package/dist/adapters/adapter-registry.d.ts +26 -0
  9. package/dist/adapters/adapter-registry.d.ts.map +1 -0
  10. package/dist/adapters/choice-adapter.d.ts +43 -0
  11. package/dist/adapters/choice-adapter.d.ts.map +1 -0
  12. package/dist/adapters/ebsr-adapter.d.ts +20 -0
  13. package/dist/adapters/ebsr-adapter.d.ts.map +1 -0
  14. package/dist/adapters/inline-dropdown-adapter.d.ts +18 -0
  15. package/dist/adapters/inline-dropdown-adapter.d.ts.map +1 -0
  16. package/dist/adapters/multiple-choice-adapter.d.ts +20 -0
  17. package/dist/adapters/multiple-choice-adapter.d.ts.map +1 -0
  18. package/dist/answer-eliminator-core.d.ts +98 -0
  19. package/dist/answer-eliminator-core.d.ts.map +1 -0
  20. package/dist/index.d.ts +8 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/strategies/elimination-strategy.d.ts +41 -0
  23. package/dist/strategies/elimination-strategy.d.ts.map +1 -0
  24. package/dist/strategies/mask-strategy.d.ts +28 -0
  25. package/dist/strategies/mask-strategy.d.ts.map +1 -0
  26. package/dist/strategies/strikethrough-strategy.d.ts +31 -0
  27. package/dist/strategies/strikethrough-strategy.d.ts.map +1 -0
  28. package/dist/tool-answer-eliminator.js +2838 -0
  29. package/dist/tool-answer-eliminator.js.map +1 -0
  30. package/dist/tool-answer-eliminator.svelte.d.ts +1 -0
  31. package/dist/vite.config.d.ts +3 -0
  32. package/dist/vite.config.d.ts.map +1 -0
  33. package/index.ts +11 -0
  34. package/package.json +69 -0
  35. package/strategies/elimination-strategy.ts +47 -0
  36. package/strategies/mask-strategy.ts +180 -0
  37. package/strategies/strikethrough-strategy.ts +239 -0
  38. package/tool-answer-eliminator.svelte +250 -0
@@ -0,0 +1,465 @@
1
+ import { AdapterRegistry } from "./adapters/adapter-registry";
2
+ import type { ChoiceAdapter } from "./adapters/choice-adapter";
3
+ import type { EliminationStrategy } from "./strategies/elimination-strategy";
4
+ import { MaskStrategy } from "./strategies/mask-strategy";
5
+ import { StrikethroughStrategy } from "./strategies/strikethrough-strategy";
6
+
7
+ /**
8
+ * Core engine for answer eliminator tool
9
+ * Coordinates adapters, strategies, and state management
10
+ */
11
+ export class AnswerEliminatorCore {
12
+ private registry: AdapterRegistry;
13
+ private strategy: EliminationStrategy;
14
+ private eliminatedChoices = new Set<string>(); // Set<choiceId> for current element
15
+ private choiceElements = new Map<string, HTMLElement>(); // choiceId -> element
16
+ private choiceButtons = new Map<string, HTMLButtonElement>(); // choiceId -> button
17
+ private buttonAlignment: "left" | "right" | "inline" = "right";
18
+ private shouldRestoreState: boolean = true; // Whether to restore eliminations from state storage
19
+
20
+ // Store integration (replaces session/localStorage)
21
+ private storeIntegration: {
22
+ store: any; // ElementToolStateStore
23
+ globalElementId: string; // Composite key: "assessmentId:sectionId:itemId:elementId"
24
+ } | null = null;
25
+
26
+ constructor(
27
+ strategyType: "strikethrough" | "mask" | "gray" = "strikethrough",
28
+ buttonAlignment: "left" | "right" | "inline" = "right",
29
+ ) {
30
+ this.registry = new AdapterRegistry();
31
+ this.strategy = this.createStrategy(strategyType);
32
+ this.strategy.initialize();
33
+ this.buttonAlignment = buttonAlignment;
34
+ }
35
+
36
+ private createStrategy(type: string): EliminationStrategy {
37
+ switch (type) {
38
+ case "mask":
39
+ return new MaskStrategy();
40
+ case "strikethrough":
41
+ default:
42
+ return new StrikethroughStrategy();
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Initialize eliminator for a question
48
+ */
49
+ initializeForQuestion(questionRoot: HTMLElement): void {
50
+ // Clean up previous question
51
+ this.cleanupButtons();
52
+
53
+ // Find all choices with their adapters
54
+ const choicesWithAdapters =
55
+ this.registry.findAllChoicesWithAdapters(questionRoot);
56
+
57
+ // Attach elimination functionality to each choice
58
+ for (const { choice, adapter } of choicesWithAdapters) {
59
+ this.initializeChoice(choice, adapter);
60
+ }
61
+
62
+ // Restore eliminated state from store (only if enabled)
63
+ if (this.shouldRestoreState) {
64
+ this.restoreState();
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Initialize a single choice
70
+ */
71
+ private initializeChoice(choice: HTMLElement, adapter: ChoiceAdapter): void {
72
+ const choiceId = adapter.getChoiceId(choice);
73
+
74
+ // Track element
75
+ this.choiceElements.set(choiceId, choice);
76
+
77
+ // Create elimination toggle button
78
+ const button = this.createToggleButton(choice, adapter);
79
+ if (!button) return;
80
+
81
+ this.choiceButtons.set(choiceId, button);
82
+
83
+ // Attach button to choice
84
+ const container = adapter.getButtonContainer(choice);
85
+ if (container) {
86
+ // Position button within container
87
+ container.style.position = "relative";
88
+ container.appendChild(button);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Create elimination toggle button
94
+ */
95
+ private createToggleButton(
96
+ choice: HTMLElement,
97
+ adapter: ChoiceAdapter,
98
+ ): HTMLButtonElement | null {
99
+ const choiceId = adapter.getChoiceId(choice);
100
+ const choiceLabel = adapter.getChoiceLabel(choice);
101
+
102
+ const button = document.createElement("button");
103
+ button.type = "button";
104
+ button.className = "answer-eliminator-toggle";
105
+ button.setAttribute("aria-label", `Toggle elimination for ${choiceLabel}`);
106
+ button.setAttribute("data-choice-id", choiceId);
107
+ button.textContent = "⊗"; // Cross mark (use textContent instead of innerHTML for better security)
108
+
109
+ // Apply positioning based on alignment configuration
110
+ this.applyButtonAlignment(button);
111
+
112
+ // Common button styling
113
+ Object.assign(button.style, {
114
+ width: "28px",
115
+ height: "28px",
116
+ padding: "0",
117
+ border: "1px solid #ccc",
118
+ borderRadius: "4px",
119
+ background: "white",
120
+ cursor: "pointer",
121
+ fontSize: "18px",
122
+ lineHeight: "1",
123
+ display: "flex",
124
+ alignItems: "center",
125
+ justifyContent: "center",
126
+ color: "#666",
127
+ transition: "all 0.2s ease",
128
+ zIndex: "10",
129
+ });
130
+
131
+ // Add hover effect
132
+ button.addEventListener("mouseenter", () => {
133
+ button.style.background = "#f0f0f0";
134
+ button.style.borderColor = "#999";
135
+ button.style.color = "#333";
136
+ });
137
+
138
+ button.addEventListener("mouseleave", () => {
139
+ if (!this.strategy.isEliminated(choiceId)) {
140
+ button.style.background = "white";
141
+ button.style.borderColor = "#ccc";
142
+ button.style.color = "#666";
143
+ }
144
+ });
145
+
146
+ button.addEventListener("click", (e) => {
147
+ e.preventDefault();
148
+ e.stopPropagation();
149
+ this.toggleElimination(choice, adapter);
150
+ });
151
+
152
+ return button;
153
+ }
154
+
155
+ /**
156
+ * Toggle elimination for a choice
157
+ */
158
+ toggleElimination(choice: HTMLElement, adapter: ChoiceAdapter): void {
159
+ const choiceId = adapter.getChoiceId(choice);
160
+
161
+ // Check if already eliminated
162
+ const isEliminated = this.strategy.isEliminated(choiceId);
163
+
164
+ if (isEliminated) {
165
+ // Restore
166
+ this.restoreChoice(choiceId);
167
+ } else {
168
+ // Eliminate
169
+ if (!adapter.canEliminate(choice)) {
170
+ console.warn(
171
+ "Cannot eliminate this choice (already selected or in evaluate mode)",
172
+ );
173
+ return;
174
+ }
175
+
176
+ this.eliminateChoice(choice, adapter);
177
+ }
178
+
179
+ // Save state
180
+ this.saveState();
181
+
182
+ // Emit state change event
183
+ this.emitStateChange();
184
+ }
185
+
186
+ /**
187
+ * Eliminate a choice
188
+ */
189
+ private eliminateChoice(choice: HTMLElement, adapter: ChoiceAdapter): void {
190
+ const choiceId = adapter.getChoiceId(choice);
191
+
192
+ // Create range for CSS Highlight API
193
+ const range = adapter.createChoiceRange(choice);
194
+ if (!range) {
195
+ console.error("Failed to create range for choice");
196
+ return;
197
+ }
198
+
199
+ // Apply strategy
200
+ this.strategy.apply(choiceId, range);
201
+
202
+ // Track in state
203
+ this.eliminatedChoices.add(choiceId);
204
+
205
+ // Update button appearance to show eliminated state
206
+ const button = this.choiceButtons.get(choiceId);
207
+ if (button) {
208
+ button.classList.add("active");
209
+ button.setAttribute("aria-pressed", "true");
210
+ // Visual feedback: filled/highlighted when eliminated
211
+ button.style.background = "#ff9800";
212
+ button.style.borderColor = "#ff9800";
213
+ button.style.color = "white";
214
+ }
215
+
216
+ // Save to store
217
+ this.saveState();
218
+ }
219
+
220
+ /**
221
+ * Restore a choice
222
+ */
223
+ private restoreChoice(choiceId: string): void {
224
+ // Remove from strategy
225
+ this.strategy.remove(choiceId);
226
+
227
+ // Remove from state
228
+ this.eliminatedChoices.delete(choiceId);
229
+
230
+ // Reset button appearance to default state
231
+ const button = this.choiceButtons.get(choiceId);
232
+ if (button) {
233
+ button.classList.remove("active");
234
+ button.setAttribute("aria-pressed", "false");
235
+ // Reset to default styling
236
+ button.style.background = "white";
237
+ button.style.borderColor = "#ccc";
238
+ button.style.color = "#666";
239
+ }
240
+
241
+ // Save to store
242
+ this.saveState();
243
+ }
244
+
245
+ /**
246
+ * Reset all eliminations for current element
247
+ */
248
+ resetAll(): void {
249
+ if (this.eliminatedChoices.size === 0) return;
250
+
251
+ // Restore all choices
252
+ for (const choiceId of Array.from(this.eliminatedChoices)) {
253
+ this.restoreChoice(choiceId);
254
+ }
255
+
256
+ // Clear state
257
+ this.eliminatedChoices.clear();
258
+ this.saveState();
259
+ this.emitStateChange();
260
+ }
261
+
262
+ /**
263
+ * Get count of eliminated choices for current element
264
+ */
265
+ getEliminatedCount(): number {
266
+ return this.eliminatedChoices.size;
267
+ }
268
+
269
+ /**
270
+ * Set store integration for element-level state
271
+ * @param store ElementToolStateStore instance
272
+ * @param globalElementId Composite key: "assessmentId:sectionId:itemId:elementId"
273
+ */
274
+ setStoreIntegration(store: any, globalElementId: string): void {
275
+ this.storeIntegration = { store, globalElementId };
276
+ }
277
+
278
+ /**
279
+ * Save state to ElementToolStateStore
280
+ */
281
+ private saveState(): void {
282
+ if (!this.storeIntegration) return;
283
+
284
+ const state = {
285
+ eliminatedChoices: Array.from(this.eliminatedChoices),
286
+ };
287
+
288
+ this.storeIntegration.store.setState(
289
+ this.storeIntegration.globalElementId,
290
+ "answerEliminator",
291
+ state,
292
+ );
293
+ }
294
+
295
+ /**
296
+ * Restore state from ElementToolStateStore
297
+ */
298
+ private restoreState(): void {
299
+ if (!this.storeIntegration) return;
300
+
301
+ const state = this.storeIntegration.store.getState(
302
+ this.storeIntegration.globalElementId,
303
+ "answerEliminator",
304
+ );
305
+
306
+ if (!state || !state.eliminatedChoices) return;
307
+
308
+ try {
309
+ const eliminated = state.eliminatedChoices;
310
+
311
+ if (!eliminated || eliminated.length === 0) return;
312
+
313
+ // Restore eliminated choices for current element
314
+ for (const choiceId of eliminated) {
315
+ const choice = this.choiceElements.get(choiceId);
316
+ if (!choice) continue;
317
+
318
+ // Find adapter for this choice
319
+ const adapter = this.findAdapterForChoice(choice);
320
+ if (!adapter) continue;
321
+
322
+ // Re-eliminate without saving (already in state)
323
+ const range = adapter.createChoiceRange(choice);
324
+ if (range) {
325
+ this.strategy.apply(choiceId, range);
326
+
327
+ // Track in memory
328
+ this.eliminatedChoices.add(choiceId);
329
+
330
+ // Update button appearance to show eliminated state
331
+ const button = this.choiceButtons.get(choiceId);
332
+ if (button) {
333
+ button.classList.add("active");
334
+ button.setAttribute("aria-pressed", "true");
335
+ // Apply eliminated styling
336
+ button.style.background = "#ff9800";
337
+ button.style.borderColor = "#ff9800";
338
+ button.style.color = "white";
339
+ }
340
+ }
341
+ }
342
+ } catch (error) {
343
+ console.error("Failed to restore eliminator state:", error);
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Find adapter for a choice element
349
+ */
350
+ private findAdapterForChoice(choice: HTMLElement): ChoiceAdapter | null {
351
+ // Walk up to find PIE element root
352
+ let element: HTMLElement | null = choice;
353
+
354
+ while (element && element !== document.body) {
355
+ const adapter = this.registry.findAdapter(element);
356
+ if (adapter) return adapter;
357
+ element = element.parentElement;
358
+ }
359
+
360
+ return null;
361
+ }
362
+
363
+ /**
364
+ * Cleanup buttons from previous element
365
+ */
366
+ private cleanupButtons(): void {
367
+ for (const button of this.choiceButtons.values()) {
368
+ button.remove();
369
+ }
370
+
371
+ this.choiceButtons.clear();
372
+ this.choiceElements.clear();
373
+ }
374
+
375
+ /**
376
+ * Apply button positioning based on alignment configuration
377
+ */
378
+ private applyButtonAlignment(button: HTMLButtonElement): void {
379
+ switch (this.buttonAlignment) {
380
+ case "right":
381
+ // Right-aligned (industry standard) - after choice text
382
+ Object.assign(button.style, {
383
+ position: "absolute",
384
+ right: "8px",
385
+ top: "50%",
386
+ transform: "translateY(-50%)",
387
+ });
388
+ break;
389
+
390
+ case "left":
391
+ // Left-aligned - before choice text
392
+ Object.assign(button.style, {
393
+ position: "absolute",
394
+ left: "8px",
395
+ top: "50%",
396
+ transform: "translateY(-50%)",
397
+ });
398
+ break;
399
+
400
+ case "inline":
401
+ // Inline with checkbox - no absolute positioning
402
+ Object.assign(button.style, {
403
+ position: "relative",
404
+ marginLeft: "8px",
405
+ marginRight: "8px",
406
+ display: "inline-flex",
407
+ verticalAlign: "middle",
408
+ });
409
+ break;
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Enable state restoration from localStorage
415
+ */
416
+ enableStateRestoration(): void {
417
+ this.shouldRestoreState = true;
418
+ }
419
+
420
+ /**
421
+ * Disable state restoration from localStorage
422
+ */
423
+ disableStateRestoration(): void {
424
+ this.shouldRestoreState = false;
425
+ }
426
+
427
+ /**
428
+ * Cleanup when tool is turned off (but don't destroy strategy)
429
+ * Hides elimination buttons AND clears all visual eliminations
430
+ * Note: State is preserved in localStorage for when tool is turned back on
431
+ */
432
+ cleanup(): void {
433
+ // Disable state restoration to prevent restoreState() from re-applying eliminations
434
+ this.disableStateRestoration();
435
+
436
+ // Remove all buttons
437
+ this.cleanupButtons();
438
+
439
+ // Clear all visual eliminations (strikethroughs)
440
+ // This removes the CSS highlights but keeps localStorage state
441
+ this.strategy.clearAll();
442
+ }
443
+
444
+ /**
445
+ * Emit state change event for UI updates
446
+ */
447
+ private emitStateChange(): void {
448
+ const event = new CustomEvent("answer-eliminator-state-change", {
449
+ detail: {
450
+ questionId: this.currentQuestionId,
451
+ eliminatedCount: this.getEliminatedCount(),
452
+ },
453
+ bubbles: true,
454
+ });
455
+ document.dispatchEvent(event);
456
+ }
457
+
458
+ /**
459
+ * Destroy and cleanup
460
+ */
461
+ destroy(): void {
462
+ this.cleanupButtons();
463
+ this.strategy.destroy();
464
+ }
465
+ }
@@ -0,0 +1,26 @@
1
+ import { ChoiceAdapter } from './choice-adapter';
2
+ export interface ChoiceWithAdapter {
3
+ choice: HTMLElement;
4
+ adapter: ChoiceAdapter;
5
+ }
6
+ /**
7
+ * Registry for choice adapters
8
+ * Automatically detects which adapter to use for different PIE elements
9
+ */
10
+ export declare class AdapterRegistry {
11
+ private adapters;
12
+ constructor();
13
+ /**
14
+ * Find the appropriate adapter for an element
15
+ */
16
+ findAdapter(element: HTMLElement): ChoiceAdapter | null;
17
+ /**
18
+ * Find all choices with their adapters within a root element
19
+ */
20
+ findAllChoicesWithAdapters(root: HTMLElement): ChoiceWithAdapter[];
21
+ /**
22
+ * Register a custom adapter
23
+ */
24
+ registerAdapter(adapter: ChoiceAdapter): void;
25
+ }
26
+ //# sourceMappingURL=adapter-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-registry.d.ts","sourceRoot":"","sources":["../../adapters/adapter-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKtD,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,aAAa,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAkB;;IAWlC;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,GAAG,IAAI;IAIvD;;OAEG;IACH,0BAA0B,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,EAAE;IAoBlE;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;CAI7C"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Adapter interface for detecting and working with choice elements
3
+ * from different PIE element types.
4
+ *
5
+ * Adapters enable the answer eliminator to work generically with
6
+ * multiple-choice, EBSR, inline-dropdown, and future choice elements.
7
+ */
8
+ export interface ChoiceAdapter {
9
+ /** Element type this adapter handles */
10
+ readonly elementType: string;
11
+ /** Priority (higher = checked first) */
12
+ readonly priority: number;
13
+ /**
14
+ * Check if this adapter can handle the given element
15
+ */
16
+ canHandle(element: HTMLElement): boolean;
17
+ /**
18
+ * Find all choice elements within the root
19
+ */
20
+ findChoices(root: HTMLElement): HTMLElement[];
21
+ /**
22
+ * Create a Range covering the choice content (for CSS Highlight API)
23
+ */
24
+ createChoiceRange(choice: HTMLElement): Range | null;
25
+ /**
26
+ * Get unique identifier for this choice (for persistence)
27
+ */
28
+ getChoiceId(choice: HTMLElement): string;
29
+ /**
30
+ * Get human-readable label (for screen readers)
31
+ */
32
+ getChoiceLabel(choice: HTMLElement): string;
33
+ /**
34
+ * Check if choice can be eliminated
35
+ * (not already selected, not in evaluate mode, etc.)
36
+ */
37
+ canEliminate(choice: HTMLElement): boolean;
38
+ /**
39
+ * Get the container element to attach elimination button
40
+ */
41
+ getButtonContainer(choice: HTMLElement): HTMLElement | null;
42
+ }
43
+ //# sourceMappingURL=choice-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choice-adapter.d.ts","sourceRoot":"","sources":["../../adapters/choice-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC;IAEzC;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;IAE9C;;OAEG;IACH,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;IAEzC;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;IAE5C;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAE3C;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;CAC5D"}
@@ -0,0 +1,20 @@
1
+ import { ChoiceAdapter } from './choice-adapter';
2
+ /**
3
+ * Adapter for EBSR (Evidence-Based Selected Response) elements
4
+ *
5
+ * EBSR contains two multiple-choice questions (Part A and Part B),
6
+ * so we delegate to MultipleChoiceAdapter and prefix IDs with part identifier
7
+ */
8
+ export declare class EBSRAdapter implements ChoiceAdapter {
9
+ readonly elementType = "ebsr";
10
+ readonly priority = 95;
11
+ private mcAdapter;
12
+ canHandle(element: HTMLElement): boolean;
13
+ findChoices(root: HTMLElement): HTMLElement[];
14
+ createChoiceRange(choice: HTMLElement): Range | null;
15
+ getChoiceId(choice: HTMLElement): string;
16
+ getChoiceLabel(choice: HTMLElement): string;
17
+ canEliminate(choice: HTMLElement): boolean;
18
+ getButtonContainer(choice: HTMLElement): HTMLElement | null;
19
+ }
20
+ //# sourceMappingURL=ebsr-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ebsr-adapter.d.ts","sourceRoot":"","sources":["../../adapters/ebsr-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,aAAa;IAChD,QAAQ,CAAC,WAAW,UAAU;IAC9B,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,SAAS,CAA+B;IAEhD,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO;IAOxC,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE;IAgB7C,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI;IAIpD,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAOxC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAI3C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAI1C,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI;CAG3D"}
@@ -0,0 +1,18 @@
1
+ import { ChoiceAdapter } from './choice-adapter';
2
+ /**
3
+ * Adapter for PIE inline-dropdown elements
4
+ *
5
+ * Works with dropdown menu items (role="option")
6
+ */
7
+ export declare class InlineDropdownAdapter implements ChoiceAdapter {
8
+ readonly elementType = "inline-dropdown";
9
+ readonly priority = 90;
10
+ canHandle(element: HTMLElement): boolean;
11
+ findChoices(root: HTMLElement): HTMLElement[];
12
+ createChoiceRange(choice: HTMLElement): Range | null;
13
+ getChoiceId(choice: HTMLElement): string;
14
+ getChoiceLabel(choice: HTMLElement): string;
15
+ canEliminate(choice: HTMLElement): boolean;
16
+ getButtonContainer(choice: HTMLElement): HTMLElement | null;
17
+ }
18
+ //# sourceMappingURL=inline-dropdown-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-dropdown-adapter.d.ts","sourceRoot":"","sources":["../../adapters/inline-dropdown-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IAC1D,QAAQ,CAAC,WAAW,qBAAqB;IACzC,QAAQ,CAAC,QAAQ,MAAM;IAEvB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO;IAOxC,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE;IAK7C,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI;IAMpD,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAIxC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAI3C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAK1C,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI;CAG3D"}
@@ -0,0 +1,20 @@
1
+ import { ChoiceAdapter } from './choice-adapter';
2
+ /**
3
+ * Adapter for PIE multiple-choice elements
4
+ *
5
+ * Works with both single-select (radio) and multiple-select (checkbox) modes
6
+ * Detects PIE's corespring-checkbox and corespring-radio-button classes
7
+ */
8
+ export declare class MultipleChoiceAdapter implements ChoiceAdapter {
9
+ readonly elementType = "multiple-choice";
10
+ readonly priority = 100;
11
+ canHandle(element: HTMLElement): boolean;
12
+ findChoices(root: HTMLElement): HTMLElement[];
13
+ createChoiceRange(choice: HTMLElement): Range | null;
14
+ getChoiceId(choice: HTMLElement): string;
15
+ getChoiceLabel(choice: HTMLElement): string;
16
+ canEliminate(choice: HTMLElement): boolean;
17
+ getButtonContainer(choice: HTMLElement): HTMLElement | null;
18
+ private generateFallbackId;
19
+ }
20
+ //# sourceMappingURL=multiple-choice-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiple-choice-adapter.d.ts","sourceRoot":"","sources":["../../adapters/multiple-choice-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IAC1D,QAAQ,CAAC,WAAW,qBAAqB;IACzC,QAAQ,CAAC,QAAQ,OAAO;IAExB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO;IAOxC,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE;IAS7C,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI;IAkBpD,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAYxC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAK3C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAoB1C,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI;IAK3D,OAAO,CAAC,kBAAkB;CAO1B"}