@cnamts/synapse 0.0.14-alpha → 0.0.16-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/dist/components/CookiesSelection/CookiesSelection.d.ts +26 -26
- package/dist/components/Customs/SyInputSelect/SyInputSelect.d.ts +2 -2
- package/dist/components/Customs/SySelect/SySelect.d.ts +24 -12
- package/dist/components/Customs/SySelect/locales.d.ts +3 -0
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +1393 -3
- package/dist/components/DatePicker/DatePicker.d.ts +3532 -22
- package/dist/components/DatePicker/DateTextInput.d.ts +1408 -11
- package/dist/components/DialogBox/config.d.ts +1 -1
- package/dist/components/DownloadBtn/DownloadBtn.d.ts +2 -0
- package/dist/components/LangBtn/LangBtn.d.ts +467 -1
- package/dist/components/LangBtn/config.d.ts +1 -3
- package/dist/components/NirField/NirField.d.ts +2805 -15
- package/dist/components/PasswordField/PasswordField.d.ts +2 -2
- package/dist/components/PeriodField/PeriodField.d.ts +7345 -325
- package/dist/components/PhoneField/PhoneField.d.ts +3 -3
- package/dist/components/SelectBtnField/SelectBtnField.d.ts +1 -1
- package/dist/components/SkipLink/SkipLink.d.ts +3 -2
- package/dist/components/SyAlert/SyAlert.d.ts +72 -1
- package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +26 -26
- package/dist/components/UserMenuBtn/UserMenuBtn.d.ts +2 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/composables/date/useDateFormat.d.ts +2 -2
- package/dist/composables/date/useDateFormatDayjs.d.ts +23 -0
- package/dist/composables/date/useDateInitializationDayjs.d.ts +18 -0
- package/dist/design-system-v3.js +4314 -3987
- package/dist/design-system-v3.umd.cjs +1 -1
- package/dist/style.css +1 -1
- package/dist/vuetifyConfig.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/BackBtn/Accessibilite.stories.ts +4 -0
- package/src/components/BackBtn/BackBtn.vue +2 -1
- package/src/components/BackToTopBtn/Accessibilite.stories.ts +4 -0
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +78 -21
- package/src/components/BackToTopBtn/BackToTopBtn.vue +15 -0
- package/src/components/BackToTopBtn/config.ts +2 -2
- package/src/components/BackToTopBtn/tests/__snapshots__/BackToTopBtn.spec.ts.snap +4 -4
- package/src/components/CopyBtn/Accessibilite.stories.ts +4 -0
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.stories.ts +2 -2
- package/src/components/Customs/SyBtnSelect/SyBtnSelect.vue +0 -1
- package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +3 -3
- package/src/components/Customs/SyInputSelect/SyInputSelect.vue +4 -4
- package/src/components/Customs/SySelect/SySelect.stories.ts +4 -0
- package/src/components/Customs/SySelect/SySelect.vue +75 -10
- package/src/components/Customs/SySelect/locales.ts +3 -0
- package/src/components/Customs/SySelect/tests/SySelect.spec.ts +24 -2
- package/src/components/Customs/SyTextField/Accessibilite.stories.ts +7 -0
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +14 -1
- package/src/components/Customs/SyTextField/SyTextField.vue +85 -20
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +795 -0
- package/src/components/DatePicker/DatePicker.stories.ts +432 -1
- package/src/components/DatePicker/DatePicker.vue +143 -76
- package/src/components/DatePicker/DatePickerValidation.mdx +338 -0
- package/src/components/DatePicker/DatePickerValidation.stories.ts +30 -0
- package/src/components/DatePicker/DateTextInput.vue +87 -135
- package/src/components/DatePicker/docExamples/DatePickerBidirectionalValidation.vue +282 -0
- package/src/components/DatePicker/docExamples/DatePickerValidationExamples.vue +535 -0
- package/src/components/DatePicker/tests/DatePicker.spec.ts +33 -32
- package/src/components/DatePicker/tests/DateTextInput.spec.ts +83 -35
- package/src/components/DialogBox/DialogBox.stories.ts +5 -2
- package/src/components/DialogBox/DialogBox.vue +1 -1
- package/src/components/DialogBox/config.ts +1 -1
- package/src/components/DownloadBtn/Accessibilite.stories.ts +4 -0
- package/src/components/DownloadBtn/DownloadBtn.stories.ts +17 -8
- package/src/components/DownloadBtn/DownloadBtn.vue +13 -6
- package/src/components/DownloadBtn/tests/__snapshots__/DownloadBtn.spec.ts.snap +0 -2
- package/src/components/FranceConnectBtn/Accessibilite.stories.ts +4 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.vue +3 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.vue +3 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/menu.scss +19 -0
- package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +12 -2
- package/src/components/LangBtn/Accessibilite.stories.ts +4 -0
- package/src/components/LangBtn/LangBtn.stories.ts +1 -4
- package/src/components/LangBtn/LangBtn.vue +68 -9
- package/src/components/LangBtn/config.ts +0 -1
- package/src/components/LangBtn/tests/LangBtn.spec.ts +30 -2
- package/src/components/PageContainer/Accessibilite.stories.ts +36 -23
- package/src/components/PaginatedTable/PaginatedTable.stories.ts +144 -18
- package/src/components/PasswordField/PasswordField.stories.ts +6 -6
- package/src/components/PasswordField/PasswordField.vue +3 -3
- package/src/components/PeriodField/PeriodField.vue +4 -4
- package/src/components/PhoneField/PhoneField.stories.ts +216 -24
- package/src/components/PhoneField/PhoneField.vue +32 -2
- package/src/components/PhoneField/tests/PhoneField.spec.ts +161 -14
- package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +2 -1
- package/src/components/RatingPicker/RatingPicker.stories.ts +1 -1
- package/src/components/SkipLink/Accessibilite.stories.ts +8 -0
- package/src/components/SkipLink/SkipLink.vue +11 -9
- package/src/components/SkipLink/tests/__snapshots__/skipLink.spec.ts.snap +7 -4
- package/src/components/SkipLink/tests/skipLink.spec.ts +120 -6
- package/src/components/SyAlert/Accessibilite.stories.ts +4 -0
- package/src/components/SyAlert/SyAlert.mdx +3 -7
- package/src/components/SyAlert/SyAlert.stories.ts +19 -12
- package/src/components/SyAlert/SyAlert.vue +88 -51
- package/src/components/SyAlert/tests/SyAlert.spec.ts +20 -2
- package/src/components/SyAlert/tests/__snapshots__/SyAlert.spec.ts.snap +83 -75
- package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +56 -0
- package/src/components/UserMenuBtn/UserMenuBtn.vue +4 -2
- package/src/components/UserMenuBtn/tests/UserMenuBtn.spec.ts +41 -0
- package/src/components/index.ts +2 -0
- package/src/composables/date/useDateFormat.ts +17 -1
- package/src/composables/date/useDateFormatDayjs.ts +84 -0
- package/src/composables/date/useDateInitializationDayjs.ts +133 -0
- package/src/composables/rules/useFieldValidation.ts +26 -3
- package/src/stories/Accessibilite/Avancement/Avancement.mdx +12 -0
- package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +134 -0
- package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +1 -1
- package/src/stories/GuideDuDev/LesBreackingChanges.mdx +31 -2
- package/src/components/LangBtn/tests/Config.spec.ts +0 -24
|
@@ -38,7 +38,7 @@ describe('DateTextInput.vue', () => {
|
|
|
38
38
|
await input.trigger('blur')
|
|
39
39
|
await wrapper.vm.$nextTick()
|
|
40
40
|
const textField = wrapper.findComponent(SyTextField)
|
|
41
|
-
expect(textField.props('errorMessages')).toContain('Format de date invalide')
|
|
41
|
+
expect(textField.props('errorMessages')).toContain('Format de date invalide (DD/MM/YYYY)')
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
it('accepts valid date format', async () => {
|
|
@@ -116,20 +116,20 @@ describe('DateTextInput.vue', () => {
|
|
|
116
116
|
},
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
// Force
|
|
119
|
+
// Force validation by triggering a blur event
|
|
120
120
|
const input = wrapper.find('input')
|
|
121
121
|
await input.trigger('focus')
|
|
122
122
|
await input.trigger('blur')
|
|
123
123
|
await wrapper.vm.$nextTick()
|
|
124
|
-
await wrapper.vm.$nextTick() // Double nextTick
|
|
125
|
-
//
|
|
124
|
+
await wrapper.vm.$nextTick() // Double nextTick to ensure updates are completed
|
|
125
|
+
// We can also force validation manually
|
|
126
126
|
await wrapper.vm.validateOnSubmit()
|
|
127
127
|
await wrapper.vm.$nextTick()
|
|
128
128
|
const textField = wrapper.findComponent(SyTextField)
|
|
129
129
|
const warningMessages = textField.props('warningMessages') || []
|
|
130
|
-
//
|
|
130
|
+
// Check that the warning message is present
|
|
131
131
|
expect(warningMessages.length).toBeGreaterThan(0)
|
|
132
|
-
//
|
|
132
|
+
// The actual message starts with "Attention:"
|
|
133
133
|
expect(warningMessages[0]).toContain('Attention :')
|
|
134
134
|
})
|
|
135
135
|
|
|
@@ -139,7 +139,7 @@ describe('DateTextInput.vue', () => {
|
|
|
139
139
|
await input.trigger('blur')
|
|
140
140
|
await wrapper.vm.$nextTick()
|
|
141
141
|
const textField = wrapper.findComponent(SyTextField)
|
|
142
|
-
expect(textField.props('errorMessages')).toContain('Format de date invalide')
|
|
142
|
+
expect(textField.props('errorMessages')).toContain('Format de date invalide (DD/MM/YYYY)')
|
|
143
143
|
})
|
|
144
144
|
|
|
145
145
|
it('formats input while typing', async () => {
|
|
@@ -169,7 +169,7 @@ describe('DateTextInput.vue', () => {
|
|
|
169
169
|
const input = wrapper.find('input')
|
|
170
170
|
await input.trigger('blur')
|
|
171
171
|
await wrapper.vm.$nextTick()
|
|
172
|
-
expect(textField.props('errorMessages')).toContain('Format de date invalide')
|
|
172
|
+
expect(textField.props('errorMessages')).toContain('Format de date invalide (DD/MM/YYYY)')
|
|
173
173
|
})
|
|
174
174
|
|
|
175
175
|
it('formats date during input', async () => {
|
|
@@ -180,13 +180,13 @@ describe('DateTextInput.vue', () => {
|
|
|
180
180
|
})
|
|
181
181
|
|
|
182
182
|
it('handles date deletion', async () => {
|
|
183
|
-
//
|
|
183
|
+
// First set a valid date
|
|
184
184
|
const input = wrapper.find('input')
|
|
185
185
|
await input.setValue('01/01/2025')
|
|
186
186
|
await input.trigger('blur')
|
|
187
187
|
await wrapper.vm.$nextTick()
|
|
188
188
|
|
|
189
|
-
//
|
|
189
|
+
// Then delete it
|
|
190
190
|
await input.setValue('')
|
|
191
191
|
await input.trigger('input')
|
|
192
192
|
await input.trigger('blur')
|
|
@@ -227,9 +227,9 @@ describe('DateTextInput.vue', () => {
|
|
|
227
227
|
})
|
|
228
228
|
|
|
229
229
|
it('handles readonly state', async () => {
|
|
230
|
-
await wrapper.setProps({
|
|
230
|
+
await wrapper.setProps({ readonly: true })
|
|
231
231
|
const textField = wrapper.findComponent(SyTextField)
|
|
232
|
-
expect(textField.props('
|
|
232
|
+
expect(textField.props('readonly')).toBe(true)
|
|
233
233
|
})
|
|
234
234
|
|
|
235
235
|
it('emits focus and blur events', async () => {
|
|
@@ -266,19 +266,61 @@ describe('DateTextInput.vue', () => {
|
|
|
266
266
|
await wrapper.vm.$nextTick()
|
|
267
267
|
expect(input.element.value).toBe('01/__/____')
|
|
268
268
|
|
|
269
|
-
//
|
|
269
|
+
// Simulate cursor position after "01"
|
|
270
270
|
input.element.setSelectionRange(2, 2)
|
|
271
271
|
await input.trigger('input')
|
|
272
272
|
await wrapper.vm.$nextTick()
|
|
273
273
|
|
|
274
|
-
//
|
|
274
|
+
// The cursor position should remain after "01"
|
|
275
275
|
expect(input.element.selectionStart).toBe(2)
|
|
276
276
|
})
|
|
277
277
|
|
|
278
|
+
it('handles 2 digits year correctly', async () => {
|
|
279
|
+
const customWrapper = mount(DateTextInput, {
|
|
280
|
+
global: {
|
|
281
|
+
plugins: [vuetify],
|
|
282
|
+
},
|
|
283
|
+
props: {
|
|
284
|
+
modelValue: null,
|
|
285
|
+
format: 'DD/MM/YY',
|
|
286
|
+
dateFormatReturn: 'YYYY-MM-DD',
|
|
287
|
+
},
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
const input = customWrapper.find('input')
|
|
291
|
+
await input.setValue('0')
|
|
292
|
+
expect(input.element.value).toBe('0_/__/__')
|
|
293
|
+
|
|
294
|
+
await input.setValue('01/02/99')
|
|
295
|
+
expect(input.element.value).toBe('01/02/99')
|
|
296
|
+
expect(customWrapper.emitted('update:model-value')?.at(-1)).toEqual(['1999-02-01'])
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('handles ISO-8601 date format correctly', async () => {
|
|
300
|
+
const customWrapper = mount(DateTextInput, {
|
|
301
|
+
global: {
|
|
302
|
+
plugins: [vuetify],
|
|
303
|
+
},
|
|
304
|
+
props: {
|
|
305
|
+
modelValue: null,
|
|
306
|
+
format: 'YYYY-MM-DD',
|
|
307
|
+
},
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
const input = customWrapper.find('input')
|
|
311
|
+
await input.setValue('2025-')
|
|
312
|
+
expect(input.element.value).toBe('2025-__-__')
|
|
313
|
+
expect(customWrapper.emitted('update:model-value')).toBeFalsy()
|
|
314
|
+
|
|
315
|
+
await input.setValue('2025-01-01')
|
|
316
|
+
expect(input.element.value).toBe('2025-01-01')
|
|
317
|
+
expect(customWrapper.emitted('update:model-value')?.at(-1)).toEqual(['2025-01-01'])
|
|
318
|
+
})
|
|
319
|
+
|
|
278
320
|
it('handles paste event with valid date', async () => {
|
|
279
321
|
const input = wrapper.find('input')
|
|
280
322
|
|
|
281
|
-
//
|
|
323
|
+
// Create a paste event with data
|
|
282
324
|
const clipboardData = {
|
|
283
325
|
getData: () => '01/01/2025',
|
|
284
326
|
}
|
|
@@ -297,26 +339,26 @@ describe('DateTextInput.vue', () => {
|
|
|
297
339
|
await input.trigger('keydown', {
|
|
298
340
|
key: 'Tab',
|
|
299
341
|
})
|
|
300
|
-
//
|
|
342
|
+
// Check that the component doesn't prevent tab navigation
|
|
301
343
|
expect(wrapper.emitted('update:model-value')).toBeFalsy()
|
|
302
344
|
|
|
303
|
-
//
|
|
345
|
+
// Test behavior with Ctrl+V (paste)
|
|
304
346
|
await input.trigger('keydown', {
|
|
305
347
|
key: 'v',
|
|
306
348
|
ctrlKey: true,
|
|
307
349
|
})
|
|
308
|
-
//
|
|
350
|
+
// Default behavior should be preserved
|
|
309
351
|
expect(wrapper.emitted('update:model-value')).toBeFalsy()
|
|
310
352
|
})
|
|
311
353
|
|
|
312
354
|
it('validates on submit correctly', async () => {
|
|
313
355
|
const input = wrapper.find('input')
|
|
314
356
|
|
|
315
|
-
//
|
|
357
|
+
// Case 1: Empty field with required=true
|
|
316
358
|
const emptyResult = await wrapper.vm.validateOnSubmit()
|
|
317
359
|
expect(emptyResult).toBe(false)
|
|
318
360
|
|
|
319
|
-
//
|
|
361
|
+
// Case 2: Valid date
|
|
320
362
|
await input.setValue('01/01/2025')
|
|
321
363
|
await input.trigger('blur')
|
|
322
364
|
await wrapper.vm.$nextTick()
|
|
@@ -326,23 +368,29 @@ describe('DateTextInput.vue', () => {
|
|
|
326
368
|
})
|
|
327
369
|
|
|
328
370
|
it('handles focus and blur methods correctly', async () => {
|
|
329
|
-
//
|
|
330
|
-
const originalQuerySelector = document.querySelector
|
|
371
|
+
// Create a mock for the input element
|
|
331
372
|
const mockInput = { focus: vi.fn(), blur: vi.fn() }
|
|
332
373
|
|
|
333
|
-
//
|
|
334
|
-
|
|
374
|
+
// Mock the component's querySelector method
|
|
375
|
+
const mockQuerySelector = vi.fn().mockReturnValue(mockInput)
|
|
376
|
+
|
|
377
|
+
// Replace the element reference and its querySelector method
|
|
378
|
+
wrapper.vm.inputRef = {
|
|
379
|
+
$el: {
|
|
380
|
+
querySelector: mockQuerySelector,
|
|
381
|
+
},
|
|
382
|
+
}
|
|
335
383
|
|
|
336
|
-
//
|
|
384
|
+
// Call the exposed methods
|
|
337
385
|
wrapper.vm.focus()
|
|
338
386
|
wrapper.vm.blur()
|
|
339
387
|
|
|
340
|
-
//
|
|
388
|
+
// Check that querySelector was called with the right selector
|
|
389
|
+
expect(mockQuerySelector).toHaveBeenCalledWith('input:not([type="hidden"])')
|
|
390
|
+
|
|
391
|
+
// Check that the methods were called
|
|
341
392
|
expect(mockInput.focus).toHaveBeenCalled()
|
|
342
393
|
expect(mockInput.blur).toHaveBeenCalled()
|
|
343
|
-
|
|
344
|
-
// Restaurer document.querySelector
|
|
345
|
-
document.querySelector = originalQuerySelector
|
|
346
394
|
})
|
|
347
395
|
|
|
348
396
|
it('initializes with model value correctly', async () => {
|
|
@@ -383,17 +431,17 @@ describe('DateTextInput.vue', () => {
|
|
|
383
431
|
it('handles partial date input correctly', async () => {
|
|
384
432
|
const input = wrapper.find('input')
|
|
385
433
|
|
|
386
|
-
//
|
|
434
|
+
// Enter only the day
|
|
387
435
|
await input.setValue('01')
|
|
388
436
|
await wrapper.vm.$nextTick()
|
|
389
437
|
expect(input.element.value).toBe('01/__/____')
|
|
390
438
|
|
|
391
|
-
//
|
|
439
|
+
// Add the month
|
|
392
440
|
await input.setValue('01/02')
|
|
393
441
|
await wrapper.vm.$nextTick()
|
|
394
442
|
expect(input.element.value).toBe('01/02/____')
|
|
395
443
|
|
|
396
|
-
//
|
|
444
|
+
// Complete the date
|
|
397
445
|
await input.setValue('01/02/2025')
|
|
398
446
|
await wrapper.vm.$nextTick()
|
|
399
447
|
expect(input.element.value).toBe('01/02/2025')
|
|
@@ -423,16 +471,16 @@ describe('DateTextInput.vue', () => {
|
|
|
423
471
|
await input.trigger('focus')
|
|
424
472
|
await input.trigger('blur')
|
|
425
473
|
await customWrapper.vm.$nextTick()
|
|
426
|
-
await customWrapper.vm.$nextTick() // Double nextTick
|
|
474
|
+
await customWrapper.vm.$nextTick() // Double nextTick for reliability
|
|
427
475
|
|
|
428
|
-
// Force validation
|
|
476
|
+
// Force manual validation
|
|
429
477
|
await customWrapper.vm.validateOnSubmit()
|
|
430
478
|
await customWrapper.vm.$nextTick()
|
|
431
479
|
|
|
432
480
|
const textField = customWrapper.findComponent(SyTextField)
|
|
433
481
|
const successMessages = textField.props('successMessages') || []
|
|
434
482
|
|
|
435
|
-
//
|
|
483
|
+
// Flexible verification
|
|
436
484
|
expect(successMessages.length).toBeGreaterThan(0)
|
|
437
485
|
expect(successMessages[0]).toContain('valide')
|
|
438
486
|
})
|
|
@@ -121,7 +121,7 @@ const meta: Meta<typeof DialogBox> = {
|
|
|
121
121
|
height: '32px',
|
|
122
122
|
class: 'mt-n2 mr-n2 ml-4',
|
|
123
123
|
},
|
|
124
|
-
|
|
124
|
+
cardActions: {
|
|
125
125
|
class: 'd-flex flex-wrap mt-6',
|
|
126
126
|
},
|
|
127
127
|
cancelBtn: {
|
|
@@ -139,8 +139,11 @@ const meta: Meta<typeof DialogBox> = {
|
|
|
139
139
|
{
|
|
140
140
|
card?: Record<string, any>,
|
|
141
141
|
cardTitle?: Record<string, any>,
|
|
142
|
+
spacer?: Record<string, any>,
|
|
142
143
|
closeBtn?: Record<string, any>,
|
|
143
|
-
|
|
144
|
+
icon?: Record<string, any>,
|
|
145
|
+
actionsBtn?: Record<string, any>,
|
|
146
|
+
actionsSpacer?: Record<string, any>,
|
|
144
147
|
cancelBtn?: Record<string, any>,
|
|
145
148
|
confirmBtn?: Record<string, any>,
|
|
146
149
|
}
|
|
@@ -159,6 +159,10 @@ export const Legende: StoryObj = {
|
|
|
159
159
|
</div>
|
|
160
160
|
</div>
|
|
161
161
|
</div>
|
|
162
|
+
<div class="mt-4">
|
|
163
|
+
<p>Rapport d’audit manuel : <a href="/audits/DownloadBtn.xlsx" style="color:#0C41BD;">Voir le rapport</a></p>
|
|
164
|
+
<p style="color: grey; font-size: 14px">Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system/issues/4007" target="_blank" style="color:#0C41BD;">issue #4007</a>)</p>
|
|
165
|
+
</div>
|
|
162
166
|
`,
|
|
163
167
|
}
|
|
164
168
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fn, userEvent, within } from '@storybook/test'
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
3
3
|
import axios from 'axios'
|
|
4
|
-
import {
|
|
4
|
+
import { VSheet } from 'vuetify/components'
|
|
5
5
|
import DownloadBtn from './DownloadBtn.vue'
|
|
6
6
|
import NotificationBar from '../NotificationBar/NotificationBar.vue'
|
|
7
7
|
import { useNotificationService } from '@/services/NotificationService'
|
|
@@ -22,6 +22,15 @@ const meta = {
|
|
|
22
22
|
category: 'slots',
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
|
+
dark: {
|
|
26
|
+
control: 'boolean',
|
|
27
|
+
description: 'Applique le thème sombre.',
|
|
28
|
+
table: {
|
|
29
|
+
type: {
|
|
30
|
+
summary: 'boolean',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
25
34
|
filePromise: {
|
|
26
35
|
control: false,
|
|
27
36
|
description: 'Une fonction retournant une valeur de retour de Axios `Promise<AxiosResponse>`. <br>Exemple: `() => axios.get("https://run.mocky.io/v3/884c25f5-6dc2-4c01-b8d9-26c54042f94f")`',
|
|
@@ -231,16 +240,16 @@ export const Dark: Story = {
|
|
|
231
240
|
{
|
|
232
241
|
name: 'Template',
|
|
233
242
|
code: `<template>
|
|
234
|
-
<
|
|
243
|
+
<VSheet color="primary" class="pa-4">
|
|
235
244
|
<DownloadBtn
|
|
245
|
+
dark
|
|
236
246
|
:file-promise="download"
|
|
237
|
-
background-color="black"
|
|
238
247
|
@error="console.log('error')"
|
|
239
248
|
@success="console.log('success')"
|
|
240
249
|
>
|
|
241
250
|
Télécharger
|
|
242
251
|
</DownloadBtn>
|
|
243
|
-
</
|
|
252
|
+
</VSheet>
|
|
244
253
|
</template>
|
|
245
254
|
`,
|
|
246
255
|
},
|
|
@@ -259,20 +268,20 @@ export const Dark: Story = {
|
|
|
259
268
|
],
|
|
260
269
|
},
|
|
261
270
|
render: args => ({
|
|
262
|
-
components: {
|
|
271
|
+
components: { VSheet, DownloadBtn },
|
|
263
272
|
setup() {
|
|
264
273
|
return { args }
|
|
265
274
|
},
|
|
266
275
|
template: `
|
|
267
|
-
<
|
|
276
|
+
<VSheet color="primary" class="pa-4">
|
|
268
277
|
<DownloadBtn v-bind="args">{{ args.default }}</DownloadBtn>
|
|
269
|
-
</
|
|
278
|
+
</VSheet>
|
|
270
279
|
`,
|
|
271
280
|
}),
|
|
272
281
|
args: {
|
|
282
|
+
dark: true,
|
|
273
283
|
filePromise: () => axios.get('https://run.mocky.io/v3/884c25f5-6dc2-4c01-b8d9-26c54042f94f'),
|
|
274
284
|
default: 'Télécharger',
|
|
275
|
-
backgroundColor: 'black',
|
|
276
285
|
onError: fn(),
|
|
277
286
|
onSuccess: fn(),
|
|
278
287
|
},
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
filePromise: () => Promise<AxiosResponse<Blob>>
|
|
20
20
|
fallbackFilename?: string
|
|
21
21
|
backgroundColor?: string
|
|
22
|
+
dark?: boolean
|
|
22
23
|
locales?: typeof defaultLocales
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -29,13 +30,19 @@
|
|
|
29
30
|
const props = withDefaults(defineProps<Props & CustomizableOptions>(), {
|
|
30
31
|
fallbackFilename: undefined,
|
|
31
32
|
backgroundColor: 'white',
|
|
33
|
+
dark: false,
|
|
32
34
|
locales: () => defaultLocales,
|
|
33
35
|
})
|
|
36
|
+
|
|
34
37
|
const emits = defineEmits(['error', 'success'])
|
|
35
38
|
const attrs = useAttrs()
|
|
36
39
|
const state = ref<State>('idle')
|
|
37
40
|
const options = useCustomizableOptions(config, props)
|
|
38
41
|
const btnOptions = computed(() => deepmerge(options.value.btn, attrs))
|
|
42
|
+
const isDark = computed(() => props.dark ?? false)
|
|
43
|
+
const buttonColor = computed(() => isDark.value ? 'white' : options.value.btn.color)
|
|
44
|
+
const buttonBgColor = computed(() => isDark.value ? 'transparent' : props.backgroundColor)
|
|
45
|
+
const iconColor = computed(() => isDark.value ? 'white' : options.value.icon.color)
|
|
39
46
|
|
|
40
47
|
/**
|
|
41
48
|
* Get filename and content type from headers
|
|
@@ -88,12 +95,16 @@
|
|
|
88
95
|
v-bind="btnOptions"
|
|
89
96
|
:loading="state === 'loading'"
|
|
90
97
|
class="sy-download-btn"
|
|
91
|
-
:
|
|
98
|
+
:color="buttonColor"
|
|
99
|
+
:class="`bg-${buttonBgColor}`"
|
|
92
100
|
data-testid="download-btn"
|
|
93
101
|
@click="download"
|
|
94
102
|
>
|
|
95
103
|
<slot name="icon">
|
|
96
|
-
<VIcon
|
|
104
|
+
<VIcon
|
|
105
|
+
v-bind="options.icon"
|
|
106
|
+
:color="iconColor"
|
|
107
|
+
>
|
|
97
108
|
{{ mdiDownload }}
|
|
98
109
|
</VIcon>
|
|
99
110
|
</slot>
|
|
@@ -141,8 +152,4 @@
|
|
|
141
152
|
.sy-download-btn:focus-visible::after {
|
|
142
153
|
opacity: 1;
|
|
143
154
|
}
|
|
144
|
-
|
|
145
|
-
.outlined-style {
|
|
146
|
-
border: 1px solid currentcolor;
|
|
147
|
-
}
|
|
148
155
|
</style>
|
|
@@ -4,7 +4,6 @@ exports[`DownloadBtn > renders correctly 1`] = `
|
|
|
4
4
|
<button
|
|
5
5
|
class="
|
|
6
6
|
bg-white
|
|
7
|
-
outlined-style
|
|
8
7
|
sy-download-btn
|
|
9
8
|
text-primary
|
|
10
9
|
text-wrap
|
|
@@ -47,7 +46,6 @@ exports[`DownloadBtn > with slots 1`] = `
|
|
|
47
46
|
<button
|
|
48
47
|
class="
|
|
49
48
|
bg-white
|
|
50
|
-
outlined-style
|
|
51
49
|
sy-download-btn
|
|
52
50
|
text-primary
|
|
53
51
|
text-wrap
|
|
@@ -187,6 +187,10 @@ export const Legende: StoryObj = {
|
|
|
187
187
|
</div>
|
|
188
188
|
</div>
|
|
189
189
|
</div>
|
|
190
|
+
<div class="mt-4">
|
|
191
|
+
<p>Rapport d’audit manuel : <a href="/audits/FranceConnectBtn.xlsx" style="color:#0C41BD;">Voir le rapport</a></p>
|
|
192
|
+
<p style="color: grey; font-size: 14px">Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system/issues/4005" target="_blank" style="color:#0C41BD;">issue #4005</a>)</p>
|
|
193
|
+
</div>
|
|
190
194
|
`,
|
|
191
195
|
}
|
|
192
196
|
},
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<style lang="scss" scoped>
|
|
12
12
|
@use '@/assets/tokens.scss' as *;
|
|
13
|
+
@use '../menu';
|
|
13
14
|
|
|
14
15
|
.header-menu-item {
|
|
15
16
|
color: rgb(var(--v-theme-primary));
|
|
@@ -37,6 +38,8 @@
|
|
|
37
38
|
&::first-letter {
|
|
38
39
|
text-transform: uppercase;
|
|
39
40
|
}
|
|
41
|
+
|
|
42
|
+
@include menu.item-focused;
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
<style lang="scss" scoped>
|
|
64
64
|
@use '@/assets/tokens.scss' as *;
|
|
65
65
|
@use '../../consts' as *;
|
|
66
|
+
@use '../menu';
|
|
66
67
|
|
|
67
68
|
.sub-menu-btn {
|
|
68
69
|
display: flex;
|
|
@@ -83,6 +84,8 @@
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
@include menu.item-focused;
|
|
88
|
+
|
|
86
89
|
&::first-letter {
|
|
87
90
|
text-transform: uppercase;
|
|
88
91
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
@use 'sass:color';
|
|
2
|
+
@use '@/assets/tokens';
|
|
3
|
+
|
|
4
|
+
$red: color.channel(tokens.$primary-base, 'red');
|
|
5
|
+
$green: color.channel(tokens.$primary-base, 'green');
|
|
6
|
+
$blue: color.channel(tokens.$primary-base, 'blue');
|
|
7
|
+
$primary: $red, $green, $blue;
|
|
8
|
+
|
|
9
|
+
@mixin item-focused() {
|
|
10
|
+
border-top: 2px solid transparent;
|
|
11
|
+
border-bottom: 2px solid transparent;
|
|
12
|
+
transition: border-color 0.1s ease;
|
|
13
|
+
|
|
14
|
+
&:focus-visible {
|
|
15
|
+
outline: 0;
|
|
16
|
+
border-top: 2px solid rgb(var(--v-theme-primary, $primary));
|
|
17
|
+
border-bottom: 2px solid rgb(var(--v-theme-primary, $primary));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -48,12 +48,22 @@
|
|
|
48
48
|
font-weight: 700;
|
|
49
49
|
background-color: rgb(var(--v-theme-primary));
|
|
50
50
|
color: tokens.$neutral-white;
|
|
51
|
-
border
|
|
52
|
-
|
|
51
|
+
border: 2px solid transparent;
|
|
52
|
+
border-bottom:
|
|
53
|
+
solid 2px linear-gradient(
|
|
54
|
+
180deg,
|
|
55
|
+
transparent 0%,
|
|
56
|
+
transparent 50%,
|
|
57
|
+
tokens.$blue-lighten-80 50%,
|
|
58
|
+
tokens.$blue-lighten-80 100%
|
|
59
|
+
);
|
|
60
|
+
transition: color 0.15s 0.1s, background-color 0.15s 0.1s, border 0.15s 0.1s;
|
|
53
61
|
|
|
54
62
|
&:focus-visible {
|
|
55
63
|
background-color: tokens.$neutral-white;
|
|
56
64
|
color: rgb(var(--v-theme-primary));
|
|
65
|
+
outline: none;
|
|
66
|
+
border: 2px solid rgb(var(--v-theme-primary));
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
|
|
@@ -159,6 +159,10 @@ export const Legende: StoryObj = {
|
|
|
159
159
|
</v-btn>
|
|
160
160
|
Problèmes relevés par Tanaguru
|
|
161
161
|
</div>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="mt-4">
|
|
164
|
+
<p>Rapport d’audit manuel : <a href="/audits/LangBtn.xlsx" style="color:#0C41BD;">Voir le rapport</a></p>
|
|
165
|
+
<p style="color: grey; font-size: 14px">Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system/issues/4009" target="_blank" style="color:#0C41BD;">issue #4009</a>)</p>
|
|
162
166
|
</div>
|
|
163
167
|
</div>
|
|
164
168
|
`,
|
|
@@ -13,13 +13,11 @@ const meta: Meta<typeof LangBtn> = {
|
|
|
13
13
|
modelValue: { control: 'text' },
|
|
14
14
|
hideDownArrow: { control: 'boolean' },
|
|
15
15
|
ariaLabel: { control: 'text' },
|
|
16
|
-
|
|
17
|
-
availableLanguages: { control: { type: 'array' } },
|
|
16
|
+
availableLanguages: { control: { type: 'object' } },
|
|
18
17
|
vuetifyOptions: {
|
|
19
18
|
control: { type: 'object' },
|
|
20
19
|
default: () => ({
|
|
21
20
|
menu: {
|
|
22
|
-
offsetY: true,
|
|
23
21
|
},
|
|
24
22
|
btn: {
|
|
25
23
|
color: 'primary',
|
|
@@ -73,7 +71,6 @@ export const Default: Story = {
|
|
|
73
71
|
availableLanguages: ['fr', 'en', 'es'],
|
|
74
72
|
vuetifyOptions: {
|
|
75
73
|
menu: {
|
|
76
|
-
offsetY: true,
|
|
77
74
|
},
|
|
78
75
|
btn: {
|
|
79
76
|
color: 'primary',
|