@cnamts/synapse 0.0.8-alpha → 0.0.9-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 (111) hide show
  1. package/dist/design-system-v3.d.ts +584 -128
  2. package/dist/design-system-v3.js +4176 -2694
  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/DatePicker.mdx +191 -0
  20. package/src/components/DatePicker/DatePicker.stories.ts +787 -0
  21. package/src/components/DatePicker/DatePicker.vue +560 -0
  22. package/src/components/DatePicker/DateTextInput.vue +409 -0
  23. package/src/components/DatePicker/tests/DatePicker.spec.ts +266 -0
  24. package/src/components/DialogBox/DialogBox.stories.ts +1 -1
  25. package/src/components/ExternalLinks/Accessibilite.mdx +14 -0
  26. package/src/components/ExternalLinks/Accessibilite.stories.ts +191 -0
  27. package/src/components/ExternalLinks/AccessibiliteItems.ts +197 -0
  28. package/src/components/ExternalLinks/constants/ExpertiseLevelEnum.ts +4 -0
  29. package/src/components/ExternalLinks/tests/__snapshots__/ExternalLinks.spec.ts.snap +9 -9
  30. package/src/components/FileUpload/FileUpload.mdx +165 -0
  31. package/src/components/FileUpload/FileUpload.stories.ts +429 -0
  32. package/src/components/FileUpload/FileUpload.vue +195 -0
  33. package/src/components/FileUpload/FileUploadContent.vue +109 -0
  34. package/src/components/FileUpload/locales.ts +10 -0
  35. package/src/components/FileUpload/tests/FileUpload.spec.ts +332 -0
  36. package/src/components/FileUpload/tests/__snapshots__/FileUpload.spec.ts.snap +7 -0
  37. package/src/components/FileUpload/useFileDrop.ts +23 -0
  38. package/src/components/FileUpload/validateFiles.ts +39 -0
  39. package/src/components/NirField/NirField.stories.ts +1 -1
  40. package/src/components/NirField/NirField.vue +2 -1
  41. package/src/components/PasswordField/Accessibilite.mdx +14 -0
  42. package/src/components/PasswordField/Accessibilite.stories.ts +191 -0
  43. package/src/components/PasswordField/AccessibiliteItems.ts +184 -0
  44. package/src/components/PasswordField/PasswordField.vue +3 -3
  45. package/src/components/PasswordField/constants/ExpertiseLevelEnum.ts +4 -0
  46. package/src/components/PhoneField/PhoneField.vue +44 -60
  47. package/src/components/PhoneField/tests/PhoneField.spec.ts +0 -15
  48. package/src/components/RangeField/RangeField.mdx +54 -0
  49. package/src/components/RangeField/RangeField.stories.ts +189 -0
  50. package/src/components/RangeField/RangeField.vue +157 -0
  51. package/src/components/RangeField/RangeSlider/RangeSlider.vue +387 -0
  52. package/src/components/RangeField/RangeSlider/Tooltip/Tooltip.vue +64 -0
  53. package/src/components/RangeField/RangeSlider/tests/__snapshots__/rangeSlider.spec.ts.snap +27 -0
  54. package/src/components/RangeField/RangeSlider/tests/rangeSlider.spec.ts +100 -0
  55. package/src/components/RangeField/RangeSlider/tests/useDoubleSlider.spec.ts +246 -0
  56. package/src/components/RangeField/RangeSlider/tests/useMouseSlide.spec.ts +204 -0
  57. package/src/components/RangeField/RangeSlider/tests/useThumb.spec.ts +22 -0
  58. package/src/components/RangeField/RangeSlider/tests/useThumbKeyboard.spec.ts +233 -0
  59. package/src/components/RangeField/RangeSlider/tests/useTooltipsNudge.spec.ts +150 -0
  60. package/src/components/RangeField/RangeSlider/tests/useTrack.spec.ts +314 -0
  61. package/src/components/RangeField/RangeSlider/tests/vAnimateClick.spec.ts +32 -0
  62. package/src/components/RangeField/RangeSlider/types.ts +15 -0
  63. package/src/components/RangeField/RangeSlider/useMouseSlide.ts +109 -0
  64. package/src/components/RangeField/RangeSlider/useRangeSlider.ts +126 -0
  65. package/src/components/RangeField/RangeSlider/useThumb.ts +18 -0
  66. package/src/components/RangeField/RangeSlider/useThumbKeyboard.ts +84 -0
  67. package/src/components/RangeField/RangeSlider/useTooltipsNudge.ts +92 -0
  68. package/src/components/RangeField/RangeSlider/useTrack.ts +116 -0
  69. package/src/components/RangeField/RangeSlider/vAnimateClick.ts +19 -0
  70. package/src/components/RangeField/config.ts +7 -0
  71. package/src/components/RangeField/locales.ts +4 -0
  72. package/src/components/RangeField/tests/RangeField.spec.ts +224 -0
  73. package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +379 -0
  74. package/src/components/RatingPicker/EmotionPicker/EmotionPicker.vue +205 -0
  75. package/src/components/RatingPicker/EmotionPicker/locales.ts +3 -0
  76. package/src/components/RatingPicker/EmotionPicker/tests/EmotionPicker.spec.ts +104 -0
  77. package/src/components/RatingPicker/EmotionPicker/tests/__snapshots__/EmotionPicker.spec.ts.snap +66 -0
  78. package/src/components/RatingPicker/NumberPicker/NumberPicker.vue +159 -0
  79. package/src/components/RatingPicker/NumberPicker/locales.ts +4 -0
  80. package/src/components/RatingPicker/NumberPicker/tests/NumberPicker.spec.ts +73 -0
  81. package/src/components/RatingPicker/NumberPicker/tests/__snapshots__/NumberPicker.spec.ts.snap +105 -0
  82. package/src/components/RatingPicker/Rating.ts +45 -0
  83. package/src/components/RatingPicker/RatingPicker.mdx +56 -0
  84. package/src/components/RatingPicker/RatingPicker.stories.ts +515 -0
  85. package/src/components/RatingPicker/RatingPicker.vue +122 -0
  86. package/src/components/RatingPicker/StarsPicker/StarsPicker.vue +116 -0
  87. package/src/components/RatingPicker/StarsPicker/tests/StarsPicker.spec.ts +95 -0
  88. package/src/components/RatingPicker/StarsPicker/tests/__snapshots__/StarsPicker.spec.ts.snap +36 -0
  89. package/src/components/RatingPicker/locales.ts +3 -0
  90. package/src/components/RatingPicker/tests/Rating.spec.ts +104 -0
  91. package/src/components/RatingPicker/tests/RatingPicker.spec.ts +187 -0
  92. package/src/components/RatingPicker/tests/__snapshots__/RatingPicker.spec.ts.snap +108 -0
  93. package/src/components/SearchListField/SearchListField.mdx +74 -0
  94. package/src/components/SearchListField/SearchListField.stories.ts +126 -0
  95. package/src/components/SearchListField/SearchListField.vue +194 -0
  96. package/src/components/SearchListField/locales.ts +5 -0
  97. package/src/components/SearchListField/tests/SearchListField.spec.ts +323 -0
  98. package/src/components/SearchListField/types.d.ts +4 -0
  99. package/src/components/SelectBtnField/SelectBtnField.mdx +50 -0
  100. package/src/components/SelectBtnField/SelectBtnField.stories.ts +763 -0
  101. package/src/components/SelectBtnField/SelectBtnField.vue +283 -0
  102. package/src/components/SelectBtnField/config.ts +11 -0
  103. package/src/components/SelectBtnField/tests/SelectBtnField.spec.ts +327 -0
  104. package/src/components/SelectBtnField/tests/__snapshots__/SelectBtnField.spec.ts.snap +125 -0
  105. package/src/components/SelectBtnField/types.d.ts +11 -0
  106. package/src/components/index.ts +8 -1
  107. package/src/composables/rules/useFieldValidation.ts +172 -44
  108. package/src/designTokens/index.ts +3 -3
  109. package/src/stories/Fondamentaux/CustomisationEtThemes.mdx +52 -2
  110. package/src/utils/calcHumanFileSize/index.ts +12 -0
  111. package/src/utils/calcHumanFileSize/tests/calcHumanFileSize.spec.ts +21 -0
@@ -0,0 +1,125 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`SelectBtnField > display correctly in dark mode with an error 1`] = `
4
+ "<div class="v-application v-theme--light v-layout v-layout--full-height v-locale--is-ltr">
5
+ <div class="v-application__wrap">
6
+ <div>
7
+ <div data-v-b3dd75c6="" class="select-btn-field">
8
+ <ul data-v-b3dd75c6="" class="v-btn-group v-theme--dark v-btn-group--density-default v-btn-toggle select-btn-field-toggle d-flex flex-wrap text-primary" aria-label="Test">
9
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--dark v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center text-error justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test1"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
10
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 1</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--dark v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
11
+ <!---->
12
+ <!---->
13
+ </button></li>
14
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--dark v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center text-error justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test2"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
15
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 2</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--dark v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
16
+ <!---->
17
+ <!---->
18
+ </button></li>
19
+ </ul>
20
+ <p data-v-b3dd75c6="" class="theme--dark v-messages text-error px-3 mt-2 mb-0 opacity-100">Test</p>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </div>"
25
+ `;
26
+
27
+ exports[`SelectBtnField > display correctly with an error 1`] = `
28
+ "<div data-v-b3dd75c6="" class="form-input select-btn-field">
29
+ <ul data-v-b3dd75c6="" class="v-btn-group v-theme--light v-btn-group--density-default v-btn-toggle d-flex flex-column select-btn-field-toggle d-flex flex-wrap text-primary" aria-label="Test">
30
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center text-error justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
31
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
32
+ <!---->
33
+ <!---->
34
+ </button></li>
35
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center text-error justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test2"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
36
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 2</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
37
+ <!---->
38
+ <!---->
39
+ </button></li>
40
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center text-error justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test3"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
41
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 3</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
42
+ <!---->
43
+ <!---->
44
+ </button></li>
45
+ </ul>
46
+ <p data-v-b3dd75c6="" class="theme--light v-messages text-error px-3 mt-2 mb-0 opacity-100">Test</p>
47
+ </div>"
48
+ `;
49
+
50
+ exports[`SelectBtnField > display correctly with in dark mode with an hint 1`] = `
51
+ "<div class="v-application v-theme--light v-layout v-layout--full-height v-locale--is-ltr">
52
+ <div class="v-application__wrap">
53
+ <div>
54
+ <div data-v-b3dd75c6="" class="select-btn-field">
55
+ <ul data-v-b3dd75c6="" class="v-btn-group v-theme--dark v-btn-group--density-default v-btn-toggle select-btn-field-toggle d-flex flex-wrap text-primary" aria-label="Test">
56
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--dark v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test1"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
57
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 1</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--dark v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
58
+ <!---->
59
+ <!---->
60
+ </button></li>
61
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--dark v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test2"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
62
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 2</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--dark v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
63
+ <!---->
64
+ <!---->
65
+ </button></li>
66
+ </ul>
67
+ <p data-v-b3dd75c6="" class="theme--dark v-messages px-3 mt-2 mb-0 opacity-100">Test</p>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </div>"
72
+ `;
73
+
74
+ exports[`SelectBtnField > render correctly in multiple mode 1`] = `
75
+ "<div data-v-b3dd75c6="" class="form-input select-btn-field">
76
+ <ul data-v-b3dd75c6="" class="v-btn-group v-theme--light v-btn-group--density-default v-btn-toggle d-flex flex-column select-btn-field-toggle d-flex flex-wrap text-primary" aria-label="Test">
77
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
78
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
79
+ <!---->
80
+ <!---->
81
+ </button></li>
82
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value=""><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
83
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 2</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
84
+ <!---->
85
+ <!---->
86
+ </button></li>
87
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test3"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
88
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 3</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
89
+ <!---->
90
+ <!---->
91
+ </button></li>
92
+ </ul>
93
+ <p data-v-b3dd75c6="" class="theme--light v-messages px-3 mt-2 mb-0 opacity-100">Test</p>
94
+ </div>"
95
+ `;
96
+
97
+ exports[`SelectBtnField > renders correctly 1`] = `
98
+ "<div data-v-b3dd75c6="" class="form-input select-btn-field">
99
+ <ul data-v-b3dd75c6="" class="v-btn-group v-theme--light v-btn-group--density-default v-btn-toggle d-flex flex-column select-btn-field-toggle d-flex flex-wrap text-primary"></ul>
100
+ <!--v-if-->
101
+ </div>"
102
+ `;
103
+
104
+ exports[`SelectBtnField > renders correctly with props 1`] = `
105
+ "<div data-v-b3dd75c6="" class="form-input select-btn-field">
106
+ <ul data-v-b3dd75c6="" class="v-btn-group v-theme--light v-btn-group--density-default v-btn-toggle d-flex flex-column select-btn-field-toggle d-flex flex-wrap text-primary" aria-label="Test">
107
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
108
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
109
+ <!---->
110
+ <!---->
111
+ </button></li>
112
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value=""><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
113
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 2</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
114
+ <!---->
115
+ <!---->
116
+ </button></li>
117
+ <li data-v-b3dd75c6="" class="select-list-item"><button data-v-b3dd75c6="" type="button" class="v-btn v-btn--flat v-theme--light v-btn--density-default elevation-0 v-btn--size-default v-btn--variant-outlined py-2 d-flex align-items-center justify-start" style="height: auto; min-height: 40px;" activeclass="text-white" aria-expanded="true" label="" value="test3"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
118
+ <!----><span class="v-btn__content" data-no-activator=""><span data-v-b3dd75c6="" class="text-body-1">Test 3</span><i data-v-b3dd75c6="" class="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z mdi v-icon notranslate v-theme--light v-icon--size-default text-white flex-shrink-0 ml-1" style="visibility: hidden;" role="img" aria-hidden="true" aria-label="Sélectionné"></i></span>
119
+ <!---->
120
+ <!---->
121
+ </button></li>
122
+ </ul>
123
+ <p data-v-b3dd75c6="" class="theme--light v-messages px-3 mt-2 mb-0 opacity-100">Test</p>
124
+ </div>"
125
+ `;
@@ -0,0 +1,11 @@
1
+ export type SelectBtnValue =
2
+ | string
3
+ | number
4
+ | Array<string | number | null | undefined>
5
+ | null
6
+
7
+ export interface SelectBtnItem {
8
+ text: string
9
+ value: string | number
10
+ unique?: boolean
11
+ }
@@ -1,3 +1,6 @@
1
+ export { default as DatePicker } from '@/components/DatePicker/DatePicker.vue'
2
+ export { useFieldValidation } from '../composables/rules/useFieldValidation'
3
+ export type { RuleOptions } from '../composables/rules/useFieldValidation'
1
4
  export { useNotificationService } from '../services/NotificationService'
2
5
  export { default as BackBtn } from './BackBtn/BackBtn.vue'
3
6
  export { default as BackToTopBtn } from './BackToTopBtn/BackToTopBtn.vue'
@@ -19,6 +22,7 @@ export { default as DialogBox } from './DialogBox/DialogBox.vue'
19
22
  export { default as DownloadBtn } from './DownloadBtn/DownloadBtn.vue'
20
23
  export { default as ErrorPage } from './ErrorPage/ErrorPage.vue'
21
24
  export { default as ExternalLinks } from './ExternalLinks/ExternalLinks.vue'
25
+ export { default as FileUpload } from './FileUpload/FileUpload.vue'
22
26
  export { default as FooterBar } from './FooterBar/FooterBar.vue'
23
27
  export { default as FranceConnectBtn } from './FranceConnectBtn/FranceConnectBtn.vue'
24
28
  export { default as HeaderBar } from './HeaderBar/HeaderBar.vue'
@@ -41,10 +45,13 @@ export { default as NotFoundPage } from './NotFoundPage/NotFoundPage.vue'
41
45
  export { default as NotificationBar } from './NotificationBar/NotificationBar.vue'
42
46
  export * from './NotificationBar/types'
43
47
  export { default as PageContainer } from './PageContainer/PageContainer.vue'
48
+ export { default as PasswordField } from './PasswordField/PasswordField.vue'
44
49
  export { default as PhoneField } from './PhoneField/PhoneField.vue'
50
+ export { default as RangeField } from './RangeField/RangeField.vue'
51
+ export { default as RatingPicker } from './RatingPicker/RatingPicker.vue'
52
+ export { default as SelectBtnField } from './SelectBtnField/SelectBtnField.vue'
45
53
  export { default as SkipLink } from './SkipLink/SkipLink.vue'
46
54
  export { default as SocialMediaLinks } from './SocialMediaLinks/SocialMediaLinks.vue'
47
55
  export { default as SubHeader } from './SubHeader/SubHeader.vue'
48
56
  export { default as SyAlert } from './SyAlert/SyAlert.vue'
49
57
  export { default as UserMenuBtn } from './UserMenuBtn/UserMenuBtn.vue'
50
- export { default as PasswordField } from './PasswordField/PasswordField.vue'
@@ -1,88 +1,216 @@
1
- type RuleOptions = {
2
- fieldName?: string
1
+ export type ValidationResult = {
2
+ success?: string
3
+ error?: string
4
+ warning?: string
5
+ }
6
+
7
+ export type RuleOptions = {
3
8
  message?: string
4
9
  successMessage?: string
10
+ warningMessage?: string
11
+ fieldName?: string
12
+ fieldIdentifier?: string
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
14
+ value?: any
5
15
  length?: number
6
- value?: number
7
16
  pattern?: RegExp
8
17
  ignoreSpace?: boolean
9
- fieldIdentifier?: string
18
+ isWarning?: boolean // Si true, la règle génère un warning au lieu d'une erreur
10
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
11
20
  validate?: (value: any) => boolean | string
21
+ date?: string | Date // Date de référence pour les règles notBeforeDate et notAfterDate
12
22
  }
13
23
 
14
- type ValidationResult = {
15
- success?: string
16
- error?: string
17
- }
18
24
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
19
- type ValidationRule = (value: any) => ValidationResult
25
+ export type ValidationRule = (value: any) => ValidationResult
20
26
 
21
27
  export function useFieldValidation() {
28
+ const getValueLength = (value: string, ignoreSpace?: boolean): number => {
29
+ return ignoreSpace ? value.replace(/\s/g, '').length : value.length
30
+ }
31
+
22
32
  const createRule = (type: string, options: RuleOptions = {}): ValidationRule => {
23
- const getValueLength = (value: string) => {
24
- return options.ignoreSpace ? value.replace(/\s/g, '').length : value.length
25
- }
26
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
27
- return (value: any) => {
34
+ return (value: any): ValidationResult => {
35
+ // Gestion des champs vides non obligatoires
28
36
  if (type !== 'required' && typeof value === 'string' && value.trim() === '') {
29
37
  return {}
30
38
  }
39
+
40
+ // Identifier de champ pour personnaliser les messages
41
+ const identifier = options.fieldIdentifier
42
+ ? `${options.fieldIdentifier}`
43
+ : options.fieldName || 'ce champ'
44
+
45
+ const baseMessages = {
46
+ success: options.successMessage || 'Le champ est valide.',
47
+ error: options.message || `Validation échouée pour ${identifier}.`,
48
+ warning: options.warningMessage || `Attention : ${identifier} peut contenir une erreur.`,
49
+ }
50
+
51
+ const createValidationResult = (isValid: boolean, message?: string): ValidationResult => {
52
+ if (isValid) {
53
+ return { success: baseMessages.success }
54
+ }
55
+ return options.isWarning
56
+ ? { warning: message || baseMessages.warning }
57
+ : { error: message || baseMessages.error }
58
+ }
59
+
31
60
  switch (type) {
32
61
  case 'required':
33
- return typeof value === 'string' && value.trim()
34
- ? { success: options.successMessage || 'Le champ est valide.' }
35
- : { error: options.message || `Vous devez renseigner ${options.fieldName || 'ce champ'}.` }
62
+ return createValidationResult(
63
+ typeof value === 'string' && value.trim() !== '',
64
+ options.message || `Vous devez renseigner ${identifier}.`,
65
+ )
36
66
 
37
67
  case 'min':
38
- return typeof value === 'number' && value >= (options.value ?? 0)
39
- ? { success: options.successMessage || 'Le champ est valide.' }
40
- : { error: options.message || `La valeur doit être supérieure ou égale à ${options.value}.` }
41
-
42
- case 'minLength':
43
- return typeof value === 'string' && getValueLength(value) >= (options.length ?? 0)
44
- ? { success: options.successMessage || 'Le champ est valide.' }
45
- : { error: options.message || `Ce champ doit avoir au moins ${options.length} caractères.` }
68
+ return createValidationResult(
69
+ typeof value === 'number' && value >= (options.value ?? 0),
70
+ options.message || `La valeur de ${identifier} doit être supérieure ou égale à ${options.value}.`,
71
+ )
46
72
 
47
73
  case 'max':
48
- return typeof value === 'number' && value <= (options.value ?? Infinity)
49
- ? { success: options.successMessage || 'Le champ est valide.' }
50
- : { error: options.message || `La valeur doit être inférieure ou égale à ${options.value}.` }
74
+ return createValidationResult(
75
+ typeof value === 'number' && value <= (options.value ?? Infinity),
76
+ options.message || `La valeur de ${identifier} doit être inférieure ou égale à ${options.value}.`,
77
+ )
78
+
79
+ case 'minLength':
80
+ return createValidationResult(
81
+ typeof value === 'string' && getValueLength(value, options.ignoreSpace) >= (options.length ?? 0),
82
+ options.message || `${identifier} doit contenir au moins ${options.length} caractères.`,
83
+ )
51
84
 
52
85
  case 'maxLength':
53
- return typeof value === 'string' && getValueLength(value) <= (options.length ?? Infinity)
54
- ? { success: options.successMessage || 'Le champ est valide.' }
55
- : { error: options.message || `Ce champ ne doit pas dépasser ${options.length} caractères.` }
86
+ return createValidationResult(
87
+ typeof value === 'string' && getValueLength(value, options.ignoreSpace) <= (options.length ?? Infinity),
88
+ options.message || `${identifier} ne doit pas dépasser ${options.length} caractères.`,
89
+ )
56
90
 
57
91
  case 'exactLength':
58
- return typeof value === 'string' && getValueLength(value) === (options.length ?? 0)
59
- ? { success: options.successMessage || 'Le champ est valide.' }
60
- : { error: options.message || `Ce champ doit avoir exactement ${options.length} caractères.` }
92
+ return createValidationResult(
93
+ typeof value === 'string' && getValueLength(value, options.ignoreSpace) === (options.length ?? 0),
94
+ options.message || `${identifier} doit contenir exactement ${options.length} caractères.`,
95
+ )
61
96
 
62
97
  case 'email':
63
- return typeof value === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
64
- ? { success: options.successMessage || 'Le champ est valide.' }
65
- : { error: options.message || `Veuillez entrer un email valide.` }
98
+ return createValidationResult(
99
+ typeof value === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
100
+ options.message || `${identifier} doit être un email valide.`,
101
+ )
66
102
 
67
103
  case 'matchPattern':
68
- return typeof value === 'string' && options.pattern?.test(value)
69
- ? { success: options.successMessage || 'Le champ est valide.' }
70
- : { error: options.message || `Format invalide.` }
104
+ return createValidationResult(
105
+ typeof value === 'string' && !!options.pattern && options.pattern.test(value),
106
+ options.message || `Le format de ${identifier} est invalide.`,
107
+ )
108
+
109
+ case 'notWeekend': {
110
+ const dateValue = new Date(value)
111
+ return createValidationResult(
112
+ !(dateValue.getDay() === 0 || dateValue.getDay() === 6),
113
+ options.message || `${identifier} ne peut pas être un jour de weekend.`,
114
+ )
115
+ }
116
+
117
+ case 'notBeforeToday': {
118
+ const dateValue = new Date(value)
119
+ return createValidationResult(
120
+ dateValue >= new Date(),
121
+ options.message || `${identifier} ne peut pas être antérieur à aujourd'hui.`,
122
+ )
123
+ }
124
+
125
+ case 'notAfterToday': {
126
+ const dateValue = new Date(value)
127
+ return createValidationResult(
128
+ dateValue <= new Date(),
129
+ options.message || `${identifier} ne peut pas être postérieur à aujourd'hui.`,
130
+ )
131
+ }
132
+
133
+ case 'notBeforeDate': {
134
+ if (!options.date) {
135
+ return { error: 'Configuration de la règle invalide' }
136
+ }
137
+
138
+ const dateValue = new Date(value)
139
+
140
+ // Check if options.date is a string and in DD/MM/YYYY format
141
+ if (typeof options.date !== 'string') {
142
+ throw new Error('Date reference must be a string in DD/MM/YYYY format')
143
+ }
144
+
145
+ // Convert reference date from DD/MM/YYYY format to YYYY-MM-DD
146
+ const [day, month, year] = options.date.split('/')
147
+ const referenceDate = new Date(`${year}-${month}-${day}`)
148
+
149
+ return createValidationResult(
150
+ dateValue >= referenceDate,
151
+ options.message || `${identifier} ne peut pas être avant le ${options.date}.`,
152
+ )
153
+ }
154
+
155
+ case 'notAfterDate': {
156
+ if (!options.date) {
157
+ return { error: 'Configuration de la règle invalide' }
158
+ }
159
+
160
+ const dateValue = new Date(value)
161
+
162
+ // Check if options.date is a string and in DD/MM/YYYY format
163
+ if (typeof options.date !== 'string') {
164
+ throw new Error('Date reference must be a string in DD/MM/YYYY format')
165
+ }
166
+
167
+ // Convert reference date from DD/MM/YYYY format to YYYY-MM-DD
168
+ const [day, month, year] = options.date.split('/')
169
+ const referenceDate = new Date(`${year}-${month}-${day}`)
170
+
171
+ return createValidationResult(
172
+ dateValue <= referenceDate,
173
+ options.message || `${identifier} ne peut pas être après le ${options.date}.`,
174
+ )
175
+ }
176
+
177
+ case 'dateExact': {
178
+ if (!options.date) {
179
+ return { error: 'Configuration de la règle invalide' }
180
+ }
181
+
182
+ const dateValue = new Date(value)
183
+
184
+ if (typeof options.date !== 'string') {
185
+ throw new Error('Date reference must be a string in DD/MM/YYYY format')
186
+ }
187
+
188
+ const [day, month, year] = options.date.split('/')
189
+ const referenceDate = new Date(`${year}-${month}-${day}`)
190
+
191
+ return createValidationResult(
192
+ dateValue.getTime() === referenceDate.getTime(),
193
+ options.message || `${identifier} doit être exactement le ${options.date}.`,
194
+ )
195
+ }
71
196
 
72
197
  case 'custom': {
73
198
  const result = options.validate?.(value)
74
- return result === true
75
- ? { success: options.successMessage || 'Le champ est valide.' }
76
- : { error: typeof result === 'string' ? result : options.message || `Validation échouée.` }
199
+ if (result === true) {
200
+ return { success: baseMessages.success }
201
+ }
202
+ return options.isWarning
203
+ ? { warning: typeof result === 'string' ? result : baseMessages.warning }
204
+ : { error: typeof result === 'string' ? result : baseMessages.error }
77
205
  }
78
206
 
79
207
  default:
80
- return { error: `La règle spécifiée n'existe pas.` }
208
+ return { error: `La règle spécifiée pour ${identifier} n'existe pas.` }
81
209
  }
82
210
  }
83
211
  }
84
212
 
85
- const generateRules = (fieldRules: Array<{ type: string, options?: RuleOptions }>) => {
213
+ const generateRules = (fieldRules: Array<{ type: string, options?: RuleOptions }>): ValidationRule[] => {
86
214
  return fieldRules.map(rule => createRule(rule.type, rule.options))
87
215
  }
88
216
 
@@ -3,9 +3,9 @@ import { cnamContextualTokens } from './tokens/cnam/cnamContextual'
3
3
  import { cnamColorsTokens } from './tokens/cnam/cnamColors'
4
4
  import { cnamLightTheme } from './tokens/cnam/cnamLightTheme'
5
5
  import { cnamDarkTheme } from './tokens/cnam/cnamDarkTheme'
6
- import { paColorsTokens } from '@/designTokens/tokens/pa/paColors'
7
- import { paLightTheme } from '@/designTokens/tokens/pa/paLightTheme'
8
- import { paDarkTheme } from '@/designTokens/tokens/pa/paDarkTheme'
6
+ import { paColorsTokens } from './tokens/pa/paColors'
7
+ import { paLightTheme } from './tokens/pa/paLightTheme'
8
+ import { paDarkTheme } from './tokens/pa/paDarkTheme'
9
9
 
10
10
  export {
11
11
  cnamColorsTokens,
@@ -1,7 +1,57 @@
1
- import { Meta } from '@storybook/addon-docs';
1
+ import {Meta, Source} from '@storybook/addon-docs/blocks';
2
2
 
3
3
  <Meta title="Fondamentaux/Customisation et thèmes" />
4
4
 
5
5
  # Customisation et thèmes
6
6
 
7
- Contenu à définir
7
+ ## Étapes pour changer le thème du Design System aux couleurs Portail Agent
8
+
9
+ ### 1. Modification du fichier nuxt.config.ts
10
+
11
+ 1. Ouvrez le fichier nuxt.config.ts dans votre éditeur de code.
12
+ 2. Remplacer les valeurs des thèmes `cnamLightTheme` et `cnamDarkTheme` par les valeurs de la charte PA : `paLightTheme` et `paDarkTheme`.
13
+
14
+ <Source dark code={`
15
+ import {paLightTheme} from '@cnamts/synapse/designTokens/tokens/pa/paLightTheme'
16
+ import {paDarkTheme} from '@cnamts/synapse/designTokens/tokens/pa/paDarkTheme'
17
+ `}
18
+ />
19
+
20
+ 3. Localisez la configuration de base de Vuetify (ligne 31 dans le fichier `nuxt.config.ts`).
21
+ 4. Mettez à jour le thème en configurant les couleurs selon la charte PA si nécessaire :
22
+
23
+ <Source dark code={`
24
+ theme: {
25
+ defaultTheme: 'light',
26
+ themes: {
27
+ light: {
28
+ colors: {
29
+ ...paLightTheme,
30
+ // ...customLightTheme
31
+ },
32
+ },
33
+ dark: {
34
+ colors: {
35
+ ...paDarkTheme,
36
+ //...customDarkTheme,
37
+ },
38
+ },
39
+ },
40
+ },
41
+ `}
42
+ />
43
+
44
+ NB : les thèmes `customLightTheme` et `customDarkTheme` sont à votre disposition pour ajouter des couleurs supplémentaires.
45
+
46
+ ### 2. Relancer le projet
47
+
48
+ Après avoir effectué les modifications dans le fichier de configuration, relancez le serveur de développement pour appliquer les changements :
49
+
50
+ <Source dark code={`
51
+ pnpm dev
52
+ `}
53
+ />
54
+
55
+ ### 3. Vérification
56
+
57
+ Une fois le projet redémarré, vérifiez que la charte PA est bien appliquée.
@@ -0,0 +1,12 @@
1
+ /** Compute a size in bytes into an human readable value */
2
+ export function calcHumanFileSize(
3
+ size: number,
4
+ fileSizeUnits: string[],
5
+ separator = ' ',
6
+ ): string {
7
+ const index = Math.floor(Math.log(size) / Math.log(1024))
8
+
9
+ const computedSize = Number((size / Math.pow(1024, index)).toFixed(2)) * 1
10
+
11
+ return computedSize + separator + fileSizeUnits[index]
12
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, it, expect } from 'vitest'
2
+
3
+ import { calcHumanFileSize } from '../'
4
+
5
+ const sizeMax = 4096 * 1024 // 4MB
6
+
7
+ const fileSizeUnits = ['B', 'KB', 'MB', 'GB', 'TB']
8
+
9
+ describe('calcHumanFileSize', () => {
10
+ it('returns the readable size', () => {
11
+ expect(calcHumanFileSize(sizeMax, fileSizeUnits)).toEqual('4 MB')
12
+ })
13
+
14
+ it('returns the readable size with a custom text separator', () => {
15
+ const separator = '_'
16
+
17
+ expect(calcHumanFileSize(sizeMax, fileSizeUnits, separator)).toEqual(
18
+ '4_MB',
19
+ )
20
+ })
21
+ })