@pie-players/pie-section-player-tools-tts-settings 0.3.20

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 ADDED
@@ -0,0 +1,220 @@
1
+ # @pie-players/pie-section-player-tools-tts-settings
2
+
3
+ Reusable TTS settings development panel for section-player consumers.
4
+
5
+ This package follows the same integration model as the other `section-player-tools-*` panels:
6
+
7
+ - side-effect import to register a custom element
8
+ - render the element tag where your app manages debug overlays
9
+
10
+ ## Install and register
11
+
12
+ ```ts
13
+ import "@pie-players/pie-section-player-tools-tts-settings";
14
+ ```
15
+
16
+ ## Render
17
+
18
+ ```svelte
19
+ <pie-section-player-tools-tts-settings
20
+ toolkitCoordinator={toolkitCoordinator}
21
+ onclose={() => (showTtsPanel = false)}
22
+ />
23
+ ```
24
+
25
+ ## Default behavior
26
+
27
+ Without adapters, the panel uses the existing route contract:
28
+
29
+ - base endpoint: `/api/tts`
30
+ - voices routes:
31
+ - `GET {base}/polly/voices`
32
+ - `GET {base}/google/voices`
33
+ - synthesize route:
34
+ - `POST {base}/synthesize`
35
+
36
+ and applies settings via toolkit coordinator:
37
+
38
+ - `getToolConfig("tts")`
39
+ - `updateToolConfig("tts", ...)`
40
+ - optional `ensureTTSReady(...)`
41
+
42
+ ## Custom element API
43
+
44
+ ### Attributes / props
45
+
46
+ - `toolkitCoordinator` (`Object`): assessment toolkit coordinator instance
47
+ - `apiEndpoint` (`String`, default `/api/tts`): base endpoint for voice/synthesis routes
48
+ - `storageKey` (`String`, default `pie:section-player-tools:tts-settings`): localStorage key
49
+ - `adapters` (`Object`, optional): override fetching/synthesis behavior
50
+ - `customProviders` (`Array`, optional): register additional provider tabs (JS adapters and/or custom elements)
51
+
52
+ ### Events
53
+
54
+ - `close`: emitted when the panel requests to close
55
+
56
+ Example:
57
+
58
+ ```svelte
59
+ <pie-section-player-tools-tts-settings
60
+ toolkitCoordinator={toolkitCoordinator}
61
+ apiEndpoint="/internal/tts"
62
+ storageKey="my-app:dev-panels:tts"
63
+ onclose={handleClose}
64
+ />
65
+ ```
66
+
67
+ ## Adapter overrides
68
+
69
+ Use adapters when your host app cannot or should not expose the default route contract.
70
+
71
+ ## Custom provider tabs
72
+
73
+ You can add provider tabs beyond Browser/Polly/Google through `customProviders`.
74
+
75
+ - Keep provider `id` unique and avoid reserved ids: `browser`, `polly`, `google`.
76
+ - The panel still owns persistence and `updateToolConfig("tts", ...)`.
77
+ - Provider apply returns normalized output: `{ config, message? }`.
78
+
79
+ ### JS adapter mode
80
+
81
+ ```ts
82
+ const customProviders = [
83
+ {
84
+ id: "acme-tts",
85
+ label: "Acme TTS",
86
+ mode: "adapter",
87
+ initialState: { voice: "acme-default", quality: "high" },
88
+ async checkAvailability({ apiEndpoint }) {
89
+ const response = await fetch(`${apiEndpoint}/acme/health`);
90
+ return {
91
+ available: response.ok,
92
+ message: response.ok ? "Acme provider available." : "Acme provider unavailable."
93
+ };
94
+ },
95
+ async buildApplyConfig({ state, apiEndpoint }) {
96
+ return {
97
+ config: {
98
+ backend: "acme-tts",
99
+ transportMode: "custom",
100
+ apiEndpoint,
101
+ defaultVoice: state.voice,
102
+ providerOptions: { quality: state.quality }
103
+ },
104
+ message: "Applied Acme TTS settings."
105
+ };
106
+ }
107
+ }
108
+ ];
109
+ ```
110
+
111
+ ### Custom element mode (CE bridge)
112
+
113
+ `mode: "component"` providers can emit normalized events that the panel consumes:
114
+
115
+ - `change` with `detail: { state: Record<string, unknown> }`
116
+ - `availability` with `detail: { available: boolean, message?: string, detail?: string }`
117
+ - `apply-request` with `detail: { config: Record<string, unknown>, message?: string }`
118
+ - `preview-request` (panel triggers provider `preview` hook if supplied)
119
+
120
+ Example descriptor:
121
+
122
+ ```ts
123
+ const customProviders = [
124
+ {
125
+ id: "vendor-x",
126
+ label: "Vendor X",
127
+ mode: "component",
128
+ tagName: "my-vendor-tts-provider-tab",
129
+ componentProps: { tenant: "district-a" },
130
+ async buildApplyConfig({ state, apiEndpoint }) {
131
+ return {
132
+ config: {
133
+ backend: "vendor-x",
134
+ transportMode: "custom",
135
+ apiEndpoint,
136
+ providerOptions: state
137
+ }
138
+ };
139
+ }
140
+ }
141
+ ];
142
+ ```
143
+
144
+ ### Adapter shape
145
+
146
+ ```ts
147
+ type TtsSettingsAdapters = {
148
+ fetchPollyVoices?: (args: {
149
+ endpoint: string;
150
+ language: string;
151
+ gender: string;
152
+ engine: "standard" | "neural";
153
+ url: URL;
154
+ }) => Promise<Array<{ id?: string; name?: string; languageCode?: string; gender?: string }>>;
155
+ fetchGoogleVoices?: (args: {
156
+ endpoint: string;
157
+ language: string;
158
+ gender: string;
159
+ voiceType: string;
160
+ url: URL;
161
+ }) => Promise<Array<{ id?: string; name?: string; languageCode?: string; gender?: string }>>;
162
+ synthesizeProbe?: (args: {
163
+ endpoint: string;
164
+ provider: "polly" | "google";
165
+ body: Record<string, unknown>;
166
+ }) => Promise<{
167
+ audio: string;
168
+ contentType?: string;
169
+ speechMarks?: Array<{ time: number; start: number; end: number }>;
170
+ }>;
171
+ };
172
+ ```
173
+
174
+ ### Example with custom adapters
175
+
176
+ ```svelte
177
+ <script lang="ts">
178
+ import "@pie-players/pie-section-player-tools-tts-settings";
179
+
180
+ const adapters = {
181
+ async fetchPollyVoices({ endpoint, language, gender, engine }) {
182
+ const response = await fetch(`${endpoint}/providers/polly/voices`, {
183
+ method: "POST",
184
+ headers: { "Content-Type": "application/json" },
185
+ body: JSON.stringify({ language, gender, engine })
186
+ });
187
+ const payload = await response.json();
188
+ return Array.isArray(payload?.voices) ? payload.voices : [];
189
+ },
190
+ async fetchGoogleVoices({ endpoint, language, gender, voiceType }) {
191
+ const response = await fetch(`${endpoint}/providers/google/voices`, {
192
+ method: "POST",
193
+ headers: { "Content-Type": "application/json" },
194
+ body: JSON.stringify({ language, gender, voiceType })
195
+ });
196
+ const payload = await response.json();
197
+ return Array.isArray(payload?.voices) ? payload.voices : [];
198
+ },
199
+ async synthesizeProbe({ endpoint, provider, body }) {
200
+ const response = await fetch(`${endpoint}/providers/${provider}/preview`, {
201
+ method: "POST",
202
+ headers: { "Content-Type": "application/json" },
203
+ body: JSON.stringify(body)
204
+ });
205
+ if (!response.ok) {
206
+ const payload = await response.json().catch(() => ({}));
207
+ throw new Error(payload?.message || `Preview failed (${response.status})`);
208
+ }
209
+ return response.json();
210
+ }
211
+ };
212
+ </script>
213
+
214
+ <pie-section-player-tools-tts-settings
215
+ toolkitCoordinator={toolkitCoordinator}
216
+ apiEndpoint="/tts-gateway"
217
+ {adapters}
218
+ onclose={() => (showTtsPanel = false)}
219
+ />
220
+ ```