@ssml-builder-js/ssml-editor-react 2.11.0 → 2.12.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 +6 -0
- package/dist/index.js +146 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +146 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/VisualSsmlEditor.tsx +172 -2
- package/test/ui-components.test.tsx +78 -0
package/dist/index.mjs
CHANGED
|
@@ -4695,6 +4695,141 @@ function updateOptionalElementProperty(document2, path, property, value) {
|
|
|
4695
4695
|
return next;
|
|
4696
4696
|
});
|
|
4697
4697
|
}
|
|
4698
|
+
var VISUAL_ELEMENT_FIELDS = {
|
|
4699
|
+
voice: [
|
|
4700
|
+
{ key: "name", label: "Voice name" },
|
|
4701
|
+
{ key: "effect", label: "Effect" }
|
|
4702
|
+
],
|
|
4703
|
+
prosody: [
|
|
4704
|
+
{ key: "rate", label: "Rate" },
|
|
4705
|
+
{ key: "pitch", label: "Pitch" },
|
|
4706
|
+
{ key: "volume", label: "Volume" },
|
|
4707
|
+
{ key: "contour", label: "Contour" },
|
|
4708
|
+
{ key: "range", label: "Range" }
|
|
4709
|
+
],
|
|
4710
|
+
"express-as": [
|
|
4711
|
+
{ key: "style", label: "Style" },
|
|
4712
|
+
{ key: "styleDegree", label: "Style degree" },
|
|
4713
|
+
{ key: "role", label: "Role" }
|
|
4714
|
+
],
|
|
4715
|
+
expressAs: [
|
|
4716
|
+
{ key: "style", label: "Style" },
|
|
4717
|
+
{ key: "styleDegree", label: "Style degree" },
|
|
4718
|
+
{ key: "role", label: "Role" }
|
|
4719
|
+
],
|
|
4720
|
+
"mstts:express-as": [
|
|
4721
|
+
{ key: "style", label: "Style" },
|
|
4722
|
+
{ key: "styleDegree", label: "Style degree" },
|
|
4723
|
+
{ key: "role", label: "Role" }
|
|
4724
|
+
],
|
|
4725
|
+
"say-as": [
|
|
4726
|
+
{ key: "interpretAs", label: "Interpret as" },
|
|
4727
|
+
{ key: "format", label: "Format" },
|
|
4728
|
+
{ key: "detail", label: "Detail" }
|
|
4729
|
+
],
|
|
4730
|
+
sayAs: [
|
|
4731
|
+
{ key: "interpretAs", label: "Interpret as" },
|
|
4732
|
+
{ key: "format", label: "Format" },
|
|
4733
|
+
{ key: "detail", label: "Detail" }
|
|
4734
|
+
],
|
|
4735
|
+
phoneme: [
|
|
4736
|
+
{ key: "alphabet", label: "Alphabet" },
|
|
4737
|
+
{ key: "ph", label: "Pronunciation" }
|
|
4738
|
+
],
|
|
4739
|
+
emphasis: [{ key: "level", label: "Level" }],
|
|
4740
|
+
audio: [
|
|
4741
|
+
{ key: "src", label: "Source URL" },
|
|
4742
|
+
{ key: "desc", label: "Description" },
|
|
4743
|
+
{ key: "clipBegin", label: "Clip begin" },
|
|
4744
|
+
{ key: "clipEnd", label: "Clip end" },
|
|
4745
|
+
{ key: "speed", label: "Speed" },
|
|
4746
|
+
{ key: "repeatCount", label: "Repeat count" },
|
|
4747
|
+
{ key: "repeatDuration", label: "Repeat duration" },
|
|
4748
|
+
{ key: "soundLevel", label: "Sound level" }
|
|
4749
|
+
],
|
|
4750
|
+
mark: [{ key: "name", label: "Mark name" }],
|
|
4751
|
+
bookmark: [{ key: "mark", label: "Bookmark name" }],
|
|
4752
|
+
sub: [{ key: "alias", label: "Alias" }],
|
|
4753
|
+
lang: [{ key: "lang", label: "Language" }],
|
|
4754
|
+
lexicon: [{ key: "uri", label: "Lexicon URI" }],
|
|
4755
|
+
"mstts:silence": [
|
|
4756
|
+
{ key: "typeValue", label: "Silence type" },
|
|
4757
|
+
{ key: "value", label: "Value" }
|
|
4758
|
+
],
|
|
4759
|
+
silence: [
|
|
4760
|
+
{ key: "typeValue", label: "Silence type" },
|
|
4761
|
+
{ key: "value", label: "Value" }
|
|
4762
|
+
],
|
|
4763
|
+
"mstts:audioduration": [{ key: "value", label: "Duration" }],
|
|
4764
|
+
"mstts:ttsembedding": [{ key: "speakerProfileId", label: "Speaker profile ID" }],
|
|
4765
|
+
"mstts:embedding": [
|
|
4766
|
+
{ key: "id", label: "Embedding ID" },
|
|
4767
|
+
{ key: "speakerProfileId", label: "Speaker profile ID" }
|
|
4768
|
+
],
|
|
4769
|
+
"mstts:voiceconversion": [
|
|
4770
|
+
{ key: "url", label: "Source URL" },
|
|
4771
|
+
{ key: "profile", label: "Profile" },
|
|
4772
|
+
{ key: "speakerProfileId", label: "Speaker profile ID" }
|
|
4773
|
+
]
|
|
4774
|
+
};
|
|
4775
|
+
function getElementFields(element) {
|
|
4776
|
+
return VISUAL_ELEMENT_FIELDS[elementLabel(element)] ?? [];
|
|
4777
|
+
}
|
|
4778
|
+
function VisualElementInspector({
|
|
4779
|
+
document: document2,
|
|
4780
|
+
element,
|
|
4781
|
+
path,
|
|
4782
|
+
readOnly,
|
|
4783
|
+
commit
|
|
4784
|
+
}) {
|
|
4785
|
+
const fields = getElementFields(element);
|
|
4786
|
+
return /* @__PURE__ */ jsxs2("fieldset", { children: [
|
|
4787
|
+
/* @__PURE__ */ jsx6("legend", { children: `<${elementLabel(element)}>` }),
|
|
4788
|
+
fields.length === 0 ? /* @__PURE__ */ jsx6("p", { children: "This element is preserved in the visual tree. Edit its attributes in Code mode." }) : fields.map((field) => {
|
|
4789
|
+
const value = element[field.key];
|
|
4790
|
+
const inputValue = value === void 0 ? "" : String(value);
|
|
4791
|
+
const inputId = `ssml-visual-${field.key}`;
|
|
4792
|
+
return /* @__PURE__ */ jsxs2("label", { htmlFor: inputId, children: [
|
|
4793
|
+
field.label,
|
|
4794
|
+
field.multiline ? /* @__PURE__ */ jsx6(
|
|
4795
|
+
"textarea",
|
|
4796
|
+
{
|
|
4797
|
+
id: inputId,
|
|
4798
|
+
value: inputValue,
|
|
4799
|
+
readOnly,
|
|
4800
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, path, field.key, event.target.value))
|
|
4801
|
+
}
|
|
4802
|
+
) : /* @__PURE__ */ jsx6(
|
|
4803
|
+
"input",
|
|
4804
|
+
{
|
|
4805
|
+
id: inputId,
|
|
4806
|
+
value: inputValue,
|
|
4807
|
+
readOnly,
|
|
4808
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, path, field.key, event.target.value))
|
|
4809
|
+
}
|
|
4810
|
+
)
|
|
4811
|
+
] }, field.key);
|
|
4812
|
+
})
|
|
4813
|
+
] });
|
|
4814
|
+
}
|
|
4815
|
+
function getElementAncestors(nodes, path, ancestors = []) {
|
|
4816
|
+
const [index, ...rest] = path;
|
|
4817
|
+
const node = nodes[index];
|
|
4818
|
+
if (!node || !isElement(node)) return ancestors;
|
|
4819
|
+
if (rest.length === 0) return ancestors;
|
|
4820
|
+
return getElementAncestors(node.children ?? [], rest, [...ancestors, node]);
|
|
4821
|
+
}
|
|
4822
|
+
function buildVisualPreview(document2, leaf, selection) {
|
|
4823
|
+
const start = Math.max(0, Math.min(selection.start, leaf.value.length));
|
|
4824
|
+
const end = Math.max(start, Math.min(selection.end, leaf.value.length));
|
|
4825
|
+
const value = start === end ? leaf.value : leaf.value.slice(start, end);
|
|
4826
|
+
const ancestors = getElementAncestors(document2.children ?? [], leaf.path);
|
|
4827
|
+
const children = ancestors.reduceRight(
|
|
4828
|
+
(current, ancestor) => [{ ...ancestor, children: current }],
|
|
4829
|
+
[value]
|
|
4830
|
+
);
|
|
4831
|
+
return buildSsml3({ ...document2, children });
|
|
4832
|
+
}
|
|
4698
4833
|
function addDialogTurn(document2, path) {
|
|
4699
4834
|
return updateElementAtPath(document2, path, (element) => ({
|
|
4700
4835
|
...element,
|
|
@@ -4892,7 +5027,16 @@ function VisualSsmlEditor({
|
|
|
4892
5027
|
}
|
|
4893
5028
|
)
|
|
4894
5029
|
] })
|
|
4895
|
-
] }) :
|
|
5030
|
+
] }) : selectedElement && isElement(selectedElement) ? /* @__PURE__ */ jsx6(
|
|
5031
|
+
VisualElementInspector,
|
|
5032
|
+
{
|
|
5033
|
+
document: document2,
|
|
5034
|
+
element: selectedElement,
|
|
5035
|
+
path: selectedPath ?? [],
|
|
5036
|
+
readOnly,
|
|
5037
|
+
commit
|
|
5038
|
+
}
|
|
5039
|
+
) : selectedLeaf ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
4896
5040
|
/* @__PURE__ */ jsxs2("label", { children: [
|
|
4897
5041
|
"Text",
|
|
4898
5042
|
/* @__PURE__ */ jsx6(
|
|
@@ -4932,7 +5076,7 @@ function VisualSsmlEditor({
|
|
|
4932
5076
|
"button",
|
|
4933
5077
|
{
|
|
4934
5078
|
type: "button",
|
|
4935
|
-
onClick: () => onPreviewSelection(
|
|
5079
|
+
onClick: () => onPreviewSelection(buildVisualPreview(document2, selectedLeaf, selection)),
|
|
4936
5080
|
children: "Preview selection"
|
|
4937
5081
|
}
|
|
4938
5082
|
)
|