@cnamts/synapse 1.0.22 → 1.0.23

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 (190) hide show
  1. package/dist/{DateFilter-B5n-ZkLi.js → DateFilter-Dc-gSGwk.js} +1 -1
  2. package/dist/{NumberFilter-CtiZ9uj8.js → NumberFilter-vP38Wp6j.js} +1 -1
  3. package/dist/{PeriodFilter-DzqiMb-b.js → PeriodFilter-Ba1uYUnT.js} +1 -1
  4. package/dist/{SelectFilter-BOYlF7rX.js → SelectFilter-BioGT6Nn.js} +1 -1
  5. package/dist/{TextFilter-BOFRNfcX.js → TextFilter-B84dpnoq.js} +1 -1
  6. package/dist/components/Accordion/Accordion.d.ts +13 -2
  7. package/dist/components/Accordion/composables/useAccordionState.d.ts +2 -1
  8. package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +7 -7
  9. package/dist/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.d.ts +1 -1
  10. package/dist/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.d.ts +1 -1
  11. package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +1 -1
  12. package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +7 -7
  13. package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +16 -16
  14. package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +1 -1
  15. package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +1 -1
  16. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +22 -1
  17. package/dist/components/Customs/Selects/SyAutocomplete/locales.d.ts +5 -0
  18. package/dist/components/Customs/Selects/SyInputSelect/SyInputSelect.d.ts +1 -1
  19. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +1 -1
  20. package/dist/components/Customs/Selects/SySelect/locales.d.ts +1 -0
  21. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -1
  22. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -1
  23. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -1
  24. package/dist/components/Customs/SyTextField/SyTextField.d.ts +5 -2
  25. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +13 -9
  26. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +7 -5
  27. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +2 -1
  28. package/dist/components/ErrorPage/ErrorPage.d.ts +3 -1
  29. package/dist/components/FileList/UploadItem/UploadItem.d.ts +6 -0
  30. package/dist/components/FileList/UploadItem/locales.d.ts +1 -4
  31. package/dist/components/FileUpload/FileUploadContent.d.ts +2 -0
  32. package/dist/components/FileUpload/validateFiles.d.ts +2 -1
  33. package/dist/components/HeaderBar/HeaderBar.d.ts +2 -1
  34. package/dist/components/HeaderBar/HeaderLogo/HeaderLogo.d.ts +2 -1
  35. package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +2 -1
  36. package/dist/components/MonthPicker/MonthPicker.d.ts +1939 -0
  37. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1899 -0
  38. package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +21 -0
  39. package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.d.ts +21 -0
  40. package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.d.ts +12 -0
  41. package/dist/components/MonthPicker/MonthPickerVisual/MonthSelector.d.ts +11 -0
  42. package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.d.ts +6 -0
  43. package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.d.ts +14 -0
  44. package/dist/components/MonthPicker/MonthPickerVisual/YearSelector.d.ts +14 -0
  45. package/dist/components/MonthPicker/MonthPickerVisual/useMonthGrid.d.ts +9 -0
  46. package/dist/components/MonthPicker/MonthPickerVisual/useYearGrid.d.ts +8 -0
  47. package/dist/components/MonthPicker/MonthPickerVisual/utils.d.ts +8 -0
  48. package/dist/components/MonthPicker/locales.d.ts +12 -0
  49. package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +25 -0
  50. package/dist/components/NirField/NirField.d.ts +3 -1
  51. package/dist/components/NotificationBar/Notification/Notification.d.ts +3 -0
  52. package/dist/components/PasswordField/PasswordField.d.ts +1 -1
  53. package/dist/components/PeriodField/PeriodField.d.ts +29 -21
  54. package/dist/components/PhoneField/PhoneField.d.ts +2 -1
  55. package/dist/components/SyBtnMenu/SyBtnMenu.d.ts +1 -1
  56. package/dist/components/SyHeading/SyHeading.a11y.test.d.ts +1 -0
  57. package/dist/components/SyHeading/SyHeading.d.ts +4 -2
  58. package/dist/components/SyHeading/SyHeading.test.d.ts +1 -0
  59. package/dist/components/SyTextArea/SyTextArea.d.ts +1 -1
  60. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
  61. package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
  62. package/dist/components/Tables/common/SyTablePagination.d.ts +6 -6
  63. package/dist/components/index.d.ts +1 -0
  64. package/dist/design-system-v3.js +102 -99
  65. package/dist/design-system-v3.umd.cjs +126 -126
  66. package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +5 -0
  67. package/dist/{main-CEl4J8_T.js → main-aLKwdMi1.js} +11167 -10522
  68. package/dist/main.d.ts +1 -0
  69. package/dist/style.css +1 -1
  70. package/package.json +10 -4
  71. package/src/assets/apTokens.scss +2 -2
  72. package/src/assets/overrides/_btns.scss +8 -0
  73. package/src/assets/overrides/_forms.scss +9 -0
  74. package/src/assets/overrides/_icons.scss +38 -9
  75. package/src/assets/overrides/_tables.scss +19 -0
  76. package/src/components/Accordion/Accordion.mdx +23 -9
  77. package/src/components/Accordion/Accordion.stories.ts +153 -3
  78. package/src/components/Accordion/Accordion.vue +7 -6
  79. package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +40 -12
  80. package/src/components/Accordion/composables/useAccordionState.ts +3 -4
  81. package/src/components/Accordion/tests/accordion.spec.ts +131 -19
  82. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.mdx +3 -1
  83. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.stories.ts +8 -0
  84. package/src/components/BackBtn/accessibilite/Accessibility.mdx +62 -10
  85. package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +9 -3
  86. package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +86 -6
  87. package/src/components/Captcha/tests/Captcha.spec.ts +0 -29
  88. package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +2 -110
  89. package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +133 -10
  90. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +379 -93
  91. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +144 -83
  92. package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibilite.stories.ts +40 -1
  93. package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibility.mdx +7 -1
  94. package/src/components/Customs/Selects/SyAutocomplete/locales.ts +5 -0
  95. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +96 -0
  96. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +234 -9
  97. package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +13 -3
  98. package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +9 -10
  99. package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -3
  100. package/src/components/Customs/Selects/SySelect/locales.ts +1 -0
  101. package/src/components/Customs/SyIcon/SyIcon.vue +1 -1
  102. package/src/components/Customs/SyIcon/tests/SyIcon.a11y.spec.ts +20 -0
  103. package/src/components/Customs/SyIconButton/SyIconButton.mdx +46 -0
  104. package/src/components/Customs/SyIconButton/SyIconButton.stories.ts +184 -0
  105. package/src/components/Customs/SyIconButton/SyIconButton.vue +38 -0
  106. package/src/components/Customs/SyIconButton/accessibilite/Accessibility.mdx +64 -0
  107. package/src/components/Customs/SyIconButton/tests/SyIconButton.a11y.spec.ts +87 -0
  108. package/src/components/Customs/SyIconButton/tests/SyIconButton.spec.ts +152 -0
  109. package/src/components/Customs/SyIconButton/tests/__snapshots__/SyIconButton.spec.ts.snap +61 -0
  110. package/src/components/Customs/SyPagination/SyPagination.vue +5 -5
  111. package/src/components/Customs/SyTextField/SyTextField.vue +20 -2
  112. package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +67 -9
  113. package/src/components/Customs/SyTextField/tests/SyTextField.a11y.spec.ts +15 -0
  114. package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +36 -0
  115. package/src/components/DataList/accessibilite/Accessibility.mdx +79 -11
  116. package/src/components/DataListGroup/accessibilite/Accessibility.mdx +80 -11
  117. package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +25 -0
  118. package/src/components/ErrorPage/ErrorPage.stories.ts +113 -19
  119. package/src/components/ErrorPage/ErrorPage.vue +17 -2
  120. package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +17 -0
  121. package/src/components/ErrorPage/tests/ErrorPage.spec.ts +21 -1
  122. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +0 -1
  123. package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +23 -0
  124. package/src/components/FileList/FileList.stories.ts +51 -1
  125. package/src/components/FileList/UploadItem/UploadItem.vue +13 -6
  126. package/src/components/FileList/UploadItem/locales.ts +3 -12
  127. package/src/components/FileList/accessibilite/Accessibility.mdx +3 -0
  128. package/src/components/FileUpload/FileUpload.vue +2 -1
  129. package/src/components/FileUpload/FileUploadContent.vue +2 -1
  130. package/src/components/FileUpload/tests/FileUpload.spec.ts +47 -0
  131. package/src/components/FileUpload/validateFiles.ts +5 -2
  132. package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +62 -9
  133. package/src/components/HeaderBar/HeaderBar.vue +2 -1
  134. package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -1
  135. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
  136. package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +74 -8
  137. package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +163 -0
  138. package/src/components/MaintenancePage/MaintenancePage.vue +1 -1
  139. package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +4 -5
  140. package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +0 -1
  141. package/src/components/MonthPicker/MonthPicker.mdx +35 -0
  142. package/src/components/MonthPicker/MonthPicker.stories.ts +527 -0
  143. package/src/components/MonthPicker/MonthPicker.vue +79 -0
  144. package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +89 -0
  145. package/src/components/MonthPicker/MonthPickerText/useTextField.ts +27 -0
  146. package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.vue +154 -0
  147. package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.ts +13 -0
  148. package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +137 -0
  149. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +60 -0
  150. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +149 -0
  151. package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +143 -0
  152. package/src/components/MonthPicker/MonthPickerVisual/useMonthGrid.ts +45 -0
  153. package/src/components/MonthPicker/MonthPickerVisual/useYearGrid.ts +45 -0
  154. package/src/components/MonthPicker/MonthPickerVisual/utils.ts +17 -0
  155. package/src/components/MonthPicker/accessibilite/Accessibility.mdx +59 -0
  156. package/src/components/MonthPicker/locales.ts +12 -0
  157. package/src/components/MonthPicker/tests/MonthPicker.a11y.spec.ts +71 -0
  158. package/src/components/MonthPicker/tests/MonthPicker.spec.ts +1248 -0
  159. package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +2545 -0
  160. package/src/components/MonthPicker/useMonthPickerValidation.ts +30 -0
  161. package/src/components/NirField/NirField.mdx +1 -2
  162. package/src/components/NirField/NirField.stories.ts +66 -6
  163. package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +2 -3
  164. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +22 -14
  165. package/src/components/NotificationBar/Notification/Notification.vue +3 -1
  166. package/src/components/NotificationBar/NotificationBar.stories.ts +154 -0
  167. package/src/components/NotificationBar/tests/NotificationBar.a11y.spec.ts +26 -0
  168. package/src/components/NotificationBar/tests/NotificationBar.spec.ts +60 -0
  169. package/src/components/RangeField/accessibilite/Accessibility.mdx +79 -11
  170. package/src/components/SkipLink/tests/SkipLink.a11y.spec.ts +23 -0
  171. package/src/components/StatusPage/StatusPage.stories.ts +118 -0
  172. package/src/components/StatusPage/StatusPage.vue +5 -3
  173. package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +22 -0
  174. package/src/components/StatusPage/tests/StatusPage.spec.ts +22 -0
  175. package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +22 -14
  176. package/src/components/SubHeader/tests/SubHeader.a11y.spec.ts +20 -0
  177. package/src/components/SyAlert/SyAlert.vue +1 -0
  178. package/src/components/SyAlert/accessibilite/Accessibility.mdx +79 -9
  179. package/src/components/SyAlert/tests/SyAlert.a11y.spec.ts +23 -0
  180. package/src/components/SyHeading/SyHeading.a11y.test.ts +149 -0
  181. package/src/components/SyHeading/SyHeading.test.ts +115 -0
  182. package/src/components/SyHeading/SyHeading.vue +5 -3
  183. package/src/components/SyTextArea/accessibilite/Accessibility.mdx +80 -8
  184. package/src/components/SyTextArea/tests/SyTextArea.a11y.spec.ts +151 -0
  185. package/src/components/ToolbarContainer/tests/ToolbarContainer.a11y.spec.ts +126 -0
  186. package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +2 -2
  187. package/src/components/index.ts +1 -0
  188. package/src/composables/useFormFieldErrorHandling.ts +11 -2
  189. package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -1
  190. package/src/main.ts +2 -0
@@ -0,0 +1,30 @@
1
+ import { type ValidationRule } from '@/composables/validation/useValidation'
2
+ import { computed } from 'vue'
3
+
4
+ export type ValidationProps = {
5
+ customRules?: ValidationRule[]
6
+ customWarningRules?: ValidationRule[]
7
+ customSuccessRules?: ValidationRule[]
8
+ errorMessages?: string[] | null
9
+ warningMessages?: string[] | null
10
+ successMessages?: string[] | null
11
+ hasError?: boolean
12
+ hasWarning?: boolean
13
+ hasSuccess?: boolean
14
+ showSuccessMessages?: boolean
15
+ }
16
+
17
+ export function useMonthPickerValidation(props: ValidationProps) {
18
+ return computed(() => ({
19
+ customRules: props.customRules,
20
+ customWarningRules: props.customWarningRules,
21
+ customSuccessRules: props.customSuccessRules,
22
+ errorMessages: props.errorMessages,
23
+ warningMessages: props.warningMessages,
24
+ successMessages: props.successMessages,
25
+ hasError: props.hasError,
26
+ hasWarning: props.hasWarning,
27
+ hasSuccess: props.hasSuccess,
28
+ showSuccessMessages: props.showSuccessMessages,
29
+ }))
30
+ }
@@ -65,8 +65,7 @@ import NirField from './NirField.vue';
65
65
 
66
66
  Le composant `NirField` utilise des règles de validation par défaut pour le numéro NIR et la Clé. Voici les règles de validation par défaut :
67
67
 
68
- #### Pour le numéro NIR :
69
-
68
+ <h4 id="ancre-nirtype">Pour le numéro NIR</h4>
70
69
  - Props: `nirType` à simple (par defaut) d'après le [repo](https://github.com/assurance-maladie-digital/nir-validation) :
71
70
 
72
71
  - Le 1er chiffre (1er composant) permet d'identifier le sexe de l'assuré (1 pour un homme et 2 pour une femme) ;
@@ -878,9 +878,6 @@ export const WithNirTooltip: Story = {
878
878
  nirTooltipPosition: 'prepend',
879
879
  },
880
880
  parameters: {
881
- a11y: {
882
- disable: true,
883
- },
884
881
  docs: {
885
882
  description: {
886
883
  story: `
@@ -929,9 +926,6 @@ export const WithKeyTooltip: Story = {
929
926
  keyTooltipPosition: 'append',
930
927
  },
931
928
  parameters: {
932
- a11y: {
933
- disable: true,
934
- },
935
929
  docs: {
936
930
  description: {
937
931
  story: `
@@ -1394,4 +1388,70 @@ const value = ref('')
1394
1388
  },
1395
1389
  ],
1396
1390
  },
1391
+
1392
+ }
1393
+
1394
+ export const ComplexNirType: Story = {
1395
+ args: {
1396
+ modelValue: '712125233333340',
1397
+ required: false,
1398
+ numberLabel: 'Numéro de sécurité sociale',
1399
+ keyLabel: 'Clé',
1400
+ displayKey: true,
1401
+ nirType: 'complexe',
1402
+ },
1403
+ parameters: {
1404
+ sourceCode: [
1405
+ {
1406
+ name: 'Template',
1407
+ code: `
1408
+ <template>
1409
+ <NirField
1410
+ v-model="value"
1411
+ :required="false"
1412
+ numberLabel="Numéro de sécurité sociale"
1413
+ keyLabel="Clé"
1414
+ :nirType="complexe"
1415
+ :displayKey="true"
1416
+ />
1417
+ </template>
1418
+ `,
1419
+ },
1420
+ {
1421
+ name: 'Script',
1422
+ code: `
1423
+ <script setup lang="ts">
1424
+ import { NirField } from '@cnamts/synapse'
1425
+ import { ref } from 'vue'
1426
+
1427
+ const value = ref('184027512345674')
1428
+
1429
+ return { value }
1430
+ </script>
1431
+ `,
1432
+ },
1433
+ ],
1434
+ },
1435
+ render: () => ({
1436
+ components: { NirField },
1437
+ setup() {
1438
+ const value = ref('712125233333340')
1439
+
1440
+ return { value }
1441
+ },
1442
+ template: `
1443
+ <div>
1444
+ <p class="mt-2">Cet exemple montre l'utilisation d'un NIR de type complexe<br/>(commençant par 7).</p>
1445
+ <p class="mb-4">Pour plus d'informations sur le NirType voir la <a href="/?path=/docs/composants-formulaires-nirfield--docs#ancre-nirtype">documentation</a>.</p>
1446
+ </div>
1447
+ <NirField
1448
+ v-model="value"
1449
+ :required="false"
1450
+ numberLabel="Numéro de sécurité sociale"
1451
+ keyLabel="Clé"
1452
+ nirType="complexe"
1453
+ :displayKey="true"
1454
+ />
1455
+ `,
1456
+ }),
1397
1457
  }
@@ -115,13 +115,12 @@ describe('NotFoundPage', () => {
115
115
  expect(img.attributes('src')).toBe('/custom.svg')
116
116
  })
117
117
 
118
- it('passes a uniqueId prop to StatusPage', async () => {
118
+ it('uses a generated uniqueId', async () => {
119
119
  const wrapper = mount(NotFoundPage)
120
120
  await flushPromises()
121
121
  await wrapper.vm.$nextTick()
122
122
 
123
- const statusPage = wrapper.findComponent(StatusPage)
124
- expect(statusPage.props('uniqueId')).toBeDefined()
123
+ expect(wrapper.find('.vd-page-container').attributes('id')).toMatch(/^[-a-z0-9]+-container$/)
125
124
  })
126
125
 
127
126
  it('passes a custom uniqueId prop to StatusPage', async () => {
@@ -1,19 +1,23 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`NotFoundPage > display the support ID if provided in the url 1`] = `
4
- <div class="
5
- d-flex
6
- justify-center
7
- px-14
8
- py-10
9
- vd-page-container
10
- ">
4
+ <div
5
+ class="
6
+ d-flex
7
+ justify-center
8
+ px-14
9
+ py-10
10
+ vd-page-container
11
+ "
12
+ id="v-0-container"
13
+ >
11
14
  <div
12
15
  class="
13
16
  bg-transparent
14
17
  v-sheet
15
18
  v-theme--light
16
19
  "
20
+ id="v-0-content"
17
21
  style="width: 800px;"
18
22
  >
19
23
  <div class="
@@ -149,19 +153,23 @@ exports[`NotFoundPage > display the support ID if provided in the url 1`] = `
149
153
  `;
150
154
 
151
155
  exports[`NotFoundPage > renders correctly 1`] = `
152
- <div class="
153
- d-flex
154
- justify-center
155
- px-14
156
- py-10
157
- vd-page-container
158
- ">
156
+ <div
157
+ class="
158
+ d-flex
159
+ justify-center
160
+ px-14
161
+ py-10
162
+ vd-page-container
163
+ "
164
+ id="v-0-container"
165
+ >
159
166
  <div
160
167
  class="
161
168
  bg-transparent
162
169
  v-sheet
163
170
  v-theme--light
164
171
  "
172
+ id="v-0-content"
165
173
  style="width: 800px;"
166
174
  >
167
175
  <div class="
@@ -74,7 +74,9 @@
74
74
  decorative
75
75
  />
76
76
 
77
- <span class="notification__message">{{ notification.message }}</span>
77
+ <span class="notification__message">
78
+ <slot :notification="props.notification">{{ notification.message }}</slot>
79
+ </span>
78
80
  <div
79
81
  class="d-flex ga-2 notification__actions"
80
82
  :class="notification.message.length > 50 ? 'action-section-long-text' : 'action-section-short-text'"
@@ -408,6 +408,160 @@ CustomCloseBtnText.parameters = {
408
408
  ],
409
409
  }
410
410
 
411
+ export const DefaultSlot: Story = (args) => {
412
+ return {
413
+ components: { NotificationBar, VBtn },
414
+ setup() {
415
+ const { addNotification } = useNotificationService()
416
+
417
+ const envoyerNotification = () => {
418
+ const notification: Notification = {
419
+ id: Date.now().toString(),
420
+ message: 'Notification avec contenu principal personnalisé.',
421
+ type: 'info',
422
+ timeout: -1,
423
+ }
424
+ addNotification(notification)
425
+ }
426
+
427
+ return { args, envoyerNotification }
428
+ },
429
+ template: `
430
+ <div class="d-flex flex-wrap align-center justify-center">
431
+ <NotificationBar v-bind="args">
432
+ <template #default="{ notification }">
433
+ Contenu personnalisé pour <strong>{{ notification.id }}</strong>
434
+ </template>
435
+ </NotificationBar>
436
+ <VBtn
437
+ color="primary"
438
+ @click="envoyerNotification()"
439
+ class="ma-6"
440
+ >
441
+ Afficher la notification
442
+ </VBtn>
443
+ </div>
444
+ `,
445
+ }
446
+ }
447
+
448
+ DefaultSlot.args = {
449
+ ...Default.args,
450
+ }
451
+
452
+ DefaultSlot.parameters = {
453
+ sourceCode: [
454
+ {
455
+ name: 'Template',
456
+ code: `
457
+ <NotificationBar>
458
+ <template #default="{ notification }">
459
+ Contenu personnalisé pour <strong>{{ notification.id }}</strong>
460
+ </template>
461
+ </NotificationBar>
462
+ `,
463
+ },
464
+ {
465
+ name: 'Script',
466
+ code: `
467
+ <script setup lang="ts">
468
+ import { NotificationBar, useNotificationService } from '@cnamts/synapse'
469
+
470
+ const { addNotification } = useNotificationService()
471
+
472
+ const envoyerNotification = () => {
473
+ addNotification({
474
+ id: Date.now().toString(),
475
+ message: 'Notification avec contenu principal personnalisé.',
476
+ type: 'info',
477
+ timeout: -1,
478
+ })
479
+ }
480
+ </script>
481
+ `,
482
+ },
483
+ ],
484
+ }
485
+
486
+ export const ActionSlot: Story = (args) => {
487
+ return {
488
+ components: { NotificationBar, VBtn },
489
+ setup() {
490
+ const { addNotification } = useNotificationService()
491
+
492
+ const envoyerNotification = () => {
493
+ const notification: Notification = {
494
+ id: Date.now().toString(),
495
+ message: 'Notification avec contenu personnalisé via slot.',
496
+ type: 'info',
497
+ timeout: -1,
498
+ }
499
+ addNotification(notification)
500
+ }
501
+
502
+ return { args, envoyerNotification }
503
+ },
504
+ template: `
505
+ <div class="d-flex flex-wrap align-center justify-center">
506
+ <NotificationBar v-bind="args">
507
+ <template #action>
508
+ <VBtn variant="outlined">
509
+ Voir le détail
510
+ </VBtn>
511
+ </template>
512
+ </NotificationBar>
513
+ <VBtn
514
+ color="primary"
515
+ @click="envoyerNotification()"
516
+ class="ma-6"
517
+ >
518
+ Afficher la notification
519
+ </VBtn>
520
+ </div>
521
+ `,
522
+ }
523
+ }
524
+
525
+ ActionSlot.args = {
526
+ ...Default.args,
527
+ }
528
+
529
+ ActionSlot.parameters = {
530
+ sourceCode: [
531
+ {
532
+ name: 'Template',
533
+ code: `
534
+ <NotificationBar>
535
+ <template #action>
536
+ <VBtn variant="outlined">
537
+ Voir le détail
538
+ </VBtn>
539
+ </template>
540
+ </NotificationBar>
541
+ `,
542
+ },
543
+ {
544
+ name: 'Script',
545
+ code: `
546
+ <script setup lang="ts">
547
+ import { NotificationBar, useNotificationService } from '@cnamts/synapse'
548
+
549
+ const { addNotification } = useNotificationService()
550
+
551
+ const envoyerNotification = () => {
552
+ addNotification({
553
+ id: Date.now().toString(),
554
+ message: 'Notification avec contenu personnalisé via slot.',
555
+ type: 'info',
556
+ timeout: -1,
557
+ })
558
+ }
559
+ </script>
560
+ `,
561
+ },
562
+ ],
563
+ }
564
+
411
565
  export const Customization: Story = Default.bind({})
412
566
  Customization.args = {
413
567
  ...Default.args,
@@ -41,6 +41,32 @@ describe('NotificationBar – accessibility (axe)', () => {
41
41
  vi.restoreAllMocks()
42
42
  })
43
43
 
44
+ it('has no obvious axe violations with default slot content', async () => {
45
+ const notification: Notification = {
46
+ id: '1',
47
+ message: 'Message original',
48
+ type: 'info',
49
+ timeout: -1,
50
+ icon: null,
51
+ }
52
+
53
+ useNotificationService().notificationQueue.value = [notification]
54
+
55
+ const wrapper = mount(NotificationBar, {
56
+ attachTo: document.body,
57
+ slots: {
58
+ default: '<span>Contenu personnalisé via slot default</span>',
59
+ },
60
+ })
61
+
62
+ const results = await axe(document.body)
63
+ assertNoA11yViolations(results, 'NotificationBar – default slot content', {
64
+ ignoreRules: ['region'],
65
+ })
66
+
67
+ wrapper.unmount()
68
+ })
69
+
44
70
  it('has no obvious axe violations with visible info notification', async () => {
45
71
  const notification: Notification = {
46
72
  id: '1',
@@ -186,6 +186,66 @@ describe('NotificationBar.vue', () => {
186
186
  expect(wrapper.html()).not.toContain('Test message 1')
187
187
  })
188
188
 
189
+ it('should render default slot content instead of message', async () => {
190
+ const notification: Notification = {
191
+ id: '1',
192
+ message: 'Message original',
193
+ type: 'info',
194
+ timeout: -1,
195
+ icon: null,
196
+ }
197
+ notificationServiceMock.notificationQueue.value = [notification]
198
+
199
+ const wrapper = mount(NotificationBar, {
200
+ slots: {
201
+ default: '<span>Contenu personnalisé</span>',
202
+ },
203
+ })
204
+ vi.runAllTimers()
205
+ await nextTick()
206
+
207
+ expect(wrapper.html()).toContain('Contenu personnalisé')
208
+ expect(wrapper.html()).not.toContain('Message original')
209
+ })
210
+
211
+ it('should expose notification slotProp in default slot', async () => {
212
+ const notification: Notification = {
213
+ id: 'abc',
214
+ message: 'Message original',
215
+ type: 'info',
216
+ timeout: -1,
217
+ icon: null,
218
+ }
219
+ notificationServiceMock.notificationQueue.value = [notification]
220
+
221
+ const wrapper = mount(NotificationBar, {
222
+ slots: {
223
+ default: `<template #default="{ notification }"><span>id: {{ notification.id }}</span></template>`,
224
+ },
225
+ })
226
+ vi.runAllTimers()
227
+ await nextTick()
228
+
229
+ expect(wrapper.html()).toContain('id: abc')
230
+ })
231
+
232
+ it('should fall back to message when no default slot is provided', async () => {
233
+ const notification: Notification = {
234
+ id: '1',
235
+ message: 'Message fallback',
236
+ type: 'info',
237
+ timeout: -1,
238
+ icon: null,
239
+ }
240
+ notificationServiceMock.notificationQueue.value = [notification]
241
+
242
+ const wrapper = mount(NotificationBar)
243
+ vi.runAllTimers()
244
+ await nextTick()
245
+
246
+ expect(wrapper.html()).toContain('Message fallback')
247
+ })
248
+
189
249
  it('should compute action', async () => {
190
250
  const notification: Notification = {
191
251
  id: '1',
@@ -1,15 +1,83 @@
1
- import { Meta, Story } from '@storybook/addon-docs';
2
- import * as Stories from '../RangeField.stories.ts';
3
- import '@/stories/styles/shared.css';
1
+ import { Meta, Primary } from '@storybook/blocks';
2
+ import * as RangeFieldStories from '../RangeField.stories.ts';
3
+ import AccessibilityIcon from '@/common/imgs/accessibility-svgrepo-com.svg';
4
+ import {
5
+ AccessibilityGuideLayout,
6
+ CriteriaSection,
7
+ CriteriaCard,
8
+ DemoSection,
9
+ BestPracticesSection,
10
+ ResourcesSection,
11
+ } from '@/stories/accessibility/AccessibilityGuideLayout.mdx';
4
12
 
5
- <Meta of={Stories} />
13
+ <Meta of={RangeFieldStories}/>
6
14
 
7
- <div className="header">
8
- <h1>Accessibilité</h1>
9
- </div>
15
+ <AccessibilityGuideLayout
16
+ componentName="RangeField"
17
+ iconSrc={AccessibilityIcon}
18
+ apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/slider/"
19
+ >
20
+ <div class="mt-8">
21
+ <p>Rapport d'audit manuel : <a href="/audits/RangeField.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
22
+ <p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/908" target="_blank" style={{color:'#0C41BD'}}>issue #908</a>)</p>
23
+ </div>
10
24
 
25
+ <CriteriaSection>
26
+ <CriteriaCard icon="🔍" title="Structure sémantique et regroupement">
27
+ <ul>
28
+ <li><strong>Fieldset/Legend</strong> : Utilisation de <code>&lt;fieldset&gt;</code> et <code>&lt;legend&gt;</code> lorsque <code>fieldsetLabel</code> est fourni pour regrouper sémantiquement les champs</li>
29
+ <li><strong>Double entrée</strong> : Composant hybride avec slider visuel et champs textuels pour une accessibilité maximale</li>
30
+ <li><strong>Labels explicites</strong> : Champs texte avec labels personnalisables via <code>textFieldMinLabel</code> et <code>textFieldMaxLabel</code></li>
31
+ </ul>
32
+ </CriteriaCard>
11
33
 
12
- <div class="mt-2">
13
- <p>Rapport d’audit manuel : <a href="/audits/RangeField.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
14
- <p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/908" target="_blank" style={{color:'#0C41BD'}}>issue #908</a>)</p>
15
- </div>
34
+ <CriteriaCard icon="⌨️" title="Navigation et interaction clavier">
35
+ <ul>
36
+ <li><strong>Input numérique</strong> : Champs texte avec <code>inputmode="numeric"</code> pour optimiser le clavier mobile</li>
37
+ <li><strong>Validation synchrone</strong> : Mise à jour bidirectionnelle entre slider et champs texte pour une cohérence immédiate</li>
38
+ <li><strong>Contraintes logiques</strong> : Validation automatique pour garantir min ≤ max avec corrections appropriées</li>
39
+ </ul>
40
+ </CriteriaCard>
41
+
42
+ <CriteriaCard icon="🎨" title="Masque saisie et formatage">
43
+ <ul>
44
+ <li><strong>vMaska</strong> : Masque de saisie personnalisé pour gérer nombres négatifs et décimaux</li>
45
+ <li><strong>Pattern flexible</strong> : Support des formats comme "-123.45" avec tokens adaptés</li>
46
+ <li><strong>Clamp automatique</strong> : Correction des valeurs hors limites avec <code>clamp()</code></li>
47
+ </ul>
48
+ </CriteriaCard>
49
+
50
+ <CriteriaCard icon="📱" title="Responsive et adaptabilité">
51
+ <ul>
52
+ <li><strong>Layout adaptatif</strong> : Orientation des champs qui passe de horizontal à vertical sur mobile</li>
53
+ <li><strong>Display Vuetify</strong> : Utilisation de <code>useDisplay()</code> pour détecter les tailles d'écran</li>
54
+ <li><strong>Options personnalisables</strong> : Composant entièrement configurable via <code>useCustomizableOptions</code></li>
55
+ </ul>
56
+ </CriteriaCard>
57
+ </CriteriaSection>
58
+
59
+ <DemoSection componentName="RangeField">
60
+ <Primary />
61
+ </DemoSection>
62
+
63
+ <BestPracticesSection>
64
+ <ul>
65
+ <li><strong>Labels descriptifs</strong> : Utilisez des labels clairs pour les champs min/max ("Prix minimum", "Âge maximum")</li>
66
+ <li><strong>Fieldset cohérent</strong> : Regroupez les champs avec un <code>fieldsetLabel</code> pertinent ("Fourchette de prix", "Plage d'âge")</li>
67
+ <li><strong>Valeurs par défaut</strong> : Initialisez toujours <code>modelValue</code> avec une plage valide [min, max]</li>
68
+ <li><strong>Step approprié</strong> : Choisissez un <code>step</code> logique (1 pour les entiers, 0.1 pour les décimales)</li>
69
+ <li><strong>Validation côté serveur</strong> : Complétez la validation client avec des vérifications serveur pour la sécurité</li>
70
+ <li><strong>Feedback utilisateur</strong> : Ajoutez des messages d'aide ou d'erreur pour guider l'utilisateur</li>
71
+ </ul>
72
+ </BestPracticesSection>
73
+
74
+ <ResourcesSection>
75
+ <ul>
76
+ <li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/slider/" target="_blank" rel="noopener noreferrer">Guide des pratiques WAI-ARIA : Sliders</a></li>
77
+ <li><a href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener noreferrer">Référence rapide WCAG 2.1</a></li>
78
+ <li><a href="https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.9" target="_blank" rel="noopener noreferrer">RGAA Critère 11.9 : Champs de saisie numérique</a></li>
79
+ <li><a href="https://developer.mozilla.org/fr/docs/Web/HTML/Element/Input/number" target="_blank" rel="noopener noreferrer">MDN : Champs input number et inputmode</a></li>
80
+ </ul>
81
+ </ResourcesSection>
82
+
83
+ </AccessibilityGuideLayout>
@@ -0,0 +1,23 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { describe, it } from 'vitest'
4
+ import { mount } from '@vue/test-utils'
5
+ import { axe } from 'vitest-axe'
6
+ import { assertNoA11yViolations } from '@tests/unit/accessibility/axeUtils'
7
+ import SkipLink from '../SkipLink.vue'
8
+
9
+ describe('SkipLink – accessibility (axe)', () => {
10
+ it('has no obvious axe violations', async () => {
11
+ const wrapper = mount(SkipLink, {
12
+ props: {
13
+ links: [
14
+ { label: 'Aller au contenu', href: '#main' },
15
+ { label: 'Aller à la navigation', href: '#nav' },
16
+ ],
17
+ },
18
+ })
19
+
20
+ const results = await axe(wrapper.element as HTMLElement)
21
+ assertNoA11yViolations(results, 'SkipLink – default state')
22
+ })
23
+ })