@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
@@ -7,6 +7,8 @@ import type { VDataTable } from 'vuetify/components'
7
7
  import dayjs from 'dayjs'
8
8
  import { fn } from '@storybook/test'
9
9
 
10
+ import { mdiChevronDown, mdiChevronUp } from '@mdi/js'
11
+
10
12
  interface User {
11
13
  [key: string]: string
12
14
  firstname: string
@@ -104,6 +106,13 @@ const meta = {
104
106
  description: 'Texte de la légende du tableau',
105
107
  control: { type: 'text' },
106
108
  },
109
+ showExpand: {
110
+ description: 'Affiche une colonne permettant d\'étendre les lignes pour afficher du contenu supplémentaire',
111
+ control: { type: 'boolean' },
112
+ table: {
113
+ category: 'props',
114
+ },
115
+ },
107
116
  resizableColumns: {
108
117
  description: 'Permet de redimensionner les colonnes du tableau',
109
118
  control: { type: 'boolean' },
@@ -153,6 +162,15 @@ const meta = {
153
162
  type: { summary: 'boolean' },
154
163
  },
155
164
  },
165
+ selectionKey: {
166
+ description: 'Clé utilisée pour identifier chaque ligne lors de la sélection. Par défaut, utilise "id" si présent, sinon l\'objet complet.',
167
+ control: { type: 'text' },
168
+ table: {
169
+ category: 'props',
170
+ type: { summary: 'string' },
171
+ defaultValue: { summary: 'undefined (fallback: id | objet complet)' },
172
+ },
173
+ },
156
174
  },
157
175
  } satisfies Meta<typeof SyServerTable & typeof VDataTable>
158
176
 
@@ -4740,6 +4758,297 @@ export const ColumnControls: StoryObj<typeof SyServerTable> = {
4740
4758
  },
4741
4759
  }
4742
4760
 
4761
+ export const ExpandableRows: Story = {
4762
+ parameters: {
4763
+ sourceCode: [
4764
+ {
4765
+ name: 'Template',
4766
+ code: `
4767
+ <template>
4768
+ <SyServerTable
4769
+ v-model:options="options"
4770
+ :items="users"
4771
+ :headers="headers"
4772
+ :server-items-length="totalUsers"
4773
+ :loading="state === StateEnum.PENDING"
4774
+ show-expand
4775
+ caption="Tableau complexe"
4776
+ suffix="server-expandable"
4777
+ @update:options="fetchData"
4778
+ >
4779
+ <template #item.data-table-expand="{ internalItem, isExpanded, toggleExpand }">
4780
+ <v-btn
4781
+ :append-icon="isExpanded(internalItem) ? mdiChevronUp : mdiChevronDown"
4782
+ :text="isExpanded(internalItem) ? 'Fermer' : \`Plus d'info\`"
4783
+ class="text-none"
4784
+ color="medium-emphasis"
4785
+ size="small"
4786
+ variant="text"
4787
+ width="105"
4788
+ border
4789
+ slim
4790
+ @click="toggleExpand(internalItem)"
4791
+ />
4792
+ </template>
4793
+
4794
+ <template #expanded-row="{ columns, item }">
4795
+ <tr>
4796
+ <td
4797
+ :colspan="columns.length"
4798
+ class="py-2"
4799
+ >
4800
+ <strong>Informations complémentaires :</strong>
4801
+ <p>Plus de détails pour {{ item.firstname }} {{ item.lastname }}.</p>
4802
+ </td>
4803
+ </tr>
4804
+ </template>
4805
+ </SyServerTable>
4806
+ </template>
4807
+ `,
4808
+ },
4809
+ {
4810
+ name: 'Script',
4811
+ code: `
4812
+ <script setup lang="ts">
4813
+ import { ref, watch } from 'vue'
4814
+ import { SyServerTable } from '@cnamts/synapse'
4815
+ import { StateEnum } from '@cnamts/synapse/src/components/Tables/common/constants/StateEnum'
4816
+ import type { DataOptions } from '@cnamts/synapse/src/components/Tables/common/types'
4817
+ import { mdiChevronDown, mdiChevronUp } from '@mdi/js'
4818
+
4819
+ interface User {
4820
+ [key: string]: string
4821
+ firstname: string
4822
+ lastname: string
4823
+ email: string
4824
+ }
4825
+
4826
+ interface DataObj {
4827
+ items: User[]
4828
+ total: number
4829
+ }
4830
+
4831
+ const totalUsers = ref(0)
4832
+ const users = ref<User[]>([])
4833
+ const state = ref(StateEnum.IDLE)
4834
+
4835
+ const options = ref({
4836
+ itemsPerPage: 5,
4837
+ sortBy: [{ key: 'lastname', order: 'asc' }],
4838
+ page: 1,
4839
+ })
4840
+
4841
+ const headers = [
4842
+ { title: 'Nom', key: 'lastname' },
4843
+ { title: 'Prénom', key: 'firstname' },
4844
+ { title: 'Email', key: 'email' },
4845
+ ]
4846
+
4847
+ const fetchData = async (): Promise<void> => {
4848
+ const { items, total } = await getDataFromApi(options.value)
4849
+ users.value = items
4850
+ totalUsers.value = total
4851
+ }
4852
+
4853
+ const wait = async (ms: number) => {
4854
+ return new Promise(resolve => setTimeout(resolve, ms))
4855
+ }
4856
+
4857
+ const getDataFromApi = async ({ sortBy, page, itemsPerPage, filters }: DataOptions): Promise<DataObj> => {
4858
+ state.value = StateEnum.PENDING
4859
+ await wait(1000)
4860
+
4861
+ return new Promise((resolve) => {
4862
+ let items: User[] = getUsers()
4863
+ const total = items.length
4864
+
4865
+ if (sortBy && sortBy.length > 0) {
4866
+ items = items.sort((a, b) => {
4867
+ const key = sortBy[0].key
4868
+ const order = sortBy[0].order === 'asc' ? 1 : -1
4869
+
4870
+ return a[key] > b[key] ? order : -order
4871
+ })
4872
+ }
4873
+
4874
+ if (itemsPerPage > 0) {
4875
+ items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage)
4876
+ }
4877
+
4878
+ resolve({ items, total })
4879
+ state.value = StateEnum.RESOLVED
4880
+ })
4881
+ }
4882
+
4883
+ const getUsers = (): User[] => {
4884
+ return [
4885
+ { firstname: 'Virginie', lastname: 'Beauchesne', email: 'virginie.beauchesne@example.com' },
4886
+ { firstname: 'Simone', lastname: 'Bellefeuille', email: 'simone.bellefeuille@example.com' },
4887
+ { firstname: 'Étienne', lastname: 'Salois', email: 'etienne.salois@example.com' },
4888
+ { firstname: 'Bernadette', lastname: 'Langelier', email: 'bernadette.langelier@example.com' },
4889
+ { firstname: 'Agate', lastname: 'Roy', email: 'agate.roy@example.com' },
4890
+ { firstname: 'Louis', lastname: 'Denis', email: 'louis.denis@example.com' },
4891
+ { firstname: 'Édith', lastname: 'Cartier', email: 'edith.cartier@example.com' },
4892
+ { firstname: 'Alphonse', lastname: 'Bouvier', email: 'alphonse.bouvier@example.com' },
4893
+ { firstname: 'Eustache', lastname: 'Dubois', email: 'eustache.dubois@example.com' },
4894
+ { firstname: 'Rosemarie', lastname: 'Quessy', email: 'rosemarie.quessy@example.com' },
4895
+ { firstname: 'Serge', lastname: 'Rivard', email: 'serge.rivard@example.com' },
4896
+ { firstname: 'Jacques', lastname: 'Demers', email: 'jacques.demers@example.com' },
4897
+ { firstname: 'Aimée', lastname: 'Josseaume', email: 'aimee.josseaume@example.com' },
4898
+ { firstname: 'Delphine', lastname: 'Robillard', email: 'delphine.robillard@example.com' },
4899
+ { firstname: 'Alexandre', lastname: 'Lazure', email: 'alexandre.lazure@example.com' },
4900
+ ]
4901
+ }
4902
+
4903
+ // Initialize data
4904
+ fetchData()
4905
+ </script>
4906
+ `,
4907
+ },
4908
+ ],
4909
+ },
4910
+ args: {
4911
+ 'options': {
4912
+ itemsPerPage: 5,
4913
+ sortBy: [{ key: 'lastname', order: 'asc' }],
4914
+ page: 1,
4915
+ },
4916
+ 'headers': [
4917
+ { title: 'Nom', key: 'lastname' },
4918
+ { title: 'Prénom', key: 'firstname' },
4919
+ { title: 'Email', key: 'email' },
4920
+ ],
4921
+ 'caption': '',
4922
+ 'serverItemsLength': 15,
4923
+ 'showExpand': true,
4924
+ 'suffix': 'server-expandable',
4925
+ 'density': 'default',
4926
+ 'striped': false,
4927
+ 'onUpdate:options': fn(),
4928
+ },
4929
+ render: (args) => {
4930
+ return {
4931
+ components: { SyServerTable },
4932
+ setup() {
4933
+ const totalUsers = ref(0)
4934
+ const users = ref<User[]>([])
4935
+ const state = ref(StateEnum.IDLE)
4936
+
4937
+ const options = ref({ ...args.options })
4938
+
4939
+ watch(options, (newVal) => {
4940
+ if (args.options) {
4941
+ Object.assign(args.options, JSON.parse(JSON.stringify(newVal)))
4942
+ }
4943
+ }, { deep: true })
4944
+
4945
+ const fetchData = async (): Promise<void> => {
4946
+ const { items, total } = await getDataFromApi(options.value as DataOptions)
4947
+ users.value = items
4948
+ totalUsers.value = total
4949
+ }
4950
+
4951
+ const wait = async (ms: number) => {
4952
+ return new Promise(resolve => setTimeout(resolve, ms))
4953
+ }
4954
+
4955
+ const getDataFromApi = async ({ sortBy, page, itemsPerPage }: DataOptions): Promise<DataObj> => {
4956
+ state.value = StateEnum.PENDING
4957
+ await wait(1000)
4958
+
4959
+ return new Promise((resolve) => {
4960
+ let items: User[] = getUsers()
4961
+ const total = items.length
4962
+
4963
+ if (sortBy && sortBy.length > 0) {
4964
+ items = items.sort((a, b) => {
4965
+ const key = sortBy[0].key
4966
+ const order = sortBy[0].order === 'asc' ? 1 : -1
4967
+
4968
+ return a[key] > b[key] ? order : -order
4969
+ })
4970
+ }
4971
+
4972
+ if (itemsPerPage > 0) {
4973
+ items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage)
4974
+ }
4975
+
4976
+ resolve({ items, total })
4977
+ state.value = StateEnum.RESOLVED
4978
+ })
4979
+ }
4980
+
4981
+ const getUsers = (): User[] => {
4982
+ return [
4983
+ { firstname: 'Virginie', lastname: 'Beauchesne', email: 'virginie.beauchesne@example.com' },
4984
+ { firstname: 'Simone', lastname: 'Bellefeuille', email: 'simone.bellefeuille@example.com' },
4985
+ { firstname: 'Étienne', lastname: 'Salois', email: 'etienne.salois@example.com' },
4986
+ { firstname: 'Bernadette', lastname: 'Langelier', email: 'bernadette.langelier@example.com' },
4987
+ { firstname: 'Agate', lastname: 'Roy', email: 'agate.roy@example.com' },
4988
+ { firstname: 'Louis', lastname: 'Denis', email: 'louis.denis@example.com' },
4989
+ { firstname: 'Édith', lastname: 'Cartier', email: 'edith.cartier@example.com' },
4990
+ { firstname: 'Alphonse', lastname: 'Bouvier', email: 'alphonse.bouvier@example.com' },
4991
+ { firstname: 'Eustache', lastname: 'Dubois', email: 'eustache.dubois@example.com' },
4992
+ { firstname: 'Rosemarie', lastname: 'Quessy', email: 'rosemarie.quessy@example.com' },
4993
+ { firstname: 'Serge', lastname: 'Rivard', email: 'serge.rivard@example.com' },
4994
+ { firstname: 'Jacques', lastname: 'Demers', email: 'jacques.demers@example.com' },
4995
+ { firstname: 'Aimée', lastname: 'Josseaume', email: 'aimee.josseaume@example.com' },
4996
+ { firstname: 'Delphine', lastname: 'Robillard', email: 'delphine.robillard@example.com' },
4997
+ { firstname: 'Alexandre', lastname: 'Lazure', email: 'alexandre.lazure@example.com' },
4998
+ ]
4999
+ }
5000
+
5001
+ // Initialize data
5002
+ fetchData()
5003
+
5004
+ return { args, users, state, fetchData, options, totalUsers, StateEnum, mdiChevronDown, mdiChevronUp }
5005
+ },
5006
+ template: `
5007
+ <div>
5008
+ <SyServerTable
5009
+ v-model:options="options"
5010
+ :items="users"
5011
+ :server-items-length="totalUsers"
5012
+ :loading="state === StateEnum.PENDING"
5013
+ v-bind="args"
5014
+ show-expand
5015
+ caption="Tableau complexe"
5016
+ suffix="server-expandable"
5017
+ @update:options="fetchData"
5018
+ >
5019
+ <template #item.data-table-expand="{ internalItem, isExpanded, toggleExpand }">
5020
+ <v-btn
5021
+ :append-icon="isExpanded(internalItem) ? mdiChevronUp : mdiChevronDown"
5022
+ :text="isExpanded(internalItem) ? 'Fermer' : \`Plus d'info\`"
5023
+ class="text-none"
5024
+ color="medium-emphasis"
5025
+ size="small"
5026
+ variant="text"
5027
+ width="105"
5028
+ border
5029
+ slim
5030
+ @click="toggleExpand(internalItem)"
5031
+ />
5032
+ </template>
5033
+
5034
+ <template #expanded-row="{ columns, item }">
5035
+ <tr>
5036
+ <td
5037
+ :colspan="columns.length"
5038
+ class="py-2"
5039
+ >
5040
+ <strong>Informations complémentaires :</strong>
5041
+ <p>Plus de détails pour {{ item.firstname }} {{ item.lastname }}.</p>
5042
+ </td>
5043
+ </tr>
5044
+ </template>
5045
+ </SyServerTable>
5046
+ </div>
5047
+ `,
5048
+ }
5049
+ },
5050
+ }
5051
+
4743
5052
  export const SlotItem: Story = {
4744
5053
  parameters: {
4745
5054
  sourceCode: [
@@ -91,12 +91,25 @@
91
91
 
92
92
  // Use the pagination composable with displayedItemsLength (stable during refetch)
93
93
  const itemsLength = computed(() => displayedItemsLength.value)
94
- const { page, pageCount, itemsPerPageValue, updateItemsPerPage } = usePagination({
94
+ const { page, pageCount, itemsPerPageValue, updateItemsPerPage, isUpdatingItemsPerPage } = usePagination({
95
95
  options,
96
96
  itemsLength,
97
- table,
98
97
  })
99
98
 
99
+ // Defines a function to handle updating the data table options
100
+ function onUpdateOptions(newOptions: Partial<DataOptions>) {
101
+ if (isUpdatingItemsPerPage.value && typeof newOptions.itemsPerPage !== 'undefined') {
102
+ // Creates a copy of the received options
103
+ const rest = { ...newOptions }
104
+ delete (rest as Record<string, unknown>).itemsPerPage
105
+ // Updates the other options without modifying itemsPerPage
106
+ updateOptions(rest)
107
+ return
108
+ }
109
+ // In all other cases, simply updates the options with the new values
110
+ updateOptions(newOptions)
111
+ }
112
+
100
113
  // Create a computed property for items to ensure reactivity
101
114
  // Bind to displayedItems so it is always an array
102
115
  const tableItems = computed<Record<string, unknown>[]>(() => displayedItems.value)
@@ -191,6 +204,7 @@
191
204
  updateModelValue: (value) => {
192
205
  model.value = value
193
206
  },
207
+ selectionKey: toRef(props, 'selectionKey'),
194
208
  })
195
209
 
196
210
  // Use the ARIA accessibility composable
@@ -267,7 +281,8 @@
267
281
  :item-value="getItemValue"
268
282
  :multi-sort="props.multiSort"
269
283
  :must-sort="props.mustSort"
270
- @update:options="updateOptions"
284
+ :show-expand="props.showExpand"
285
+ @update:options="onUpdateOptions"
271
286
  >
272
287
  <template #top>
273
288
  <caption
@@ -662,6 +662,73 @@ describe('SyServerTable', () => {
662
662
  })
663
663
  })
664
664
 
665
+ describe('SyServerTable Checkbox selectionKey', () => {
666
+ it('uses custom selectionKey when provided', async () => {
667
+ const items = [
668
+ { id: 1, uuid: 's-1', name: 'A' },
669
+ { id: 2, uuid: 's-2', name: 'B' },
670
+ ]
671
+
672
+ const wrapper = mount(SyServerTable, {
673
+ props: {
674
+ headers,
675
+ items,
676
+ serverItemsLength: items.length,
677
+ showSelect: true,
678
+ selectionKey: 'uuid',
679
+ suffix: '',
680
+ },
681
+ })
682
+
683
+ const dataTable = wrapper.findComponent({ name: 'VDataTableServer' })
684
+ const itemValue = dataTable.props('itemValue') as (item: unknown) => unknown
685
+
686
+ expect(itemValue(items[0] as unknown as Record<string, unknown>)).toBe('s-1')
687
+ expect(itemValue(items[1] as unknown as Record<string, unknown>)).toBe('s-2')
688
+ })
689
+
690
+ it('falls back to id when selectionKey is missing on item', async () => {
691
+ const items = [{ id: 10, name: 'No UUID' }]
692
+
693
+ const wrapper = mount(SyServerTable, {
694
+ props: {
695
+ headers,
696
+ items,
697
+ serverItemsLength: items.length,
698
+ showSelect: true,
699
+ selectionKey: 'uuid',
700
+ suffix: '',
701
+ },
702
+ })
703
+
704
+ const dataTable = wrapper.findComponent({ name: 'VDataTableServer' })
705
+ const itemValue = dataTable.props('itemValue') as (item: unknown) => unknown
706
+
707
+ expect(itemValue(items[0] as unknown as Record<string, unknown>)).toBe(10)
708
+ })
709
+
710
+ it('falls back to full object when neither selectionKey nor id are present', async () => {
711
+ const item = { name: 'No keys' }
712
+
713
+ const wrapper = mount(SyServerTable, {
714
+ props: {
715
+ headers,
716
+ items: [item],
717
+ serverItemsLength: 1,
718
+ showSelect: true,
719
+ selectionKey: 'uuid',
720
+ suffix: '',
721
+ },
722
+ })
723
+
724
+ const dataTable = wrapper.findComponent({ name: 'VDataTableServer' })
725
+ const itemValue = dataTable.props('itemValue') as (item: unknown) => unknown
726
+
727
+ const result = itemValue(item as unknown as Record<string, unknown>)
728
+ expect(result).toBe(item)
729
+ })
730
+ })
731
+
665
732
  describe('Column management', () => {
666
733
  it('should hide a column when hideColumn is called', async () => {
667
734
  // Create a mock for OrganizeColumns component
@@ -44,6 +44,21 @@ Le composant permet de cacher ou réorganiser l'ordre des colonnes en utilisant
44
44
 
45
45
  Le composant permet de sélectionner des lignes individuellement ou en masse. Vous pouvez activer la sélection en utilisant la prop `show-select`.
46
46
 
47
+ Par défaut, la clé utilisée pour identifier chaque ligne lors de la sélection est `id`. Si vos éléments ne possèdent pas de propriété `id`, la valeur sélectionnée correspondra à l'objet complet de la ligne.
48
+
49
+ Vous pouvez personnaliser cette clé avec la prop `selection-key` pour indiquer quel champ utiliser (ex: `userId`).
50
+
51
+ Exemple d'utilisation :
52
+ <Source dark code={`
53
+ <SyTable
54
+ v-model="selected"
55
+ :items="items"
56
+ :headers="headers"
57
+ show-select
58
+ selection-key="userId"
59
+ />
60
+ `}/>
61
+
47
62
  ### Slot item
48
63
  Le composant permet de personnaliser l'affichage des contenus en utilisant le slot `item`. Vous pouvez définir la structure de chaque contenu en fonction de vos besoins.
49
64