ssml-builder-js 2.16.0 → 2.18.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/README.md +10 -2
- package/dist/{chunk-NKLZGITR.mjs → chunk-2SYLELUT.mjs} +4 -2
- package/dist/{chunk-NKLZGITR.mjs.map → chunk-2SYLELUT.mjs.map} +1 -1
- package/dist/{chunk-HI74FTKY.mjs → chunk-5AZWURHW.mjs} +4 -2
- package/dist/{chunk-HI74FTKY.mjs.map → chunk-5AZWURHW.mjs.map} +1 -1
- package/dist/{chunk-F2EMU3HM.mjs → chunk-SLZ7PE6W.mjs} +2 -2
- package/dist/core.d.mts +4 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.js +3 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/elements.js +3 -1
- package/dist/elements.js.map +1 -1
- package/dist/elements.mjs +2 -2
- package/dist/{index.d-DR5Qz43p.d.mts → index.d-B2WddTa4.d.mts} +12 -1
- package/dist/{index.d-DR5Qz43p.d.ts → index.d-B2WddTa4.d.ts} +12 -1
- package/dist/index.d.mts +223 -127
- package/dist/index.d.ts +223 -127
- package/dist/index.js +558 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +551 -100
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +5 -2
- package/dist/react.d.ts +5 -2
- package/dist/react.js +111 -25
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +110 -26
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-F2EMU3HM.mjs.map → chunk-SLZ7PE6W.mjs.map} +0 -0
package/dist/react.mjs
CHANGED
|
@@ -42,13 +42,13 @@ import {
|
|
|
42
42
|
resolveExpressAsStyles,
|
|
43
43
|
updateEditableText,
|
|
44
44
|
updateTagAttribute
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-SLZ7PE6W.mjs";
|
|
46
46
|
import {
|
|
47
47
|
buildPartialSsml,
|
|
48
48
|
buildSsml,
|
|
49
49
|
validateAzureSsml,
|
|
50
50
|
validateSsml
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-5AZWURHW.mjs";
|
|
52
52
|
import "./chunk-6S5ODO6A.mjs";
|
|
53
53
|
|
|
54
54
|
// packages/ssml-editor-react/src/SsmlEditor.tsx
|
|
@@ -369,6 +369,8 @@ function InsertionPopover({
|
|
|
369
369
|
toolbarButtonStyle,
|
|
370
370
|
emptyOptionsMessage,
|
|
371
371
|
isReadOnly,
|
|
372
|
+
disabled = false,
|
|
373
|
+
disabledReason,
|
|
372
374
|
isOpen,
|
|
373
375
|
menuPosition,
|
|
374
376
|
menuRef,
|
|
@@ -386,7 +388,7 @@ function InsertionPopover({
|
|
|
386
388
|
role: "menuitem",
|
|
387
389
|
style: editorStyles.toolbarOption,
|
|
388
390
|
title: option.descriptions?.[language] ?? insertion.descriptions[language],
|
|
389
|
-
disabled: isReadOnly,
|
|
391
|
+
disabled: isReadOnly || disabled,
|
|
390
392
|
onMouseDown: (event) => event.preventDefault(),
|
|
391
393
|
onClick: () => {
|
|
392
394
|
if (!isReadOnly) {
|
|
@@ -415,11 +417,12 @@ function InsertionPopover({
|
|
|
415
417
|
{
|
|
416
418
|
type: "button",
|
|
417
419
|
style: toolbarButtonStyle,
|
|
418
|
-
title: getInsertionTitle(insertion, language),
|
|
420
|
+
title: disabledReason ?? getInsertionTitle(insertion, language),
|
|
419
421
|
"aria-label": insertion.labels[language],
|
|
420
422
|
"aria-haspopup": "menu",
|
|
421
423
|
"aria-expanded": isOpen,
|
|
422
424
|
"aria-controls": isOpen ? `ssml-editor-popover-${insertion.id}` : void 0,
|
|
425
|
+
disabled: isReadOnly || disabled,
|
|
423
426
|
onClick: (event) => onToggle(event.currentTarget)
|
|
424
427
|
},
|
|
425
428
|
showToolbarIcons && /* @__PURE__ */ React.createElement("span", { style: editorStyles.toolbarIcon, "aria-hidden": "true" }, insertion.icon),
|
|
@@ -1969,6 +1972,21 @@ function filteredVoices(voiceCatalog, locale, region, style) {
|
|
|
1969
1972
|
return true;
|
|
1970
1973
|
});
|
|
1971
1974
|
}
|
|
1975
|
+
function voiceForPath(document2, path, voiceCatalog) {
|
|
1976
|
+
if (!path || !voiceCatalog) return void 0;
|
|
1977
|
+
const ancestors = getElementAncestors(document2.children ?? [], path);
|
|
1978
|
+
const node = getNodeAtPath(document2.children ?? [], path);
|
|
1979
|
+
const candidates = [...ancestors, ...node && isElement(node) ? [node] : []].reverse();
|
|
1980
|
+
const voiceName = candidates.find((element) => element.type === "voice")?.name ?? candidates.find((element) => element.type === "mstts:turn")?.voice;
|
|
1981
|
+
return voiceName ? voiceCatalog.find((voice) => voice.name.toLowerCase() === voiceName.toLowerCase()) : void 0;
|
|
1982
|
+
}
|
|
1983
|
+
function isVisualTagSupported(tagName, voice) {
|
|
1984
|
+
if (!voice) return true;
|
|
1985
|
+
const tag = tagName.toLowerCase();
|
|
1986
|
+
const unsupported = new Set((voice.unsupportedTags ?? []).map((candidate) => candidate.toLowerCase()));
|
|
1987
|
+
const supported = voice.supportedTags?.map((candidate) => candidate.toLowerCase());
|
|
1988
|
+
return !unsupported.has(tag) && (supported === void 0 || supported.includes(tag));
|
|
1989
|
+
}
|
|
1972
1990
|
function VoiceCapabilityMatrix({
|
|
1973
1991
|
voice,
|
|
1974
1992
|
locale
|
|
@@ -2043,10 +2061,12 @@ function VisualElementInspector({
|
|
|
2043
2061
|
voiceLocale,
|
|
2044
2062
|
voiceRegion,
|
|
2045
2063
|
voiceStyle,
|
|
2046
|
-
diagnostics
|
|
2064
|
+
diagnostics,
|
|
2065
|
+
voiceDefinition
|
|
2047
2066
|
}) {
|
|
2067
|
+
const tagSupported = isVisualTagSupported(elementLabel(element), voiceDefinition);
|
|
2048
2068
|
if (customInspector) {
|
|
2049
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, customInspector({ document: document2, element, path, readOnly, onChange: commit, locale }));
|
|
2069
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, customInspector({ document: document2, element, path, readOnly: readOnly || !tagSupported, onChange: commit, locale }));
|
|
2050
2070
|
}
|
|
2051
2071
|
const fields = getElementFields(element);
|
|
2052
2072
|
const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
|
|
@@ -2054,7 +2074,7 @@ function VisualElementInspector({
|
|
|
2054
2074
|
(voice) => voice.name === (element.type === "voice" ? element.name : void 0)
|
|
2055
2075
|
);
|
|
2056
2076
|
const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
|
|
2057
|
-
return /* @__PURE__ */ React.createElement("fieldset",
|
|
2077
|
+
return /* @__PURE__ */ React.createElement("fieldset", { disabled: readOnly || !tagSupported, style: !tagSupported ? { border: "1px solid #c0392b" } : void 0 }, /* @__PURE__ */ React.createElement("legend", null, `<${elementLabel(element)}>`, " ", /* @__PURE__ */ React.createElement(WarningBadge, { messages: elementWarnings(diagnostics, element) })), fields.length === 0 ? /* @__PURE__ */ React.createElement("p", null, "This element is preserved in the visual tree. Edit its attributes in Code mode.") : fields.map((field) => {
|
|
2058
2078
|
const value = element[field.key];
|
|
2059
2079
|
const inputValue = value === void 0 ? "" : String(value);
|
|
2060
2080
|
const inputId = `ssml-visual-${field.key}`;
|
|
@@ -2103,6 +2123,7 @@ function VisualElementInspector({
|
|
|
2103
2123
|
{
|
|
2104
2124
|
id: inputId,
|
|
2105
2125
|
value: inputValue,
|
|
2126
|
+
disabled: readOnly || !tagSupported,
|
|
2106
2127
|
readOnly,
|
|
2107
2128
|
onChange: (event) => commit(updateOptionalElementProperty(document2, path, field.key, event.target.value))
|
|
2108
2129
|
}
|
|
@@ -2111,6 +2132,7 @@ function VisualElementInspector({
|
|
|
2111
2132
|
{
|
|
2112
2133
|
id: inputId,
|
|
2113
2134
|
value: inputValue,
|
|
2135
|
+
disabled: readOnly || !tagSupported,
|
|
2114
2136
|
readOnly,
|
|
2115
2137
|
onChange: (event) => commit(updateOptionalElementProperty(document2, path, field.key, event.target.value))
|
|
2116
2138
|
}
|
|
@@ -2174,18 +2196,27 @@ function TreeNode({
|
|
|
2174
2196
|
}) {
|
|
2175
2197
|
if (!isElement(node)) return null;
|
|
2176
2198
|
const name = elementLabel(node);
|
|
2199
|
+
const messages = getWarnings(node);
|
|
2177
2200
|
const isSelected = selectedPath?.join(".") === path.join(".");
|
|
2178
|
-
return /* @__PURE__ */ React.createElement(
|
|
2179
|
-
|
|
2201
|
+
return /* @__PURE__ */ React.createElement(
|
|
2202
|
+
"li",
|
|
2180
2203
|
{
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2204
|
+
"data-ssml-diagnostic": messages.length > 0 ? "error" : void 0,
|
|
2205
|
+
style: messages.length > 0 ? { border: "1px solid #c0392b", borderRadius: "0.25rem" } : void 0
|
|
2206
|
+
},
|
|
2207
|
+
/* @__PURE__ */ React.createElement("button", { type: "button", "aria-current": isSelected ? "true" : void 0, onClick: () => onSelect(path) }, `<${name}>`, /* @__PURE__ */ React.createElement(WarningBadge, { messages: getWarnings(node) })),
|
|
2208
|
+
(node.children ?? []).length > 0 && /* @__PURE__ */ React.createElement("ul", null, node.children?.map((child, index) => /* @__PURE__ */ React.createElement(
|
|
2209
|
+
TreeNode,
|
|
2210
|
+
{
|
|
2211
|
+
key: `${path.join(".")}/${isElement(child) ? elementLabel(child) : JSON.stringify(child)}`,
|
|
2212
|
+
node: child,
|
|
2213
|
+
path: [...path, index],
|
|
2214
|
+
selectedPath,
|
|
2215
|
+
onSelect,
|
|
2216
|
+
getWarnings
|
|
2217
|
+
}
|
|
2218
|
+
)))
|
|
2219
|
+
);
|
|
2189
2220
|
}
|
|
2190
2221
|
function VisualSsmlEditor({
|
|
2191
2222
|
document: document2,
|
|
@@ -2200,13 +2231,16 @@ function VisualSsmlEditor({
|
|
|
2200
2231
|
voiceRegion,
|
|
2201
2232
|
voiceStyle,
|
|
2202
2233
|
voiceModel,
|
|
2203
|
-
model
|
|
2234
|
+
model,
|
|
2235
|
+
voiceCatalogMetadata
|
|
2204
2236
|
}) {
|
|
2205
2237
|
const [selectedPath, setSelectedPath] = useState2(null);
|
|
2206
2238
|
const [selection, setSelection] = useState2({ start: 0, end: 0 });
|
|
2207
2239
|
const textLeaves = useMemo(() => collectTextLeaves(document2.children ?? []), [document2]);
|
|
2208
2240
|
const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
|
|
2209
2241
|
const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
|
|
2242
|
+
const activeVoice = voiceForPath(document2, selectedPath ?? selectedLeaf?.path, voiceCatalog);
|
|
2243
|
+
const staleCatalog = voiceCatalogMetadata?.expiresAt ? Date.parse(voiceCatalogMetadata.expiresAt) <= Date.now() : false;
|
|
2210
2244
|
const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
|
|
2211
2245
|
const validationOptions = useMemo(
|
|
2212
2246
|
() => ({
|
|
@@ -2236,7 +2270,7 @@ function VisualSsmlEditor({
|
|
|
2236
2270
|
const end = selection.start === selection.end ? selectedLeaf.value.length : selection.end;
|
|
2237
2271
|
commit(wrapTextAtPath(document2, selectedLeaf.path, start, end, tag, attributes));
|
|
2238
2272
|
};
|
|
2239
|
-
return /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual", "data-ssml-editor-visual": "" }, /* @__PURE__ */ React.createElement("fieldset", { className: "ssml-editor-visual-breadcrumb" }, /* @__PURE__ */ React.createElement("legend", null, "SSML structure breadcrumb"), /* @__PURE__ */ React.createElement("span", null, "<speak>"), selectedLeaf?.ancestors.map((ancestor, index) => /* @__PURE__ */ React.createElement("span", { key: selectedLeaf?.ancestors.slice(0, index + 1).join("/") }, " / <", ancestor, ">")), selectedPath && /* @__PURE__ */ React.createElement("button", { type: "button", onClick: () => setSelectedPath(null) }, "Clear parent")), diagnostics.length > 0 && /* @__PURE__ */ React.createElement("div", { role: "alert", "aria-invalid": "true", className: "ssml-editor-visual-errors" }, diagnostics.map((diagnostic) => /* @__PURE__ */ React.createElement("div", { key: `${diagnostic.code}-${diagnostic.message}` }, diagnostic.message))), /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual-layout" }, /* @__PURE__ */ React.createElement("nav", { "aria-label": "SSML structure tree", className: "ssml-editor-visual-tree" }, /* @__PURE__ */ React.createElement("strong", null, "Structure"), /* @__PURE__ */ React.createElement("ul", null, document2.children?.map((node, index) => /* @__PURE__ */ React.createElement(
|
|
2273
|
+
return /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual", "data-ssml-editor-visual": "" }, /* @__PURE__ */ React.createElement("fieldset", { className: "ssml-editor-visual-breadcrumb" }, /* @__PURE__ */ React.createElement("legend", null, "SSML structure breadcrumb"), /* @__PURE__ */ React.createElement("span", null, "<speak>"), selectedLeaf?.ancestors.map((ancestor, index) => /* @__PURE__ */ React.createElement("span", { key: selectedLeaf?.ancestors.slice(0, index + 1).join("/") }, " / <", ancestor, ">")), selectedPath && /* @__PURE__ */ React.createElement("button", { type: "button", onClick: () => setSelectedPath(null) }, "Clear parent")), diagnostics.length > 0 && /* @__PURE__ */ React.createElement("div", { role: "alert", "aria-invalid": "true", className: "ssml-editor-visual-errors" }, diagnostics.map((diagnostic) => /* @__PURE__ */ React.createElement("div", { key: `${diagnostic.code}-${diagnostic.message}` }, diagnostic.message))), staleCatalog && /* @__PURE__ */ React.createElement("div", { role: "status", className: "ssml-editor-visual-catalog-warning" }, locale === "ja" ? "\u97F3\u58F0\u30AB\u30BF\u30ED\u30B0\u304C\u53E4\u304F\u306A\u3063\u3066\u3044\u307E\u3059\u3002\u66F4\u65B0\u3057\u3066\u304F\u3060\u3055\u3044\u3002" : "The voice catalog is stale. Refresh it before synthesizing."), /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual-layout" }, /* @__PURE__ */ React.createElement("nav", { "aria-label": "SSML structure tree", className: "ssml-editor-visual-tree" }, /* @__PURE__ */ React.createElement("strong", null, "Structure"), /* @__PURE__ */ React.createElement("ul", null, document2.children?.map((node, index) => /* @__PURE__ */ React.createElement(
|
|
2240
2274
|
TreeNode,
|
|
2241
2275
|
{
|
|
2242
2276
|
key: isElement(node) ? elementLabel(node) : JSON.stringify(node),
|
|
@@ -2250,14 +2284,14 @@ function VisualSsmlEditor({
|
|
|
2250
2284
|
document: document2,
|
|
2251
2285
|
element: selectedElement,
|
|
2252
2286
|
path: selectedPath ?? [],
|
|
2253
|
-
readOnly,
|
|
2287
|
+
readOnly: readOnly || !isVisualTagSupported(elementLabel(selectedElement), activeVoice),
|
|
2254
2288
|
onChange: commit,
|
|
2255
2289
|
locale
|
|
2256
2290
|
}) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("p", null, SSML_ELEMENT_COPY[locale][elementLabel(selectedElement)]?.description), /* @__PURE__ */ React.createElement(
|
|
2257
2291
|
"button",
|
|
2258
2292
|
{
|
|
2259
2293
|
type: "button",
|
|
2260
|
-
disabled: readOnly,
|
|
2294
|
+
disabled: readOnly || !isVisualTagSupported("mstts:dialog", activeVoice),
|
|
2261
2295
|
onClick: () => commit(addDialogTurn(document2, selectedPath ?? []))
|
|
2262
2296
|
},
|
|
2263
2297
|
locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
|
|
@@ -2339,7 +2373,8 @@ function VisualSsmlEditor({
|
|
|
2339
2373
|
voiceLocale,
|
|
2340
2374
|
voiceRegion,
|
|
2341
2375
|
voiceStyle,
|
|
2342
|
-
diagnostics
|
|
2376
|
+
diagnostics,
|
|
2377
|
+
voiceDefinition: activeVoice
|
|
2343
2378
|
}
|
|
2344
2379
|
) : selectedLeaf ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", null, "Text", /* @__PURE__ */ React.createElement(
|
|
2345
2380
|
"textarea",
|
|
@@ -2349,19 +2384,43 @@ function VisualSsmlEditor({
|
|
|
2349
2384
|
onSelect: (event) => setSelection({ start: event.currentTarget.selectionStart, end: event.currentTarget.selectionEnd }),
|
|
2350
2385
|
onChange: (event) => commit(updateTextAtPath(document2, selectedLeaf.path, event.target.value))
|
|
2351
2386
|
}
|
|
2352
|
-
)), /* @__PURE__ */ React.createElement("fieldset", { className: "ssml-editor-visual-actions" }, /* @__PURE__ */ React.createElement("legend", null, "Apply SSML formatting"), /* @__PURE__ */ React.createElement(
|
|
2387
|
+
)), /* @__PURE__ */ React.createElement("fieldset", { className: "ssml-editor-visual-actions" }, /* @__PURE__ */ React.createElement("legend", null, "Apply SSML formatting"), /* @__PURE__ */ React.createElement(
|
|
2353
2388
|
"button",
|
|
2354
2389
|
{
|
|
2355
2390
|
type: "button",
|
|
2356
|
-
disabled: readOnly,
|
|
2391
|
+
disabled: readOnly || !isVisualTagSupported("prosody", activeVoice),
|
|
2392
|
+
onClick: () => applyWrapper("prosody", { rate: "slow" })
|
|
2393
|
+
},
|
|
2394
|
+
"Rate"
|
|
2395
|
+
), /* @__PURE__ */ React.createElement(
|
|
2396
|
+
"button",
|
|
2397
|
+
{
|
|
2398
|
+
type: "button",
|
|
2399
|
+
disabled: readOnly || !isVisualTagSupported("prosody", activeVoice),
|
|
2400
|
+
onClick: () => applyWrapper("prosody", { pitch: "high" })
|
|
2401
|
+
},
|
|
2402
|
+
"Pitch"
|
|
2403
|
+
), /* @__PURE__ */ React.createElement(
|
|
2404
|
+
"button",
|
|
2405
|
+
{
|
|
2406
|
+
type: "button",
|
|
2407
|
+
disabled: readOnly || !isVisualTagSupported("mstts:express-as", activeVoice),
|
|
2357
2408
|
onClick: () => applyWrapper("mstts:express-as", { style: "cheerful" })
|
|
2358
2409
|
},
|
|
2359
2410
|
"Emotion"
|
|
2360
|
-
), /* @__PURE__ */ React.createElement(
|
|
2411
|
+
), /* @__PURE__ */ React.createElement(
|
|
2361
2412
|
"button",
|
|
2362
2413
|
{
|
|
2363
2414
|
type: "button",
|
|
2364
|
-
disabled: readOnly,
|
|
2415
|
+
disabled: readOnly || !isVisualTagSupported("break", activeVoice),
|
|
2416
|
+
onClick: () => applyWrapper("break", { time: "500ms" })
|
|
2417
|
+
},
|
|
2418
|
+
"Pause"
|
|
2419
|
+
), /* @__PURE__ */ React.createElement(
|
|
2420
|
+
"button",
|
|
2421
|
+
{
|
|
2422
|
+
type: "button",
|
|
2423
|
+
disabled: readOnly || !isVisualTagSupported("phoneme", activeVoice),
|
|
2365
2424
|
onClick: () => applyWrapper("phoneme", { alphabet: "ipa", ph: selectedLeaf.value })
|
|
2366
2425
|
},
|
|
2367
2426
|
"Pronunciation"
|
|
@@ -2380,6 +2439,23 @@ var UNGROUPED_TOOLBAR_GROUP = "__ssml-editor-ungrouped__";
|
|
|
2380
2439
|
var TIMING_POPOVER_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence", "mstts:audioduration"]);
|
|
2381
2440
|
var PROSODY_POPOVER_TAGS = /* @__PURE__ */ new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
|
|
2382
2441
|
var TEXT_POPOVER_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w", "lang"]);
|
|
2442
|
+
function isVoiceTagSupported(tagName, voice) {
|
|
2443
|
+
if (!tagName || !voice) return true;
|
|
2444
|
+
const tag = tagName.toLowerCase();
|
|
2445
|
+
const unsupported = new Set((voice.unsupportedTags ?? []).map((candidate) => candidate.toLowerCase()));
|
|
2446
|
+
const supported = voice.supportedTags?.map((candidate) => candidate.toLowerCase());
|
|
2447
|
+
return !unsupported.has(tag) && (supported === void 0 || supported.includes(tag));
|
|
2448
|
+
}
|
|
2449
|
+
function findFirstVoiceName(nodes) {
|
|
2450
|
+
for (const node of nodes) {
|
|
2451
|
+
if (typeof node === "string" || node.type === "text") continue;
|
|
2452
|
+
if (node.type === "voice" && node.name) return node.name;
|
|
2453
|
+
if (node.type === "mstts:turn" && node.voice) return node.voice;
|
|
2454
|
+
const nested = findFirstVoiceName(node.children ?? []);
|
|
2455
|
+
if (nested) return nested;
|
|
2456
|
+
}
|
|
2457
|
+
return void 0;
|
|
2458
|
+
}
|
|
2383
2459
|
function localizedText(value) {
|
|
2384
2460
|
return { ja: value, en: value };
|
|
2385
2461
|
}
|
|
@@ -2965,6 +3041,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
2965
3041
|
voiceStyle,
|
|
2966
3042
|
voiceModel,
|
|
2967
3043
|
model,
|
|
3044
|
+
voiceCatalogMetadata,
|
|
2968
3045
|
emotionStyles,
|
|
2969
3046
|
className,
|
|
2970
3047
|
style,
|
|
@@ -3128,6 +3205,10 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
3128
3205
|
const isProsodyPopover = insertion.tagName !== void 0 && PROSODY_POPOVER_TAGS.has(insertion.tagName);
|
|
3129
3206
|
const isTextPopover = insertion.tagName !== void 0 && TEXT_POPOVER_TAGS.has(insertion.tagName);
|
|
3130
3207
|
const insertionButtonStyle = insertion.tagName && activeTags.has(insertion.tagName.toLowerCase()) ? { ...toolbarButtonStyle, ...editorStyles.toolbarButtonActive } : toolbarButtonStyle;
|
|
3208
|
+
const activeVoiceName = popoverVoiceName ?? findFirstVoiceName(draftDocument.children ?? []);
|
|
3209
|
+
const activeVoice = voiceCatalog?.find((voice) => voice.name.toLowerCase() === activeVoiceName?.toLowerCase());
|
|
3210
|
+
const insertionDisabled = !isVoiceTagSupported(insertion.tagName, activeVoice);
|
|
3211
|
+
const disabledReason = insertionDisabled ? language === "ja" ? `\u9078\u629E\u4E2D\u306E\u97F3\u58F0\u306F <${insertion.tagName}> \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093\u3002` : `The selected voice does not support <${insertion.tagName}>.` : void 0;
|
|
3131
3212
|
const props = {
|
|
3132
3213
|
language,
|
|
3133
3214
|
isDarkTheme,
|
|
@@ -3136,6 +3217,8 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
3136
3217
|
toolbarButtonStyle: insertionButtonStyle,
|
|
3137
3218
|
emptyOptionsMessage: copy.noAvailableOptions,
|
|
3138
3219
|
isReadOnly,
|
|
3220
|
+
disabled: insertionDisabled,
|
|
3221
|
+
disabledReason,
|
|
3139
3222
|
openPopoverId,
|
|
3140
3223
|
menuPosition: popoverPosition,
|
|
3141
3224
|
menuRef: setPopoverMenuRef,
|
|
@@ -3364,6 +3447,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
3364
3447
|
voiceLocale,
|
|
3365
3448
|
voiceRegion,
|
|
3366
3449
|
voiceStyle,
|
|
3450
|
+
voiceCatalogMetadata,
|
|
3367
3451
|
voiceModel,
|
|
3368
3452
|
model
|
|
3369
3453
|
}
|