@quidgest/chatbot 0.5.1 → 0.5.3-dev.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 (66) hide show
  1. package/README.md +1 -2
  2. package/dist/components/ChatBot/ChatBot.vue.d.ts +2 -0
  3. package/dist/components/ChatBot/types.d.ts +2 -1
  4. package/dist/components/ChatBotInput/ChatBotInput.vue.d.ts +2 -2
  5. package/dist/components/ChatBotInput/__tests__/ChatBotInput.spec.d.ts +1 -0
  6. package/dist/components/ChatBotMessage/ChatBotMessage.vue.d.ts +3 -1
  7. package/dist/components/ChatBotMessage/__tests__/ChatBotMessageButtons.spec.d.ts +1 -0
  8. package/dist/components/ChatToolBar/__tests__/ChatToolBar.spec.d.ts +1 -0
  9. package/dist/components/FieldPreview/FieldPreview.vue.d.ts +2 -0
  10. package/dist/components/FieldPreview/__tests__/FieldPreview.spec.d.ts +1 -0
  11. package/dist/components/MarkdownRender/__tests__/MarkdownRender.spec.d.ts +1 -0
  12. package/dist/components/PulseDots/__tests__/PulseDots.spec.d.ts +1 -0
  13. package/dist/composables/__tests__/useChatMessages.spec.d.ts +1 -0
  14. package/dist/composables/__tests__/useSSE.spec.d.ts +1 -0
  15. package/dist/composables/useChatApi.d.ts +1 -1
  16. package/dist/composables/useChatMessages.d.ts +2 -1
  17. package/dist/composables/useSSE.d.ts +1 -2
  18. package/dist/composables/useTexts.d.ts +5 -0
  19. package/dist/index.js +25 -25
  20. package/dist/index.mjs +2319 -1812
  21. package/dist/style.css +1 -1
  22. package/dist/test/setup.d.ts +1 -0
  23. package/dist/utils/__tests__/parseFieldValue.spec.d.ts +1 -0
  24. package/package.json +27 -6
  25. package/src/assets/styles/styles.scss +212 -220
  26. package/src/components/ChatBot/ChatBot.vue +346 -368
  27. package/src/components/ChatBot/types.ts +34 -33
  28. package/src/components/ChatBotInput/ChatBotInput.vue +181 -190
  29. package/src/components/ChatBotInput/__tests__/ChatBotInput.spec.ts +292 -0
  30. package/src/components/ChatBotInput/__tests__/__snapshots__/ChatBotInput.spec.ts.snap +25 -0
  31. package/src/components/ChatBotInput/types.ts +24 -24
  32. package/src/components/ChatBotMessage/ChatBotMessage.vue +133 -134
  33. package/src/components/ChatBotMessage/ChatBotMessageButtons.vue +179 -164
  34. package/src/components/ChatBotMessage/__tests__/ChatBotMessageButtons.spec.ts +199 -0
  35. package/src/components/ChatBotMessage/__tests__/__snapshots__/ChatBotMessageButtons.spec.ts.snap +25 -0
  36. package/src/components/ChatBotMessage/types.ts +52 -52
  37. package/src/components/ChatToolBar/ChatToolBar.vue +69 -64
  38. package/src/components/ChatToolBar/__tests__/ChatToolBar.spec.ts +138 -0
  39. package/src/components/ChatToolBar/__tests__/__snapshots__/ChatToolBar.spec.ts.snap +11 -0
  40. package/src/components/ChatToolBar/types.ts +12 -12
  41. package/src/components/FieldPreview/FieldPreview.vue +83 -63
  42. package/src/components/FieldPreview/__tests__/FieldPreview.spec.ts +72 -0
  43. package/src/components/FieldPreview/__tests__/__snapshots__/FieldPreview.spec.ts.snap +19 -0
  44. package/src/components/FieldPreview/field-preview.scss +28 -24
  45. package/src/components/FieldPreview/types.ts +5 -5
  46. package/src/components/MarkdownRender/MarkdownRender.vue +16 -15
  47. package/src/components/MarkdownRender/__tests__/MarkdownRender.spec.ts +68 -0
  48. package/src/components/MarkdownRender/__tests__/__snapshots__/MarkdownRender.spec.ts.snap +8 -0
  49. package/src/components/MarkdownRender/markdown-render.scss +19 -20
  50. package/src/components/MarkdownRender/types.ts +3 -3
  51. package/src/components/PulseDots/PulseDots.vue +17 -17
  52. package/src/components/PulseDots/__tests__/PulseDots.spec.ts +35 -0
  53. package/src/components/PulseDots/__tests__/__snapshots__/PulseDots.spec.ts.snap +7 -0
  54. package/src/components/PulseDots/__tests__/__snapshots__/pulse-dots.spec.ts.snap +7 -0
  55. package/src/components/PulseDots/pulse-dots.scss +24 -23
  56. package/src/composables/__tests__/useChatMessages.spec.ts +64 -0
  57. package/src/composables/__tests__/useSSE.spec.ts +132 -0
  58. package/src/composables/useChatApi.ts +132 -134
  59. package/src/composables/useChatMessages.ts +50 -48
  60. package/src/composables/useSSE.ts +75 -76
  61. package/src/composables/useTexts.ts +33 -30
  62. package/src/test/setup.ts +41 -0
  63. package/src/utils/__tests__/parseFieldValue.spec.ts +27 -0
  64. package/src/utils/parseFieldValue.ts +12 -0
  65. package/src/utils/helper.ts +0 -12
  66. /package/dist/utils/{helper.d.ts → parseFieldValue.d.ts} +0 -0
@@ -1,70 +1,70 @@
1
1
  import { ChatBotMessageSender, FieldData } from '@/components/ChatBot/types'
2
2
 
3
3
  export type ChatBotMessageProps = {
4
- /*
5
- * Sender of the message
6
- */
7
- sender?: ChatBotMessageSender
4
+ /*
5
+ * Sender of the message
6
+ */
7
+ sender?: ChatBotMessageSender
8
8
 
9
- /*
10
- * Message to be displayed
11
- */
12
- message?: string
9
+ /*
10
+ * Message to be displayed
11
+ */
12
+ message?: string
13
13
 
14
- /*
15
- * Date of when the message was sent
16
- */
17
- date?: Date
14
+ /*
15
+ * Date of when the message was sent
16
+ */
17
+ date?: Date
18
18
 
19
- /*
20
- * If the message is loading
21
- */
22
- loading?: boolean
19
+ /*
20
+ * If the message is loading
21
+ */
22
+ loading?: boolean
23
23
 
24
- /**
25
- * Project locale
26
- */
27
- dateFormat: string
24
+ /**
25
+ * Project locale
26
+ */
27
+ dateFormat: string
28
28
 
29
- /**
30
- * Image preview URL
31
- */
32
- imagePreviewUrl?: string
29
+ /**
30
+ * Image preview URL
31
+ */
32
+ imagePreviewUrl?: string
33
33
 
34
- /**
35
- * Default api endpoint
36
- */
37
- apiEndpoint: string
34
+ /**
35
+ * Default api endpoint
36
+ */
37
+ apiEndpoint: string
38
38
 
39
- /**
40
- * Session ID
41
- */
42
- sessionID?: string
39
+ /**
40
+ * Session ID
41
+ */
42
+ sessionID?: string
43
43
 
44
- /**
45
- * User image
46
- */
47
- userImage: string
44
+ /**
45
+ * User image
46
+ */
47
+ userImage: string
48
48
 
49
- /**
50
- * Chatbot image
51
- */
52
- chatbotImage: string
49
+ /**
50
+ * Chatbot image
51
+ */
52
+ chatbotImage: string
53
53
 
54
- /**
55
- * Flag to mark welcome messages
56
- */
57
- isWelcomeMessage?: boolean
54
+ /**
55
+ * Flag to mark welcome messages
56
+ */
57
+ isWelcomeMessage?: boolean
58
58
 
59
- /**
60
- * Additional fields for the message
61
- */
62
- fields?: FieldData[]
59
+ /**
60
+ * Additional fields for the message
61
+ */
62
+ fields?: FieldData[]
63
63
  }
64
64
 
65
65
  export type ChatBotMessageButtonsProps = {
66
- loading: boolean
67
- showButtons: boolean
68
- dateFormat: string
69
- date?: Date
66
+ loading: boolean
67
+ showButtons: boolean
68
+ dateFormat: string
69
+ date?: Date
70
70
  }
@@ -1,82 +1,87 @@
1
1
  <template>
2
- <div class="q-chatbot__tools">
3
- <div class="q-chatbot__tools__select">
4
- <q-select
5
- v-if="hasAgents"
6
- v-model="selectedChat"
7
- size="medium"
8
- :items="availableChats"
9
- @update:model-value="changeChat" />
10
- </div>
2
+ <div class="q-chatbot__tools">
3
+ <div class="q-chatbot__tools__select">
4
+ <q-select
5
+ v-if="hasAgents"
6
+ v-model="selectedChat"
7
+ inline
8
+ class="q-chatbot__tools-select-input"
9
+ size="medium"
10
+ :items="availableChats"
11
+ @update:model-value="changeChat" />
12
+ </div>
11
13
 
12
- <q-button
13
- :title="clearChat"
14
- :disabled="props.disabled"
15
- borderless
16
- @click="clear">
17
- <q-icon icon="bin" />
18
- </q-button>
19
- </div>
14
+ <q-button
15
+ :title="clearChat"
16
+ :disabled="props.disabled"
17
+ class="q-chatbot__tools-clear"
18
+ borderless
19
+ @click="clear">
20
+ <q-icon icon="bin" />
21
+ </q-button>
22
+ </div>
20
23
  </template>
21
24
 
22
25
  <script setup lang="ts">
23
- import { useTexts } from '@/composables/useTexts'
24
- import { ChatToolBarProps } from './types'
25
- import { computed, ref, watch } from 'vue'
26
+ import { QButton, QIcon } from '@quidgest/ui/components'
26
27
 
27
- const { clearChat } = useTexts()
28
+ import { useTexts } from '@/composables/useTexts'
29
+ import { ChatToolBarProps } from './types'
30
+ import { computed, ref, watch } from 'vue'
28
31
 
29
- const defaultChat = {
30
- key: '',
31
- value: 'Default Chat',
32
- formId: ''
33
- }
32
+ const props = withDefaults(defineProps<ChatToolBarProps>(), {
33
+ availableAgents: () => []
34
+ })
34
35
 
35
- const props = withDefaults(defineProps<ChatToolBarProps>(), {
36
- availableAgents: () => []
37
- })
36
+ const emit = defineEmits<{
37
+ (e: 'clear'): void
38
+ (e: 'change-chat', value: { key: string; formId: string }): void
39
+ }>()
38
40
 
39
- const emit = defineEmits<{
40
- (e: 'clear'): void
41
- (e: 'change-chat', value: { key: string; formId: string }): void
42
- }>()
41
+ const { clearChat } = useTexts()
43
42
 
44
- const hasAgents = computed(() => {
45
- return props.availableAgents && props.availableAgents.length > 0
46
- })
43
+ const defaultChat = {
44
+ key: '',
45
+ value: 'Default Chat',
46
+ formId: ''
47
+ }
47
48
 
48
- const selectedChat = ref(props.selectedAgentKey || defaultChat.key)
49
- watch(
50
- () => props.selectedAgentKey,
51
- (newValue) => {
52
- selectedChat.value = newValue || defaultChat.key
53
- }
54
- )
49
+ const hasAgents = computed(() => {
50
+ return props.availableAgents && props.availableAgents.length > 0
51
+ })
55
52
 
56
- const availableChats = computed(() => {
57
- const chats = props.availableAgents?.map((agent) => ({
58
- key: agent.key,
59
- value: agent.value,
60
- formId: agent.formId
61
- }))
53
+ const selectedChat = ref(props.selectedAgentKey || defaultChat.key)
54
+ watch(
55
+ () => props.selectedAgentKey,
56
+ (newValue) => {
57
+ selectedChat.value = newValue || defaultChat.key
58
+ }
59
+ )
62
60
 
63
- chats?.push(defaultChat)
64
- return chats || [defaultChat]
65
- })
61
+ const availableChats = computed(() => {
62
+ const chats = props.availableAgents?.map((agent) => ({
63
+ key: agent.key,
64
+ value: agent.value,
65
+ formId: agent.formId
66
+ }))
66
67
 
67
- function clear() {
68
- emit('clear')
69
- }
68
+ chats?.push(defaultChat)
69
+ return chats || [defaultChat]
70
+ })
70
71
 
71
- function changeChat(value: string) {
72
- const item = availableChats.value.find((chat) => chat.key === value)
73
- if (!item) return
72
+ function clear() {
73
+ emit('clear')
74
+ }
74
75
 
75
- if (item.key === defaultChat.key) {
76
- emit('change-chat', { key: '', formId: '' })
77
- return
78
- }
76
+ function changeChat(value: string) {
77
+ const item = availableChats.value.find((chat) => chat.key === value)
78
+ if (!item) return
79
79
 
80
- emit('change-chat', item)
81
- }
80
+ if (item.key === defaultChat.key) {
81
+ emit('change-chat', { key: '', formId: '' })
82
+ return
83
+ }
84
+
85
+ emit('change-chat', item)
86
+ }
82
87
  </script>
@@ -0,0 +1,138 @@
1
+ // Components
2
+ import { ChatToolBar } from '..'
3
+
4
+ // Utils
5
+ import { describe, it, expect } from 'vitest'
6
+ import { mount } from '@vue/test-utils'
7
+
8
+ // Types
9
+ import type { ChatToolBarProps } from '../'
10
+ import { nextTick } from 'vue'
11
+
12
+ describe('ChatToolBar', () => {
13
+ const props: ChatToolBarProps = {
14
+ disabled: false,
15
+ availableAgents: [],
16
+ selectedAgentKey: ''
17
+ }
18
+
19
+ it('should render the component', () => {
20
+ const wrapper = mount(ChatToolBar, { props })
21
+ expect(wrapper.html()).toMatchSnapshot()
22
+ })
23
+
24
+ it('should emit clear event when clear button is clicked', async () => {
25
+ const wrapper = mount(ChatToolBar, { props })
26
+ const button = wrapper.find('.q-chatbot__tools-clear')
27
+
28
+ await button.trigger('click')
29
+ expect(wrapper.emitted()['clear']).toBeTruthy()
30
+ })
31
+
32
+ it('should disable the clear button when disabled prop is true', () => {
33
+ const wrapper = mount(ChatToolBar, { props: { ...props, disabled: true } })
34
+ const button = wrapper.find<HTMLButtonElement>('.q-chatbot__tools-clear')
35
+ expect(button.element.disabled).toBe(true)
36
+ })
37
+
38
+ it('should not render the select when no agents are provided', () => {
39
+ const wrapper = mount(ChatToolBar, { props })
40
+ expect(wrapper.find('.q-chatbot__tools-select-input').exists()).toBe(false)
41
+ })
42
+
43
+ it('should render the select when agents are provided', () => {
44
+ const wrapper = mount(ChatToolBar, {
45
+ props: {
46
+ ...props,
47
+ availableAgents: [{ key: 'agent1', value: 'Agent 1', formId: 'key' }]
48
+ }
49
+ })
50
+ expect(wrapper.find('.q-chatbot__tools-select-input').exists()).toBe(true)
51
+ })
52
+
53
+ it('should emit change-agent event when a new agent is selected', async () => {
54
+ const wrapper = mount(ChatToolBar, {
55
+ props: {
56
+ ...props,
57
+ availableAgents: [{ key: 'agent1', value: 'Agent 1', formId: 'key' }],
58
+ selectedAgentKey: ''
59
+ }
60
+ })
61
+
62
+ const select = wrapper.find('.q-field__control')
63
+ await select.trigger('click')
64
+
65
+ const overlay = wrapper.find('.q-overlay__content')
66
+
67
+ const item = overlay.find('.q-list-item')
68
+ await item.trigger('click')
69
+
70
+ expect(wrapper.emitted()['change-chat']).toBeTruthy()
71
+ expect(wrapper.emitted()['change-chat'][0]).toEqual([
72
+ {
73
+ key: 'agent1',
74
+ formId: 'key',
75
+ value: 'Agent 1'
76
+ }
77
+ ])
78
+ })
79
+
80
+ it('should not emit change-agent if it receive a non-existing agent key', async () => {
81
+ const wrapper = mount(ChatToolBar, {
82
+ props: {
83
+ ...props,
84
+ availableAgents: [
85
+ { key: 'agent1', value: 'Agent 1', formId: 'key' },
86
+ { key: 'agent2', value: 'Agent 2', formId: 'key' }
87
+ ],
88
+ selectedAgentKey: 'agent1'
89
+ }
90
+ })
91
+
92
+ const select = wrapper.find('.q-field__control')
93
+ await select.trigger('click')
94
+
95
+ const overlay = wrapper.find('.q-overlay__content')
96
+
97
+ // Manually add a fake item that does not exist in the options
98
+ const fakeItem = document.createElement('div')
99
+ fakeItem.setAttribute('data-key', 'agent3')
100
+ overlay.element.appendChild(fakeItem)
101
+
102
+ await nextTick()
103
+ const item = overlay.find('[data-key="agent3"]')
104
+ await item.trigger('click')
105
+
106
+ expect(wrapper.emitted()['change-chat']).toBeFalsy()
107
+ })
108
+
109
+ it('shoudld emit change-agent when selecting the default option', async () => {
110
+ const wrapper = mount(ChatToolBar, {
111
+ props: {
112
+ ...props,
113
+ availableAgents: [
114
+ { key: 'agent1', value: 'Agent 1', formId: 'key' },
115
+ { key: 'agent2', value: 'Agent 2', formId: 'key' }
116
+ ],
117
+ selectedAgentKey: 'agent1'
118
+ }
119
+ })
120
+ const select = wrapper.find('.q-field__control')
121
+ await select.trigger('click')
122
+
123
+ const overlay = wrapper.find('.q-overlay__content')
124
+ const items = overlay.findAll('.q-list-item')
125
+
126
+ // Default options is always the last one
127
+ const defaultOption = items[items.length - 1]
128
+ await defaultOption.trigger('click')
129
+
130
+ expect(wrapper.emitted()['change-chat']).toBeTruthy()
131
+ expect(wrapper.emitted()['change-chat'][0]).toEqual([
132
+ {
133
+ key: '',
134
+ formId: ''
135
+ }
136
+ ])
137
+ })
138
+ })
@@ -0,0 +1,11 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`ChatToolBar > should render the component 1`] = `
4
+ "<div class="q-chatbot__tools">
5
+ <div class="q-chatbot__tools__select">
6
+ <!--v-if-->
7
+ </div><button type="button" class="q-button q-button--outlined q-button--primary q-button--borderless q-chatbot__tools-clear" title="Clear chat">
8
+ <!--v-if--><span class="q-button__content"><span data-test="bin"></span> </span>
9
+ </button>
10
+ </div>"
11
+ `;
@@ -1,18 +1,18 @@
1
1
  import { AvailableAgents } from '../ChatBot/types'
2
2
 
3
3
  export type ChatToolBarProps = {
4
- /**
5
- * If true, the toolbar will be disabled and not clickable.
6
- */
7
- disabled?: boolean
4
+ /**
5
+ * If true, the toolbar will be disabled and not clickable.
6
+ */
7
+ disabled?: boolean
8
8
 
9
- /**
10
- * Availabe Agents to select from.
11
- */
12
- availableAgents?: AvailableAgents[]
9
+ /**
10
+ * Availabe Agents to select from.
11
+ */
12
+ availableAgents?: AvailableAgents[]
13
13
 
14
- /**
15
- * The currently selected agent.
16
- */
17
- selectedAgentKey?: string
14
+ /**
15
+ * The currently selected agent.
16
+ */
17
+ selectedAgentKey?: string
18
18
  }
@@ -1,78 +1,98 @@
1
1
  <template>
2
- <div class="q-field-preview">
3
- <div class="q-field-preview__toolbar">
4
- <span>
5
- Suggestions for field: <b>{{ props.name }}</b>
6
- </span>
7
- </div>
8
- <div class="q-field-preview__content">
9
- <component
10
- :is="previewComponent"
11
- v-bind="previewComponentProps" />
12
- </div>
13
- <div class="q-field-preview__footer">
14
- <q-button-group borderless>
15
- <!-- <q-button
16
- :title="texts.regenerateResponse"
17
- :disabled="props.disabled"
18
- borderless
19
- @click="console.log('Regenerate response')">
20
- <q-icon icon="reset" />
21
- </q-button> -->
22
- <q-button
23
- :label="texts.apply"
24
- :disabled="blockApplyButton"
25
- :readonly="blockApplyButton"
26
- @click="emitApply">
27
- <q-icon icon="apply" />
28
- </q-button>
29
- </q-button-group>
30
- </div>
31
- </div>
2
+ <div class="q-field-preview">
3
+ <div class="q-field-preview__toolbar">
4
+ <span>
5
+ {{ texts.suggestionsForField }} <b>{{ props.name }}</b>
6
+ </span>
7
+ </div>
8
+ <div :class="classes">
9
+ <component
10
+ :is="previewComponent"
11
+ v-bind="previewComponentProps" />
12
+ </div>
13
+ <div class="q-field-preview__footer">
14
+ <q-button-group borderless>
15
+ <q-button
16
+ :title="texts.regenerateResponse"
17
+ :disabled="blockRegenerateButton"
18
+ :readonly="blockRegenerateButton"
19
+ borderless
20
+ @click="regenerate">
21
+ <q-icon icon="reset" />
22
+ </q-button>
23
+ <q-button
24
+ :label="texts.apply"
25
+ data-testid="apply-button"
26
+ :disabled="blockApplyButton"
27
+ :readonly="blockApplyButton"
28
+ @click="emitApply">
29
+ <q-icon icon="apply" />
30
+ </q-button>
31
+ </q-button-group>
32
+ </div>
33
+ </div>
32
34
  </template>
33
35
 
34
36
  <script setup lang="ts">
35
- import { QButton, QIcon, QButtonGroup } from '@quidgest/ui/components'
36
- import MarkdownRender from '../MarkdownRender/MarkdownRender.vue'
37
- import { FieldPreviewProps } from './types'
38
- import { useTexts } from '@/composables/useTexts'
39
- import { computed, ref } from 'vue'
40
- import { parseFieldValue } from '@/utils/helper'
37
+ import { QButton, QIcon, QButtonGroup } from '@quidgest/ui/components'
38
+ import { MarkdownRender } from '@/components/MarkdownRender'
39
+ import { FieldPreviewProps } from './types'
40
+ import { useTexts } from '@/composables/useTexts'
41
+ import { computed, ref } from 'vue'
42
+ import { parseFieldValue } from '@/utils/parseFieldValue'
41
43
 
42
- const texts = useTexts()
43
- const props = defineProps<FieldPreviewProps>()
44
- const blockApply = ref(props.applied)
45
- const blockApplyButton = computed(() => {
46
- return props.disabled || blockApply.value
47
- })
44
+ const props = defineProps<FieldPreviewProps>()
45
+ const emit = defineEmits<{
46
+ (e: 'apply', text: unknown): void
47
+ (e: 'regenerate', name: string): void
48
+ }>()
49
+ const texts = useTexts()
50
+ const blockApply = ref(props.applied)
51
+ const blockRegenerate = ref(false)
52
+ const blockApplyButton = computed(() => {
53
+ return props.disabled || blockApply.value
54
+ })
48
55
 
49
- const previewComponent = computed(() => {
50
- if (props.type === 'text' || props.type === 'multiline_text')
51
- return MarkdownRender
56
+ const blockRegenerateButton = computed(() => {
57
+ return props.disabled || blockRegenerate.value
58
+ })
52
59
 
53
- return 'div'
54
- })
60
+ const previewComponent = computed(() => {
61
+ if (props.type === 'text' || props.type === 'multiline_text') return MarkdownRender
55
62
 
56
- const previewComponentProps = computed(() => {
57
- const componentProps: Record<string, unknown> = {}
63
+ return 'div'
64
+ })
58
65
 
59
- if (previewComponent.value === MarkdownRender)
60
- componentProps.source = props.text
61
- else componentProps.innerHTML = props.text
66
+ const previewComponentProps = computed(() => {
67
+ const componentProps: Record<string, unknown> = {}
62
68
 
63
- return componentProps
64
- })
69
+ if (previewComponent.value === MarkdownRender) componentProps.source = props.text
70
+ else componentProps.innerHTML = props.text
65
71
 
66
- const emits = defineEmits<{
67
- (e: 'apply', text: unknown): void
68
- }>()
72
+ return componentProps
73
+ })
69
74
 
70
- function emitApply() {
71
- if (blockApply.value) return
72
- blockApply.value = true
75
+ const classes = computed(() => {
76
+ const classes = ['q-field-preview__content']
73
77
 
74
- const text = parseFieldValue(props.type, props.text)
78
+ if (previewComponent.value !== MarkdownRender) classes.push('preserve-whitespace')
75
79
 
76
- emits('apply', text)
77
- }
80
+ return classes
81
+ })
82
+
83
+ function emitApply() {
84
+ if (blockApply.value) return
85
+ blockApply.value = true
86
+
87
+ const text = parseFieldValue(props.type, props.text)
88
+
89
+ emit('apply', text)
90
+ }
91
+
92
+ function regenerate() {
93
+ if (blockRegenerate.value) return
94
+ blockRegenerate.value = true
95
+
96
+ emit('regenerate', props.name)
97
+ }
78
98
  </script>