@pie-players/pie-tool-tts-inline 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 CHANGED
@@ -8,20 +8,20 @@ focuses on the inline custom element API.
8
8
 
9
9
  ## Overview
10
10
 
11
- `pie-tool-tts-inline` is a web component that renders an inline speaker trigger with an expanded floating control panel for reading controls. Unlike floating modal tools, this component renders at its natural position in the DOM (typically in passage/item headers).
11
+ `pie-tool-tts-inline` is a web component that renders an inline play/pause trigger with an expanded floating control panel for reading controls. Unlike floating modal tools, this component renders at its natural position in the DOM (typically in passage/item headers).
12
12
 
13
13
  ## Features
14
14
 
15
- - Speaker trigger that toggles an expanded panel
16
- - Expanded controls: Play/Pause, Stop, Fast-forward, Rewind, configurable Speed options
15
+ - Play/pause trigger that opens the expanded panel when reading starts
16
+ - Expanded controls: configurable Speed options, Rewind, Fast-forward, Stop
17
17
  - Play button switches to Pause while reading
18
18
  - Panel remains open while reading and closes on Stop
19
19
  - Arrow-key navigation within the controls toolbar
20
- - Registers with `ToolCoordinator` for lifecycle management
20
+ - Takes its services from the toolkit runtime context and its reading scope from the enclosing item or passage shell
21
21
  - Integrates with `TTSService` for QTI 3.0 catalog-based TTS
22
22
  - Size variants: `sm`, `md`, `lg`
23
23
  - Full accessibility support (ARIA labels, `role="toolbar"`, live status updates)
24
- - Coordinator-controlled visibility via CSS `display` property
24
+ - Four panel layouts through `layout-mode`
25
25
 
26
26
  ## Installation
27
27
 
@@ -31,27 +31,25 @@ bun add @pie-players/pie-tool-tts-inline
31
31
 
32
32
  ## Usage
33
33
 
34
+ The element renders inside `<pie-item-scope>` or `<pie-passage-shell>` under
35
+ `<pie-assessment-toolkit>`. The toolkit runtime context supplies the TTS service,
36
+ the highlight coordinator and the toolkit coordinator, and the shell supplies the
37
+ content to read. Section players provide both; around a plain item player, the
38
+ host writes the toolkit and the scope. The packaged
39
+ `textToSpeech` capability in `@pie-players/pie-default-tool-loaders` creates
40
+ this element in item and passage toolbars, takes `catalog-id`, `language` and
41
+ `size` from the toolbar, and takes `layout-mode`, `speedOptions` and
42
+ `showSingleSpeedOption` from the toolkit's `textToSpeech` tool configuration.
43
+
34
44
  ```javascript
35
45
  import '@pie-players/pie-tool-tts-inline';
36
- import { TTSService, BrowserTTSProvider, ToolCoordinator } from '@pie-players/pie-assessment-toolkit';
37
-
38
- // Initialize services
39
- const ttsService = new TTSService();
40
- await ttsService.initialize(new BrowserTTSProvider());
41
- const toolCoordinator = new ToolCoordinator();
42
46
 
43
- // Create element
47
+ // passageHeader: an element inside <pie-passage-shell>
44
48
  const ttsButton = document.createElement('pie-tool-tts-inline');
45
- ttsButton.setAttribute('tool-id', 'tts-passage-1');
46
49
  ttsButton.setAttribute('catalog-id', 'passage-1');
47
50
  ttsButton.setAttribute('size', 'md');
48
-
49
- // Bind services as JavaScript properties (not HTML attributes)
50
- ttsButton.ttsService = ttsService;
51
- ttsButton.coordinator = toolCoordinator;
52
-
53
- // Coordinator controls visibility
54
- toolCoordinator.showTool('tts-passage-1');
51
+ ttsButton.setAttribute('layout-mode', 'expanding-row');
52
+ passageHeader.append(ttsButton);
55
53
  ```
56
54
 
57
55
  ### With Svelte
@@ -59,29 +57,14 @@ toolCoordinator.showTool('tts-passage-1');
59
57
  ```svelte
60
58
  <script>
61
59
  import '@pie-players/pie-tool-tts-inline';
62
- import { ZIndexLayer } from '@pie-players/pie-assessment-toolkit';
63
-
64
- let ttsToolElement;
65
-
66
- $effect(() => {
67
- if (ttsToolElement && toolCoordinator) {
68
- ttsToolElement.ttsService = ttsService;
69
- ttsToolElement.coordinator = toolCoordinator;
70
-
71
- if (ttsService) {
72
- toolCoordinator.showTool('tts-passage-1');
73
- }
74
- }
75
- });
76
60
  </script>
77
61
 
78
62
  <div class="header">
79
63
  <h3>Passage Title</h3>
80
64
  <pie-tool-tts-inline
81
- bind:this={ttsToolElement}
82
- tool-id="tts-passage-1"
83
65
  catalog-id="passage-1"
84
66
  size="md"
67
+ layout-mode="expanding-row"
85
68
  ></pie-tool-tts-inline>
86
69
  </div>
87
70
  ```
@@ -90,18 +73,25 @@ toolCoordinator.showTool('tts-passage-1');
90
73
 
91
74
  ### HTML Attributes
92
75
 
93
- - `tool-id` - Unique identifier for tool registration (default: `'tts-inline'`)
94
76
  - `catalog-id` - QTI 3.0 accessibility catalog ID for SSML lookup (default: `''`)
95
- - `language` - Language code for TTS (default: `'en-US'`)
77
+ - `language` - The content language when the markup names none (default: `''`,
78
+ which falls back to the toolkit's `content-language`). A `lang` attribute
79
+ between the reading target and its shell wins over it.
96
80
  - `size` - Icon size: `'sm'` (1.5rem), `'md'` (2rem), or `'lg'` (2.5rem) (default: `'md'`)
81
+ - `layout-mode` - Panel placement (default: `'left-aligned'`). `'reserved-row'`
82
+ and `'expanding-row'` drop the panel below the trigger; in the packaged toolbar
83
+ the first keeps the controls row reserved and the second expands it while the
84
+ panel is open. `'floating-overlay'` and `'left-aligned'` open the panel as an
85
+ overlay to the left of the trigger.
97
86
 
98
87
  ### JavaScript Properties
99
88
 
100
- - `ttsService` - ITTSService instance (required)
101
- - `coordinator` - IToolCoordinator instance (optional, for visibility management)
102
89
  - `speedOptions` - Optional speed options controlling inline speed button rendering
103
90
  - `showSingleSpeedOption` - Optional boolean to show a one-option speed group (hidden by default)
104
91
 
92
+ Both also read attributes: `speed-options` takes a JSON array, and
93
+ `show-single-speed-option` is true when present.
94
+
105
95
  ### `speedOptions` Configuration
106
96
 
107
97
  `speedOptions` is intended to be set as a JavaScript property (not as a
@@ -145,19 +135,19 @@ Semantics:
145
135
 
146
136
  ## Behavior
147
137
 
148
- 1. **Tool Registration**: Registers with ToolCoordinator on mount using the provided `tool-id`
149
- 2. **Text Extraction**: Finds nearest `.pie-section-player__passage-content` or `.pie-section-player__item-content` container
150
- 3. **TTS Trigger**: Calls `ttsService.speak(text, { catalogId, language })`
138
+ 1. **Services**: Reads `ttsService`, `highlightCoordinator` and `toolkitCoordinator` from the toolkit runtime context; the controls stay disabled until a `ttsService` arrives, and starting playback awaits `toolkitCoordinator.ensureTTSReady()`
139
+ 2. **Text Extraction**: Reads the text of the scope element's content region (the region scope, else the shell scope, when it is `[data-region='content']`, else its first `[data-region='content']` descendant, else the scope element itself), including text rendered into open shadow roots
140
+ 3. **TTS Trigger**: Calls `ttsService.speak(readingTarget, { catalogId, catalogContext, language })`, where `catalogContext` names the owning item or passage and `language` is the `language` attribute, else the toolkit's `content-language`. `speak` resolves the read's language from it as [TTS language](../../docs/architecture/internationalization.md#tts-language) sets out
151
141
  4. **Catalog Resolution**: TTSService checks for SSML in accessibility catalogs (priority order):
152
142
  - **Extracted catalogs** (from embedded SSML) - generated before render by hosts that run `SSMLExtractor`
153
143
  - **Item-level catalogs** (manually authored)
154
144
  - **Assessment-level catalogs** (manually authored)
155
145
  - **Plain text fallback** (browser TTS)
156
146
  5. **Expanded Controls**:
157
- - Trigger button opens/closes the panel
158
- - Play/Pause toggles based on playback state
147
+ - The trigger starts, pauses and resumes reading; starting opens the panel
148
+ - Starting one instance stops playback another instance owns and closes that instance's panel
159
149
  - Stop halts playback and closes the panel
160
- - Fast-forward/Rewind invoke sentence-jump seek on `ITTSService`
150
+ - Fast-forward/Rewind call `seekForward(1)` / `seekBackward(1)` on the TTS service, one sentence per press, and are enabled only while reading
161
151
  - Speed buttons call `ttsService.setPlaybackRate(rate)` when available,
162
152
  otherwise `ttsService.updateSettings({ rate })`
163
153
  - Speed choices render as a named `Playback speed` radio group with
@@ -166,8 +156,9 @@ Semantics:
166
156
  - Clicking the currently active speed leaves the selection unchanged
167
157
  - If `speedOptions` is `[]`, speed controls are omitted and playback rate is
168
158
  reset to `1x` while rewind/forward/stop still render
169
- 6. **Keyboard Interaction**: Arrow keys move between controls; Tab enters/leaves the toolbar
170
- 7. **Cleanup**: Unregisters from coordinator on unmount
159
+ 6. **Keyboard Interaction**: Arrow keys, Home and End move focus within one cluster, either the speed radio group or the Rewind/Fast-forward/Stop buttons, and skip disabled controls; arrowing onto a speed also selects it. Every control is a Tab stop except the speed radios, which share one Tab stop on the checked option
160
+ 7. **Active State**: Opening or closing the panel dispatches a bubbling, composed `pie-tool-active-change` event with `{ active }` and mirrors the state in the host's `data-active` attribute
161
+ 8. **Cleanup**: Releases playback ownership and clears its highlight target resolver provider on unmount
171
162
 
172
163
  ## SSML Extraction Integration
173
164
 
@@ -192,7 +183,7 @@ when a host/import pipeline runs `SSMLExtractor` before render:
192
183
  **Tool uses extracted catalog:**
193
184
 
194
185
  - User clicks TTS button in header
195
- - Tool calls `ttsService.speak(text, { catalogId: 'auto-prompt-q1-0' })`
186
+ - Tool calls `ttsService.speak(readingTarget, { catalogId: 'auto-prompt-q1-0' })`
196
187
  - TTSService finds SSML in extracted catalogs
197
188
  - Speaks with proper math pronunciation and pacing
198
189
 
@@ -202,8 +193,8 @@ when a host/import pipeline runs `SSMLExtractor` before render:
202
193
 
203
194
  The component uses scoped styles and doesn't require external CSS. Styling uses `--pie-*` token variables:
204
195
 
205
- - **Trigger**: Circular speaker button that indicates panel open state
206
- - **Panel**: Floating card with vertically stacked controls
196
+ - **Trigger**: Circular play/pause button that indicates panel open state
197
+ - **Panel**: Floating card with the controls in a row; in the compact `left-aligned` overlay the speed options stack below them
207
198
  - **Speed state**: Active speed button receives distinct token-driven styling
208
199
  - **Disabled**: Reduced opacity, no pointer
209
200
 
@@ -220,7 +211,7 @@ component-scoped variables instead of overriding broad semantic tokens such as
220
211
  If unset, the trigger looks the same open as closed: each hook falls back to the
221
212
  value the control already resolves to — background through
222
213
  `--pie-button-background-color` / `--pie-button-bg` / `--pie-background`, border
223
- through `--pie-button-border-color` / `--pie-button-border` / `--pie-border`, and
214
+ through `--pie-button-border` / `--pie-border`, and
224
215
  foreground through `--pie-button-color` / `--pie-text`. Setting a hook is how a
225
216
  host opts into a distinct active/open appearance.
226
217
 
@@ -233,10 +224,9 @@ colors.
233
224
 
234
225
  ### Overlay panel colours
235
226
 
236
- The floating and left-aligned panels take their shape from the Knowledge-Check
237
- design and their colour from the active theme. Each surface resolves a
238
- component-scoped hook first, then a canonical token, then a literal that only
239
- applies when no theme is loaded:
227
+ The floating and left-aligned panels take their colour from the active theme.
228
+ Each surface resolves a component-scoped hook first, then a canonical token,
229
+ then a literal that only applies when no theme is loaded:
240
230
 
241
231
  ```css
242
232
  --pie-tts-button-color /* media glyphs, selected speed → --pie-button-color */
@@ -270,21 +260,21 @@ Selection reads from the chip fill and the bolder weight instead of from hue. A
270
260
  host that wants a branded accent sets `--pie-tts-button-color` and owns the
271
261
  contrast, as with the active-trigger hooks above.
272
262
 
273
- Ordinary trigger and control button styling also preserves these legacy aliases:
274
- `--pie-button-background-color`, `--pie-button-border-color`, and
275
- `--pie-button-hover-background-color`. They remain supported for host
276
- compatibility, but fall back through the canonical `--pie-button-bg`,
277
- `--pie-button-border`, and `--pie-button-hover-bg` tokens before broad surface
278
- tokens.
263
+ Trigger and control backgrounds read `--pie-button-background-color` ahead of
264
+ the canonical `--pie-button-bg`; borders and hover backgrounds read
265
+ `--pie-button-border` and `--pie-button-hover-bg`. Each falls back to the broad
266
+ surface tokens.
279
267
 
280
268
  ## Architecture
281
269
 
282
270
  This tool follows the PIE Assessment Toolkit tool pattern:
283
271
 
284
272
  - Always rendered in DOM at natural position
285
- - ToolCoordinator controls visibility via `showTool()`/`hideTool()` (CSS `display` property)
286
- - Registers with `ZIndexLayer.TOOL` for proper layering
287
- - Services passed as JavaScript properties (objects can't be HTML attributes)
273
+ - Services arrive through `connectToolRuntimeContext`, and the reading scope
274
+ through `connectToolShellContext` and `connectToolRegionScopeContext`
275
+ - One instance owns playback at a time across the page
276
+ - Panel state is announced with `pie-tool-active-change`, which the packaged
277
+ toolbar registration subscribes to
288
278
 
289
279
  ## Example
290
280
 
package/dist/index.d.ts CHANGED
@@ -1 +1,8 @@
1
- export { default } from './tool-tts-inline.svelte';
1
+ /**
2
+ * pie-tool-tts-inline
3
+ *
4
+ * Importing this package registers `<pie-tool-tts-inline>`. The build entry is
5
+ * the component, so this file is the type entry alone and declares nothing: a
6
+ * runtime export here would not exist in the built bundle.
7
+ */
8
+ export type {};