@cnamts/synapse 1.0.11 → 1.0.13

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 (200) hide show
  1. package/dist/{DateFilter-QEfKOz0P.js → DateFilter-_EFzsvvM.js} +1 -1
  2. package/dist/{NumberFilter-C0h7gVzp.js → NumberFilter-CUxEbKJh.js} +1 -1
  3. package/dist/{PeriodFilter-8dVrKjju.js → PeriodFilter-D5ueqtKy.js} +1 -1
  4. package/dist/{SelectFilter-BI3QGbqb.js → SelectFilter-BciBNydy.js} +1 -1
  5. package/dist/{TextFilter-UOp1hcPp.js → TextFilter-DMN_WAQB.js} +1 -1
  6. package/dist/components/Amelipro/AmeliproAccordion/AmeliproAccordion.d.ts +7 -3
  7. package/dist/components/Amelipro/AmeliproAccordion/AmeliproAccordionTemplate/AmeliproAccordionTemplate.d.ts +1 -1
  8. package/dist/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.d.ts +2 -0
  9. package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.d.ts +7 -3
  10. package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.d.ts +1 -1
  11. package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +50 -68
  12. package/dist/components/Amelipro/AmeliproCard/AmeliproCard.d.ts +1 -1
  13. package/dist/components/Amelipro/AmeliproIcon/AmeliproIcon.d.ts +1 -1
  14. package/dist/components/Amelipro/AmeliproIconBtn/AmeliproIconBtn.d.ts +5 -5
  15. package/dist/components/Amelipro/AmeliproMultipleFoldingCard/AmeliproMultipleFoldingCard.d.ts +1 -1
  16. package/dist/components/Amelipro/AmeliproNumberedCard/AmeliproNumberedCard.d.ts +1 -1
  17. package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressCityRow/AmeliproPostalAddressCityRow.d.ts +24 -32
  18. package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +36 -48
  19. package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +50 -68
  20. package/dist/components/Amelipro/AmeliproTable/AmeliproTable.d.ts +4 -0
  21. package/dist/components/Amelipro/AmeliproTable/types.d.ts +11 -0
  22. package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +50 -68
  23. package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +0 -4
  24. package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +12 -16
  25. package/dist/components/Captcha/Captcha.d.ts +68 -0
  26. package/dist/components/Captcha/CaptchaAlert.d.ts +13 -0
  27. package/dist/components/Captcha/CaptchaBase.d.ts +55 -0
  28. package/dist/components/Captcha/CaptchaBtn.d.ts +12 -0
  29. package/dist/components/Captcha/CaptchaForm.d.ts +16 -0
  30. package/dist/components/Captcha/CaptchaImg.d.ts +12 -0
  31. package/dist/components/Captcha/CaptchaInformation.d.ts +20 -0
  32. package/dist/components/Captcha/captchaApi.d.ts +41 -0
  33. package/dist/components/Captcha/icons/volumeUp.d.ts +2 -0
  34. package/dist/components/Captcha/locales.d.ts +35 -0
  35. package/dist/components/Captcha/types.d.ts +2 -0
  36. package/dist/components/ChipList/ChipList.d.ts +2 -2
  37. package/dist/components/CookiesSelection/CookiesInformation/CookiesInformation.d.ts +14 -14
  38. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +5 -5
  39. package/dist/components/Customs/SyForm/SyForm.d.ts +6 -3
  40. package/dist/components/Customs/SyTextField/SyTextField.d.ts +12 -16
  41. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +96 -68
  42. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +63 -38
  43. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +23 -27
  44. package/dist/components/DatePicker/composables/useDatePickerViewMode.d.ts +2 -1
  45. package/dist/components/DatePicker/tests/setup.d.ts +816 -520
  46. package/dist/components/HeaderToolbar/HeaderToolbar.d.ts +10 -10
  47. package/dist/components/NirField/NirField.d.ts +31 -34
  48. package/dist/components/NirField/locales.d.ts +1 -3
  49. package/dist/components/PasswordField/PasswordField.d.ts +2 -0
  50. package/dist/components/PeriodField/PeriodField.d.ts +192 -128
  51. package/dist/components/PhoneField/PhoneField.d.ts +13 -17
  52. package/dist/components/SearchListField/SearchListField.d.ts +5 -5
  53. package/dist/components/SyTextArea/SyTextArea.d.ts +0 -4
  54. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +5 -8
  55. package/dist/components/Tables/SyTable/SyTable.d.ts +5 -8
  56. package/dist/components/Tables/common/SyTablePagination.d.ts +5 -5
  57. package/dist/components/Tables/common/types.d.ts +4 -0
  58. package/dist/components/Tables/common/usePagination.d.ts +3 -4
  59. package/dist/components/Tables/common/useTableCheckbox.d.ts +10 -6
  60. package/dist/components/index.d.ts +1 -0
  61. package/dist/composables/validation/useFormValidation.d.ts +10 -0
  62. package/dist/composables/validation/useValidatable.d.ts +10 -2
  63. package/dist/design-system-v3.js +126 -125
  64. package/dist/design-system-v3.umd.cjs +265 -265
  65. package/dist/main-DISHlqcd.js +34217 -0
  66. package/dist/style.css +1 -1
  67. package/package.json +1 -1
  68. package/src/assets/overrides/_forms.scss +2 -0
  69. package/src/components/Amelipro/AmeliproAccordion/AmeliproAccordion.stories.ts +7 -4
  70. package/src/components/Amelipro/AmeliproAccordion/AmeliproAccordion.vue +2 -0
  71. package/src/components/Amelipro/AmeliproAccordionFrieze/AmeliproAccordionFrieze.vue +1 -0
  72. package/src/components/Amelipro/AmeliproAccordionFrieze/__tests__/__snapshots__/AmeliproAccordionFrieze.spec.ts.snap +574 -112
  73. package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.stories.ts +5 -2
  74. package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.vue +2 -1
  75. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.stories.ts +6 -3
  76. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.vue +2 -0
  77. package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.stories.ts +5 -2
  78. package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.vue +2 -1
  79. package/src/components/Amelipro/AmeliproCheckbox/__tests__/AmeliproCheckbox.spec.ts +175 -0
  80. package/src/components/Amelipro/AmeliproCheckbox/__tests__/__snapshots__/AmeliproCheckbox.spec.ts.snap +88 -0
  81. package/src/components/Amelipro/AmeliproCheckboxGroup/__tests__/AmeliproCheckboxGroup.spec.ts +423 -0
  82. package/src/components/Amelipro/AmeliproCheckboxGroup/{tests → __tests__}/__snapshots__/AmeliproCheckboxGroup.spec.ts.snap +112 -78
  83. package/src/components/Amelipro/AmeliproChips/__tests__/AmeliproChips.spec.ts +92 -0
  84. package/src/components/Amelipro/AmeliproChips/__tests__/__snapshots__/AmeliproChips.spec.ts.snap +81 -0
  85. package/src/components/Amelipro/AmeliproDialog/__tests__/AmeliproDialog.spec.ts +257 -0
  86. package/src/components/Amelipro/AmeliproDialog/__tests__/__snapshots__/AmeliproDialog.spec.ts.snap +61 -0
  87. package/src/components/Amelipro/AmeliproDisclosure/__tests__/AmeliproDisclosure.spec.ts +79 -0
  88. package/src/components/Amelipro/AmeliproDisclosure/__tests__/__snapshots__/AmeliproDisclosure.spec.ts.snap +89 -0
  89. package/src/components/Amelipro/AmeliproFooter/AmeliproFooter.vue +6 -7
  90. package/src/components/Amelipro/AmeliproFooter/__tests__/AmeliproFooter.spec.ts +787 -0
  91. package/src/components/Amelipro/AmeliproFooter/__tests__/__snapshots__/AmeliproFooter.spec.ts.snap +318 -0
  92. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/__tests__/AmeliproHeaderBrandSection.spec.ts +167 -0
  93. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/__tests__/__snapshots__/AmeliproHeaderBrandSection.spec.ts.snap +100 -0
  94. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/__tests__/AmeliproHeaderBar.spec.ts +312 -0
  95. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/__tests__/__snapshots__/AmeliproHeaderBar.spec.ts.snap +98 -0
  96. package/src/components/Amelipro/AmeliproHeader/__tests__/AmeliproHeader.spec.ts +361 -0
  97. package/src/components/Amelipro/AmeliproHeader/__tests__/__snapshots__/AmeliproHeader.spec.ts.snap +22 -0
  98. package/src/components/Amelipro/AmeliproMenu/__tests__/AmeliproMenu.spec.ts +168 -0
  99. package/src/components/Amelipro/AmeliproMenu/__tests__/__snapshots__/AmeliproMenu.spec.ts.snap +295 -0
  100. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/AmeliproDropdownMenuBtn/__tests__/AmeliproDropdownMenuBtn.spec.ts +128 -0
  101. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/AmeliproDropdownMenuBtn/__tests__/__snapshots__/AmeliproDropdownMenuBtn.spec.ts.snap +67 -0
  102. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/__tests__/AmeliproDropdownMenu.spec.ts +266 -0
  103. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/__tests__/__snapshots__/AmeliproDropdownMenu.spec.ts.snap +134 -0
  104. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproMessagingMenuBtn/__tests__/AmeliproMessagingMenuBtn.spec.ts +72 -0
  105. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproMessagingMenuBtn/__tests__/__snapshots__/AmeliproMessagingMenuBtn.spec.ts.snap +71 -0
  106. package/src/components/Amelipro/AmeliproPageLayout/tests/__snapshots__/AmeliproPageLayout.spec.ts.snap +12 -0
  107. package/src/components/Amelipro/AmeliproTable/AmeliproTable.stories.ts +81 -9
  108. package/src/components/Amelipro/AmeliproTable/AmeliproTable.vue +139 -61
  109. package/src/components/Amelipro/AmeliproTable/__tests__/AmeliproTable.spec.ts +10 -0
  110. package/src/components/Amelipro/AmeliproTable/__tests__/__snapshots__/AmeliproTable.spec.ts.snap +361 -187
  111. package/src/components/Amelipro/AmeliproTable/types.d.ts +11 -0
  112. package/src/components/Captcha/Captcha.mdx +72 -0
  113. package/src/components/Captcha/Captcha.stories.ts +276 -0
  114. package/src/components/Captcha/Captcha.vue +325 -0
  115. package/src/components/Captcha/CaptchaAlert.vue +60 -0
  116. package/src/components/Captcha/CaptchaBase.vue +219 -0
  117. package/src/components/Captcha/CaptchaBtn.vue +35 -0
  118. package/src/components/Captcha/CaptchaForm.vue +58 -0
  119. package/src/components/Captcha/CaptchaImg.vue +41 -0
  120. package/src/components/Captcha/CaptchaInformation.vue +64 -0
  121. package/src/components/Captcha/captchaApi.ts +111 -0
  122. package/src/components/Captcha/icons/volumeUp.vue +11 -0
  123. package/src/components/Captcha/locales.ts +35 -0
  124. package/src/components/Captcha/readme.md +5 -0
  125. package/src/components/Captcha/tests/Captcha.spec.ts +298 -0
  126. package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +716 -0
  127. package/src/components/Captcha/types.ts +2 -0
  128. package/src/components/Customs/Selects/SySelect/SySelect.vue +2 -2
  129. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +4 -0
  130. package/src/components/Customs/SyForm/SyForm.stories.ts +133 -23
  131. package/src/components/Customs/SyForm/SyForm.vue +17 -1
  132. package/src/components/Customs/SyTextField/SyTextField.vue +29 -7
  133. package/src/components/DatePicker/CalendarMode/DatePicker.vue +32 -9
  134. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +154 -18
  135. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +2 -2
  136. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +35 -4
  137. package/src/components/DatePicker/composables/tests/useDatePickerViewMode.spec.ts +107 -72
  138. package/src/components/DatePicker/composables/tests/useMonthButtonCustomization.spec.ts +6 -6
  139. package/src/components/DatePicker/composables/useDatePickerViewMode.ts +57 -7
  140. package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +14 -14
  141. package/src/components/DatePicker/tests/navigation.regression.spec.ts +74 -0
  142. package/src/components/DatePicker/tests/navigation.simple.spec.ts +137 -0
  143. package/src/components/NirField/NirField.stories.ts +85 -2
  144. package/src/components/NirField/NirField.vue +55 -18
  145. package/src/components/NirField/locales.ts +1 -3
  146. package/src/components/PasswordField/PasswordField.vue +39 -7
  147. package/src/components/PhoneField/PhoneField.vue +43 -10
  148. package/src/components/RangeField/tests/RangeField.spec.ts +0 -3
  149. package/src/components/Tables/SyServerTable/SyServerTable.mdx +15 -0
  150. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +309 -0
  151. package/src/components/Tables/SyServerTable/SyServerTable.vue +18 -3
  152. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +67 -0
  153. package/src/components/Tables/SyTable/SyTable.mdx +15 -0
  154. package/src/components/Tables/SyTable/SyTable.stories.ts +228 -0
  155. package/src/components/Tables/SyTable/SyTable.vue +18 -3
  156. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +63 -0
  157. package/src/components/Tables/common/SyTablePagination.vue +10 -8
  158. package/src/components/Tables/common/types.ts +4 -0
  159. package/src/components/Tables/common/usePagination.ts +11 -20
  160. package/src/components/Tables/common/useTableCheckbox.ts +23 -11
  161. package/src/components/index.ts +1 -0
  162. package/src/composables/validation/AvecVosComposants.mdx.old +1 -1
  163. package/src/composables/validation/FormValidation.stories.ts.old +5 -5
  164. package/src/composables/validation/useFormValidation.ts +46 -8
  165. package/src/composables/validation/useValidatable.ts +19 -8
  166. package/src/stories/Accessibilite/Introduction.mdx +1 -1
  167. package/src/stories/Demarrer/EnrichirLeDesignSystem.mdx +43 -0
  168. package/src/stories/Demarrer/EnrichirLeDesignSystem.stories.ts +239 -0
  169. package/src/stories/Demarrer/SignalerUneAnomalie.mdx +39 -0
  170. package/src/stories/Demarrer/SignalerUneAnomalie.stories.ts +261 -0
  171. package/dist/main-DyEOPqqn.js +0 -33329
  172. package/src/components/Amelipro/AmeliproCheckbox/tests/AmeliproCheckbox.spec.ts +0 -19
  173. package/src/components/Amelipro/AmeliproCheckbox/tests/__snapshots__/AmeliproCheckbox.spec.ts.snap +0 -40
  174. package/src/components/Amelipro/AmeliproCheckboxGroup/tests/AmeliproCheckboxGroup.spec.ts +0 -46
  175. package/src/components/Amelipro/AmeliproChips/tests/AmeliproChips.spec.ts +0 -16
  176. package/src/components/Amelipro/AmeliproChips/tests/__snapshots__/AmeliproChips.spec.ts.snap +0 -97
  177. package/src/components/Amelipro/AmeliproDialog/tests/AmeliproDialog.spec.ts +0 -24
  178. package/src/components/Amelipro/AmeliproDialog/tests/__snapshots__/AmeliproDialog.spec.ts.snap +0 -134
  179. package/src/components/Amelipro/AmeliproDisclosure/tests/AmeliproDisclosure.spec.ts +0 -19
  180. package/src/components/Amelipro/AmeliproDisclosure/tests/__snapshots__/AmeliproDisclosure.spec.ts.snap +0 -104
  181. package/src/components/Amelipro/AmeliproFooter/tests/AmeliproFooter.spec.ts +0 -15
  182. package/src/components/Amelipro/AmeliproFooter/tests/__snapshots__/AmeliproFooter.spec.ts.snap +0 -432
  183. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/tests/AmeliproHeaderBrandSection.spec.ts +0 -15
  184. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/AmeliproHeaderBrandSection/tests/__snapshots__/AmeliproHeaderBrandSection.spec.ts.snap +0 -131
  185. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/tests/AmeliproHeaderBar.spec.ts +0 -15
  186. package/src/components/Amelipro/AmeliproHeader/AmeliproHeaderBar/tests/__snapshots__/AmeliproHeaderBar.spec.ts.snap +0 -172
  187. package/src/components/Amelipro/AmeliproHeader/tests/AmeliproHeader.spec.ts +0 -159
  188. package/src/components/Amelipro/AmeliproHeader/tests/__snapshots__/AmeliproHeader.spec.ts.snap +0 -841
  189. package/src/components/Amelipro/AmeliproMenu/tests/AmeliproMenu.spec.ts +0 -85
  190. package/src/components/Amelipro/AmeliproMenu/tests/__snapshots__/AmeliproMenu.spec.ts.snap +0 -537
  191. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/AmeliproDropdownMenuBtn/tests/AmeliproDropdownMenuBtn.spec.ts +0 -16
  192. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/AmeliproDropdownMenuBtn/tests/__snapshots__/AmeliproDropdownMenuBtn.spec.ts.snap +0 -56
  193. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/tests/AmeliproDropdownMenu.spec.ts +0 -28
  194. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproDropdownMenu/tests/__snapshots__/AmeliproDropdownMenu.spec.ts.snap +0 -300
  195. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproMessagingMenuBtn/tests/AmeliproMessagingMenuBtn.spec.ts +0 -16
  196. package/src/components/Amelipro/AmeliproMessagingLayout/AmeliproMessagingMenuBtn/tests/__snapshots__/AmeliproMessagingMenuBtn.spec.ts.snap +0 -89
  197. package/src/components/BackBtn/tests/__snapshots__/BackBtn.spec.ts.snap +0 -45
  198. package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +0 -1270
  199. package/src/stories/Demarrer/CreerUneIssue.mdx +0 -67
  200. package/src/stories/Demarrer/components.stories.ts +0 -25
@@ -0,0 +1,219 @@
1
+ <script setup lang="ts">
2
+ import { onMounted, ref, watch } from 'vue'
3
+ import {
4
+ createCaptchaAudio,
5
+ createCaptchaImage,
6
+ getCaptchaAudioUrl,
7
+ getCaptchaImageUrl,
8
+ } from './captchaApi'
9
+ import type { CaptchaType, StateType } from './types'
10
+ import type { locales as defaultLocales } from './locales'
11
+
12
+ const props = defineProps<{
13
+ modelValue: CaptchaType
14
+ urlCreate: string
15
+ urlGetImage: string
16
+ urlGetAudio: string
17
+ locales: typeof defaultLocales
18
+ }>()
19
+
20
+ const emit = defineEmits<{
21
+ (e: 'update:modelValue', modelValue: CaptchaType): void
22
+ (e: 'create-captcha:init'): void
23
+ (e: 'create-captcha:error', error: Error): void
24
+ (e: 'create-captcha:success', id: string | null): void
25
+ }>()
26
+
27
+ const type = ref<CaptchaType>(props.modelValue)
28
+ const id = ref<string | null>(null)
29
+ const url = ref<string | null>(null)
30
+ const audioElement = ref<HTMLAudioElement | null>(null)
31
+ const isPlaying = ref(false)
32
+ const isError = ref(false)
33
+ const errorMessage = ref<string | null>(null)
34
+ const state = ref<StateType>('idle')
35
+
36
+ onMounted(async () => {
37
+ await chooseType(props.modelValue)
38
+ })
39
+
40
+ watch(() => props.modelValue, async (newType) => {
41
+ if (type.value !== newType) {
42
+ type.value = newType
43
+ await chooseType(newType)
44
+ }
45
+ })
46
+
47
+ async function chooseType(selectedType: CaptchaType) {
48
+ updateType(selectedType)
49
+ resetError()
50
+
51
+ switch (selectedType) {
52
+ case 'image':
53
+ createImage()
54
+ break
55
+ case 'audio':
56
+ createAudio()
57
+ break
58
+ default:
59
+ break
60
+ }
61
+ }
62
+
63
+ function chooseImage() {
64
+ chooseType('image')
65
+ }
66
+
67
+ function chooseAudio() {
68
+ chooseType('audio')
69
+ }
70
+
71
+ function createImage() {
72
+ emitCreateInitEvent()
73
+ resetValues()
74
+
75
+ createCaptchaImage(
76
+ props.urlCreate,
77
+ (captchaId: string) => {
78
+ id.value = captchaId
79
+ url.value = getCaptchaImageUrl(props.urlGetImage, captchaId)
80
+ emitCreateSuccessEvent()
81
+ state.value = 'resolved'
82
+ },
83
+ onCreateCaptchaError,
84
+ )
85
+ }
86
+
87
+ function createAudio() {
88
+ emitCreateInitEvent()
89
+ resetValues()
90
+
91
+ createCaptchaAudio(
92
+ props.urlCreate,
93
+ (captchaId: string) => {
94
+ id.value = captchaId
95
+ url.value = getCaptchaAudioUrl(props.urlGetAudio, captchaId)
96
+
97
+ audioElement.value = new Audio(url.value)
98
+ audioElement.value.addEventListener('ended', () => {
99
+ isPlaying.value = false
100
+ })
101
+ audioElement.value.addEventListener('error', () => {
102
+ onCreateCaptchaError(new Error('Audio failed to load'))
103
+ })
104
+
105
+ emitCreateSuccessEvent()
106
+ state.value = 'resolved'
107
+ },
108
+ onCreateCaptchaError,
109
+ )
110
+ }
111
+
112
+ function resetValues() {
113
+ // Stop audio and clean up in a safe order
114
+ if (audioElement.value) {
115
+ try {
116
+ audioElement.value.pause()
117
+ }
118
+ catch {
119
+ // Ignore errors if audio element is already disposed
120
+ }
121
+ audioElement.value = null
122
+ }
123
+
124
+ url.value = null
125
+ id.value = null
126
+ state.value = 'pending'
127
+ }
128
+
129
+ function resetError() {
130
+ isError.value = false
131
+ errorMessage.value = null
132
+ }
133
+
134
+ function toggleAudio() {
135
+ if (!audioElement.value) return
136
+
137
+ if (isPlaying.value) {
138
+ audioElement.value.pause()
139
+ isPlaying.value = false
140
+ }
141
+ else {
142
+ audioElement.value.play()
143
+ isPlaying.value = true
144
+ }
145
+ }
146
+
147
+ function onCreateCaptchaError(error: Error) {
148
+ isError.value = true
149
+
150
+ try {
151
+ errorMessage.value = JSON.parse(error.message)
152
+ }
153
+ catch {
154
+ errorMessage.value = props.locales.defaultErrorMessage
155
+ }
156
+
157
+ emitCreateErrorEvent(error)
158
+ state.value = 'rejected'
159
+ }
160
+
161
+ function updateType(selectedType: CaptchaType) {
162
+ type.value = selectedType
163
+ emitTypeChangeEvent(selectedType)
164
+ }
165
+
166
+ function emitTypeChangeEvent(newType: CaptchaType) {
167
+ emit('update:modelValue', newType)
168
+ }
169
+
170
+ function emitCreateInitEvent() {
171
+ emit('create-captcha:init')
172
+ }
173
+
174
+ function emitCreateErrorEvent(error: Error) {
175
+ emit('create-captcha:error', error)
176
+ }
177
+
178
+ function emitCreateSuccessEvent() {
179
+ emit('create-captcha:success', id.value)
180
+ }
181
+ </script>
182
+
183
+ <template>
184
+ <div class="captcha">
185
+ <slot
186
+ v-if="type === 'image'"
187
+ name="image"
188
+ :choose-image="chooseImage"
189
+ :choose-audio="chooseAudio"
190
+ :url="url"
191
+ :is-error="isError"
192
+ :error-message="errorMessage"
193
+ :state="state"
194
+ />
195
+
196
+ <slot
197
+ v-else-if="type === 'audio'"
198
+ name="audio"
199
+ :choose-image="chooseImage"
200
+ :choose-audio="chooseAudio"
201
+ :toggle-audio="toggleAudio"
202
+ :url="url"
203
+ :is-error="isError"
204
+ :error-message="errorMessage"
205
+ :is-playing="isPlaying"
206
+ :state="state"
207
+ />
208
+
209
+ <slot
210
+ v-else
211
+ name="default"
212
+ :choose-image="chooseImage"
213
+ :choose-audio="chooseAudio"
214
+ :is-error="isError"
215
+ :error-message="errorMessage"
216
+ :state="state"
217
+ />
218
+ </div>
219
+ </template>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import SyIcon from '../Customs/SyIcon/SyIcon.vue'
3
+
4
+ defineProps<{
5
+ prependIcon?: string
6
+ }>()
7
+
8
+ </script>
9
+
10
+ <template>
11
+ <button
12
+ class="captcha-btn text-primary"
13
+ type="button"
14
+ >
15
+ <SyIcon
16
+ v-if="prependIcon"
17
+ size="x-small"
18
+ :icon="prependIcon"
19
+ decorative
20
+ />
21
+ <slot />
22
+ </button>
23
+ </template>
24
+
25
+ <style scoped lang="scss">
26
+ .captcha-btn {
27
+ cursor: pointer;
28
+ display: flex;
29
+ align-items: center;
30
+ gap: 4px;
31
+ padding: 4px 8px;
32
+ font-weight: 700;
33
+ font-size: 0.875rem;
34
+ }
35
+ </style>
@@ -0,0 +1,58 @@
1
+ <script setup lang="ts">
2
+ import { ref, watch } from 'vue'
3
+ import SyTextField from '../Customs/SyTextField/SyTextField.vue'
4
+ import type { locales as defaultLocales } from './locales'
5
+
6
+ interface Props {
7
+ label: string
8
+ modelValue?: string | null
9
+ state?: string | null
10
+ loading?: boolean
11
+ errors: string[] | undefined
12
+ success: boolean
13
+ locales: typeof defaultLocales
14
+ }
15
+
16
+ const props = defineProps<Props>()
17
+ const emit = defineEmits(['update:modelValue'])
18
+
19
+ const text = ref<string | null>(props.modelValue ?? null)
20
+
21
+ watch(() => props.modelValue, (newVal) => {
22
+ text.value = newVal ?? null
23
+ }, { immediate: true })
24
+
25
+ function emitChangeEvent() {
26
+ emit('update:modelValue', text.value)
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <VSheet>
32
+ <SyTextField
33
+ v-model="text"
34
+ class="mt-4"
35
+ variant="outlined"
36
+ :error-messages="props.errors"
37
+ :custom-rules="[
38
+ {
39
+ type: 'required',
40
+ options: { message: locales.required },
41
+ }
42
+ ]"
43
+ :show-success-messages="false"
44
+ :has-success="success"
45
+ :disabled="state === 'rejected'"
46
+ :label="label"
47
+ hide-details="auto"
48
+ :readonly="success"
49
+ :is-clearable="!success"
50
+ @update:model-value="emitChangeEvent"
51
+ />
52
+ </VSheet>
53
+ </template>
54
+ <style lang="scss" scoped>
55
+ :deep(.v-input__control:not(:has(.v-field--error))+.v-input__details) {
56
+ display: none;
57
+ }
58
+ </style>
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ import type { locales as defaultLocales } from './locales'
3
+
4
+ defineProps<{
5
+ state: string
6
+ src?: string | null
7
+ locales: typeof defaultLocales
8
+ }>()
9
+
10
+ defineEmits<{
11
+ (e: 'imageError'): void
12
+ }>()
13
+ </script>
14
+
15
+ <template>
16
+ <div>
17
+ <VSkeletonLoader
18
+ v-if="state === 'pending'"
19
+ :aria-label="locales.captchaImgLoading"
20
+ type="image"
21
+ height="64"
22
+ width="311"
23
+ tile
24
+ />
25
+
26
+ <img
27
+ v-else
28
+ height="64"
29
+ width="311"
30
+ :alt="locales.captchaImgAlt"
31
+ :src="src as string"
32
+ @error="$emit('imageError')"
33
+ >
34
+ </div>
35
+ </template>
36
+
37
+ <style lang="scss" scoped>
38
+ :deep(.v-skeleton-loader__image) {
39
+ height: 100%;
40
+ }
41
+ </style>
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ import type { CaptchaType } from './types'
3
+ import type { locales as defaultLocales } from './locales'
4
+
5
+ interface Props {
6
+ type?: CaptchaType | string
7
+ tagTitle?: string
8
+ locales: typeof defaultLocales
9
+ }
10
+
11
+ withDefaults(defineProps<Props>(), {
12
+ type: undefined,
13
+ tagTitle: 'h3',
14
+ })
15
+ </script>
16
+
17
+ <template>
18
+ <div>
19
+ <div class="d-flex flex-row align-center">
20
+ <component
21
+ :is="tagTitle"
22
+ class="captcha-title text-textBase"
23
+ >
24
+ {{ locales.information.securityCheck }}
25
+ </component>
26
+ </div>
27
+
28
+ <div
29
+ v-if="type"
30
+ >
31
+ <div v-if="type === 'image'">
32
+ <p class="captcha-instructions text-textSubdued">
33
+ {{ locales.information.imageInstruction }}
34
+ </p>
35
+
36
+ <slot name="error" />
37
+ </div>
38
+
39
+ <div v-if="type === 'audio'">
40
+ <p class="captcha-instructions text-textSubdued">
41
+ {{ locales.information.audioInstruction }}
42
+ </p>
43
+
44
+ <slot name="error" />
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </template>
49
+
50
+ <style lang="scss" scoped>
51
+ .captcha-title {
52
+ font-weight: 700;
53
+ font-size: 1.125rem;
54
+ line-height: 150%;
55
+ margin: 0;
56
+ padding: 0;
57
+ }
58
+
59
+ .captcha-instructions {
60
+ font-size: 1rem;
61
+ line-height: 150%;
62
+ font-weight: 400;
63
+ }
64
+ </style>
@@ -0,0 +1,111 @@
1
+ const reGet = /CAPTCHAID/
2
+
3
+ type SuccessCallback = (captchaId: string) => void
4
+ type ErrorCallback = (error: Error) => void
5
+
6
+ /**
7
+ * Création du captcha auprès d'OBS
8
+ * @param urlCreate - URL de création
9
+ * @param body - Corps de la requête (peut être un Document ou un BodyInit)
10
+ * @param cbsuccess - Fonction à appeler en cas de succès
11
+ * @param cberror - Fonction à appeler en cas d'erreur
12
+ */
13
+ export function createCaptcha(
14
+ urlCreate: string,
15
+ body: string | null,
16
+ cbsuccess: SuccessCallback,
17
+ cberror: ErrorCallback,
18
+ ): void {
19
+ fetch(urlCreate, {
20
+ method: 'POST',
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ body: body,
25
+ })
26
+ .then(async (response) => {
27
+ if (response.ok) {
28
+ try {
29
+ const json = await response.json()
30
+ cbsuccess(json.id)
31
+ }
32
+ catch (err) {
33
+ cberror(err as Error)
34
+ }
35
+ }
36
+ else {
37
+ cberror(response.statusText ? new Error(response.statusText) : new Error('Erreur inconnue'))
38
+ }
39
+ })
40
+ .catch((error) => {
41
+ cberror(error)
42
+ })
43
+ }
44
+
45
+ /**
46
+ * Création d'un captcha image auprès d'OBS avec locale par défaut
47
+ * @param urlCreate - URL de création
48
+ * @param cbsuccess - Callback de succès
49
+ * @param cberror - Callback d'erreur
50
+ * @param locale - Locale (langue)
51
+ */
52
+ export function createCaptchaImage(
53
+ urlCreate: string,
54
+ cbsuccess: SuccessCallback,
55
+ cberror: ErrorCallback,
56
+ locale: string = 'default',
57
+ ): void {
58
+ const body = JSON.stringify({
59
+ type: 'IMAGE',
60
+ locale,
61
+ })
62
+
63
+ createCaptcha(urlCreate, body, cbsuccess, cberror)
64
+ }
65
+
66
+ /**
67
+ * Création d'un captcha audio auprès d'OBS
68
+ * @param urlCreate - URL de création
69
+ * @param cbsuccess - Callback de succès
70
+ * @param cberror - Callback d'erreur
71
+ * @param locale - Locale (langue), "default" si non indiqué
72
+ */
73
+ export function createCaptchaAudio(
74
+ urlCreate: string,
75
+ cbsuccess: SuccessCallback,
76
+ cberror: ErrorCallback,
77
+ locale: string = 'default',
78
+ ): void {
79
+ const body = JSON.stringify({
80
+ type: 'AUDIO',
81
+ locale,
82
+ })
83
+
84
+ createCaptcha(urlCreate, body, cbsuccess, cberror)
85
+ }
86
+
87
+ /**
88
+ * Génère l'URL de récupération de l'image du captcha
89
+ * @param urlGetImage - URL avec le placeholder CAPTCHAID
90
+ * @param captchaId - Identifiant du captcha
91
+ * @returns L'URL avec l'identifiant inséré
92
+ */
93
+ export function getCaptchaImageUrl(
94
+ urlGetImage: string,
95
+ captchaId: string,
96
+ ): string {
97
+ return urlGetImage.replace(reGet, captchaId)
98
+ }
99
+
100
+ /**
101
+ * Génère l'URL de récupération de l'audio du captcha
102
+ * @param urlGetAudio - URL avec le placeholder CAPTCHAID
103
+ * @param captchaId - Identifiant du captcha
104
+ * @returns L'URL avec l'identifiant inséré
105
+ */
106
+ export function getCaptchaAudioUrl(
107
+ urlGetAudio: string,
108
+ captchaId: string,
109
+ ): string {
110
+ return urlGetAudio.replace(reGet, captchaId)
111
+ }
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ height="24px"
5
+ viewBox="0 -960 960 960"
6
+ width="24px"
7
+ fill="#1f1f1f"
8
+ >
9
+ <path d="M560-131v-82q90-26 145-100t55-168q0-94-55-168T560-749v-82q124 28 202 125.5T840-481q0 127-78 224.5T560-131ZM120-360v-240h160l200-200v640L280-360H120Zm440 40v-322q47 22 73.5 66t26.5 96q0 51-26.5 94.5T560-320ZM400-606l-86 86H200v80h114l86 86v-252ZM300-480Z" />
10
+ </svg>
11
+ </template>
@@ -0,0 +1,35 @@
1
+ export const locales = {
2
+ hardToRead: 'Vous n\'arrivez pas à lire ?',
3
+ image: {
4
+ new: 'Changer d’image',
5
+ change: 'Utiliser un captcha audio',
6
+ textfieldLabel: 'Caractères de l’image',
7
+ },
8
+ audio: {
9
+ new: 'Changer d’audio',
10
+ change: 'Utiliser un captcha image',
11
+ textfieldLabel: 'Caractères de l’audio',
12
+ loading: 'Chargement de l\'audio du captcha',
13
+ },
14
+ choiceCaptcha: {
15
+ image: 'captcha image',
16
+ audio: 'captcha audio',
17
+ },
18
+ helpDesk: (phoneNumber: string) => `Si vous êtes en incapacité de résoudre le captcha, contactez le support au ${phoneNumber}.`,
19
+ pause: 'Pause',
20
+ play: 'Lire l\'audio',
21
+ renew: 'Renouveler le captcha',
22
+ validate: 'Vérifier',
23
+ captchaImgLoading: 'Chargement de l\'image du captcha',
24
+ captchaImgAlt: 'Le captcha à saisir',
25
+ information: {
26
+ securityCheck: 'Vérification de sécurité',
27
+ btnAriaLabel: 'Ouvrir la bulle d’information',
28
+ tooltip: 'Nous nous assurons ainsi que vous êtes un être humain, et non un robot.',
29
+ imageInstruction: 'Saisissez les caractères affichés ci-dessous.',
30
+ audioInstruction: 'Saisissez le texte que vous entendez.',
31
+ },
32
+ defaultErrorMessage: 'Une erreur inconnue est survenue',
33
+ required: 'Le captcha est requis',
34
+ choiceCaptchaTitle: 'Choisissez le type de captcha de votre choix.',
35
+ }
@@ -0,0 +1,5 @@
1
+ https://gitlab.cnqd.cnamts.fr/captcha/capt_x
2
+ http://pad-st.cnamts.fr/pad-ddst/fabricant/dait/captcha/fiche-resume.html
3
+ http://pad-st.cnamts.fr/pad-ddst/fabricant/dait/captcha/demo/captcha.html
4
+ https://gitlab.cnqd.cnamts.fr/captcha/captcha-vue-design-system
5
+ https://gitlab.cnqd.cnamts.fr/captcha/captchavue