@cnamts/synapse 0.0.4-alpha → 0.0.5-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 (150) hide show
  1. package/dist/design-system-v3.d.ts +932 -224
  2. package/dist/design-system-v3.js +3374 -1502
  3. package/dist/design-system-v3.umd.cjs +6 -6
  4. package/dist/style.css +1 -1
  5. package/package.json +2 -1
  6. package/src/assets/tokens.scss +0 -1
  7. package/src/components/Alert/Accessibilite.mdx +14 -0
  8. package/src/components/Alert/Accessibilite.stories.ts +166 -0
  9. package/src/components/Alert/AccessibiliteItems.ts +152 -0
  10. package/src/components/Alert/constants/ExpertiseLevelEnum.ts +4 -0
  11. package/src/components/BackBtn/Accessibilite.mdx +14 -0
  12. package/src/components/BackBtn/Accessibilite.stories.ts +166 -0
  13. package/src/components/BackBtn/AccessibiliteItems.ts +132 -0
  14. package/src/components/BackBtn/constants/ExpertiseLevelEnum.ts +4 -0
  15. package/src/components/BackToTopBtn/Accessibilite.mdx +14 -0
  16. package/src/components/BackToTopBtn/Accessibilite.stories.ts +166 -0
  17. package/src/components/BackToTopBtn/AccessibiliteItems.ts +82 -0
  18. package/src/components/BackToTopBtn/constants/ExpertiseLevelEnum.ts +4 -0
  19. package/src/components/CollapsibleList/Accessibilite.mdx +14 -0
  20. package/src/components/CollapsibleList/Accessibilite.stories.ts +166 -0
  21. package/src/components/CollapsibleList/AccessibiliteItems.ts +129 -0
  22. package/src/components/CollapsibleList/constants/ExpertiseLevelEnum.ts +4 -0
  23. package/src/components/CopyBtn/Accessibilite.mdx +14 -0
  24. package/src/components/CopyBtn/Accessibilite.stories.ts +166 -0
  25. package/src/components/CopyBtn/AccessibiliteItems.ts +135 -0
  26. package/src/components/CopyBtn/config.ts +2 -0
  27. package/src/components/CopyBtn/constants/ExpertiseLevelEnum.ts +4 -0
  28. package/src/components/Customs/SyBtnSelect/SyBtnSelect.mdx +44 -0
  29. package/src/components/Customs/SyBtnSelect/SyBtnSelect.stories.ts +606 -0
  30. package/src/components/Customs/SyBtnSelect/SyBtnSelect.vue +246 -0
  31. package/src/components/Customs/SyBtnSelect/tests/SyBtnSelect.spec.ts +168 -0
  32. package/src/components/Customs/SyInputSelect/SyInputSelect.mdx +40 -0
  33. package/src/components/Customs/{CustomInputSelect/CustomInputSelect.stories.ts → SyInputSelect/SyInputSelect.stories.ts} +29 -29
  34. package/src/components/Customs/{CustomInputSelect/CustomInputSelect.vue → SyInputSelect/SyInputSelect.vue} +10 -2
  35. package/src/components/Customs/SyInputSelect/tests/SyInputSelect.spec.ts +140 -0
  36. package/src/components/Customs/{CustomSelect/CustomSelect.mdx → SySelect/SySelect.mdx} +8 -8
  37. package/src/components/Customs/{CustomSelect/CustomSelect.stories.ts → SySelect/SySelect.stories.ts} +25 -25
  38. package/src/components/Customs/{CustomSelect/CustomSelect.vue → SySelect/SySelect.vue} +9 -5
  39. package/src/components/Customs/{CustomInputSelect/tests/CustomInputSelect.spec.ts → SySelect/tests/SySelect.spec.ts} +48 -71
  40. package/src/components/Customs/SyTextField/SyTextField.mdx +44 -0
  41. package/src/components/Customs/{CustomTextField/CustomTextField.stories.ts → SyTextField/SyTextField.stories.ts} +34 -34
  42. package/src/components/Customs/{CustomTextField/tests/CustomTextField.spec.ts → SyTextField/tests/SyTextField.spec.ts} +3 -3
  43. package/src/components/Customs/{CustomTextField/tests/__snapshots__/CustomTextField.spec.ts.snap → SyTextField/tests/__snapshots__/SyTextField.spec.ts.snap} +3 -5
  44. package/src/components/DialogBox/DialogBox.mdx +14 -0
  45. package/src/components/DialogBox/DialogBox.stories.ts +798 -0
  46. package/src/components/DialogBox/DialogBox.vue +181 -0
  47. package/src/components/DialogBox/config.ts +25 -0
  48. package/src/components/DialogBox/locales.ts +5 -0
  49. package/src/components/DialogBox/tests/DialogBox.spec.ts +329 -0
  50. package/src/components/DialogBox/tests/__snapshots__/DialogBox.spec.ts.snap +46 -0
  51. package/src/components/ErrorPage/ErrorPage.mdx +21 -0
  52. package/src/components/ErrorPage/ErrorPage.stories.ts +133 -0
  53. package/src/components/ErrorPage/ErrorPage.vue +93 -0
  54. package/src/components/ErrorPage/locales.ts +5 -0
  55. package/src/components/ErrorPage/tests/ErrorPage.spec.ts +40 -0
  56. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +78 -0
  57. package/src/components/FooterBar/FooterBar.stories.ts +556 -8
  58. package/src/components/FooterBar/config.ts +2 -3
  59. package/src/components/FooterBar/tests/FooterBar.spec.ts +1 -1
  60. package/src/components/FooterBar/tests/FooterBarConfig.spec.ts +1 -1
  61. package/src/components/FooterBar/tests/__snapshots__/FooterBar.spec.ts.snap +2 -2
  62. package/src/components/FranceConnectBtn/Accessibilite.mdx +14 -0
  63. package/src/components/FranceConnectBtn/Accessibilite.stories.ts +194 -0
  64. package/src/components/FranceConnectBtn/AccessibiliteItems.ts +199 -0
  65. package/src/components/FranceConnectBtn/constants/ExpertiseLevelEnum.ts +4 -0
  66. package/src/components/HeaderBar/HeaderBar.stories.ts +60 -2
  67. package/src/components/HeaderNavigationBar/HeaderNavigationBar.mdx +6 -6
  68. package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.spec.ts +1 -1
  69. package/src/components/HeaderToolbar/HeaderToolbar.vue +2 -2
  70. package/src/components/HeaderToolbar/tests/HeaderToolbar.spec.ts +36 -2
  71. package/src/components/LangBtn/Accessibilite.mdx +14 -0
  72. package/src/components/LangBtn/Accessibilite.stories.ts +166 -0
  73. package/src/components/LangBtn/AccessibiliteItems.ts +132 -0
  74. package/src/components/LangBtn/constants/ExpertiseLevelEnum.ts +4 -0
  75. package/src/components/LangBtn/tests/LangBtn.spec.ts +1 -1
  76. package/src/components/LangBtn/tests/__snapshots__/LangBtn.spec.ts.snap +1 -1
  77. package/src/components/MaintenancePage/MaintenancePage.mdx +11 -0
  78. package/src/components/MaintenancePage/MaintenancePage.stories.ts +41 -0
  79. package/src/components/MaintenancePage/MaintenancePage.vue +25 -0
  80. package/src/components/MaintenancePage/assets/maintenance.svg +1 -0
  81. package/src/components/MaintenancePage/index.ts +3 -0
  82. package/src/components/MaintenancePage/locales.ts +5 -0
  83. package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +12 -0
  84. package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +3 -0
  85. package/src/components/NotFoundPage/NotFoundPage.mdx +19 -0
  86. package/src/components/NotFoundPage/NotFoundPage.stories.ts +76 -0
  87. package/src/components/NotFoundPage/NotFoundPage.vue +52 -0
  88. package/src/components/NotFoundPage/assets/not-found.svg +1 -0
  89. package/src/components/NotFoundPage/locales.ts +6 -0
  90. package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +38 -0
  91. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +76 -0
  92. package/src/components/NotificationBar/Accessibilite.mdx +14 -0
  93. package/src/components/NotificationBar/Accessibilite.stories.ts +166 -0
  94. package/src/components/NotificationBar/AccessibiliteItems.ts +174 -0
  95. package/src/components/NotificationBar/constants/ExpertiseLevelEnum.ts +4 -0
  96. package/src/components/NotificationBar/options.ts +1 -0
  97. package/src/components/PageContainer/Accessibilite.mdx +14 -0
  98. package/src/components/PageContainer/Accessibilite.stories.ts +166 -0
  99. package/src/components/PageContainer/AccessibiliteItems.ts +52 -0
  100. package/src/components/PageContainer/constants/ExpertiseLevelEnum.ts +4 -0
  101. package/src/components/PhoneField/PhoneField.vue +5 -5
  102. package/src/components/PhoneField/tests/PhoneField.spec.ts +3 -3
  103. package/src/components/SkipLink/Accessibilite.mdx +14 -0
  104. package/src/components/SkipLink/Accessibilite.stories.ts +167 -0
  105. package/src/components/SkipLink/AccessibiliteItems.ts +77 -0
  106. package/src/components/SkipLink/constants/ExpertiseLevelEnum.ts +4 -0
  107. package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +17 -13
  108. package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +2 -1
  109. package/src/components/SocialMediaLinks/tests/SocialMediaLinks.spec.ts +1 -1
  110. package/src/components/SocialMediaLinks/tests/__snapshots__/SocialMediaLinks.spec.ts.snap +2 -2
  111. package/src/components/SubHeader/SubHeader.vue +1 -1
  112. package/src/components/UserMenuBtn/UserMenuBtn.mdx +35 -0
  113. package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +438 -0
  114. package/src/components/UserMenuBtn/UserMenuBtn.vue +105 -0
  115. package/src/components/UserMenuBtn/config.ts +24 -0
  116. package/src/components/UserMenuBtn/tests/UserMenuBtn.spec.ts +125 -0
  117. package/src/components/index.ts +12 -3
  118. package/src/composables/index.ts +8 -0
  119. package/src/composables/rules/tests/useFieldValidation.spec.ts +82 -0
  120. package/src/composables/rules/useFieldValidation.ts +53 -0
  121. package/src/designTokens/index.ts +2 -0
  122. package/src/designTokens/tokens/cnam/cnamDarkTheme.ts +5 -0
  123. package/src/designTokens/tokens/cnam/cnamLightTheme.ts +1 -0
  124. package/src/main.ts +2 -0
  125. package/src/stories/Fondamentaux/Arrondis.mdx +24 -0
  126. package/src/stories/{Guidelines → Fondamentaux}/Colors.mdx +1 -1
  127. package/src/stories/Fondamentaux/Conteneurs.mdx +7 -0
  128. package/src/stories/Fondamentaux/CustomisationEtThemes.mdx +7 -0
  129. package/src/stories/Fondamentaux/Elevations.mdx +14 -0
  130. package/src/stories/Fondamentaux/Espacements.mdx +29 -0
  131. package/src/stories/{Guidelines → Fondamentaux}/Introduction.mdx +1 -1
  132. package/src/stories/Fondamentaux/StylesTypographiques.mdx +33 -0
  133. package/src/stories/Fondamentaux/Typographie.mdx +58 -0
  134. package/src/stories/GuideDuDev/CommentUtiliserLesRules.mdx +132 -0
  135. package/src/stories/{Fondamentaux → Guidelines}/Accessibilite/Accessibilite.stories.ts +1 -1
  136. package/src/stories/{Fondamentaux → Guidelines}/EcoConception/Econception.stories.ts +2 -2
  137. package/src/components/Customs/CustomInputSelect/CustomInputSelect.mdx +0 -40
  138. package/src/components/Customs/CustomSelect/tests/CustomSelect.spec.ts +0 -236
  139. package/src/components/Customs/CustomTextField/CustomTextField.mdx +0 -44
  140. package/src/stories/Guidelines/CustomisationEtThemes.mdx +0 -3
  141. package/src/stories/Guidelines/Typo.mdx +0 -53
  142. /package/src/components/Customs/{CustomInputSelect → SyInputSelect}/config.ts +0 -0
  143. /package/src/components/Customs/{CustomTextField/CustomTextField.vue → SyTextField/SyTextField.vue} +0 -0
  144. /package/src/components/Customs/{CustomTextField → SyTextField}/types.d.ts +0 -0
  145. /package/src/stories/{Fondamentaux → Guidelines}/Accessibilite/Accessibilite.mdx +0 -0
  146. /package/src/stories/{Fondamentaux → Guidelines}/Accessibilite/AccessibiliteItems.ts +0 -0
  147. /package/src/stories/{Fondamentaux → Guidelines}/Accessibilite/constants/ExpertiseLevelEnum.ts +0 -0
  148. /package/src/stories/{Fondamentaux → Guidelines}/Accessibilite/constants/RGAALevelEnum.ts +0 -0
  149. /package/src/stories/{Fondamentaux → Guidelines}/EcoConception/EcoConception.mdx +0 -0
  150. /package/src/stories/{Fondamentaux → Guidelines}/EcoConception/ecoDesignItems.ts +0 -0
@@ -0,0 +1,246 @@
1
+ <script lang="ts" setup>
2
+ import { ref, watch, computed, onMounted, useSlots } from 'vue'
3
+ import { useDisplay } from 'vuetify'
4
+
5
+ const props = defineProps({
6
+ modelValue: {
7
+ type: [Object, String, null],
8
+ default: null,
9
+ },
10
+ menuItems: {
11
+ type: Array,
12
+ default: () => [],
13
+ },
14
+ label: {
15
+ type: String,
16
+ default: 'Sélectionnez une option',
17
+ },
18
+ required: {
19
+ type: Boolean,
20
+ default: false,
21
+ },
22
+ menuId: {
23
+ type: String,
24
+ default: 'custom-btn-select-menu',
25
+ },
26
+ textKey: {
27
+ type: String,
28
+ default: 'text',
29
+ },
30
+ valueKey: {
31
+ type: String,
32
+ default: 'value',
33
+ },
34
+ primaryInfo: {
35
+ type: String,
36
+ default: 'Information principale',
37
+ },
38
+ secondaryInfo: {
39
+ type: String,
40
+ default: undefined,
41
+ },
42
+ hideIcon: {
43
+ type: Boolean,
44
+ default: false,
45
+ },
46
+ hideLogoutBtn: {
47
+ type: Boolean,
48
+ default: false,
49
+ },
50
+ isMobileView: {
51
+ type: Boolean,
52
+ default: false,
53
+ },
54
+ iconOnly: {
55
+ type: Boolean,
56
+ default: false,
57
+ },
58
+ options: {
59
+ type: Object,
60
+ default: () => ({ menu: {}, btn: {}, list: {} }),
61
+ },
62
+ })
63
+
64
+ const emit = defineEmits(['update:modelValue', 'logout'])
65
+ const slots = useSlots()
66
+ const { smAndDown } = useDisplay()
67
+
68
+ const isOpen = ref(false)
69
+ const selectedItem = ref<Record<string, unknown> | string | null>(props.modelValue as Record<string, unknown> | string | null)
70
+ const toggleMenu = () => {
71
+ isOpen.value = !isOpen.value
72
+ }
73
+
74
+ const buttonRef = ref<HTMLElement | null>(null)
75
+ const buttonWidth = ref('')
76
+
77
+ onMounted(() => {
78
+ if (buttonRef.value && !isMobileVersion.value) {
79
+ buttonWidth.value = `${buttonRef.value.getBoundingClientRect().width}px`
80
+ }
81
+ })
82
+
83
+ const selectItem = (item: unknown) => {
84
+ selectedItem.value = item as string | Record<string, unknown> | null
85
+ emit('update:modelValue', item)
86
+ isOpen.value = false
87
+ }
88
+
89
+ const getItemText = (item: unknown) => {
90
+ return (item as Record<string, unknown>)[props.textKey]
91
+ }
92
+
93
+ const formattedItems = computed(() => {
94
+ return props.menuItems.map((item) => {
95
+ if (typeof item === 'string') {
96
+ return { [props.textKey]: item, [props.valueKey]: item }
97
+ }
98
+ return item
99
+ })
100
+ })
101
+
102
+ const btnPadding = computed(() => {
103
+ if (props.hideIcon) {
104
+ return 'pa-1 pa-sm-2'
105
+ }
106
+ return isMobileVersion.value ? 'pa-0' : 'pa-1 pa-sm-3'
107
+ })
108
+
109
+ const hasListContent = computed(() => {
110
+ return Boolean(slots.default || !props.hideLogoutBtn)
111
+ })
112
+
113
+ const isMobileVersion = computed(() => {
114
+ return props.isMobileView || smAndDown.value || props.iconOnly
115
+ })
116
+
117
+ watch(() => props.modelValue, (newValue) => {
118
+ selectedItem.value = newValue
119
+ })
120
+
121
+ const generatedId = ref(`custom-btn-select-${Math.random().toString(36).substring(7)}`)
122
+
123
+ defineExpose({
124
+ isOpen,
125
+ formattedItems,
126
+ selectedItem,
127
+ })
128
+ </script>
129
+
130
+ <template>
131
+ <div
132
+ ref="buttonRef"
133
+ class="vd-user-menu-btn-ctn d-inline-block"
134
+ >
135
+ <VMenu
136
+ :id="generatedId"
137
+ :disabled="!hasListContent"
138
+ location="bottom end"
139
+ transition="fade-transition"
140
+ v-bind="props.options['menu']"
141
+ z-index="9999"
142
+ >
143
+ <template #activator="{ props: menuProps }">
144
+ <VBtn
145
+ :id="generatedId"
146
+ :class="btnPadding"
147
+ :height="iconOnly ? 'auto' : undefined"
148
+ :width="iconOnly ? 'auto' : undefined"
149
+ :icon="iconOnly"
150
+ :size="iconOnly ? 'x-large' : 'default'"
151
+ class="vd-user-menu-btn"
152
+ v-bind="{
153
+ ...menuProps,
154
+ ...props.options['btn'],
155
+ }"
156
+ @click="toggleMenu"
157
+ >
158
+ <div
159
+ :class="['text-'+props?.options['btn']?.color]"
160
+ class="d-flex align-center"
161
+ >
162
+ <slot name="prepend-icon" />
163
+ <span class="d-sr-only">{{ props.label }}</span>
164
+ <span
165
+ v-if="!isMobileVersion && !iconOnly"
166
+ class="d-flex flex-column align-end py-1 mr-1"
167
+ >
168
+ <span
169
+ :class="`text-${props?.options['btn']?.textColor}`"
170
+ class="font-weight-bold"
171
+ >{{ props.primaryInfo }}
172
+ </span>
173
+ <span
174
+ :class="`text-${props?.options['btn']?.textColor}`"
175
+ class="text-grey text-darken-2 font-weight-medium"
176
+ >{{ props.secondaryInfo }}
177
+ </span>
178
+ </span>
179
+ <span
180
+ v-if="isMobileVersion && !iconOnly"
181
+ :class="`text-${props?.options['btn']?.textColor}`"
182
+ class="font-weight-bold text-caption"
183
+ >{{ props.primaryInfo }}</span>
184
+ <slot name="append-icon" />
185
+ </div>
186
+ </VBtn>
187
+ </template>
188
+ <slot name="content">
189
+ <VList
190
+ v-if="hasListContent"
191
+ v-bind="props.options['list']"
192
+ >
193
+ <VListItem
194
+ v-for="(item, index) in formattedItems"
195
+ :key="index"
196
+ :class="`text-${props?.options['list']?.textColor}`"
197
+ v-bind="props.options['list']"
198
+ @click="selectItem(item)"
199
+ >
200
+ <VListItemTitle v-bind="props.options['list']">
201
+ {{ getItemText(item) }}
202
+ </VListItemTitle>
203
+ </VListItem>
204
+ <slot />
205
+ <slot name="footer-list-item" />
206
+ </VList>
207
+ </slot>
208
+ </VMenu>
209
+ </div>
210
+ </template>
211
+
212
+ <style lang="scss" scoped>
213
+ @use '@/assets/tokens.scss';
214
+
215
+ .vd-user-menu-btn-ctn {
216
+ position: relative;
217
+ z-index: 1;
218
+
219
+ .v-btn.v-btn--density-default {
220
+ height: auto !important;
221
+ }
222
+ }
223
+
224
+ .vd-user-menu-btn {
225
+ outline: none;
226
+ padding: 12px !important;
227
+
228
+ &:hover:before {
229
+ background: #000;
230
+ opacity: 0.05;
231
+ }
232
+
233
+ &:focus:before {
234
+ background: tokens.$blue-base;
235
+ opacity: 0.08;
236
+ }
237
+
238
+ &:focus {
239
+ background: rgba(tokens.$blue-base, 0.08) !important;
240
+ }
241
+ }
242
+
243
+ :deep(.vd-user-menu-btn:focus > .v-btn__overlay) {
244
+ opacity: 0 !important;
245
+ }
246
+ </style>
@@ -0,0 +1,168 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import SyBtnSelect from '../SyBtnSelect.vue'
4
+ import { vuetify } from '@tests/unit/setup'
5
+
6
+ describe('SyBtnSelect', () => {
7
+ it('renders the component with default props', () => {
8
+ const wrapper = mount(SyBtnSelect, {
9
+ global: {
10
+ plugins: [vuetify],
11
+ },
12
+ props: {
13
+ primaryInfo: 'John Doe',
14
+ },
15
+ })
16
+
17
+ expect(wrapper.exists()).toBe(true)
18
+ expect(wrapper.text()).toContain('John Doe')
19
+ })
20
+
21
+ it('shows secondaryInfo if provided', () => {
22
+ const wrapper = mount(SyBtnSelect, {
23
+ global: {
24
+ plugins: [vuetify],
25
+ },
26
+ props: {
27
+ primaryInfo: 'John Doe',
28
+ secondaryInfo: 'Additional Info',
29
+ },
30
+ })
31
+
32
+ expect(wrapper.text()).toContain('Additional Info')
33
+ })
34
+
35
+ it('emits "update:modelValue" when an item is selected', async () => {
36
+ const wrapper = mount(SyBtnSelect, {
37
+ global: {
38
+ plugins: [vuetify],
39
+ },
40
+ props: {
41
+ modelValue: null,
42
+ menuItems: [
43
+ { text: 'Option 1', value: 'option1' },
44
+ { text: 'Option 2', value: 'option2' },
45
+ ],
46
+ primaryInfo: 'John Doe',
47
+ },
48
+ })
49
+
50
+ const button = wrapper.find('.vd-user-menu-btn')
51
+ await button.trigger('click')
52
+
53
+ expect(wrapper.vm.isOpen).toBe(true)
54
+
55
+ const listItem = wrapper.findAllComponents({ name: 'VListItem' }).at(0)
56
+ expect(listItem).toBeTruthy()
57
+ await listItem?.trigger('click')
58
+
59
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy()
60
+ expect(wrapper.emitted('update:modelValue')![0]).toEqual([
61
+ { text: 'Option 1', value: 'option1' },
62
+ ])
63
+ })
64
+
65
+ it('toggles the menu open and closed', async () => {
66
+ const wrapper = mount(SyBtnSelect, {
67
+ global: {
68
+ plugins: [vuetify],
69
+ },
70
+ props: {
71
+ primaryInfo: 'John Doe',
72
+ },
73
+ })
74
+
75
+ const button = wrapper.find('.vd-user-menu-btn')
76
+ expect(wrapper.vm.isOpen).toBe(false)
77
+
78
+ await button.trigger('click')
79
+ expect(wrapper.vm.isOpen).toBe(true)
80
+
81
+ await button.trigger('click')
82
+ expect(wrapper.vm.isOpen).toBe(false)
83
+ })
84
+
85
+ it('formats menu items correctly', () => {
86
+ const wrapper = mount(SyBtnSelect, {
87
+ global: {
88
+ plugins: [vuetify],
89
+ },
90
+ props: {
91
+ primaryInfo: 'John Doe',
92
+ menuItems: ['Option 1', 'Option 2'],
93
+ },
94
+ })
95
+
96
+ const formattedItems = wrapper.vm.formattedItems
97
+ expect(formattedItems).toEqual([
98
+ { text: 'Option 1', value: 'Option 1' },
99
+ { text: 'Option 2', value: 'Option 2' },
100
+ ])
101
+ })
102
+
103
+ it('updates selectedItem when modelValue changes', async () => {
104
+ const wrapper = mount(SyBtnSelect, {
105
+ global: {
106
+ plugins: [vuetify],
107
+ },
108
+ props: {
109
+ modelValue: 'initial-value',
110
+ primaryInfo: 'John Doe',
111
+ },
112
+ })
113
+
114
+ expect(wrapper.vm.selectedItem).toBe('initial-value')
115
+
116
+ await wrapper.setProps({ modelValue: 'new-value' })
117
+ expect(wrapper.vm.selectedItem).toBe('new-value')
118
+ })
119
+
120
+ it('renders the primaryInfo in a span when isMobileVersion and hideIcon are true', async () => {
121
+ const wrapper = mount(SyBtnSelect, {
122
+ global: {
123
+ plugins: [vuetify],
124
+ },
125
+ props: {
126
+ primaryInfo: 'John Doe',
127
+ isMobileView: true,
128
+ hideIcon: true,
129
+ },
130
+ })
131
+
132
+ const span = wrapper.find('span.font-weight-bold.text-caption')
133
+
134
+ expect(span.text()).toBe('John Doe')
135
+ })
136
+
137
+ it('does not render the span if isMobileVersion is false', () => {
138
+ const wrapper = mount(SyBtnSelect, {
139
+ global: {
140
+ plugins: [vuetify],
141
+ },
142
+ props: {
143
+ primaryInfo: 'John Doe',
144
+ isMobileView: false,
145
+ hideIcon: true,
146
+ },
147
+ })
148
+
149
+ const span = wrapper.find('span.font-weight-bold.text-sm-caption')
150
+ expect(span.exists()).toBe(false)
151
+ })
152
+
153
+ it('does not render the span if hideIcon is false', () => {
154
+ const wrapper = mount(SyBtnSelect, {
155
+ global: {
156
+ plugins: [vuetify],
157
+ },
158
+ props: {
159
+ primaryInfo: 'John Doe',
160
+ isMobileView: true,
161
+ hideIcon: false,
162
+ },
163
+ })
164
+
165
+ const span = wrapper.find('span.font-weight-bold.text-sm-caption')
166
+ expect(span.exists()).toBe(false)
167
+ })
168
+ })
@@ -0,0 +1,40 @@
1
+ import { Canvas, Meta, Controls, Story, Source } from '@storybook/blocks';
2
+ import * as SyInputSelectStories from "./SyInputSelect.stories";
3
+
4
+ <Meta of={SyInputSelectStories} />
5
+
6
+ # SyInputSelect
7
+
8
+ Le composant `SyInputSelect` est utilisé pour proposer une alternative au `v-select` de Vuetify qui ne respecte pas les règles RGAA.
9
+
10
+ <Canvas of={SyInputSelectStories.Default} />
11
+
12
+ <Story of={SyInputSelectStories.Info} />
13
+
14
+ # API
15
+
16
+ <Controls of={SyInputSelectStories.Default} />
17
+
18
+ # Exemple d'utilisation
19
+
20
+ <Source dark code={`
21
+ <script setup lang="ts">
22
+ import SyInputSelect from '@cnamts/synapse'
23
+
24
+ const items = [
25
+ { text: 'Option 1', value: '1' },
26
+ { text: 'Option 2', value: '2' },
27
+ ],
28
+ </script>
29
+
30
+ <template>
31
+ <main>
32
+ <div class="mt-12 ml-12">
33
+ <SyInputSelect
34
+ v-model="value"
35
+ :items="items"
36
+ />
37
+ </div>
38
+ </main>
39
+ </template>
40
+ `} />
@@ -1,15 +1,15 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
- import CustomInputSelect from './CustomInputSelect.vue'
2
+ import SyInputSelect from './SyInputSelect.vue'
3
3
  import { VBtn, VMenu, VList, VListItem, VListItemTitle } from 'vuetify/components'
4
4
  import { ref } from 'vue'
5
5
  import Alert from '../../Alert/Alert.vue'
6
6
 
7
7
  const meta = {
8
- title: 'Composants/Formulaires/CustomInputSelect',
9
- component: CustomInputSelect,
8
+ title: 'Composants/Formulaires/SyInputSelect',
9
+ component: SyInputSelect,
10
10
  parameters: {
11
11
  layout: 'fullscreen',
12
- controls: { exclude: ['selectedValue'] },
12
+ controls: { exclude: ['selectedValue', 'isOpen', 'toggleMenu', 'closeList', 'selectItem', 'selectedItem', 'getItemText'] },
13
13
  },
14
14
  argTypes: {
15
15
  selectedValue: { control: 'text' },
@@ -20,7 +20,7 @@ const meta = {
20
20
  valueKey: { control: 'text' },
21
21
  vuetifyOptions: { control: 'object' },
22
22
  },
23
- } as Meta<typeof CustomInputSelect>
23
+ } as Meta<typeof SyInputSelect>
24
24
 
25
25
  export default meta
26
26
 
@@ -32,7 +32,7 @@ export const Default: Story = {
32
32
  name: 'Template',
33
33
  code: `
34
34
  <template>
35
- <CustomInputSelect
35
+ <SyInputSelect
36
36
  v-model="value"
37
37
  :items="items"
38
38
  />
@@ -43,7 +43,7 @@ export const Default: Story = {
43
43
  name: 'Script',
44
44
  code: `
45
45
  <script setup lang="ts">
46
- import CustomInputSelect from '@cnamts/CustomInputSelect'
46
+ import SyInputSelect from '@cnamts/SyInputSelect'
47
47
 
48
48
  const items = [
49
49
  { text: 'Option 1', value: '1' },
@@ -70,13 +70,13 @@ export const Default: Story = {
70
70
  },
71
71
  render: (args) => {
72
72
  return {
73
- components: { CustomInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
73
+ components: { SyInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
74
74
  setup() {
75
75
  return { args }
76
76
  },
77
77
  template: `
78
78
  <div class="d-flex flex-wrap align-center pa-4">
79
- <CustomInputSelect
79
+ <SyInputSelect
80
80
  v-bind="args"
81
81
  :vuetify-options="args.vuetifyOptions"
82
82
  />
@@ -94,7 +94,7 @@ export const Outlined: Story = {
94
94
  name: 'Template',
95
95
  code: `
96
96
  <template>
97
- <CustomInputSelect
97
+ <SyInputSelect
98
98
  v-model="value"
99
99
  :items="items"
100
100
  outlined
@@ -106,7 +106,7 @@ export const Outlined: Story = {
106
106
  name: 'Script',
107
107
  code: `
108
108
  <script setup lang="ts">
109
- import CustomInputSelect from '@cnamts/CustomInputSelect'
109
+ import SyInputSelect from '@cnamts/SyInputSelect'
110
110
 
111
111
  const items = [
112
112
  { text: 'Option 1', value: '1' },
@@ -125,13 +125,13 @@ export const Outlined: Story = {
125
125
  },
126
126
  render: (args) => {
127
127
  return {
128
- components: { CustomInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
128
+ components: { SyInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
129
129
  setup() {
130
130
  return { args }
131
131
  },
132
132
  template: `
133
133
  <div class="d-flex flex-wrap align-center pa-4">
134
- <CustomInputSelect
134
+ <SyInputSelect
135
135
  v-bind="args"
136
136
  outlined
137
137
  />
@@ -148,7 +148,7 @@ export const Required: Story = {
148
148
  name: 'Template',
149
149
  code: `
150
150
  <template>
151
- <CustomInputSelect
151
+ <SyInputSelect
152
152
  v-model="value"
153
153
  :items="items"
154
154
  required
@@ -160,7 +160,7 @@ export const Required: Story = {
160
160
  name: 'Script',
161
161
  code: `
162
162
  <script setup lang="ts">
163
- import CustomInputSelect from '@cnamts/CustomInputSelect'
163
+ import SyInputSelect from '@cnamts/SyInputSelect'
164
164
 
165
165
  const items = [
166
166
  { text: 'Option 1', value: '1' },
@@ -180,13 +180,13 @@ export const Required: Story = {
180
180
  },
181
181
  render: (args) => {
182
182
  return {
183
- components: { CustomInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
183
+ components: { SyInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
184
184
  setup() {
185
185
  return { args }
186
186
  },
187
187
  template: `
188
188
  <div class="d-flex flex-wrap align-center pa-4">
189
- <CustomInputSelect
189
+ <SyInputSelect
190
190
  v-bind="args"
191
191
  :required="args.required"
192
192
  />
@@ -203,7 +203,7 @@ export const withCustomError: Story = {
203
203
  name: 'Template',
204
204
  code: `
205
205
  <template>
206
- <CustomInputSelect
206
+ <SyInputSelect
207
207
  v-model="value"
208
208
  :items="items"
209
209
  :error-messages="errorMessages"
@@ -218,7 +218,7 @@ export const withCustomError: Story = {
218
218
  name: 'Script',
219
219
  code: `
220
220
  <script setup lang="ts">
221
- import CustomInputSelect from '@cnamts/CustomInputSelect'
221
+ import SyInputSelect from '@cnamts/SyInputSelect'
222
222
  import { ref } from 'vue'
223
223
 
224
224
  const items = [
@@ -244,7 +244,7 @@ export const withCustomError: Story = {
244
244
  },
245
245
  render: (args) => {
246
246
  return {
247
- components: { CustomInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
247
+ components: { SyInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
248
248
  setup() {
249
249
  const errorMessages = ref([])
250
250
  const triggerError = () => {
@@ -255,7 +255,7 @@ export const withCustomError: Story = {
255
255
  },
256
256
  template: `
257
257
  <div class="d-flex flex-wrap align-center pa-4">
258
- <CustomInputSelect
258
+ <SyInputSelect
259
259
  v-bind="args"
260
260
  :error-messages="errorMessages"
261
261
  />
@@ -275,7 +275,7 @@ export const withCustomKey: Story = {
275
275
  name: 'Template',
276
276
  code: `
277
277
  <template>
278
- <CustomInputSelect
278
+ <SyInputSelect
279
279
  v-model="value"
280
280
  :items="items"
281
281
  text-key="customKey"
@@ -288,7 +288,7 @@ export const withCustomKey: Story = {
288
288
  name: 'Script',
289
289
  code: `
290
290
  <script setup lang="ts">
291
- import CustomInputSelect from '@cnamts/CustomInputSelect'
291
+ import SyInputSelect from '@cnamts/SyInputSelect'
292
292
 
293
293
  const items = [
294
294
  { customKey: 'Choix 1', value: '1' },
@@ -307,13 +307,13 @@ export const withCustomKey: Story = {
307
307
  },
308
308
  render: (args) => {
309
309
  return {
310
- components: { CustomInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
310
+ components: { SyInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
311
311
  setup() {
312
312
  return { args }
313
313
  },
314
314
  template: `
315
315
  <div class="d-flex flex-wrap align-center pa-4">
316
- <CustomInputSelect
316
+ <SyInputSelect
317
317
  v-bind="args"
318
318
  outlined
319
319
  text-key="customKey"
@@ -331,7 +331,7 @@ export const withCustomStyles: Story = {
331
331
  name: 'Template',
332
332
  code: `
333
333
  <template>
334
- <CustomInputSelect
334
+ <SyInputSelect
335
335
  v-model="value"
336
336
  :items="items"
337
337
  :vuetify-options="vuetifyOptions
@@ -343,7 +343,7 @@ export const withCustomStyles: Story = {
343
343
  name: 'Script',
344
344
  code: `
345
345
  <script setup lang="ts">
346
- import CustomInputSelect from '@cnamts/CustomInputSelect'
346
+ import SyInputSelect from '@cnamts/SyInputSelect'
347
347
 
348
348
  const items = [
349
349
  { text: 'Option 1', value: '1' },
@@ -379,13 +379,13 @@ export const withCustomStyles: Story = {
379
379
  },
380
380
  render: (args) => {
381
381
  return {
382
- components: { CustomInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
382
+ components: { SyInputSelect, VBtn, VMenu, VList, VListItem, VListItemTitle },
383
383
  setup() {
384
384
  return { args }
385
385
  },
386
386
  template: `
387
387
  <div class="d-flex flex-wrap align-center pa-4">
388
- <CustomInputSelect
388
+ <SyInputSelect
389
389
  v-bind="args"
390
390
  :items="args.items"
391
391
  :vuetify-options="args.vuetifyOptions"