ssml-builder-js 2.8.0 → 2.9.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 +95 -17
- package/dist/{chunk-TKD3PU5Y.mjs → chunk-7LCSH4SZ.mjs} +610 -124
- package/dist/chunk-7LCSH4SZ.mjs.map +1 -0
- package/dist/{chunk-4RQETJUI.mjs → chunk-JNJVTEL6.mjs} +939 -10
- package/dist/chunk-JNJVTEL6.mjs.map +1 -0
- package/dist/core.d.mts +97 -3
- package/dist/core.d.ts +97 -3
- package/dist/core.js +616 -124
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +15 -3
- package/dist/elements.d.mts +10 -1
- package/dist/elements.d.ts +10 -1
- package/dist/elements.js +1245 -15
- package/dist/elements.js.map +1 -1
- package/dist/elements.mjs +316 -9
- package/dist/elements.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +616 -124
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -3
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +47 -6
- package/dist/react.d.ts +47 -6
- package/dist/react.js +1219 -25
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +280 -10
- package/dist/react.mjs.map +1 -1
- package/package.json +4 -3
- package/dist/chunk-4RQETJUI.mjs.map +0 -1
- package/dist/chunk-TKD3PU5Y.mjs.map +0 -1
package/dist/react.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
|
+
AUDIO_DURATION_DESCRIPTIONS,
|
|
4
|
+
AUDIO_DURATION_PRESETS,
|
|
3
5
|
BREAK_TIME_DESCRIPTIONS,
|
|
4
6
|
BREAK_TIME_PRESETS,
|
|
5
7
|
DEFAULT_LOCALE,
|
|
@@ -41,12 +43,13 @@ import {
|
|
|
41
43
|
resolveExpressAsStyles,
|
|
42
44
|
updateEditableText,
|
|
43
45
|
updateTagAttribute,
|
|
46
|
+
validateAzureSsml,
|
|
44
47
|
validateSsml
|
|
45
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-JNJVTEL6.mjs";
|
|
46
49
|
import "./chunk-6S5ODO6A.mjs";
|
|
47
50
|
|
|
48
51
|
// packages/ssml-editor-react/src/SsmlEditor.tsx
|
|
49
|
-
import { Fragment, forwardRef, useImperativeHandle } from "react";
|
|
52
|
+
import { Fragment, forwardRef, useEffect as useEffect3, useImperativeHandle, useState as useState3 } from "react";
|
|
50
53
|
import Editor from "@monaco-editor/react";
|
|
51
54
|
|
|
52
55
|
// packages/ssml-editor-react/src/buttonVisibility.ts
|
|
@@ -139,6 +142,14 @@ var editorStyles = {
|
|
|
139
142
|
display: "grid",
|
|
140
143
|
gap: "0.5rem"
|
|
141
144
|
},
|
|
145
|
+
visual: {
|
|
146
|
+
display: "grid",
|
|
147
|
+
gap: "0.75rem",
|
|
148
|
+
minHeight: "8rem",
|
|
149
|
+
padding: "0.75rem",
|
|
150
|
+
border: "1px solid var(--ssml-editor-control-border)",
|
|
151
|
+
borderRadius: "0.25rem"
|
|
152
|
+
},
|
|
142
153
|
toolbarIconOnly: {
|
|
143
154
|
justifyContent: "center",
|
|
144
155
|
minWidth: "2.25rem",
|
|
@@ -503,7 +514,7 @@ function TimingPopovers(props) {
|
|
|
503
514
|
|
|
504
515
|
// packages/ssml-editor-react/src/hooks/useSsmlEditorState.ts
|
|
505
516
|
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
506
|
-
var TIMING_INSERTION_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence"]);
|
|
517
|
+
var TIMING_INSERTION_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence", "mstts:audioduration"]);
|
|
507
518
|
var PROSODY_INSERTION_TAGS = /* @__PURE__ */ new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
|
|
508
519
|
var TEXT_INSERTION_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w", "lang"]);
|
|
509
520
|
var EMPTY_SELECTION_OVERLAY = {
|
|
@@ -1407,7 +1418,7 @@ function registerSsmlCodeLens(monaco, editor, onOpenPopover) {
|
|
|
1407
1418
|
break;
|
|
1408
1419
|
}
|
|
1409
1420
|
const tag = source.slice(tagStart, tagEnd + 1);
|
|
1410
|
-
const tagName = tag.match(/^<\s*(prosody|break)\b/i)?.[1]?.toLowerCase();
|
|
1421
|
+
const tagName = tag.match(/^<\s*(prosody|break|mstts:audioduration)\b/i)?.[1]?.toLowerCase();
|
|
1411
1422
|
index = tagEnd + 1;
|
|
1412
1423
|
if (!tagName) {
|
|
1413
1424
|
continue;
|
|
@@ -1437,7 +1448,22 @@ function registerSsmlCodeLens(monaco, editor, onOpenPopover) {
|
|
|
1437
1448
|
elementRange
|
|
1438
1449
|
})
|
|
1439
1450
|
);
|
|
1440
|
-
} else if (/\/\s*>$/.test(tag)) {
|
|
1451
|
+
} else if (tagName === "mstts:audioduration" && /\/\s*>$/.test(tag)) {
|
|
1452
|
+
lenses.push(
|
|
1453
|
+
createLens(
|
|
1454
|
+
model,
|
|
1455
|
+
tagStart,
|
|
1456
|
+
tagEnd + 1,
|
|
1457
|
+
`\u26A1 Duration: ${getAttributeValue(tag, "value") ?? "default"} (Click to edit)`,
|
|
1458
|
+
{ type: "attribute", insertionId: "mstts:audioduration", attributeName: "value", tagRange }
|
|
1459
|
+
),
|
|
1460
|
+
createLens(model, tagStart, tagEnd + 1, "Delete", {
|
|
1461
|
+
type: "delete",
|
|
1462
|
+
tagRange,
|
|
1463
|
+
elementRange
|
|
1464
|
+
})
|
|
1465
|
+
);
|
|
1466
|
+
} else if (tagName === "break" && /\/\s*>$/.test(tag)) {
|
|
1441
1467
|
lenses.push(
|
|
1442
1468
|
createLens(
|
|
1443
1469
|
model,
|
|
@@ -1782,9 +1808,143 @@ function useSsmlMonaco({
|
|
|
1782
1808
|
return { editorRef, onMount };
|
|
1783
1809
|
}
|
|
1784
1810
|
|
|
1811
|
+
// packages/ssml-editor-react/src/components/VisualSsmlEditor.tsx
|
|
1812
|
+
import { useMemo, useState as useState2 } from "react";
|
|
1813
|
+
function isElement(node) {
|
|
1814
|
+
return typeof node !== "string" && node.type !== "text";
|
|
1815
|
+
}
|
|
1816
|
+
function elementLabel(element) {
|
|
1817
|
+
return element.type === "custom" || element.type === "element" ? element.name : element.type;
|
|
1818
|
+
}
|
|
1819
|
+
function collectTextLeaves(nodes, path = [], ancestors = []) {
|
|
1820
|
+
return nodes.flatMap((node, index) => {
|
|
1821
|
+
const currentPath = [...path, index];
|
|
1822
|
+
if (typeof node === "string") return [{ ancestors, path: currentPath, value: node }];
|
|
1823
|
+
if (node.type === "text") return [{ ancestors, path: currentPath, value: node.value }];
|
|
1824
|
+
return collectTextLeaves(node.children ?? [], currentPath, [...ancestors, elementLabel(node)]);
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
function updateNodesAtPath(nodes, path, update) {
|
|
1828
|
+
if (path.length === 0) return nodes;
|
|
1829
|
+
const [index, ...rest] = path;
|
|
1830
|
+
return nodes.flatMap((node, nodeIndex) => {
|
|
1831
|
+
if (nodeIndex !== index) return [node];
|
|
1832
|
+
if (rest.length === 0) {
|
|
1833
|
+
const next = update(node);
|
|
1834
|
+
return Array.isArray(next) ? next : [next];
|
|
1835
|
+
}
|
|
1836
|
+
if (!isElement(node)) return [node];
|
|
1837
|
+
return [{ ...node, children: updateNodesAtPath(node.children ?? [], rest, update) }];
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
function updateTextAtPath(document2, path, value) {
|
|
1841
|
+
return { ...document2, children: updateNodesAtPath(document2.children ?? [], path, () => value) };
|
|
1842
|
+
}
|
|
1843
|
+
function wrapTextAtPath(document2, path, start, end, tag, attributes) {
|
|
1844
|
+
return {
|
|
1845
|
+
...document2,
|
|
1846
|
+
children: updateNodesAtPath(document2.children ?? [], path, (node) => {
|
|
1847
|
+
const value = typeof node === "string" ? node : node.type === "text" ? node.value : "";
|
|
1848
|
+
if (!value || start === end) return node;
|
|
1849
|
+
if (tag === "break") {
|
|
1850
|
+
return [
|
|
1851
|
+
value.slice(0, start),
|
|
1852
|
+
{ type: tag, attributes, children: [] },
|
|
1853
|
+
value.slice(start)
|
|
1854
|
+
].filter((part) => typeof part === "string" ? part.length > 0 : true);
|
|
1855
|
+
}
|
|
1856
|
+
const selected = value.slice(start, end);
|
|
1857
|
+
const wrapped = { type: tag, attributes, children: [selected] };
|
|
1858
|
+
return [value.slice(0, start), wrapped, value.slice(end)].filter(
|
|
1859
|
+
(part) => typeof part === "string" ? part.length > 0 : true
|
|
1860
|
+
);
|
|
1861
|
+
})
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
function TreeNode({
|
|
1865
|
+
node,
|
|
1866
|
+
path,
|
|
1867
|
+
selectedPath,
|
|
1868
|
+
onSelect
|
|
1869
|
+
}) {
|
|
1870
|
+
if (!isElement(node)) return null;
|
|
1871
|
+
const name = elementLabel(node);
|
|
1872
|
+
const isSelected = selectedPath?.join(".") === path.join(".");
|
|
1873
|
+
return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("button", { type: "button", "aria-current": isSelected ? "true" : void 0, onClick: () => onSelect(path) }, `<${name}>`), (node.children ?? []).length > 0 && /* @__PURE__ */ React.createElement("ul", null, node.children?.map((child, index) => /* @__PURE__ */ React.createElement(
|
|
1874
|
+
TreeNode,
|
|
1875
|
+
{
|
|
1876
|
+
key: `${path.join(".")}/${isElement(child) ? elementLabel(child) : JSON.stringify(child)}`,
|
|
1877
|
+
node: child,
|
|
1878
|
+
path: [...path, index],
|
|
1879
|
+
selectedPath,
|
|
1880
|
+
onSelect
|
|
1881
|
+
}
|
|
1882
|
+
))));
|
|
1883
|
+
}
|
|
1884
|
+
function VisualSsmlEditor({
|
|
1885
|
+
document: document2,
|
|
1886
|
+
readOnly = false,
|
|
1887
|
+
onChange,
|
|
1888
|
+
onPreviewSelection
|
|
1889
|
+
}) {
|
|
1890
|
+
const [selectedPath, setSelectedPath] = useState2(null);
|
|
1891
|
+
const [selection, setSelection] = useState2({ start: 0, end: 0 });
|
|
1892
|
+
const textLeaves = useMemo(() => collectTextLeaves(document2.children ?? []), [document2]);
|
|
1893
|
+
const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
|
|
1894
|
+
const diagnostics = useMemo(() => validateAzureSsml(buildSsml(document2)), [document2]);
|
|
1895
|
+
const commit = (nextDocument) => onChange?.(nextDocument);
|
|
1896
|
+
const applyWrapper = (tag, attributes) => {
|
|
1897
|
+
if (readOnly || !selectedLeaf) return;
|
|
1898
|
+
const start = selection.start === selection.end ? 0 : selection.start;
|
|
1899
|
+
const end = selection.start === selection.end ? selectedLeaf.value.length : selection.end;
|
|
1900
|
+
commit(wrapTextAtPath(document2, selectedLeaf.path, start, end, tag, attributes));
|
|
1901
|
+
};
|
|
1902
|
+
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(
|
|
1903
|
+
TreeNode,
|
|
1904
|
+
{
|
|
1905
|
+
key: isElement(node) ? elementLabel(node) : JSON.stringify(node),
|
|
1906
|
+
node,
|
|
1907
|
+
path: [index],
|
|
1908
|
+
selectedPath,
|
|
1909
|
+
onSelect: setSelectedPath
|
|
1910
|
+
}
|
|
1911
|
+
)))), /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual-form" }, selectedLeaf ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", null, "Text", /* @__PURE__ */ React.createElement(
|
|
1912
|
+
"textarea",
|
|
1913
|
+
{
|
|
1914
|
+
value: selectedLeaf.value,
|
|
1915
|
+
readOnly,
|
|
1916
|
+
onSelect: (event) => setSelection({ start: event.currentTarget.selectionStart, end: event.currentTarget.selectionEnd }),
|
|
1917
|
+
onChange: (event) => commit(updateTextAtPath(document2, selectedLeaf.path, event.target.value))
|
|
1918
|
+
}
|
|
1919
|
+
)), /* @__PURE__ */ React.createElement("fieldset", { className: "ssml-editor-visual-actions" }, /* @__PURE__ */ React.createElement("legend", null, "Apply SSML formatting"), /* @__PURE__ */ React.createElement("button", { type: "button", disabled: readOnly, onClick: () => applyWrapper("prosody", { rate: "slow" }) }, "Rate"), /* @__PURE__ */ React.createElement("button", { type: "button", disabled: readOnly, onClick: () => applyWrapper("prosody", { pitch: "high" }) }, "Pitch"), /* @__PURE__ */ React.createElement(
|
|
1920
|
+
"button",
|
|
1921
|
+
{
|
|
1922
|
+
type: "button",
|
|
1923
|
+
disabled: readOnly,
|
|
1924
|
+
onClick: () => applyWrapper("mstts:express-as", { style: "cheerful" })
|
|
1925
|
+
},
|
|
1926
|
+
"Emotion"
|
|
1927
|
+
), /* @__PURE__ */ React.createElement("button", { type: "button", disabled: readOnly, onClick: () => applyWrapper("break", { time: "500ms" }) }, "Pause"), /* @__PURE__ */ React.createElement(
|
|
1928
|
+
"button",
|
|
1929
|
+
{
|
|
1930
|
+
type: "button",
|
|
1931
|
+
disabled: readOnly,
|
|
1932
|
+
onClick: () => applyWrapper("phoneme", { alphabet: "ipa", ph: selectedLeaf.value })
|
|
1933
|
+
},
|
|
1934
|
+
"Pronunciation"
|
|
1935
|
+
), onPreviewSelection && /* @__PURE__ */ React.createElement(
|
|
1936
|
+
"button",
|
|
1937
|
+
{
|
|
1938
|
+
type: "button",
|
|
1939
|
+
onClick: () => onPreviewSelection(buildSsml({ ...document2, children: [selectedLeaf.value] }))
|
|
1940
|
+
},
|
|
1941
|
+
"Preview selection"
|
|
1942
|
+
))) : /* @__PURE__ */ React.createElement("p", null, "Select an element or text node to edit it."))));
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1785
1945
|
// packages/ssml-editor-react/src/SsmlEditor.tsx
|
|
1786
1946
|
var UNGROUPED_TOOLBAR_GROUP = "__ssml-editor-ungrouped__";
|
|
1787
|
-
var TIMING_POPOVER_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence"]);
|
|
1947
|
+
var TIMING_POPOVER_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence", "mstts:audioduration"]);
|
|
1788
1948
|
var PROSODY_POPOVER_TAGS = /* @__PURE__ */ new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
|
|
1789
1949
|
var TEXT_POPOVER_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w", "lang"]);
|
|
1790
1950
|
function localizedText(value) {
|
|
@@ -2012,13 +2172,34 @@ var SSML_INSERTIONS = [
|
|
|
2012
2172
|
suffix: "",
|
|
2013
2173
|
mode: "insert"
|
|
2014
2174
|
})
|
|
2175
|
+
},
|
|
2176
|
+
{
|
|
2177
|
+
id: "mstts:audioduration",
|
|
2178
|
+
icon: "\u25F7",
|
|
2179
|
+
tagName: "mstts:audioduration",
|
|
2180
|
+
selfClosing: true,
|
|
2181
|
+
labels: { ja: "\u97F3\u58F0\u9577", en: "Audio duration" },
|
|
2182
|
+
descriptions: {
|
|
2183
|
+
ja: "\u5408\u6210\u97F3\u58F0\u306E\u76EE\u6A19\u6642\u9593\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
|
|
2184
|
+
en: "Sets the target duration of synthesized audio."
|
|
2185
|
+
},
|
|
2186
|
+
parameterDescription: {
|
|
2187
|
+
ja: "\u76EE\u6A19\u6642\u9593\u3092\u9078\u629E\u3057\u307E\u3059\u3002",
|
|
2188
|
+
en: "Selects the target duration."
|
|
2189
|
+
},
|
|
2190
|
+
options: createInsertionOptions(AUDIO_DURATION_PRESETS, AUDIO_DURATION_DESCRIPTIONS),
|
|
2191
|
+
createTemplate: (value) => ({
|
|
2192
|
+
prefix: `<mstts:audioduration value="${value}"/>`,
|
|
2193
|
+
suffix: "",
|
|
2194
|
+
mode: "insert"
|
|
2195
|
+
})
|
|
2015
2196
|
}
|
|
2016
2197
|
];
|
|
2017
2198
|
var DEFAULT_INSERTION_GROUPS = [
|
|
2018
2199
|
{
|
|
2019
2200
|
id: "pauses",
|
|
2020
2201
|
labels: { ja: "\u9593\u30FB\u7121\u97F3", en: "Pauses" },
|
|
2021
|
-
insertionIds: ["break", "mstts:silence"]
|
|
2202
|
+
insertionIds: ["break", "mstts:silence", "mstts:audioduration"]
|
|
2022
2203
|
},
|
|
2023
2204
|
{
|
|
2024
2205
|
id: "prosody",
|
|
@@ -2227,6 +2408,60 @@ var STYLE_CSS = `
|
|
|
2227
2408
|
> .ssml-editor-help-settings-summary::before {
|
|
2228
2409
|
content: "\u25BE";
|
|
2229
2410
|
}
|
|
2411
|
+
[data-ssml-editor] .ssml-editor-visual-layout {
|
|
2412
|
+
display: grid;
|
|
2413
|
+
grid-template-columns: minmax(12rem, 0.35fr) minmax(16rem, 1fr);
|
|
2414
|
+
gap: 1rem;
|
|
2415
|
+
}
|
|
2416
|
+
[data-ssml-editor] .ssml-editor-visual-tree,
|
|
2417
|
+
[data-ssml-editor] .ssml-editor-visual-form {
|
|
2418
|
+
display: grid;
|
|
2419
|
+
gap: 0.5rem;
|
|
2420
|
+
align-content: start;
|
|
2421
|
+
}
|
|
2422
|
+
[data-ssml-editor] .ssml-editor-visual-tree ul {
|
|
2423
|
+
margin: 0;
|
|
2424
|
+
padding-left: 1.25rem;
|
|
2425
|
+
}
|
|
2426
|
+
[data-ssml-editor] .ssml-editor-visual-tree button,
|
|
2427
|
+
[data-ssml-editor] .ssml-editor-visual-breadcrumb button,
|
|
2428
|
+
[data-ssml-editor] .ssml-editor-visual-actions button {
|
|
2429
|
+
padding: 0.35rem 0.5rem;
|
|
2430
|
+
border: 1px solid var(--ssml-editor-control-border);
|
|
2431
|
+
border-radius: 0.25rem;
|
|
2432
|
+
color: var(--ssml-editor-color);
|
|
2433
|
+
background: var(--ssml-editor-control-bg);
|
|
2434
|
+
cursor: pointer;
|
|
2435
|
+
}
|
|
2436
|
+
[data-ssml-editor] .ssml-editor-visual-tree button[aria-current] {
|
|
2437
|
+
border-color: var(--ssml-editor-active-border);
|
|
2438
|
+
background: var(--ssml-editor-active-bg);
|
|
2439
|
+
}
|
|
2440
|
+
[data-ssml-editor] .ssml-editor-visual-breadcrumb,
|
|
2441
|
+
[data-ssml-editor] .ssml-editor-visual-actions {
|
|
2442
|
+
display: flex;
|
|
2443
|
+
flex-wrap: wrap;
|
|
2444
|
+
gap: 0.4rem;
|
|
2445
|
+
align-items: center;
|
|
2446
|
+
}
|
|
2447
|
+
[data-ssml-editor] .ssml-editor-visual-form textarea {
|
|
2448
|
+
box-sizing: border-box;
|
|
2449
|
+
width: 100%;
|
|
2450
|
+
min-height: 6rem;
|
|
2451
|
+
padding: 0.5rem;
|
|
2452
|
+
color: var(--ssml-editor-color);
|
|
2453
|
+
background: var(--ssml-editor-control-bg);
|
|
2454
|
+
border: 1px solid var(--ssml-editor-control-border);
|
|
2455
|
+
border-radius: 0.25rem;
|
|
2456
|
+
font: inherit;
|
|
2457
|
+
}
|
|
2458
|
+
[data-ssml-editor] .ssml-editor-visual-errors {
|
|
2459
|
+
padding: 0.5rem;
|
|
2460
|
+
color: var(--ssml-editor-error);
|
|
2461
|
+
background: var(--ssml-editor-error-bg);
|
|
2462
|
+
border: 1px solid var(--ssml-editor-error);
|
|
2463
|
+
border-radius: 0.25rem;
|
|
2464
|
+
}
|
|
2230
2465
|
`.trim();
|
|
2231
2466
|
function injectEditorTheme() {
|
|
2232
2467
|
if (typeof document !== "undefined" && !document.getElementById(STYLE_ID)) {
|
|
@@ -2296,8 +2531,11 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
2296
2531
|
toolbarStyle,
|
|
2297
2532
|
displayClassName,
|
|
2298
2533
|
displayStyle,
|
|
2299
|
-
loadingFallback
|
|
2534
|
+
loadingFallback,
|
|
2535
|
+
editMode: editModeProp = "code"
|
|
2300
2536
|
}, ref) {
|
|
2537
|
+
const [editMode, setEditMode] = useState3(editModeProp);
|
|
2538
|
+
useEffect3(() => setEditMode(editModeProp), [editModeProp]);
|
|
2301
2539
|
const resolvedEditorOptions = {
|
|
2302
2540
|
...settings,
|
|
2303
2541
|
...editorOptions,
|
|
@@ -2375,6 +2613,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
2375
2613
|
);
|
|
2376
2614
|
const {
|
|
2377
2615
|
editorRef,
|
|
2616
|
+
draftDocument,
|
|
2378
2617
|
text,
|
|
2379
2618
|
selectionOverlay,
|
|
2380
2619
|
activeTags,
|
|
@@ -2386,6 +2625,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
2386
2625
|
syntaxError,
|
|
2387
2626
|
setSyntaxError,
|
|
2388
2627
|
helpPanelId,
|
|
2628
|
+
commit,
|
|
2389
2629
|
handleTextChange,
|
|
2390
2630
|
handleInsert,
|
|
2391
2631
|
handleInsertBreak,
|
|
@@ -2645,10 +2885,39 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
2645
2885
|
"aria-label": copy.toolbarAriaLabel,
|
|
2646
2886
|
"data-ssml-editor-toolbar-actions": ""
|
|
2647
2887
|
},
|
|
2648
|
-
renderToolbarItems()
|
|
2888
|
+
renderToolbarItems(),
|
|
2889
|
+
/* @__PURE__ */ React.createElement("span", { style: editorStyles.toolbarSeparator, "aria-hidden": "true" }),
|
|
2890
|
+
/* @__PURE__ */ React.createElement(
|
|
2891
|
+
"button",
|
|
2892
|
+
{
|
|
2893
|
+
type: "button",
|
|
2894
|
+
style: editMode === "visual" ? { ...toolbarButtonStyle, ...editorStyles.toolbarButtonActive } : toolbarButtonStyle,
|
|
2895
|
+
"aria-pressed": editMode === "visual",
|
|
2896
|
+
onClick: () => setEditMode("visual")
|
|
2897
|
+
},
|
|
2898
|
+
"Visual"
|
|
2899
|
+
),
|
|
2900
|
+
/* @__PURE__ */ React.createElement(
|
|
2901
|
+
"button",
|
|
2902
|
+
{
|
|
2903
|
+
type: "button",
|
|
2904
|
+
style: editMode === "code" ? { ...toolbarButtonStyle, ...editorStyles.toolbarButtonActive } : toolbarButtonStyle,
|
|
2905
|
+
"aria-pressed": editMode === "code",
|
|
2906
|
+
onClick: () => setEditMode("code")
|
|
2907
|
+
},
|
|
2908
|
+
"Code"
|
|
2909
|
+
)
|
|
2649
2910
|
)
|
|
2650
2911
|
),
|
|
2651
|
-
/* @__PURE__ */ React.createElement("div", { className: displayClassName, style: { ...editorStyles.display, ...displayStyle }, "data-ssml-editor-display": "" }, isHelpOpen && isSsmlEditorButtonVisible(buttonVisibility, "help") && /* @__PURE__ */ React.createElement("section", { id: helpPanelId, style: editorStyles.helpPanel, "aria-label": copy.helpHeading }, /* @__PURE__ */ React.createElement("h3", { style: editorStyles.helpHeading }, copy.helpHeading), /* @__PURE__ */ React.createElement("p", { style: editorStyles.helpDescription }, copy.helpDescription), helpInsertions.length > 0 && /* @__PURE__ */ React.createElement("ul", { style: editorStyles.helpList }, helpInsertions.map((insertion) => /* @__PURE__ */ React.createElement("li", { key: insertion.id, style: editorStyles.helpItem }, /* @__PURE__ */ React.createElement("details", { className: "ssml-editor-help-settings-accordion", style: editorStyles.helpSettingsAccordion }, /* @__PURE__ */ React.createElement("summary", { className: "ssml-editor-help-settings-summary", style: editorStyles.helpSettingsSummary }, /* @__PURE__ */ React.createElement("span", { style: editorStyles.helpIcon, "aria-hidden": "true" }, insertion.icon), /* @__PURE__ */ React.createElement("span", { style: editorStyles.helpSettingsSummaryContent }, /* @__PURE__ */ React.createElement("strong", null, insertion.labels[language]), " ", insertion.tagName && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("code", null, `<${insertion.tagName}${insertion.selfClosing ? "/>" : ">"}`), " \u2014", " "), insertion.descriptions[language])), /* @__PURE__ */ React.createElement("p", { style: editorStyles.helpSettingsDescription }, /* @__PURE__ */ React.createElement("strong", null, copy.parameters, ":"), " ", insertion.parameterDescription[language]), /* @__PURE__ */ React.createElement("ul", { style: editorStyles.helpSettingsList }, insertion.options.map((option) => /* @__PURE__ */ React.createElement("li", { key: option.value }, /* @__PURE__ */ React.createElement("strong", null, option.labels[language]), option.descriptions && /* @__PURE__ */ React.createElement(React.Fragment, null, " \u2014 ", option.descriptions[language]))))))))), /* @__PURE__ */ React.createElement("div", { style:
|
|
2912
|
+
/* @__PURE__ */ React.createElement("div", { className: displayClassName, style: { ...editorStyles.display, ...displayStyle }, "data-ssml-editor-display": "" }, isHelpOpen && isSsmlEditorButtonVisible(buttonVisibility, "help") && /* @__PURE__ */ React.createElement("section", { id: helpPanelId, style: editorStyles.helpPanel, "aria-label": copy.helpHeading }, /* @__PURE__ */ React.createElement("h3", { style: editorStyles.helpHeading }, copy.helpHeading), /* @__PURE__ */ React.createElement("p", { style: editorStyles.helpDescription }, copy.helpDescription), helpInsertions.length > 0 && /* @__PURE__ */ React.createElement("ul", { style: editorStyles.helpList }, helpInsertions.map((insertion) => /* @__PURE__ */ React.createElement("li", { key: insertion.id, style: editorStyles.helpItem }, /* @__PURE__ */ React.createElement("details", { className: "ssml-editor-help-settings-accordion", style: editorStyles.helpSettingsAccordion }, /* @__PURE__ */ React.createElement("summary", { className: "ssml-editor-help-settings-summary", style: editorStyles.helpSettingsSummary }, /* @__PURE__ */ React.createElement("span", { style: editorStyles.helpIcon, "aria-hidden": "true" }, insertion.icon), /* @__PURE__ */ React.createElement("span", { style: editorStyles.helpSettingsSummaryContent }, /* @__PURE__ */ React.createElement("strong", null, insertion.labels[language]), " ", insertion.tagName && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("code", null, `<${insertion.tagName}${insertion.selfClosing ? "/>" : ">"}`), " \u2014", " "), insertion.descriptions[language])), /* @__PURE__ */ React.createElement("p", { style: editorStyles.helpSettingsDescription }, /* @__PURE__ */ React.createElement("strong", null, copy.parameters, ":"), " ", insertion.parameterDescription[language]), /* @__PURE__ */ React.createElement("ul", { style: editorStyles.helpSettingsList }, insertion.options.map((option) => /* @__PURE__ */ React.createElement("li", { key: option.value }, /* @__PURE__ */ React.createElement("strong", null, option.labels[language]), option.descriptions && /* @__PURE__ */ React.createElement(React.Fragment, null, " \u2014 ", option.descriptions[language]))))))))), editMode === "visual" ? /* @__PURE__ */ React.createElement("div", { style: editorStyles.visual }, /* @__PURE__ */ React.createElement(
|
|
2913
|
+
VisualSsmlEditor,
|
|
2914
|
+
{
|
|
2915
|
+
document: draftDocument,
|
|
2916
|
+
readOnly: isReadOnly,
|
|
2917
|
+
onChange: commit,
|
|
2918
|
+
onPreviewSelection
|
|
2919
|
+
}
|
|
2920
|
+
)) : /* @__PURE__ */ React.createElement("div", { style: { ...editorStyles.editor, minHeight: editorMinHeight } }, /* @__PURE__ */ React.createElement(
|
|
2652
2921
|
Editor,
|
|
2653
2922
|
{
|
|
2654
2923
|
height: editorHeight,
|
|
@@ -2709,6 +2978,7 @@ export {
|
|
|
2709
2978
|
SSML_HOVER_COPY,
|
|
2710
2979
|
SSML_INSERTIONS,
|
|
2711
2980
|
SsmlEditor,
|
|
2981
|
+
VisualSsmlEditor,
|
|
2712
2982
|
createSsmlEditorInsertionDefinition,
|
|
2713
2983
|
registerSsmlCodeLens,
|
|
2714
2984
|
updateTagAttribute
|