@ssml-builder-js/ssml-editor-react 2.10.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 +17 -0
- package/dist/index.js +300 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +300 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/VisualSsmlEditor.tsx +324 -2
- package/src/constants/azureVoiceStyleMap.generated.ts +3 -0
- package/src/constants/ssmlPresets.ts +3 -2
- package/src/ssmlCompletion.ts +1 -1
- package/src/ssmlHover.ts +6 -6
- package/test/ui-components.test.tsx +140 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ssml-builder-js/ssml-editor-react
|
|
2
2
|
|
|
3
|
+
## 2.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add Visual Editor forms for the supported SSML and Azure extension elements and preserve parent context during selection preview.
|
|
8
|
+
|
|
9
|
+
## 2.11.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Release v2.11.0 with Azure voice catalog APIs and synchronization tools, expanded editor voice support, and stricter background audio validation.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @ssml-builder-js/ssml-core@2.11.0
|
|
19
|
+
|
|
3
20
|
## 2.10.0
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,7 @@ var ssmlPresets_exports = {};
|
|
|
57
57
|
__export(ssmlPresets_exports, {
|
|
58
58
|
AUDIO_DURATION_DESCRIPTIONS: () => AUDIO_DURATION_DESCRIPTIONS,
|
|
59
59
|
AUDIO_DURATION_PRESETS: () => AUDIO_DURATION_PRESETS,
|
|
60
|
+
BACKGROUND_AUDIO_DURATION_PRESETS: () => BACKGROUND_AUDIO_DURATION_PRESETS,
|
|
60
61
|
BREAK_STRENGTH_PRESETS: () => BREAK_STRENGTH_PRESETS,
|
|
61
62
|
BREAK_TIME_DESCRIPTIONS: () => BREAK_TIME_DESCRIPTIONS,
|
|
62
63
|
BREAK_TIME_PRESETS: () => BREAK_TIME_PRESETS,
|
|
@@ -138,6 +139,9 @@ var AZURE_VOICE_STYLE_MAP = {
|
|
|
138
139
|
],
|
|
139
140
|
"es-ES-ElviraNeural": [],
|
|
140
141
|
"fil-PH-AngeloNeural": [],
|
|
142
|
+
"fil-PH-Angelo:DragonHDLatestNeural": [],
|
|
143
|
+
"fil-PH-BlessicaNeural": [],
|
|
144
|
+
"fil-PH-Blessica:DragonHDLatestNeural": [],
|
|
141
145
|
"fr-FR-DeniseNeural": ["cheerful", "sad"],
|
|
142
146
|
"fr-FR-HenriNeural": ["cheerful", "sad"],
|
|
143
147
|
"id-ID-GadisNeural": [],
|
|
@@ -415,6 +419,7 @@ var SAY_AS_PRESETS = [
|
|
|
415
419
|
var LANGUAGE_PRESETS = ["ja-JP", "en-US", "de-DE", "fr-FR"];
|
|
416
420
|
var SILENCE_VALUE_PRESETS = ["300ms", "500ms", "1s"];
|
|
417
421
|
var AUDIO_DURATION_PRESETS = ["5s", "10s", "30s"];
|
|
422
|
+
var BACKGROUND_AUDIO_DURATION_PRESETS = ["0", "500", "1000", "3000", "10000"];
|
|
418
423
|
var SILENCE_TYPE_PRESETS = [
|
|
419
424
|
"Leading",
|
|
420
425
|
"Tailing",
|
|
@@ -476,8 +481,8 @@ var SSML_ATTRIBUTE_PRESETS = {
|
|
|
476
481
|
},
|
|
477
482
|
"mstts:backgroundaudio": {
|
|
478
483
|
volume: PROSODY_VOLUME_PRESETS,
|
|
479
|
-
fadein:
|
|
480
|
-
fadeout:
|
|
484
|
+
fadein: BACKGROUND_AUDIO_DURATION_PRESETS,
|
|
485
|
+
fadeout: BACKGROUND_AUDIO_DURATION_PRESETS
|
|
481
486
|
},
|
|
482
487
|
silence: {
|
|
483
488
|
type: SILENCE_TYPE_PRESETS,
|
|
@@ -3326,7 +3331,7 @@ var SSML_COMPLETION_SNIPPETS = [
|
|
|
3326
3331
|
},
|
|
3327
3332
|
{
|
|
3328
3333
|
label: "mstts:backgroundaudio",
|
|
3329
|
-
insertText: `<mstts:backgroundaudio src="\${1:https://example.com/audio.mp3}" volume="\${2
|
|
3334
|
+
insertText: `<mstts:backgroundaudio src="\${1:https://example.com/audio.mp3}" volume="\${2:70}" fadein="\${3:1000}" fadeout="\${4:1000}" />`
|
|
3330
3335
|
},
|
|
3331
3336
|
{
|
|
3332
3337
|
label: "mstts:ttsembedding",
|
|
@@ -4027,18 +4032,18 @@ var SSML_TAG_DEFINITIONS = [
|
|
|
4027
4032
|
},
|
|
4028
4033
|
{
|
|
4029
4034
|
name: "volume",
|
|
4030
|
-
description: "The background audio volume
|
|
4031
|
-
example: "
|
|
4035
|
+
description: "The background audio volume from 0 to 100.",
|
|
4036
|
+
example: "70"
|
|
4032
4037
|
},
|
|
4033
4038
|
{
|
|
4034
4039
|
name: "fadein",
|
|
4035
|
-
description: "The fade-in duration
|
|
4036
|
-
example: "
|
|
4040
|
+
description: "The fade-in duration in milliseconds from 0 to 10000.",
|
|
4041
|
+
example: "1000"
|
|
4037
4042
|
},
|
|
4038
4043
|
{
|
|
4039
4044
|
name: "fadeout",
|
|
4040
|
-
description: "The fade-out duration
|
|
4041
|
-
example: "
|
|
4045
|
+
description: "The fade-out duration in milliseconds from 0 to 10000.",
|
|
4046
|
+
example: "1000"
|
|
4042
4047
|
}
|
|
4043
4048
|
]
|
|
4044
4049
|
},
|
|
@@ -4694,6 +4699,181 @@ function updateNodesAtPath(nodes, path, update) {
|
|
|
4694
4699
|
function updateTextAtPath(document2, path, value) {
|
|
4695
4700
|
return { ...document2, children: updateNodesAtPath(document2.children ?? [], path, () => value) };
|
|
4696
4701
|
}
|
|
4702
|
+
function getNodeAtPath(nodes, path) {
|
|
4703
|
+
let current;
|
|
4704
|
+
let currentNodes = nodes;
|
|
4705
|
+
for (const index of path) {
|
|
4706
|
+
current = currentNodes[index];
|
|
4707
|
+
if (current === void 0) return void 0;
|
|
4708
|
+
if (!isElement(current)) {
|
|
4709
|
+
currentNodes = [];
|
|
4710
|
+
} else {
|
|
4711
|
+
currentNodes = current.children ?? [];
|
|
4712
|
+
}
|
|
4713
|
+
}
|
|
4714
|
+
return current;
|
|
4715
|
+
}
|
|
4716
|
+
function updateElementAtPath(document2, path, update) {
|
|
4717
|
+
return {
|
|
4718
|
+
...document2,
|
|
4719
|
+
children: updateNodesAtPath(document2.children ?? [], path, (node) => isElement(node) ? update(node) : node)
|
|
4720
|
+
};
|
|
4721
|
+
}
|
|
4722
|
+
function updateElementText(element, value) {
|
|
4723
|
+
return { ...element, children: [value] };
|
|
4724
|
+
}
|
|
4725
|
+
function updateOptionalElementProperty(document2, path, property, value) {
|
|
4726
|
+
return updateElementAtPath(document2, path, (element) => {
|
|
4727
|
+
const next = { ...element };
|
|
4728
|
+
if (value.trim()) next[property] = value;
|
|
4729
|
+
else delete next[property];
|
|
4730
|
+
return next;
|
|
4731
|
+
});
|
|
4732
|
+
}
|
|
4733
|
+
var VISUAL_ELEMENT_FIELDS = {
|
|
4734
|
+
voice: [
|
|
4735
|
+
{ key: "name", label: "Voice name" },
|
|
4736
|
+
{ key: "effect", label: "Effect" }
|
|
4737
|
+
],
|
|
4738
|
+
prosody: [
|
|
4739
|
+
{ key: "rate", label: "Rate" },
|
|
4740
|
+
{ key: "pitch", label: "Pitch" },
|
|
4741
|
+
{ key: "volume", label: "Volume" },
|
|
4742
|
+
{ key: "contour", label: "Contour" },
|
|
4743
|
+
{ key: "range", label: "Range" }
|
|
4744
|
+
],
|
|
4745
|
+
"express-as": [
|
|
4746
|
+
{ key: "style", label: "Style" },
|
|
4747
|
+
{ key: "styleDegree", label: "Style degree" },
|
|
4748
|
+
{ key: "role", label: "Role" }
|
|
4749
|
+
],
|
|
4750
|
+
expressAs: [
|
|
4751
|
+
{ key: "style", label: "Style" },
|
|
4752
|
+
{ key: "styleDegree", label: "Style degree" },
|
|
4753
|
+
{ key: "role", label: "Role" }
|
|
4754
|
+
],
|
|
4755
|
+
"mstts:express-as": [
|
|
4756
|
+
{ key: "style", label: "Style" },
|
|
4757
|
+
{ key: "styleDegree", label: "Style degree" },
|
|
4758
|
+
{ key: "role", label: "Role" }
|
|
4759
|
+
],
|
|
4760
|
+
"say-as": [
|
|
4761
|
+
{ key: "interpretAs", label: "Interpret as" },
|
|
4762
|
+
{ key: "format", label: "Format" },
|
|
4763
|
+
{ key: "detail", label: "Detail" }
|
|
4764
|
+
],
|
|
4765
|
+
sayAs: [
|
|
4766
|
+
{ key: "interpretAs", label: "Interpret as" },
|
|
4767
|
+
{ key: "format", label: "Format" },
|
|
4768
|
+
{ key: "detail", label: "Detail" }
|
|
4769
|
+
],
|
|
4770
|
+
phoneme: [
|
|
4771
|
+
{ key: "alphabet", label: "Alphabet" },
|
|
4772
|
+
{ key: "ph", label: "Pronunciation" }
|
|
4773
|
+
],
|
|
4774
|
+
emphasis: [{ key: "level", label: "Level" }],
|
|
4775
|
+
audio: [
|
|
4776
|
+
{ key: "src", label: "Source URL" },
|
|
4777
|
+
{ key: "desc", label: "Description" },
|
|
4778
|
+
{ key: "clipBegin", label: "Clip begin" },
|
|
4779
|
+
{ key: "clipEnd", label: "Clip end" },
|
|
4780
|
+
{ key: "speed", label: "Speed" },
|
|
4781
|
+
{ key: "repeatCount", label: "Repeat count" },
|
|
4782
|
+
{ key: "repeatDuration", label: "Repeat duration" },
|
|
4783
|
+
{ key: "soundLevel", label: "Sound level" }
|
|
4784
|
+
],
|
|
4785
|
+
mark: [{ key: "name", label: "Mark name" }],
|
|
4786
|
+
bookmark: [{ key: "mark", label: "Bookmark name" }],
|
|
4787
|
+
sub: [{ key: "alias", label: "Alias" }],
|
|
4788
|
+
lang: [{ key: "lang", label: "Language" }],
|
|
4789
|
+
lexicon: [{ key: "uri", label: "Lexicon URI" }],
|
|
4790
|
+
"mstts:silence": [
|
|
4791
|
+
{ key: "typeValue", label: "Silence type" },
|
|
4792
|
+
{ key: "value", label: "Value" }
|
|
4793
|
+
],
|
|
4794
|
+
silence: [
|
|
4795
|
+
{ key: "typeValue", label: "Silence type" },
|
|
4796
|
+
{ key: "value", label: "Value" }
|
|
4797
|
+
],
|
|
4798
|
+
"mstts:audioduration": [{ key: "value", label: "Duration" }],
|
|
4799
|
+
"mstts:ttsembedding": [{ key: "speakerProfileId", label: "Speaker profile ID" }],
|
|
4800
|
+
"mstts:embedding": [
|
|
4801
|
+
{ key: "id", label: "Embedding ID" },
|
|
4802
|
+
{ key: "speakerProfileId", label: "Speaker profile ID" }
|
|
4803
|
+
],
|
|
4804
|
+
"mstts:voiceconversion": [
|
|
4805
|
+
{ key: "url", label: "Source URL" },
|
|
4806
|
+
{ key: "profile", label: "Profile" },
|
|
4807
|
+
{ key: "speakerProfileId", label: "Speaker profile ID" }
|
|
4808
|
+
]
|
|
4809
|
+
};
|
|
4810
|
+
function getElementFields(element) {
|
|
4811
|
+
return VISUAL_ELEMENT_FIELDS[elementLabel(element)] ?? [];
|
|
4812
|
+
}
|
|
4813
|
+
function VisualElementInspector({
|
|
4814
|
+
document: document2,
|
|
4815
|
+
element,
|
|
4816
|
+
path,
|
|
4817
|
+
readOnly,
|
|
4818
|
+
commit
|
|
4819
|
+
}) {
|
|
4820
|
+
const fields = getElementFields(element);
|
|
4821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { children: [
|
|
4822
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: `<${elementLabel(element)}>` }),
|
|
4823
|
+
fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "This element is preserved in the visual tree. Edit its attributes in Code mode." }) : fields.map((field) => {
|
|
4824
|
+
const value = element[field.key];
|
|
4825
|
+
const inputValue = value === void 0 ? "" : String(value);
|
|
4826
|
+
const inputId = `ssml-visual-${field.key}`;
|
|
4827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { htmlFor: inputId, children: [
|
|
4828
|
+
field.label,
|
|
4829
|
+
field.multiline ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4830
|
+
"textarea",
|
|
4831
|
+
{
|
|
4832
|
+
id: inputId,
|
|
4833
|
+
value: inputValue,
|
|
4834
|
+
readOnly,
|
|
4835
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, path, field.key, event.target.value))
|
|
4836
|
+
}
|
|
4837
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4838
|
+
"input",
|
|
4839
|
+
{
|
|
4840
|
+
id: inputId,
|
|
4841
|
+
value: inputValue,
|
|
4842
|
+
readOnly,
|
|
4843
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, path, field.key, event.target.value))
|
|
4844
|
+
}
|
|
4845
|
+
)
|
|
4846
|
+
] }, field.key);
|
|
4847
|
+
})
|
|
4848
|
+
] });
|
|
4849
|
+
}
|
|
4850
|
+
function getElementAncestors(nodes, path, ancestors = []) {
|
|
4851
|
+
const [index, ...rest] = path;
|
|
4852
|
+
const node = nodes[index];
|
|
4853
|
+
if (!node || !isElement(node)) return ancestors;
|
|
4854
|
+
if (rest.length === 0) return ancestors;
|
|
4855
|
+
return getElementAncestors(node.children ?? [], rest, [...ancestors, node]);
|
|
4856
|
+
}
|
|
4857
|
+
function buildVisualPreview(document2, leaf, selection) {
|
|
4858
|
+
const start = Math.max(0, Math.min(selection.start, leaf.value.length));
|
|
4859
|
+
const end = Math.max(start, Math.min(selection.end, leaf.value.length));
|
|
4860
|
+
const value = start === end ? leaf.value : leaf.value.slice(start, end);
|
|
4861
|
+
const ancestors = getElementAncestors(document2.children ?? [], leaf.path);
|
|
4862
|
+
const children = ancestors.reduceRight(
|
|
4863
|
+
(current, ancestor) => [{ ...ancestor, children: current }],
|
|
4864
|
+
[value]
|
|
4865
|
+
);
|
|
4866
|
+
return (0, import_ssml_core4.buildSsml)({ ...document2, children });
|
|
4867
|
+
}
|
|
4868
|
+
function addDialogTurn(document2, path) {
|
|
4869
|
+
return updateElementAtPath(document2, path, (element) => ({
|
|
4870
|
+
...element,
|
|
4871
|
+
children: [
|
|
4872
|
+
...element.children ?? [],
|
|
4873
|
+
{ type: "mstts:turn", voice: "en-US-JennyNeural", children: ["New dialog turn"] }
|
|
4874
|
+
]
|
|
4875
|
+
}));
|
|
4876
|
+
}
|
|
4697
4877
|
function wrapTextAtPath(document2, path, start, end, tag, attributes) {
|
|
4698
4878
|
return {
|
|
4699
4879
|
...document2,
|
|
@@ -4748,6 +4928,7 @@ function VisualSsmlEditor({
|
|
|
4748
4928
|
const [selection, setSelection] = (0, import_react3.useState)({ start: 0, end: 0 });
|
|
4749
4929
|
const textLeaves = (0, import_react3.useMemo)(() => collectTextLeaves(document2.children ?? []), [document2]);
|
|
4750
4930
|
const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
|
|
4931
|
+
const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
|
|
4751
4932
|
const diagnostics = (0, import_react3.useMemo)(() => (0, import_ssml_core4.validateAzureSsml)((0, import_ssml_core4.buildSsml)(document2)), [document2]);
|
|
4752
4933
|
const commit = (nextDocument) => onChange?.(nextDocument);
|
|
4753
4934
|
const applyWrapper = (tag, attributes) => {
|
|
@@ -4782,7 +4963,115 @@ function VisualSsmlEditor({
|
|
|
4782
4963
|
isElement(node) ? elementLabel(node) : JSON.stringify(node)
|
|
4783
4964
|
)) })
|
|
4784
4965
|
] }),
|
|
4785
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ssml-editor-visual-form", children:
|
|
4966
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ssml-editor-visual-form", children: selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { children: [
|
|
4967
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: "Dialog" }),
|
|
4968
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "Add and edit speaker turns in this dialog." }),
|
|
4969
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4970
|
+
"button",
|
|
4971
|
+
{
|
|
4972
|
+
type: "button",
|
|
4973
|
+
disabled: readOnly,
|
|
4974
|
+
onClick: () => commit(addDialogTurn(document2, selectedPath ?? [])),
|
|
4975
|
+
children: "Add turn"
|
|
4976
|
+
}
|
|
4977
|
+
)
|
|
4978
|
+
] }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { children: [
|
|
4979
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: "Dialog turn" }),
|
|
4980
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
4981
|
+
"Voice",
|
|
4982
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4983
|
+
"input",
|
|
4984
|
+
{
|
|
4985
|
+
value: selectedElement.voice ?? "",
|
|
4986
|
+
readOnly,
|
|
4987
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", event.target.value))
|
|
4988
|
+
}
|
|
4989
|
+
)
|
|
4990
|
+
] }),
|
|
4991
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
4992
|
+
"Speaker",
|
|
4993
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4994
|
+
"input",
|
|
4995
|
+
{
|
|
4996
|
+
value: selectedElement.speaker ?? "",
|
|
4997
|
+
readOnly,
|
|
4998
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "speaker", event.target.value))
|
|
4999
|
+
}
|
|
5000
|
+
)
|
|
5001
|
+
] }),
|
|
5002
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
5003
|
+
"Turn text",
|
|
5004
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5005
|
+
"textarea",
|
|
5006
|
+
{
|
|
5007
|
+
value: selectedElement.children?.filter((child) => typeof child === "string").join("") ?? "",
|
|
5008
|
+
readOnly,
|
|
5009
|
+
onChange: (event) => commit(
|
|
5010
|
+
updateElementAtPath(
|
|
5011
|
+
document2,
|
|
5012
|
+
selectedPath ?? [],
|
|
5013
|
+
(element) => updateElementText(element, event.target.value)
|
|
5014
|
+
)
|
|
5015
|
+
)
|
|
5016
|
+
}
|
|
5017
|
+
)
|
|
5018
|
+
] })
|
|
5019
|
+
] }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:backgroundaudio" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { children: [
|
|
5020
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: "Background audio" }),
|
|
5021
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
5022
|
+
"Source URL",
|
|
5023
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5024
|
+
"input",
|
|
5025
|
+
{
|
|
5026
|
+
value: selectedElement.src ?? "",
|
|
5027
|
+
readOnly,
|
|
5028
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "src", event.target.value))
|
|
5029
|
+
}
|
|
5030
|
+
)
|
|
5031
|
+
] }),
|
|
5032
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
5033
|
+
"Volume",
|
|
5034
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5035
|
+
"input",
|
|
5036
|
+
{
|
|
5037
|
+
value: selectedElement.volume === void 0 ? "" : String(selectedElement.volume),
|
|
5038
|
+
readOnly,
|
|
5039
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "volume", event.target.value))
|
|
5040
|
+
}
|
|
5041
|
+
)
|
|
5042
|
+
] }),
|
|
5043
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
5044
|
+
"Fade in",
|
|
5045
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5046
|
+
"input",
|
|
5047
|
+
{
|
|
5048
|
+
value: selectedElement.fadeIn === void 0 ? "" : String(selectedElement.fadeIn),
|
|
5049
|
+
readOnly,
|
|
5050
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "fadeIn", event.target.value))
|
|
5051
|
+
}
|
|
5052
|
+
)
|
|
5053
|
+
] }),
|
|
5054
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
5055
|
+
"Fade out",
|
|
5056
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5057
|
+
"input",
|
|
5058
|
+
{
|
|
5059
|
+
value: selectedElement.fadeOut === void 0 ? "" : String(selectedElement.fadeOut),
|
|
5060
|
+
readOnly,
|
|
5061
|
+
onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "fadeOut", event.target.value))
|
|
5062
|
+
}
|
|
5063
|
+
)
|
|
5064
|
+
] })
|
|
5065
|
+
] }) : selectedElement && isElement(selectedElement) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5066
|
+
VisualElementInspector,
|
|
5067
|
+
{
|
|
5068
|
+
document: document2,
|
|
5069
|
+
element: selectedElement,
|
|
5070
|
+
path: selectedPath ?? [],
|
|
5071
|
+
readOnly,
|
|
5072
|
+
commit
|
|
5073
|
+
}
|
|
5074
|
+
) : selectedLeaf ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
4786
5075
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
|
|
4787
5076
|
"Text",
|
|
4788
5077
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -4822,7 +5111,7 @@ function VisualSsmlEditor({
|
|
|
4822
5111
|
"button",
|
|
4823
5112
|
{
|
|
4824
5113
|
type: "button",
|
|
4825
|
-
onClick: () => onPreviewSelection((
|
|
5114
|
+
onClick: () => onPreviewSelection(buildVisualPreview(document2, selectedLeaf, selection)),
|
|
4826
5115
|
children: "Preview selection"
|
|
4827
5116
|
}
|
|
4828
5117
|
)
|