@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.
- package/README.md +1 -1
- package/dist/design-system-v3.d.ts +712 -27
- package/dist/design-system-v3.js +2745 -5384
- package/dist/design-system-v3.umd.cjs +10 -2
- package/dist/style.css +1 -1
- package/package.json +32 -29
- package/src/components/Alert/Alert.mdx +1 -1
- package/src/components/Alert/Alert.stories.ts +91 -1
- package/src/components/Alert/Alert.vue +8 -8
- package/src/components/BackBtn/BackBtn.mdx +1 -1
- package/src/components/BackBtn/BackBtn.stories.ts +84 -1
- package/src/components/BackToTopBtn/BackToTopBtn.mdx +3 -3
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +172 -11
- package/src/components/CollapsibleList/CollapsibleList.mdx +2 -2
- package/src/components/CollapsibleList/CollapsibleList.stories.ts +37 -1
- package/src/components/CopyBtn/CopyBtn.mdx +1 -1
- package/src/components/CopyBtn/CopyBtn.stories.ts +120 -1
- package/src/components/CopyBtn/CopyBtn.vue +1 -1
- package/src/components/Customs/CustomInputSelect/CustomInputSelect.mdx +6 -8
- package/src/components/Customs/CustomInputSelect/CustomInputSelect.stories.ts +270 -4
- package/src/components/Customs/CustomInputSelect/CustomInputSelect.vue +80 -53
- package/src/components/Customs/CustomInputSelect/config.ts +10 -0
- package/src/components/Customs/CustomSelect/CustomSelect.mdx +3 -3
- package/src/components/Customs/CustomSelect/CustomSelect.stories.ts +158 -2
- package/src/components/Customs/CustomSelect/CustomSelect.vue +25 -6
- package/src/components/Customs/CustomTextField/CustomTextField.mdx +44 -0
- package/src/components/Customs/CustomTextField/CustomTextField.stories.ts +403 -0
- package/src/components/Customs/CustomTextField/CustomTextField.vue +110 -0
- package/src/components/Customs/CustomTextField/tests/CustomTextField.spec.ts +93 -0
- package/src/components/Customs/CustomTextField/tests/__snapshots__/CustomTextField.spec.ts.snap +59 -0
- package/src/components/Customs/CustomTextField/types.d.ts +3 -0
- package/src/components/DataList/DataList.mdx +77 -0
- package/src/components/DataList/DataList.stories.ts +960 -0
- package/src/components/DataList/DataList.vue +140 -0
- package/src/components/DataList/DataListLoading/DataListLoading.vue +56 -0
- package/src/components/DataList/DataListLoading/tests/DataListLoading.spec.ts +23 -0
- package/src/components/DataList/locales.ts +3 -0
- package/src/components/DataList/tests/DataList.spec.ts +194 -0
- package/src/components/DataList/types.d.ts +23 -0
- package/src/components/DataListGroup/DataListGroup.mdx +77 -0
- package/src/components/DataListGroup/DataListGroup.stories.ts +987 -0
- package/src/components/DataListGroup/DataListGroup.vue +59 -0
- package/src/components/DataListGroup/tests/DataListGroup.spec.ts +54 -0
- package/src/components/DataListGroup/tests/data/dataListGroupItems.ts +41 -0
- package/src/components/DataListGroup/types.d.ts +15 -0
- package/src/components/DataListItem/DataListItem.vue +135 -0
- package/src/components/DataListItem/config.ts +17 -0
- package/src/components/DataListItem/locales.ts +3 -0
- package/src/components/DataListItem/tests/DataListItem.spec.ts +156 -0
- package/src/components/DataListItem/types.d.ts +23 -0
- package/src/components/DownloadBtn/Accessibilite.mdx +14 -0
- package/src/components/DownloadBtn/Accessibilite.stories.ts +166 -0
- package/src/components/DownloadBtn/AccessibiliteItems.ts +129 -0
- package/src/components/DownloadBtn/DownloadBtn.mdx +5 -6
- package/src/components/DownloadBtn/DownloadBtn.stories.ts +207 -2
- package/src/components/DownloadBtn/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/FooterBar/FooterBar.mdx +2 -2
- package/src/components/FooterBar/FooterBar.stories.ts +1 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +1 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.stories.ts +58 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.vue +2 -2
- package/src/components/HeaderBar/HeaderBar.mdx +256 -0
- package/src/components/HeaderBar/HeaderBar.stories.ts +703 -0
- package/src/components/HeaderBar/HeaderBar.vue +276 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.mdx +433 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.stories.ts +1089 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.vue +234 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.mdx +38 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.stories.ts +89 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +51 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/tests/HeaderMenuItem.spec.ts +16 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/tests/__snapshots__/HeaderMenuItem.spec.ts.snap +3 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.mdx +17 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.stories.ts +121 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.vue +51 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/tests/HeaderMenuSection.spec.ts +31 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.mdx +43 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.stories.ts +261 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +194 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/tests/HeaderSubMenu.spec.ts +63 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/conts.ts +1 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/locals.ts +4 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/HeaderBurgerMenu.spec.ts +180 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/HeaderBurgerMenu.spec.ts.snap +13 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/HeaderComplexMenu.spec.ts.snap +13 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/useHandleSubMenus.spec.ts +158 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/useHandleSubMenus.ts +49 -0
- package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +143 -0
- package/src/components/HeaderBar/HeaderLogo/locales.ts +3 -0
- package/src/components/HeaderBar/HeaderLogo/logos/Logo-mobile.vue +117 -0
- package/src/components/HeaderBar/HeaderLogo/logos/Logo.vue +279 -0
- package/src/components/HeaderBar/HeaderLogo/tests/HeaderLogo.spec.ts +119 -0
- package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +84 -0
- package/src/components/HeaderBar/HeaderMenuBtn/locals.ts +4 -0
- package/src/components/HeaderBar/HeaderMenuBtn/tests/HeaderMenuBtn.spec.ts +70 -0
- package/src/components/HeaderBar/Usages.mdx +85 -0
- package/src/components/HeaderBar/consts.scss +6 -0
- package/src/components/HeaderBar/consts.ts +2 -0
- package/src/components/HeaderBar/locales.ts +3 -0
- package/src/components/HeaderBar/tests/HeaderBar.spec.ts +216 -0
- package/src/components/HeaderBar/tests/__snapshots__/HeaderBar.spec.ts.snap +45 -0
- package/src/components/HeaderBar/tests/useHeaderResponsiveMode.spec.ts +26 -0
- package/src/components/HeaderBar/tests/useScrollDirection.spec.ts +34 -0
- package/src/components/HeaderBar/useHeaderResponsiveMode.ts +25 -0
- package/src/components/HeaderBar/useScrollDirection.ts +26 -0
- package/src/components/HeaderLoading/HeaderLoading.mdx +28 -0
- package/src/components/HeaderLoading/HeaderLoading.stories.ts +62 -0
- package/src/components/HeaderLoading/HeaderLoading.vue +45 -0
- package/src/components/HeaderLoading/tests/HeaderLoading.spec.ts +22 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.mdx +128 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +784 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +194 -0
- package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +74 -0
- package/src/components/HeaderNavigationBar/HorizontalNavbar/config.ts +18 -0
- package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.spec.ts +127 -0
- package/src/components/HeaderNavigationBar/types.ts +7 -0
- package/src/components/HeaderToolbar/HeaderToolbar.mdx +31 -0
- package/src/components/HeaderToolbar/HeaderToolbar.stories.ts +343 -0
- package/src/components/HeaderToolbar/HeaderToolbar.vue +487 -0
- package/src/components/HeaderToolbar/tests/HeaderToolbar.spec.ts +196 -0
- package/src/components/HeaderToolbar/types.d.ts +20 -0
- package/src/components/LangBtn/LangBtn.mdx +1 -1
- package/src/components/LangBtn/LangBtn.stories.ts +125 -8
- package/src/components/Logo/Logo.mdx +2 -2
- package/src/components/Logo/Logo.stories.ts +147 -1
- package/src/components/LogoBrandSection/LogoBrandSection.mdx +14 -0
- package/src/components/LogoBrandSection/LogoBrandSection.stories.ts +158 -0
- package/src/components/LogoBrandSection/LogoBrandSection.vue +312 -0
- package/src/components/LogoBrandSection/assets/ameli-pro.svg +1 -0
- package/src/components/LogoBrandSection/assets/ameli.svg +1 -0
- package/src/components/LogoBrandSection/assets/cnam.svg +1 -0
- package/src/components/LogoBrandSection/assets/compte-ameli.svg +1 -0
- package/src/components/LogoBrandSection/dividerDimensionsMapping.ts +14 -0
- package/src/components/LogoBrandSection/locales.ts +14 -0
- package/src/components/LogoBrandSection/secondaryLogoMapping.ts +24 -0
- package/src/components/LogoBrandSection/tests/LogoBrandSection.spec.ts +365 -0
- package/src/components/LogoBrandSection/tests/__snapshots__/LogoBrandSection.spec.ts.snap +14 -0
- package/src/components/LogoBrandSection/types.ts +8 -0
- package/src/components/NotificationBar/NotificationBar.mdx +6 -6
- package/src/components/NotificationBar/NotificationBar.stories.ts +1 -1
- package/src/components/NotificationBar/NotificationBar.vue +7 -9
- package/src/components/NotificationBar/tests/NotificationBar.spec.ts +1 -1
- package/src/components/PageContainer/PageContainer.mdx +1 -1
- package/src/components/PageContainer/PageContainer.stories.ts +86 -1
- package/src/components/PageContainer/PageContainer.vue +0 -1
- package/src/components/PhoneField/PhoneField.mdx +49 -0
- package/src/components/PhoneField/PhoneField.stories.ts +869 -0
- package/src/components/PhoneField/PhoneField.vue +230 -0
- package/src/components/PhoneField/indicatifs.ts +104 -0
- package/src/components/PhoneField/locales.ts +4 -0
- package/src/components/PhoneField/tests/PhoneField.spec.ts +179 -0
- package/src/components/SkipLink/SkipLink.stories.ts +50 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +28 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +37 -1
- package/src/components/SubHeader/SubHeader.mdx +31 -0
- package/src/components/SubHeader/SubHeader.stories.ts +1032 -0
- package/src/components/SubHeader/SubHeader.vue +185 -0
- package/src/components/SubHeader/config.ts +12 -0
- package/src/components/SubHeader/locales.ts +3 -0
- package/src/components/SubHeader/tests/SubHeader.spec.ts +144 -0
- package/src/components/index.ts +24 -7
- package/src/composables/widthable/index.ts +29 -0
- package/src/composables/widthable/tests/widthable.spec.ts +52 -0
- package/src/designTokens/tokens/cnam/cnamLightTheme.ts +2 -2
- package/src/main.ts +1 -0
- package/src/modules.d.ts +4 -0
- package/src/services/index.ts +1 -0
- package/src/stories/Demarrer/Accueil.mdx +10 -0
- package/src/stories/Demarrer/Accueil.stories.ts +76 -0
- package/src/stories/Demarrer/PolitiqueDeConfidentialite.mdx +9 -0
- package/src/stories/Demarrer/PolitiqueDeConfidentialite.stories.ts +20 -0
- package/src/stories/Fondamentaux/Accessibilite/Accessibilite.mdx +1 -2
- package/src/stories/Fondamentaux/Accessibilite/Accessibilite.stories.ts +1 -1
- package/src/stories/Fondamentaux/EcoConception/Econception.stories.ts +1 -1
- package/src/stories/GuideDuDev/moduleDeNotification.mdx +52 -48
- package/src/stories/GuideDuDev/vuetifyOptions.mdx +31 -28
- package/src/stories/Guidelines/CustomisationEtThemes.mdx +1 -1
- package/src/utils/functions/throttleDisplayFn/tests/throttleDisplayFn.spec.ts +47 -0
- package/src/utils/functions/throttleDisplayFn/throttleDisplayFn.ts +26 -0
- package/src/utils/rules/exactLength/index.ts +33 -0
- package/src/utils/rules/exactLength/locales.ts +6 -0
- package/src/utils/rules/required/index.ts +25 -0
- package/src/utils/rules/required/locales.ts +5 -0
- package/src/utils/rules/required/ruleMessageHelper.ts +14 -0
- package/src/utils/rules/required/tests/index.spec.ts +47 -0
- package/src/utils/rules/required/tests/rulesMessageHelper.spec.ts +22 -0
- package/src/utils/rules/types.d.ts +15 -0
- package/src/components/Beta/beta.mdx +0 -5
- package/src/components/Deprecated/deprecated.mdx +0 -5
- package/src/stories/Home/Accueil.mdx +0 -7
- package/src/stories/Home/PolitiqueDeConfidentialite.mdx +0 -4
- package/src/stories/Home/synapse.webp +0 -0
- /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} />
|