ssml-builder-js 2.13.0 → 2.15.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/react.js CHANGED
@@ -2953,6 +2953,86 @@ var AZURE_VOICE_DEFINITIONS = [
2953
2953
  },
2954
2954
  { name: "zh-TW-HsiaoChenNeural", locale: "zh-TW" }
2955
2955
  ];
2956
+ function createAzureUrlValidatorRunner(validator, options = {}) {
2957
+ if (typeof validator !== "function") throw new TypeError("A URL validator function is required.");
2958
+ const concurrency = options.concurrency === void 0 ? Infinity : Number.isFinite(options.concurrency) ? Math.max(1, Math.floor(options.concurrency)) : Infinity;
2959
+ const cache = options.cache ?? /* @__PURE__ */ new Map();
2960
+ const inFlight = /* @__PURE__ */ new Map();
2961
+ const waiters = [];
2962
+ let active = 0;
2963
+ const configuredSignal = options.signal ?? new AbortController().signal;
2964
+ const acquire = async (signal) => {
2965
+ if (signal.aborted) throw new Error("URL validation was aborted.");
2966
+ if (active < concurrency) {
2967
+ active += 1;
2968
+ return;
2969
+ }
2970
+ await new Promise((resolve, reject) => {
2971
+ let waiter;
2972
+ const abortHandler = () => {
2973
+ const index = waiters.indexOf(waiter);
2974
+ if (index >= 0) waiters.splice(index, 1);
2975
+ signal.removeEventListener("abort", abortHandler);
2976
+ reject(new Error("URL validation was aborted."));
2977
+ };
2978
+ signal.addEventListener("abort", abortHandler, { once: true });
2979
+ waiter = () => {
2980
+ signal.removeEventListener("abort", abortHandler);
2981
+ resolve();
2982
+ };
2983
+ waiters.push(waiter);
2984
+ });
2985
+ active += 1;
2986
+ };
2987
+ const release = () => {
2988
+ active -= 1;
2989
+ waiters.shift()?.();
2990
+ };
2991
+ const check = async (url, context, signal = configuredSignal) => {
2992
+ if (signal.aborted) throw new Error("URL validation was aborted.");
2993
+ const key = `${context.tag}:${context.attribute}:${url}`;
2994
+ const cached = cache.get(key);
2995
+ if (cached !== void 0) return cached;
2996
+ const existing = inFlight.get(key);
2997
+ if (existing) return existing;
2998
+ const promise = (async () => {
2999
+ await acquire(signal);
3000
+ try {
3001
+ if (signal.aborted) throw new Error("URL validation was aborted.");
3002
+ const validation = Promise.resolve(validator(url, context, signal));
3003
+ let timer;
3004
+ let abortHandler;
3005
+ const cancellation = new Promise((_resolve, reject) => {
3006
+ abortHandler = () => reject(new Error("URL validation was aborted."));
3007
+ signal.addEventListener("abort", abortHandler, { once: true });
3008
+ if (options.timeoutMs !== void 0 && options.timeoutMs > 0) {
3009
+ timer = setTimeout(
3010
+ () => reject(new Error(`URL validation timed out after ${options.timeoutMs} ms.`)),
3011
+ options.timeoutMs
3012
+ );
3013
+ }
3014
+ });
3015
+ try {
3016
+ const result = await (timer || abortHandler ? Promise.race([validation, cancellation]) : validation);
3017
+ cache.set(key, result);
3018
+ return result;
3019
+ } finally {
3020
+ if (timer) clearTimeout(timer);
3021
+ if (abortHandler) signal.removeEventListener("abort", abortHandler);
3022
+ }
3023
+ } finally {
3024
+ release();
3025
+ }
3026
+ })();
3027
+ inFlight.set(key, promise);
3028
+ try {
3029
+ return await promise;
3030
+ } finally {
3031
+ inFlight.delete(key);
3032
+ }
3033
+ };
3034
+ return (url, context, signal) => check(url, context, signal ?? configuredSignal);
3035
+ }
2956
3036
  var ALLOWED_BREAK_STRENGTHS = /* @__PURE__ */ new Set(["none", "x-weak", "weak", "medium", "strong", "x-strong"]);
2957
3037
  var ALLOWED_SAY_AS = /* @__PURE__ */ new Set([
2958
3038
  "characters",
@@ -3237,23 +3317,23 @@ function validateVoiceFeatureMatrix(token, source, diagnostics, voiceName, defin
3237
3317
  );
3238
3318
  }
3239
3319
  }
3240
- function validateAudioSource(token, source, diagnostics, options, elementName2) {
3320
+ function validateAudioSource(token, source, diagnostics, options, elementName3) {
3241
3321
  const src = attr(token, "src");
3242
3322
  if (!src) {
3243
- addDiagnostic(diagnostics, source, token.start, `<${elementName2}> requires a "src" attribute.`);
3323
+ addDiagnostic(diagnostics, source, token.start, `<${elementName3}> requires a "src" attribute.`);
3244
3324
  return;
3245
3325
  }
3246
3326
  let parsed;
3247
3327
  try {
3248
3328
  parsed = new URL(src);
3249
3329
  } catch {
3250
- addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> must be an absolute HTTP(S) URL.`);
3330
+ addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must be an absolute HTTP(S) URL.`);
3251
3331
  return;
3252
3332
  }
3253
3333
  if (parsed.username || parsed.password)
3254
- addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> must not contain URL credentials.`);
3334
+ addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must not contain URL credentials.`);
3255
3335
  if (parsed.protocol !== "https:" && !(options.allowHttpAudio && parsed.protocol === "http:"))
3256
- addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> must use HTTPS.`);
3336
+ addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must use HTTPS.`);
3257
3337
  const isAllowedOrigin = options.allowedAudioOrigins?.some((allowedOrigin) => {
3258
3338
  try {
3259
3339
  const configured = new URL(allowedOrigin);
@@ -3265,13 +3345,13 @@ function validateAudioSource(token, source, diagnostics, options, elementName2)
3265
3345
  }
3266
3346
  }) ?? false;
3267
3347
  if (options.allowedAudioOrigins && !isAllowedOrigin)
3268
- addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> origin "${parsed.origin}" is not allowed.`);
3348
+ addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> origin "${parsed.origin}" is not allowed.`);
3269
3349
  else if (!isAllowedOrigin && !options.allowExternalAudio)
3270
3350
  addDiagnostic(
3271
3351
  diagnostics,
3272
3352
  source,
3273
3353
  token.start,
3274
- `<${elementName2} src> external origin "${parsed.origin}" is blocked by default; set allowExternalAudio to true or provide allowedAudioOrigins.`
3354
+ `<${elementName3} src> external origin "${parsed.origin}" is blocked by default; set allowExternalAudio to true or provide allowedAudioOrigins.`
3275
3355
  );
3276
3356
  }
3277
3357
  function validateElement(token, source, diagnostics, voiceName, options, voiceCatalog) {
@@ -3589,6 +3669,15 @@ function validateAzureSsml(ssml, options = {}) {
3589
3669
  const diagnostics = validateAzureSsmlStatic(ssml, options);
3590
3670
  const validator = options.urlValidator ?? options.customUrlValidator;
3591
3671
  if (!validator || typeof ssml !== "string") return diagnostics;
3672
+ const runnerOptions = options.urlValidation ?? {};
3673
+ const boundedValidator = createAzureUrlValidatorRunner(validator, {
3674
+ ...runnerOptions,
3675
+ ...options.urlValidatorConcurrency !== void 0 ? { concurrency: options.urlValidatorConcurrency } : {},
3676
+ ...options.urlValidatorTimeoutMs !== void 0 ? { timeoutMs: options.urlValidatorTimeoutMs } : {},
3677
+ ...options.urlValidatorSignal ? { signal: options.urlValidatorSignal } : {},
3678
+ ...options.urlValidatorCache ? { cache: options.urlValidatorCache } : {}
3679
+ });
3680
+ const validationSignal = options.urlValidatorSignal ?? options.urlValidation?.signal ?? new AbortController().signal;
3592
3681
  let tokens;
3593
3682
  try {
3594
3683
  tokens = tokenizeElements(ssml);
@@ -3598,7 +3687,11 @@ function validateAzureSsml(ssml, options = {}) {
3598
3687
  const checks = tokens.flatMap(
3599
3688
  (token) => urlAttributes(token).map(async ({ attribute, value }) => {
3600
3689
  try {
3601
- const result = await validator(value, { tag: token.name, attribute });
3690
+ const result = await boundedValidator(
3691
+ value,
3692
+ { tag: token.name, attribute, ...options.sourceNodePath ? { sourceNodePath: options.sourceNodePath } : {} },
3693
+ validationSignal
3694
+ );
3602
3695
  const valid = typeof result === "boolean" ? result : result.valid;
3603
3696
  if (!valid) {
3604
3697
  const reason = typeof result === "boolean" ? void 0 : result.reason;
@@ -6754,13 +6847,65 @@ function localizedElementLabel(element, locale) {
6754
6847
  function filteredVoices(voiceCatalog, locale, region, style) {
6755
6848
  return (voiceCatalog ?? []).filter((voice) => {
6756
6849
  if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
6757
- if (region && voice.region && voice.region.toLowerCase() !== region.toLowerCase()) return false;
6850
+ const regions = [voice.region, ...voice.regions ?? []].filter(
6851
+ (candidate) => Boolean(candidate)
6852
+ );
6853
+ if (region && regions.length > 0 && !regions.some((candidate) => candidate.toLowerCase() === region.toLowerCase()))
6854
+ return false;
6758
6855
  if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
6759
6856
  return true;
6760
6857
  });
6761
6858
  }
6762
- function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }) {
6859
+ function VoiceCapabilityMatrix({
6860
+ voice,
6861
+ locale
6862
+ }) {
6863
+ const status = voice.status ?? (voice.preview ? "preview" : void 0);
6864
+ return /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-capabilities", "data-voice-capabilities": "" }, /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u30B9\u30C6\u30FC\u30BF\u30B9" : "Status", ": ", status?.toUpperCase() ?? (locale === "ja" ? "GA" : "GA"), status === "preview" || status === "deprecated" ? /* @__PURE__ */ React.createElement("span", { role: "status", "aria-label": status, className: "ssml-editor-voice-warning-badge" }, status === "preview" ? "\u26A0 Preview" : "\u26A0 Deprecated") : null), (voice.regions?.length || voice.region) && /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u30EA\u30FC\u30B8\u30E7\u30F3" : "Regions", ":", " ", [...voice.regions ?? [], ...voice.region ? [voice.region] : []].filter((region, index, all) => all.indexOf(region) === index).join(", ")), voice.supportedTags && voice.supportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u5BFE\u5FDC\u30BF\u30B0" : "Supported tags", ": ", voice.supportedTags.join(", ")), voice.unsupportedTags && voice.unsupportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-unsupported" }, locale === "ja" ? "\u975E\u5BFE\u5FDC\u30BF\u30B0" : "Unsupported tags", ": ", voice.unsupportedTags.join(", ")));
6865
+ }
6866
+ function diagnosticMatchesElement(diagnostic, element) {
6867
+ const name = elementLabel(element).toLowerCase().replace("expressas", "mstts:express-as");
6868
+ if (diagnostic.code === "azure-unsupported-style") return name === "mstts:express-as" || name === "express-as";
6869
+ if (diagnostic.code === "azure-unsupported-tag-for-voice") {
6870
+ return diagnostic.message.toLowerCase().includes(`<${name}>`) || diagnostic.message.toLowerCase().includes(`<${name.replace("mstts:", "")}>`);
6871
+ }
6872
+ if (diagnostic.code === "azure-locale-mismatch" || diagnostic.code === "azure-unsupported-model-for-voice")
6873
+ return name === "voice" || name === "mstts:turn";
6874
+ return false;
6875
+ }
6876
+ function elementWarnings(diagnostics, element) {
6877
+ return diagnostics.filter((diagnostic) => diagnosticMatchesElement(diagnostic, element));
6878
+ }
6879
+ function fieldWarnings(diagnostics, element, field) {
6880
+ return elementWarnings(diagnostics, element).filter((diagnostic) => {
6881
+ if (diagnostic.code === "azure-unsupported-style") return field.key === "style";
6882
+ return field.key === "name" || field.key === "voice";
6883
+ });
6884
+ }
6885
+ function WarningBadge({ messages }) {
6886
+ if (messages.length === 0) return null;
6763
6887
  return /* @__PURE__ */ React.createElement(
6888
+ "span",
6889
+ {
6890
+ role: "status",
6891
+ "aria-label": messages.map((message) => message.message).join(" "),
6892
+ title: messages.map((message) => message.message).join(" "),
6893
+ "data-ssml-warning-badge": "",
6894
+ "data-testid": "ssml-editor-warning-badge",
6895
+ className: "ssml-editor-warning-badge"
6896
+ },
6897
+ "\u26A0"
6898
+ );
6899
+ }
6900
+ function DefaultVoiceSelector({
6901
+ value,
6902
+ voices,
6903
+ selectedVoice,
6904
+ readOnly,
6905
+ locale,
6906
+ onChange
6907
+ }) {
6908
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
6764
6909
  "select",
6765
6910
  {
6766
6911
  "aria-label": locale === "ja" ? "\u97F3\u58F0" : "Voice",
@@ -6770,7 +6915,7 @@ function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }) {
6770
6915
  },
6771
6916
  /* @__PURE__ */ React.createElement("option", { value: "" }, locale === "ja" ? "\u97F3\u58F0\u3092\u9078\u629E" : "Select a voice"),
6772
6917
  voices.map((voice) => /* @__PURE__ */ React.createElement("option", { key: voice.name, value: voice.name }, voice.name, voice.preview || voice.status === "preview" ? " (preview)" : ""))
6773
- );
6918
+ ), selectedVoice ? /* @__PURE__ */ React.createElement(VoiceCapabilityMatrix, { voice: selectedVoice, locale }) : null);
6774
6919
  }
6775
6920
  function VisualElementInspector({
6776
6921
  document: document2,
@@ -6784,15 +6929,19 @@ function VisualElementInspector({
6784
6929
  voiceCatalog,
6785
6930
  voiceLocale,
6786
6931
  voiceRegion,
6787
- voiceStyle
6932
+ voiceStyle,
6933
+ diagnostics
6788
6934
  }) {
6789
6935
  if (customInspector) {
6790
6936
  return /* @__PURE__ */ React.createElement(React.Fragment, null, customInspector({ document: document2, element, path, readOnly, onChange: commit, locale }));
6791
6937
  }
6792
6938
  const fields = getElementFields(element);
6793
6939
  const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
6940
+ const selectedVoice = voiceCatalog?.find(
6941
+ (voice) => voice.name === (element.type === "voice" ? element.name : void 0)
6942
+ );
6794
6943
  const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
6795
- return /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, `<${elementLabel(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) => {
6944
+ return /* @__PURE__ */ React.createElement("fieldset", null, /* @__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) => {
6796
6945
  const value = element[field.key];
6797
6946
  const inputValue = value === void 0 ? "" : String(value);
6798
6947
  const inputId = `ssml-visual-${field.key}`;
@@ -6829,9 +6978,10 @@ function VisualElementInspector({
6829
6978
  speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID",
6830
6979
  url: "\u97F3\u58F0\u5909\u63DB URL",
6831
6980
  profile: "\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB"
6832
- }[field.key] ?? field.label : field.label, field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
6981
+ }[field.key] ?? field.label : field.label, /* @__PURE__ */ React.createElement(WarningBadge, { messages: fieldWarnings(diagnostics, element, field) }), field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
6833
6982
  value: inputValue,
6834
6983
  voices: availableVoices,
6984
+ selectedVoice,
6835
6985
  readOnly,
6836
6986
  locale,
6837
6987
  onChange: (value2) => commit(updateOptionalElementProperty(document2, path, field.key, value2))
@@ -6906,19 +7056,21 @@ function TreeNode({
6906
7056
  node,
6907
7057
  path,
6908
7058
  selectedPath,
6909
- onSelect
7059
+ onSelect,
7060
+ getWarnings
6910
7061
  }) {
6911
7062
  if (!isElement(node)) return null;
6912
7063
  const name = elementLabel(node);
6913
7064
  const isSelected = selectedPath?.join(".") === path.join(".");
6914
- 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(
7065
+ return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("button", { type: "button", "aria-current": isSelected ? "true" : void 0, onClick: () => onSelect(path) }, `<${name}>`, /* @__PURE__ */ React.createElement(WarningBadge, { messages: getWarnings(node) })), (node.children ?? []).length > 0 && /* @__PURE__ */ React.createElement("ul", null, node.children?.map((child, index) => /* @__PURE__ */ React.createElement(
6915
7066
  TreeNode,
6916
7067
  {
6917
7068
  key: `${path.join(".")}/${isElement(child) ? elementLabel(child) : JSON.stringify(child)}`,
6918
7069
  node: child,
6919
7070
  path: [...path, index],
6920
7071
  selectedPath,
6921
- onSelect
7072
+ onSelect,
7073
+ getWarnings
6922
7074
  }
6923
7075
  ))));
6924
7076
  }
@@ -6933,7 +7085,9 @@ function VisualSsmlEditor({
6933
7085
  voiceCatalog,
6934
7086
  voiceLocale,
6935
7087
  voiceRegion,
6936
- voiceStyle
7088
+ voiceStyle,
7089
+ voiceModel,
7090
+ model
6937
7091
  }) {
6938
7092
  const [selectedPath, setSelectedPath] = (0, import_react3.useState)(null);
6939
7093
  const [selection, setSelection] = (0, import_react3.useState)({ start: 0, end: 0 });
@@ -6941,7 +7095,27 @@ function VisualSsmlEditor({
6941
7095
  const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
6942
7096
  const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
6943
7097
  const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
6944
- const diagnostics = (0, import_react3.useMemo)(() => validateAzureSsml(buildSsml(document2)), [document2]);
7098
+ const validationOptions = (0, import_react3.useMemo)(
7099
+ () => ({
7100
+ model: voiceModel ?? model,
7101
+ customVoiceDefinitions: voiceCatalog?.map((voice) => ({
7102
+ name: voice.name,
7103
+ locale: voice.locale,
7104
+ regions: voice.regions ?? (voice.region ? [voice.region] : void 0),
7105
+ styles: voice.styles,
7106
+ supportedTags: voice.supportedTags,
7107
+ unsupportedTags: voice.unsupportedTags,
7108
+ models: voice.models,
7109
+ status: voice.status ?? (voice.preview ? "preview" : "ga")
7110
+ }))
7111
+ }),
7112
+ [model, voiceCatalog, voiceModel]
7113
+ );
7114
+ const diagnostics = (0, import_react3.useMemo)(
7115
+ () => validateAzureSsml(buildSsml(document2), validationOptions),
7116
+ [document2, validationOptions]
7117
+ );
7118
+ const getWarnings = (element) => elementWarnings(diagnostics, element);
6945
7119
  const commit = (nextDocument) => onChange?.(nextDocument);
6946
7120
  const applyWrapper = (tag, attributes) => {
6947
7121
  if (readOnly || !selectedLeaf) return;
@@ -6956,7 +7130,8 @@ function VisualSsmlEditor({
6956
7130
  node,
6957
7131
  path: [index],
6958
7132
  selectedPath,
6959
- onSelect: setSelectedPath
7133
+ onSelect: setSelectedPath,
7134
+ getWarnings
6960
7135
  }
6961
7136
  )))), /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual-form" }, selectedCustomInspector && selectedElement && isElement(selectedElement) ? selectedCustomInspector({
6962
7137
  document: document2,
@@ -6973,9 +7148,10 @@ function VisualSsmlEditor({
6973
7148
  onClick: () => commit(addDialogTurn(document2, selectedPath ?? []))
6974
7149
  },
6975
7150
  locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
6976
- )) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("label", { htmlFor: "ssml-visual-turn-voice" }, locale === "ja" ? "\u97F3\u58F0" : "Voice", voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
7151
+ )) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("label", { htmlFor: "ssml-visual-turn-voice" }, locale === "ja" ? "\u97F3\u58F0" : "Voice", /* @__PURE__ */ React.createElement(WarningBadge, { messages: elementWarnings(diagnostics, selectedElement) }), voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
6977
7152
  value: selectedElement.voice ?? "",
6978
7153
  voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
7154
+ selectedVoice: voiceCatalog?.find((voice) => voice.name === selectedElement.voice),
6979
7155
  readOnly,
6980
7156
  locale,
6981
7157
  onChange: (value) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", value))
@@ -7049,7 +7225,8 @@ function VisualSsmlEditor({
7049
7225
  voiceCatalog,
7050
7226
  voiceLocale,
7051
7227
  voiceRegion,
7052
- voiceStyle
7228
+ voiceStyle,
7229
+ diagnostics
7053
7230
  }
7054
7231
  ) : selectedLeaf ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", null, "Text", /* @__PURE__ */ React.createElement(
7055
7232
  "textarea",
@@ -7673,6 +7850,8 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
7673
7850
  voiceLocale,
7674
7851
  voiceRegion,
7675
7852
  voiceStyle,
7853
+ voiceModel,
7854
+ model,
7676
7855
  emotionStyles,
7677
7856
  className,
7678
7857
  style,
@@ -8071,7 +8250,9 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
8071
8250
  voiceCatalog,
8072
8251
  voiceLocale,
8073
8252
  voiceRegion,
8074
- voiceStyle
8253
+ voiceStyle,
8254
+ voiceModel,
8255
+ model
8075
8256
  }
8076
8257
  )) : /* @__PURE__ */ React.createElement("div", { style: { ...editorStyles.editor, minHeight: editorMinHeight } }, /* @__PURE__ */ React.createElement(
8077
8258
  import_react5.default,