@pie-players/pie-tool-tts-inline 0.3.75 → 1.0.0-beta.1

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
@@ -15,7 +15,7 @@ focuses on the inline custom element API.
15
15
  - Play/pause trigger that opens the expanded panel when reading starts
16
16
  - Expanded controls: configurable Speed options, Rewind, Fast-forward, Stop
17
17
  - Play button switches to Pause while reading
18
- - Panel remains open while reading and closes on Stop
18
+ - Panel stays open while reading and after a read ends on its own; it closes on Stop or when the host calls `TTSService.stop()`
19
19
  - Arrow-key navigation within the controls toolbar
20
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
@@ -37,9 +37,10 @@ the highlight coordinator and the toolkit coordinator, and the shell supplies th
37
37
  content to read. Section players provide both; around a plain item player, the
38
38
  host writes the toolkit and the scope. The packaged
39
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.
40
+ this element in item and passage toolbars, takes `catalog-id` and `size` from
41
+ the toolbar, takes `layout-mode`, `speedOptions` and `showSingleSpeedOption` from
42
+ the toolkit's `textToSpeech` tool configuration, and takes `base-rate`, `pitch`
43
+ and `volume` from the policy's `textToSpeech` tool parameters.
43
44
 
44
45
  ```javascript
45
46
  import '@pie-players/pie-tool-tts-inline';
@@ -74,15 +75,23 @@ passageHeader.append(ttsButton);
74
75
  ### HTML Attributes
75
76
 
76
77
  - `catalog-id` - QTI 3.0 accessibility catalog ID for SSML lookup (default: `''`)
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.
80
78
  - `size` - Icon size: `'sm'` (1.5rem), `'md'` (2rem), or `'lg'` (2.5rem) (default: `'md'`)
81
79
  - `layout-mode` - Panel placement (default: `'left-aligned'`). `'reserved-row'`
82
80
  and `'expanding-row'` drop the panel below the trigger; in the packaged toolbar
83
81
  the first keeps the controls row reserved and the second expands it while the
84
82
  panel is open. `'floating-overlay'` and `'left-aligned'` open the panel as an
85
83
  overlay to the left of the trigger.
84
+ - `base-rate` - Multiplies every speed option, so a learner's normal speed
85
+ can differ from the provider's (default: `1`). A value that is not a
86
+ positive number means `1`.
87
+ - `pitch` - The pitch this element's reads start at, `0`–`2` with `1` normal,
88
+ clamped to that range (default: the service's).
89
+ - `volume` - The volume this element's reads start at, `0`–`1`, clamped
90
+ (default: the service's).
91
+
92
+ Pitch and volume stay the service's after a read, so a read started
93
+ elsewhere, such as the annotation toolbar's read-selection, uses the last
94
+ values set.
86
95
 
87
96
  ### JavaScript Properties
88
97
 
@@ -135,21 +144,20 @@ Semantics:
135
144
 
136
145
  ## Behavior
137
146
 
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()`
147
+ 1. **Services**: Reads `ttsService`, `highlightCoordinator` and `toolkitCoordinator` from the toolkit runtime context; the controls stay disabled until a `ttsService` arrives. A read started before the service is ready waits on the service's readiness gate, and a failure there announces that text-to-speech could not initialize
139
148
  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
149
+ 3. **TTS Trigger**: Calls `ttsService.speak(readingTarget, { ownerId, rate, catalogId, catalogContext, language })`, where `ownerId` names this instance, `rate` is the selected speed, `catalogContext` names the owning item or passage and `language` is the toolkit's `content-language`. The service decides whether anything is speakable, cards included; a read that settles without playing closes the panel and announces that there is nothing to read. `speak` resolves the read's language from it as [TTS language](../../docs/architecture/internationalization.md#tts-language) sets out
141
150
  4. **Catalog Resolution**: TTSService checks for SSML in accessibility catalogs (priority order):
142
151
  - **Extracted catalogs** (from embedded SSML) - generated before render by hosts that run `SSMLExtractor`
143
152
  - **Item-level catalogs** (manually authored)
144
153
  - **Assessment-level catalogs** (manually authored)
145
- - **Plain text fallback** (browser TTS)
154
+ - **Generated speech** - MathML speech, else the visible text, on any backend
146
155
  5. **Expanded Controls**:
147
156
  - 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
157
+ - The instance owns the service's run its read started (`getRunOwner()`); a read started by anything else, another instance or a selection read, closes its panel
149
158
  - Stop halts playback and closes the panel
150
159
  - Fast-forward/Rewind call `seekForward(1)` / `seekBackward(1)` on the TTS service, one sentence per press, and are enabled only while reading
151
- - Speed buttons call `ttsService.setPlaybackRate(rate)` when available,
152
- otherwise `ttsService.updateSettings({ rate })`
160
+ - Speed buttons call `ttsService.setPlaybackRate(rate)`
153
161
  - Speed choices render as a named `Playback speed` radio group with
154
162
  `aria-checked` state
155
163
  - Selecting another speed switches the active radio to that option
@@ -158,7 +166,7 @@ Semantics:
158
166
  reset to `1x` while rewind/forward/stop still render
159
167
  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
168
  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
169
+ 8. **Cleanup**: Clears its highlight target resolver provider on unmount
162
170
 
163
171
  ## SSML Extraction Integration
164
172
 
@@ -208,6 +216,8 @@ component-scoped variables instead of overriding broad semantic tokens such as
208
216
  --pie-tool-trigger-active-border-color: Active/open trigger border
209
217
  ```
210
218
 
219
+ These three are registered `component-public` tokens.
220
+
211
221
  If unset, the trigger looks the same open as closed: each hook falls back to the
212
222
  value the control already resolves to — background through
213
223
  `--pie-button-background-color` / `--pie-button-bg` / `--pie-background`, border
@@ -222,9 +232,9 @@ indication — so these defaults do not introduce one. Hosts remain responsible
222
232
  maintaining WCAG AA foreground/background contrast when overriding active trigger
223
233
  colors.
224
234
 
225
- ### Overlay panel colours
235
+ ### Overlay panel colors
226
236
 
227
- The floating and left-aligned panels take their colour from the active theme.
237
+ The floating and left-aligned panels take their color from the active theme.
228
238
  Each surface resolves a component-scoped hook first, then a canonical token,
229
239
  then a literal that only applies when no theme is loaded:
230
240
 
@@ -235,7 +245,7 @@ then a literal that only applies when no theme is loaded:
235
245
  --pie-selected-button-background /* selected speed chip → --pie-button-active-bg */
236
246
  --pie-selected-button-border /* selected speed chip border → --pie-button-border */
237
247
  --pie-tts-menu-shadow /* card elevation */
238
- --pie-tts-card-border /* card hairline; `transparent` for shadow-only */
248
+ --pie-tts-card-border /* card hairline */
239
249
  ```
240
250
 
241
251
  None of the seven is a registered host token. Each is read as
@@ -245,20 +255,16 @@ carries no compatibility guarantee — the panel's internals may move it.
245
255
  The card carries a hairline mixed from `--pie-text` because its shadow is black
246
256
  and disappears once the surface goes dark. It is deliberately not derived from
247
257
  `--pie-border`: a host that wants borderless controls sets that to transparent,
248
- which is the case where the shadow is the only edge. Set
249
- `--pie-tts-card-border: transparent` for the shadow-only card.
258
+ which is the case where the shadow is the only edge.
250
259
 
251
260
  A host that sets `--pie-button-border: transparent` also flattens the selected
252
- speed chip, which defaults through it — set `--pie-selected-button-border` to
253
- keep the chip outlined.
261
+ speed chip, which defaults through it.
254
262
 
255
263
  Foregrounds default through `--pie-button-color` (DaisyUI `base-content`) rather
256
264
  than `--pie-primary` or `--pie-tertiary`: those are direct mappings of DaisyUI
257
- slots chosen to pair with their own `-content` colour, so an accent glyph taken
265
+ slots chosen to pair with their own `-content` color, so an accent glyph taken
258
266
  from either falls under 3:1 against the card in 11 of the 35 shipped themes.
259
- Selection reads from the chip fill and the bolder weight instead of from hue. A
260
- host that wants a branded accent sets `--pie-tts-button-color` and owns the
261
- contrast, as with the active-trigger hooks above.
267
+ Selection reads from the chip fill and the bolder weight instead of from hue.
262
268
 
263
269
  Trigger and control backgrounds read `--pie-button-background-color` ahead of
264
270
  the canonical `--pie-button-bg`; borders and hover backgrounds read
@@ -276,10 +282,6 @@ This tool follows the PIE Assessment Toolkit tool pattern:
276
282
  - Panel state is announced with `pie-tool-active-change`, which the packaged
277
283
  toolbar registration subscribes to
278
284
 
279
- ## Example
280
-
281
- See active demos in `apps/section-demos`.
282
-
283
285
  ## License
284
286
 
285
287
  MIT
@@ -0,0 +1,197 @@
1
+ {
2
+ "schemaVersion": "2.1.0",
3
+ "modules": [
4
+ {
5
+ "kind": "javascript-module",
6
+ "path": "dist/tool-tts-inline.js",
7
+ "declarations": [
8
+ {
9
+ "kind": "class",
10
+ "description": "Read-aloud trigger for an item or passage header inside `<pie-item-scope>` or `<pie-passage-shell>`: play/pause opens a panel of speed, rewind, fast-forward and stop controls. It reads the shell's content region through the TTS service in the toolkit runtime context, passing `catalog-id` so the service can speak authored SSML from the accessibility catalogs. Its controls stay disabled until the runtime context supplies a TTS service.",
11
+ "name": "ToolTtsInline",
12
+ "tagName": "pie-tool-tts-inline",
13
+ "customElement": true,
14
+ "members": [
15
+ {
16
+ "kind": "field",
17
+ "name": "catalogId",
18
+ "type": {
19
+ "text": "string"
20
+ },
21
+ "default": "''",
22
+ "attribute": "catalog-id"
23
+ },
24
+ {
25
+ "kind": "field",
26
+ "name": "size",
27
+ "type": {
28
+ "text": "'sm' | 'md' | 'lg'"
29
+ },
30
+ "default": "'md'",
31
+ "attribute": "size"
32
+ },
33
+ {
34
+ "kind": "field",
35
+ "name": "speedOptions",
36
+ "type": {
37
+ "text": "TTSSpeedOption[]"
38
+ },
39
+ "attribute": "speed-options"
40
+ },
41
+ {
42
+ "kind": "field",
43
+ "name": "showSingleSpeedOption",
44
+ "type": {
45
+ "text": "boolean"
46
+ },
47
+ "default": "false",
48
+ "attribute": "show-single-speed-option"
49
+ },
50
+ {
51
+ "kind": "field",
52
+ "name": "layoutMode",
53
+ "type": {
54
+ "text": "TTSLayoutMode"
55
+ },
56
+ "default": "'left-aligned'",
57
+ "attribute": "layout-mode"
58
+ },
59
+ {
60
+ "kind": "field",
61
+ "name": "baseRate",
62
+ "type": {
63
+ "text": "number"
64
+ },
65
+ "default": "1",
66
+ "description": "Multiplies every speed choice's rate, so 1× reads at this rate.",
67
+ "attribute": "base-rate"
68
+ },
69
+ {
70
+ "kind": "field",
71
+ "name": "pitch",
72
+ "type": {
73
+ "text": "number"
74
+ },
75
+ "description": "The pitch each read starts at, 0–2 with 1 normal.",
76
+ "attribute": "pitch"
77
+ },
78
+ {
79
+ "kind": "field",
80
+ "name": "volume",
81
+ "type": {
82
+ "text": "number"
83
+ },
84
+ "description": "The volume each read starts at, 0–1.",
85
+ "attribute": "volume"
86
+ }
87
+ ],
88
+ "attributes": [
89
+ {
90
+ "name": "catalog-id",
91
+ "type": {
92
+ "text": "string"
93
+ },
94
+ "default": "''",
95
+ "fieldName": "catalogId"
96
+ },
97
+ {
98
+ "name": "size",
99
+ "type": {
100
+ "text": "string"
101
+ },
102
+ "default": "'md'",
103
+ "fieldName": "size"
104
+ },
105
+ {
106
+ "name": "speed-options",
107
+ "type": {
108
+ "text": "TTSSpeedOption[]"
109
+ },
110
+ "fieldName": "speedOptions"
111
+ },
112
+ {
113
+ "name": "show-single-speed-option",
114
+ "type": {
115
+ "text": "boolean"
116
+ },
117
+ "default": "false",
118
+ "fieldName": "showSingleSpeedOption"
119
+ },
120
+ {
121
+ "name": "layout-mode",
122
+ "type": {
123
+ "text": "string"
124
+ },
125
+ "default": "'left-aligned'",
126
+ "fieldName": "layoutMode"
127
+ },
128
+ {
129
+ "name": "base-rate",
130
+ "type": {
131
+ "text": "number"
132
+ },
133
+ "default": "1",
134
+ "description": "Multiplies every speed choice's rate, so 1× reads at this rate.",
135
+ "fieldName": "baseRate"
136
+ },
137
+ {
138
+ "name": "pitch",
139
+ "type": {
140
+ "text": "number"
141
+ },
142
+ "description": "The pitch each read starts at, 0–2 with 1 normal.",
143
+ "fieldName": "pitch"
144
+ },
145
+ {
146
+ "name": "volume",
147
+ "type": {
148
+ "text": "number"
149
+ },
150
+ "description": "The volume each read starts at, 0–1.",
151
+ "fieldName": "volume"
152
+ }
153
+ ],
154
+ "events": [
155
+ {
156
+ "name": "pie-tool-active-change",
157
+ "type": {
158
+ "text": "CustomEvent<{ active: boolean }>"
159
+ },
160
+ "description": "When its panel opens or closes."
161
+ }
162
+ ],
163
+ "cssProperties": [
164
+ {
165
+ "name": "--pie-button-background-color",
166
+ "description": "Compatibility alias retained for TTS inline button backgrounds; implementations must fall back through canonical --pie-button-bg before broad surface tokens."
167
+ },
168
+ {
169
+ "name": "--pie-tool-trigger-active-background",
170
+ "description": "Component trigger active/open background hook; falls back through existing semantic tokens and must preserve WCAG contrast when overridden by hosts."
171
+ },
172
+ {
173
+ "name": "--pie-tool-trigger-active-border-color",
174
+ "description": "Component trigger active/open border hook; falls back through existing semantic tokens."
175
+ },
176
+ {
177
+ "name": "--pie-tool-trigger-active-color",
178
+ "description": "Component trigger active/open foreground hook; hosts are responsible for preserving contrast with the active trigger background."
179
+ }
180
+ ],
181
+ "x-pie": {
182
+ "shadow": "open"
183
+ }
184
+ }
185
+ ],
186
+ "exports": [
187
+ {
188
+ "kind": "custom-element-definition",
189
+ "name": "pie-tool-tts-inline",
190
+ "declaration": {
191
+ "name": "ToolTtsInline"
192
+ }
193
+ }
194
+ ]
195
+ }
196
+ ]
197
+ }