@cnamts/synapse 1.0.6 → 1.0.8

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 (235) hide show
  1. package/dist/{DateFilter-BlOpwEVq.js → DateFilter-DkqG0pmr.js} +1 -1
  2. package/dist/{NumberFilter-BPUXE4wY.js → NumberFilter-Ck7AwD39.js} +1 -1
  3. package/dist/{PeriodFilter-B2yx329_.js → PeriodFilter-LRI6YpgU.js} +1 -1
  4. package/dist/{SelectFilter-CedKn1oV.js → SelectFilter-DPc70Jk7.js} +1 -1
  5. package/dist/{TextFilter-DkhJjRtR.js → TextFilter-DRQL7uD8.js} +1 -1
  6. package/dist/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.d.ts +116 -0
  7. package/dist/components/Amelipro/AmeliproAccordionGroup/types.d.ts +4 -0
  8. package/dist/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.d.ts +220 -0
  9. package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.d.ts +68 -0
  10. package/dist/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.d.ts +70 -0
  11. package/dist/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.d.ts +204 -0
  12. package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +26 -26
  13. package/dist/components/Amelipro/AmeliproBadge/AmeliproBadge.d.ts +59 -0
  14. package/dist/components/Amelipro/AmeliproBtn/AmeliproBtn.d.ts +3 -3
  15. package/dist/components/Amelipro/AmeliproCaptcha/AmeliproCaptcha.d.ts +1 -1
  16. package/dist/components/Amelipro/AmeliproCarousel/AmeliproCarousel.d.ts +214 -0
  17. package/dist/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/AmeliproCarouselItem.d.ts +70 -0
  18. package/dist/components/Amelipro/AmeliproCarousel/types.d.ts +7 -0
  19. package/dist/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.d.ts +125 -0
  20. package/dist/components/Amelipro/AmeliproIconBtn/AmeliproIconBtn.d.ts +1 -1
  21. package/dist/components/Amelipro/AmeliproIllustratedDataTile/AmeliproIllustratedDataTile.d.ts +2 -2
  22. package/dist/components/Amelipro/AmeliproResultList/AmeliproResultList.d.ts +164 -0
  23. package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +27 -27
  24. package/dist/components/Amelipro/AmeliproStateTile/AmeliproStateTile.d.ts +1 -1
  25. package/dist/components/Amelipro/AmeliproTable/AmeliproTable.d.ts +1 -1
  26. package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +32 -32
  27. package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +6 -6
  28. package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +7 -7
  29. package/dist/components/Amelipro/AmeliproTileBtn/AmeliproTileBtn.d.ts +1 -1
  30. package/dist/components/Amelipro/AmeliproTooltips/AmeliproTooltips.d.ts +2 -2
  31. package/dist/components/ChipList/ChipList.d.ts +4 -0
  32. package/dist/components/ChipList/locales.d.ts +4 -2
  33. package/dist/components/CookiesSelection/CookiesInformation/CookiesInformation.d.ts +8 -8
  34. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +329 -1296
  35. package/dist/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.d.ts +0 -1
  36. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +2 -0
  37. package/dist/components/Customs/SyTabs/SyTabs.d.ts +71 -0
  38. package/dist/components/Customs/SyTabs/config.d.ts +17 -0
  39. package/dist/components/Customs/SyTabs/types.d.ts +11 -0
  40. package/dist/components/Customs/SyTextField/SyTextField.d.ts +9 -9
  41. package/dist/components/DataList/DataList.d.ts +1 -1
  42. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +4811 -240
  43. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +52 -33
  44. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +23 -10
  45. package/dist/components/DatePicker/composables/useDateInputEditing.d.ts +1 -0
  46. package/dist/components/DatePicker/composables/useTodayButton.d.ts +1 -0
  47. package/dist/components/DialogBox/DialogBox.d.ts +219 -0
  48. package/dist/components/HeaderLoading/HeaderLoading.d.ts +27 -0
  49. package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +110 -3
  50. package/dist/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.d.ts +19 -1
  51. package/dist/components/LangBtn/LangBtn.d.ts +2 -2
  52. package/dist/components/NirField/NirField.d.ts +18 -18
  53. package/dist/components/PeriodField/PeriodField.d.ts +10766 -1620
  54. package/dist/components/PhoneField/PhoneField.d.ts +1866 -2
  55. package/dist/components/PhoneField/indicatifs.d.ts +1 -0
  56. package/dist/components/PhoneField/locales.d.ts +1 -0
  57. package/dist/components/RangeField/RangeField.d.ts +1 -1
  58. package/dist/components/RangeField/RangeSlider/RangeSlider.d.ts +1 -1
  59. package/dist/components/SubHeader/SubHeader.d.ts +8 -0
  60. package/dist/components/SubHeader/locales.d.ts +1 -0
  61. package/dist/components/SyTextArea/SyTextArea.d.ts +6 -6
  62. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +5 -4
  63. package/dist/components/Tables/SyTable/SyTable.d.ts +5 -4
  64. package/dist/components/Tables/common/SyTablePagination.d.ts +333 -1296
  65. package/dist/components/Tables/common/organizeColumns/OrganizeColumns.d.ts +2 -2
  66. package/dist/components/Tables/common/types.d.ts +2 -0
  67. package/dist/components/index.d.ts +9 -0
  68. package/dist/design-system-v3.js +173 -164
  69. package/dist/design-system-v3.umd.cjs +286 -263
  70. package/dist/{main-BXPFSAB4.js → main-DXMoMtj5.js} +13176 -11457
  71. package/dist/services/NotificationService.d.ts +1 -0
  72. package/dist/style.css +1 -1
  73. package/package.json +1 -1
  74. package/src/assets/amelipro/icons.ts +38 -11
  75. package/src/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.mdx +20 -0
  76. package/src/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.stories.ts +135 -0
  77. package/src/components/Amelipro/AmeliproAccordionGroup/AmeliproAccordionGroup.vue +107 -0
  78. package/src/components/Amelipro/AmeliproAccordionGroup/__tests__/AmeliproAccordionGroup.spec.ts +37 -0
  79. package/src/components/Amelipro/AmeliproAccordionGroup/__tests__/__snapshots__/AmeliproAccordionGroup.spec.ts.snap +513 -0
  80. package/src/components/Amelipro/AmeliproAccordionGroup/types.d.ts +4 -0
  81. package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.mdx +16 -0
  82. package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.stories.ts +300 -0
  83. package/src/components/Amelipro/AmeliproAccordionList/AmeliproAccordionList.vue +288 -0
  84. package/src/components/Amelipro/AmeliproAccordionList/__tests__/AmeliproAccordionList.spec.ts +38 -0
  85. package/src/components/Amelipro/AmeliproAccordionList/__tests__/__snapshots__/AmeliproAccordionList.spec.ts.snap +1712 -0
  86. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.mdx +19 -0
  87. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.stories.ts +68 -0
  88. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResult.vue +66 -0
  89. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/AmeliproAccordionResultTemplate.vue +145 -0
  90. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/__tests__/AmeliproAccordionResultTemplate.spec.ts +24 -0
  91. package/src/components/Amelipro/AmeliproAccordionResult/AmeliproAccordionResultTemplate/__tests__/__snapshots__/AmeliproAccordionResultTemplate.spec.ts.snap +127 -0
  92. package/src/components/Amelipro/AmeliproAccordionResult/__tests__/AmeliproAccordionResult.spec.ts +24 -0
  93. package/src/components/Amelipro/AmeliproAccordionResult/__tests__/__snapshots__/AmeliproAccordionResult.spec.ts.snap +123 -0
  94. package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.mdx +20 -0
  95. package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.stories.ts +273 -0
  96. package/src/components/Amelipro/AmeliproAccordionResultList/AmeliproAccordionResultList.vue +275 -0
  97. package/src/components/Amelipro/AmeliproAccordionResultList/__tests__/AmeliproAccordionResultList.spec.ts +38 -0
  98. package/src/components/Amelipro/AmeliproAccordionResultList/__tests__/__snapshots__/AmeliproAccordionResultList.spec.ts.snap +1593 -0
  99. package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.mdx +15 -0
  100. package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.stories.ts +54 -0
  101. package/src/components/Amelipro/AmeliproBadge/AmeliproBadge.vue +76 -0
  102. package/src/components/Amelipro/AmeliproBadge/__tests__/AmeliproBadge.spec.ts +20 -0
  103. package/src/components/Amelipro/AmeliproBadge/__tests__/__snapshots__/AmeliproBadge.spec.ts.snap +19 -0
  104. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.mdx +15 -0
  105. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.stories.ts +191 -0
  106. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarousel.vue +263 -0
  107. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/AmeliproCarouselItem.vue +93 -0
  108. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/__tests__/AmeliproCarouselItem.spec.ts +24 -0
  109. package/src/components/Amelipro/AmeliproCarousel/AmeliproCarouselItem/__tests__/__snapshots__/AmeliproCarouselItem.spec.ts.snap +43 -0
  110. package/src/components/Amelipro/AmeliproCarousel/__tests__/AmeliproCarousel.spec.ts +40 -0
  111. package/src/components/Amelipro/AmeliproCarousel/__tests__/__snapshots__/AmeliproCarousel.spec.ts.snap +342 -0
  112. package/src/components/Amelipro/AmeliproCarousel/types.d.ts +8 -0
  113. package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.mdx +18 -0
  114. package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.stories.ts +67 -0
  115. package/src/components/Amelipro/AmeliproClickableTile/AmeliproClickableTile.vue +233 -0
  116. package/src/components/Amelipro/AmeliproClickableTile/tests/AmeliproClickableTile.spec.ts +21 -0
  117. package/src/components/Amelipro/AmeliproClickableTile/tests/__snapshots__/AmeliproClickableTile.spec.ts.snap +140 -0
  118. package/src/components/Amelipro/AmeliproHeader/AmeliproHeader.vue +7 -1
  119. package/src/components/Amelipro/AmeliproHeader/tests/__snapshots__/AmeliproHeader.spec.ts.snap +5 -4
  120. package/src/components/Amelipro/AmeliproIcon/iconList.ts +6 -0
  121. package/src/components/Amelipro/AmeliproPageLayout/tests/__snapshots__/AmeliproPageLayout.spec.ts.snap +5 -4
  122. package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.mdx +15 -0
  123. package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.stories.ts +264 -0
  124. package/src/components/Amelipro/AmeliproResultList/AmeliproResultList.vue +231 -0
  125. package/src/components/Amelipro/AmeliproResultList/__tests__/AmeliproResultList.spec.ts +37 -0
  126. package/src/components/Amelipro/AmeliproResultList/__tests__/__snapshots__/AmeliproResultList.spec.ts.snap +434 -0
  127. package/src/components/Amelipro/AmeliproTable/AmeliproTable.vue +6 -5
  128. package/src/components/Amelipro/AmeliproTable/__tests__/__snapshots__/AmeliproTable.spec.ts.snap +23 -26
  129. package/src/components/Amelipro/AmeliproTileBtn/AmeliproTileBtn.stories.ts +2 -2
  130. package/src/components/ChipList/Accessibilite.stories.ts +4 -0
  131. package/src/components/ChipList/ChipList.vue +185 -42
  132. package/src/components/ChipList/locales.ts +4 -2
  133. package/src/components/ChipList/tests/chipList.spec.ts +7 -4
  134. package/src/components/Customs/Selects/SelectOverview.mdx +34 -66
  135. package/src/components/Customs/Selects/SyBtnSelect/SyBtnSelect.stories.ts +10 -10
  136. package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.mdx +3 -0
  137. package/src/components/Customs/Selects/SyInputSelect/SyInputSelect.stories.ts +14 -0
  138. package/src/components/Customs/Selects/SySelect/SySelect.stories.ts +14 -6
  139. package/src/components/Customs/Selects/SySelect/SySelect.vue +268 -205
  140. package/src/components/Customs/Selects/SySelect/composables/tests/useSySelectKeyboard.spec.ts +0 -10
  141. package/src/components/Customs/Selects/SySelect/composables/useSySelectKeyboard.ts +0 -5
  142. package/src/components/Customs/Selects/SySelect/tests/SySelect.spec.ts +184 -25
  143. package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +3 -1
  144. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +165 -0
  145. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +28 -9
  146. package/src/components/Customs/SyTabs/Accessibilite.mdx +309 -0
  147. package/src/components/Customs/SyTabs/SyTabs.mdx +117 -0
  148. package/src/components/Customs/SyTabs/SyTabs.stories.ts +354 -0
  149. package/src/components/Customs/SyTabs/SyTabs.vue +413 -0
  150. package/src/components/Customs/SyTabs/config.ts +17 -0
  151. package/src/components/Customs/SyTabs/tests/SyTabs.spec.ts +425 -0
  152. package/src/components/Customs/SyTabs/types.ts +12 -0
  153. package/src/components/Customs/SyTextField/SyTextField.mdx +3 -0
  154. package/src/components/Customs/SyTextField/SyTextField.stories.ts +142 -1
  155. package/src/components/Customs/SyTextField/SyTextField.vue +19 -16
  156. package/src/components/DataList/DataList.vue +47 -49
  157. package/src/components/DataListGroup/DataListGroup.vue +1 -1
  158. package/src/components/DataListItem/DataListItem.vue +67 -63
  159. package/src/components/DataListItem/tests/DataListItem.spec.ts +2 -2
  160. package/src/components/DatePicker/CalendarMode/DatePicker.stories.ts +3 -3
  161. package/src/components/DatePicker/CalendarMode/DatePicker.vue +49 -13
  162. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +412 -649
  163. package/src/components/DatePicker/DatePickerValidationExample/CalendarMode.stories.ts +215 -0
  164. package/src/components/DatePicker/DatePickerValidationExample/ComplexDatePicker.stories.ts +218 -0
  165. package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.mdx +2 -0
  166. package/src/components/DatePicker/DatePickerValidationExample/DatePickerValidation.stories.ts +1 -1
  167. package/src/components/DatePicker/DatePickerValidationExample/DateTextInput.stories.ts +218 -0
  168. package/src/components/DatePicker/DatePickerValidationExample/MultiMode.stories.ts +281 -0
  169. package/src/components/DatePicker/DateTextInput/DateTextInput.events.spec.ts +17 -4
  170. package/src/components/DatePicker/DateTextInput/DateTextInput.range.spec.ts +111 -18
  171. package/src/components/DatePicker/DateTextInput/DateTextInput.spec.ts +238 -6
  172. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +716 -757
  173. package/src/components/DatePicker/composables/tests/useDateInputEditing.spec.ts +4 -4
  174. package/src/components/DatePicker/composables/tests/useDisplayedDateString.spec.ts +17 -10
  175. package/src/components/DatePicker/composables/useDateInputEditing.ts +52 -22
  176. package/src/components/DatePicker/composables/useDisplayedDateString.ts +18 -4
  177. package/src/components/DatePicker/composables/useTodayButton.ts +13 -1
  178. package/src/components/DatePicker/utils/dateFormattingUtils.ts +79 -14
  179. package/src/components/DialogBox/DialogBox.stories.ts +12 -0
  180. package/src/components/DialogBox/DialogBox.vue +16 -11
  181. package/src/components/DialogBox/tests/DialogBox.spec.ts +22 -0
  182. package/src/components/HeaderLoading/Accessibilite.mdx +429 -8
  183. package/src/components/HeaderLoading/Accessibilite.stories.ts +4 -0
  184. package/src/components/HeaderLoading/HeaderLoading.vue +59 -0
  185. package/src/components/HeaderNavigationBar/HeaderNavigationBar.mdx +17 -2
  186. package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +91 -2
  187. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +37 -1
  188. package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +284 -21
  189. package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.spec.ts +2 -2
  190. package/src/components/NirField/NirField.mdx +3 -0
  191. package/src/components/NirField/NirField.vue +10 -1
  192. package/src/components/NirField/tests/NirField.spec.ts +81 -0
  193. package/src/components/NotificationBar/NotificationBar.stories.ts +128 -2
  194. package/src/components/NotificationBar/NotificationBar.vue +16 -1
  195. package/src/components/NotificationBar/tests/NotificationBar.spec.ts +65 -0
  196. package/src/components/PasswordField/PasswordField.mdx +3 -0
  197. package/src/components/PeriodField/PeriodField.mdx +2 -0
  198. package/src/components/PeriodField/PeriodField.stories.ts +195 -0
  199. package/src/components/PhoneField/Accessibilite.stories.ts +4 -0
  200. package/src/components/PhoneField/PhoneField.mdx +3 -1
  201. package/src/components/PhoneField/PhoneField.stories.ts +285 -1
  202. package/src/components/PhoneField/PhoneField.vue +228 -95
  203. package/src/components/PhoneField/indicatifs.ts +102 -102
  204. package/src/components/PhoneField/locales.ts +1 -0
  205. package/src/components/PhoneField/tests/PhoneField.spec.ts +419 -2
  206. package/src/components/SkipLink/SkipLink.vue +3 -31
  207. package/src/components/SkipLink/tests/skipLink.spec.ts +0 -21
  208. package/src/components/SubHeader/Accessibilite.stories.ts +8 -0
  209. package/src/components/SubHeader/SubHeader.mdx +1 -0
  210. package/src/components/SubHeader/SubHeader.stories.ts +179 -60
  211. package/src/components/SubHeader/SubHeader.vue +45 -15
  212. package/src/components/SubHeader/locales.ts +1 -0
  213. package/src/components/SyAlert/SyAlert.vue +6 -0
  214. package/src/components/Tables/SyServerTable/SyServerTable.mdx +3 -10
  215. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +242 -0
  216. package/src/components/Tables/SyServerTable/SyServerTable.vue +29 -10
  217. package/src/components/Tables/SyTable/SyTable.mdx +3 -10
  218. package/src/components/Tables/SyTable/SyTable.stories.ts +242 -0
  219. package/src/components/Tables/SyTable/SyTable.vue +2 -0
  220. package/src/components/Tables/common/SyTablePagination.vue +13 -6
  221. package/src/components/Tables/common/filters/tests/SelectFilter.spec.ts +6 -1
  222. package/src/components/Tables/common/tests/SyTablePagination.spec.ts +157 -0
  223. package/src/components/Tables/common/types.ts +2 -0
  224. package/src/components/index.ts +9 -0
  225. package/src/composables/useFilterable/useFilterable.ts +10 -0
  226. package/src/designTokens/tokens/amelipro/apColors.ts +1 -1
  227. package/src/designTokens/tokens/cnam/cnamSemantic.ts +3 -3
  228. package/src/services/NotificationService.ts +9 -0
  229. package/src/stories/Components/Components.stories.ts +1 -1
  230. package/src/stories/GuideDuDev/FormValidationGuide.mdx +342 -0
  231. package/src/stories/Templates/Templates.stories.ts +1 -1
  232. package/src/utils/functions/ameliproColors/ameliproColors.ts +1 -1
  233. package/dist/components/DataList/locales.d.ts +0 -3
  234. package/src/components/DataList/locales.ts +0 -3
  235. package/src/components/PhoneField/tests/PhoneField.additional.spec.ts +0 -266
@@ -0,0 +1,413 @@
1
+ <script setup lang="ts">
2
+ import type { TabItem } from './types'
3
+ import useCustomizableOptions from '@/composables/useCustomizableOptions'
4
+ import { config } from './config'
5
+ import { ref, watch, onMounted, onUnmounted, getCurrentInstance } from 'vue'
6
+ import type { Router } from 'vue-router'
7
+
8
+ const props = withDefaults(defineProps<{
9
+ items: TabItem[]
10
+ modelValue?: number | string
11
+ /** Si activé, une confirmation sera demandée avant de changer d'onglet */
12
+ confirmTabChange?: boolean
13
+ /** Message affiché dans la boîte de dialogue de confirmation */
14
+ confirmationMessage?: boolean
15
+ /** Options personnalisées pour les composants Vuetify */
16
+ vuetifyOptions?: {
17
+ sheet?: {
18
+ theme?: string
19
+ dense?: boolean
20
+ color?: string
21
+ }
22
+ tabs?: {
23
+ height?: string
24
+ showArrows?: boolean
25
+ }
26
+ tab?: {
27
+ 'base-color'?: string
28
+ 'active-color'?: string
29
+ 'slider-color'?: string
30
+ 'ripple'?: boolean
31
+ }
32
+ }
33
+ }>(), {
34
+ modelValue: undefined,
35
+ confirmTabChange: false,
36
+ confirmationMessage: false,
37
+ vuetifyOptions: () => ({}),
38
+ })
39
+
40
+ // Disable automatic attribute inheritance since we handle it manually
41
+ defineOptions({
42
+ inheritAttrs: false,
43
+ })
44
+
45
+ const emit = defineEmits(['update:modelValue', 'cancel-navigation', 'confirm-tab-change'])
46
+
47
+ defineSlots<{
48
+ 'tabs-prepend': () => unknown
49
+ 'tabs-append': () => unknown
50
+ 'default': () => unknown
51
+ }>()
52
+
53
+ const options = useCustomizableOptions(config, { vuetifyOptions: props.vuetifyOptions })
54
+
55
+ // Safely get router through getCurrentInstance - it might not be available in all contexts
56
+ const instance = getCurrentInstance()
57
+ const router = instance?.appContext.config.globalProperties.$router as Router | null || null
58
+
59
+ // État pour suivre l'élément activement sélectionné
60
+ const activeItemIndex = ref<number>(0)
61
+ // Élément actuellement focusé (pour la navigation clavier)
62
+ const focusedItemIndex = ref<number>(-1)
63
+
64
+ // Émet un événement pour gérer la confirmation de changement d'onglet
65
+ async function handleTabChangeConfirmation(message: string): Promise<boolean> {
66
+ // Émettre l'événement avec le message et retourner une promesse
67
+ let resolver: (value: boolean) => void
68
+ const promise = new Promise<boolean>((resolve) => {
69
+ resolver = resolve
70
+ })
71
+
72
+ // Émettre l'événement avec le message et un callback pour résoudre la promesse
73
+ emit('confirm-tab-change', message, (confirmed: boolean) => {
74
+ resolver(confirmed)
75
+ })
76
+
77
+ return promise
78
+ }
79
+
80
+ // Fonction pour activer un élément au clic avec confirmation si nécessaire
81
+ async function setActiveItem(index: number) {
82
+ // Si l'index est déjà actif, ne rien faire
83
+ if (index === activeItemIndex.value) return
84
+
85
+ // Récupérer l'item pour la navigation potentielle
86
+ const item = props.items[index]
87
+ const hasHref = item && (item.href || item.to)
88
+
89
+ // Si la confirmation est activée, demander confirmation
90
+ if (props.confirmTabChange && hasHref) {
91
+ const confirmMessage = props.confirmationMessage
92
+ const confirmed = await handleTabChangeConfirmation(confirmMessage.toString())
93
+
94
+ if (!confirmed) {
95
+ // L'utilisateur a annulé, émettre un événement d'annulation
96
+ emit('cancel-navigation')
97
+ return
98
+ }
99
+ // Si confirmé, laisser la navigation se faire naturellement (RouterLink ou href)
100
+ }
101
+
102
+ // Mettre à jour l'onglet actif
103
+ activeItemIndex.value = index
104
+ emit('update:modelValue', typeof props.modelValue === 'string' ? props.items[index].value : index)
105
+
106
+ // Pour les éléments sans navigation (ni href ni to), on ne fait que mettre à jour l'état
107
+ // La navigation pour RouterLink et href se fait automatiquement via les éléments HTML
108
+ }
109
+
110
+ // Fonction pour gérer les touches Enter et Space
111
+ function handleKeyPress(event: KeyboardEvent, index: number) {
112
+ if (event.key === 'Enter' || event.key === ' ') {
113
+ const item = props.items[index]
114
+ // Don't prevent default for external links - let them navigate naturally
115
+ if (!item.href) {
116
+ event.preventDefault()
117
+ }
118
+ void setActiveItem(index) // void pour ignorer la promesse
119
+ }
120
+ }
121
+
122
+ // Configuration des attributs ARIA et gestion du focus global
123
+ function setupAccessibilityFeatures() {
124
+ // Ajouter un écouteur global pour gérer l'escape key
125
+ const handleEscape = (event: KeyboardEvent) => {
126
+ if (event.key === 'Escape' && focusedItemIndex.value >= 0) {
127
+ // Retirer le focus des éléments du menu
128
+ focusedItemIndex.value = -1
129
+ }
130
+ }
131
+
132
+ window.addEventListener('keydown', handleEscape)
133
+
134
+ // Cleanup
135
+ onUnmounted(() => {
136
+ window.removeEventListener('keydown', handleEscape)
137
+ })
138
+ }
139
+
140
+ // Navigation clavier entre les tabs (touches de direction)
141
+ function handleArrowNavigation(event: KeyboardEvent, currentIndex: number) {
142
+ if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return
143
+ event.preventDefault()
144
+ const itemCount = props.items?.length || 0
145
+ if (itemCount === 0) return
146
+
147
+ let newIndex = currentIndex
148
+ switch (event.key) {
149
+ case 'ArrowLeft':
150
+ newIndex = currentIndex <= 0 ? itemCount - 1 : currentIndex - 1
151
+ break
152
+ case 'ArrowRight':
153
+ newIndex = currentIndex >= itemCount - 1 ? 0 : currentIndex + 1
154
+ break
155
+ case 'Home':
156
+ newIndex = 0
157
+ break
158
+ case 'End':
159
+ newIndex = itemCount - 1
160
+ break
161
+ }
162
+
163
+ // Mettre à jour l'index de l'élément focusé et actif
164
+ focusedItemIndex.value = newIndex
165
+
166
+ // Focus sur le nouvel élément et l'activer
167
+ // Vérifier si l'élément existe et se focaliser sur le bouton
168
+ const tabButton = document.getElementById(`tab-${newIndex}`)
169
+ if (tabButton) {
170
+ tabButton.focus()
171
+ setActiveItem(newIndex)
172
+ }
173
+ }
174
+
175
+ // Initialiser l'élément actif au montage
176
+ onMounted(() => {
177
+ // Configurer l'accessibilité
178
+ setupAccessibilityFeatures()
179
+
180
+ // Si les items ne sont pas un tableau ou vides, ne rien faire
181
+ if (!Array.isArray(props.items) || props.items.length === 0) return
182
+
183
+ // Si modelValue est défini, utiliser cette valeur pour déterminer l'index actif
184
+ if (props.modelValue !== undefined) {
185
+ if (typeof props.modelValue === 'number') {
186
+ try {
187
+ const currentPath = window.location?.pathname
188
+ const index = currentPath ? props.items.findIndex(item => item.to === currentPath) : -1
189
+
190
+ // Si un index valide est trouvé, l'utiliser
191
+ if (index >= 0) {
192
+ activeItemIndex.value = index
193
+ }
194
+ // Sinon utiliser props.modelValue comme index direct si c'est valide
195
+ else if (props.modelValue >= 0 && props.modelValue < props.items.length) {
196
+ activeItemIndex.value = props.modelValue
197
+ }
198
+ }
199
+ catch {
200
+ // Utiliser props.modelValue comme fallback si c'est dans la plage valide
201
+ if (props.modelValue >= 0 && props.modelValue < props.items.length) {
202
+ activeItemIndex.value = props.modelValue
203
+ }
204
+ }
205
+ }
206
+ else {
207
+ // Chercher l'index de l'item avec la valeur correspondante
208
+ const index = props.items.findIndex(item => item.value === props.modelValue)
209
+ if (index !== -1) {
210
+ activeItemIndex.value = index
211
+ }
212
+ }
213
+ }
214
+ else {
215
+ // Par défaut, sélectionner le premier élément
216
+ activeItemIndex.value = 0
217
+ }
218
+ })
219
+
220
+ // Observer les changements du modelValue pour mettre à jour l'élément actif
221
+ watch(() => props.modelValue, (newValue) => {
222
+ if (newValue !== undefined) {
223
+ if (typeof newValue === 'number') {
224
+ activeItemIndex.value = newValue
225
+ }
226
+ else {
227
+ const index = props.items.findIndex(item => item.value === newValue)
228
+ if (index !== -1) {
229
+ activeItemIndex.value = index
230
+ }
231
+ }
232
+ }
233
+ })
234
+ </script>
235
+
236
+ <template>
237
+ <VSheet
238
+ :theme="options.sheet.theme"
239
+ :color="options.sheet.color"
240
+ :class="[{ 'v-sheet--dense': options.sheet.dense }, $attrs.class]"
241
+ v-bind="$attrs"
242
+ >
243
+ <div class="sy-tabs px-xl-0 px-4">
244
+ <slot name="tabs-prepend" />
245
+ <slot>
246
+ <nav
247
+ role="tablist"
248
+ aria-label="Onglets de navigation"
249
+ class="sy-tabs__nav"
250
+ >
251
+ <ul
252
+ class="sy-tabs__list"
253
+ >
254
+ <li
255
+ v-for="(item, index) in Array.isArray(items) ? items : []"
256
+ :key="index"
257
+ class="sy-tabs__item"
258
+ role="presentation"
259
+ >
260
+ <!-- Use RouterLink for internal navigation -->
261
+ <RouterLink
262
+ v-if="item.to && router"
263
+ :id="`tab-${index}`"
264
+ :to="item.to"
265
+ class="sy-tabs__button"
266
+ :class="{ 'sy-tabs__button--active': activeItemIndex === index }"
267
+ role="tab"
268
+ :aria-selected="activeItemIndex === index"
269
+ :aria-controls="`panel-${index}`"
270
+ tabindex="0"
271
+ @click="setActiveItem(index)"
272
+ @keydown="(event) => {
273
+ handleKeyPress(event, index);
274
+ handleArrowNavigation(event, index);
275
+ }"
276
+ >
277
+ {{ item.label.toUpperCase() }}
278
+ </RouterLink>
279
+ <!-- Use regular anchor for external links -->
280
+ <a
281
+ v-else-if="item.href"
282
+ :id="`tab-${index}`"
283
+ :href="item.href"
284
+ class="sy-tabs__button"
285
+ :class="{ 'sy-tabs__button--active': activeItemIndex === index }"
286
+ role="tab"
287
+ :aria-selected="activeItemIndex === index"
288
+ :aria-controls="`panel-${index}`"
289
+ tabindex="0"
290
+ @click="(event) => {
291
+ // Don't prevent default for external links - let them navigate naturally
292
+ setActiveItem(index);
293
+ }"
294
+ @keydown="(event) => {
295
+ handleKeyPress(event, index);
296
+ handleArrowNavigation(event, index);
297
+ }"
298
+ >
299
+ {{ item.label.toUpperCase() }}
300
+ </a>
301
+ <!-- Fallback button for items without navigation -->
302
+ <button
303
+ v-else
304
+ :id="`tab-${index}`"
305
+ class="sy-tabs__button"
306
+ :class="{ 'sy-tabs__button--active': activeItemIndex === index }"
307
+ role="tab"
308
+ :aria-selected="activeItemIndex === index"
309
+ :aria-controls="`panel-${index}`"
310
+ tabindex="0"
311
+ @click="setActiveItem(index)"
312
+ @keydown="(event) => {
313
+ handleKeyPress(event, index);
314
+ handleArrowNavigation(event, index);
315
+ }"
316
+ >
317
+ {{ item.label.toUpperCase() }}
318
+ </button>
319
+ </li>
320
+ </ul>
321
+ </nav>
322
+ </slot>
323
+ <slot name="tabs-append" />
324
+ </div>
325
+ </VSheet>
326
+
327
+ <!-- Panneau de contenu des onglets -->
328
+ <div class="sy-tabs-panels">
329
+ <div
330
+ v-for="(item, index) in Array.isArray(items) ? items : []"
331
+ :id="`panel-${index}`"
332
+ :key="`panel-${index}`"
333
+ class="sy-tabs-panel"
334
+ role="tabpanel"
335
+ :aria-labelledby="`tab-${index}`"
336
+ :hidden="activeItemIndex !== index"
337
+ >
338
+ <slot
339
+ :name="`panel-${index}`"
340
+ :active="activeItemIndex === index"
341
+ >
342
+ {{ item.content || '' }}
343
+ </slot>
344
+ </div>
345
+ </div>
346
+ </template>
347
+
348
+ <style lang="scss" scoped>
349
+ @use '@/assets/tokens.scss' as *;
350
+
351
+ .sy-tabs {
352
+ display: flex;
353
+ align-items: center;
354
+ }
355
+
356
+ .sy-tabs__nav {
357
+ flex: 1 1 0;
358
+ width: 100%;
359
+ }
360
+
361
+ .sy-tabs__list {
362
+ display: flex;
363
+ list-style-type: none;
364
+ padding: 0;
365
+ margin: 0;
366
+ width: 100%;
367
+ }
368
+
369
+ .sy-tabs__item {
370
+ cursor: pointer;
371
+ display: flex;
372
+ align-items: stretch;
373
+ }
374
+
375
+ .sy-tabs__button {
376
+ display: flex;
377
+ align-items: center;
378
+ justify-content: center;
379
+ padding: 0 16px;
380
+ min-height: v-bind("options.tabs.height + 'px'");
381
+ font-size: 0.875rem;
382
+ font-weight: 700;
383
+ background: none;
384
+ border: none;
385
+ color: v-bind("options.tab['base-color']");
386
+ transition: color 0.2s ease;
387
+ text-decoration: none; /* For RouterLink elements */
388
+
389
+ &:hover {
390
+ color: v-bind("options.tab['active-color']");
391
+ }
392
+
393
+ &:focus-visible {
394
+ outline: 3px solid v-bind("options.tab['active-color']");
395
+ outline-offset: -3px;
396
+ }
397
+
398
+ &--active {
399
+ color: v-bind("options.tab['active-color']");
400
+ border-bottom: 3px solid v-bind("options.tab['slider-color']");
401
+ }
402
+ }
403
+
404
+ .sy-tabs-panels {
405
+ padding: 16px;
406
+ }
407
+
408
+ .sy-tabs-panel {
409
+ &[hidden] {
410
+ display: none;
411
+ }
412
+ }
413
+ </style>
@@ -0,0 +1,17 @@
1
+ export const config = {
2
+ sheet: {
3
+ theme: 'default',
4
+ dense: false,
5
+ color: '#fff',
6
+ },
7
+ tabs: {
8
+ 'height': '48',
9
+ 'show-arrows': true,
10
+ },
11
+ tab: {
12
+ 'base-color': '#0C419A',
13
+ 'active-color': '#0C419A',
14
+ 'slider-color': '#0C419A',
15
+ 'ripple': false,
16
+ },
17
+ }