@ssml-builder-js/ssml-editor-react 2.12.0 → 2.13.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.
- package/CHANGELOG.md +11 -0
- package/dist/index.d.mts +61 -11
- package/dist/index.d.ts +61 -11
- package/dist/index.js +363 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +362 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/SsmlEditor.tsx +31 -1
- package/src/components/VisualSsmlEditor.tsx +202 -24
- package/src/index.tsx +9 -2
- package/src/locales.ts +226 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssml-builder-js/ssml-editor-react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "React-based SSML editor component",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,6 +52,6 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@ssml-builder-js/ssml-core": "^2.
|
|
55
|
+
"@ssml-builder-js/ssml-core": "^2.13.0"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/src/SsmlEditor.tsx
CHANGED
|
@@ -40,7 +40,12 @@ import { InsertionPopover } from "./components/popovers/InsertionPopover";
|
|
|
40
40
|
import { useSsmlEditorState } from "./hooks/useSsmlEditorState";
|
|
41
41
|
import { useSsmlMonaco } from "./hooks/useSsmlMonaco";
|
|
42
42
|
import { editorStyles as styles } from "./styles/editorStyles";
|
|
43
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
VisualSsmlEditor,
|
|
45
|
+
type VisualInspectorRenderer,
|
|
46
|
+
type VisualVoiceCatalogEntry,
|
|
47
|
+
type VoiceSelectorRenderProps,
|
|
48
|
+
} from "./components/VisualSsmlEditor";
|
|
44
49
|
const UNGROUPED_TOOLBAR_GROUP = "__ssml-editor-ungrouped__";
|
|
45
50
|
const TIMING_POPOVER_TAGS = new Set(["break", "mstts:silence", "mstts:audioduration"]);
|
|
46
51
|
const PROSODY_POPOVER_TAGS = new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
|
|
@@ -764,6 +769,18 @@ export interface SsmlEditorProps {
|
|
|
764
769
|
customInsertions?: SsmlEditorCustomInsertionCollection;
|
|
765
770
|
/** Adds insertion definitions without replacing built-in definitions. */
|
|
766
771
|
additionalInsertions?: SsmlEditorCustomInsertionCollection;
|
|
772
|
+
/** Replaces the visual inspector for an element type or serialized tag name. */
|
|
773
|
+
customInspectors?: Readonly<Record<string, VisualInspectorRenderer>>;
|
|
774
|
+
/** Replaces the built-in voice catalog selector in visual mode. */
|
|
775
|
+
renderVoiceSelector?: (props: VoiceSelectorRenderProps) => ReactNode;
|
|
776
|
+
/** Voice metadata used by the visual selector. */
|
|
777
|
+
voiceCatalog?: readonly VisualVoiceCatalogEntry[];
|
|
778
|
+
/** Optional locale filter for the visual voice selector. */
|
|
779
|
+
voiceLocale?: string;
|
|
780
|
+
/** Optional region filter for the visual voice selector. */
|
|
781
|
+
voiceRegion?: string;
|
|
782
|
+
/** Optional style filter for the visual voice selector. */
|
|
783
|
+
voiceStyle?: string;
|
|
767
784
|
/** Candidate style values shown by the built-in emotion insertion. */
|
|
768
785
|
emotionStyles?: readonly string[];
|
|
769
786
|
/** Class name applied to the editor container. */
|
|
@@ -865,6 +882,12 @@ export const SsmlEditor = forwardRef<SsmlEditorRef, SsmlEditorProps>(function Ss
|
|
|
865
882
|
insertionGroups,
|
|
866
883
|
customInsertions,
|
|
867
884
|
additionalInsertions,
|
|
885
|
+
customInspectors,
|
|
886
|
+
renderVoiceSelector,
|
|
887
|
+
voiceCatalog,
|
|
888
|
+
voiceLocale,
|
|
889
|
+
voiceRegion,
|
|
890
|
+
voiceStyle,
|
|
868
891
|
emotionStyles,
|
|
869
892
|
className,
|
|
870
893
|
style,
|
|
@@ -1347,6 +1370,13 @@ export const SsmlEditor = forwardRef<SsmlEditorRef, SsmlEditorProps>(function Ss
|
|
|
1347
1370
|
readOnly={isReadOnly}
|
|
1348
1371
|
onChange={commit}
|
|
1349
1372
|
onPreviewSelection={onPreviewSelection}
|
|
1373
|
+
locale={localeProp ?? languageProp}
|
|
1374
|
+
customInspectors={customInspectors}
|
|
1375
|
+
renderVoiceSelector={renderVoiceSelector}
|
|
1376
|
+
voiceCatalog={voiceCatalog}
|
|
1377
|
+
voiceLocale={voiceLocale}
|
|
1378
|
+
voiceRegion={voiceRegion}
|
|
1379
|
+
voiceStyle={voiceStyle}
|
|
1350
1380
|
/>
|
|
1351
1381
|
</div>
|
|
1352
1382
|
) : (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo, useState } from "react";
|
|
2
|
-
import type { ReactElement } from "react";
|
|
2
|
+
import type { ReactElement, ReactNode } from "react";
|
|
3
3
|
import {
|
|
4
4
|
buildSsml,
|
|
5
5
|
validateAzureSsml,
|
|
@@ -7,12 +7,48 @@ import {
|
|
|
7
7
|
type SsmlElement,
|
|
8
8
|
type SsmlNode,
|
|
9
9
|
} from "@ssml-builder-js/ssml-core";
|
|
10
|
+
import { SSML_ELEMENT_COPY, type SsmlEditorLocale } from "../locales";
|
|
11
|
+
|
|
12
|
+
export interface VisualVoiceCatalogEntry {
|
|
13
|
+
name: string;
|
|
14
|
+
locale: string;
|
|
15
|
+
region?: string;
|
|
16
|
+
styles?: readonly string[];
|
|
17
|
+
preview?: boolean;
|
|
18
|
+
status?: "ga" | "preview" | "deprecated";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface VoiceSelectorRenderProps {
|
|
22
|
+
value: string;
|
|
23
|
+
voices: readonly VisualVoiceCatalogEntry[];
|
|
24
|
+
readOnly: boolean;
|
|
25
|
+
locale: SsmlEditorLocale;
|
|
26
|
+
onChange: (voice: string) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface VisualInspectorRenderProps {
|
|
30
|
+
document: SsmlDocument;
|
|
31
|
+
element: SsmlElement;
|
|
32
|
+
path: number[];
|
|
33
|
+
readOnly: boolean;
|
|
34
|
+
onChange: (document: SsmlDocument) => void;
|
|
35
|
+
locale: SsmlEditorLocale;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type VisualInspectorRenderer = (props: VisualInspectorRenderProps) => ReactNode;
|
|
10
39
|
|
|
11
40
|
export interface VisualSsmlEditorProps {
|
|
12
41
|
document: SsmlDocument;
|
|
13
42
|
readOnly?: boolean;
|
|
14
43
|
onChange?: (document: SsmlDocument) => void;
|
|
15
44
|
onPreviewSelection?: (ssml: string) => void;
|
|
45
|
+
locale?: SsmlEditorLocale;
|
|
46
|
+
customInspectors?: Readonly<Record<string, VisualInspectorRenderer>>;
|
|
47
|
+
renderVoiceSelector?: (props: VoiceSelectorRenderProps) => ReactNode;
|
|
48
|
+
voiceCatalog?: readonly VisualVoiceCatalogEntry[];
|
|
49
|
+
voiceLocale?: string;
|
|
50
|
+
voiceRegion?: string;
|
|
51
|
+
voiceStyle?: string;
|
|
16
52
|
}
|
|
17
53
|
|
|
18
54
|
interface TextLeaf {
|
|
@@ -192,20 +228,76 @@ function getElementFields(element: SsmlElement): readonly VisualElementField[] {
|
|
|
192
228
|
return VISUAL_ELEMENT_FIELDS[elementLabel(element)] ?? [];
|
|
193
229
|
}
|
|
194
230
|
|
|
231
|
+
function localizedElementLabel(element: SsmlElement, locale: SsmlEditorLocale): string {
|
|
232
|
+
return SSML_ELEMENT_COPY[locale][elementLabel(element)]?.label ?? elementLabel(element);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function filteredVoices(
|
|
236
|
+
voiceCatalog: readonly VisualVoiceCatalogEntry[] | undefined,
|
|
237
|
+
locale: string | undefined,
|
|
238
|
+
region: string | undefined,
|
|
239
|
+
style: string | undefined,
|
|
240
|
+
): readonly VisualVoiceCatalogEntry[] {
|
|
241
|
+
return (voiceCatalog ?? []).filter((voice) => {
|
|
242
|
+
if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
|
|
243
|
+
if (region && voice.region && voice.region.toLowerCase() !== region.toLowerCase()) return false;
|
|
244
|
+
if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
|
|
245
|
+
return true;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }: VoiceSelectorRenderProps): ReactElement {
|
|
250
|
+
return (
|
|
251
|
+
<select
|
|
252
|
+
aria-label={locale === "ja" ? "音声" : "Voice"}
|
|
253
|
+
value={value}
|
|
254
|
+
disabled={readOnly}
|
|
255
|
+
onChange={(event) => onChange(event.target.value)}
|
|
256
|
+
>
|
|
257
|
+
<option value="">{locale === "ja" ? "音声を選択" : "Select a voice"}</option>
|
|
258
|
+
{voices.map((voice) => (
|
|
259
|
+
<option key={voice.name} value={voice.name}>
|
|
260
|
+
{voice.name}
|
|
261
|
+
{voice.preview || voice.status === "preview" ? " (preview)" : ""}
|
|
262
|
+
</option>
|
|
263
|
+
))}
|
|
264
|
+
</select>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
195
268
|
function VisualElementInspector({
|
|
196
269
|
document,
|
|
197
270
|
element,
|
|
198
271
|
path,
|
|
199
272
|
readOnly,
|
|
200
273
|
commit,
|
|
274
|
+
locale,
|
|
275
|
+
customInspector,
|
|
276
|
+
renderVoiceSelector,
|
|
277
|
+
voiceCatalog,
|
|
278
|
+
voiceLocale,
|
|
279
|
+
voiceRegion,
|
|
280
|
+
voiceStyle,
|
|
201
281
|
}: {
|
|
202
282
|
document: SsmlDocument;
|
|
203
283
|
element: SsmlElement;
|
|
204
284
|
path: number[];
|
|
205
285
|
readOnly: boolean;
|
|
206
286
|
commit: (document: SsmlDocument) => void;
|
|
287
|
+
locale: SsmlEditorLocale;
|
|
288
|
+
customInspector?: VisualInspectorRenderer;
|
|
289
|
+
renderVoiceSelector?: (props: VoiceSelectorRenderProps) => ReactNode;
|
|
290
|
+
voiceCatalog?: readonly VisualVoiceCatalogEntry[];
|
|
291
|
+
voiceLocale?: string;
|
|
292
|
+
voiceRegion?: string;
|
|
293
|
+
voiceStyle?: string;
|
|
207
294
|
}): ReactElement {
|
|
295
|
+
if (customInspector) {
|
|
296
|
+
return <>{customInspector({ document, element, path, readOnly, onChange: commit, locale })}</>;
|
|
297
|
+
}
|
|
208
298
|
const fields = getElementFields(element);
|
|
299
|
+
const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
|
|
300
|
+
const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
|
|
209
301
|
return (
|
|
210
302
|
<fieldset>
|
|
211
303
|
<legend>{`<${elementLabel(element)}>`}</legend>
|
|
@@ -218,8 +310,53 @@ function VisualElementInspector({
|
|
|
218
310
|
const inputId = `ssml-visual-${field.key}`;
|
|
219
311
|
return (
|
|
220
312
|
<label key={field.key} htmlFor={inputId}>
|
|
221
|
-
{
|
|
222
|
-
|
|
313
|
+
{locale === "ja"
|
|
314
|
+
? ((
|
|
315
|
+
{
|
|
316
|
+
name: "名前",
|
|
317
|
+
effect: "効果",
|
|
318
|
+
rate: "速度",
|
|
319
|
+
pitch: "ピッチ",
|
|
320
|
+
volume: "音量",
|
|
321
|
+
contour: "ピッチ曲線",
|
|
322
|
+
range: "範囲",
|
|
323
|
+
style: "スタイル",
|
|
324
|
+
styleDegree: "スタイル強度",
|
|
325
|
+
role: "役割",
|
|
326
|
+
interpretAs: "解釈",
|
|
327
|
+
alphabet: "アルファベット",
|
|
328
|
+
ph: "発音",
|
|
329
|
+
level: "強調レベル",
|
|
330
|
+
src: "音声 URL",
|
|
331
|
+
desc: "説明",
|
|
332
|
+
clipBegin: "開始位置",
|
|
333
|
+
clipEnd: "終了位置",
|
|
334
|
+
speed: "速度",
|
|
335
|
+
repeatCount: "繰り返し回数",
|
|
336
|
+
repeatDuration: "繰り返し時間",
|
|
337
|
+
soundLevel: "音量レベル",
|
|
338
|
+
mark: "ブックマーク名",
|
|
339
|
+
alias: "別名",
|
|
340
|
+
lang: "言語",
|
|
341
|
+
uri: "辞書 URI",
|
|
342
|
+
typeValue: "無音の種類",
|
|
343
|
+
value: "値",
|
|
344
|
+
id: "埋め込み ID",
|
|
345
|
+
speakerProfileId: "話者プロファイル ID",
|
|
346
|
+
url: "音声変換 URL",
|
|
347
|
+
profile: "プロファイル",
|
|
348
|
+
} as Record<string, string>
|
|
349
|
+
)[field.key] ?? field.label)
|
|
350
|
+
: field.label}
|
|
351
|
+
{field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? (
|
|
352
|
+
renderSelector({
|
|
353
|
+
value: inputValue,
|
|
354
|
+
voices: availableVoices,
|
|
355
|
+
readOnly,
|
|
356
|
+
locale,
|
|
357
|
+
onChange: (value) => commit(updateOptionalElementProperty(document, path, field.key, value)),
|
|
358
|
+
})
|
|
359
|
+
) : field.multiline ? (
|
|
223
360
|
<textarea
|
|
224
361
|
id={inputId}
|
|
225
362
|
value={inputValue}
|
|
@@ -346,12 +483,23 @@ export function VisualSsmlEditor({
|
|
|
346
483
|
readOnly = false,
|
|
347
484
|
onChange,
|
|
348
485
|
onPreviewSelection,
|
|
486
|
+
locale = "en",
|
|
487
|
+
customInspectors,
|
|
488
|
+
renderVoiceSelector,
|
|
489
|
+
voiceCatalog,
|
|
490
|
+
voiceLocale,
|
|
491
|
+
voiceRegion,
|
|
492
|
+
voiceStyle,
|
|
349
493
|
}: VisualSsmlEditorProps): ReactElement {
|
|
350
494
|
const [selectedPath, setSelectedPath] = useState<number[] | null>(null);
|
|
351
495
|
const [selection, setSelection] = useState({ start: 0, end: 0 });
|
|
352
496
|
const textLeaves = useMemo(() => collectTextLeaves(document.children ?? []), [document]);
|
|
353
497
|
const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
|
|
354
498
|
const selectedElement = selectedPath ? getNodeAtPath(document.children ?? [], selectedPath) : undefined;
|
|
499
|
+
const selectedCustomInspector =
|
|
500
|
+
selectedElement && isElement(selectedElement)
|
|
501
|
+
? (customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type])
|
|
502
|
+
: undefined;
|
|
355
503
|
const diagnostics = useMemo(() => validateAzureSsml(buildSsml(document)), [document]);
|
|
356
504
|
const commit = (nextDocument: SsmlDocument): void => onChange?.(nextDocument);
|
|
357
505
|
|
|
@@ -399,33 +547,54 @@ export function VisualSsmlEditor({
|
|
|
399
547
|
</ul>
|
|
400
548
|
</nav>
|
|
401
549
|
<div className="ssml-editor-visual-form">
|
|
402
|
-
{selectedElement && isElement(selectedElement)
|
|
550
|
+
{selectedCustomInspector && selectedElement && isElement(selectedElement) ? (
|
|
551
|
+
selectedCustomInspector({
|
|
552
|
+
document,
|
|
553
|
+
element: selectedElement,
|
|
554
|
+
path: selectedPath ?? [],
|
|
555
|
+
readOnly,
|
|
556
|
+
onChange: commit,
|
|
557
|
+
locale,
|
|
558
|
+
})
|
|
559
|
+
) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? (
|
|
403
560
|
<fieldset>
|
|
404
|
-
<legend>
|
|
405
|
-
<p>
|
|
561
|
+
<legend>{localizedElementLabel(selectedElement, locale)}</legend>
|
|
562
|
+
<p>{SSML_ELEMENT_COPY[locale][elementLabel(selectedElement)]?.description}</p>
|
|
406
563
|
<button
|
|
407
564
|
type="button"
|
|
408
565
|
disabled={readOnly}
|
|
409
566
|
onClick={() => commit(addDialogTurn(document, selectedPath ?? []))}
|
|
410
567
|
>
|
|
411
|
-
Add turn
|
|
568
|
+
{locale === "ja" ? "ターンを追加" : "Add turn"}
|
|
412
569
|
</button>
|
|
413
570
|
</fieldset>
|
|
414
571
|
) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? (
|
|
415
572
|
<fieldset>
|
|
416
|
-
<legend>
|
|
417
|
-
<label>
|
|
418
|
-
Voice
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
573
|
+
<legend>{localizedElementLabel(selectedElement, locale)}</legend>
|
|
574
|
+
<label htmlFor="ssml-visual-turn-voice">
|
|
575
|
+
{locale === "ja" ? "音声" : "Voice"}
|
|
576
|
+
{voiceCatalog ? (
|
|
577
|
+
(renderVoiceSelector ?? DefaultVoiceSelector)({
|
|
578
|
+
value: selectedElement.voice ?? "",
|
|
579
|
+
voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
|
|
580
|
+
readOnly,
|
|
581
|
+
locale,
|
|
582
|
+
onChange: (value) =>
|
|
583
|
+
commit(updateOptionalElementProperty(document, selectedPath ?? [], "voice", value)),
|
|
584
|
+
})
|
|
585
|
+
) : (
|
|
586
|
+
<input
|
|
587
|
+
id="ssml-visual-turn-voice"
|
|
588
|
+
value={selectedElement.voice ?? ""}
|
|
589
|
+
readOnly={readOnly}
|
|
590
|
+
onChange={(event) =>
|
|
591
|
+
commit(updateOptionalElementProperty(document, selectedPath ?? [], "voice", event.target.value))
|
|
592
|
+
}
|
|
593
|
+
/>
|
|
594
|
+
)}
|
|
426
595
|
</label>
|
|
427
596
|
<label>
|
|
428
|
-
Speaker
|
|
597
|
+
{locale === "ja" ? "話者" : "Speaker"}
|
|
429
598
|
<input
|
|
430
599
|
value={selectedElement.speaker ?? ""}
|
|
431
600
|
readOnly={readOnly}
|
|
@@ -435,7 +604,7 @@ export function VisualSsmlEditor({
|
|
|
435
604
|
/>
|
|
436
605
|
</label>
|
|
437
606
|
<label>
|
|
438
|
-
Turn text
|
|
607
|
+
{locale === "ja" ? "発話テキスト" : "Turn text"}
|
|
439
608
|
<textarea
|
|
440
609
|
value={
|
|
441
610
|
selectedElement.children?.filter((child): child is string => typeof child === "string").join("") ??
|
|
@@ -454,9 +623,9 @@ export function VisualSsmlEditor({
|
|
|
454
623
|
</fieldset>
|
|
455
624
|
) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:backgroundaudio" ? (
|
|
456
625
|
<fieldset>
|
|
457
|
-
<legend>
|
|
626
|
+
<legend>{localizedElementLabel(selectedElement, locale)}</legend>
|
|
458
627
|
<label>
|
|
459
|
-
Source URL
|
|
628
|
+
{locale === "ja" ? "音声 URL" : "Source URL"}
|
|
460
629
|
<input
|
|
461
630
|
value={selectedElement.src ?? ""}
|
|
462
631
|
readOnly={readOnly}
|
|
@@ -466,7 +635,7 @@ export function VisualSsmlEditor({
|
|
|
466
635
|
/>
|
|
467
636
|
</label>
|
|
468
637
|
<label>
|
|
469
|
-
Volume
|
|
638
|
+
{locale === "ja" ? "音量" : "Volume"}
|
|
470
639
|
<input
|
|
471
640
|
value={selectedElement.volume === undefined ? "" : String(selectedElement.volume)}
|
|
472
641
|
readOnly={readOnly}
|
|
@@ -476,7 +645,7 @@ export function VisualSsmlEditor({
|
|
|
476
645
|
/>
|
|
477
646
|
</label>
|
|
478
647
|
<label>
|
|
479
|
-
Fade in
|
|
648
|
+
{locale === "ja" ? "フェードイン" : "Fade in"}
|
|
480
649
|
<input
|
|
481
650
|
value={selectedElement.fadeIn === undefined ? "" : String(selectedElement.fadeIn)}
|
|
482
651
|
readOnly={readOnly}
|
|
@@ -486,7 +655,7 @@ export function VisualSsmlEditor({
|
|
|
486
655
|
/>
|
|
487
656
|
</label>
|
|
488
657
|
<label>
|
|
489
|
-
Fade out
|
|
658
|
+
{locale === "ja" ? "フェードアウト" : "Fade out"}
|
|
490
659
|
<input
|
|
491
660
|
value={selectedElement.fadeOut === undefined ? "" : String(selectedElement.fadeOut)}
|
|
492
661
|
readOnly={readOnly}
|
|
@@ -503,6 +672,15 @@ export function VisualSsmlEditor({
|
|
|
503
672
|
path={selectedPath ?? []}
|
|
504
673
|
readOnly={readOnly}
|
|
505
674
|
commit={commit}
|
|
675
|
+
locale={locale}
|
|
676
|
+
customInspector={
|
|
677
|
+
customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type]
|
|
678
|
+
}
|
|
679
|
+
renderVoiceSelector={renderVoiceSelector}
|
|
680
|
+
voiceCatalog={voiceCatalog}
|
|
681
|
+
voiceLocale={voiceLocale}
|
|
682
|
+
voiceRegion={voiceRegion}
|
|
683
|
+
voiceStyle={voiceStyle}
|
|
506
684
|
/>
|
|
507
685
|
) : selectedLeaf ? (
|
|
508
686
|
<>
|
package/src/index.tsx
CHANGED
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
export { SsmlEditor } from "./SsmlEditor";
|
|
6
6
|
export { VisualSsmlEditor } from "./components/VisualSsmlEditor";
|
|
7
|
-
export type {
|
|
7
|
+
export type {
|
|
8
|
+
VisualInspectorRenderProps,
|
|
9
|
+
VisualInspectorRenderer,
|
|
10
|
+
VisualSsmlEditorProps,
|
|
11
|
+
VisualVoiceCatalogEntry,
|
|
12
|
+
VoiceSelectorRenderProps,
|
|
13
|
+
} from "./components/VisualSsmlEditor";
|
|
8
14
|
export type {
|
|
9
15
|
SsmlEditorButton,
|
|
10
16
|
SsmlEditorButtonVisibility,
|
|
@@ -32,7 +38,7 @@ export type {
|
|
|
32
38
|
SsmlInsertionOption,
|
|
33
39
|
SsmlInsertionTemplate,
|
|
34
40
|
} from "./SsmlEditor";
|
|
35
|
-
export { EDITOR_COPY, INLINE_BADGE_COPY, SSML_HOVER_COPY } from "./locales";
|
|
41
|
+
export { EDITOR_COPY, INLINE_BADGE_COPY, SSML_ELEMENT_COPY, SSML_HOVER_COPY } from "./locales";
|
|
36
42
|
export type {
|
|
37
43
|
EditorCopy,
|
|
38
44
|
InlineBadgeCopy,
|
|
@@ -42,6 +48,7 @@ export type {
|
|
|
42
48
|
SsmlHoverLocale,
|
|
43
49
|
SsmlHoverParameterCopy,
|
|
44
50
|
SsmlHoverTagCopy,
|
|
51
|
+
SsmlElementLocaleCopy,
|
|
45
52
|
} from "./locales";
|
|
46
53
|
export {
|
|
47
54
|
createSsmlEditorInsertionDefinition,
|