@8wave/ai-elements 0.103.0-beta.3 → 0.103.0-beta.4

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 (128) hide show
  1. package/dist/_chunks/PkLazyImg-CyeqD59M.js +34 -0
  2. package/dist/_chunks/{PkLazyImg-_389yCnQ.js.map → PkLazyImg-CyeqD59M.js.map} +1 -1
  3. package/dist/_chunks/{PkStreamingMarkdown-YJDdYD0E.js → PkStreamingMarkdown-DIkusrTI.js} +28 -28
  4. package/dist/_chunks/{PkStreamingMarkdown-YJDdYD0E.js.map → PkStreamingMarkdown-DIkusrTI.js.map} +1 -1
  5. package/dist/_chunks/PkToolRequestGeolocation-Cgus94KF.js +69 -0
  6. package/dist/_chunks/{PkToolRequestGeolocation-T16QI-Uv.js.map → PkToolRequestGeolocation-Cgus94KF.js.map} +1 -1
  7. package/dist/_chunks/{PkToolRequestOAuthConnection-C8e5np2q.js → PkToolRequestOAuthConnection-DsUpUh97.js} +21 -21
  8. package/dist/_chunks/{PkToolRequestOAuthConnection-C8e5np2q.js.map → PkToolRequestOAuthConnection-DsUpUh97.js.map} +1 -1
  9. package/dist/_chunks/PkToolShowArtifact-griVx9w3.js +93 -0
  10. package/dist/_chunks/{PkToolShowArtifact-D15GjBm6.js.map → PkToolShowArtifact-griVx9w3.js.map} +1 -1
  11. package/dist/_chunks/{PkToolShowCalendarEvent-D_GjXl2_.js → PkToolShowCalendarEvent-DyiNmqqo.js} +43 -43
  12. package/dist/_chunks/{PkToolShowCalendarEvent-D_GjXl2_.js.map → PkToolShowCalendarEvent-DyiNmqqo.js.map} +1 -1
  13. package/dist/_chunks/PkToolShowComparison-RA72YL7R.js +66 -0
  14. package/dist/_chunks/{PkToolShowComparison-Bp2rP2Hx.js.map → PkToolShowComparison-RA72YL7R.js.map} +1 -1
  15. package/dist/_chunks/{PkToolShowContactForm-NVzIu2t0.js → PkToolShowContactForm-BzDhv2yd.js} +41 -41
  16. package/dist/_chunks/{PkToolShowContactForm-NVzIu2t0.js.map → PkToolShowContactForm-BzDhv2yd.js.map} +1 -1
  17. package/dist/_chunks/{PkToolShowDiagram-BnZrDPVC.js → PkToolShowDiagram-DhXe8IPm.js} +79 -79
  18. package/dist/_chunks/{PkToolShowDiagram-BnZrDPVC.js.map → PkToolShowDiagram-DhXe8IPm.js.map} +1 -1
  19. package/dist/_chunks/{PkToolShowEmail-DCSj4328.js → PkToolShowEmail-CBmfy_I9.js} +34 -34
  20. package/dist/_chunks/{PkToolShowEmail-DCSj4328.js.map → PkToolShowEmail-CBmfy_I9.js.map} +1 -1
  21. package/dist/_chunks/PkToolShowForm-CzIfm5de.js +365 -0
  22. package/dist/_chunks/{PkToolShowForm-ztQFyFd9.js.map → PkToolShowForm-CzIfm5de.js.map} +1 -1
  23. package/dist/_chunks/PkToolShowImageGallery-CSIiRuSC.js +74 -0
  24. package/dist/_chunks/{PkToolShowImageGallery-DiOR0vYa.js.map → PkToolShowImageGallery-CSIiRuSC.js.map} +1 -1
  25. package/dist/_chunks/{PkToolShowLocation-CQmgakEo.js → PkToolShowLocation-BHoUqpx4.js} +4079 -4079
  26. package/dist/_chunks/{PkToolShowLocation-CQmgakEo.js.map → PkToolShowLocation-BHoUqpx4.js.map} +1 -1
  27. package/dist/_chunks/PkToolShowMessage-CpDmPfCG.js +77 -0
  28. package/dist/_chunks/{PkToolShowMessage-BysjJ1oS.js.map → PkToolShowMessage-CpDmPfCG.js.map} +1 -1
  29. package/dist/_chunks/{PkToolShowProductList-D-JXSRmA.js → PkToolShowProductList-B8uuIvGo.js} +28 -28
  30. package/dist/_chunks/{PkToolShowProductList-D-JXSRmA.js.map → PkToolShowProductList-B8uuIvGo.js.map} +1 -1
  31. package/dist/_chunks/{PkToolShowQrCode-BcIwuGqm.js → PkToolShowQrCode-CD2lo3O0.js} +23 -23
  32. package/dist/_chunks/{PkToolShowQrCode-BcIwuGqm.js.map → PkToolShowQrCode-CD2lo3O0.js.map} +1 -1
  33. package/dist/_chunks/{PkToolShowSources-U7etupUP.js → PkToolShowSources-JxaTAEpc.js} +98 -98
  34. package/dist/_chunks/{PkToolShowSources-U7etupUP.js.map → PkToolShowSources-JxaTAEpc.js.map} +1 -1
  35. package/dist/_chunks/{PkToolShowSuggestedReply-Dqe4gtEY.js → PkToolShowSuggestedReply-BTxqEwEm.js} +18 -18
  36. package/dist/_chunks/{PkToolShowSuggestedReply-Dqe4gtEY.js.map → PkToolShowSuggestedReply-BTxqEwEm.js.map} +1 -1
  37. package/dist/_chunks/{PkToolShowVideo-DYMhfXKH.js → PkToolShowVideo-CVksKdPD.js} +17 -17
  38. package/dist/_chunks/{PkToolShowVideo-DYMhfXKH.js.map → PkToolShowVideo-CVksKdPD.js.map} +1 -1
  39. package/dist/_chunks/{PkToolShowWeather-D_pJe5DI.js → PkToolShowWeather-IDwTDozU.js} +68 -68
  40. package/dist/_chunks/{PkToolShowWeather-D_pJe5DI.js.map → PkToolShowWeather-IDwTDozU.js.map} +1 -1
  41. package/dist/_chunks/PkToolShowWebPages-D9Yst_2O.js +78 -0
  42. package/dist/_chunks/{PkToolShowWebPages-CPNgXzrS.js.map → PkToolShowWebPages-D9Yst_2O.js.map} +1 -1
  43. package/dist/_chunks/{PkUrl-C3gMPCjz.js → PkUrl-B3FTSURr.js} +19 -19
  44. package/dist/_chunks/{PkUrl-C3gMPCjz.js.map → PkUrl-B3FTSURr.js.map} +1 -1
  45. package/dist/_chunks/{VvCheckbox.es-CEfwI84M.js → VvCheckbox.es-C_dlDzrr.js} +78 -78
  46. package/dist/_chunks/{VvCheckbox.es-CEfwI84M.js.map → VvCheckbox.es-C_dlDzrr.js.map} +1 -1
  47. package/dist/_chunks/{VvCheckboxGroup.es-B-eWqe8G.js → VvCheckboxGroup.es-hY0kWpC2.js} +197 -197
  48. package/dist/_chunks/{VvCheckboxGroup.es-B-eWqe8G.js.map → VvCheckboxGroup.es-hY0kWpC2.js.map} +1 -1
  49. package/dist/_chunks/VvCombobox.es-DxhDF7ab.js +2044 -0
  50. package/dist/_chunks/{VvCombobox.es-CfRJtWOd.js.map → VvCombobox.es-DxhDF7ab.js.map} +1 -1
  51. package/dist/_chunks/{VvInputText.es-B0HHD6Th.js → VvInputText.es-CdpU8kvP.js} +460 -460
  52. package/dist/_chunks/{VvInputText.es-B0HHD6Th.js.map → VvInputText.es-CdpU8kvP.js.map} +1 -1
  53. package/dist/_chunks/{VvRadio.es-B3u8JJFF.js → VvRadio.es-BruZ5FHR.js} +144 -144
  54. package/dist/_chunks/{VvRadio.es-B3u8JJFF.js.map → VvRadio.es-BruZ5FHR.js.map} +1 -1
  55. package/dist/_chunks/{VvRadioGroup.es--AMV1wAw.js → VvRadioGroup.es-DSv6UdEy.js} +148 -148
  56. package/dist/_chunks/{VvRadioGroup.es--AMV1wAw.js.map → VvRadioGroup.es-DSv6UdEy.js.map} +1 -1
  57. package/dist/_chunks/{VvSelect.es-BfrDID0e.js → VvSelect.es-C244CAei.js} +155 -155
  58. package/dist/_chunks/{VvSelect.es-BfrDID0e.js.map → VvSelect.es-C244CAei.js.map} +1 -1
  59. package/dist/_chunks/VvTextarea.es-DbaPIcWl.js +1166 -0
  60. package/dist/_chunks/{VvTextarea.es-CAzFW944.js.map → VvTextarea.es-DbaPIcWl.js.map} +1 -1
  61. package/dist/_chunks/{dist-BvSGMyWS.js → dist-BgJVX4FG.js} +12 -12
  62. package/dist/_chunks/{dist-BvSGMyWS.js.map → dist-BgJVX4FG.js.map} +1 -1
  63. package/dist/_chunks/{dist-TFHdNK0W.js → dist-C5Y-NI3i.js} +230 -230
  64. package/dist/_chunks/{dist-TFHdNK0W.js.map → dist-C5Y-NI3i.js.map} +1 -1
  65. package/dist/_chunks/{esm-CUYQMpeA.js → esm-BTbGj6W3.js} +25 -25
  66. package/dist/_chunks/{esm-CUYQMpeA.js.map → esm-BTbGj6W3.js.map} +1 -1
  67. package/dist/_chunks/{floating-ui.vue-Br_zOLJv.js → floating-ui.vue-CoA4oagI.js} +16 -16
  68. package/dist/_chunks/{floating-ui.vue-Br_zOLJv.js.map → floating-ui.vue-CoA4oagI.js.map} +1 -1
  69. package/dist/_chunks/{iconify-BGSTR7vH.js → iconify-6ObncgfH.js} +36 -36
  70. package/dist/_chunks/{iconify-BGSTR7vH.js.map → iconify-6ObncgfH.js.map} +1 -1
  71. package/dist/_chunks/{index.es-B9rhQl9Z.js → index.es-BbyodRh9.js} +258 -258
  72. package/dist/_chunks/{index.es-B9rhQl9Z.js.map → index.es-BbyodRh9.js.map} +1 -1
  73. package/dist/_chunks/index.es-gbmOq0Nu.js +3124 -0
  74. package/dist/_chunks/index.es-gbmOq0Nu.js.map +1 -0
  75. package/dist/_chunks/{rolldown-runtime-CEFd7nDs.js → rolldown-runtime-CoeuCKPe.js} +4 -11
  76. package/dist/_chunks/{src-BjFv9Ag8.js → src-CIEdKLKO.js} +2 -2
  77. package/dist/_chunks/{src-BjFv9Ag8.js.map → src-CIEdKLKO.js.map} +1 -1
  78. package/dist/_chunks/useImageFallback-BAsLRsyg.js +19 -0
  79. package/dist/_chunks/{useImageFallback-8kfLDjXm.js.map → useImageFallback-BAsLRsyg.js.map} +1 -1
  80. package/dist/_chunks/{useLightbox-Bq6k-Wlt.js → useLightbox-Epg2fN87.js} +7 -7
  81. package/dist/_chunks/{useLightbox-Bq6k-Wlt.js.map → useLightbox-Epg2fN87.js.map} +1 -1
  82. package/dist/_chunks/useShortUrlResolver--HRa6Od3.js +72 -0
  83. package/dist/_chunks/{useShortUrlResolver-BTJM8XRw.js.map → useShortUrlResolver--HRa6Od3.js.map} +1 -1
  84. package/dist/_chunks/{vue-i18n-BJ7nxwO3.js → vue-i18n-t25g63Be.js} +81 -81
  85. package/dist/_chunks/{vue-i18n-BJ7nxwO3.js.map → vue-i18n-t25g63Be.js.map} +1 -1
  86. package/dist/_chunks/vue.runtime.esm-bundler-B3bThTaf.js +3747 -0
  87. package/dist/_chunks/vue.runtime.esm-bundler-B3bThTaf.js.map +1 -0
  88. package/dist/ai-elements.es.js +1861 -1861
  89. package/dist/ai-elements.es.js.map +1 -1
  90. package/dist-vue/PkChatbot.js +1 -1
  91. package/dist-vue/PkChatbotAuth.js +1 -1
  92. package/dist-vue/PkChatbotFeedbackForm.js +1 -1
  93. package/dist-vue/PkChatbotMessages.js +1 -1
  94. package/dist-vue/PkChatbotViewChat.js +1 -1
  95. package/dist-vue/_chunks/{PkChatbot-DZ6TaZHh.js → PkChatbot-Ch8FlZjC.js} +2 -2
  96. package/dist-vue/_chunks/{PkChatbot-DZ6TaZHh.js.map → PkChatbot-Ch8FlZjC.js.map} +1 -1
  97. package/dist-vue/_chunks/{PkChatbotAuth-CqwTN8ih.js → PkChatbotAuth-DvnmIukc.js} +2 -2
  98. package/dist-vue/_chunks/{PkChatbotAuth-CqwTN8ih.js.map → PkChatbotAuth-DvnmIukc.js.map} +1 -1
  99. package/dist-vue/_chunks/{PkChatbotFeedbackForm-nEevDHmI.js → PkChatbotFeedbackForm-D0RNa7bE.js} +2 -2
  100. package/dist-vue/_chunks/{PkChatbotFeedbackForm-nEevDHmI.js.map → PkChatbotFeedbackForm-D0RNa7bE.js.map} +1 -1
  101. package/dist-vue/_chunks/{PkChatbotMessages-BgsyN-mB.js → PkChatbotMessages-DGO0WIqx.js} +4 -4
  102. package/dist-vue/_chunks/{PkChatbotMessages-BgsyN-mB.js.map → PkChatbotMessages-DGO0WIqx.js.map} +1 -1
  103. package/dist-vue/_chunks/{PkChatbotViewChat-0g30_sQH.js → PkChatbotViewChat-Dkz8dq8N.js} +3 -3
  104. package/dist-vue/_chunks/{PkChatbotViewChat-0g30_sQH.js.map → PkChatbotViewChat-Dkz8dq8N.js.map} +1 -1
  105. package/dist-vue/_chunks/{PkToolShowContactForm-CMK4zR2J.js → PkToolShowContactForm-CkkWxSSz.js} +2 -2
  106. package/dist-vue/_chunks/{PkToolShowContactForm-CMK4zR2J.js.map → PkToolShowContactForm-CkkWxSSz.js.map} +1 -1
  107. package/dist-vue/_chunks/{PkToolShowDiagram-DoklcF3f.js → PkToolShowDiagram-D0NBG-Gy.js} +2 -2
  108. package/dist-vue/_chunks/{PkToolShowDiagram-DoklcF3f.js.map → PkToolShowDiagram-D0NBG-Gy.js.map} +1 -1
  109. package/dist-vue/_chunks/{index.es-BT6Jr2yi.js → index.es-BKxzs6Sh.js} +2 -2
  110. package/dist-vue/_chunks/{index.es-BT6Jr2yi.js.map → index.es-BKxzs6Sh.js.map} +1 -1
  111. package/dist-vue/index.js +10 -10
  112. package/package.json +2 -2
  113. package/dist/_chunks/PkLazyImg-_389yCnQ.js +0 -34
  114. package/dist/_chunks/PkToolRequestGeolocation-T16QI-Uv.js +0 -69
  115. package/dist/_chunks/PkToolShowArtifact-D15GjBm6.js +0 -93
  116. package/dist/_chunks/PkToolShowComparison-Bp2rP2Hx.js +0 -66
  117. package/dist/_chunks/PkToolShowForm-ztQFyFd9.js +0 -365
  118. package/dist/_chunks/PkToolShowImageGallery-DiOR0vYa.js +0 -74
  119. package/dist/_chunks/PkToolShowMessage-BysjJ1oS.js +0 -77
  120. package/dist/_chunks/PkToolShowWebPages-CPNgXzrS.js +0 -78
  121. package/dist/_chunks/VvCombobox.es-CfRJtWOd.js +0 -2044
  122. package/dist/_chunks/VvTextarea.es-CAzFW944.js +0 -1166
  123. package/dist/_chunks/index.es-DvV0VhDa.js +0 -9832
  124. package/dist/_chunks/index.es-DvV0VhDa.js.map +0 -1
  125. package/dist/_chunks/useImageFallback-8kfLDjXm.js +0 -19
  126. package/dist/_chunks/useShortUrlResolver-BTJM8XRw.js +0 -72
  127. package/dist/_chunks/vue.runtime.esm-bundler-DF2of3lp.js +0 -5007
  128. package/dist/_chunks/vue.runtime.esm-bundler-DF2of3lp.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowSuggestedReply-Dqe4gtEY.js","names":[],"sources":["../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n import { isVoiceRenderAck } from 'models'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n // A chip drawn during a CALL arrives already resolved: the turn could\n // not wait for a tap, so the backend closed the tool with the note\n // that it was drawn (see `isVoiceRenderAck`, same rule as the forms).\n // The note is not a tap, and without this the chips of every spoken\n // turn rendered dead.\n return (\n (toolPart.value?.state === 'input-available' ||\n isVoiceRenderAck(toolPart.value?.output)) &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n import { isVoiceRenderAck } from 'models'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n // A chip drawn during a CALL arrives already resolved: the turn could\n // not wait for a tap, so the backend closed the tool with the note\n // that it was drawn (see `isVoiceRenderAck`, same rule as the forms).\n // The note is not a tap, and without this the chips of every spoken\n // turn rendered dead.\n return (\n (toolPart.value?.state === 'input-available' ||\n isVoiceRenderAck(toolPart.value?.output)) &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n import { isVoiceRenderAck } from 'models'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n // A chip drawn during a CALL arrives already resolved: the turn could\n // not wait for a tap, so the backend closed the tool with the note\n // that it was drawn (see `isVoiceRenderAck`, same rule as the forms).\n // The note is not a tap, and without this the chips of every spoken\n // turn rendered dead.\n return (\n (toolPart.value?.state === 'input-available' ||\n isVoiceRenderAck(toolPart.value?.output)) &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n"],"mappings":";;;;;;;;;;;;;EAMI,IAAM,IAAQ,GAIR,IAAO,GAIP,IAAW,QACN,KAAK,MAAM,KAAK,UAAU,EAAM,IAAI,CAAC,CAY/C,GAGK,IAAc,QAA6B;GAC7C,IAAM,IAAQ,EAAS,OAAO;GAW9B,OAVK,IAGD,EAAM,aAAa,SACZ,EAAM,cAGb,EAAM,QACC,CAAC;IAAE,OAAO,EAAM;IAAO,QAAQ,EAAM,UAAU,EAAM;GAAM,CAAC,IAEhE,CAAC,IATG,CAAC;EAUhB,CAAC,GAEK,IAAe,EAAmB,IAAI,GAEtC,IAAgB,SAOb,EAAS,OAAO,UAAU,qBACvB,EAAiB,EAAS,OAAO,MAAM,MAC3C,EAAa,UAAU,IAE9B;EAED,SAAS,EAAY,GAAe;GAChC,IAAI,CAAC,EAAc,OACf;GAEJ,EAAa,QAAQ;GACrB,IAAM,IAAa,EAAY,MAAM,IAC/B,IAAQ,GAAY,UAAU,GAAY;GAChD,AAAI,KACA,EAAK,UAAU,CAAK;EAE5B;;;GAIW,OAAA,EAAA,MAAY,UAAvB,EAAA,GAAA,EAiBM,OAjBN,GAiBM,EAhBF,EAAA,EAAA,GAAA,EAeS,GAAA,MAAA,EAdyB,EAAA,QAAtB,GAAY,OADxB,EAAA,GAAA,EAeS,UAAA;IAbJ,KAAK;IACN,MAAK;IACL,OAAK,EAAA,CAAC,iCAA+B;KACG,cAAA,EAAA,UAAiB;KAAuC,eAAA,CAAA,EAAA;;IAI/F,UAAQ,CAAG,EAAA;IACX,SAAK,GAAA,MAAO,EAAY,CAAK,GAAA,CAAA,MAAA,CAAA;GAC9B,GAAA,CAAA,EAE4C,GAAA;IADxC,MAAK;IACL,OAAM;GACV,CAAA,GAAA,EAAmC,QAAA,MAAA,EAA1B,EAAW,KAAK,GAAA,CAAA,CAAA,GAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"PkToolShowSuggestedReply-BTxqEwEm.js","names":[],"sources":["../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n import { isVoiceRenderAck } from 'models'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n // A chip drawn during a CALL arrives already resolved: the turn could\n // not wait for a tap, so the backend closed the tool with the note\n // that it was drawn (see `isVoiceRenderAck`, same rule as the forms).\n // The note is not a tap, and without this the chips of every spoken\n // turn rendered dead.\n return (\n (toolPart.value?.state === 'input-available' ||\n isVoiceRenderAck(toolPart.value?.output)) &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n import { isVoiceRenderAck } from 'models'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n // A chip drawn during a CALL arrives already resolved: the turn could\n // not wait for a tap, so the backend closed the tool with the note\n // that it was drawn (see `isVoiceRenderAck`, same rule as the forms).\n // The note is not a tap, and without this the chips of every spoken\n // turn rendered dead.\n return (\n (toolPart.value?.state === 'input-available' ||\n isVoiceRenderAck(toolPart.value?.output)) &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n import { isVoiceRenderAck } from 'models'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n // A chip drawn during a CALL arrives already resolved: the turn could\n // not wait for a tap, so the backend closed the tool with the note\n // that it was drawn (see `isVoiceRenderAck`, same rule as the forms).\n // The note is not a tap, and without this the chips of every spoken\n // turn rendered dead.\n return (\n (toolPart.value?.state === 'input-available' ||\n isVoiceRenderAck(toolPart.value?.output)) &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n"],"mappings":";;;;;;;;;;;;;EAMI,IAAM,IAAQ,GAIR,IAAO,GAIP,IAAW,QACN,KAAK,MAAM,KAAK,UAAU,EAAM,IAAI,CAAC,CAY/C,GAGK,IAAc,QAA6B;GAC7C,IAAM,IAAQ,EAAS,OAAO;GAW9B,OAVK,IAGD,EAAM,aAAa,SACZ,EAAM,cAGb,EAAM,QACC,CAAC;IAAE,OAAO,EAAM;IAAO,QAAQ,EAAM,UAAU,EAAM;GAAM,CAAC,IAEhE,CAAC,IATG,CAAC;EAUhB,CAAC,GAEK,IAAe,EAAmB,IAAI,GAEtC,IAAgB,SAOb,EAAS,OAAO,UAAU,qBACvB,EAAiB,EAAS,OAAO,MAAM,MAC3C,EAAa,UAAU,IAE9B;EAED,SAAS,EAAY,GAAe;GAChC,IAAI,CAAC,EAAc,OACf;GAEJ,EAAa,QAAQ;GACrB,IAAM,IAAa,EAAY,MAAM,IAC/B,IAAQ,GAAY,UAAU,GAAY;GAChD,AAAI,KACA,EAAK,UAAU,CAAK;EAE5B;;;GAIW,OAAA,EAAA,MAAY,UAAvB,EAAA,GAAA,EAiBM,OAjBN,GAiBM,EAhBF,EAAA,EAAA,GAAA,EAeS,GAAA,MAAA,EAdyB,EAAA,QAAtB,GAAY,OADxB,EAAA,GAAA,EAeS,UAAA;IAbJ,KAAK;IACN,MAAK;IACL,OAAK,EAAA,CAAC,iCAA+B;KACG,cAAA,EAAA,UAAiB;KAAuC,eAAA,CAAA,EAAA;;IAI/F,UAAQ,CAAG,EAAA;IACX,SAAK,GAAA,MAAO,EAAY,CAAK,GAAA,CAAA,MAAA,CAAA;GAC9B,GAAA,CAAA,EAE4C,GAAA;IADxC,MAAK;IACL,OAAM;GACV,CAAA,GAAA,EAAmC,QAAA,MAAA,EAA1B,EAAW,KAAK,GAAA,CAAA,CAAA,GAAA,IAAA,CAAA"}
@@ -1,6 +1,6 @@
1
- import { B as e, R as t, S as n, f as r, g as i, h as a, k as o, kt as s, qt as c, v as l, w as u, y as d } from "./vue.runtime.esm-bundler-DF2of3lp.js";
2
- import "./src-BjFv9Ag8.js";
3
- import { u as f } from "./index.es-DvV0VhDa.js";
1
+ import { C as e, L as t, O as n, Tt as r, _ as i, d as a, h as o, m as s, v as c, x as l, xt as u, z as d } from "./vue.runtime.esm-bundler-B3bThTaf.js";
2
+ import "./src-CIEdKLKO.js";
3
+ import { p as f } from "./index.es-gbmOq0Nu.js";
4
4
  //#region ../../packages/utils/src/video-source.ts
5
5
  var p = (e) => e.replace(/[^a-zA-Z0-9_-]/g, ""), m = (e, t) => e === t || e.endsWith(`.${t}`), h = (e) => {
6
6
  if (e.hostname.endsWith("youtu.be")) return p(e.pathname.split("/")[1] ?? "") || null;
@@ -53,7 +53,7 @@ function _(e, t) {
53
53
  embedUrl: e
54
54
  };
55
55
  }
56
- o(), s();
56
+ n(), u();
57
57
  var v = {
58
58
  key: 0,
59
59
  class: "border border-surface-3 rounded-xl w-full overflow-hidden bg-surface"
@@ -67,25 +67,25 @@ var v = {
67
67
  }, E = ["src", "title"], D = {
68
68
  key: 3,
69
69
  class: "text-12 text-word-3 mt-sm"
70
- }, O = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", k = /* @__PURE__ */ u({
70
+ }, O = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", k = /* @__PURE__ */ e({
71
71
  __name: "PkToolShowVideo",
72
72
  props: { part: { type: null } },
73
- setup(o) {
74
- let s = o, u = a(() => (s.part.input?.videos ?? []).map((e) => ({
73
+ setup(e) {
74
+ let n = e, u = s(() => (n.part.input?.videos ?? []).map((e) => ({
75
75
  ...e,
76
76
  source: _(e.url, e.provider)
77
77
  })));
78
- return (a, o) => {
78
+ return (e, n) => {
79
79
  let s = f;
80
- return u.value.length ? (t(), d("div", v, [i("div", y, [n(s, {
80
+ return u.value.length ? (t(), c("div", v, [o("div", y, [l(s, {
81
81
  name: "ri:film-line",
82
82
  class: "text-16"
83
- }), i("strong", b, c(a.$t("label.video")), 1)]), i("div", x, [(t(!0), d(r, null, e(u.value, (e) => (t(), d("div", {
83
+ }), o("strong", b, r(e.$t("label.video")), 1)]), o("div", x, [(t(!0), c(a, null, d(u.value, (e) => (t(), c("div", {
84
84
  key: e.url,
85
85
  class: "flex flex-col"
86
86
  }, [
87
- e.title ? (t(), d("strong", S, c(e.title), 1)) : l("", !0),
88
- e.source.provider === "file" ? (t(), d("video", {
87
+ e.title ? (t(), c("strong", S, r(e.title), 1)) : i("", !0),
88
+ e.source.provider === "file" ? (t(), c("video", {
89
89
  key: 1,
90
90
  src: e.source.embedUrl,
91
91
  poster: e.poster,
@@ -97,11 +97,11 @@ var v = {
97
97
  "aspect-ratio": "16 / 9",
98
98
  "max-height": "480px"
99
99
  }
100
- }, [i("a", {
100
+ }, [o("a", {
101
101
  href: e.url,
102
102
  target: "_blank",
103
103
  rel: "noopener noreferrer"
104
- }, c(e.title ?? e.url), 9, w)], 8, C)) : (t(), d("div", T, [i("iframe", {
104
+ }, r(e.title ?? e.url), 9, w)], 8, C)) : (t(), c("div", T, [o("iframe", {
105
105
  src: e.source.embedUrl,
106
106
  title: e.title ?? e.url,
107
107
  loading: "lazy",
@@ -110,12 +110,12 @@ var v = {
110
110
  allowfullscreen: "",
111
111
  class: "absolute inset-0 w-full h-full border-0"
112
112
  }, null, 8, E)])),
113
- e.description ? (t(), d("span", D, c(e.description), 1)) : l("", !0)
114
- ]))), 128))])])) : l("", !0);
113
+ e.description ? (t(), c("span", D, r(e.description), 1)) : i("", !0)
114
+ ]))), 128))])])) : i("", !0);
115
115
  };
116
116
  }
117
117
  });
118
118
  //#endregion
119
119
  export { k as default };
120
120
 
121
- //# sourceMappingURL=PkToolShowVideo-DYMhfXKH.js.map
121
+ //# sourceMappingURL=PkToolShowVideo-CVksKdPD.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowVideo-DYMhfXKH.js","names":["$t"],"sources":["../../../../packages/utils/src/video-source.ts","../../../../packages/components/src/chat/PkToolShowVideo.vue","../../../../packages/components/src/chat/PkToolShowVideo.vue"],"sourcesContent":["/**\n * Video source parsing shared by the backend platform renderer and the frontend\n * player component, so both classify a video URL the same way.\n *\n * A URL is either a known provider (YouTube/Vimeo), which plays through the\n * provider's iframe embed, or a direct media file (`file`), which plays in a\n * native `<video>` element. Detection is by URL shape; an explicit `hint` is\n * used only as a fallback when the URL alone is inconclusive.\n */\n\nexport type VideoProvider = 'youtube' | 'vimeo' | 'file'\n\nexport interface ParsedVideoSource {\n provider: VideoProvider\n /** The original URL, unchanged. */\n url: string\n /**\n * The URL to actually load: the provider iframe embed URL for\n * YouTube/Vimeo, or the direct file URL for `file`.\n */\n embedUrl: string\n /** The provider video id (providers only). */\n videoId?: string\n /**\n * A preview image URL derived from the provider, when one is available\n * without an extra API call (currently YouTube only). Lets a link-only\n * surface (e.g. a Teams card) show a thumbnail instead of a bare link.\n */\n thumbnailUrl?: string\n}\n\n/** Keep only characters that are legal in a provider video id. */\nconst sanitizeId = (raw: string): string => raw.replace(/[^a-zA-Z0-9_-]/g, '')\n\n/**\n * True when `host` is exactly `domain` or a subdomain of it. Guards against\n * lookalike hosts (e.g. `notyoutube.com`) that a bare substring check would\n * misclassify.\n */\nconst hostMatches = (host: string, domain: string): boolean =>\n host === domain || host.endsWith(`.${domain}`)\n\n/** Extract the YouTube video id from any of its URL shapes, or null. */\nconst youtubeId = (u: URL): string | null => {\n // youtu.be/<id>\n if (u.hostname.endsWith('youtu.be')) {\n return sanitizeId(u.pathname.split('/')[1] ?? '') || null\n }\n // youtube.com/watch?v=<id>\n const v = u.searchParams.get('v')\n if (v) {\n return sanitizeId(v) || null\n }\n // youtube.com/shorts/<id>, /embed/<id>, /v/<id>\n const m = u.pathname.match(/^\\/(?:shorts|embed|v)\\/([^/?#]+)/)\n return m ? sanitizeId(m[1]) || null : null\n}\n\n/** Extract the Vimeo (numeric) video id, or null. */\nconst vimeoId = (u: URL): string | null => {\n // player.vimeo.com/video/<id> or vimeo.com/<id>\n const m = u.pathname.match(/(?:^|\\/)(\\d+)(?:$|[/?#])/)\n return m ? m[1] : null\n}\n\n/**\n * Classify a video URL into a provider + a loadable embed/file URL.\n * Falls back to `file` (native `<video>`) for anything not recognized as a\n * supported provider, or when a provider is matched but no id can be extracted.\n */\nexport function parseVideoSource(\n url: string,\n hint?: VideoProvider,\n): ParsedVideoSource {\n let u: URL | undefined\n try {\n u = new URL(url)\n } catch {\n // Not an absolute URL: treat as a direct file reference.\n return { provider: 'file', url, embedUrl: url }\n }\n\n const host = u.hostname.toLowerCase()\n\n const isYouTube =\n hostMatches(host, 'youtube.com') ||\n hostMatches(host, 'youtu.be') ||\n hostMatches(host, 'youtube-nocookie.com')\n if (isYouTube) {\n const id = youtubeId(u)\n if (id) {\n return {\n provider: 'youtube',\n url,\n videoId: id,\n embedUrl: `https://www.youtube-nocookie.com/embed/${id}`,\n thumbnailUrl: `https://img.youtube.com/vi/${id}/hqdefault.jpg`,\n }\n }\n }\n\n if (hostMatches(host, 'vimeo.com')) {\n const id = vimeoId(u)\n if (id) {\n return {\n provider: 'vimeo',\n url,\n videoId: id,\n embedUrl: `https://player.vimeo.com/video/${id}`,\n }\n }\n }\n\n // Honor an explicit provider hint only if we could not extract an id from a\n // provider URL (so a caller-tagged provider link still routes to an iframe\n // via its original URL rather than a broken native <video>).\n if (hint && hint !== 'file') {\n return { provider: hint, url, embedUrl: url }\n }\n\n return { provider: 'file', url, embedUrl: url }\n}\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { parseVideoSource, type VideoProvider } from 'utils'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n interface VideoInput {\n url: string\n title?: string\n description?: string\n poster?: string\n provider?: VideoProvider\n }\n\n // Permissions granted to provider embeds (YouTube/Vimeo players).\n const IFRAME_ALLOW =\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n\n const videos = computed(() => {\n const part = props.part as { input?: { videos?: VideoInput[] } }\n return (part.input?.videos ?? []).map((video) => ({\n ...video,\n source: parseVideoSource(video.url, video.provider),\n }))\n })\n</script>\n\n<template>\n <div\n v-if=\"videos.length\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40\">\n <VvIcon name=\"ri:film-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.video') }}\n </strong>\n </div>\n <div class=\"p-sm flex flex-col gap-16\">\n <div v-for=\"video in videos\" :key=\"video.url\" class=\"flex flex-col\">\n <strong v-if=\"video.title\" class=\"font-bold text-14 mb-sm\">\n {{ video.title }}\n </strong>\n <!-- Direct file: native player. Handles MP4/WebM/OGG and works\n inside the widget's Shadow DOM without any extra CSS. -->\n <video\n v-if=\"video.source.provider === 'file'\"\n :src=\"video.source.embedUrl\"\n :poster=\"video.poster\"\n controls\n preload=\"metadata\"\n playsinline\n class=\"w-full rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9; max-height: 480px\">\n <a\n :href=\"video.url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n {{ video.title ?? video.url }}\n </a>\n </video>\n <!-- Provider (YouTube/Vimeo): iframe embed, 16:9 responsive. -->\n <div\n v-else\n class=\"relative w-full overflow-hidden rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9\">\n <iframe\n :src=\"video.source.embedUrl\"\n :title=\"video.title ?? video.url\"\n loading=\"lazy\"\n referrerpolicy=\"strict-origin-when-cross-origin\"\n :allow=\"IFRAME_ALLOW\"\n allowfullscreen\n class=\"absolute inset-0 w-full h-full border-0\"></iframe>\n </div>\n <span\n v-if=\"video.description\"\n class=\"text-12 text-word-3 mt-sm\">\n {{ video.description }}\n </span>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { parseVideoSource, type VideoProvider } from 'utils'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n interface VideoInput {\n url: string\n title?: string\n description?: string\n poster?: string\n provider?: VideoProvider\n }\n\n // Permissions granted to provider embeds (YouTube/Vimeo players).\n const IFRAME_ALLOW =\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n\n const videos = computed(() => {\n const part = props.part as { input?: { videos?: VideoInput[] } }\n return (part.input?.videos ?? []).map((video) => ({\n ...video,\n source: parseVideoSource(video.url, video.provider),\n }))\n })\n</script>\n\n<template>\n <div\n v-if=\"videos.length\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40\">\n <VvIcon name=\"ri:film-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.video') }}\n </strong>\n </div>\n <div class=\"p-sm flex flex-col gap-16\">\n <div v-for=\"video in videos\" :key=\"video.url\" class=\"flex flex-col\">\n <strong v-if=\"video.title\" class=\"font-bold text-14 mb-sm\">\n {{ video.title }}\n </strong>\n <!-- Direct file: native player. Handles MP4/WebM/OGG and works\n inside the widget's Shadow DOM without any extra CSS. -->\n <video\n v-if=\"video.source.provider === 'file'\"\n :src=\"video.source.embedUrl\"\n :poster=\"video.poster\"\n controls\n preload=\"metadata\"\n playsinline\n class=\"w-full rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9; max-height: 480px\">\n <a\n :href=\"video.url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n {{ video.title ?? video.url }}\n </a>\n </video>\n <!-- Provider (YouTube/Vimeo): iframe embed, 16:9 responsive. -->\n <div\n v-else\n class=\"relative w-full overflow-hidden rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9\">\n <iframe\n :src=\"video.source.embedUrl\"\n :title=\"video.title ?? video.url\"\n loading=\"lazy\"\n referrerpolicy=\"strict-origin-when-cross-origin\"\n :allow=\"IFRAME_ALLOW\"\n allowfullscreen\n class=\"absolute inset-0 w-full h-full border-0\"></iframe>\n </div>\n <span\n v-if=\"video.description\"\n class=\"text-12 text-word-3 mt-sm\">\n {{ video.description }}\n </span>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"PkToolShowVideo-CVksKdPD.js","names":["$t"],"sources":["../../../../packages/utils/src/video-source.ts","../../../../packages/components/src/chat/PkToolShowVideo.vue","../../../../packages/components/src/chat/PkToolShowVideo.vue"],"sourcesContent":["/**\n * Video source parsing shared by the backend platform renderer and the frontend\n * player component, so both classify a video URL the same way.\n *\n * A URL is either a known provider (YouTube/Vimeo), which plays through the\n * provider's iframe embed, or a direct media file (`file`), which plays in a\n * native `<video>` element. Detection is by URL shape; an explicit `hint` is\n * used only as a fallback when the URL alone is inconclusive.\n */\n\nexport type VideoProvider = 'youtube' | 'vimeo' | 'file'\n\nexport interface ParsedVideoSource {\n provider: VideoProvider\n /** The original URL, unchanged. */\n url: string\n /**\n * The URL to actually load: the provider iframe embed URL for\n * YouTube/Vimeo, or the direct file URL for `file`.\n */\n embedUrl: string\n /** The provider video id (providers only). */\n videoId?: string\n /**\n * A preview image URL derived from the provider, when one is available\n * without an extra API call (currently YouTube only). Lets a link-only\n * surface (e.g. a Teams card) show a thumbnail instead of a bare link.\n */\n thumbnailUrl?: string\n}\n\n/** Keep only characters that are legal in a provider video id. */\nconst sanitizeId = (raw: string): string => raw.replace(/[^a-zA-Z0-9_-]/g, '')\n\n/**\n * True when `host` is exactly `domain` or a subdomain of it. Guards against\n * lookalike hosts (e.g. `notyoutube.com`) that a bare substring check would\n * misclassify.\n */\nconst hostMatches = (host: string, domain: string): boolean =>\n host === domain || host.endsWith(`.${domain}`)\n\n/** Extract the YouTube video id from any of its URL shapes, or null. */\nconst youtubeId = (u: URL): string | null => {\n // youtu.be/<id>\n if (u.hostname.endsWith('youtu.be')) {\n return sanitizeId(u.pathname.split('/')[1] ?? '') || null\n }\n // youtube.com/watch?v=<id>\n const v = u.searchParams.get('v')\n if (v) {\n return sanitizeId(v) || null\n }\n // youtube.com/shorts/<id>, /embed/<id>, /v/<id>\n const m = u.pathname.match(/^\\/(?:shorts|embed|v)\\/([^/?#]+)/)\n return m ? sanitizeId(m[1]) || null : null\n}\n\n/** Extract the Vimeo (numeric) video id, or null. */\nconst vimeoId = (u: URL): string | null => {\n // player.vimeo.com/video/<id> or vimeo.com/<id>\n const m = u.pathname.match(/(?:^|\\/)(\\d+)(?:$|[/?#])/)\n return m ? m[1] : null\n}\n\n/**\n * Classify a video URL into a provider + a loadable embed/file URL.\n * Falls back to `file` (native `<video>`) for anything not recognized as a\n * supported provider, or when a provider is matched but no id can be extracted.\n */\nexport function parseVideoSource(\n url: string,\n hint?: VideoProvider,\n): ParsedVideoSource {\n let u: URL | undefined\n try {\n u = new URL(url)\n } catch {\n // Not an absolute URL: treat as a direct file reference.\n return { provider: 'file', url, embedUrl: url }\n }\n\n const host = u.hostname.toLowerCase()\n\n const isYouTube =\n hostMatches(host, 'youtube.com') ||\n hostMatches(host, 'youtu.be') ||\n hostMatches(host, 'youtube-nocookie.com')\n if (isYouTube) {\n const id = youtubeId(u)\n if (id) {\n return {\n provider: 'youtube',\n url,\n videoId: id,\n embedUrl: `https://www.youtube-nocookie.com/embed/${id}`,\n thumbnailUrl: `https://img.youtube.com/vi/${id}/hqdefault.jpg`,\n }\n }\n }\n\n if (hostMatches(host, 'vimeo.com')) {\n const id = vimeoId(u)\n if (id) {\n return {\n provider: 'vimeo',\n url,\n videoId: id,\n embedUrl: `https://player.vimeo.com/video/${id}`,\n }\n }\n }\n\n // Honor an explicit provider hint only if we could not extract an id from a\n // provider URL (so a caller-tagged provider link still routes to an iframe\n // via its original URL rather than a broken native <video>).\n if (hint && hint !== 'file') {\n return { provider: hint, url, embedUrl: url }\n }\n\n return { provider: 'file', url, embedUrl: url }\n}\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { parseVideoSource, type VideoProvider } from 'utils'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n interface VideoInput {\n url: string\n title?: string\n description?: string\n poster?: string\n provider?: VideoProvider\n }\n\n // Permissions granted to provider embeds (YouTube/Vimeo players).\n const IFRAME_ALLOW =\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n\n const videos = computed(() => {\n const part = props.part as { input?: { videos?: VideoInput[] } }\n return (part.input?.videos ?? []).map((video) => ({\n ...video,\n source: parseVideoSource(video.url, video.provider),\n }))\n })\n</script>\n\n<template>\n <div\n v-if=\"videos.length\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40\">\n <VvIcon name=\"ri:film-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.video') }}\n </strong>\n </div>\n <div class=\"p-sm flex flex-col gap-16\">\n <div v-for=\"video in videos\" :key=\"video.url\" class=\"flex flex-col\">\n <strong v-if=\"video.title\" class=\"font-bold text-14 mb-sm\">\n {{ video.title }}\n </strong>\n <!-- Direct file: native player. Handles MP4/WebM/OGG and works\n inside the widget's Shadow DOM without any extra CSS. -->\n <video\n v-if=\"video.source.provider === 'file'\"\n :src=\"video.source.embedUrl\"\n :poster=\"video.poster\"\n controls\n preload=\"metadata\"\n playsinline\n class=\"w-full rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9; max-height: 480px\">\n <a\n :href=\"video.url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n {{ video.title ?? video.url }}\n </a>\n </video>\n <!-- Provider (YouTube/Vimeo): iframe embed, 16:9 responsive. -->\n <div\n v-else\n class=\"relative w-full overflow-hidden rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9\">\n <iframe\n :src=\"video.source.embedUrl\"\n :title=\"video.title ?? video.url\"\n loading=\"lazy\"\n referrerpolicy=\"strict-origin-when-cross-origin\"\n :allow=\"IFRAME_ALLOW\"\n allowfullscreen\n class=\"absolute inset-0 w-full h-full border-0\"></iframe>\n </div>\n <span\n v-if=\"video.description\"\n class=\"text-12 text-word-3 mt-sm\">\n {{ video.description }}\n </span>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { parseVideoSource, type VideoProvider } from 'utils'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n interface VideoInput {\n url: string\n title?: string\n description?: string\n poster?: string\n provider?: VideoProvider\n }\n\n // Permissions granted to provider embeds (YouTube/Vimeo players).\n const IFRAME_ALLOW =\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n\n const videos = computed(() => {\n const part = props.part as { input?: { videos?: VideoInput[] } }\n return (part.input?.videos ?? []).map((video) => ({\n ...video,\n source: parseVideoSource(video.url, video.provider),\n }))\n })\n</script>\n\n<template>\n <div\n v-if=\"videos.length\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40\">\n <VvIcon name=\"ri:film-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.video') }}\n </strong>\n </div>\n <div class=\"p-sm flex flex-col gap-16\">\n <div v-for=\"video in videos\" :key=\"video.url\" class=\"flex flex-col\">\n <strong v-if=\"video.title\" class=\"font-bold text-14 mb-sm\">\n {{ video.title }}\n </strong>\n <!-- Direct file: native player. Handles MP4/WebM/OGG and works\n inside the widget's Shadow DOM without any extra CSS. -->\n <video\n v-if=\"video.source.provider === 'file'\"\n :src=\"video.source.embedUrl\"\n :poster=\"video.poster\"\n controls\n preload=\"metadata\"\n playsinline\n class=\"w-full rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9; max-height: 480px\">\n <a\n :href=\"video.url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n {{ video.title ?? video.url }}\n </a>\n </video>\n <!-- Provider (YouTube/Vimeo): iframe embed, 16:9 responsive. -->\n <div\n v-else\n class=\"relative w-full overflow-hidden rounded-xl bg-word-1\"\n style=\"aspect-ratio: 16 / 9\">\n <iframe\n :src=\"video.source.embedUrl\"\n :title=\"video.title ?? video.url\"\n loading=\"lazy\"\n referrerpolicy=\"strict-origin-when-cross-origin\"\n :allow=\"IFRAME_ALLOW\"\n allowfullscreen\n class=\"absolute inset-0 w-full h-full border-0\"></iframe>\n </div>\n <span\n v-if=\"video.description\"\n class=\"text-12 text-word-3 mt-sm\">\n {{ video.description }}\n </span>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
- import { B as e, Ht as t, R as n, S as r, Z as i, _ as a, at as o, et as s, f as c, g as l, h as u, k as d, kt as f, mt as p, qt as m, r as h, t as g, v as _, w as v, x as y, xt as b, y as x } from "./vue.runtime.esm-bundler-DF2of3lp.js";
2
- import { r as ee } from "./vue-i18n-BJ7nxwO3.js";
3
- import "./src-BjFv9Ag8.js";
4
- import { d as te, u as ne } from "./index.es-DvV0VhDa.js";
1
+ import { $ as e, C as t, L as n, O as r, St as i, Tt as a, X as o, _ as s, b as c, bt as l, d as u, g as ee, h as d, it as f, m as p, pt as m, r as h, t as g, v as _, x as v, xt as y, z as b } from "./vue.runtime.esm-bundler-B3bThTaf.js";
2
+ import { r as te } from "./vue-i18n-t25g63Be.js";
3
+ import "./src-CIEdKLKO.js";
4
+ import { c as ne, p as re } from "./index.es-gbmOq0Nu.js";
5
5
  //#region ../../packages/utils/src/weather.ts
6
- function re(e) {
6
+ function ie(e) {
7
7
  return e === void 0 ? "unknown" : e === 0 ? "clear" : e === 1 ? "mainlyClear" : e === 2 ? "partlyCloudy" : e === 3 ? "overcast" : e === 45 || e === 48 ? "fog" : e >= 51 && e <= 55 ? "drizzle" : e === 56 || e === 57 ? "freezingDrizzle" : e >= 61 && e <= 65 ? "rain" : e === 66 || e === 67 ? "freezingRain" : e >= 71 && e <= 77 ? "snow" : e >= 80 && e <= 82 ? "rainShowers" : e === 85 || e === 86 ? "snowShowers" : e === 95 ? "thunderstorm" : e === 96 || e === 99 ? "thunderstormHail" : "unknown";
8
8
  }
9
- function ie(e) {
9
+ function x(e) {
10
10
  return e <= 20 ? {
11
11
  index: 0,
12
12
  key: "good"
@@ -27,11 +27,11 @@ function ie(e) {
27
27
  key: "hazardous"
28
28
  };
29
29
  }
30
- d(), f(), o(), h();
31
- var ae = {
30
+ r(), y(), f(), h();
31
+ var S = {
32
32
  key: 0,
33
33
  class: "border border-surface-3 rounded-xl w-full overflow-hidden bg-surface"
34
- }, S = { class: "px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40" }, oe = { class: "font-bold truncate" }, se = { class: "ml-auto shrink-0 capitalize" }, ce = {
34
+ }, ae = { class: "px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40" }, oe = { class: "font-bold truncate" }, se = { class: "ml-auto shrink-0 capitalize" }, ce = {
35
35
  key: 0,
36
36
  class: "px-sm py-md flex items-center gap-md flex-wrap"
37
37
  }, le = { class: "flex items-center gap-8" }, C = { class: "text-48 font-light leading-none text-word-1" }, w = { class: "flex flex-col gap-4 text-12 text-word-3" }, T = { class: "flex items-center gap-6" }, E = { class: "flex items-center gap-6" }, D = { class: "flex items-center gap-6" }, O = {
@@ -61,15 +61,15 @@ var ae = {
61
61
  }, pe = { class: "ml-auto flex items-center gap-8 text-word-3" }, me = { class: "text-word-1 font-semibold" }, he = {
62
62
  key: 2,
63
63
  class: "border-t border-surface-3 px-sm py-8 flex items-center gap-8 text-12"
64
- }, ge = { class: "text-word-3" }, W = /* @__PURE__ */ v({
64
+ }, ge = { class: "text-word-3" }, W = /* @__PURE__ */ t({
65
65
  __name: "PkToolShowWeather",
66
66
  props: { part: { type: null } },
67
- setup(o) {
68
- let d = o, { t: f, d: h, n: v } = ee({ useScope: "global" }), W = u(() => d.part), G = u(() => W.value.output ?? W.value.input ?? null), K = p(0), q = p(!G.value?.current);
69
- i(K, (e) => {
67
+ setup(t) {
68
+ let r = t, { t: f, d: h, n: y } = te({ useScope: "global" }), W = p(() => r.part), G = p(() => W.value.output ?? W.value.input ?? null), K = m(0), q = m(!G.value?.current);
69
+ o(K, (e) => {
70
70
  e > 0 && (q.value = !0);
71
71
  });
72
- let J = u(() => G.value?.daily?.[K.value]), Y = u(() => {
72
+ let J = p(() => G.value?.daily?.[K.value]), Y = p(() => {
73
73
  if (!G.value?.hourly?.length || !J.value) return G.value?.hourly ?? [];
74
74
  let e = J.value.date;
75
75
  return G.value.hourly.filter((t) => t.time.startsWith(e));
@@ -110,7 +110,7 @@ var ae = {
110
110
  unknown: "wi:na"
111
111
  };
112
112
  function Z(e) {
113
- return _e[re(e)];
113
+ return _e[ie(e)];
114
114
  }
115
115
  function Q(e, t, n) {
116
116
  let r = X(e + "T12:00:00");
@@ -122,7 +122,7 @@ var ae = {
122
122
  let i = /* @__PURE__ */ new Date();
123
123
  return i.setDate(i.getDate() + t), h(i, "weekday-day");
124
124
  }
125
- let ve = u(() => {
125
+ let ve = p(() => {
126
126
  if (J.value) {
127
127
  let e = X(J.value.date + "T12:00:00");
128
128
  if (!Number.isNaN(e.getTime())) return Q(J.value.date, K.value, G.value?.daily?.length ?? 1);
@@ -155,7 +155,7 @@ var ae = {
155
155
  }
156
156
  };
157
157
  function $(e) {
158
- let { labelKey: t, class: n } = ye[ie(e).key];
158
+ let { labelKey: t, class: n } = ye[x(e).key];
159
159
  return {
160
160
  label: f(t),
161
161
  class: n
@@ -173,106 +173,106 @@ var ae = {
173
173
  "NO"
174
174
  ][Math.round(e / 45) % 8];
175
175
  }
176
- return (i, o) => {
177
- let u = ne, d = te;
178
- return G.value ? (n(), x("div", ae, [
179
- l("div", S, [
180
- r(u, {
176
+ return (t, r) => {
177
+ let o = re, p = ne;
178
+ return G.value ? (n(), _("div", S, [
179
+ d("div", ae, [
180
+ v(o, {
181
181
  name: "ri:temp-cold-line",
182
182
  class: "text-16"
183
183
  }),
184
- l("strong", oe, m(G.value.locationName), 1),
185
- l("span", se, m(ve.value), 1)
184
+ d("strong", oe, a(G.value.locationName), 1),
185
+ d("span", se, a(ve.value), 1)
186
186
  ]),
187
- G.value.current && K.value === 0 ? (n(), x("div", ce, [l("div", le, [r(u, {
187
+ G.value.current && K.value === 0 ? (n(), _("div", ce, [d("div", le, [v(o, {
188
188
  name: Z(G.value.current.weatherCode),
189
189
  class: "text-48 text-word-2 shrink-0"
190
- }, null, 8, ["name"]), l("span", C, m(b(v)(G.value.current.temperature, "integer")) + "° ", 1)]), l("div", w, [
191
- l("div", T, m(b(f)("weather.feelsLike")) + " " + m(b(v)(G.value.current.feelsLike, "integer")) + "° ", 1),
192
- l("div", E, [r(u, {
190
+ }, null, 8, ["name"]), d("span", C, a(l(y)(G.value.current.temperature, "integer")) + "° ", 1)]), d("div", w, [
191
+ d("div", T, a(l(f)("weather.feelsLike")) + " " + a(l(y)(G.value.current.feelsLike, "integer")) + "° ", 1),
192
+ d("div", E, [v(o, {
193
193
  name: "ri:water-percent-line",
194
194
  class: "text-14"
195
- }), y(" " + m(G.value.current.humidity) + "% ", 1)]),
196
- l("div", D, [r(u, {
195
+ }), c(" " + a(G.value.current.humidity) + "% ", 1)]),
196
+ d("div", D, [v(o, {
197
197
  name: "ri:windy-line",
198
198
  class: "text-14"
199
- }), y(" " + m(b(v)(G.value.current.windSpeed, "integer")) + " km/h " + m(be(G.value.current.windDirection)), 1)]),
200
- G.value.current.uvIndex > 0 ? (n(), x("div", O, [r(u, {
199
+ }), c(" " + a(l(y)(G.value.current.windSpeed, "integer")) + " km/h " + a(be(G.value.current.windDirection)), 1)]),
200
+ G.value.current.uvIndex > 0 ? (n(), _("div", O, [v(o, {
201
201
  name: "ri:sun-line",
202
202
  class: "text-14"
203
- }), y(" UV " + m(b(v)(G.value.current.uvIndex, "integer")), 1)])) : _("", !0)
204
- ])])) : J.value ? (n(), x("div", k, [l("div", A, [r(u, {
203
+ }), c(" UV " + a(l(y)(G.value.current.uvIndex, "integer")), 1)])) : s("", !0)
204
+ ])])) : J.value ? (n(), _("div", k, [d("div", A, [v(o, {
205
205
  name: Z(J.value.weatherCode),
206
206
  class: "text-48 text-word-2 shrink-0"
207
- }, null, 8, ["name"]), l("div", j, [l("span", M, m(b(v)(J.value.maxTemp, "integer")) + "° ", 1), l("span", N, m(b(v)(J.value.minTemp, "integer")) + "° ", 1)])]), l("div", P, [
208
- J.value.precipitationProbabilityMax > 0 ? (n(), x("div", F, [r(u, {
207
+ }, null, 8, ["name"]), d("div", j, [d("span", M, a(l(y)(J.value.maxTemp, "integer")) + "° ", 1), d("span", N, a(l(y)(J.value.minTemp, "integer")) + "° ", 1)])]), d("div", P, [
208
+ J.value.precipitationProbabilityMax > 0 ? (n(), _("div", F, [v(o, {
209
209
  name: "ri:drop-line",
210
210
  class: "text-14"
211
- }), y(" " + m(J.value.precipitationProbabilityMax) + "% (" + m(J.value.precipitationSum) + " mm) ", 1)])) : _("", !0),
212
- J.value.uvIndexMax > 0 ? (n(), x("div", I, [r(u, {
211
+ }), c(" " + a(J.value.precipitationProbabilityMax) + "% (" + a(J.value.precipitationSum) + " mm) ", 1)])) : s("", !0),
212
+ J.value.uvIndexMax > 0 ? (n(), _("div", I, [v(o, {
213
213
  name: "ri:sun-line",
214
214
  class: "text-14"
215
- }), y(" UV " + m(b(v)(J.value.uvIndexMax, "integer")), 1)])) : _("", !0),
216
- l("div", L, [r(u, {
215
+ }), c(" UV " + a(l(y)(J.value.uvIndexMax, "integer")), 1)])) : s("", !0),
216
+ d("div", L, [v(o, {
217
217
  name: "ri:sun-foggy-line",
218
218
  class: "text-14"
219
- }), y(" " + m(b(h)(X(J.value.sunrise), "time")) + " – " + m(b(h)(X(J.value.sunset), "time")), 1)])
220
- ])])) : _("", !0),
221
- r(g, null, {
222
- default: s(() => [Y.value.length > 0 ? (n(), x("div", R, [l("div", z, [(n(!0), x(c, null, e(Y.value, (e) => (n(), x("div", {
219
+ }), c(" " + a(l(h)(X(J.value.sunrise), "time")) + " – " + a(l(h)(X(J.value.sunset), "time")), 1)])
220
+ ])])) : s("", !0),
221
+ v(g, null, {
222
+ default: e(() => [Y.value.length > 0 ? (n(), _("div", R, [d("div", z, [(n(!0), _(u, null, b(Y.value, (e) => (n(), _("div", {
223
223
  key: e.time,
224
224
  class: "flex flex-col items-center gap-4 min-w-48 px-4 py-6 rounded-xl text-11 text-word-3 shrink-0"
225
225
  }, [
226
- l("span", B, m(Number.isNaN(X(e.time).getTime()) ? e.time : b(h)(X(e.time), "time")), 1),
227
- r(u, {
226
+ d("span", B, a(Number.isNaN(X(e.time).getTime()) ? e.time : l(h)(X(e.time), "time")), 1),
227
+ v(o, {
228
228
  name: Z(e.weatherCode),
229
229
  class: "text-20 text-word-2"
230
230
  }, null, 8, ["name"]),
231
- l("span", V, m(b(v)(e.temperature, "integer")) + "° ", 1),
232
- e.precipitationProbability > 0 ? (n(), x("span", ue, m(e.precipitationProbability) + "% ", 1)) : _("", !0)
233
- ]))), 128))])])) : _("", !0)]),
231
+ d("span", V, a(l(y)(e.temperature, "integer")) + "° ", 1),
232
+ e.precipitationProbability > 0 ? (n(), _("span", ue, a(e.precipitationProbability) + "% ", 1)) : s("", !0)
233
+ ]))), 128))])])) : s("", !0)]),
234
234
  _: 1
235
235
  }),
236
- r(g, null, {
237
- default: s(() => [G.value.daily?.length > 1 ? (n(), a(d, {
236
+ v(g, null, {
237
+ default: e(() => [G.value.daily?.length > 1 ? (n(), ee(p, {
238
238
  key: 0,
239
239
  modelValue: q.value,
240
- "onUpdate:modelValue": o[0] ||= (e) => q.value = e,
240
+ "onUpdate:modelValue": r[0] ||= (e) => q.value = e,
241
241
  modifiers: "details no-padding",
242
- title: b(f)("weather.dailyForecast"),
242
+ title: l(f)("weather.dailyForecast"),
243
243
  class: "border-t border-surface-3"
244
244
  }, {
245
- default: s(() => [(n(!0), x(c, null, e(G.value.daily, (e, i) => (n(), x("button", {
245
+ default: e(() => [(n(!0), _(u, null, b(G.value.daily, (e, t) => (n(), _("button", {
246
246
  key: e.date,
247
247
  type: "button",
248
- class: t(["flex items-center gap-sm px-sm py-8 text-12 w-full text-left transition-colors cursor-pointer border-t border-surface-3", i === K.value ? "bg-surface-2" : "hover:bg-surface-1"]),
249
- onClick: (e) => K.value = i
248
+ class: i(["flex items-center gap-sm px-sm py-8 text-12 w-full text-left transition-colors cursor-pointer border-t border-surface-3", t === K.value ? "bg-surface-2" : "hover:bg-surface-1"]),
249
+ onClick: (e) => K.value = t
250
250
  }, [
251
- l("span", U, m(Q(e.date, i, G.value.daily.length)), 1),
252
- r(u, {
251
+ d("span", U, a(Q(e.date, t, G.value.daily.length)), 1),
252
+ v(o, {
253
253
  name: Z(e.weatherCode),
254
254
  class: "text-18 text-word-2 shrink-0"
255
255
  }, null, 8, ["name"]),
256
- e.precipitationProbabilityMax > 0 ? (n(), x("span", de, m(e.precipitationProbabilityMax) + "% ", 1)) : (n(), x("span", fe)),
257
- l("div", pe, [l("span", me, m(b(v)(e.maxTemp, "integer")) + "° ", 1), l("span", null, m(b(v)(e.minTemp, "integer")) + "°", 1)])
256
+ e.precipitationProbabilityMax > 0 ? (n(), _("span", de, a(e.precipitationProbabilityMax) + "% ", 1)) : (n(), _("span", fe)),
257
+ d("div", pe, [d("span", me, a(l(y)(e.maxTemp, "integer")) + "° ", 1), d("span", null, a(l(y)(e.minTemp, "integer")) + "°", 1)])
258
258
  ], 10, H))), 128))]),
259
259
  _: 1
260
- }, 8, ["modelValue", "title"])) : _("", !0)]),
260
+ }, 8, ["modelValue", "title"])) : s("", !0)]),
261
261
  _: 1
262
262
  }),
263
- G.value.airQuality ? (n(), x("div", he, [
264
- r(u, {
263
+ G.value.airQuality ? (n(), _("div", he, [
264
+ v(o, {
265
265
  name: "ri:windy-line",
266
266
  class: "text-14 text-word-3"
267
267
  }),
268
- l("span", ge, m(b(f)("weather.airQuality")), 1),
269
- l("span", { class: t(["ml-auto px-8 py-2 text-11 font-semibold", $(G.value.airQuality.aqi).class]) }, m($(G.value.airQuality.aqi).label) + " (" + m(G.value.airQuality.aqi) + ") ", 3)
270
- ])) : _("", !0)
271
- ])) : _("", !0);
268
+ d("span", ge, a(l(f)("weather.airQuality")), 1),
269
+ d("span", { class: i(["ml-auto px-8 py-2 text-11 font-semibold", $(G.value.airQuality.aqi).class]) }, a($(G.value.airQuality.aqi).label) + " (" + a(G.value.airQuality.aqi) + ") ", 3)
270
+ ])) : s("", !0)
271
+ ])) : s("", !0);
272
272
  };
273
273
  }
274
274
  });
275
275
  //#endregion
276
276
  export { W as default };
277
277
 
278
- //# sourceMappingURL=PkToolShowWeather-D_pJe5DI.js.map
278
+ //# sourceMappingURL=PkToolShowWeather-IDwTDozU.js.map