@cnamts/synapse 0.0.7-alpha → 0.0.9-alpha

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 (198) hide show
  1. package/dist/design-system-v3.d.ts +785 -372
  2. package/dist/design-system-v3.js +4993 -3357
  3. package/dist/design-system-v3.umd.cjs +1 -10
  4. package/dist/style.css +1 -1
  5. package/package.json +10 -2
  6. package/src/assets/settings.scss +2 -2
  7. package/src/assets/tokens.scss +107 -112
  8. package/src/components/BackBtn/BackBtn.vue +4 -4
  9. package/src/components/BackToTopBtn/BackToTopBtn.vue +1 -0
  10. package/src/components/CollapsibleList/CollapsibleList.mdx +1 -1
  11. package/src/components/CollapsibleList/CollapsibleList.vue +43 -44
  12. package/src/components/ContextualMenu/Accessibilite.mdx +14 -0
  13. package/src/components/ContextualMenu/Accessibilite.stories.ts +191 -0
  14. package/src/components/ContextualMenu/AccessibiliteItems.ts +89 -0
  15. package/src/components/ContextualMenu/ContextualMenu.mdx +118 -0
  16. package/src/components/ContextualMenu/ContextualMenu.stories.ts +430 -0
  17. package/src/components/ContextualMenu/ContextualMenu.vue +101 -0
  18. package/src/components/ContextualMenu/constants/ExpertiseLevelEnum.ts +4 -0
  19. package/src/components/ContextualMenu/tests/ContextualMenu.spec.ts +115 -0
  20. package/src/components/ContextualMenu/tests/__snapshots__/ContextualMenu.spec.ts.snap +10 -0
  21. package/src/components/ContextualMenu/types.ts +5 -0
  22. package/src/components/CookieBanner/CookieBanner.stories.ts +1 -2
  23. package/src/components/CookieBanner/CookieBanner.vue +13 -10
  24. package/src/components/CookieBanner/tests/__snapshots__/CookieBanner.spec.ts.snap +17 -15
  25. package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +6 -1
  26. package/src/components/CookiesSelection/CookiesInformation/locales.ts +1 -0
  27. package/src/components/CookiesSelection/CookiesTable/CookiesTable.vue +1 -0
  28. package/src/components/CookiesSelection/tests/__snapshots__/CookiesSelection.spec.ts.snap +17 -15
  29. package/src/components/CopyBtn/CopyBtn.vue +7 -7
  30. package/src/components/Customs/SyBtnSelect/SyBtnSelect.vue +26 -26
  31. package/src/components/Customs/SyInputSelect/SyInputSelect.vue +24 -24
  32. package/src/components/Customs/SySelect/SySelect.stories.ts +7 -7
  33. package/src/components/Customs/SySelect/SySelect.vue +36 -30
  34. package/src/components/Customs/SySelect/tests/SySelect.spec.ts +2 -2
  35. package/src/components/Customs/SyTextField/SyTextField.stories.ts +187 -2
  36. package/src/components/Customs/SyTextField/SyTextField.vue +185 -16
  37. package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +2 -4
  38. package/src/components/Customs/SyTextField/tests/__snapshots__/SyTextField.spec.ts.snap +18 -16
  39. package/src/components/Customs/SyTextField/types.d.ts +2 -2
  40. package/src/components/DataList/DataList.stories.ts +3 -2
  41. package/src/components/DataList/DataList.vue +1 -1
  42. package/src/components/DataListGroup/DataListGroup.stories.ts +3 -2
  43. package/src/components/DataListItem/DataListItem.vue +12 -12
  44. package/src/components/DatePicker/DatePicker.mdx +191 -0
  45. package/src/components/DatePicker/DatePicker.stories.ts +787 -0
  46. package/src/components/DatePicker/DatePicker.vue +560 -0
  47. package/src/components/DatePicker/DateTextInput.vue +409 -0
  48. package/src/components/DatePicker/tests/DatePicker.spec.ts +266 -0
  49. package/src/components/DialogBox/DialogBox.mdx +28 -2
  50. package/src/components/DialogBox/DialogBox.stories.ts +2 -2
  51. package/src/components/DialogBox/DialogBox.vue +3 -2
  52. package/src/components/DownloadBtn/DownloadBtn.vue +2 -1
  53. package/src/components/ExternalLinks/Accessibilite.mdx +14 -0
  54. package/src/components/ExternalLinks/Accessibilite.stories.ts +191 -0
  55. package/src/components/ExternalLinks/AccessibiliteItems.ts +197 -0
  56. package/src/components/ExternalLinks/ExternalLinks.mdx +86 -0
  57. package/src/components/ExternalLinks/ExternalLinks.stories.ts +553 -0
  58. package/src/components/ExternalLinks/ExternalLinks.vue +200 -0
  59. package/src/components/ExternalLinks/config.ts +34 -0
  60. package/src/components/ExternalLinks/constants/ExpertiseLevelEnum.ts +4 -0
  61. package/src/components/ExternalLinks/locales.ts +4 -0
  62. package/src/components/ExternalLinks/tests/ExternalLinks.spec.ts +154 -0
  63. package/src/components/ExternalLinks/tests/__snapshots__/ExternalLinks.spec.ts.snap +159 -0
  64. package/src/components/FileUpload/FileUpload.mdx +165 -0
  65. package/src/components/FileUpload/FileUpload.stories.ts +429 -0
  66. package/src/components/FileUpload/FileUpload.vue +195 -0
  67. package/src/components/FileUpload/FileUploadContent.vue +109 -0
  68. package/src/components/FileUpload/locales.ts +10 -0
  69. package/src/components/FileUpload/tests/FileUpload.spec.ts +332 -0
  70. package/src/components/FileUpload/tests/__snapshots__/FileUpload.spec.ts.snap +7 -0
  71. package/src/components/FileUpload/useFileDrop.ts +23 -0
  72. package/src/components/FileUpload/validateFiles.ts +39 -0
  73. package/src/components/FooterBar/FooterBar.vue +105 -80
  74. package/src/components/FranceConnectBtn/FranceConnectBtn.vue +14 -13
  75. package/src/components/HeaderBar/HeaderBar.vue +3 -3
  76. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +11 -7
  77. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +5 -5
  78. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.vue +2 -2
  79. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +10 -8
  80. package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -2
  81. package/src/components/HeaderBar/HeaderLogo/logos/Logo-mobile.vue +2 -1
  82. package/src/components/HeaderBar/HeaderLogo/logos/Logo.vue +2 -1
  83. package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +10 -10
  84. package/src/components/HeaderBar/consts.scss +1 -1
  85. package/src/components/HeaderLoading/HeaderLoading.vue +12 -11
  86. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
  87. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +9 -9
  88. package/src/components/HeaderToolbar/HeaderToolbar.vue +215 -202
  89. package/src/components/LangBtn/LangBtn.vue +8 -6
  90. package/src/components/LogoBrandSection/LogoBrandSection.stories.ts +2 -2
  91. package/src/components/NirField/NirField.stories.ts +8 -8
  92. package/src/components/NirField/NirField.vue +46 -48
  93. package/src/components/NotFoundPage/NotFoundPage.stories.ts +33 -2
  94. package/src/components/NotFoundPage/NotFoundPage.vue +17 -0
  95. package/src/components/NotificationBar/NotificationBar.mdx +5 -5
  96. package/src/components/NotificationBar/NotificationBar.stories.ts +410 -314
  97. package/src/components/NotificationBar/NotificationBar.vue +43 -41
  98. package/src/components/PageContainer/PageContainer.vue +4 -4
  99. package/src/components/PasswordField/Accessibilite.mdx +14 -0
  100. package/src/components/PasswordField/Accessibilite.stories.ts +191 -0
  101. package/src/components/PasswordField/AccessibiliteItems.ts +184 -0
  102. package/src/components/PasswordField/PasswordField.mdx +70 -0
  103. package/src/components/PasswordField/PasswordField.stories.ts +213 -0
  104. package/src/components/PasswordField/PasswordField.vue +189 -0
  105. package/src/components/PasswordField/config.ts +11 -0
  106. package/src/components/PasswordField/constants/ExpertiseLevelEnum.ts +4 -0
  107. package/src/components/PasswordField/locales.ts +4 -0
  108. package/src/components/PasswordField/tests/PasswordField.spec.ts +96 -0
  109. package/src/components/PhoneField/PhoneField.mdx +0 -2
  110. package/src/components/PhoneField/PhoneField.stories.ts +10 -50
  111. package/src/components/PhoneField/PhoneField.vue +77 -93
  112. package/src/components/PhoneField/tests/PhoneField.spec.ts +0 -15
  113. package/src/components/RangeField/RangeField.mdx +54 -0
  114. package/src/components/RangeField/RangeField.stories.ts +189 -0
  115. package/src/components/RangeField/RangeField.vue +157 -0
  116. package/src/components/RangeField/RangeSlider/RangeSlider.vue +387 -0
  117. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +64 -0
  118. package/src/components/RangeField/RangeSlider/tests/__snapshots__/rangeSlider.spec.ts.snap +27 -0
  119. package/src/components/RangeField/RangeSlider/tests/rangeSlider.spec.ts +100 -0
  120. package/src/components/RangeField/RangeSlider/tests/useDoubleSlider.spec.ts +246 -0
  121. package/src/components/RangeField/RangeSlider/tests/useMouseSlide.spec.ts +204 -0
  122. package/src/components/RangeField/RangeSlider/tests/useThumb.spec.ts +22 -0
  123. package/src/components/RangeField/RangeSlider/tests/useThumbKeyboard.spec.ts +233 -0
  124. package/src/components/RangeField/RangeSlider/tests/useTooltipsNudge.spec.ts +150 -0
  125. package/src/components/RangeField/RangeSlider/tests/useTrack.spec.ts +314 -0
  126. package/src/components/RangeField/RangeSlider/tests/vAnimateClick.spec.ts +32 -0
  127. package/src/components/RangeField/RangeSlider/types.ts +15 -0
  128. package/src/components/RangeField/RangeSlider/useMouseSlide.ts +109 -0
  129. package/src/components/RangeField/RangeSlider/useRangeSlider.ts +126 -0
  130. package/src/components/RangeField/RangeSlider/useThumb.ts +18 -0
  131. package/src/components/RangeField/RangeSlider/useThumbKeyboard.ts +84 -0
  132. package/src/components/RangeField/RangeSlider/useTooltipsNudge.ts +92 -0
  133. package/src/components/RangeField/RangeSlider/useTrack.ts +116 -0
  134. package/src/components/RangeField/RangeSlider/vAnimateClick.ts +19 -0
  135. package/src/components/RangeField/config.ts +7 -0
  136. package/src/components/RangeField/locales.ts +4 -0
  137. package/src/components/RangeField/tests/RangeField.spec.ts +224 -0
  138. package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +379 -0
  139. package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +205 -0
  140. package/src/components/RatingPicker/EmotionPicker/locales.ts +3 -0
  141. package/src/components/RatingPicker/EmotionPicker/tests/EmotionPicker.spec.ts +104 -0
  142. package/src/components/RatingPicker/EmotionPicker/tests/__snapshots__/EmotionPicker.spec.ts.snap +66 -0
  143. package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +159 -0
  144. package/src/components/RatingPicker/NumberPicker/locales.ts +4 -0
  145. package/src/components/RatingPicker/NumberPicker/tests/NumberPicker.spec.ts +73 -0
  146. package/src/components/RatingPicker/NumberPicker/tests/__snapshots__/NumberPicker.spec.ts.snap +105 -0
  147. package/src/components/RatingPicker/Rating.ts +45 -0
  148. package/src/components/RatingPicker/RatingPicker.mdx +56 -0
  149. package/src/components/RatingPicker/RatingPicker.stories.ts +515 -0
  150. package/src/components/RatingPicker/RatingPicker.vue +122 -0
  151. package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +116 -0
  152. package/src/components/RatingPicker/StarsPicker/tests/StarsPicker.spec.ts +95 -0
  153. package/src/components/RatingPicker/StarsPicker/tests/__snapshots__/StarsPicker.spec.ts.snap +36 -0
  154. package/src/components/RatingPicker/locales.ts +3 -0
  155. package/src/components/RatingPicker/tests/Rating.spec.ts +104 -0
  156. package/src/components/RatingPicker/tests/RatingPicker.spec.ts +187 -0
  157. package/src/components/RatingPicker/tests/__snapshots__/RatingPicker.spec.ts.snap +108 -0
  158. package/src/components/SearchListField/SearchListField.mdx +74 -0
  159. package/src/components/SearchListField/SearchListField.stories.ts +126 -0
  160. package/src/components/SearchListField/SearchListField.vue +194 -0
  161. package/src/components/SearchListField/locales.ts +5 -0
  162. package/src/components/SearchListField/tests/SearchListField.spec.ts +323 -0
  163. package/src/components/SearchListField/types.d.ts +4 -0
  164. package/src/components/SelectBtnField/SelectBtnField.mdx +50 -0
  165. package/src/components/SelectBtnField/SelectBtnField.stories.ts +763 -0
  166. package/src/components/SelectBtnField/SelectBtnField.vue +283 -0
  167. package/src/components/SelectBtnField/config.ts +11 -0
  168. package/src/components/SelectBtnField/tests/SelectBtnField.spec.ts +327 -0
  169. package/src/components/SelectBtnField/tests/__snapshots__/SelectBtnField.spec.ts.snap +125 -0
  170. package/src/components/SelectBtnField/types.d.ts +11 -0
  171. package/src/components/SkipLink/SkipLink.vue +10 -10
  172. package/src/components/SocialMediaLinks/SocialMediaLinks.vue +28 -26
  173. package/src/components/SubHeader/SubHeader.vue +32 -31
  174. package/src/components/SyAlert/SyAlert.vue +12 -12
  175. package/src/components/UserMenuBtn/UserMenuBtn.vue +1 -1
  176. package/src/components/UserMenuBtn/config.ts +1 -1
  177. package/src/components/index.ts +17 -7
  178. package/src/composables/rules/useFieldValidation.ts +172 -44
  179. package/src/designTokens/index.ts +6 -4
  180. package/src/designTokens/{bootstrapColors.md → paColors.md} +1 -1
  181. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +2 -0
  182. package/src/designTokens/tokens/pa/paColors.ts +171 -0
  183. package/src/designTokens/tokens/pa/paContextual.ts +58 -0
  184. package/src/designTokens/tokens/pa/paDarkTheme.ts +5 -0
  185. package/src/designTokens/tokens/pa/paLightTheme.ts +123 -0
  186. package/src/designTokens/tokens/pa/paSemantic.ts +87 -0
  187. package/src/stories/Fondamentaux/CustomisationEtThemes.mdx +52 -2
  188. package/src/stories/GuideDuDev/CreerUneIssue.mdx +64 -0
  189. package/src/stories/GuideDuDev/{CommentUtiliserLesRules.mdx → UtiliserLesRules.mdx} +2 -2
  190. package/src/stories/GuideDuDev/components.stories.ts +9 -7
  191. package/src/stories/Guidelines/Vuetify/Vuetify.stories.ts +163 -88
  192. package/src/stories/Guidelines/Vuetify/VuetifyItems.ts +250 -23
  193. package/src/temp/TestDTComponent.vue +5 -6
  194. package/src/utils/calcHumanFileSize/index.ts +12 -0
  195. package/src/utils/calcHumanFileSize/tests/calcHumanFileSize.spec.ts +21 -0
  196. package/src/designTokens/tokens/bootstrap/bootstrapColors.ts +0 -158
  197. package/src/designTokens/tokens/bootstrap/bootstrapLightTheme.ts +0 -22
  198. package/src/stories/GuideDuDev/CommentContribuer.mdx +0 -22
@@ -0,0 +1,116 @@
1
+ <script lang="ts" setup>
2
+ import { ref, type PropType, onMounted } from 'vue'
3
+ import { RatingEnum, useRating } from '../Rating'
4
+ import { mdiStarOutline, mdiStar } from '@mdi/js'
5
+
6
+ const props = defineProps({
7
+ label: {
8
+ type: String as PropType<string | null>,
9
+ default: RatingEnum.STARS,
10
+ },
11
+ length: {
12
+ type: Number,
13
+ default: 5,
14
+ },
15
+ readonly: {
16
+ type: Boolean,
17
+ default: false,
18
+ },
19
+ modelValue: {
20
+ type: Number,
21
+ default: -1,
22
+ },
23
+ })
24
+
25
+ const emit = defineEmits(['update:modelValue'])
26
+ const { hasAnswered, emitInputEvent } = useRating(props, emit)
27
+
28
+ const starOutlineIcon = mdiStarOutline
29
+ const starIcon = mdiStar
30
+ const hoverIndex = ref<number | null>(-1)
31
+
32
+ function isActive(index: number): boolean {
33
+ return props.modelValue - 1 === index
34
+ }
35
+
36
+ function isFilled(index: number): boolean {
37
+ const isHovered = hoverIndex.value !== null && hoverIndex.value >= index
38
+ const isActive = props.modelValue - 1 >= index
39
+ return isHovered || isActive
40
+ }
41
+
42
+ onMounted(() => {
43
+ const hiddenInputs = document.querySelectorAll('.v-rating__hidden')
44
+ hiddenInputs.forEach((input) => {
45
+ (input as HTMLElement).setAttribute('aria-hidden', 'true')
46
+ })
47
+ })
48
+ </script>
49
+
50
+ <template>
51
+ <fieldset class="vd-stars-picker">
52
+ <legend class="text-h6 mb-6">
53
+ <slot name="label">
54
+ {{ props.label }}
55
+ </slot>
56
+ </legend>
57
+
58
+ <VRating
59
+ :model-value="props.modelValue"
60
+ :length="props.length"
61
+ :readonly="props.readonly || hasAnswered"
62
+ class="d-flex flex-wrap max-width-none mx-n3"
63
+ @update:model-value="(value) => emit('update:modelValue', value)"
64
+ >
65
+ <template #item="{ index }">
66
+ <button
67
+ :disabled="props.readonly"
68
+ :aria-pressed="isActive(index)"
69
+ :aria-label="`${index + 1} star`"
70
+ @mouseover="hoverIndex = index"
71
+ @focus="hoverIndex = index"
72
+ @mouseleave="hoverIndex = -1"
73
+ @blur="hoverIndex = -1"
74
+ @click="emitInputEvent(index + 1)"
75
+ >
76
+ <VIcon
77
+ :class="
78
+ isFilled(index)
79
+ ? 'text-primary'
80
+ : 'text-blue-lighten'
81
+ "
82
+ size="36px"
83
+ class="py-0 px-2"
84
+ >
85
+ {{ isFilled(index) ? starIcon : starOutlineIcon }}
86
+ </VIcon>
87
+ </button>
88
+ </template>
89
+ </VRating>
90
+ </fieldset>
91
+ </template>
92
+
93
+ <style lang="scss" scoped>
94
+ @use '@/assets/tokens';
95
+
96
+ .vd-stars-picker {
97
+ border: 0;
98
+ }
99
+
100
+ .v-rating .v-icon {
101
+ width: 52px !important;
102
+ height: 36px !important;
103
+
104
+ &--disabled.text-primary {
105
+ color: tokens.$primary-base !important;
106
+ }
107
+
108
+ &.text-blue-lighten {
109
+ color: tokens.$blue-lighten-60 !important;
110
+ }
111
+
112
+ &--disabled.text-blue-lighten {
113
+ color: tokens.$blue-lighten-60 !important;
114
+ }
115
+ }
116
+ </style>
@@ -0,0 +1,95 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+
5
+ import StarsPicker from '../StarsPicker.vue'
6
+ import { VIcon } from 'vuetify/components'
7
+ import { mdiStarOutline, mdiStar } from '@mdi/js'
8
+
9
+ describe('StarsPicker', () => {
10
+ it('renders correctly', () => {
11
+ const wrapper = mount(StarsPicker, {
12
+ global: {
13
+ plugins: [vuetify],
14
+ },
15
+ propsData: {
16
+ label: 'Pourriez-vous donner une note ?',
17
+ },
18
+ })
19
+
20
+ expect(wrapper.html()).toMatchSnapshot()
21
+ })
22
+
23
+ it('emits an event when a number is selected', async () => {
24
+ const wrapper = mount(StarsPicker, {
25
+ global: {
26
+ plugins: [vuetify],
27
+ },
28
+ })
29
+
30
+ await wrapper.findAll('button')!.at(3)!.trigger('click')
31
+
32
+ expect(wrapper.emitted('update:modelValue')![0]).toEqual([4])
33
+ })
34
+
35
+ it('change the displayed value when the modelValue is updated', async () => {
36
+ const wrapper = mount(StarsPicker, {
37
+ global: {
38
+ plugins: [vuetify],
39
+ },
40
+ propsData: {
41
+ modelValue: 3,
42
+ },
43
+ })
44
+
45
+ await wrapper.setProps({ modelValue: 4 })
46
+ expect(wrapper.findAll('button')[3].attributes('aria-pressed')).toBe(
47
+ 'true',
48
+ )
49
+ await wrapper.setProps({ modelValue: 1 })
50
+ expect(wrapper.findAll('button')[3].attributes('aria-pressed')).toBe(
51
+ 'false',
52
+ )
53
+ expect(wrapper.findAll('button')[0].attributes('aria-pressed')).toBe(
54
+ 'true',
55
+ )
56
+ })
57
+
58
+ it('change the style of the stars on hover', async () => {
59
+ const wrapper = mount(StarsPicker, {
60
+ global: {
61
+ plugins: [vuetify],
62
+ },
63
+ })
64
+
65
+ const buttons = wrapper.findAll('button')
66
+ await buttons.at(3)!.trigger('mouseover')
67
+
68
+ const icon = buttons!.at(3)!.findComponent(VIcon)
69
+ let slotContent = icon.vm.$slots.default!()![0].children
70
+ expect(slotContent).toContain(mdiStar)
71
+
72
+ await buttons.at(3)!.trigger('mouseleave')
73
+ slotContent = icon.vm.$slots.default!()![0].children
74
+ expect(slotContent).toContain(mdiStarOutline)
75
+ })
76
+
77
+ it('change the style of the stars on focus', async () => {
78
+ const wrapper = mount(StarsPicker, {
79
+ global: {
80
+ plugins: [vuetify],
81
+ },
82
+ })
83
+
84
+ const buttons = wrapper.findAll('button')
85
+ await buttons.at(3)!.trigger('focus')
86
+
87
+ const icon = buttons!.at(3)!.findComponent(VIcon)
88
+ let slotContent = icon.vm.$slots.default!()![0].children
89
+ expect(slotContent).toContain(mdiStar)
90
+
91
+ await buttons.at(3)!.trigger('blur')
92
+ slotContent = icon.vm.$slots.default!()![0].children
93
+ expect(slotContent).toContain(mdiStarOutline)
94
+ })
95
+ })
@@ -0,0 +1,36 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`StarsPicker > renders correctly 1`] = `
4
+ "<fieldset data-v-b11635b9="" class="vd-stars-picker">
5
+ <legend data-v-b11635b9="" class="text-h6 mb-6">Pourriez-vous donner une note ?</legend>
6
+ <div data-v-b11635b9="" class="v-rating v-theme--light d-flex flex-wrap max-width-none mx-n3"><label for="v-rating-0-0" class=""><span class="v-rating__hidden">Rating 0 of 5</span>
7
+ <!---->
8
+ </label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-0" type="radio" checked="" tabindex="-1" value="0">
9
+ <div class="v-rating__wrapper">
10
+ <!---->
11
+ <div class="v-rating__item"><label for="v-rating-0-1" class=""><span class="v-rating__hidden">Rating 1 of 5</span><button data-v-b11635b9="" aria-pressed="false" aria-label="1 star"><i data-v-b11635b9="" class="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z mdi v-icon notranslate v-theme--light text-blue-lighten py-0 px-2" style="font-size: 36px; height: 36px; width: 36px;" aria-hidden="true"></i></button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-1" type="radio" tabindex="-1" value="1"></div>
12
+ <!---->
13
+ </div>
14
+ <div class="v-rating__wrapper">
15
+ <!---->
16
+ <div class="v-rating__item"><label for="v-rating-0-2" class=""><span class="v-rating__hidden">Rating 2 of 5</span><button data-v-b11635b9="" aria-pressed="false" aria-label="2 star"><i data-v-b11635b9="" class="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z mdi v-icon notranslate v-theme--light text-blue-lighten py-0 px-2" style="font-size: 36px; height: 36px; width: 36px;" aria-hidden="true"></i></button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-2" type="radio" tabindex="-1" value="2"></div>
17
+ <!---->
18
+ </div>
19
+ <div class="v-rating__wrapper">
20
+ <!---->
21
+ <div class="v-rating__item"><label for="v-rating-0-3" class=""><span class="v-rating__hidden">Rating 3 of 5</span><button data-v-b11635b9="" aria-pressed="false" aria-label="3 star"><i data-v-b11635b9="" class="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z mdi v-icon notranslate v-theme--light text-blue-lighten py-0 px-2" style="font-size: 36px; height: 36px; width: 36px;" aria-hidden="true"></i></button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-3" type="radio" tabindex="-1" value="3"></div>
22
+ <!---->
23
+ </div>
24
+ <div class="v-rating__wrapper">
25
+ <!---->
26
+ <div class="v-rating__item"><label for="v-rating-0-4" class=""><span class="v-rating__hidden">Rating 4 of 5</span><button data-v-b11635b9="" aria-pressed="false" aria-label="4 star"><i data-v-b11635b9="" class="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z mdi v-icon notranslate v-theme--light text-blue-lighten py-0 px-2" style="font-size: 36px; height: 36px; width: 36px;" aria-hidden="true"></i></button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-4" type="radio" tabindex="-1" value="4"></div>
27
+ <!---->
28
+ </div>
29
+ <div class="v-rating__wrapper">
30
+ <!---->
31
+ <div class="v-rating__item"><label for="v-rating-0-5" class=""><span class="v-rating__hidden">Rating 5 of 5</span><button data-v-b11635b9="" aria-pressed="false" aria-label="5 star"><i data-v-b11635b9="" class="M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z mdi v-icon notranslate v-theme--light text-blue-lighten py-0 px-2" style="font-size: 36px; height: 36px; width: 36px;" aria-hidden="true"></i></button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-5" type="radio" tabindex="-1" value="5"></div>
32
+ <!---->
33
+ </div>
34
+ </div>
35
+ </fieldset>"
36
+ `;
@@ -0,0 +1,3 @@
1
+ export const locales = {
2
+ thanks: 'Merci pour votre réponse',
3
+ }
@@ -0,0 +1,104 @@
1
+ import { defineComponent } from 'vue'
2
+ import { describe, it, expect } from 'vitest'
3
+ import { mount } from '@vue/test-utils'
4
+ import { vuetify } from '@tests/unit/setup'
5
+
6
+ import { useRating } from '../Rating'
7
+
8
+ /** Create the test component */
9
+ function createTestComponent() {
10
+ return defineComponent({
11
+ props: {
12
+ label: {
13
+ type: String,
14
+ default: null,
15
+ },
16
+ readonly: {
17
+ type: Boolean,
18
+ default: false,
19
+ },
20
+ modelValue: {
21
+ type: Number,
22
+ default: -1,
23
+ },
24
+ },
25
+ emits: ['update:modelValue'],
26
+ setup(props, { emit }) {
27
+ const { internalValue, hasAnswered, emitInputEvent } = useRating(props, emit)
28
+
29
+ return {
30
+ internalValue,
31
+ hasAnswered,
32
+ emitInputEvent,
33
+ }
34
+ },
35
+ template: '<div />', // Placeholder template for the test
36
+ })
37
+ }
38
+
39
+ describe('useRating', () => {
40
+ const label = 'Pouvez-vous nous en dire plus ?'
41
+
42
+ it('verifies props', () => {
43
+ const testComponent = createTestComponent()
44
+
45
+ const wrapper = mount(testComponent, {
46
+ props: {
47
+ label,
48
+ },
49
+ global: {
50
+ plugins: [vuetify],
51
+ },
52
+ })
53
+
54
+ expect(wrapper.props('label')).toBe(label)
55
+ expect(wrapper.props('readonly')).toBe(false) // Ensure default prop value
56
+ expect(wrapper.props('modelValue')).toBe(-1) // Ensure default model value
57
+ })
58
+
59
+ it('emits input event', async () => {
60
+ const testComponent = createTestComponent()
61
+
62
+ const wrapper = mount(testComponent, {
63
+ props: {
64
+ label,
65
+ },
66
+ global: {
67
+ plugins: [vuetify],
68
+ },
69
+ })
70
+
71
+ // Call the composable's emitInputEvent method
72
+ wrapper.vm.emitInputEvent(3)
73
+
74
+ await wrapper.vm.$nextTick() // Wait for any asynchronous updates
75
+
76
+ // Check that the emit occurred
77
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy()
78
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([3])
79
+ })
80
+
81
+ it('checks hasAnswered computed property', async () => {
82
+ const testComponent = createTestComponent()
83
+
84
+ const wrapper = mount(testComponent, {
85
+ props: {
86
+ label,
87
+ modelValue: 3, // Set modelValue to a non-default value
88
+ },
89
+ global: {
90
+ plugins: [vuetify],
91
+ },
92
+ })
93
+
94
+ // Ensure hasAnswered reflects the proper state
95
+ expect(wrapper.vm.hasAnswered).toBe(true)
96
+
97
+ // Modify the modelValue
98
+ wrapper.vm.emitInputEvent(-1)
99
+ await wrapper.vm.$nextTick()
100
+
101
+ // Ensure hasAnswered updates accordingly
102
+ expect(wrapper.vm.hasAnswered).toBe(false)
103
+ })
104
+ })
@@ -0,0 +1,187 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+
5
+ import RatingPicker from '../RatingPicker.vue'
6
+ import { RatingEnum } from '../Rating'
7
+ import NumberPicker from '../NumberPicker/NumberPicker.vue'
8
+ import EmotionPicker from '../EmotionPicker/EmotionPicker.vue'
9
+ import StarsPicker from '../StarsPicker/StarsPicker.vue'
10
+
11
+ import { locales as emotionPickerlocales } from '../EmotionPicker/locales'
12
+ import { locales } from '../locales'
13
+
14
+ describe('RatingPicker', () => {
15
+ it('renders correctly', () => {
16
+ const wrapper = mount(RatingPicker, {
17
+ global: {
18
+ plugins: [vuetify],
19
+ },
20
+ stubs: {
21
+ NumberPicker: {
22
+ template: '<div />',
23
+ },
24
+ },
25
+ propsData: {
26
+ type: RatingEnum.NUMBER,
27
+ },
28
+ })
29
+
30
+ expect(wrapper.html()).toMatchSnapshot()
31
+ })
32
+
33
+ it('renders with additional content with the NumberPicker', async () => {
34
+ const wrapper = mount(RatingPicker, {
35
+ global: {
36
+ plugins: [vuetify],
37
+ },
38
+ stubs: {
39
+ NumberPicker: {
40
+ template: '<div />',
41
+ },
42
+ },
43
+ propsData: {
44
+ type: RatingEnum.NUMBER,
45
+ },
46
+ slots: {
47
+ default: '<div>Additional content</div>',
48
+ },
49
+ })
50
+
51
+ wrapper.findComponent(NumberPicker).vm.$emit('update:modelValue', 5)
52
+ await wrapper.setProps({ modelValue: 5 })
53
+
54
+ expect(wrapper.text()).toContain(locales.thanks)
55
+ expect(wrapper.text()).toContain('Additional content')
56
+ })
57
+
58
+ it('renders with additional content with the StarsPicker', async () => {
59
+ const wrapper = mount(RatingPicker, {
60
+ global: {
61
+ plugins: [vuetify],
62
+ },
63
+ stubs: {
64
+ StarsPicker: {
65
+ template: '<div />',
66
+ },
67
+ },
68
+ propsData: {
69
+ type: RatingEnum.STARS,
70
+ },
71
+ slots: {
72
+ default: '<div>Additional content</div>',
73
+ },
74
+ })
75
+
76
+ wrapper.findComponent(StarsPicker).vm.$emit('update:modelValue', 3)
77
+ await wrapper.setProps({ modelValue: 3 })
78
+
79
+ expect(wrapper.text()).toContain(locales.thanks)
80
+ expect(wrapper.text()).toContain('Additional content')
81
+ })
82
+
83
+ it('renders with additional content with the EmotionPicker', async () => {
84
+ const wrapper = mount(RatingPicker, {
85
+ global: {
86
+ plugins: [vuetify],
87
+ },
88
+ stubs: {
89
+ EmotionPicker: {
90
+ template: '<div />',
91
+ },
92
+ },
93
+ propsData: {
94
+ type: RatingEnum.EMOTION,
95
+ },
96
+ slots: {
97
+ default: '<div>Additional content</div>',
98
+ },
99
+ })
100
+
101
+ wrapper.findComponent(EmotionPicker).vm.$emit('update:modelValue', 2)
102
+ await wrapper.setProps({ modelValue: 2 })
103
+
104
+ expect(wrapper.text()).toContain(locales.thanks)
105
+ expect(wrapper.text()).toContain('Additional content')
106
+ })
107
+
108
+ it('renders with additional content with the EmotionPicker when twoEmotions is true', async () => {
109
+ const wrapper = mount(RatingPicker, {
110
+ global: {
111
+ plugins: [vuetify],
112
+ },
113
+ stubs: {
114
+ EmotionPicker: {
115
+ template: '<div />',
116
+ },
117
+ },
118
+ propsData: {
119
+ type: RatingEnum.EMOTION,
120
+ twoEmotions: true,
121
+ },
122
+ slots: {
123
+ default: '<div>Additional content</div>',
124
+ },
125
+ })
126
+
127
+ wrapper.findComponent(EmotionPicker).vm.$emit('update:modelValue', 1)
128
+ await wrapper.setProps({ modelValue: 1 })
129
+
130
+ expect(wrapper.text()).toContain(locales.thanks)
131
+ expect(wrapper.text()).toContain('Additional content')
132
+ })
133
+
134
+ it('do not render the additional content when the rating is good', async () => {
135
+ const wrapper = mount(RatingPicker, {
136
+ global: {
137
+ plugins: [vuetify],
138
+ },
139
+ stubs: {
140
+ NumberPicker: {
141
+ template: '<div />',
142
+ },
143
+ },
144
+ propsData: {
145
+ type: RatingEnum.NUMBER,
146
+ },
147
+ slots: {
148
+ default: '<div>Additional content</div>',
149
+ },
150
+ })
151
+
152
+ wrapper.findComponent(NumberPicker).vm.$emit('update:modelValue', 8)
153
+ await wrapper.setProps({ modelValue: 8 })
154
+ expect(wrapper.text()).toContain(locales.thanks)
155
+ expect(wrapper.text()).not.toContain('Additional content')
156
+ })
157
+
158
+ it('sends the correct values to the EmotionPicker', async () => {
159
+ const wrapper = mount(RatingPicker, {
160
+ global: {
161
+ plugins: [vuetify],
162
+ },
163
+ stubs: {
164
+ EmotionPicker: {
165
+ template: '<div />',
166
+ },
167
+ },
168
+ propsData: {
169
+ type: RatingEnum.EMOTION,
170
+ itemLabels: ['label1', 'label3'],
171
+ twoEmotions: true,
172
+ },
173
+ })
174
+
175
+ expect(wrapper.findComponent(EmotionPicker).props('length')).toBe(2)
176
+ expect(
177
+ wrapper.findComponent(EmotionPicker).props('itemLabels'),
178
+ ).toEqual(['label1', 'label3'])
179
+
180
+ await wrapper.setProps({ twoEmotions: false })
181
+ await wrapper.setProps({ itemLabels: undefined })
182
+ expect(wrapper.findComponent(EmotionPicker).props('length')).toBe(3)
183
+ expect(
184
+ wrapper.findComponent(EmotionPicker).props('itemLabels'),
185
+ ).toEqual(emotionPickerlocales.defaultEmotionLabels)
186
+ })
187
+ })
@@ -0,0 +1,108 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`RatingPicker > renders correctly 1`] = `
4
+ "<div class="vd-rating-picker">
5
+ <fieldset data-v-30bbac4d="" class="vd-number-picker">
6
+ <legend data-v-30bbac4d="" class="d-sr-only"></legend>
7
+ <legend data-v-30bbac4d="" class="text-h6 mb-6"></legend>
8
+ <div data-v-30bbac4d="" class="d-inline-block">
9
+ <div data-v-30bbac4d="" class="v-rating v-theme--light d-flex flex-wrap max-width-none"><label for="v-rating-0-0" class=""><span class="v-rating__hidden">Rating 0 of 10</span>
10
+ <!---->
11
+ </label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-0" type="radio" checked="" tabindex="-1" value="0">
12
+ <div class="v-rating__wrapper">
13
+ <!---->
14
+ <div class="v-rating__item"><label for="v-rating-0-1" class=""><span class="v-rating__hidden">Rating 1 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 1 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
15
+ <!----><span class="v-btn__content" data-no-activator="">1</span>
16
+ <!---->
17
+ <!---->
18
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-1" type="radio" tabindex="-1" value="1"></div>
19
+ <!---->
20
+ </div>
21
+ <div class="v-rating__wrapper">
22
+ <!---->
23
+ <div class="v-rating__item"><label for="v-rating-0-2" class=""><span class="v-rating__hidden">Rating 2 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 2 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
24
+ <!----><span class="v-btn__content" data-no-activator="">2</span>
25
+ <!---->
26
+ <!---->
27
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-2" type="radio" tabindex="-1" value="2"></div>
28
+ <!---->
29
+ </div>
30
+ <div class="v-rating__wrapper">
31
+ <!---->
32
+ <div class="v-rating__item"><label for="v-rating-0-3" class=""><span class="v-rating__hidden">Rating 3 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 3 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
33
+ <!----><span class="v-btn__content" data-no-activator="">3</span>
34
+ <!---->
35
+ <!---->
36
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-3" type="radio" tabindex="-1" value="3"></div>
37
+ <!---->
38
+ </div>
39
+ <div class="v-rating__wrapper">
40
+ <!---->
41
+ <div class="v-rating__item"><label for="v-rating-0-4" class=""><span class="v-rating__hidden">Rating 4 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 4 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
42
+ <!----><span class="v-btn__content" data-no-activator="">4</span>
43
+ <!---->
44
+ <!---->
45
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-4" type="radio" tabindex="-1" value="4"></div>
46
+ <!---->
47
+ </div>
48
+ <div class="v-rating__wrapper">
49
+ <!---->
50
+ <div class="v-rating__item"><label for="v-rating-0-5" class=""><span class="v-rating__hidden">Rating 5 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 5 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
51
+ <!----><span class="v-btn__content" data-no-activator="">5</span>
52
+ <!---->
53
+ <!---->
54
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-5" type="radio" tabindex="-1" value="5"></div>
55
+ <!---->
56
+ </div>
57
+ <div class="v-rating__wrapper">
58
+ <!---->
59
+ <div class="v-rating__item"><label for="v-rating-0-6" class=""><span class="v-rating__hidden">Rating 6 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 6 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
60
+ <!----><span class="v-btn__content" data-no-activator="">6</span>
61
+ <!---->
62
+ <!---->
63
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-6" type="radio" tabindex="-1" value="6"></div>
64
+ <!---->
65
+ </div>
66
+ <div class="v-rating__wrapper">
67
+ <!---->
68
+ <div class="v-rating__item"><label for="v-rating-0-7" class=""><span class="v-rating__hidden">Rating 7 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 7 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
69
+ <!----><span class="v-btn__content" data-no-activator="">7</span>
70
+ <!---->
71
+ <!---->
72
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-7" type="radio" tabindex="-1" value="7"></div>
73
+ <!---->
74
+ </div>
75
+ <div class="v-rating__wrapper">
76
+ <!---->
77
+ <div class="v-rating__item"><label for="v-rating-0-8" class=""><span class="v-rating__hidden">Rating 8 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 8 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
78
+ <!----><span class="v-btn__content" data-no-activator="">8</span>
79
+ <!---->
80
+ <!---->
81
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-8" type="radio" tabindex="-1" value="8"></div>
82
+ <!---->
83
+ </div>
84
+ <div class="v-rating__wrapper">
85
+ <!---->
86
+ <div class="v-rating__item"><label for="v-rating-0-9" class=""><span class="v-rating__hidden">Rating 9 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 9 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
87
+ <!----><span class="v-btn__content" data-no-activator="">9</span>
88
+ <!---->
89
+ <!---->
90
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-9" type="radio" tabindex="-1" value="9"></div>
91
+ <!---->
92
+ </div>
93
+ <div class="v-rating__wrapper">
94
+ <!---->
95
+ <div class="v-rating__item"><label for="v-rating-0-10" class=""><span class="v-rating__hidden">Rating 10 of 10</span><button data-v-30bbac4d="" type="button" class="v-btn v-theme--light text-primary v-btn--density-default v-btn--size-x-small v-btn--variant-outlined text-body-2 pa-0 mr-2" style="height: 36px;" aria-label="Note de 10 sur 10."><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
96
+ <!----><span class="v-btn__content" data-no-activator="">10</span>
97
+ <!---->
98
+ <!---->
99
+ </button></label><input class="v-rating__hidden" name="v-rating-0" id="v-rating-0-10" type="radio" tabindex="-1" value="10"></div>
100
+ <!---->
101
+ </div>
102
+ </div>
103
+ <!--v-if-->
104
+ </div>
105
+ </fieldset>
106
+ <!--v-if-->
107
+ </div>"
108
+ `;