@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,64 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue'
3
+
4
+ const props = withDefaults(defineProps<{
5
+ nudgeLeft?: number
6
+ nudgeRight?: number
7
+ }>(), {
8
+ nudgeLeft: 0,
9
+ nudgeRight: 0,
10
+ })
11
+
12
+ const tooltipStyle = computed(() => {
13
+ const correction = props.nudgeLeft ? props.nudgeLeft : props.nudgeRight * -1
14
+ return {
15
+ transform: `translateX(calc(-50% + ${Math.ceil(correction)}px))`,
16
+ }
17
+ })
18
+
19
+ const tooltip = ref<HTMLElement | null>(null)
20
+
21
+ defineExpose({
22
+ element: tooltip,
23
+ })
24
+ </script>
25
+
26
+ <template>
27
+ <div class="tooltip-wrapper">
28
+ <div
29
+ ref="tooltip"
30
+ class="tooltip"
31
+ :style="tooltipStyle"
32
+ >
33
+ <slot />
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <style lang="scss" scoped>
39
+ .tooltip-wrapper {
40
+ position: absolute;
41
+ top: 0;
42
+ left: 20px;
43
+
44
+ &::before {
45
+ content: '';
46
+ position: absolute;
47
+ top: 100%;
48
+ left: 50%;
49
+ transform: translate(-50%, 0);
50
+ border: 6px solid transparent;
51
+ border-top-color: rgb(0 0 0 / 70%);
52
+ }
53
+ }
54
+
55
+ .tooltip {
56
+ position: absolute;
57
+ bottom: 0;
58
+ background-color: rgb(0 0 0 / 70%);
59
+ color: #fff;
60
+ padding: 4px 8px;
61
+ border-radius: 4px;
62
+ will-change: transform;
63
+ }
64
+ </style>
@@ -0,0 +1,27 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`RangeField component > should render the component 1`] = `
4
+ "<div data-v-cfbfc2ef="" class="wrapper">
5
+ <div data-v-cfbfc2ef="" class="track"><button data-v-cfbfc2ef="" class="thumb-min" style="left: 25%;" role="slider" aria-valuenow="25" tabindex="0" aria-valuemin="0" aria-valuemax="75" aria-orientation="horizontal" aria-label="Minimum" title="Minimum">
6
+ <div data-v-24e1b71f="" data-v-cfbfc2ef="" class="tooltip-wrapper">
7
+ <div data-v-24e1b71f="" class="tooltip" style="transform: translateX(calc(-50% + 0px)); transition: transform 0.1s;">25</div>
8
+ </div><span data-v-cfbfc2ef="" class="inner-thumb"></span>
9
+ </button><button data-v-cfbfc2ef="" role="slider" class="thumb-max" style="left: 75%;" aria-valuenow="75" tabindex="0" aria-valuemin="25" aria-valuemax="100" aria-orientation="horizontal" aria-label="Maximum" title="Maximum">
10
+ <div data-v-24e1b71f="" data-v-cfbfc2ef="" class="tooltip-wrapper">
11
+ <div data-v-24e1b71f="" class="tooltip" style="transform: translateX(calc(-50% + 0px)); transition: transform 0.1s;">75</div>
12
+ </div><span data-v-cfbfc2ef="" class="inner-thumb"></span>
13
+ </button>
14
+ <div data-v-cfbfc2ef="" class="fake-thumb thumb-min" aria-hidden="true" style="left: 25%;">
15
+ <div data-v-24e1b71f="" data-v-cfbfc2ef="" class="tooltip-wrapper">
16
+ <div data-v-24e1b71f="" class="tooltip" style="transform: translateX(calc(-50% + 0px));">25</div>
17
+ </div>
18
+ </div>
19
+ <div data-v-cfbfc2ef="" class="fake-thumb thumb-max" aria-hidden="true" style="left: 75%;">
20
+ <div data-v-24e1b71f="" data-v-cfbfc2ef="" class="tooltip-wrapper">
21
+ <div data-v-24e1b71f="" class="tooltip" style="transform: translateX(calc(-50% + 0px));">75</div>
22
+ </div>
23
+ </div>
24
+ <div data-v-cfbfc2ef="" class="filled-track" style="left: 25%; width: 50%;"></div>
25
+ </div>
26
+ </div>"
27
+ `;
@@ -0,0 +1,100 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+ import RangeSlider from '../RangeSlider.vue'
5
+
6
+ describe('RangeField component', () => {
7
+ it('should render the component', () => {
8
+ const wrapper = mount(RangeSlider, {
9
+ global: {
10
+ plugins: [vuetify],
11
+ },
12
+ props: {
13
+ min: 0,
14
+ max: 100,
15
+ modelValue: [25, 75],
16
+ },
17
+ })
18
+
19
+ expect(wrapper.html()).toMatchSnapshot()
20
+
21
+ const minThumb = wrapper.find('.thumb-min')
22
+ expect(minThumb.attributes('style')).toBe('left: 25%;')
23
+ expect(minThumb.attributes('aria-valuenow')).toBe('25')
24
+ expect(minThumb.text()).toBe('25')
25
+
26
+ const maxThumb = wrapper.find('.thumb-max')
27
+ expect(maxThumb.attributes('style')).toBe('left: 75%;')
28
+ expect(maxThumb.attributes('aria-valuenow')).toBe('75')
29
+ expect(maxThumb.text()).toBe('75')
30
+ })
31
+
32
+ it('should update the model value on thumb drag', async () => {
33
+ const wrapper = mount(RangeSlider, {
34
+ global: {
35
+ plugins: [vuetify],
36
+ },
37
+ props: {
38
+ min: 0,
39
+ max: 100,
40
+ modelValue: [25, 75],
41
+ },
42
+ })
43
+
44
+ const minThumb = wrapper.find('.thumb-min')
45
+ await minThumb.trigger('keydown', { key: 'ArrowRight' })
46
+
47
+ expect(wrapper.emitted('update:modelValue')).toHaveLength(1)
48
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([[26, 75]])
49
+ })
50
+
51
+ it('should update the range when the modelValue is updated', async () => {
52
+ const wrapper = mount(RangeSlider, {
53
+ global: {
54
+ plugins: [vuetify],
55
+ },
56
+ props: {
57
+ min: 0,
58
+ max: 100,
59
+ modelValue: [25, 75],
60
+ },
61
+ })
62
+
63
+ await wrapper.setProps({ modelValue: [30, 70] })
64
+
65
+ const minThumb = wrapper.find('.thumb-min')
66
+ expect(minThumb.attributes('style')).toBe('left: 30%;')
67
+ expect(minThumb.attributes('aria-valuenow')).toBe('30')
68
+ expect(minThumb.text()).toBe('30')
69
+
70
+ const maxThumb = wrapper.find('.thumb-max')
71
+ expect(maxThumb.attributes('style')).toBe('left: 70%;')
72
+ expect(maxThumb.attributes('aria-valuenow')).toBe('70')
73
+ expect(maxThumb.text()).toBe('70')
74
+ })
75
+
76
+ it('emit an event when the track is clicked', async () => {
77
+ const wrapper = mount(RangeSlider, {
78
+ global: {
79
+ plugins: [vuetify],
80
+ },
81
+ props: {
82
+ min: 0,
83
+ max: 100,
84
+ modelValue: [25, 75],
85
+ },
86
+ })
87
+
88
+ const track = wrapper.find('.track')
89
+
90
+ vi.spyOn(track.element, 'getBoundingClientRect').mockReturnValue({
91
+ left: 0,
92
+ width: 100,
93
+ } as DOMRect)
94
+
95
+ await wrapper.find('.track').trigger('click', { clientX: 33 })
96
+
97
+ expect(wrapper.emitted('update:modelValue')).toHaveLength(1)
98
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([[33, 75]])
99
+ })
100
+ })
@@ -0,0 +1,246 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { nextTick, ref } from 'vue'
3
+ import useDoubleSlider from '../useRangeSlider'
4
+
5
+ describe('useDoubleSlider', () => {
6
+ it('return a correct object', () => {
7
+ const min = ref(0)
8
+ const max = ref(100)
9
+ const step = ref(1)
10
+ const value = ref([25, 75])
11
+
12
+ const range = useDoubleSlider(
13
+ min, max, step, value,
14
+ )
15
+
16
+ expect(range.rangeMin.value).toBe(0)
17
+ expect(range.rangeMax.value).toBe(100)
18
+ expect(range.step.value).toBe(1)
19
+ expect(range.selectedMin.value).toBe(25)
20
+ expect(range.selectedMax.value).toBe(75)
21
+ })
22
+
23
+ it('update the values', async () => {
24
+ const min = ref(0)
25
+ const max = ref(100)
26
+ const step = ref(1)
27
+ const value = ref([25, 75])
28
+
29
+ const range = useDoubleSlider(
30
+ min, max, step, value,
31
+ )
32
+
33
+ expect(range.rangeMin.value).toBe(0)
34
+ expect(range.rangeMax.value).toBe(100)
35
+ expect(range.step.value).toBe(1)
36
+ expect(range.selectedMin.value).toBe(25)
37
+ expect(range.selectedMax.value).toBe(75)
38
+
39
+ min.value = -100
40
+ max.value = 200
41
+ step.value = 2
42
+ value.value = [-50, 150]
43
+
44
+ await nextTick()
45
+
46
+ expect(range.rangeMin.value).toBe(-100)
47
+ expect(range.rangeMax.value).toBe(200)
48
+ expect(range.step.value).toBe(2)
49
+ expect(range.selectedMin.value).toBe(-50)
50
+ expect(range.selectedMax.value).toBe(150)
51
+ })
52
+
53
+ it('do not accept out of bounds values', async () => {
54
+ const min = ref(0)
55
+ const max = ref(100)
56
+ const step = ref(1)
57
+ const value = ref([25, 75])
58
+
59
+ const range = useDoubleSlider(
60
+ min, max, step, value,
61
+ )
62
+
63
+ value.value = [-50, 100]
64
+
65
+ await nextTick()
66
+
67
+ expect(range.selectedMax.value).toBe(100)
68
+ expect(range.selectedMin.value).not.toBe(-50)
69
+ expect(range.selectedMin.value).toBe(0)
70
+ })
71
+
72
+ it('do not accept a min bound superior than a max bound', () => {
73
+ const min = ref(100)
74
+ const max = ref(-100)
75
+ const step = ref(1)
76
+ const value = ref([25, 75])
77
+
78
+ const range = useDoubleSlider(
79
+ min, max, step, value,
80
+ )
81
+
82
+ expect(range.rangeMin.value).toBe(-100)
83
+ expect(range.rangeMax.value).toBe(100)
84
+ })
85
+
86
+ it('do not accept an invalide value', async () => {
87
+ const min = ref(0)
88
+ const max = ref(100)
89
+ const step = ref(1)
90
+ const value = ref([25, 75])
91
+
92
+ const range = useDoubleSlider(
93
+ min, max, step, value,
94
+ )
95
+
96
+ value.value = [NaN, NaN]
97
+ await nextTick()
98
+ expect(range.selectedMin.value).toBe(25)
99
+ expect(range.selectedMax.value).toBe(75)
100
+
101
+ value.value = [-Infinity, +Infinity]
102
+ await nextTick()
103
+ expect(range.selectedMin.value).toBe(25)
104
+ expect(range.selectedMax.value).toBe(75)
105
+
106
+ value.value = [60, 40]
107
+ await nextTick()
108
+ expect(range.selectedMin.value).toBe(25)
109
+ expect(range.selectedMax.value).toBe(75)
110
+ })
111
+
112
+ it('set automatically the selected value in bounds', async () => {
113
+ const min = ref(0)
114
+ const max = ref(100)
115
+ const step = ref(1)
116
+ const value = ref([25, 75])
117
+
118
+ const range = useDoubleSlider(
119
+ min, max, step, value,
120
+ )
121
+
122
+ value.value = [-50, 150]
123
+
124
+ await nextTick()
125
+
126
+ expect(range.selectedMin.value).toBe(0)
127
+ expect(range.selectedMax.value).toBe(100)
128
+ })
129
+
130
+ it('do not accept an invalide min and max limit value', async () => {
131
+ const min = ref(0)
132
+ const max = ref(100)
133
+ const step = ref(1)
134
+ const value = ref([25, 75])
135
+
136
+ const range = useDoubleSlider(
137
+ min, max, step, value,
138
+ )
139
+
140
+ min.value = NaN
141
+ await nextTick()
142
+ expect(range.rangeMin.value).toBe(0)
143
+
144
+ min.value = -Infinity
145
+ await nextTick()
146
+ expect(range.rangeMin.value).toBe(0)
147
+
148
+ min.value = 150
149
+ await nextTick()
150
+ expect(range.rangeMin.value).toBe(0)
151
+
152
+ max.value = NaN
153
+ await nextTick()
154
+ expect(range.rangeMax.value).toBe(100)
155
+
156
+ max.value = -Infinity
157
+ await nextTick()
158
+ expect(range.rangeMax.value).toBe(100)
159
+
160
+ max.value = -1
161
+ await nextTick()
162
+ expect(range.rangeMax.value).toBe(100)
163
+ })
164
+
165
+ it('set automatically the selected value in bounds (min and max)', async () => {
166
+ const min = ref(0)
167
+ const max = ref(100)
168
+ const step = ref(1)
169
+ const value = ref([10, 90])
170
+
171
+ const range = useDoubleSlider(
172
+ min, max, step, value,
173
+ )
174
+
175
+ min.value = 20
176
+ max.value = 80
177
+
178
+ await nextTick()
179
+
180
+ expect(range.selectedMin.value).toBe(20)
181
+ expect(range.selectedMax.value).toBe(80)
182
+ })
183
+
184
+ it('set automatically the selected value in bounds (min)', async () => {
185
+ const min = ref(0)
186
+ const max = ref(100)
187
+ const step = ref(1)
188
+ const value = ref([10, 20])
189
+
190
+ const range = useDoubleSlider(
191
+ min, max, step, value,
192
+ )
193
+
194
+ min.value = 40
195
+
196
+ await nextTick()
197
+
198
+ expect(range.selectedMin.value).toBe(40)
199
+ expect(range.selectedMax.value).toBe(40)
200
+ })
201
+
202
+ it('set automatically the selected value in bounds (max)', async () => {
203
+ const min = ref(0)
204
+ const max = ref(100)
205
+ const step = ref(1)
206
+ const value = ref([80, 90])
207
+
208
+ const range = useDoubleSlider(
209
+ min, max, step, value,
210
+ )
211
+
212
+ max.value = 60
213
+
214
+ await nextTick()
215
+
216
+ expect(range.selectedMin.value).toBe(60)
217
+ expect(range.selectedMax.value).toBe(60)
218
+ })
219
+
220
+ it('do not take into account an invalide step', async () => {
221
+ const min = ref(100)
222
+ const max = ref(200)
223
+ const step = ref(1)
224
+ const value = ref([80, 90])
225
+
226
+ const range = useDoubleSlider(
227
+ min, max, step, value,
228
+ )
229
+
230
+ step.value = NaN
231
+ await nextTick()
232
+ expect(range.step.value).toBe(1)
233
+
234
+ step.value = +Infinity
235
+ await nextTick()
236
+ expect(range.step.value).toBe(1)
237
+
238
+ step.value = 0
239
+ await nextTick()
240
+ expect(range.step.value).toBe(1)
241
+
242
+ step.value = 150
243
+ await nextTick()
244
+ expect(range.step.value).toBe(1)
245
+ })
246
+ })
@@ -0,0 +1,204 @@
1
+ import { describe, expect, it, vi, afterEach } from 'vitest'
2
+ import useMouseSlide from '../useMouseSlide'
3
+
4
+ import { defineComponent, onMounted, ref, type Ref } from 'vue'
5
+ import { mount } from '@vue/test-utils'
6
+
7
+ describe('useMouseSlide', () => {
8
+ let callbackFn = vi.fn()
9
+ const TestComponent = defineComponent({
10
+ setup() {
11
+ const track = ref<HTMLElement | null>(null)
12
+ const thumb = ref<HTMLElement | null>(null)
13
+
14
+ onMounted(() => {
15
+ const mockRect = vi.spyOn((track.value as HTMLElement), 'getBoundingClientRect')
16
+ mockRect.mockReturnValue({
17
+ left: 0,
18
+ width: 200,
19
+ } as DOMRect)
20
+ })
21
+
22
+ const {
23
+ inProgress,
24
+ } = useMouseSlide(
25
+ thumb as Ref<HTMLElement>,
26
+ track as Ref<HTMLElement>,
27
+ ref(50),
28
+ 0,
29
+ 100,
30
+ 1,
31
+ 0,
32
+ 100,
33
+ callbackFn,
34
+ )
35
+ return { track, thumb, inProgress }
36
+ },
37
+ template: `
38
+ <div ref="track">
39
+ <div ref="thumb" class="thumb"></div>
40
+ </div>`,
41
+ })
42
+
43
+ afterEach(() => {
44
+ callbackFn = vi.fn()
45
+ })
46
+
47
+ it('calls the callback function when the mouse is down', async () => {
48
+ const wrapper = mount(TestComponent, {
49
+ attachTo: document.body,
50
+ })
51
+
52
+ const thumb = wrapper.find('div.thumb')
53
+
54
+ await thumb.trigger('mousedown')
55
+ await thumb.trigger('mousemove', {
56
+ clientX: 100,
57
+ })
58
+ await thumb.trigger('mousemove', {
59
+ clientX: 150,
60
+ })
61
+ await thumb.trigger('mouseup')
62
+
63
+ expect(callbackFn).toHaveBeenCalledWith(75) // 50 + 25
64
+
65
+ wrapper.unmount()
66
+ })
67
+
68
+ it('handle touch events', async () => {
69
+ const wrapper = mount(TestComponent, {
70
+ attachTo: document.body,
71
+ })
72
+
73
+ const thumb = wrapper.find('div.thumb')
74
+
75
+ await thumb.trigger('touchstart')
76
+ await thumb.trigger('touchmove', {
77
+ touches: [{ clientX: 100 }],
78
+ })
79
+ await thumb.trigger('touchmove', {
80
+ touches: [{ clientX: 150 }],
81
+ })
82
+ await thumb.trigger('touchend')
83
+
84
+ expect(callbackFn).toHaveBeenCalledWith(75) // 50 + 25
85
+
86
+ wrapper.unmount()
87
+ })
88
+
89
+ it('handle going backward', async () => {
90
+ const wrapper = mount(TestComponent, {
91
+ attachTo: document.body,
92
+ })
93
+
94
+ const thumb = wrapper.find('div.thumb')
95
+
96
+ await thumb.trigger('mousedown')
97
+ await thumb.trigger('mousemove', {
98
+ clientX: 100,
99
+ })
100
+ await thumb.trigger('mousemove', {
101
+ clientX: 50,
102
+ })
103
+ await thumb.trigger('mouseup')
104
+
105
+ expect(callbackFn).toHaveBeenCalledWith(25) // 50 - 25
106
+
107
+ wrapper.unmount()
108
+ })
109
+
110
+ it('do not call the callback function when the mouse have not moved', async () => {
111
+ const wrapper = mount(TestComponent, {
112
+ attachTo: document.body,
113
+ })
114
+
115
+ const thumb = wrapper.find('div.thumb')
116
+
117
+ await thumb.trigger('mousedown')
118
+ await thumb.trigger('mousemove', {
119
+ clientX: 100,
120
+ })
121
+ await thumb.trigger('mousemove', {
122
+ clientX: 100,
123
+ })
124
+ await thumb.trigger('mouseup')
125
+
126
+ expect(callbackFn).not.toHaveBeenCalled()
127
+
128
+ wrapper.unmount()
129
+ })
130
+
131
+ it('set the inProgress to false after 100ms', async () => {
132
+ vi.useFakeTimers()
133
+ const wrapper = mount(TestComponent, {
134
+ attachTo: document.body,
135
+ })
136
+
137
+ const thumb = wrapper.find('div.thumb')
138
+
139
+ await thumb.trigger('mousedown')
140
+ await thumb.trigger('mousemove', {
141
+ clientX: 100,
142
+ })
143
+ await thumb.trigger('mousemove', {
144
+ clientX: 150,
145
+ })
146
+ await thumb.trigger('mouseup')
147
+
148
+ expect(wrapper.vm.inProgress).toBe(true)
149
+
150
+ await thumb.trigger('mousemove', {
151
+ clientX: 100,
152
+ })
153
+
154
+ expect(wrapper.vm.inProgress).toBe(true)
155
+
156
+ vi.advanceTimersByTime(100)
157
+
158
+ expect(wrapper.vm.inProgress).toBe(false)
159
+
160
+ wrapper.unmount()
161
+ })
162
+
163
+ it('do not overstep the minSelectableValue', async () => {
164
+ const wrapper = mount(TestComponent, {
165
+ attachTo: document.body,
166
+ })
167
+
168
+ const thumb = wrapper.find('div.thumb')
169
+
170
+ await thumb.trigger('mousedown')
171
+ await thumb.trigger('mousemove', {
172
+ clientX: 0,
173
+ })
174
+ await thumb.trigger('mousemove', {
175
+ clientX: -300,
176
+ })
177
+ await thumb.trigger('mouseup')
178
+
179
+ expect(callbackFn).toHaveBeenCalledWith(0)
180
+
181
+ wrapper.unmount()
182
+ })
183
+
184
+ it('do not overstep the maxSelectableValue', async () => {
185
+ const wrapper = mount(TestComponent, {
186
+ attachTo: document.body,
187
+ })
188
+
189
+ const thumb = wrapper.find('div.thumb')
190
+
191
+ await thumb.trigger('mousedown')
192
+ await thumb.trigger('mousemove', {
193
+ clientX: 200,
194
+ })
195
+ await thumb.trigger('mousemove', {
196
+ clientX: 500,
197
+ })
198
+ await thumb.trigger('mouseup')
199
+
200
+ expect(callbackFn).toHaveBeenCalledWith(100)
201
+
202
+ wrapper.unmount()
203
+ })
204
+ })
@@ -0,0 +1,22 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import useThumb from '../useThumb'
3
+
4
+ describe('useThumb', () => {
5
+ it('should return the correct thumb style', () => {
6
+ const { thumbStyle } = useThumb(10, -60, 40)
7
+
8
+ expect(thumbStyle.value.left).toBe('70%')
9
+ })
10
+
11
+ it('should return the correct thumb style with a negative value', () => {
12
+ const { thumbStyle } = useThumb(-60, -100, 0)
13
+
14
+ expect(thumbStyle.value.left).toBe('40%')
15
+ })
16
+
17
+ it('should return the correct thumb style with a range of 0', () => {
18
+ const { thumbStyle } = useThumb(0, 0, 0)
19
+
20
+ expect(thumbStyle.value.left).toBe('100%')
21
+ })
22
+ })