@vunk/plus 1.2.0 → 1.3.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.
Files changed (117) hide show
  1. package/components/SendOutlined.mjs +43 -25
  2. package/components/agent-chat-provider/index.mjs +789 -0
  3. package/components/avatar/index.mjs +2 -2
  4. package/components/broadcasting-markdown/index.css +3 -0
  5. package/components/broadcasting-markdown/index.mjs +637 -0
  6. package/components/bubble-list/index.css +18 -0
  7. package/components/bubble-list/index.mjs +386 -0
  8. package/components/bubble-templates/index.css +18 -0
  9. package/components/bubble-templates/index.mjs +258 -0
  10. package/components/chat-independent/index.css +47 -0
  11. package/components/chat-independent/index.mjs +184 -0
  12. package/components/index.mjs +35980 -0
  13. package/components/lottie-animation/index.mjs +2 -2
  14. package/components/monaco-editor/index.mjs +2 -2
  15. package/components/monaco-environment/index.mjs +11 -11
  16. package/components/recorder-button/index.css +7 -10
  17. package/components/recorder-button/index.mjs +115 -83
  18. package/components/routes-menu-content/index.mjs +5 -5
  19. package/components/sender/index.css +6 -5
  20. package/components/sender/index.mjs +174 -26
  21. package/components/speech-button/index.mjs +40 -14
  22. package/components/table-columns/index.mjs +3 -6
  23. package/components/tables-v1/index.mjs +9 -10
  24. package/components/tables-v1-checkbox/index.mjs +269 -33
  25. package/components/typing-markdown/index.mjs +128 -33
  26. package/components/vditor/index.mjs +5 -9
  27. package/composables/el-breakpoints/index.d.ts +1 -1
  28. package/composables/recorder/index.mjs +752 -182
  29. package/icons/_plugin-vue_export-helper.mjs +9 -0
  30. package/icons/end/index.d.ts +4 -0
  31. package/icons/end/index.mjs +36 -0
  32. package/icons/end/src/avatar.d.ts +12 -0
  33. package/icons/end/src/icon.d.ts +57 -0
  34. package/icons/keyboard/index.d.ts +4 -0
  35. package/icons/keyboard/index.mjs +36 -0
  36. package/icons/keyboard/src/avatar.d.ts +12 -0
  37. package/icons/keyboard/src/icon.d.ts +57 -0
  38. package/icons/start/index.d.ts +4 -0
  39. package/icons/start/index.mjs +36 -0
  40. package/icons/start/src/avatar.d.ts +12 -0
  41. package/icons/start/src/icon.d.ts +57 -0
  42. package/icons/voice/index.d.ts +4 -0
  43. package/icons/voice/index.mjs +51 -0
  44. package/icons/voice/src/avatar.d.ts +12 -0
  45. package/icons/voice/src/icon.d.ts +57 -0
  46. package/icons/voice/src/index.vue.d.ts +4 -0
  47. package/index.css +103 -15
  48. package/package.json +51 -7
  49. package/components/avatar/index.d.ts +0 -4
  50. package/components/avatar/src/ctx.d.ts +0 -18
  51. package/components/avatar/src/index.vue.d.ts +0 -180
  52. package/components/avatar/src/types.d.ts +0 -1
  53. package/components/lottie-animation/index.d.ts +0 -4
  54. package/components/lottie-animation/src/ctx.d.ts +0 -10
  55. package/components/lottie-animation/src/index.vue.d.ts +0 -21
  56. package/components/lottie-animation/src/types.d.ts +0 -4
  57. package/components/monaco-editor/index.d.ts +0 -5
  58. package/components/monaco-editor/src/ctx.d.ts +0 -23
  59. package/components/monaco-editor/src/index.vue.d.ts +0 -40
  60. package/components/monaco-editor/src/types.d.ts +0 -1
  61. package/components/monaco-environment/index.d.ts +0 -4
  62. package/components/monaco-environment/src/ctx.d.ts +0 -8
  63. package/components/monaco-environment/src/index.vue.d.ts +0 -2
  64. package/components/monaco-environment/src/types.d.ts +0 -1
  65. package/components/recorder-button/index.d.ts +0 -4
  66. package/components/recorder-button/src/ctx.d.ts +0 -19
  67. package/components/recorder-button/src/index.vue.d.ts +0 -309
  68. package/components/recorder-button/src/speech-to-text.d.ts +0 -1
  69. package/components/recorder-button/src/types.d.ts +0 -6
  70. package/components/routes-menu-content/index.d.ts +0 -4
  71. package/components/routes-menu-content/src/ctx.d.ts +0 -17
  72. package/components/routes-menu-content/src/index.vue.d.ts +0 -350
  73. package/components/routes-menu-content/src/item/core/ctx.d.ts +0 -18
  74. package/components/routes-menu-content/src/item/core/index.vue.d.ts +0 -185
  75. package/components/routes-menu-content/src/item/ctx.d.ts +0 -14
  76. package/components/routes-menu-content/src/item/index.vue.d.ts +0 -316
  77. package/components/routes-menu-content/src/types.d.ts +0 -1
  78. package/components/sender/index.d.ts +0 -4
  79. package/components/sender/src/ctx.d.ts +0 -21
  80. package/components/sender/src/index.vue.d.ts +0 -484
  81. package/components/sender/src/types.d.ts +0 -1
  82. package/components/speech-button/index.d.ts +0 -4
  83. package/components/speech-button/src/RecordingIcon.vue.d.ts +0 -2
  84. package/components/speech-button/src/ctx.d.ts +0 -10
  85. package/components/speech-button/src/index.vue.d.ts +0 -22
  86. package/components/speech-button/src/types.d.ts +0 -1
  87. package/components/table-columns/index.d.ts +0 -5
  88. package/components/table-columns/src/ctx.d.ts +0 -66
  89. package/components/table-columns/src/el-ctx.d.ts +0 -63
  90. package/components/table-columns/src/index.vue.d.ts +0 -280
  91. package/components/table-columns/src/types.d.ts +0 -21
  92. package/components/tables-v1/index.d.ts +0 -5
  93. package/components/tables-v1/src/ctx.d.ts +0 -283
  94. package/components/tables-v1/src/el-ctx.d.ts +0 -272
  95. package/components/tables-v1/src/index.vue.d.ts +0 -2997
  96. package/components/tables-v1/src/types.d.ts +0 -4
  97. package/components/tables-v1-checkbox/index.d.ts +0 -5
  98. package/components/tables-v1-checkbox/src/ctx.d.ts +0 -322
  99. package/components/tables-v1-checkbox/src/index.vue.d.ts +0 -3788
  100. package/components/tables-v1-checkbox/src/types.d.ts +0 -1
  101. package/components/typing-markdown/index.d.ts +0 -4
  102. package/components/typing-markdown/src/core.d.ts +0 -3
  103. package/components/typing-markdown/src/ctx.d.ts +0 -33
  104. package/components/typing-markdown/src/index.vue.d.ts +0 -57
  105. package/components/typing-markdown/src/types.d.ts +0 -1
  106. package/components/vditor/index.d.ts +0 -5
  107. package/components/vditor/src/ctx.d.ts +0 -37
  108. package/components/vditor/src/handle-fullscreen.vue.d.ts +0 -18
  109. package/components/vditor/src/handle-value.vue.d.ts +0 -18
  110. package/components/vditor/src/index.vue.d.ts +0 -144
  111. package/components/vditor/src/types.d.ts +0 -9
  112. package/components/vditor/src/use.d.ts +0 -4
  113. package/fetch/PlusFetch/index.d.ts +0 -14
  114. package/fetch/PlusFetch/index.mjs +0 -638
  115. package/fetch/PlusFetch/types.d.ts +0 -54
  116. package/fetch/index.d.ts +0 -1
  117. package/fetch/index.mjs +0 -5
@@ -1,5 +1,5 @@
1
1
  import { ElAvatar } from 'element-plus';
2
- import { defineComponent, resolveComponent, openBlock, createBlock, normalizeStyle, withCtx, renderSlot } from 'vue';
2
+ import { defineComponent, resolveComponent, createBlock, openBlock, normalizeStyle, withCtx, renderSlot } from 'vue';
3
3
  import { _ as _export_sfc } from '../_plugin-vue_export-helper.mjs';
4
4
 
5
5
  const props = {
@@ -36,7 +36,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
36
36
  /* FORWARDED */
37
37
  }, 8, ["style"]);
38
38
  }
39
- var VkAvatar = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "/home/runner/work/vunk-plus/vunk-plus/packages/components/avatar/src/index.vue"]]);
39
+ var VkAvatar = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
40
40
 
41
41
  var types = /*#__PURE__*/Object.freeze({
42
42
  __proto__: null
@@ -0,0 +1,3 @@
1
+ .vk-broadcasting-markdown-web-speech-icon{
2
+ vertical-align: text-bottom;
3
+ }
@@ -0,0 +1,637 @@
1
+ import { VkTypingMarkdown } from '@vunk/plus/components/typing-markdown';
2
+ import { setData } from '@vunk/core';
3
+ import { defineComponent, createElementBlock, openBlock, createElementVNode, Fragment, createVNode, unref, withCtx, computed, onBeforeUnmount, onMounted, watch, shallowRef, nextTick, renderSlot, createCommentVNode, ref, watchEffect, resolveComponent, renderList, createBlock } from 'vue';
4
+ import markdownIt from 'markdown-it';
5
+ import { useDeferred } from '@vunk/core/composables';
6
+ import { ElIcon } from 'element-plus';
7
+ import { noop } from '@vunk/shared/function';
8
+ import { Deferred } from '@vunk/shared/promise';
9
+ import { _ as _export_sfc } from '../_plugin-vue_export-helper.mjs';
10
+
11
+ const md = markdownIt();
12
+ function defaultRender(mdText) {
13
+ const html = md.render(mdText);
14
+ const doc = new DOMParser().parseFromString(html, "text/html");
15
+ return doc.body.textContent || "";
16
+ }
17
+ var ParagraphStatus = /* @__PURE__ */ ((ParagraphStatus2) => {
18
+ ParagraphStatus2["initial"] = "initial";
19
+ ParagraphStatus2["processing"] = "processing";
20
+ ParagraphStatus2["pending"] = "pending";
21
+ ParagraphStatus2["fulfilled"] = "fulfilled";
22
+ ParagraphStatus2["rejected"] = "rejected";
23
+ return ParagraphStatus2;
24
+ })(ParagraphStatus || {});
25
+ var Broadcast = /* @__PURE__ */ ((Broadcast2) => {
26
+ Broadcast2["initial"] = "initial";
27
+ Broadcast2["playing"] = "playing";
28
+ Broadcast2["ended"] = "ended";
29
+ Broadcast2["paused"] = "paused";
30
+ Broadcast2["failed"] = "failed";
31
+ return Broadcast2;
32
+ })(Broadcast || {});
33
+
34
+ const props = {
35
+ /**
36
+ * @description 段落详情
37
+ */
38
+ data: {
39
+ type: Array,
40
+ default: void 0
41
+ },
42
+ /**
43
+ * @description md 文本
44
+ */
45
+ source: {
46
+ type: String,
47
+ default: ""
48
+ },
49
+ /**
50
+ * @description 游标阅读延迟
51
+ */
52
+ delay: {
53
+ type: Number,
54
+ default: 0
55
+ },
56
+ /**
57
+ * @description 段落切割符号
58
+ */
59
+ separators: {
60
+ type: Array,
61
+ default: () => ["\n\n", "\n"]
62
+ },
63
+ /**
64
+ * @description 暂停的
65
+ */
66
+ pause: {
67
+ type: Boolean,
68
+ default: false
69
+ },
70
+ /**
71
+ * @description 组件内会根据当前游标是否和 source 长度一致来判断,是否持续阅读, 当一致时,会关闭阅读状态。但若设置为 true,则会持续阅读, 这在动态接收数据时会有用
72
+ */
73
+ keepRead: {
74
+ type: Boolean,
75
+ default: false
76
+ },
77
+ /**
78
+ * @description 是否使用 web speech api
79
+ */
80
+ webSpeech: {
81
+ type: Boolean,
82
+ default: false
83
+ },
84
+ /**
85
+ * @description 是否使用自定义语音合成
86
+ */
87
+ textToSpeech: {
88
+ type: Function,
89
+ default: void 0
90
+ }
91
+ };
92
+ const emits = {
93
+ "setData": (e) => e,
94
+ "update:broadcasting": (_) => true,
95
+ "update:completed": (_) => true,
96
+ "update:error": (_) => true
97
+ };
98
+
99
+ /*! Element Plus Icons Vue v2.3.1 */
100
+
101
+ var close_bold_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
102
+ name: "CloseBold",
103
+ __name: "close-bold",
104
+ setup(__props) {
105
+ return (_ctx, _cache) => (openBlock(), createElementBlock("svg", {
106
+ xmlns: "http://www.w3.org/2000/svg",
107
+ viewBox: "0 0 1024 1024"
108
+ }, [
109
+ createElementVNode("path", {
110
+ fill: "currentColor",
111
+ d: "M195.2 195.2a64 64 0 0 1 90.496 0L512 421.504 738.304 195.2a64 64 0 0 1 90.496 90.496L602.496 512 828.8 738.304a64 64 0 0 1-90.496 90.496L512 602.496 285.696 828.8a64 64 0 0 1-90.496-90.496L421.504 512 195.2 285.696a64 64 0 0 1 0-90.496z"
112
+ })
113
+ ]));
114
+ }
115
+ });
116
+
117
+ // src/components/close-bold.vue
118
+ var close_bold_default = close_bold_vue_vue_type_script_setup_true_lang_default;
119
+
120
+ var _sfc_main$4 = /* @__PURE__ */ defineComponent({
121
+ __name: "speech-error",
122
+ setup(__props) {
123
+ return (_ctx, _cache) => {
124
+ return openBlock(), createElementBlock(
125
+ Fragment,
126
+ null,
127
+ [
128
+ createVNode(unref(ElIcon), {
129
+ color: "var(--el-color-danger)",
130
+ size: "1.5em",
131
+ style: {
132
+ verticalAlign: "text-bottom"
133
+ }
134
+ }, {
135
+ default: withCtx(() => [
136
+ createVNode(unref(close_bold_default))
137
+ ]),
138
+ _: 1
139
+ /* STABLE */
140
+ }),
141
+ _cache[0] || (_cache[0] = createElementVNode(
142
+ "span",
143
+ { style: {
144
+ color: "var(--el-color-danger)"
145
+ } },
146
+ " \u64AD\u62A5\u5931\u8D25 ",
147
+ -1
148
+ /* HOISTED */
149
+ ))
150
+ ],
151
+ 64
152
+ /* STABLE_FRAGMENT */
153
+ );
154
+ };
155
+ }
156
+ });
157
+
158
+ var _sfc_main$3 = /* @__PURE__ */ defineComponent({
159
+ components: {
160
+ SpeechError: _sfc_main$4
161
+ },
162
+ props: {
163
+ data: {
164
+ type: Object,
165
+ default: () => ({})
166
+ },
167
+ deferred: {
168
+ type: Object,
169
+ required: true
170
+ },
171
+ pause: {
172
+ type: Boolean,
173
+ default: false
174
+ },
175
+ /**
176
+ * @description 语音资源路径
177
+ */
178
+ url: {
179
+ type: String,
180
+ default: ""
181
+ }
182
+ },
183
+ setup(props) {
184
+ const value = defaultRender(props.data.value).replace(/\n/g, "");
185
+ const theData = computed(() => props.data);
186
+ if (!value.trim()) {
187
+ props.deferred.resolve(true);
188
+ theData.value.broadcast = Broadcast.ended;
189
+ return () => null;
190
+ }
191
+ const audioDef = useDeferred();
192
+ audioDef.promise.then(audio => {
193
+ audio.addEventListener("playing", onPlaying);
194
+ audio.addEventListener("pause", onPause);
195
+ audio.addEventListener("error", onError);
196
+ audio.addEventListener("ended", onEnded);
197
+ });
198
+ onBeforeUnmount(() => {
199
+ audioDef.value?.removeEventListener("playing", onPlaying);
200
+ audioDef.value?.removeEventListener("pause", onPause);
201
+ audioDef.value?.removeEventListener("error", onError);
202
+ audioDef.value?.removeEventListener("ended", onEnded);
203
+ });
204
+ function onPlaying() {
205
+ theData.value.broadcast = Broadcast.playing;
206
+ }
207
+ function onPause() {
208
+ theData.value.broadcast = Broadcast.paused;
209
+ }
210
+ function onError(err) {
211
+ theData.value.broadcast = Broadcast.failed;
212
+ props.deferred.reject(err);
213
+ }
214
+ function onEnded() {
215
+ theData.value.broadcast = Broadcast.ended;
216
+ props.deferred.resolve(true);
217
+ }
218
+ onMounted(() => {
219
+ watch(() => props.pause, v => {
220
+ if (props.data.status === ParagraphStatus.pending) {
221
+ if (v) {
222
+ audioDef.value?.pause();
223
+ } else {
224
+ if (theData.value.broadcast === Broadcast.failed || theData.value.broadcast === Broadcast.initial) {
225
+ audioDef.promise.then(audio => {
226
+ audio.play().catch(err => {
227
+ theData.value.broadcast = Broadcast.failed;
228
+ props.deferred.reject(err);
229
+ });
230
+ });
231
+ }
232
+ }
233
+ }
234
+ }, {
235
+ immediate: true
236
+ });
237
+ });
238
+ return () => createVNode(Fragment, null, [props.url && createVNode("audio", {
239
+ "src": props.url,
240
+ "ref": audioDef.resolve
241
+ }, null), theData.value.status === ParagraphStatus.rejected && createVNode(_sfc_main$4, null, null)]);
242
+ }
243
+ });
244
+
245
+ var _sfc_main$2 = /* @__PURE__ */ defineComponent({
246
+ __name: "paragraph",
247
+ props: {
248
+ enable: {
249
+ type: Boolean,
250
+ default: true
251
+ },
252
+ status: {
253
+ type: String,
254
+ default: ParagraphStatus.initial
255
+ },
256
+ pause: {
257
+ type: Boolean,
258
+ default: false
259
+ },
260
+ processing: {
261
+ type: Function,
262
+ default: noop
263
+ }
264
+ },
265
+ emits: ["update:status"],
266
+ setup(__props, { emit: __emit }) {
267
+ const props = __props;
268
+ const emit = __emit;
269
+ const theDef = shallowRef();
270
+ const processingDef = useDeferred();
271
+ onMounted(async () => {
272
+ emit("update:status", ParagraphStatus.processing);
273
+ await props.processing?.();
274
+ processingDef.resolve();
275
+ });
276
+ processingDef.promise.catch(() => {
277
+ emit("update:status", ParagraphStatus.rejected);
278
+ });
279
+ watch(() => props.enable, async (enable) => {
280
+ if (enable) {
281
+ init();
282
+ } else {
283
+ theDef.value = void 0;
284
+ }
285
+ }, { immediate: true });
286
+ async function init() {
287
+ const deferred = new Deferred();
288
+ await processingDef.promise;
289
+ emit("update:status", ParagraphStatus.pending);
290
+ deferred.promise.then(() => {
291
+ emit("update:status", ParagraphStatus.fulfilled);
292
+ }).catch((err) => {
293
+ console.error(err);
294
+ emit("update:status", ParagraphStatus.rejected);
295
+ });
296
+ theDef.value = void 0;
297
+ nextTick(() => {
298
+ theDef.value = deferred;
299
+ });
300
+ }
301
+ return (_ctx, _cache) => {
302
+ return __props.enable && theDef.value ? renderSlot(_ctx.$slots, "default", {
303
+ key: 0,
304
+ deferred: theDef.value
305
+ }) : createCommentVNode("v-if", true);
306
+ };
307
+ }
308
+ });
309
+
310
+ var _sfc_main$1 = /* @__PURE__ */ defineComponent({
311
+ components: {
312
+ SpeechError: _sfc_main$4
313
+ },
314
+ props: {
315
+ voice: {
316
+ type: null,
317
+ required: false
318
+ },
319
+ data: {
320
+ type: Object,
321
+ default: () => ({})
322
+ },
323
+ deferred: {
324
+ type: Object,
325
+ required: true
326
+ },
327
+ pause: {
328
+ type: Boolean,
329
+ default: false
330
+ }
331
+ },
332
+ setup(props) {
333
+ const value = defaultRender(props.data.value).replace(/\n/g, "");
334
+ const theData = computed(() => {
335
+ return props.data;
336
+ });
337
+ if (!value.trim()) {
338
+ props.deferred.resolve(true);
339
+ theData.value.broadcast = Broadcast.ended;
340
+ return () => null;
341
+ }
342
+ const utterThis = new SpeechSynthesisUtterance(value);
343
+ utterThis.onend = function () {
344
+ props.deferred.resolve(true);
345
+ theData.value.broadcast = Broadcast.ended;
346
+ };
347
+ utterThis.onstart = function () {
348
+ if (props.pause) return;
349
+ theData.value.broadcast = Broadcast.playing;
350
+ };
351
+ utterThis.onerror = function (err) {
352
+ props.deferred.reject(err);
353
+ theData.value.broadcast = Broadcast.failed;
354
+ window.speechSynthesis.cancel();
355
+ };
356
+ props.voice && (utterThis.voice = props.voice);
357
+ watch(() => props.pause, v => {
358
+ if (props.data.status === ParagraphStatus.pending) {
359
+ if (v) {
360
+ window.speechSynthesis.pause();
361
+ if (theData.value.broadcast === Broadcast.playing) {
362
+ theData.value.broadcast = Broadcast.paused;
363
+ }
364
+ } else {
365
+ window.speechSynthesis.resume();
366
+ if (theData.value.broadcast === Broadcast.failed || theData.value.broadcast === Broadcast.initial) {
367
+ if (props.data.start === 0) {
368
+ window.speechSynthesis.cancel();
369
+ }
370
+ console.log("start speaking");
371
+ window.speechSynthesis.speak(utterThis);
372
+ }
373
+ if (theData.value.broadcast === Broadcast.paused) {
374
+ theData.value.broadcast = Broadcast.playing;
375
+ }
376
+ }
377
+ }
378
+ }, {
379
+ immediate: true
380
+ });
381
+ return () => theData.value.status === ParagraphStatus.rejected && createVNode(_sfc_main$4, null, null);
382
+ }
383
+ });
384
+
385
+ var _sfc_main = defineComponent({
386
+ name: "VkBroadcastingMarkdown",
387
+ components: {
388
+ ParagraphView: _sfc_main$2,
389
+ VkTypingMarkdown,
390
+ WebSpeechView: _sfc_main$1,
391
+ CustomSpeechView: _sfc_main$3
392
+ },
393
+ props,
394
+ emits,
395
+ setup(props2, { emit }) {
396
+ const _data = ref([]);
397
+ const theData = computed(() => {
398
+ return props2.data ?? _data.value;
399
+ });
400
+ const handleSetData = (e) => {
401
+ if (props2.data === void 0) {
402
+ setData(_data.value, e);
403
+ return;
404
+ }
405
+ emit("setData", e);
406
+ };
407
+ const addParagraph = (paragraph) => {
408
+ const k = theData.value.length;
409
+ handleSetData({
410
+ k,
411
+ v: paragraph
412
+ });
413
+ };
414
+ const processingParagraph = (paragraph) => {
415
+ if (!props2.textToSpeech) {
416
+ return;
417
+ }
418
+ const value = defaultRender(paragraph.value);
419
+ return props2.textToSpeech(`${value}`).then((url) => {
420
+ paragraph.url = url;
421
+ });
422
+ };
423
+ const currentIndex = ref(0);
424
+ const isFinished = computed(() => {
425
+ return currentIndex.value >= props2.source.length;
426
+ });
427
+ const currentText = computed(() => {
428
+ return props2.source.substring(0, currentIndex.value);
429
+ });
430
+ const fulfilledTextValue = computed(() => {
431
+ if (theData.value.length === 0) {
432
+ return "......";
433
+ }
434
+ if (theData.value[0].broadcast === Broadcast.failed) {
435
+ return "";
436
+ }
437
+ if (theData.value[0].broadcast === Broadcast.initial) {
438
+ return "......";
439
+ }
440
+ return theData.value.filter(
441
+ (item) => item.status === ParagraphStatus.fulfilled || item.status === ParagraphStatus.pending
442
+ ).map((item) => item.value).join("");
443
+ });
444
+ const sortedSeparators = computed(() => {
445
+ return [...props2.separators].sort((a, b) => {
446
+ return a.length - b.length;
447
+ });
448
+ });
449
+ watch(isFinished, (val) => {
450
+ !val && write();
451
+ }, { immediate: true });
452
+ function write() {
453
+ const lastParagraph = theData.value.at(-1);
454
+ for (const separator of sortedSeparators.value) {
455
+ const separatorLen = separator.length;
456
+ const compareText = currentText.value.slice(
457
+ currentIndex.value - separatorLen,
458
+ currentIndex.value
459
+ );
460
+ if (compareText === separator) {
461
+ const start = lastParagraph?.end ?? 0;
462
+ const end = currentIndex.value;
463
+ const value = props2.source.slice(
464
+ start,
465
+ end
466
+ );
467
+ if (lastParagraph && separator.length >= value.length) {
468
+ if (lastParagraph.status === ParagraphStatus.initial) {
469
+ lastParagraph.end = end;
470
+ lastParagraph.value = props2.source.slice(
471
+ lastParagraph.start,
472
+ end
473
+ );
474
+ lastParagraph.separator = separator;
475
+ }
476
+ } else {
477
+ const paragraph = {
478
+ start,
479
+ separator,
480
+ end,
481
+ status: ParagraphStatus.initial,
482
+ value,
483
+ broadcast: Broadcast.initial
484
+ };
485
+ addParagraph(paragraph);
486
+ }
487
+ }
488
+ }
489
+ if (currentIndex.value < props2.source.length) {
490
+ currentIndex.value++;
491
+ setTimeout(write, props2.delay);
492
+ } else {
493
+ if (props2.keepRead) {
494
+ setTimeout(write, props2.delay);
495
+ return;
496
+ }
497
+ if (lastParagraph?.end === currentIndex.value) {
498
+ return;
499
+ }
500
+ const start = lastParagraph?.end ?? 0;
501
+ const end = currentIndex.value;
502
+ const value = props2.source.slice(start, end);
503
+ if (lastParagraph && lastParagraph.status === ParagraphStatus.initial && lastParagraph.separator === "") {
504
+ lastParagraph.end = end;
505
+ lastParagraph.value = props2.source.slice(
506
+ lastParagraph.start,
507
+ end
508
+ );
509
+ lastParagraph.separator = "";
510
+ } else {
511
+ const paragraph = {
512
+ start,
513
+ separator: "",
514
+ end,
515
+ status: ParagraphStatus.initial,
516
+ value,
517
+ broadcast: Broadcast.initial
518
+ };
519
+ addParagraph(paragraph);
520
+ }
521
+ }
522
+ }
523
+ const isBroadcasting = computed(() => {
524
+ return theData.value.some(
525
+ (item) => item.broadcast === Broadcast.playing
526
+ );
527
+ });
528
+ watchEffect(() => {
529
+ emit("update:broadcasting", isBroadcasting.value);
530
+ });
531
+ const isCompleted = computed(() => {
532
+ return props2.keepRead === false && theData.value.every(
533
+ (item) => item.status === ParagraphStatus.fulfilled
534
+ );
535
+ });
536
+ watchEffect(() => {
537
+ emit("update:completed", isCompleted.value);
538
+ });
539
+ const isError = computed(() => {
540
+ return theData.value.some(
541
+ (item) => item.status === ParagraphStatus.rejected
542
+ );
543
+ });
544
+ watchEffect(() => {
545
+ emit("update:error", isError.value);
546
+ });
547
+ function isPrevParagraphFulfilled(currentIndex2) {
548
+ return theData.value[currentIndex2 - 1] ? [
549
+ ParagraphStatus.fulfilled
550
+ ].includes(theData.value[currentIndex2 - 1].status) : true;
551
+ }
552
+ function isParagraphEnabled(currentIndex2) {
553
+ const isPrevFulfilled = isPrevParagraphFulfilled(currentIndex2);
554
+ return isPrevFulfilled;
555
+ }
556
+ return {
557
+ theData,
558
+ ParagraphStatus,
559
+ fulfilledTextValue,
560
+ isPrevParagraphFulfilled,
561
+ isParagraphEnabled,
562
+ processingParagraph
563
+ };
564
+ }
565
+ });
566
+
567
+ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
568
+ const _component_VkTypingMarkdown = resolveComponent("VkTypingMarkdown");
569
+ const _component_CustomSpeechView = resolveComponent("CustomSpeechView");
570
+ const _component_WebSpeechView = resolveComponent("WebSpeechView");
571
+ const _component_ParagraphView = resolveComponent("ParagraphView");
572
+ return openBlock(), createElementBlock(
573
+ Fragment,
574
+ null,
575
+ [
576
+ renderSlot(_ctx.$slots, "default", { paragraphs: _ctx.theData }, () => [
577
+ createCommentVNode(' <ElButton @click="() => console.log(theData)">\n log\n </ElButton> '),
578
+ createVNode(_component_VkTypingMarkdown, {
579
+ source: _ctx.fulfilledTextValue,
580
+ delay: 200,
581
+ pause: _ctx.pause
582
+ }, null, 8, ["source", "pause"])
583
+ ]),
584
+ (openBlock(true), createElementBlock(
585
+ Fragment,
586
+ null,
587
+ renderList(_ctx.theData, (item, index) => {
588
+ return openBlock(), createBlock(_component_ParagraphView, {
589
+ key: item.value,
590
+ status: item.status,
591
+ "onUpdate:status": ($event) => item.status = $event,
592
+ enable: _ctx.isParagraphEnabled(index),
593
+ processing: () => _ctx.processingParagraph(item)
594
+ }, {
595
+ default: withCtx(({ deferred }) => [
596
+ renderSlot(_ctx.$slots, "paragraph", {
597
+ data: item,
598
+ deferred
599
+ }, () => [
600
+ item.url ? (openBlock(), createBlock(_component_CustomSpeechView, {
601
+ key: 0,
602
+ url: item.url,
603
+ pause: _ctx.pause,
604
+ deferred,
605
+ data: item
606
+ }, null, 8, ["url", "pause", "deferred", "data"])) : createCommentVNode("v-if", true),
607
+ _ctx.webSpeech ? (openBlock(), createBlock(_component_WebSpeechView, {
608
+ key: 1,
609
+ pause: _ctx.pause,
610
+ deferred,
611
+ data: item
612
+ }, null, 8, ["pause", "deferred", "data"])) : createCommentVNode("v-if", true)
613
+ ])
614
+ ]),
615
+ _: 2
616
+ /* DYNAMIC */
617
+ }, 1032, ["status", "onUpdate:status", "enable", "processing"]);
618
+ }),
619
+ 128
620
+ /* KEYED_FRAGMENT */
621
+ ))
622
+ ],
623
+ 64
624
+ /* STABLE_FRAGMENT */
625
+ );
626
+ }
627
+ var VkBroadcastingMarkdown = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
628
+
629
+ var types = /*#__PURE__*/Object.freeze({
630
+ __proto__: null
631
+ });
632
+
633
+ VkBroadcastingMarkdown.install = (app) => {
634
+ app.component(VkBroadcastingMarkdown.name || "VkBroadcastingMarkdown", VkBroadcastingMarkdown);
635
+ };
636
+
637
+ export { Broadcast, ParagraphStatus, VkBroadcastingMarkdown, types as __VkBroadcastingMarkdown, VkBroadcastingMarkdown as default, defaultRender };