@cnamts/synapse 0.0.2-alpha → 0.0.4-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 (193) hide show
  1. package/README.md +1 -1
  2. package/dist/design-system-v3.d.ts +712 -27
  3. package/dist/design-system-v3.js +2745 -5384
  4. package/dist/design-system-v3.umd.cjs +10 -2
  5. package/dist/style.css +1 -1
  6. package/package.json +32 -29
  7. package/src/components/Alert/Alert.mdx +1 -1
  8. package/src/components/Alert/Alert.stories.ts +91 -1
  9. package/src/components/Alert/Alert.vue +8 -8
  10. package/src/components/BackBtn/BackBtn.mdx +1 -1
  11. package/src/components/BackBtn/BackBtn.stories.ts +84 -1
  12. package/src/components/BackToTopBtn/BackToTopBtn.mdx +3 -3
  13. package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +172 -11
  14. package/src/components/CollapsibleList/CollapsibleList.mdx +2 -2
  15. package/src/components/CollapsibleList/CollapsibleList.stories.ts +37 -1
  16. package/src/components/CopyBtn/CopyBtn.mdx +1 -1
  17. package/src/components/CopyBtn/CopyBtn.stories.ts +120 -1
  18. package/src/components/CopyBtn/CopyBtn.vue +1 -1
  19. package/src/components/Customs/CustomInputSelect/CustomInputSelect.mdx +6 -8
  20. package/src/components/Customs/CustomInputSelect/CustomInputSelect.stories.ts +270 -4
  21. package/src/components/Customs/CustomInputSelect/CustomInputSelect.vue +80 -53
  22. package/src/components/Customs/CustomInputSelect/config.ts +10 -0
  23. package/src/components/Customs/CustomSelect/CustomSelect.mdx +3 -3
  24. package/src/components/Customs/CustomSelect/CustomSelect.stories.ts +158 -2
  25. package/src/components/Customs/CustomSelect/CustomSelect.vue +25 -6
  26. package/src/components/Customs/CustomTextField/CustomTextField.mdx +44 -0
  27. package/src/components/Customs/CustomTextField/CustomTextField.stories.ts +403 -0
  28. package/src/components/Customs/CustomTextField/CustomTextField.vue +110 -0
  29. package/src/components/Customs/CustomTextField/tests/CustomTextField.spec.ts +93 -0
  30. package/src/components/Customs/CustomTextField/tests/__snapshots__/CustomTextField.spec.ts.snap +59 -0
  31. package/src/components/Customs/CustomTextField/types.d.ts +3 -0
  32. package/src/components/DataList/DataList.mdx +77 -0
  33. package/src/components/DataList/DataList.stories.ts +960 -0
  34. package/src/components/DataList/DataList.vue +140 -0
  35. package/src/components/DataList/DataListLoading/DataListLoading.vue +56 -0
  36. package/src/components/DataList/DataListLoading/tests/DataListLoading.spec.ts +23 -0
  37. package/src/components/DataList/locales.ts +3 -0
  38. package/src/components/DataList/tests/DataList.spec.ts +194 -0
  39. package/src/components/DataList/types.d.ts +23 -0
  40. package/src/components/DataListGroup/DataListGroup.mdx +77 -0
  41. package/src/components/DataListGroup/DataListGroup.stories.ts +987 -0
  42. package/src/components/DataListGroup/DataListGroup.vue +59 -0
  43. package/src/components/DataListGroup/tests/DataListGroup.spec.ts +54 -0
  44. package/src/components/DataListGroup/tests/data/dataListGroupItems.ts +41 -0
  45. package/src/components/DataListGroup/types.d.ts +15 -0
  46. package/src/components/DataListItem/DataListItem.vue +135 -0
  47. package/src/components/DataListItem/config.ts +17 -0
  48. package/src/components/DataListItem/locales.ts +3 -0
  49. package/src/components/DataListItem/tests/DataListItem.spec.ts +156 -0
  50. package/src/components/DataListItem/types.d.ts +23 -0
  51. package/src/components/DownloadBtn/Accessibilite.mdx +14 -0
  52. package/src/components/DownloadBtn/Accessibilite.stories.ts +166 -0
  53. package/src/components/DownloadBtn/AccessibiliteItems.ts +129 -0
  54. package/src/components/DownloadBtn/DownloadBtn.mdx +5 -6
  55. package/src/components/DownloadBtn/DownloadBtn.stories.ts +207 -2
  56. package/src/components/DownloadBtn/constants/ExpertiseLevelEnum.ts +4 -0
  57. package/src/components/FooterBar/FooterBar.mdx +2 -2
  58. package/src/components/FooterBar/FooterBar.stories.ts +1 -1
  59. package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +1 -1
  60. package/src/components/FranceConnectBtn/FranceConnectBtn.stories.ts +58 -1
  61. package/src/components/FranceConnectBtn/FranceConnectBtn.vue +2 -2
  62. package/src/components/HeaderBar/HeaderBar.mdx +256 -0
  63. package/src/components/HeaderBar/HeaderBar.stories.ts +703 -0
  64. package/src/components/HeaderBar/HeaderBar.vue +276 -0
  65. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.mdx +433 -0
  66. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.stories.ts +1089 -0
  67. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +234 -0
  68. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.mdx +38 -0
  69. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.stories.ts +89 -0
  70. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +51 -0
  71. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/tests/HeaderMenuItem.spec.ts +16 -0
  72. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/tests/__snapshots__/HeaderMenuItem.spec.ts.snap +3 -0
  73. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.mdx +17 -0
  74. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.stories.ts +121 -0
  75. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.vue +51 -0
  76. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/tests/HeaderMenuSection.spec.ts +31 -0
  77. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.mdx +43 -0
  78. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.stories.ts +261 -0
  79. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +194 -0
  80. package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/tests/HeaderSubMenu.spec.ts +63 -0
  81. package/src/components/HeaderBar/HeaderBurgerMenu/conts.ts +1 -0
  82. package/src/components/HeaderBar/HeaderBurgerMenu/locals.ts +4 -0
  83. package/src/components/HeaderBar/HeaderBurgerMenu/tests/HeaderBurgerMenu.spec.ts +180 -0
  84. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/HeaderBurgerMenu.spec.ts.snap +13 -0
  85. package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/HeaderComplexMenu.spec.ts.snap +13 -0
  86. package/src/components/HeaderBar/HeaderBurgerMenu/tests/useHandleSubMenus.spec.ts +158 -0
  87. package/src/components/HeaderBar/HeaderBurgerMenu/useHandleSubMenus.ts +49 -0
  88. package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +143 -0
  89. package/src/components/HeaderBar/HeaderLogo/locales.ts +3 -0
  90. package/src/components/HeaderBar/HeaderLogo/logos/Logo-mobile.vue +117 -0
  91. package/src/components/HeaderBar/HeaderLogo/logos/Logo.vue +279 -0
  92. package/src/components/HeaderBar/HeaderLogo/tests/HeaderLogo.spec.ts +119 -0
  93. package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +84 -0
  94. package/src/components/HeaderBar/HeaderMenuBtn/locals.ts +4 -0
  95. package/src/components/HeaderBar/HeaderMenuBtn/tests/HeaderMenuBtn.spec.ts +70 -0
  96. package/src/components/HeaderBar/Usages.mdx +85 -0
  97. package/src/components/HeaderBar/consts.scss +6 -0
  98. package/src/components/HeaderBar/consts.ts +2 -0
  99. package/src/components/HeaderBar/locales.ts +3 -0
  100. package/src/components/HeaderBar/tests/HeaderBar.spec.ts +216 -0
  101. package/src/components/HeaderBar/tests/__snapshots__/HeaderBar.spec.ts.snap +45 -0
  102. package/src/components/HeaderBar/tests/useHeaderResponsiveMode.spec.ts +26 -0
  103. package/src/components/HeaderBar/tests/useScrollDirection.spec.ts +34 -0
  104. package/src/components/HeaderBar/useHeaderResponsiveMode.ts +25 -0
  105. package/src/components/HeaderBar/useScrollDirection.ts +26 -0
  106. package/src/components/HeaderLoading/HeaderLoading.mdx +28 -0
  107. package/src/components/HeaderLoading/HeaderLoading.stories.ts +62 -0
  108. package/src/components/HeaderLoading/HeaderLoading.vue +45 -0
  109. package/src/components/HeaderLoading/tests/HeaderLoading.spec.ts +22 -0
  110. package/src/components/HeaderNavigationBar/HeaderNavigationBar.mdx +128 -0
  111. package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +784 -0
  112. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +194 -0
  113. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +74 -0
  114. package/src/components/HeaderNavigationBar/HorizontalNavbar/config.ts +18 -0
  115. package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.spec.ts +127 -0
  116. package/src/components/HeaderNavigationBar/types.ts +7 -0
  117. package/src/components/HeaderToolbar/HeaderToolbar.mdx +31 -0
  118. package/src/components/HeaderToolbar/HeaderToolbar.stories.ts +343 -0
  119. package/src/components/HeaderToolbar/HeaderToolbar.vue +487 -0
  120. package/src/components/HeaderToolbar/tests/HeaderToolbar.spec.ts +196 -0
  121. package/src/components/HeaderToolbar/types.d.ts +20 -0
  122. package/src/components/LangBtn/LangBtn.mdx +1 -1
  123. package/src/components/LangBtn/LangBtn.stories.ts +125 -8
  124. package/src/components/Logo/Logo.mdx +2 -2
  125. package/src/components/Logo/Logo.stories.ts +147 -1
  126. package/src/components/LogoBrandSection/LogoBrandSection.mdx +14 -0
  127. package/src/components/LogoBrandSection/LogoBrandSection.stories.ts +158 -0
  128. package/src/components/LogoBrandSection/LogoBrandSection.vue +312 -0
  129. package/src/components/LogoBrandSection/assets/ameli-pro.svg +1 -0
  130. package/src/components/LogoBrandSection/assets/ameli.svg +1 -0
  131. package/src/components/LogoBrandSection/assets/cnam.svg +1 -0
  132. package/src/components/LogoBrandSection/assets/compte-ameli.svg +1 -0
  133. package/src/components/LogoBrandSection/dividerDimensionsMapping.ts +14 -0
  134. package/src/components/LogoBrandSection/locales.ts +14 -0
  135. package/src/components/LogoBrandSection/secondaryLogoMapping.ts +24 -0
  136. package/src/components/LogoBrandSection/tests/LogoBrandSection.spec.ts +365 -0
  137. package/src/components/LogoBrandSection/tests/__snapshots__/LogoBrandSection.spec.ts.snap +14 -0
  138. package/src/components/LogoBrandSection/types.ts +8 -0
  139. package/src/components/NotificationBar/NotificationBar.mdx +6 -6
  140. package/src/components/NotificationBar/NotificationBar.stories.ts +1 -1
  141. package/src/components/NotificationBar/NotificationBar.vue +7 -9
  142. package/src/components/NotificationBar/tests/NotificationBar.spec.ts +1 -1
  143. package/src/components/PageContainer/PageContainer.mdx +1 -1
  144. package/src/components/PageContainer/PageContainer.stories.ts +86 -1
  145. package/src/components/PageContainer/PageContainer.vue +0 -1
  146. package/src/components/PhoneField/PhoneField.mdx +49 -0
  147. package/src/components/PhoneField/PhoneField.stories.ts +869 -0
  148. package/src/components/PhoneField/PhoneField.vue +230 -0
  149. package/src/components/PhoneField/indicatifs.ts +104 -0
  150. package/src/components/PhoneField/locales.ts +4 -0
  151. package/src/components/PhoneField/tests/PhoneField.spec.ts +179 -0
  152. package/src/components/SkipLink/SkipLink.stories.ts +50 -1
  153. package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +28 -1
  154. package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +37 -1
  155. package/src/components/SubHeader/SubHeader.mdx +31 -0
  156. package/src/components/SubHeader/SubHeader.stories.ts +1032 -0
  157. package/src/components/SubHeader/SubHeader.vue +185 -0
  158. package/src/components/SubHeader/config.ts +12 -0
  159. package/src/components/SubHeader/locales.ts +3 -0
  160. package/src/components/SubHeader/tests/SubHeader.spec.ts +144 -0
  161. package/src/components/index.ts +24 -7
  162. package/src/composables/widthable/index.ts +29 -0
  163. package/src/composables/widthable/tests/widthable.spec.ts +52 -0
  164. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +2 -2
  165. package/src/main.ts +1 -0
  166. package/src/modules.d.ts +4 -0
  167. package/src/services/index.ts +1 -0
  168. package/src/stories/Demarrer/Accueil.mdx +10 -0
  169. package/src/stories/Demarrer/Accueil.stories.ts +76 -0
  170. package/src/stories/Demarrer/PolitiqueDeConfidentialite.mdx +9 -0
  171. package/src/stories/Demarrer/PolitiqueDeConfidentialite.stories.ts +20 -0
  172. package/src/stories/Fondamentaux/Accessibilite/Accessibilite.mdx +1 -2
  173. package/src/stories/Fondamentaux/Accessibilite/Accessibilite.stories.ts +1 -1
  174. package/src/stories/Fondamentaux/EcoConception/Econception.stories.ts +1 -1
  175. package/src/stories/GuideDuDev/moduleDeNotification.mdx +52 -48
  176. package/src/stories/GuideDuDev/vuetifyOptions.mdx +31 -28
  177. package/src/stories/Guidelines/CustomisationEtThemes.mdx +1 -1
  178. package/src/utils/functions/throttleDisplayFn/tests/throttleDisplayFn.spec.ts +47 -0
  179. package/src/utils/functions/throttleDisplayFn/throttleDisplayFn.ts +26 -0
  180. package/src/utils/rules/exactLength/index.ts +33 -0
  181. package/src/utils/rules/exactLength/locales.ts +6 -0
  182. package/src/utils/rules/required/index.ts +25 -0
  183. package/src/utils/rules/required/locales.ts +5 -0
  184. package/src/utils/rules/required/ruleMessageHelper.ts +14 -0
  185. package/src/utils/rules/required/tests/index.spec.ts +47 -0
  186. package/src/utils/rules/required/tests/rulesMessageHelper.spec.ts +22 -0
  187. package/src/utils/rules/types.d.ts +15 -0
  188. package/src/components/Beta/beta.mdx +0 -5
  189. package/src/components/Deprecated/deprecated.mdx +0 -5
  190. package/src/stories/Home/Accueil.mdx +0 -7
  191. package/src/stories/Home/PolitiqueDeConfidentialite.mdx +0 -4
  192. package/src/stories/Home/synapse.webp +0 -0
  193. /package/src/components/Logo/{types.d.ts → types.ts} +0 -0
@@ -0,0 +1,216 @@
1
+ import { vuetify } from '@tests/unit/setup'
2
+ import { mount } from '@vue/test-utils'
3
+ import { afterAll, describe, expect, it, vi } from 'vitest'
4
+ import { defineComponent, inject, onMounted, ref, type Ref } from 'vue'
5
+ import HeaderBar from '../HeaderBar.vue'
6
+ import { registerHeaderMenuKey } from '../consts'
7
+
8
+ describe('HeaderBar', () => {
9
+ vi.mock('@/utils/functions/throttleDisplayFn/throttleDisplayFn.ts', () => ({
10
+ default: (fn: (...args: unknown[]) => void) => fn,
11
+ }))
12
+
13
+ afterAll(() => {
14
+ vi.restoreAllMocks()
15
+ document.body.innerHTML = ''
16
+ })
17
+
18
+ it('should render the component', async () => {
19
+ const wrapper = mount(HeaderBar, {
20
+ props: {
21
+ sticky: false,
22
+ },
23
+ global: {
24
+ plugins: [vuetify],
25
+ },
26
+ attachTo: document.body,
27
+ })
28
+ window.dispatchEvent(new CustomEvent('scroll'))
29
+
30
+ expect(wrapper.html()).toMatchSnapshot()
31
+
32
+ // mock scroll related values
33
+ vi.spyOn(window, 'scrollY', 'get').mockReturnValue(2000)
34
+ const header = wrapper.find('.header')
35
+ vi.spyOn(header.element, 'getBoundingClientRect').mockReturnValue({
36
+ top: -2000,
37
+ } as DOMRect)
38
+ window.dispatchEvent(new CustomEvent('scroll'))
39
+
40
+ await wrapper.vm.$nextTick()
41
+
42
+ const stickyHeader = wrapper.find('.sticky-header')
43
+ const stickyHeaderStyle = stickyHeader.attributes('style')
44
+ expect(stickyHeaderStyle).toContain('position: relative;')
45
+ expect(stickyHeaderStyle).toContain('top: auto;')
46
+
47
+ wrapper.unmount()
48
+ })
49
+
50
+ it('should render all the component slots', async () => {
51
+ const wrapper = mount(HeaderBar, {
52
+ global: {
53
+ plugins: [vuetify],
54
+ },
55
+ attachTo: document.body,
56
+ slots: {
57
+ 'default': '<div>Default slot</div>',
58
+ 'prepend': '<div>Prepend slot</div>',
59
+ 'append': '<div>Append slot</div>',
60
+ 'menu': '<div>Menu slot</div>',
61
+ 'logo': '<div>Logo slot</div>',
62
+ 'header-side': '<div>Header side slot</div>',
63
+ 'logo-brand-content': '<div>Logo brand content slot</div>',
64
+ },
65
+ })
66
+
67
+ const text = wrapper.text()
68
+
69
+ expect(text).not.toContain('Default slot')
70
+ expect(text).toContain('Prepend slot')
71
+ expect(text).toContain('Append slot')
72
+ expect(text).toContain('Menu slot')
73
+ expect(text).toContain('Logo slot')
74
+ expect(text).toContain('Header side slot')
75
+ expect(text).not.toContain('Logo brand content slot')
76
+
77
+ wrapper.unmount()
78
+ })
79
+
80
+ const TestMenu = defineComponent({
81
+ setup() {
82
+ const menu = ref(false)
83
+ const registerHeaderMenu = inject<(r: Ref<boolean>) => void>(registerHeaderMenuKey)
84
+
85
+ onMounted(() => {
86
+ if (registerHeaderMenu) {
87
+ registerHeaderMenu(menu)
88
+ }
89
+ })
90
+
91
+ return {
92
+ menu,
93
+ }
94
+ },
95
+ template: '<button @click="menu = true">Menu</button>',
96
+ })
97
+
98
+ it('should render the menu slot', async () => {
99
+ const wrapper = mount({
100
+ components: {
101
+ HeaderBar,
102
+ TestMenu,
103
+ },
104
+ template: `
105
+ <HeaderBar>
106
+ <template #menu>
107
+ <TestMenu />
108
+ </template>
109
+ <template #logo="{menuOpen}">
110
+ <div>{{menuOpen ? 'the menu is open' : 'the menu is closed'}}</div>
111
+ </template>
112
+ </HeaderBar>`,
113
+ }, {
114
+ global: {
115
+ plugins: [vuetify],
116
+ },
117
+ attachTo: document.body,
118
+ })
119
+ const text = wrapper.text()
120
+ expect(text).toContain('Menu')
121
+ expect(text).toContain('the menu is closed')
122
+
123
+ const button = wrapper.find('button')
124
+ await button.trigger('click')
125
+
126
+ expect(wrapper.text()).toContain('the menu is open')
127
+
128
+ wrapper.unmount()
129
+ })
130
+
131
+ it('should render in sticky mode', async () => {
132
+ const wrapper = mount(HeaderBar, {
133
+ props: {
134
+ sticky: true,
135
+ },
136
+ global: {
137
+ plugins: [vuetify],
138
+ },
139
+ attachTo: document.body,
140
+ })
141
+ window.dispatchEvent(new CustomEvent('scroll'))
142
+
143
+ // mock scroll related values
144
+ vi.spyOn(window, 'scrollY', 'get').mockReturnValue(2000)
145
+ const header = wrapper.find('.header')
146
+ vi.spyOn(header.element, 'getBoundingClientRect').mockReturnValue({
147
+ top: -2000,
148
+ } as DOMRect)
149
+ window.dispatchEvent(new CustomEvent('scroll'))
150
+
151
+ await wrapper.vm.$nextTick()
152
+
153
+ const stickyHeader = wrapper.find('.sticky-header')
154
+ const stickyHeaderStyle = stickyHeader.attributes('style')
155
+ expect(stickyHeaderStyle).toContain('position: fixed;')
156
+ expect(stickyHeaderStyle).toContain('top: 0px;')
157
+
158
+ wrapper.unmount()
159
+ })
160
+
161
+ it('should only show the header when the user scrolls up', async () => {
162
+ // @ts-expect-error - Property 'happyDOM' does not exist on type 'Window & typeof globalThis'.
163
+ window.happyDOM.setInnerWidth(600)
164
+ const wrapper = mount(HeaderBar, {
165
+ props: {
166
+ hideWhenDown: true,
167
+ },
168
+ global: {
169
+ plugins: [vuetify],
170
+ },
171
+ attachTo: document.body,
172
+ })
173
+ window.dispatchEvent(new CustomEvent('scroll'))
174
+
175
+ const header = wrapper.find('.header')
176
+ const mockHeaderRect = vi.spyOn(header.element, 'getBoundingClientRect')
177
+
178
+ // mock scroll related values
179
+ const mockScrollY = vi.spyOn(window, 'scrollY', 'get')
180
+ const mockScrollTop = vi.spyOn(document.documentElement, 'scrollTop', 'get')
181
+ mockScrollY.mockReturnValue(2000)
182
+ mockScrollTop.mockReturnValue(2000)
183
+ mockHeaderRect.mockReturnValue({
184
+ top: -2000,
185
+ height: 77,
186
+ } as DOMRect)
187
+ window.dispatchEvent(new CustomEvent('scroll'))
188
+ await wrapper.vm.$nextTick()
189
+
190
+ const stickyHeader = wrapper.find('.sticky-header')
191
+ let stickyHeaderStyle = stickyHeader.attributes('style')
192
+
193
+ // Do not show the header when the user scrolls down
194
+ expect(stickyHeaderStyle).toContain('position: fixed;')
195
+ expect(stickyHeaderStyle).toContain('top: 0px;')
196
+ expect(stickyHeaderStyle).toContain('transform: translateY(-100%);')
197
+
198
+ mockScrollY.mockReturnValue(800)
199
+ mockScrollTop.mockReturnValue(800)
200
+ mockHeaderRect.mockReturnValue({
201
+ top: -800,
202
+ height: 77,
203
+ } as DOMRect)
204
+ window.dispatchEvent(new CustomEvent('scroll'))
205
+ await wrapper.vm.$nextTick()
206
+
207
+ stickyHeaderStyle = stickyHeader.attributes('style')
208
+
209
+ // Do show the header when the user scrolls up
210
+ expect(stickyHeaderStyle).toContain('position: fixed;')
211
+ expect(stickyHeaderStyle).toContain('top: 0px;')
212
+ expect(stickyHeaderStyle).toContain('transform: none;')
213
+
214
+ wrapper.unmount()
215
+ })
216
+ })
@@ -0,0 +1,45 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`HeaderBar > should render the component 1`] = `
4
+ "<header data-v-efdbe191="" class="header" style="min-height: auto;">
5
+ <div data-v-efdbe191="" class="sticky-header" style="position: relative; width: 100%; top: auto; transform: none; transition: none;">
6
+ <!--v-if-->
7
+ <div data-v-efdbe191="" class="inner-header">
8
+ <div data-v-efdbe191="" class="header-logo"><a data-v-a3ce97de="" data-v-efdbe191="" href="/" class="logo"><svg data-v-d1ac2910="" data-v-a3ce97de="" fill="#0c419a" width="141" height="42" viewBox="0 0 211 64" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-label="Logo de l'Assurance Maladie, cliquez pour revenir à l'accueil">
9
+ <g data-v-d1ac2910="">
10
+ <path d="M100.1 45V30.6h3.8v14.6c0 .8.4 1 .7 1h.5l.5 2.9a5 5 0 0 1-2 .3c-2.6 0-3.5-1.7-3.5-4.4Z" data-v-d1ac2910=""></path>
11
+ <path d="m75.7 40.4 3.8-8.5h4V49h-3.6V38.4l-3 7.8h-2.4l-3-7.8v10.7H68V32h4l3.8 8.5Z" data-v-d1ac2910=""></path>
12
+ <path d="M107.1 45.5c0-2.8 2.3-4.3 7.4-4.9 0-1.1-.8-1.8-2.2-1.8-1 0-2.1.4-3.4 1.2l-1.3-2.6c1.6-1 3.5-1.7 5.5-1.7 3.3 0 5 1.9 5 5.9V49h-3.5v-1.3s-1.5 1.6-3.6 1.6c-2.4 0-3.9-1.7-3.9-4Zm7.4-.3V43c-2.7.3-3.7 1.2-3.7 2.2 0 .8.5 1.2 1.5 1.2.8 0 1.5-.5 2.2-1.2Z" data-v-d1ac2910=""></path>
13
+ <path d="M86.1 45.5c0-2.8 2.3-4.3 7.4-4.9 0-1.1-.8-1.8-2.2-1.8-1 0-2.1.4-3.4 1.2l-1.3-2.6c1.6-1 3.5-1.7 5.5-1.7 3.3 0 5 1.9 5 5.9V49h-3.5v-1.3S92 49.4 90 49.4c-2.4 0-3.9-1.7-3.9-4Zm7.4-.3V43c-2.7.3-3.7 1.2-3.7 2.2 0 .8.6 1.2 1.5 1.2.8 0 1.6-.5 2.2-1.2Z" data-v-d1ac2910=""></path>
14
+ <path d="M129 30.6v6.3a4.1 4.1 0 0 0-3.2-1.2c-2.7 0-5.3 2.6-5.3 6.8 0 4.3 2 7 5.2 7 1.8 0 3.1-1.4 3.2-1.5v1.1h3.8V30.6H129Zm-2.3 15.7c-1.5 0-2.4-1.2-2.4-3.8 0-2.5 1.1-3.6 2.4-3.6.6 0 1.4.2 2.2.8v5.4c-.7.8-1.4 1.2-2.2 1.2Z" data-v-d1ac2910=""></path>
15
+ <path d="M135.7 32c0-1.2 1-2 2.2-2 1.2 0 2.2.8 2.2 2s-1 2-2.2 2c-1.3 0-2.2-.8-2.2-2Zm.3 4h3.8V49H136V36Z" data-v-d1ac2910=""></path>
16
+ <path d="M142.2 42.5c0-4.2 2.6-6.8 5.9-6.8 3.6 0 5.6 2.7 5.6 6.3l-.1 1.7h-7.7c.3 2 1.6 2.8 3.3 2.8 1 0 1.8-.4 2.8-1l1.3 2.5c-1.3.9-3 1.4-4.6 1.4-3.8 0-6.5-2.5-6.5-6.9Zm8.3-1.4c0-1.4-.9-2.5-2.4-2.5-1.2 0-2 .9-2.3 2.5h4.7Z" data-v-d1ac2910=""></path>
17
+ <path d="M68 23.3V8.8h3.7v14.7c0 .8.4 1 .7 1h.5l.4 2.9a5 5 0 0 1-1.9.3c-2.6 0-3.5-1.7-3.5-4.4Z" data-v-d1ac2910=""></path>
18
+ <path d="m88.1 23.3 1 4.1h4l-5.3-17.3h-4.4l-5.3 17.3h4l1-4.1h5Zm-4.2-3 1.6-6.6h.2l1.6 6.5H84Z" data-v-d1ac2910=""></path>
19
+ <path d="m93.9 25.9 1.7-2.4c1.1.9 2.2 1.3 3.3 1.3 1.1 0 1.6-.4 1.6-1 0-1-1.2-1.4-2.6-1.9-1.6-.6-3.4-1.7-3.4-3.8 0-2.5 2-4.2 5-4.2 1.9 0 3.4.8 4.5 1.7l-1.7 2.4c-1-.7-1.8-1.2-2.8-1.2-1 0-1.4.4-1.4 1 0 1 1.2 1.2 2.5 1.7 1.6.7 3.5 1.6 3.5 4s-1.9 4.2-5.3 4.2c-1.7 0-3.6-.7-5-1.8Z" data-v-d1ac2910=""></path>
20
+ <path d="m105.3 25.9 1.7-2.4c1.1.9 2.2 1.3 3.3 1.3 1.1 0 1.6-.4 1.6-1 0-1-1.2-1.4-2.6-1.9-1.6-.6-3.4-1.7-3.4-3.8 0-2.5 2-4.2 5-4.2 1.9 0 3.4.8 4.5 1.7l-1.7 2.4c-1-.7-1.8-1.2-2.8-1.2-1 0-1.4.4-1.4 1 0 1 1.2 1.2 2.5 1.7 1.6.7 3.5 1.6 3.5 4s-1.9 4.2-5.3 4.2c-1.7 0-3.6-.7-5-1.8Z" data-v-d1ac2910=""></path>
21
+ <path d="M132.2 14.3h3.8V16c.8-1.4 2.5-2 3.4-2 .8 0 1.2.2 1.6.3l-.4 3.6c-.5-.2-1.1-.4-1.7-.4-1.5 0-2.8 1.3-2.9 3v6.8h-3.8V14.3Z" data-v-d1ac2910=""></path>
22
+ <path d="M155.7 14.3h3.8v1.6c1-1 2.2-2 4-2 2.7 0 4 2 4 5.3v8.2h-3.9v-7.7c0-1.9-.5-2.5-1.6-2.5-1 0-1.6.5-2.5 1.3v8.8h-3.8v-13Z" data-v-d1ac2910=""></path>
23
+ <path d="M180.6 20.8c0-4.3 2.7-6.9 5.9-6.9 3.7 0 5.7 2.8 5.7 6.3 0 .7 0 1.4-.2 1.8h-7.7c.4 1.9 1.7 2.8 3.4 2.8 1 0 1.8-.4 2.7-1l1.3 2.4c-1.3 1-3 1.5-4.6 1.5-3.7 0-6.5-2.5-6.5-6.9Zm8.4-1.4c0-1.4-.9-2.5-2.4-2.5-1.2 0-2 .8-2.3 2.5h4.7Z" data-v-d1ac2910=""></path>
24
+ <path d="M141.8 23.7c0-2.7 2.3-4.3 7.4-4.8 0-1.2-.8-1.9-2.2-1.9a7 7 0 0 0-3.4 1.2l-1.3-2.5c1.6-1 3.4-1.8 5.5-1.8 3.3 0 5 2 5 6v7.5h-3.6V26s-1.4 1.6-3.5 1.6c-2.4 0-4-1.7-4-4Zm7.4-.2v-2.3c-2.7.4-3.8 1.3-3.8 2.3 0 .8.6 1.2 1.5 1.2s1.7-.5 2.3-1.2Z" data-v-d1ac2910=""></path>
25
+ <path d="M76.7 8.8c-.8 0-1.9.6-1.9 1.7 0 1 .8 1.5 1.6 1.5 0 1.2-1 1.8-1.5 2.1l1 1.4c3.3-1 4-6.7.8-6.7Z" data-v-d1ac2910=""></path>
26
+ <path d="M125.3 14.3V23c-.8 1-1.4 1.4-2.3 1.4-1 0-1.6-.6-1.6-2.5v-7.6h-3.8v8.3c0 3 1.4 5.1 4 5.1 2.5 0 3.8-1.6 3.8-1.6v1.3h3.7V14.3h-3.8Z" data-v-d1ac2910=""></path>
27
+ <path d="M176.3 24.6c-1.7 0-3-1.5-3-3.7 0-2.3 1.3-3.8 3-3.8.6 0 1.1.2 1.7.7l1.8-2.5c-.9-.8-2.1-1.3-3.7-1.3a6.5 6.5 0 0 0-6.6 6.9c0 4.3 2.7 6.8 6.3 6.8 1.4 0 3-.4 4.2-1.5l-1.4-2.7c-.7.6-1.5 1-2.3 1Z" data-v-d1ac2910=""></path>
28
+ </g>
29
+ <path d="M34.8 9c-.1-.2-.4-.3-.6-.3H34c-.2-.2-5.3 0-6.5.7 0-.8-.4-1.8-1.7-2-1-.3-3.1.7-2.4 2.8 0 .3.3.6.7.8.2 0 .5 0 .7.6h.3l.2.2h.5c.4.4.8-.1 1-.5l.7 2c-.2-.2-1.8-.6-2.5.2s-1.2 1.8-1.7 3.5c-.2.4-.5.7-1 .9-.9.3-.4.7-.2.7a6 6 0 0 0 2 0c.4-.2.1-1 .5-1.4l.8-1c0 .5 0 .8-.3 1.5-.2.7-1 1-1.3 1.3-.4.5.6.5.8.5.7-.2 1-.2 1.3-.4.4-.2.2-.8.3-1 .3-.7 1.4-2 1.6-2.3.8.2 1.7.2 2 .2 1.9-.2 2.3-1.5 2-2.6-.1-1-.7-1.5-.9-1.8l-.9-1.4 3.5-.9c0 .3.3.3.4.4.2.1.3 0 .2-.1a.6.6 0 0 1-.2-.2h.7c.3 0 .4-.4.3-.5Z" data-v-d1ac2910=""></path>
30
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M61 26.7c-.5-2.6-2.9-4.1-4.1-4.7l-1.4-.4-.4-.2c.1-.5.8-.5 1.2-1.3 1-2.3-1.2-3.8-2.8-3.5-.8.2-1.3.4-1.5 1 0 .4-.3.4-.7.8-.2.2.1.4.2.5l-.1.3v.5s-.3.3 0 .7l.3.8c0 .1 0 .2-.3 0l-3.4-1a37.4 37.4 0 0 1-4.2-4.7c-.7 0 .5 1.3-.1.8-.2 0-.7-.4-.8-.5l-.1-.2-.3-.3H42.2c-.2 0-.1.5 0 .7 0 0 .4 1.2.6 1.4l1.5 1 2.6 3c.7.7 3.8 2.5 3.9 2.6.2 0 .5.8 0 5.5-.1 1.8-1.4 5.6-.8 7.5.4 1.3.9 2.2 1.3 5.6.1.8-.5 1.3-1.3 2l-1.4.8c-.2.2 0 .4.2.5.2 0 .5.3.8.3.3.1.9 0 1.4-.3.7-.3.7-.4 1-.6.5-.3 1-.3 1.2-.8.2-.6-.3-1.4-.3-1.7.4-2.8.9-4.1.2-5.8-.2-.3 1-4 1-3.4.2.9.3 3.8.3 5.9 0 .9.8 4.2 1 5.4.4 1.8-2.6 3.2-2 3.8l1 .3 1-.1c.3-.1.6-.5.7-.6.6-.8.4-.6 1-1.1.4-.5 0-1.4 0-1.8v-2.9c0-1.9 0-2.4.2-3.2l1-6.2s.2 0 .3-.2c.2-.2.1-.5.2-.7 0-.2 0 0 0 0l.2.6-.2.8c-.2.4.1.4.2.5 0 0 1-.7 1.2-1l.1-.8-.2-1.8c.2-.9 1-3.2.8-3.8Zm-2.2 3.6c-.2.5-.2 0-.6 1.7V31.1c0-2.1-1.5-6.5-.6-5.6 0 0 1.2.8 1.4 1.4.2.5.1 1.8-.2 3.4Z" data-v-d1ac2910=""></path>
31
+ <path d="M20 35.3c-.3-.3-1.6-2-2.4-2.7l-1-1.5c-1.6-2-1.9-2.1-3-2.2-.1-.2 0-.3 0-.4 1.3-.5.9-1.6.8-1.7l.2-.6-.2-1-.1-.7c-.8-.9-2.6-.9-3.5-.3-.8.5-.3.9-.6 1.6-.1.5 0 .9.3 1.2 0 .3.8.7.7 1.2-.2.6-1 .7-1 .7l-.3.1c-1.4.8-2.7 2-2.9 3.2 0 1 1.7 2.5 2.7 3.3.1 1.7 1.2 4.4 1.3 4.5.1.3-.3-.3-1.4-.7-.6-.1-1.2-.9-1.4 0 0 .4 0 1-.3 1.8-.2.6 0 1.5.7 1.5.5 0 .8-1.4.8-1.4s2.3 1 3.3.7c.7-.2.8-2.7.2-5-.2-.8.4 1.3 2 3.1.2.4 0 .7.2 2.2v1c0 .7-.7 1.6.9 2 1.6.4 1.5.8 2.5.1.5-.3-1.4-.5-1.8-1.6v-.2c0-.9.3-2.9.2-3.6-.6-3.4-2-5-2.2-5.8 0-2.4-.2-3.2 0-2.6l1 1.5.3.3.4.4 2.8 2.1s.1 1 .6 1c.4 0 2.3-1 2.2-1.1 0-.3-2-.3-2-.4ZM9.7 34l-1-1.8c.4-.7 1-1 1-.9.2 0 0 2.7 0 2.7Z" data-v-d1ac2910=""></path>
32
+ <path d="M51.8 54.8c-.1 0-1.2-.5-2.2-2-.5-.8-3.8-7-4.3-8.2-.9-2.4-8-6.7-8.2-7-.2-.1-.2-.5-.1-.8.5-2 .3-3.8.4-4.1.3-.7.8-1.7.4-2.3l-.7-1.2s3.7 1.4 4.6 1.2c.8-.2 4.5-2.8 4.7-2.9.5-.2 1.8.1 3-1.3.5-.5.2-.6 0-.6.1 0-.1-.2-.4 0-.2.1-1.3.4-1.1.2.8-.5.2-.7.2-.7-.3.3-1.8.7-2.1 1l-.8.5c-.9.5-2.4 1.3-4 1.7-.3 0-3.3-2-5-2.2-1-.1-1.3 0-1.8.1-.6.2-.6-.7 0-1 .2 0 .6-.1.7-.4.2-.4 0-.7 0-.8v-.2l-.1-.1v-.5c.3-.2.2-.4.1-.4-.1-.1-.6-.4-.7-.7 0-.6-.3-.9-.3-1.2 0 0-.1-.8-.4-1-.4-.4-1.2-.8-2.8-.3-.6.1-.5.4-1.8.6-1.6.3-2.4 2.7-2.3 3.7.1.8.8.4.8.7 0 .6-.1 1.5 1 1.8.3 0 1.8-.2 2.4 0 0 0 .5 0 .2.4-.1.2-1.6.9-2 1-1 .4-3.6 4.6-4.3 5-.7.3-1 .6-1.3.8-1 .6-2.1 1.4-2.7 1.4-.7 0-1.4.3-1.9 1.5-.1.3 0 .5.3.5 0 .1.2.3.4.3.2.2.5 0 .7 0l1-.7c.5-.2 4-1.5 4.7-2.1 1.2-.6 3.5-3 4-3s1.6 1 1.2 3c0 .7-1 2-1.4 2.6-1 1.5-.2 2.7-.4 3-1 1.6-2.2 3.7-4.2 5.5-.8.6-2.4.7-3.3 1-2 .5-4.2 2-5.7 2.8-.5.3-1-.3-1.6-.4-.7 0-.7 1-1 1.8l-.7 1.5c-.1.4-.7 1.7-.1 2.2.4.7 1.5-1.4 2.4-2.3.4-.5.7-.7 1.7-1 .6 0 5.6-1.4 8.8-2.2h.3c4.2-1.1 8.6-6.6 8.7-6.6l7.2 3.5c.7.4.7 1.8 1.5 3.4a22 22 0 0 0 4.4 4.9c.4.4 0 1 .2 1.6.2.6.6.6 1.1.6l1.6-.2c.7 0 .5 0 1.3.2.4 0 1.3.1 2-.5 1-1.2-1.2-.6-2.3-1.1Z" data-v-d1ac2910=""></path>
33
+ <path d="M44 51.7a.4.4 0 0 0-.6-.2 22.2 22.2 0 0 1-21-.6.5.5 0 0 0-.6.2c-.1.2 0 .4.1.6a23 23 0 0 0 21.9.5c.2 0 .3-.3.2-.5Z" data-v-d1ac2910=""></path>
34
+ <path d="M12.9 22.9h-.2c-.2-.2-.3-.4-.2-.6 2-4.4 5.2-8 9.3-10.4.2-.1.5 0 .6.2.2.2 0 .4-.1.6-4 2.3-7.1 5.7-9 10l-.4.2Z" data-v-d1ac2910=""></path>
35
+ <path d="M50.3 17.3c-.1 0-.3 0-.3-.2A22 22 0 0 0 36.5 10c-.2 0-.4-.3-.3-.5 0-.3.2-.4.5-.4a23 23 0 0 1 14 7.5v.7h-.4Z" data-v-d1ac2910=""></path>
36
+ </svg>
37
+ <!--v-if-->
38
+ <!--v-if-->
39
+ </a></div>
40
+ <!--v-if-->
41
+ </div>
42
+ <!--v-if-->
43
+ </div>
44
+ </header>"
45
+ `;
@@ -0,0 +1,26 @@
1
+ import { it, describe, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import useHeaderResponsiveMode from '../useHeaderResponsiveMode'
4
+
5
+ describe('useHeaderResponsiveMode', () => {
6
+ it('should return the correct responsive mode', async () => {
7
+ // @ts-expect-error - Property 'happyDOM' does not exist on type 'Window & typeof globalThis'.
8
+ window.happyDOM.setInnerWidth(600)
9
+ const wrapper = mount({
10
+ template: `<div :class="{'is-desktop': isDesktop}"></div>`,
11
+ setup() {
12
+ const { isDesktop } = useHeaderResponsiveMode()
13
+ return { isDesktop }
14
+ },
15
+ })
16
+
17
+ expect(wrapper.find('.is-desktop').exists()).toBe(false)
18
+
19
+ // @ts-expect-error - Property 'happyDOM' does not exist on type 'Window & typeof globalThis'.
20
+ window.happyDOM.setInnerWidth(1200)
21
+ await wrapper.vm.$nextTick()
22
+ expect(wrapper.find('.is-desktop').exists()).toBe(true)
23
+
24
+ wrapper.unmount()
25
+ })
26
+ })
@@ -0,0 +1,34 @@
1
+ import { it, describe, expect, vi } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import useScrollDirection from '../useScrollDirection'
4
+
5
+ describe('useScrollDirection', () => {
6
+ it('should return the correct scroll direction', async () => {
7
+ const mockScrollTop = vi.spyOn(document.documentElement, 'scrollTop', 'get')
8
+
9
+ const wrapper = mount({
10
+ template: `<div :class="scrollDirection"></div>`,
11
+ setup() {
12
+ const { scrollDirection } = useScrollDirection()
13
+ return { scrollDirection }
14
+ },
15
+ })
16
+ mockScrollTop.mockReturnValue(0)
17
+ window.dispatchEvent(new CustomEvent('scroll'))
18
+
19
+ expect(wrapper.find('div').classes()).toEqual([])
20
+
21
+ mockScrollTop.mockReturnValue(100)
22
+ window.dispatchEvent(new CustomEvent('scroll'))
23
+ await wrapper.vm.$nextTick()
24
+ expect(wrapper.find('div').classes()).toEqual(['bottom'])
25
+
26
+ mockScrollTop.mockReturnValue(50)
27
+ window.dispatchEvent(new CustomEvent('scroll'))
28
+ await wrapper.vm.$nextTick()
29
+ expect(wrapper.find('div').classes()).toEqual(['top'])
30
+
31
+ vi.clearAllMocks()
32
+ wrapper.unmount()
33
+ })
34
+ })
@@ -0,0 +1,25 @@
1
+ import { ref, onMounted, onUnmounted } from 'vue'
2
+ import { headerBreakpoint } from './consts'
3
+
4
+ export default function useIsDesktop() {
5
+ const isDesktop = ref(false)
6
+
7
+ let mediaQuery: MediaQueryList
8
+
9
+ function handleChange(e: MediaQueryListEvent) {
10
+ isDesktop.value = e.matches
11
+ }
12
+
13
+ onMounted(() => {
14
+ mediaQuery = window.matchMedia(`(min-width: ${headerBreakpoint}px)`)
15
+ isDesktop.value = mediaQuery.matches
16
+
17
+ mediaQuery.addEventListener('change', handleChange)
18
+ })
19
+
20
+ onUnmounted(() => {
21
+ mediaQuery.removeEventListener('change', handleChange)
22
+ })
23
+
24
+ return { isDesktop }
25
+ }
@@ -0,0 +1,26 @@
1
+ import { onMounted, onUnmounted, ref } from 'vue'
2
+
3
+ export default function useScrollDirection() {
4
+ const lastYPos = ref<number | null>(null)
5
+ const scrollDirection = ref<'' | 'top' | 'bottom'>('')
6
+
7
+ function handleScroll() {
8
+ const yPos = document.documentElement.scrollTop
9
+ if (lastYPos.value === null) {
10
+ lastYPos.value = yPos
11
+ return ''
12
+ }
13
+ scrollDirection.value = yPos >= lastYPos.value ? 'bottom' : 'top'
14
+ lastYPos.value = yPos
15
+ }
16
+
17
+ onMounted(() => {
18
+ window.addEventListener('scroll', handleScroll)
19
+ })
20
+
21
+ onUnmounted(() => {
22
+ window.removeEventListener('scroll', handleScroll)
23
+ })
24
+
25
+ return { scrollDirection }
26
+ }
@@ -0,0 +1,28 @@
1
+ import { Controls, Canvas, Meta, Source } from '@storybook/blocks';
2
+ import * as HeaderLoading from './HeaderLoading.stories';
3
+
4
+ <Meta of={HeaderLoading} />
5
+
6
+ # HeaderLoading
7
+
8
+ L’élément `HeaderLoading` est une extension du composant `VSkeletonLoader` de Vuetify, il est utilisé pour afficher un élément de chargement avec des dimensions personnalisées.
9
+
10
+ <Canvas of={HeaderLoading.Default} />
11
+
12
+ # API
13
+
14
+ <Controls of={HeaderLoading.Default} />
15
+
16
+ # Exemple d'utilisation
17
+
18
+ <Source dark code={`
19
+ <script setup lang="ts">
20
+ import HeaderLoading from '@cnamts/synapse'
21
+ </script>
22
+
23
+ <template>
24
+ <div class="pa-4">
25
+ <HeaderLoading width="200px" />
26
+ </div>
27
+ </template>
28
+ `} />
@@ -0,0 +1,62 @@
1
+ import HeaderLoading from './HeaderLoading.vue'
2
+ import type { Meta, StoryObj } from '@storybook/vue3'
3
+
4
+ const meta: Meta<typeof HeaderLoading> = {
5
+ title: 'Composants/Structure/HeaderLoading',
6
+ component: HeaderLoading,
7
+ parameters: {
8
+ layout: 'fullscreen',
9
+ controls: { exclude: ['heading', 'itemsNumber', 'row'] },
10
+ },
11
+ argTypes: {
12
+ width: { control: 'text' },
13
+ height: { control: 'text' },
14
+ },
15
+ }
16
+
17
+ export default meta
18
+
19
+ type Story = StoryObj<typeof meta>
20
+
21
+ export const Default: Story = {
22
+ parameters: {
23
+ sourceCode: [
24
+ {
25
+ name: 'Template',
26
+ code: `
27
+ <template>
28
+ <HeaderLoading :width="width" :height="height" />
29
+ </template>
30
+ `,
31
+ },
32
+ {
33
+ name: 'Script',
34
+ code: `
35
+ <script setup lang="ts">
36
+ import HeaderLoading from '@cnamts/synapse'
37
+
38
+ const width = '100px'
39
+ const height = '1rem'
40
+ </script>
41
+ `,
42
+ },
43
+ ],
44
+ },
45
+ args: {
46
+ width: '100px',
47
+ height: '1rem',
48
+ },
49
+ render: (args) => {
50
+ return {
51
+ components: { HeaderLoading },
52
+ setup() {
53
+ return { args }
54
+ },
55
+ template: `
56
+ <div class="pa-4">
57
+ <HeaderLoading v-bind="args" />
58
+ </div>
59
+ `,
60
+ }
61
+ },
62
+ }
@@ -0,0 +1,45 @@
1
+ <script lang="ts" setup>
2
+ import { VSkeletonLoader } from 'vuetify/components/VSkeletonLoader'
3
+
4
+ const props = defineProps({
5
+ width: {
6
+ type: String,
7
+ default: '100px',
8
+ },
9
+ height: {
10
+ type: String,
11
+ default: '1rem',
12
+ },
13
+ })
14
+ </script>
15
+
16
+ <template>
17
+ <VSkeletonLoader
18
+ v-bind="$attrs"
19
+ :width="props.width"
20
+ :height="props.height"
21
+ type="heading"
22
+ aria-hidden="true"
23
+ class="vd-header-loading"
24
+ />
25
+ </template>
26
+
27
+ <style lang="scss" scoped>
28
+ .vd-header-loading :deep() {
29
+ background: transparent;
30
+ .v-skeleton-loader__heading {
31
+ width: 100%;
32
+ height: 100%;
33
+ border-radius: 35px;
34
+ margin: 0;
35
+ background: rgba(grey, var(--v-border-opacity));
36
+ }
37
+ }
38
+
39
+ // Remove border radius when tile option is activated
40
+ .vd-header-loading.v-skeleton-loader--tile :deep() {
41
+ .v-skeleton-loader__heading {
42
+ border-radius: 0;
43
+ }
44
+ }
45
+ </style>
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { vuetify } from '@tests/unit/setup'
4
+
5
+ import HeaderLoading from '../HeaderLoading.vue'
6
+
7
+ describe('HeaderLoading', () => {
8
+ it('renders correctly', () => {
9
+ const wrapper = mount(HeaderLoading, {
10
+ global: {
11
+ plugins: [vuetify],
12
+ },
13
+ props: {
14
+ width: '100px',
15
+ height: '1rem',
16
+ },
17
+ })
18
+
19
+ const elExists = wrapper.find('.vd-header-loading').exists()
20
+ expect(elExists).toBe(true)
21
+ })
22
+ })
@@ -0,0 +1,128 @@
1
+ import { Controls, Canvas, Meta, Source } from "@storybook/blocks";
2
+ import * as HeaderNavigationBarStories from "./HeaderNavigationBar.stories";
3
+
4
+ <Meta of={HeaderNavigationBarStories} />
5
+
6
+ # HeaderNavigationBar
7
+
8
+ Le composant `HeaderNavigationBar` est un composant de navigation qui permet de naviguer entre les différentes pages de l'application.
9
+
10
+ Il est basé sur les composants `HeaderBar` et `HeaderBurgerMenu` du design system.
11
+
12
+ Ce composant propose un navigation à l'aide d'un menu horizontal en mode desktop ce qui peut être util pour les produits ayant peut de page a destination des agents.
13
+
14
+ Si vous n'avez pas besoin du menu horizontal, vous devriez utiliser le composant `HeaderBar` directement.
15
+
16
+ Il est conseillé de ne pas utiliser le menu horizontal pour afficher plus de 6 liens. Vous pouvez configurer le nombre de lien affiché dans le menu horizontal en utilisant la prop `maxHorizontalMenuItems`. Au-delà de ce chiffre, le menu passera en mode burger. Par défaut, le menu horizontal affiche au maximum six items.
17
+
18
+
19
+ <Canvas of={HeaderNavigationBarStories.Default} />
20
+
21
+ ## API
22
+
23
+ <Controls of={HeaderNavigationBarStories.Default} />
24
+
25
+
26
+ ## Exemple d'utilisation
27
+
28
+ <Source
29
+ dark
30
+ code={`
31
+ <HeaderNavigationBar
32
+ home-aria-label="Home"
33
+ service-title="Synapse"
34
+ service-subtitle="design system de la CNAM"
35
+ :sticky="true"
36
+ :items="[
37
+ { label: 'Home', to: '/' },
38
+ { label: 'About', to: '/about' },
39
+ { label: 'Services', to: '/services' },
40
+ { label: 'Contact', to: '/contact' },
41
+ { label: 'Blog', to: '/blog' },
42
+ ]"
43
+ />
44
+ `}
45
+ />
46
+
47
+ ## Les slots
48
+
49
+ ### HeaderSide
50
+
51
+ Le slot `header-side` permet d'ajouter du contenu à droite du header. Il est possible d'ajouter plusieurs éléments dans ce slot.
52
+ Il sera principalement utilisé pour ajouter un bouton de connexion, d'accès à un compte ou de recherche.
53
+ Il est nécessaire de faire attention à la place que prendront les éléments en mode mobile et de prévoir un mode réduit ou bien de les déporter dans le menu burger.
54
+
55
+ <Source dark code={`
56
+ <script setup lang="ts">
57
+ import { mdiMagnify, mdiAccountCircleOutline } from '@mdi/js'
58
+ </script>
59
+
60
+ <template>
61
+ <HeaderNavigationBar>
62
+ <template #header-side>
63
+ <div class="d-flex justify-center h-100 ga-4 pr-4">
64
+ <VBtn
65
+ variant="text"
66
+ :prepend-icon="mdiMagnify"
67
+ color="primary"
68
+ >
69
+ Rechercher
70
+ </VBtn>
71
+ <VBtn
72
+ color="primary"
73
+ :prepend-icon="mdiAccountCircleOutline"
74
+ >
75
+ Login
76
+ </VBtn>
77
+ </div>
78
+ </template>
79
+ </HeaderNavigationBar>
80
+ </template>
81
+ `} />
82
+
83
+ ### Les slots concernant le menu
84
+
85
+
86
+ <Canvas of={HeaderNavigationBarStories.WithSlots} />
87
+
88
+ #### le slot `logo-brand-section`
89
+
90
+ <Canvas of={HeaderNavigationBarStories.WithLogoSlot} />
91
+
92
+ #### Le menu horizontal
93
+
94
+ Quand le menu est en mode horizontal, les slots `navigation-bar-prepend` et `navigation-bar-append` permettent d'ajouter du contenu avant et après le menu.
95
+
96
+ Le slot `navigation-bar-content` quant à lui, remplace les items du menu tel que généré avec la props `items`. Il n'écrase pas les slots `navigation-bar-prepend` et `navigation-bar-append`.
97
+
98
+ ##### Slot `Navigation-bar-prepend`
99
+
100
+ <Canvas of={HeaderNavigationBarStories.WithNavigationBarPrependSlot} />
101
+
102
+
103
+ ##### Slot `Navigation-bar-append`
104
+
105
+ <Canvas of={HeaderNavigationBarStories.WithNavigationBarAppendSlot} />
106
+
107
+
108
+ #### Les slots concernant le menu burger
109
+
110
+ Le menu burger est généré automatiquement à partir des items passés en props, il utilise en interne le composant `HeaderBurgerMenu`.
111
+
112
+
113
+ les slots `burger-menu-prepend` et `burger-menu-append` permettent d'ajouter du contenu en haut et en bas du menu burger.
114
+
115
+
116
+ Le slot `burger-menu-content` permet de remplacer le contenu du menu burger. Il n'écrase pas les slots `burger-menu-prepend` et `burger-menu-append` et permet d'utiliser les composants `HeaderMenuItem` et `HeaderMenuGroup` pour construire le menu.
117
+ Pour plus de d'information sur la manière de construire un menu avec le composant `HeaderBurgerMenu`, vous pouvez consulter la documentation de ce [composant](/docs/components-headerbar-headerburgermenu--docs).
118
+
119
+ ##### Slot `burger-menu-append`
120
+
121
+ <Canvas of={HeaderNavigationBarStories.WithNavigationMenuAppendSlot} />
122
+
123
+
124
+ ## Configuration des composants Vuetify internes.
125
+
126
+ Le composant `HeaderNavigationBar` utilise les composants `VSheet`, `VTabs` et `VTab` de Vuetify pour construire le menu horizontal. Il est possible de configurer ces composants en utilisant la props `vuetifyOptions`.
127
+
128
+ <Canvas of={HeaderNavigationBarStories.WithVuetifyOptions} />