@cnamts/synapse 0.0.8-alpha → 0.0.10-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 (156) hide show
  1. package/dist/design-system-v3.d.ts +1152 -127
  2. package/dist/design-system-v3.js +4888 -2605
  3. package/dist/design-system-v3.umd.cjs +1 -1
  4. package/dist/style.css +1 -1
  5. package/package.json +1 -1
  6. package/src/assets/settings.scss +1 -1
  7. package/src/components/ContextualMenu/Accessibilite.mdx +14 -0
  8. package/src/components/ContextualMenu/Accessibilite.stories.ts +191 -0
  9. package/src/components/ContextualMenu/AccessibiliteItems.ts +89 -0
  10. package/src/components/ContextualMenu/constants/ExpertiseLevelEnum.ts +4 -0
  11. package/src/components/Customs/SySelect/SySelect.stories.ts +7 -7
  12. package/src/components/Customs/SySelect/SySelect.vue +9 -4
  13. package/src/components/Customs/SySelect/tests/SySelect.spec.ts +2 -2
  14. package/src/components/Customs/SyTextField/SyTextField.stories.ts +187 -2
  15. package/src/components/Customs/SyTextField/SyTextField.vue +185 -16
  16. package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +2 -4
  17. package/src/components/Customs/SyTextField/tests/__snapshots__/SyTextField.spec.ts.snap +18 -16
  18. package/src/components/Customs/SyTextField/types.d.ts +2 -2
  19. package/src/components/DatePicker/Accessibilite.mdx +14 -0
  20. package/src/components/DatePicker/Accessibilite.stories.ts +191 -0
  21. package/src/components/DatePicker/AccessibiliteItems.ts +233 -0
  22. package/src/components/DatePicker/DatePicker.mdx +186 -0
  23. package/src/components/DatePicker/DatePicker.stories.ts +787 -0
  24. package/src/components/DatePicker/DatePicker.vue +574 -0
  25. package/src/components/DatePicker/DateTextInput.vue +409 -0
  26. package/src/components/DatePicker/constants/ExpertiseLevelEnum.ts +4 -0
  27. package/src/components/DatePicker/tests/DatePicker.spec.ts +266 -0
  28. package/src/components/DialogBox/DialogBox.stories.ts +1 -1
  29. package/src/components/ExternalLinks/Accessibilite.mdx +14 -0
  30. package/src/components/ExternalLinks/Accessibilite.stories.ts +191 -0
  31. package/src/components/ExternalLinks/AccessibiliteItems.ts +197 -0
  32. package/src/components/ExternalLinks/constants/ExpertiseLevelEnum.ts +4 -0
  33. package/src/components/ExternalLinks/tests/__snapshots__/ExternalLinks.spec.ts.snap +9 -9
  34. package/src/components/FileList/FileList.mdx +103 -0
  35. package/src/components/FileList/FileList.stories.ts +562 -0
  36. package/src/components/FileList/FileList.vue +78 -0
  37. package/src/components/FileList/UploadItem/UploadItem.vue +270 -0
  38. package/src/components/FileList/UploadItem/locales.ts +9 -0
  39. package/src/components/FileList/tests/FileList.spec.ts +176 -0
  40. package/src/components/FilePreview/FilePreview.mdx +82 -0
  41. package/src/components/FilePreview/FilePreview.stories.ts +242 -0
  42. package/src/components/FilePreview/FilePreview.vue +68 -0
  43. package/src/components/FilePreview/config.ts +10 -0
  44. package/src/components/FilePreview/locales.ts +4 -0
  45. package/src/components/FilePreview/tests/FilePreview.spec.ts +124 -0
  46. package/src/components/FilePreview/tests/__snapshots__/FilePreview.spec.ts.snap +11 -0
  47. package/src/components/FileUpload/FileUpload.mdx +165 -0
  48. package/src/components/FileUpload/FileUpload.stories.ts +429 -0
  49. package/src/components/FileUpload/FileUpload.vue +195 -0
  50. package/src/components/FileUpload/FileUploadContent.vue +109 -0
  51. package/src/components/FileUpload/locales.ts +10 -0
  52. package/src/components/FileUpload/tests/FileUpload.spec.ts +332 -0
  53. package/src/components/FileUpload/tests/__snapshots__/FileUpload.spec.ts.snap +7 -0
  54. package/src/components/FileUpload/useFileDrop.ts +23 -0
  55. package/src/components/FileUpload/validateFiles.ts +39 -0
  56. package/src/components/NirField/NirField.stories.ts +1 -1
  57. package/src/components/NirField/NirField.vue +2 -1
  58. package/src/components/PasswordField/Accessibilite.mdx +14 -0
  59. package/src/components/PasswordField/Accessibilite.stories.ts +191 -0
  60. package/src/components/PasswordField/AccessibiliteItems.ts +184 -0
  61. package/src/components/PasswordField/PasswordField.vue +3 -3
  62. package/src/components/PasswordField/constants/ExpertiseLevelEnum.ts +4 -0
  63. package/src/components/PeriodField/PeriodField.mdx +32 -0
  64. package/src/components/PeriodField/PeriodField.stories.ts +807 -0
  65. package/src/components/PeriodField/PeriodField.vue +355 -0
  66. package/src/components/PeriodField/tests/PeriodField.spec.ts +348 -0
  67. package/src/components/PhoneField/PhoneField.vue +44 -60
  68. package/src/components/PhoneField/tests/PhoneField.spec.ts +0 -15
  69. package/src/components/RangeField/Accessibilite.mdx +14 -0
  70. package/src/components/RangeField/Accessibilite.stories.ts +191 -0
  71. package/src/components/RangeField/AccessibiliteItems.ts +179 -0
  72. package/src/components/RangeField/RangeField.mdx +54 -0
  73. package/src/components/RangeField/RangeField.stories.ts +189 -0
  74. package/src/components/RangeField/RangeField.vue +157 -0
  75. package/src/components/RangeField/RangeSlider/RangeSlider.vue +387 -0
  76. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +64 -0
  77. package/src/components/RangeField/RangeSlider/tests/__snapshots__/rangeSlider.spec.ts.snap +27 -0
  78. package/src/components/RangeField/RangeSlider/tests/rangeSlider.spec.ts +100 -0
  79. package/src/components/RangeField/RangeSlider/tests/useDoubleSlider.spec.ts +246 -0
  80. package/src/components/RangeField/RangeSlider/tests/useMouseSlide.spec.ts +204 -0
  81. package/src/components/RangeField/RangeSlider/tests/useThumb.spec.ts +22 -0
  82. package/src/components/RangeField/RangeSlider/tests/useThumbKeyboard.spec.ts +233 -0
  83. package/src/components/RangeField/RangeSlider/tests/useTooltipsNudge.spec.ts +150 -0
  84. package/src/components/RangeField/RangeSlider/tests/useTrack.spec.ts +314 -0
  85. package/src/components/RangeField/RangeSlider/tests/vAnimateClick.spec.ts +32 -0
  86. package/src/components/RangeField/RangeSlider/types.ts +15 -0
  87. package/src/components/RangeField/RangeSlider/useMouseSlide.ts +109 -0
  88. package/src/components/RangeField/RangeSlider/useRangeSlider.ts +126 -0
  89. package/src/components/RangeField/RangeSlider/useThumb.ts +18 -0
  90. package/src/components/RangeField/RangeSlider/useThumbKeyboard.ts +84 -0
  91. package/src/components/RangeField/RangeSlider/useTooltipsNudge.ts +92 -0
  92. package/src/components/RangeField/RangeSlider/useTrack.ts +116 -0
  93. package/src/components/RangeField/RangeSlider/vAnimateClick.ts +19 -0
  94. package/src/components/RangeField/config.ts +7 -0
  95. package/src/components/RangeField/constants/ExpertiseLevelEnum.ts +4 -0
  96. package/src/components/RangeField/locales.ts +4 -0
  97. package/src/components/RangeField/tests/RangeField.spec.ts +224 -0
  98. package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +379 -0
  99. package/src/components/RatingPicker/Accessibilite.mdx +14 -0
  100. package/src/components/RatingPicker/Accessibilite.stories.ts +191 -0
  101. package/src/components/RatingPicker/AccessibiliteItems.ts +208 -0
  102. package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +205 -0
  103. package/src/components/RatingPicker/EmotionPicker/locales.ts +3 -0
  104. package/src/components/RatingPicker/EmotionPicker/tests/EmotionPicker.spec.ts +104 -0
  105. package/src/components/RatingPicker/EmotionPicker/tests/__snapshots__/EmotionPicker.spec.ts.snap +66 -0
  106. package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +159 -0
  107. package/src/components/RatingPicker/NumberPicker/locales.ts +4 -0
  108. package/src/components/RatingPicker/NumberPicker/tests/NumberPicker.spec.ts +73 -0
  109. package/src/components/RatingPicker/NumberPicker/tests/__snapshots__/NumberPicker.spec.ts.snap +105 -0
  110. package/src/components/RatingPicker/Rating.ts +45 -0
  111. package/src/components/RatingPicker/RatingPicker.mdx +56 -0
  112. package/src/components/RatingPicker/RatingPicker.stories.ts +515 -0
  113. package/src/components/RatingPicker/RatingPicker.vue +122 -0
  114. package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +116 -0
  115. package/src/components/RatingPicker/StarsPicker/tests/StarsPicker.spec.ts +95 -0
  116. package/src/components/RatingPicker/StarsPicker/tests/__snapshots__/StarsPicker.spec.ts.snap +36 -0
  117. package/src/components/RatingPicker/constants/ExpertiseLevelEnum.ts +4 -0
  118. package/src/components/RatingPicker/locales.ts +3 -0
  119. package/src/components/RatingPicker/tests/Rating.spec.ts +104 -0
  120. package/src/components/RatingPicker/tests/RatingPicker.spec.ts +187 -0
  121. package/src/components/RatingPicker/tests/__snapshots__/RatingPicker.spec.ts.snap +108 -0
  122. package/src/components/SearchListField/Accessibilite.mdx +14 -0
  123. package/src/components/SearchListField/Accessibilite.stories.ts +191 -0
  124. package/src/components/SearchListField/AccessibiliteItems.ts +310 -0
  125. package/src/components/SearchListField/SearchListField.mdx +74 -0
  126. package/src/components/SearchListField/SearchListField.stories.ts +126 -0
  127. package/src/components/SearchListField/SearchListField.vue +194 -0
  128. package/src/components/SearchListField/constants/ExpertiseLevelEnum.ts +4 -0
  129. package/src/components/SearchListField/locales.ts +5 -0
  130. package/src/components/SearchListField/tests/SearchListField.spec.ts +323 -0
  131. package/src/components/SearchListField/types.d.ts +4 -0
  132. package/src/components/SelectBtnField/Accessibilite.mdx +14 -0
  133. package/src/components/SelectBtnField/Accessibilite.stories.ts +191 -0
  134. package/src/components/SelectBtnField/AccessibiliteItems.ts +191 -0
  135. package/src/components/SelectBtnField/SelectBtnField.mdx +50 -0
  136. package/src/components/SelectBtnField/SelectBtnField.stories.ts +763 -0
  137. package/src/components/SelectBtnField/SelectBtnField.vue +283 -0
  138. package/src/components/SelectBtnField/config.ts +11 -0
  139. package/src/components/SelectBtnField/constants/ExpertiseLevelEnum.ts +4 -0
  140. package/src/components/SelectBtnField/tests/SelectBtnField.spec.ts +327 -0
  141. package/src/components/SelectBtnField/tests/__snapshots__/SelectBtnField.spec.ts.snap +125 -0
  142. package/src/components/SelectBtnField/types.d.ts +11 -0
  143. package/src/components/SyAlert/SyAlert.vue +11 -9
  144. package/src/components/TableToolbar/TableToolbar.mdx +130 -0
  145. package/src/components/TableToolbar/TableToolbar.stories.ts +935 -0
  146. package/src/components/TableToolbar/TableToolbar.vue +168 -0
  147. package/src/components/TableToolbar/config.ts +24 -0
  148. package/src/components/TableToolbar/locales.ts +6 -0
  149. package/src/components/TableToolbar/tests/TableToolbar.spec.ts +166 -0
  150. package/src/components/TableToolbar/tests/__snapshots__/TableToolbar.spec.ts.snap +359 -0
  151. package/src/components/index.ts +11 -1
  152. package/src/composables/rules/useFieldValidation.ts +174 -44
  153. package/src/designTokens/index.ts +3 -3
  154. package/src/stories/Fondamentaux/CustomisationEtThemes.mdx +52 -2
  155. package/src/utils/calcHumanFileSize/index.ts +12 -0
  156. package/src/utils/calcHumanFileSize/tests/calcHumanFileSize.spec.ts +21 -0
@@ -0,0 +1,270 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ mdiFile,
4
+ mdiTrayArrowUp,
5
+ mdiDeleteOutline,
6
+ mdiEyeOutline,
7
+ mdiAlertCircle,
8
+ mdiCheckCircle,
9
+ } from '@mdi/js'
10
+ import { cnamContextualTokens } from '@/designTokens/tokens/cnam/cnamContextual'
11
+ import { locales as defaultLocales } from './locales'
12
+
13
+ type FileState = 'initial' | 'success' | 'error' | 'loading'
14
+
15
+ defineEmits<{
16
+ (e: 'upload', item: string): void
17
+ (e: 'preview', item: string): void
18
+ (e: 'delete', item: string): void
19
+ }>()
20
+
21
+ withDefaults(defineProps<{
22
+ itemId: string
23
+ title: string
24
+ fileName?: string
25
+ message?: string
26
+ optional?: boolean
27
+ state?: FileState
28
+ progress?: number
29
+ showUploadBtn?: boolean
30
+ showDeleteBtn?: boolean
31
+ showPreviewBtn?: boolean
32
+ tag?: string
33
+ locales?: typeof defaultLocales
34
+ }>(), {
35
+ fileName: undefined,
36
+ message: undefined,
37
+ optional: false,
38
+ state: 'initial',
39
+ progress: undefined,
40
+ showUploadBtn: true,
41
+ showDeleteBtn: true,
42
+ showPreviewBtn: false,
43
+ tag: 'div',
44
+ locales: () => defaultLocales,
45
+ })
46
+
47
+ defineSlots<{
48
+ 'file-icon'(props: { state: FileState }): void
49
+ }>()
50
+
51
+ </script>
52
+
53
+ <template>
54
+ <component
55
+ :is="tag"
56
+ class="file-item"
57
+ >
58
+ <div class="file-item__description">
59
+ <div class="file-item__content">
60
+ <span
61
+ class="file-item__icon"
62
+ >
63
+ <slot
64
+ name="file-icon"
65
+ :state
66
+ >
67
+ <span
68
+ v-if="state === 'success'"
69
+ class="d-sr-only"
70
+ >
71
+ {{ locales.success }}
72
+ </span>
73
+
74
+ <span
75
+ v-else-if="state === 'error'"
76
+ class="d-sr-only"
77
+ >
78
+ {{ locales.error }}
79
+ </span>
80
+
81
+ <VIcon
82
+ v-if="state === 'error'"
83
+ :size="cnamContextualTokens.iconSize.default"
84
+ :aria-label="locales.error"
85
+ color="error"
86
+ >{{ mdiAlertCircle }}</VIcon>
87
+
88
+ <VIcon
89
+ v-else-if="state === 'success'"
90
+ :size="cnamContextualTokens.iconSize.default"
91
+ :aria-label="locales.success"
92
+ color="success"
93
+ >{{ mdiCheckCircle }}</VIcon>
94
+
95
+ <VIcon
96
+ v-else
97
+ :size="cnamContextualTokens.iconSize.default"
98
+ color="primary"
99
+ >{{ mdiFile }}</VIcon>
100
+ </slot>
101
+ </span>
102
+ <div>
103
+ <div class="file-item__title">
104
+ {{ title }}
105
+ </div>
106
+ <div class="file-item__name text-base">
107
+ {{ fileName }}
108
+ </div>
109
+ <div
110
+ v-if="message || optional"
111
+ class="file-item__message text-base"
112
+ >
113
+ {{ message ?? locales.optionalDocument }}
114
+ </div>
115
+ </div>
116
+ </div>
117
+ <div class="file-item__actions">
118
+ <VBtn
119
+ v-if="(state === 'initial' || state == 'error') && showUploadBtn"
120
+ class="file-item__action file-item__action-upload text-primary"
121
+ variant="text"
122
+ @click="$emit('upload', itemId)"
123
+ >
124
+ <span>Importer</span>
125
+ <template #prepend>
126
+ <VIcon
127
+ color="primary"
128
+ >
129
+ {{ mdiTrayArrowUp }}
130
+ </VIcon>
131
+ </template>
132
+ </VBtn>
133
+ <VBtn
134
+ v-if="state === 'success' && showPreviewBtn"
135
+ class="file-item__action file-item__action-preview text-primary"
136
+ variant="text"
137
+ @click="$emit('preview', itemId)"
138
+ >
139
+ <span>{{ locales.see }}</span>
140
+ <template #prepend>
141
+ <VIcon
142
+ color="primary"
143
+ >
144
+ {{ mdiEyeOutline }}
145
+ </VIcon>
146
+ </template>
147
+ </VBtn>
148
+ <VBtn
149
+ v-if="state === 'success' && showDeleteBtn"
150
+ class="file-item__action file-item__action-delete text-error"
151
+ variant="text"
152
+ @click="$emit('delete', itemId)"
153
+ >
154
+ <span>{{ locales.delete }}</span>
155
+ <template #prepend>
156
+ <VIcon
157
+ color="error"
158
+ >
159
+ {{ mdiDeleteOutline }}
160
+ </VIcon>
161
+ </template>
162
+ </VBtn>
163
+ </div>
164
+ </div>
165
+
166
+ <div
167
+ v-if="state === 'loading'"
168
+ class="file-item__message-progress"
169
+ >
170
+ <p class="d-sr-only">
171
+ {{ locales.uploading }}
172
+ </p>
173
+ <VProgressLinear
174
+ :indeterminate="progress === undefined"
175
+ :model-value="progress"
176
+ :progress="progress"
177
+ height="7"
178
+ color="primary"
179
+ rounded="true"
180
+ />
181
+ </div>
182
+ </component>
183
+ </template>
184
+
185
+ <style lang="scss" scoped>
186
+ @use '@/assets/tokens';
187
+
188
+ .file-item {
189
+ display: flex;
190
+ flex-direction: column;
191
+ gap: tokens.$gap-3;
192
+ padding-block: tokens.$padding-4;
193
+ border-bottom: 1px solid tokens.$colors-border-subdued;
194
+ }
195
+
196
+ .file-item__title {
197
+ font-size: tokens.$font-size-body-text;
198
+ }
199
+
200
+ .file-item__name {
201
+ font-size: 0.875rem;
202
+ color: tokens.$colors-text-base;
203
+ }
204
+
205
+ .file-item__description {
206
+ display: flex;
207
+ justify-content: space-between;
208
+ align-items: center;
209
+ flex-wrap: wrap;
210
+
211
+ > * {
212
+ grid-column: 1 / -1;
213
+ }
214
+
215
+ > *:nth-child(1),
216
+ > *:nth-child(2) {
217
+ grid-column: 1 / 2;
218
+ }
219
+
220
+ > .file-item__actions {
221
+ grid-column-start: 2;
222
+ grid-row: span 2;
223
+ }
224
+ }
225
+
226
+ .file-item__content {
227
+ display: flex;
228
+ gap: tokens.$gap-4;
229
+ align-items: center;
230
+ }
231
+
232
+ .file-item__actions {
233
+ display: flex;
234
+ flex-direction: column;
235
+ align-items: end;
236
+ justify-content: center;
237
+ margin-left: auto;
238
+ height: 100%;
239
+ gap: tokens.$gap-1;
240
+
241
+ @media screen and (min-width: tokens.$container-tablet-max-width) {
242
+ flex-direction: row;
243
+ }
244
+ }
245
+
246
+ .file-item__action {
247
+ display: flex;
248
+ justify-content: end;
249
+ text-transform: unset;
250
+ padding: 0.625rem 1.25rem;
251
+ font-weight: bold;
252
+ }
253
+
254
+ .file-item__message {
255
+ font-size: 0.875rem;
256
+ color: tokens.$colors-text-subdued;
257
+ }
258
+
259
+ .file-item__message-success,
260
+ .file-item__message-error {
261
+ margin-top: tokens.$gap-3;
262
+ }
263
+
264
+ .file-item__message-error {
265
+ display: flex;
266
+ align-items: center;
267
+ gap: tokens.$gap-4;
268
+ }
269
+
270
+ </style>
@@ -0,0 +1,9 @@
1
+ export const locales = {
2
+ optionalDocument: 'Document facultatif',
3
+ see: 'Voir',
4
+ delete: 'Supprimer',
5
+ uploading: 'En cours',
6
+ success: 'Téléchargé',
7
+ error: 'Erreur',
8
+ errorOccurred: 'Une erreur est survenue pendant le téléchargement.',
9
+ }
@@ -0,0 +1,176 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import FileList from '../FileList.vue'
4
+ import { vuetify } from '@tests/unit/setup'
5
+ import { locales } from '../UploadItem/locales'
6
+
7
+ describe('FileList', () => {
8
+ it('renders many file items', () => {
9
+ const wrapper = mount(FileList, {
10
+ props: {
11
+ uploadList: [
12
+ {
13
+ id: 'residenceCertificate',
14
+ title: 'Attestation de domicile',
15
+ state: 'initial',
16
+ },
17
+ {
18
+ id: 'identityCard',
19
+ title: 'Carte d\'identité',
20
+ state: 'initial',
21
+ },
22
+ ],
23
+ },
24
+ global: {
25
+ plugins: [vuetify],
26
+ },
27
+ })
28
+ expect(wrapper.findAll('.file-item').length).toBe(2)
29
+ const item1 = wrapper.findAll('.file-item').at(0)
30
+ expect(item1!.text()).toContain('Attestation de domicile')
31
+ const item2 = wrapper.findAll('.file-item').at(1)
32
+ expect(item2!.text()).toContain('Carte d\'identité')
33
+ })
34
+
35
+ it('shows the right action for each state and item preference', async () => {
36
+ const wrapper = mount(FileList, {
37
+ props: {
38
+ uploadList: [
39
+ {
40
+ id: 'file1',
41
+ title: 'file1',
42
+ state: 'initial',
43
+ },
44
+ {
45
+ id: 'file2',
46
+ title: 'file2',
47
+ state: 'initial',
48
+ showUploadBtn: false,
49
+ },
50
+ {
51
+ id: 'file3',
52
+ title: 'file3',
53
+ state: 'success',
54
+ showDeleteBtn: true,
55
+ showPreviewBtn: true,
56
+ },
57
+ {
58
+ id: 'file4',
59
+ title: 'file4',
60
+ state: 'success',
61
+ showDeleteBtn: false,
62
+ showPreviewBtn: false,
63
+ },
64
+ {
65
+ id: 'file5',
66
+ title: 'file5',
67
+ state: 'error',
68
+ },
69
+ {
70
+ id: 'file6',
71
+ title: 'file6',
72
+ state: 'error',
73
+ showUploadBtn: false,
74
+ },
75
+ ],
76
+ },
77
+ global: {
78
+ plugins: [vuetify],
79
+ },
80
+ })
81
+
82
+ const item1 = wrapper.findAll('.file-item').at(0)
83
+ expect(item1!.findAll('button').length).toBe(1)
84
+ const item1UploadBtn = item1!.find('.file-item__action-upload')
85
+ expect(item1UploadBtn.exists()).toBe(true)
86
+
87
+ const item2 = wrapper.findAll('.file-item').at(1)
88
+ expect(item2!.findAll('button').length).toBe(0)
89
+
90
+ const item3 = wrapper.findAll('.file-item').at(2)
91
+ expect(item3!.findAll('button').length).toBe(2)
92
+ const item3DeleteBtn = item3!.find('.file-item__action-delete')
93
+ expect(item3DeleteBtn.exists()).toBe(true)
94
+ const item3PreviewBtn = item3!.find('.file-item__action-preview')
95
+ expect(item3PreviewBtn.exists()).toBe(true)
96
+
97
+ const item4 = wrapper.findAll('.file-item').at(3)
98
+ expect(item4!.findAll('button').length).toBe(0)
99
+
100
+ const item5 = wrapper.findAll('.file-item').at(4)
101
+ expect(item5!.findAll('button').length).toBe(1)
102
+ const item5UploadBtn = item5!.find('.file-item__action-upload')
103
+ expect(item5UploadBtn.exists()).toBe(true)
104
+
105
+ const item6 = wrapper.findAll('.file-item').at(5)
106
+ expect(item6!.findAll('button').length).toBe(0)
107
+ })
108
+
109
+ it('emits the right event when clicking on an action button', async () => {
110
+ const fileItem1 = {
111
+ id: 'file1',
112
+ title: 'file1',
113
+ state: 'initial',
114
+ }
115
+
116
+ const fileItem2 = {
117
+ id: 'file2',
118
+ title: 'file2',
119
+ state: 'success',
120
+ showDeleteBtn: true,
121
+ showPreviewBtn: true,
122
+ }
123
+
124
+ const wrapper = mount(FileList, {
125
+ props: {
126
+ uploadList: [fileItem1, fileItem2],
127
+ },
128
+ global: {
129
+ plugins: [vuetify],
130
+ },
131
+ })
132
+
133
+ const item1 = wrapper.findAll('.file-item').at(0)
134
+ const item1UploadBtn = item1!.find('.file-item__action-upload')
135
+ await item1UploadBtn!.trigger('click')
136
+ expect(wrapper.emitted('upload')?.[0][0]).toEqual(fileItem1)
137
+
138
+ const item2 = wrapper.findAll('.file-item').at(1)
139
+ const item2DeleteBtn = item2!.find('.file-item__action-delete')
140
+ await item2DeleteBtn!.trigger('click')
141
+ expect(wrapper.emitted('delete')?.[0][0]).toEqual(fileItem2)
142
+
143
+ const item2PreviewBtn = item2!.find('.file-item__action-preview')
144
+ await item2PreviewBtn!.trigger('click')
145
+ expect(wrapper.emitted('preview')?.[0][0]).toEqual(fileItem2)
146
+ })
147
+
148
+ it('shows when a file is optional', () => {
149
+ const wrapper = mount(FileList, {
150
+ props: {
151
+ uploadList: [
152
+ {
153
+ id: 'file1',
154
+ title: 'file1',
155
+ state: 'initial',
156
+ optional: true,
157
+ },
158
+ {
159
+ id: 'file2',
160
+ title: 'file2',
161
+ state: 'initial',
162
+ },
163
+ ],
164
+ },
165
+ global: {
166
+ plugins: [vuetify],
167
+ },
168
+ })
169
+
170
+ const item1 = wrapper.findAll('.file-item').at(0)
171
+ expect(item1!.text()).toContain(locales.optionalDocument)
172
+
173
+ const item2 = wrapper.findAll('.file-item').at(1)
174
+ expect(item2!.text()).not.toContain(locales.optionalDocument)
175
+ })
176
+ })
@@ -0,0 +1,82 @@
1
+ import {Controls, Canvas, Meta, Source} from '@storybook/blocks';
2
+
3
+ import * as FilePreviewStories from './FilePreview.stories.ts'
4
+
5
+ <Meta of={FilePreviewStories} />
6
+
7
+
8
+ # FilePreview
9
+
10
+ L'élément `FilePreview` est utilisé pour afficher l'aperçu d'un fichier.
11
+
12
+ <Canvas of={FilePreviewStories.Default} />
13
+
14
+
15
+ # API
16
+
17
+ <Controls of={FilePreviewStories.Default} />
18
+
19
+
20
+ # Exemple
21
+
22
+ ## Afficher un fichier depuis une API
23
+
24
+ Vous pouvez afficher une image ou un fichier PDF récupéré depuis une API sous forme de `Blob`.
25
+
26
+ <Canvas
27
+ of={FilePreviewStories.FromApi}
28
+ source={{
29
+ language: 'html',
30
+ format: 'dedent',
31
+ code: `
32
+ <script lang="ts" setup>
33
+ import { onMounted, ref } from 'vue'
34
+ import { FilePreview } from '@cnamts/synapse'
35
+
36
+ const file = ref<File | Blob | undefined>()
37
+
38
+ onMounted(() => {
39
+ fetch('https://picsum.photos/seed/picsum/750/350')
40
+ .then(res => res.blob())
41
+ .then(blob => file.value = blob)
42
+ })
43
+ </script>
44
+
45
+ <template>
46
+ <FilePreview :file="file" />
47
+ </template>
48
+ `,
49
+ }}
50
+ />
51
+
52
+ ## Fichier non supporté
53
+
54
+ Lorsque le fichier n'est pas supporté, un message d'erreur est affiché.
55
+
56
+ <Canvas of={FilePreviewStories.UnsupportedFile} />
57
+
58
+ ## Usage avec `FileUpload`
59
+
60
+ Vous pouvez utiliser ce composant en combinaison avec `FileUpload` pour afficher un aperçu du fichier avant de l'envoyer.
61
+
62
+ <Canvas
63
+ of={FilePreviewStories.WithFileUpload}
64
+ source={{
65
+ language: 'html',
66
+ format: 'dedent',
67
+ code: `
68
+ <script lang="ts" setup>
69
+ import { ref } from 'vue'
70
+ import { FilePreview, FileUpload } from '@cnamts/synapse'
71
+
72
+ const files = ref<File[]>([])
73
+ </script>
74
+ <template>
75
+ <div>
76
+ <FileUpload v-model="files" class="mb-4"/>
77
+ <FilePreview :file="files[0]"/>
78
+ </div>
79
+ </template>
80
+ `,
81
+ }}
82
+ />