@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/dist/index.js CHANGED
@@ -33,6 +33,7 @@ var index_exports = {};
33
33
  __export(index_exports, {
34
34
  EDITOR_COPY: () => EDITOR_COPY,
35
35
  INLINE_BADGE_COPY: () => INLINE_BADGE_COPY,
36
+ SSML_ELEMENT_COPY: () => SSML_ELEMENT_COPY,
36
37
  SSML_HOVER_COPY: () => SSML_HOVER_COPY,
37
38
  SSML_INSERTIONS: () => SSML_INSERTIONS,
38
39
  SsmlEditor: () => SsmlEditor,
@@ -820,6 +821,152 @@ var SILENCE_VALUE_DESCRIPTIONS = {
820
821
  };
821
822
 
822
823
  // src/locales.ts
824
+ var SSML_ELEMENT_COPY = {
825
+ ja: {
826
+ dialog: {
827
+ label: "\u30C0\u30A4\u30A2\u30ED\u30B0",
828
+ description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002",
829
+ validationErrors: { turn: "turn \u306F dialog \u306E\u76F4\u4E0B\u306B\u914D\u7F6E\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
830
+ },
831
+ "mstts:dialog": {
832
+ label: "\u30C0\u30A4\u30A2\u30ED\u30B0",
833
+ description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002",
834
+ validationErrors: { turn: "turn \u306F dialog \u306E\u76F4\u4E0B\u306B\u914D\u7F6E\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
835
+ },
836
+ turn: {
837
+ label: "\u8A71\u8005\u30BF\u30FC\u30F3",
838
+ description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
839
+ validationErrors: { voice: "voice \u307E\u305F\u306F speaker \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
840
+ },
841
+ "mstts:turn": {
842
+ label: "\u8A71\u8005\u30BF\u30FC\u30F3",
843
+ description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
844
+ validationErrors: { voice: "voice \u307E\u305F\u306F speaker \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
845
+ },
846
+ backgroundaudio: {
847
+ label: "\u80CC\u666F\u97F3\u58F0",
848
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
849
+ validationErrors: { src: "\u80CC\u666F\u97F3\u58F0\u306B\u306F URL \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
850
+ },
851
+ "mstts:backgroundaudio": {
852
+ label: "\u80CC\u666F\u97F3\u58F0",
853
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
854
+ validationErrors: { src: "\u80CC\u666F\u97F3\u58F0\u306B\u306F URL \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
855
+ },
856
+ ttsembedding: {
857
+ label: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
858
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
859
+ validationErrors: { speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
860
+ },
861
+ "mstts:ttsembedding": {
862
+ label: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
863
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
864
+ validationErrors: { speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
865
+ },
866
+ embedding: {
867
+ label: "\u57CB\u3081\u8FBC\u307F",
868
+ description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
869
+ validationErrors: {}
870
+ },
871
+ "mstts:embedding": {
872
+ label: "\u57CB\u3081\u8FBC\u307F",
873
+ description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
874
+ validationErrors: {}
875
+ },
876
+ silence: {
877
+ label: "\u7121\u97F3",
878
+ description: "\u767A\u8A71\u524D\u5F8C\u307E\u305F\u306F\u53E5\u8AAD\u70B9\u306E\u5883\u754C\u306B\u7121\u97F3\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002",
879
+ validationErrors: { value: "\u7121\u97F3\u306E\u9577\u3055\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
880
+ },
881
+ "mstts:silence": {
882
+ label: "\u7121\u97F3",
883
+ description: "\u767A\u8A71\u524D\u5F8C\u307E\u305F\u306F\u53E5\u8AAD\u70B9\u306E\u5883\u754C\u306B\u7121\u97F3\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002",
884
+ validationErrors: { value: "\u7121\u97F3\u306E\u9577\u3055\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
885
+ },
886
+ voiceconversion: {
887
+ label: "\u97F3\u58F0\u5909\u63DB",
888
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
889
+ validationErrors: {}
890
+ },
891
+ "mstts:voiceconversion": {
892
+ label: "\u97F3\u58F0\u5909\u63DB",
893
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
894
+ validationErrors: {}
895
+ }
896
+ },
897
+ en: {
898
+ dialog: {
899
+ label: "Dialog",
900
+ description: "Groups multiple speaker turns.",
901
+ validationErrors: { turn: "Place turns directly inside a dialog." }
902
+ },
903
+ "mstts:dialog": {
904
+ label: "Dialog",
905
+ description: "Groups multiple speaker turns.",
906
+ validationErrors: { turn: "Place turns directly inside a dialog." }
907
+ },
908
+ turn: {
909
+ label: "Dialog turn",
910
+ description: "Specifies a speaker and utterance within a dialog.",
911
+ validationErrors: { voice: "Provide a voice or speaker." }
912
+ },
913
+ "mstts:turn": {
914
+ label: "Dialog turn",
915
+ description: "Specifies a speaker and utterance within a dialog.",
916
+ validationErrors: { voice: "Provide a voice or speaker." }
917
+ },
918
+ backgroundaudio: {
919
+ label: "Background audio",
920
+ description: "Specifies an audio file played behind synthesized speech.",
921
+ validationErrors: { src: "Provide a background audio URL." }
922
+ },
923
+ "mstts:backgroundaudio": {
924
+ label: "Background audio",
925
+ description: "Specifies an audio file played behind synthesized speech.",
926
+ validationErrors: { src: "Provide a background audio URL." }
927
+ },
928
+ ttsembedding: {
929
+ label: "TTS embedding",
930
+ description: "Embeds custom voice or speaker profile metadata.",
931
+ validationErrors: { speakerProfileId: "Provide a speaker profile ID." }
932
+ },
933
+ "mstts:ttsembedding": {
934
+ label: "TTS embedding",
935
+ description: "Embeds custom voice or speaker profile metadata.",
936
+ validationErrors: { speakerProfileId: "Provide a speaker profile ID." }
937
+ },
938
+ embedding: {
939
+ label: "Embedding",
940
+ description: "Specifies speaker embedding metadata.",
941
+ validationErrors: {}
942
+ },
943
+ "mstts:embedding": {
944
+ label: "Embedding",
945
+ description: "Specifies speaker embedding metadata.",
946
+ validationErrors: {}
947
+ },
948
+ silence: {
949
+ label: "Silence",
950
+ description: "Adds silence before, after, or around punctuation.",
951
+ validationErrors: { value: "Provide a silence duration." }
952
+ },
953
+ "mstts:silence": {
954
+ label: "Silence",
955
+ description: "Adds silence before, after, or around punctuation.",
956
+ validationErrors: { value: "Provide a silence duration." }
957
+ },
958
+ voiceconversion: {
959
+ label: "Voice conversion",
960
+ description: "Specifies custom voice conversion metadata.",
961
+ validationErrors: {}
962
+ },
963
+ "mstts:voiceconversion": {
964
+ label: "Voice conversion",
965
+ description: "Specifies custom voice conversion metadata.",
966
+ validationErrors: {}
967
+ }
968
+ }
969
+ };
823
970
  var EDITOR_COPY = {
824
971
  ja: {
825
972
  editorAriaLabel: "SSML\u30A8\u30C7\u30A3\u30BF\u30FC",
@@ -1037,6 +1184,42 @@ var SSML_HOVER_COPY = {
1037
1184
  parameters: {
1038
1185
  value: { title: "value", description: "\u76EE\u6A19\u6642\u9593\u3002\u4F8B: `10s`\u3001`5000ms`\u3001`00:00:10`\u3002" }
1039
1186
  }
1187
+ },
1188
+ "mstts:dialog": { title: "\u30C0\u30A4\u30A2\u30ED\u30B0", description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002", parameters: {} },
1189
+ "mstts:turn": {
1190
+ title: "\u8A71\u8005\u30BF\u30FC\u30F3",
1191
+ description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1192
+ parameters: {
1193
+ voice: { title: "voice", description: "\u3053\u306E\u30BF\u30FC\u30F3\u3067\u4F7F\u7528\u3059\u308B Azure \u97F3\u58F0\u540D\u3002" },
1194
+ speaker: { title: "speaker", description: "\u8A71\u8005\u8B58\u5225\u5B50\u3002" }
1195
+ }
1196
+ },
1197
+ "mstts:backgroundaudio": {
1198
+ title: "\u80CC\u666F\u97F3\u58F0",
1199
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1200
+ parameters: { src: { title: "src", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u306E HTTPS URL\u3002" } }
1201
+ },
1202
+ "mstts:ttsembedding": {
1203
+ title: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
1204
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
1205
+ parameters: { speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" } }
1206
+ },
1207
+ "mstts:embedding": {
1208
+ title: "\u57CB\u3081\u8FBC\u307F",
1209
+ description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1210
+ parameters: {
1211
+ id: { title: "id", description: "\u57CB\u3081\u8FBC\u307F ID\u3002" },
1212
+ speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" }
1213
+ }
1214
+ },
1215
+ "mstts:voiceconversion": {
1216
+ title: "\u97F3\u58F0\u5909\u63DB",
1217
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1218
+ parameters: {
1219
+ url: { title: "url", description: "\u97F3\u58F0\u5909\u63DB\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB URL\u3002" },
1220
+ profile: { title: "profile", description: "\u5909\u63DB\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3002" },
1221
+ speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" }
1222
+ }
1040
1223
  }
1041
1224
  }
1042
1225
  },
@@ -1201,6 +1384,42 @@ var SSML_HOVER_COPY = {
1201
1384
  parameters: {
1202
1385
  value: { title: "value", description: "The target duration, such as `10s`, `5000ms`, or `00:00:10`." }
1203
1386
  }
1387
+ },
1388
+ "mstts:dialog": { title: "Dialog", description: "Groups multiple speaker turns.", parameters: {} },
1389
+ "mstts:turn": {
1390
+ title: "Dialog turn",
1391
+ description: "Specifies a speaker and utterance within a dialog.",
1392
+ parameters: {
1393
+ voice: { title: "voice", description: "The Azure voice used by this turn." },
1394
+ speaker: { title: "speaker", description: "The speaker identifier." }
1395
+ }
1396
+ },
1397
+ "mstts:backgroundaudio": {
1398
+ title: "Background audio",
1399
+ description: "Specifies an audio file played behind synthesized speech.",
1400
+ parameters: { src: { title: "src", description: "The HTTPS URL of the audio file." } }
1401
+ },
1402
+ "mstts:ttsembedding": {
1403
+ title: "TTS embedding",
1404
+ description: "Embeds custom voice or speaker profile metadata.",
1405
+ parameters: { speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." } }
1406
+ },
1407
+ "mstts:embedding": {
1408
+ title: "Embedding",
1409
+ description: "Specifies speaker embedding metadata.",
1410
+ parameters: {
1411
+ id: { title: "id", description: "The embedding ID." },
1412
+ speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." }
1413
+ }
1414
+ },
1415
+ "mstts:voiceconversion": {
1416
+ title: "Voice conversion",
1417
+ description: "Specifies custom voice conversion metadata.",
1418
+ parameters: {
1419
+ url: { title: "url", description: "The voice conversion profile URL." },
1420
+ profile: { title: "profile", description: "The conversion profile." },
1421
+ speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." }
1422
+ }
1204
1423
  }
1205
1424
  }
1206
1425
  }
@@ -4810,14 +5029,55 @@ var VISUAL_ELEMENT_FIELDS = {
4810
5029
  function getElementFields(element) {
4811
5030
  return VISUAL_ELEMENT_FIELDS[elementLabel(element)] ?? [];
4812
5031
  }
5032
+ function localizedElementLabel(element, locale) {
5033
+ return SSML_ELEMENT_COPY[locale][elementLabel(element)]?.label ?? elementLabel(element);
5034
+ }
5035
+ function filteredVoices(voiceCatalog, locale, region, style) {
5036
+ return (voiceCatalog ?? []).filter((voice) => {
5037
+ if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
5038
+ if (region && voice.region && voice.region.toLowerCase() !== region.toLowerCase()) return false;
5039
+ if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
5040
+ return true;
5041
+ });
5042
+ }
5043
+ function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }) {
5044
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5045
+ "select",
5046
+ {
5047
+ "aria-label": locale === "ja" ? "\u97F3\u58F0" : "Voice",
5048
+ value,
5049
+ disabled: readOnly,
5050
+ onChange: (event) => onChange(event.target.value),
5051
+ children: [
5052
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: locale === "ja" ? "\u97F3\u58F0\u3092\u9078\u629E" : "Select a voice" }),
5053
+ voices.map((voice) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: voice.name, children: [
5054
+ voice.name,
5055
+ voice.preview || voice.status === "preview" ? " (preview)" : ""
5056
+ ] }, voice.name))
5057
+ ]
5058
+ }
5059
+ );
5060
+ }
4813
5061
  function VisualElementInspector({
4814
5062
  document: document2,
4815
5063
  element,
4816
5064
  path,
4817
5065
  readOnly,
4818
- commit
5066
+ commit,
5067
+ locale,
5068
+ customInspector,
5069
+ renderVoiceSelector,
5070
+ voiceCatalog,
5071
+ voiceLocale,
5072
+ voiceRegion,
5073
+ voiceStyle
4819
5074
  }) {
5075
+ if (customInspector) {
5076
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: customInspector({ document: document2, element, path, readOnly, onChange: commit, locale }) });
5077
+ }
4820
5078
  const fields = getElementFields(element);
5079
+ const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
5080
+ const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
4821
5081
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { children: [
4822
5082
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: `<${elementLabel(element)}>` }),
4823
5083
  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) => {
@@ -4825,8 +5085,47 @@ function VisualElementInspector({
4825
5085
  const inputValue = value === void 0 ? "" : String(value);
4826
5086
  const inputId = `ssml-visual-${field.key}`;
4827
5087
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { htmlFor: inputId, children: [
4828
- field.label,
4829
- field.multiline ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5088
+ locale === "ja" ? {
5089
+ name: "\u540D\u524D",
5090
+ effect: "\u52B9\u679C",
5091
+ rate: "\u901F\u5EA6",
5092
+ pitch: "\u30D4\u30C3\u30C1",
5093
+ volume: "\u97F3\u91CF",
5094
+ contour: "\u30D4\u30C3\u30C1\u66F2\u7DDA",
5095
+ range: "\u7BC4\u56F2",
5096
+ style: "\u30B9\u30BF\u30A4\u30EB",
5097
+ styleDegree: "\u30B9\u30BF\u30A4\u30EB\u5F37\u5EA6",
5098
+ role: "\u5F79\u5272",
5099
+ interpretAs: "\u89E3\u91C8",
5100
+ alphabet: "\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8",
5101
+ ph: "\u767A\u97F3",
5102
+ level: "\u5F37\u8ABF\u30EC\u30D9\u30EB",
5103
+ src: "\u97F3\u58F0 URL",
5104
+ desc: "\u8AAC\u660E",
5105
+ clipBegin: "\u958B\u59CB\u4F4D\u7F6E",
5106
+ clipEnd: "\u7D42\u4E86\u4F4D\u7F6E",
5107
+ speed: "\u901F\u5EA6",
5108
+ repeatCount: "\u7E70\u308A\u8FD4\u3057\u56DE\u6570",
5109
+ repeatDuration: "\u7E70\u308A\u8FD4\u3057\u6642\u9593",
5110
+ soundLevel: "\u97F3\u91CF\u30EC\u30D9\u30EB",
5111
+ mark: "\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u540D",
5112
+ alias: "\u5225\u540D",
5113
+ lang: "\u8A00\u8A9E",
5114
+ uri: "\u8F9E\u66F8 URI",
5115
+ typeValue: "\u7121\u97F3\u306E\u7A2E\u985E",
5116
+ value: "\u5024",
5117
+ id: "\u57CB\u3081\u8FBC\u307F ID",
5118
+ speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID",
5119
+ url: "\u97F3\u58F0\u5909\u63DB URL",
5120
+ profile: "\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB"
5121
+ }[field.key] ?? field.label : field.label,
5122
+ field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
5123
+ value: inputValue,
5124
+ voices: availableVoices,
5125
+ readOnly,
5126
+ locale,
5127
+ onChange: (value2) => commit(updateOptionalElementProperty(document2, path, field.key, value2))
5128
+ }) : field.multiline ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4830
5129
  "textarea",
4831
5130
  {
4832
5131
  id: inputId,
@@ -4922,13 +5221,21 @@ function VisualSsmlEditor({
4922
5221
  document: document2,
4923
5222
  readOnly = false,
4924
5223
  onChange,
4925
- onPreviewSelection
5224
+ onPreviewSelection,
5225
+ locale = "en",
5226
+ customInspectors,
5227
+ renderVoiceSelector,
5228
+ voiceCatalog,
5229
+ voiceLocale,
5230
+ voiceRegion,
5231
+ voiceStyle
4926
5232
  }) {
4927
5233
  const [selectedPath, setSelectedPath] = (0, import_react3.useState)(null);
4928
5234
  const [selection, setSelection] = (0, import_react3.useState)({ start: 0, end: 0 });
4929
5235
  const textLeaves = (0, import_react3.useMemo)(() => collectTextLeaves(document2.children ?? []), [document2]);
4930
5236
  const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
4931
5237
  const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
5238
+ const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
4932
5239
  const diagnostics = (0, import_react3.useMemo)(() => (0, import_ssml_core4.validateAzureSsml)((0, import_ssml_core4.buildSsml)(document2)), [document2]);
4933
5240
  const commit = (nextDocument) => onChange?.(nextDocument);
4934
5241
  const applyWrapper = (tag, attributes) => {
@@ -4963,25 +5270,39 @@ function VisualSsmlEditor({
4963
5270
  isElement(node) ? elementLabel(node) : JSON.stringify(node)
4964
5271
  )) })
4965
5272
  ] }),
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." }),
5273
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ssml-editor-visual-form", children: selectedCustomInspector && selectedElement && isElement(selectedElement) ? selectedCustomInspector({
5274
+ document: document2,
5275
+ element: selectedElement,
5276
+ path: selectedPath ?? [],
5277
+ readOnly,
5278
+ onChange: commit,
5279
+ locale
5280
+ }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { children: [
5281
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: localizedElementLabel(selectedElement, locale) }),
5282
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: SSML_ELEMENT_COPY[locale][elementLabel(selectedElement)]?.description }),
4969
5283
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4970
5284
  "button",
4971
5285
  {
4972
5286
  type: "button",
4973
5287
  disabled: readOnly,
4974
5288
  onClick: () => commit(addDialogTurn(document2, selectedPath ?? [])),
4975
- children: "Add turn"
5289
+ children: locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
4976
5290
  }
4977
5291
  )
4978
5292
  ] }) : 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)(
5293
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: localizedElementLabel(selectedElement, locale) }),
5294
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { htmlFor: "ssml-visual-turn-voice", children: [
5295
+ locale === "ja" ? "\u97F3\u58F0" : "Voice",
5296
+ voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
5297
+ value: selectedElement.voice ?? "",
5298
+ voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
5299
+ readOnly,
5300
+ locale,
5301
+ onChange: (value) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", value))
5302
+ }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4983
5303
  "input",
4984
5304
  {
5305
+ id: "ssml-visual-turn-voice",
4985
5306
  value: selectedElement.voice ?? "",
4986
5307
  readOnly,
4987
5308
  onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", event.target.value))
@@ -4989,7 +5310,7 @@ function VisualSsmlEditor({
4989
5310
  )
4990
5311
  ] }),
4991
5312
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
4992
- "Speaker",
5313
+ locale === "ja" ? "\u8A71\u8005" : "Speaker",
4993
5314
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4994
5315
  "input",
4995
5316
  {
@@ -5000,7 +5321,7 @@ function VisualSsmlEditor({
5000
5321
  )
5001
5322
  ] }),
5002
5323
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
5003
- "Turn text",
5324
+ locale === "ja" ? "\u767A\u8A71\u30C6\u30AD\u30B9\u30C8" : "Turn text",
5004
5325
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5005
5326
  "textarea",
5006
5327
  {
@@ -5017,9 +5338,9 @@ function VisualSsmlEditor({
5017
5338
  )
5018
5339
  ] })
5019
5340
  ] }) : 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" }),
5341
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { children: localizedElementLabel(selectedElement, locale) }),
5021
5342
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
5022
- "Source URL",
5343
+ locale === "ja" ? "\u97F3\u58F0 URL" : "Source URL",
5023
5344
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5024
5345
  "input",
5025
5346
  {
@@ -5030,7 +5351,7 @@ function VisualSsmlEditor({
5030
5351
  )
5031
5352
  ] }),
5032
5353
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
5033
- "Volume",
5354
+ locale === "ja" ? "\u97F3\u91CF" : "Volume",
5034
5355
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5035
5356
  "input",
5036
5357
  {
@@ -5041,7 +5362,7 @@ function VisualSsmlEditor({
5041
5362
  )
5042
5363
  ] }),
5043
5364
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
5044
- "Fade in",
5365
+ locale === "ja" ? "\u30D5\u30A7\u30FC\u30C9\u30A4\u30F3" : "Fade in",
5045
5366
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5046
5367
  "input",
5047
5368
  {
@@ -5052,7 +5373,7 @@ function VisualSsmlEditor({
5052
5373
  )
5053
5374
  ] }),
5054
5375
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
5055
- "Fade out",
5376
+ locale === "ja" ? "\u30D5\u30A7\u30FC\u30C9\u30A2\u30A6\u30C8" : "Fade out",
5056
5377
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5057
5378
  "input",
5058
5379
  {
@@ -5069,7 +5390,14 @@ function VisualSsmlEditor({
5069
5390
  element: selectedElement,
5070
5391
  path: selectedPath ?? [],
5071
5392
  readOnly,
5072
- commit
5393
+ commit,
5394
+ locale,
5395
+ customInspector: customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type],
5396
+ renderVoiceSelector,
5397
+ voiceCatalog,
5398
+ voiceLocale,
5399
+ voiceRegion,
5400
+ voiceStyle
5073
5401
  }
5074
5402
  ) : selectedLeaf ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
5075
5403
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { children: [
@@ -5708,6 +6036,12 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
5708
6036
  insertionGroups,
5709
6037
  customInsertions,
5710
6038
  additionalInsertions,
6039
+ customInspectors,
6040
+ renderVoiceSelector,
6041
+ voiceCatalog,
6042
+ voiceLocale,
6043
+ voiceRegion,
6044
+ voiceStyle,
5711
6045
  emotionStyles,
5712
6046
  className,
5713
6047
  style,
@@ -6149,7 +6483,14 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
6149
6483
  document: draftDocument,
6150
6484
  readOnly: isReadOnly,
6151
6485
  onChange: commit,
6152
- onPreviewSelection
6486
+ onPreviewSelection,
6487
+ locale: localeProp ?? languageProp,
6488
+ customInspectors,
6489
+ renderVoiceSelector,
6490
+ voiceCatalog,
6491
+ voiceLocale,
6492
+ voiceRegion,
6493
+ voiceStyle
6153
6494
  }
6154
6495
  ) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { ...editorStyles.editor, minHeight: editorMinHeight }, children: [
6155
6496
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -6228,6 +6569,7 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
6228
6569
  0 && (module.exports = {
6229
6570
  EDITOR_COPY,
6230
6571
  INLINE_BADGE_COPY,
6572
+ SSML_ELEMENT_COPY,
6231
6573
  SSML_HOVER_COPY,
6232
6574
  SSML_INSERTIONS,
6233
6575
  SsmlEditor,