@pie-players/pie-tool-magnifier 0.1.6 → 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
@@ -1,135 +1,112 @@
1
- # PIE Magnifier Tool
1
+ # @pie-players/pie-tool-magnifier
2
2
 
3
- A draggable magnification tool that allows students to zoom in on any content on the assessment page. This tool is an accessibility accommodation for students with visual impairments.
3
+ Magnifying lens tool for PIE assessment players.
4
4
 
5
- ## Features
6
-
7
- - **Multiple Zoom Levels**: 1.5x, 2x, and 3x magnification
8
- - **Draggable**: Can be moved anywhere on the screen using mouse or keyboard
9
- - **Content Cloning**: Creates a live clone of page content with accurate scroll positions
10
- - **Keyboard Accessible**: Full keyboard navigation support
11
- - **Zero DOM Mutation**: Does not modify the original content
12
-
13
- ## Architecture
14
-
15
- This tool follows PIE's custom element (Web Component) architecture:
16
-
17
- - Built with Svelte 5
18
- - Registered as a custom element `<pie-tool-magnifier>`
19
- - Integrates with PIE's ToolCoordinator for z-index management
20
- - Uses Moveable.js for drag functionality
21
-
22
- ## Comparison to Production Implementations
23
-
24
- ### Similarities
25
-
26
- - **Visual Design**: Same zoom levels (1.5x, 2x, 3x), button layout, and frame dimensions
27
- - **Core Functionality**: DOM cloning, scroll position preservation, mouse tracking
28
- - **UX Patterns**: Frozen view on mouse leave, continuous update on drag
29
-
30
- ### Differences
5
+ ## Overview
31
6
 
32
- - **Framework**: Svelte 5 (with runes) instead of Vue 3 (Composition API)
33
- - **Architecture**: Web Component (custom element) instead of Vue SFC
34
- - **Dependencies**: Uses Moveable.js directly instead of VueUse composables
35
- - **Coordination**: Integrates with PIE's ToolCoordinator for z-index management
36
- - **Styling**: Uses PIE CSS variables for consistency
37
- - **DOM Mutation**: Zero mutation approach (clones only, never modifies original)
7
+ A movable, resizable lens that shows the content under it enlarged. The lens is a
8
+ window with a bar on top: zoom out, the current zoom, zoom in, and close. Its
9
+ viewport shows a scaled copy of the page around the point beneath the lens, so
10
+ moving the lens moves what it magnifies. The shown point travels the lens's block
11
+ in step with the lens, so at the block's edges the view reaches the edge content
12
+ the lens stops short of.
38
13
 
39
- ### Key Architectural Improvements
14
+ The tool serves the AfA PNP 3.0 `magnification` support. Its tool id is that term,
15
+ `magnification`.
40
16
 
41
- 1. **Web Component Standard**: Framework-agnostic, can be used in any context
42
- 2. **Modern Svelte 5**: Uses runes (`$state`, `$derived`, `$effect`) for reactive state
43
- 3. **Cleaner Separation**: Tool coordination is handled by external coordinator, not internal store
44
- 4. **Accessibility First**: ARIA labels, keyboard navigation, screen reader announcements
17
+ ## Custom Element
45
18
 
46
- ## Usage
19
+ Tag: `pie-tool-magnifier`
47
20
 
48
- ### As a Custom Element
21
+ | Attribute | Type | Default | Description |
22
+ |---|---|---|---|
23
+ | `visible` | `boolean` | `false` | Controls visibility |
24
+ | `tool-id` | `string` | `'magnification'` | Identifier used by the ToolCoordinator |
25
+ | `zoom` | `number` | `2` | Starting magnification, 2 meaning twice the size. Clamped to 1.25–8; a value of 1 or less, or none, is the default |
49
26
 
50
- ```html
51
- <pie-tool-magnifier
52
- visible="true"
53
- tool-id="magnifier"
54
- magnify-root-selector="body"
55
- ></pie-tool-magnifier>
56
- ```
57
-
58
- ### With Coordinator
59
-
60
- ```typescript
61
- import { ToolMagnifier } from '@pie-api-aws/pieoneer-tool-magnifier';
62
- import { ToolCoordinator } from '$lib/assessment-toolkit';
63
-
64
- const coordinator = new ToolCoordinator();
27
+ ## Features
65
28
 
66
- // The tool will auto-register when visible=true
29
+ - Zoom steps of 1.5×, 2×, 2.5×, 3×, 4×, 5×, 6× and 8× from the bar's buttons or
30
+ the keyboard
31
+ - Drag the bar or the viewport to move the lens; drag the corner grip to resize it
32
+ around its centre
33
+ - Full keyboard support:
34
+ - On the lens: arrow keys to move, `+`/`-` to zoom
35
+ - On the resize grip: arrow keys change the width and height
36
+ - Anywhere on the page: `Escape` closes the lens, unless something else there
37
+ handles the key. Pressed on the lens it also returns focus to where it was
38
+ before the lens opened
39
+ - Keyboard focus on the page beneath the lens shows as a ring in the magnified view
40
+ - Tap controls beside the focused lens move it and change its width and height
41
+ without a drag (WCAG 2.5.7), and every control meets the 24×24 minimum target
42
+ size (WCAG 2.5.8). On a narrow pane they wrap onto a second row
43
+ - Screen reader announcements for zoom, size and position changes
44
+ - Stays inside its containing block, and opens over the part of it on screen
45
+ - Connects to `AssessmentToolkitRuntimeContext` for ToolCoordinator integration
46
+
47
+ ## Profile and policy
48
+
49
+ A personal needs profile grants the tool by listing `magnification` in `supports`.
50
+ The starting zoom is the `zoom` tool parameter, which the registration in
51
+ `@pie-players/pie-default-tool-loaders` reads through the toolbar and sets as the
52
+ `zoom` attribute. `createPersonalNeedsProfileFromAfa` maps an AfA record's
53
+ `magnification` `zoom-amount` to it, taking the `text` amount when the record sets
54
+ text and non-text apart:
55
+
56
+ ```ts
57
+ createPersonalNeedsProfileFromAfa({ magnification: { "all-content": { "zoom-amount": 2.5 } } });
58
+ // { supports: ["magnification"], toolParameters: { magnification: { zoom: 2.5 } } }
67
59
  ```
68
60
 
69
- ## Props
70
-
71
- - `visible` (Boolean): Show/hide the tool
72
- - `toolId` (String): Unique identifier for this tool instance (default: 'magnifier')
73
- - `coordinator` (Object): ToolCoordinator instance for z-index management
74
- - `magnifyRootSelector` (String): CSS selector for root element to magnify (default: 'body')
75
-
76
- ## Keyboard Navigation
77
-
78
- - **Arrow Keys**: Move the magnifier frame (10px steps)
79
- - **1 / 2 / 3**: Set zoom level to 1.5x / 2x / 3x
80
- - **+ / =**: Cycle to next zoom level
81
- - **-**: Cycle to previous zoom level
82
-
83
- ## Accessibility Features
84
-
85
- - Full keyboard navigation
86
- - ARIA labels and roles
87
- - Screen reader announcements for state changes
88
- - Focus visible indicators
89
- - High contrast focus rings
90
-
91
- ## Implementation Notes
92
-
93
- ### Content Cloning
94
-
95
- The tool creates a deep clone of the content specified by `magnifyRootSelector` and:
96
-
97
- 1. Preserves scroll positions of all scrollable elements
98
- 2. Removes elements with `.magnifier-clone-ignore` class or `[data-magnifier-ignore]` attribute
99
- 3. Applies scaling and positioning transforms
100
- 4. Updates on scroll events (debounced)
101
-
102
- ### Performance
103
-
104
- - Uses `requestAnimationFrame` for smooth updates
105
- - Debounces scroll event handlers (100ms)
106
- - Cleans up all listeners and RAF loops on unmount
107
- - Only updates during drag or mouse-inside states
108
-
109
- ### Z-Index Management
110
-
111
- The tool uses PIE's ZIndexLayer system:
112
-
113
- - Tool frame: `ZIndexLayer.MODAL` (2002)
114
- - Moveable controls: `ZIndexLayer.CONTROL` (2003)
115
-
116
- ### Preventing Self-Magnification
117
-
118
- The tool adds `.magnifier-clone-ignore` class and `[data-magnifier-ignore]` attribute to its own frame to prevent recursive magnification.
119
-
120
- ## Browser Compatibility
121
-
122
- - Chrome/Edge 90+
123
- - Firefox 90+
124
- - Safari 14+
125
-
126
- Requires:
127
- - Custom Elements (Web Components)
128
- - CSS Transform
129
- - RequestAnimationFrame
130
- - DOMMatrix
131
-
132
- ## Related Documentation
133
-
134
- - [PIE Tools Architecture](../../docs/tools-high-level-architecture.md)
135
- - [ToolCoordinator](../../tools/tool-coordinator.ts)
61
+ The learner changes the zoom from there; a new host value replaces theirs.
62
+
63
+ The packaged registration places the tool at section level by default and supports
64
+ section, passage, rubric and item placement. Placement puts it on a toolbar; a
65
+ profile's `prohibitedSupports`, a district block or a test-administration override
66
+ withdraws it. It is not universal: magnification is a granted accommodation, so
67
+ `createUniversalPersonalNeedsProfile()` leaves it out.
68
+
69
+ ## How the lens draws
70
+
71
+ CSS cannot paint one part of a document inside another, so the lens shows a copy.
72
+ The live document is serialized without scripts or event-handler attributes into a
73
+ sandboxed `srcdoc` iframe: open shadow roots become declarative shadow roots, every
74
+ style sheet is written out from its CSSOM, and form state, scroll offsets, canvas
75
+ pixels and video frames are copied across after the copy loads. The lens scales and
76
+ offsets the iframe with a transform, which follows its position, size, the zoom and
77
+ page scrolling every frame.
78
+
79
+ A mutation observer marks the copy stale, and it is re-rendered at most every
80
+ 200 ms, or every four times the main-thread time the last render took when that is
81
+ longer, so copying a large page keeps to about a quarter of the main thread. Two
82
+ iframes alternate, so the new copy paints in the hidden one and swaps in when it has
83
+ loaded. Every lens is left out of the copy.
84
+
85
+ Highlights painted through the CSS Custom Highlight API, text-to-speech word and
86
+ sentence highlighting and annotation-toolbar highlights among them, are mapped onto
87
+ the copy's nodes and registered in its frame under the same names, where the copy's
88
+ own `::highlight()` rules paint them. They follow the page every frame, without
89
+ waiting for a re-render.
90
+
91
+ The copy is inert: it takes no input and runs no script, so the lens is a viewing
92
+ aid and the learner answers on the page beneath it.
93
+
94
+ ## Limitations
95
+
96
+ - Closed shadow roots, cross-origin iframes and WebGL canvases without a preserved
97
+ drawing buffer appear empty.
98
+ - A highlight over markup the HTML parser restructures, such as a block element a
99
+ script placed inside a `<p>`, does not show.
100
+ - Top-layer content is not carried: a modal dialog shows as a non-modal one in
101
+ place, and an open popover does not show.
102
+ - A custom element that renders its content only from script, with no open shadow
103
+ root or light-DOM children, appears as it does before it upgrades.
104
+ - Changes to the page reach the lens a render or two late: well under a second on a
105
+ typical section, and up to about five seconds on a page of 40,000 elements, whose
106
+ copy takes over a second to render.
107
+
108
+ ## Theming
109
+
110
+ The lens reads canonical theme tokens and defines none of its own: `--pie-primary`
111
+ for the border, `--pie-background` and `--pie-text` for the lens, and
112
+ `--pie-secondary-background` and `--pie-border` for the bar.
@@ -0,0 +1,83 @@
1
+ {
2
+ "schemaVersion": "2.1.0",
3
+ "modules": [
4
+ {
5
+ "kind": "javascript-module",
6
+ "path": "dist/tool-magnifier.js",
7
+ "declarations": [
8
+ {
9
+ "kind": "class",
10
+ "description": "Magnifying lens: a movable, resizable window that shows the content under it enlarged, with controls on its bar to change the zoom and close. The host shows it with `visible` and sets the starting magnification with `zoom` (the AfA PNP `magnification` amount; 2 when absent). Inside a toolkit runtime context it registers `tool-id` with the tool coordinator on the tool layer, and the close control hides it there. Arrow keys move it, `+` and `-` change the zoom, and Escape closes it, wherever on the page it is pressed.",
11
+ "name": "ToolMagnifier",
12
+ "tagName": "pie-tool-magnifier",
13
+ "customElement": true,
14
+ "members": [
15
+ {
16
+ "kind": "field",
17
+ "name": "visible",
18
+ "type": {
19
+ "text": "boolean"
20
+ },
21
+ "default": "false",
22
+ "attribute": "visible"
23
+ },
24
+ {
25
+ "kind": "field",
26
+ "name": "toolId",
27
+ "type": {
28
+ "text": "string"
29
+ },
30
+ "default": "'magnification'",
31
+ "attribute": "tool-id"
32
+ },
33
+ {
34
+ "kind": "field",
35
+ "name": "zoom",
36
+ "type": {
37
+ "text": "number"
38
+ },
39
+ "attribute": "zoom"
40
+ }
41
+ ],
42
+ "attributes": [
43
+ {
44
+ "name": "visible",
45
+ "type": {
46
+ "text": "boolean"
47
+ },
48
+ "default": "false",
49
+ "fieldName": "visible"
50
+ },
51
+ {
52
+ "name": "tool-id",
53
+ "type": {
54
+ "text": "string"
55
+ },
56
+ "default": "'magnification'",
57
+ "fieldName": "toolId"
58
+ },
59
+ {
60
+ "name": "zoom",
61
+ "type": {
62
+ "text": "number"
63
+ },
64
+ "fieldName": "zoom"
65
+ }
66
+ ],
67
+ "x-pie": {
68
+ "shadow": "open"
69
+ }
70
+ }
71
+ ],
72
+ "exports": [
73
+ {
74
+ "kind": "custom-element-definition",
75
+ "name": "pie-tool-magnifier",
76
+ "declaration": {
77
+ "name": "ToolMagnifier"
78
+ }
79
+ }
80
+ ]
81
+ }
82
+ ]
83
+ }
package/dist/index.d.ts CHANGED
@@ -1,7 +1 @@
1
- /**
2
- * pie-tool-magnifier - PIE Assessment Tool
3
- *
4
- * This package exports a web component built from Svelte.
5
- * Import the built version for CDN usage, or the .svelte source for Svelte projects.
6
- */
7
- //# sourceMappingURL=index.d.ts.map
1
+ export {}