@pyreweb/fabric 1.2.6

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 (210) hide show
  1. package/README.md +119 -0
  2. package/dist/fabric.cjs.js +18109 -0
  3. package/dist/fabric.css +2180 -0
  4. package/dist/fabric.esm.js +18062 -0
  5. package/dist/fabric.min.js +18112 -0
  6. package/dist/types/components/atoms/FAvatar/FAvatar.test.d.ts +1 -0
  7. package/dist/types/components/atoms/FBadge/FBadge.test.d.ts +1 -0
  8. package/dist/types/components/atoms/FButton/FButton.test.d.ts +1 -0
  9. package/dist/types/components/atoms/FCheckbox/FCheckbox.test.d.ts +1 -0
  10. package/dist/types/components/atoms/FDivider/FDivider.test.d.ts +1 -0
  11. package/dist/types/components/atoms/FIcon/FIcon.test.d.ts +1 -0
  12. package/dist/types/components/atoms/FInput/FInput.test.d.ts +1 -0
  13. package/dist/types/components/atoms/FLoader/FLoader.test.d.ts +1 -0
  14. package/dist/types/components/atoms/FRadio/FRadio.test.d.ts +1 -0
  15. package/dist/types/components/atoms/FTextarea/FTextarea.test.d.ts +1 -0
  16. package/dist/types/components/atoms/FToggle/FToggle.test.d.ts +1 -0
  17. package/dist/types/components/atoms/FTypography/FTypography.test.d.ts +1 -0
  18. package/dist/types/components/atoms/index.d.ts +13 -0
  19. package/dist/types/components/molecules/FAccordionItem/FAccordionItem.test.d.ts +1 -0
  20. package/dist/types/components/molecules/FAlert/FAlert.test.d.ts +1 -0
  21. package/dist/types/components/molecules/FBreadcrumb/FBreadcrumb.test.d.ts +1 -0
  22. package/dist/types/components/molecules/FButtonGroup/FButtonGroup.test.d.ts +1 -0
  23. package/dist/types/components/molecules/FCard/FCard.test.d.ts +1 -0
  24. package/dist/types/components/molecules/FDatePicker/FDatePicker.test.d.ts +1 -0
  25. package/dist/types/components/molecules/FEmptyState/FEmptyState.test.d.ts +1 -0
  26. package/dist/types/components/molecules/FFilePreview/FFilePreview.test.d.ts +1 -0
  27. package/dist/types/components/molecules/FFormField/FFormField.test.d.ts +1 -0
  28. package/dist/types/components/molecules/FListItem/FListItem.test.d.ts +1 -0
  29. package/dist/types/components/molecules/FPagination/FPagination.test.d.ts +1 -0
  30. package/dist/types/components/molecules/FSearchBar/FSearchBar.test.d.ts +1 -0
  31. package/dist/types/components/molecules/FSelect/FSelect.test.d.ts +1 -0
  32. package/dist/types/components/molecules/FStatCard/FStatCard.test.d.ts +1 -0
  33. package/dist/types/components/molecules/FTabs/FTabs.test.d.ts +1 -0
  34. package/dist/types/components/molecules/FToast/FToast.test.d.ts +1 -0
  35. package/dist/types/components/molecules/index.d.ts +18 -0
  36. package/dist/types/components/organisms/FActivityFeed/FActivityFeed.test.d.ts +1 -0
  37. package/dist/types/components/organisms/FDataTable/FDataTable.test.d.ts +1 -0
  38. package/dist/types/components/organisms/FDrawer/FDrawer.test.d.ts +1 -0
  39. package/dist/types/components/organisms/FFileUpload/FFileUpload.test.d.ts +1 -0
  40. package/dist/types/components/organisms/FFilterSidebar/FFilterSidebar.test.d.ts +1 -0
  41. package/dist/types/components/organisms/FForm/FForm.test.d.ts +1 -0
  42. package/dist/types/components/organisms/FModal/FModal.test.d.ts +1 -0
  43. package/dist/types/components/organisms/FNavigationSidebar/FNavigationSidebar.test.d.ts +1 -0
  44. package/dist/types/components/organisms/FOnboardingStepper/FOnboardingStepper.test.d.ts +1 -0
  45. package/dist/types/components/organisms/FOnboardingStepper/FStepperProgress.test.d.ts +1 -0
  46. package/dist/types/components/organisms/FPageHeader/FPageHeader.test.d.ts +1 -0
  47. package/dist/types/components/organisms/FProfileSection/FProfileSection.test.d.ts +1 -0
  48. package/dist/types/components/organisms/FToastProvider/FToastProvider.test.d.ts +1 -0
  49. package/dist/types/components/organisms/FUserMenu/FUserMenu.test.d.ts +1 -0
  50. package/dist/types/components/organisms/index.d.ts +14 -0
  51. package/dist/types/components/utils/FThemeProvider.test.d.ts +1 -0
  52. package/dist/types/components/utils/index.d.ts +2 -0
  53. package/dist/types/components.d.ts +602 -0
  54. package/dist/types/composables/index.d.ts +12 -0
  55. package/dist/types/composables/useDataTableState.d.ts +106 -0
  56. package/dist/types/composables/useDataTableState.test.d.ts +1 -0
  57. package/dist/types/composables/useFormValidation.d.ts +49 -0
  58. package/dist/types/composables/useFormValidation.test.d.ts +1 -0
  59. package/dist/types/composables/useSidebarState.d.ts +65 -0
  60. package/dist/types/composables/useSidebarState.test.d.ts +1 -0
  61. package/dist/types/index.d.ts +19 -0
  62. package/dist/types/types.d.ts +529 -0
  63. package/package.json +100 -0
  64. package/src/components/atoms/FAvatar/FAvatar.stories.js +100 -0
  65. package/src/components/atoms/FAvatar/FAvatar.test.ts +95 -0
  66. package/src/components/atoms/FAvatar/FAvatar.vue +190 -0
  67. package/src/components/atoms/FBadge/FBadge.stories.js +129 -0
  68. package/src/components/atoms/FBadge/FBadge.test.ts +93 -0
  69. package/src/components/atoms/FBadge/FBadge.vue +103 -0
  70. package/src/components/atoms/FButton/FButton.stories.js +122 -0
  71. package/src/components/atoms/FButton/FButton.test.ts +98 -0
  72. package/src/components/atoms/FButton/FButton.vue +147 -0
  73. package/src/components/atoms/FCheckbox/FCheckbox.stories.js +96 -0
  74. package/src/components/atoms/FCheckbox/FCheckbox.test.ts +64 -0
  75. package/src/components/atoms/FCheckbox/FCheckbox.vue +76 -0
  76. package/src/components/atoms/FDivider/FDivider.stories.js +104 -0
  77. package/src/components/atoms/FDivider/FDivider.test.ts +80 -0
  78. package/src/components/atoms/FDivider/FDivider.vue +117 -0
  79. package/src/components/atoms/FIcon/FIcon.stories.js +189 -0
  80. package/src/components/atoms/FIcon/FIcon.test.ts +99 -0
  81. package/src/components/atoms/FIcon/FIcon.vue +192 -0
  82. package/src/components/atoms/FInput/FInput.stories.js +119 -0
  83. package/src/components/atoms/FInput/FInput.test.ts +79 -0
  84. package/src/components/atoms/FInput/FInput.vue +88 -0
  85. package/src/components/atoms/FLoader/FLoader.stories.js +109 -0
  86. package/src/components/atoms/FLoader/FLoader.test.ts +66 -0
  87. package/src/components/atoms/FLoader/FLoader.vue +97 -0
  88. package/src/components/atoms/FRadio/FRadio.stories.js +105 -0
  89. package/src/components/atoms/FRadio/FRadio.test.ts +75 -0
  90. package/src/components/atoms/FRadio/FRadio.vue +119 -0
  91. package/src/components/atoms/FTextarea/FTextarea.stories.js +126 -0
  92. package/src/components/atoms/FTextarea/FTextarea.test.ts +94 -0
  93. package/src/components/atoms/FTextarea/FTextarea.vue +156 -0
  94. package/src/components/atoms/FToggle/FToggle.stories.js +108 -0
  95. package/src/components/atoms/FToggle/FToggle.test.ts +96 -0
  96. package/src/components/atoms/FToggle/FToggle.vue +123 -0
  97. package/src/components/atoms/FTypography/FTypography.stories.js +127 -0
  98. package/src/components/atoms/FTypography/FTypography.test.ts +93 -0
  99. package/src/components/atoms/FTypography/FTypography.vue +78 -0
  100. package/src/components/atoms/index.ts +27 -0
  101. package/src/components/molecules/FAccordionItem/FAccordionItem.stories.js +71 -0
  102. package/src/components/molecules/FAccordionItem/FAccordionItem.test.ts +61 -0
  103. package/src/components/molecules/FAccordionItem/FAccordionItem.vue +105 -0
  104. package/src/components/molecules/FAlert/FAlert.stories.js +87 -0
  105. package/src/components/molecules/FAlert/FAlert.test.ts +59 -0
  106. package/src/components/molecules/FAlert/FAlert.vue +108 -0
  107. package/src/components/molecules/FBreadcrumb/FBreadcrumb.stories.js +90 -0
  108. package/src/components/molecules/FBreadcrumb/FBreadcrumb.test.ts +76 -0
  109. package/src/components/molecules/FBreadcrumb/FBreadcrumb.vue +117 -0
  110. package/src/components/molecules/FButtonGroup/FButtonGroup.stories.js +82 -0
  111. package/src/components/molecules/FButtonGroup/FButtonGroup.test.ts +44 -0
  112. package/src/components/molecules/FButtonGroup/FButtonGroup.vue +31 -0
  113. package/src/components/molecules/FCard/FCard.stories.js +136 -0
  114. package/src/components/molecules/FCard/FCard.test.ts +87 -0
  115. package/src/components/molecules/FCard/FCard.vue +75 -0
  116. package/src/components/molecules/FDatePicker/FDatePicker.stories.js +305 -0
  117. package/src/components/molecules/FDatePicker/FDatePicker.test.ts +282 -0
  118. package/src/components/molecules/FDatePicker/FDatePicker.vue +750 -0
  119. package/src/components/molecules/FEmptyState/FEmptyState.stories.js +98 -0
  120. package/src/components/molecules/FEmptyState/FEmptyState.test.ts +82 -0
  121. package/src/components/molecules/FEmptyState/FEmptyState.vue +89 -0
  122. package/src/components/molecules/FFilePreview/FFilePreview.stories.js +130 -0
  123. package/src/components/molecules/FFilePreview/FFilePreview.test.ts +70 -0
  124. package/src/components/molecules/FFilePreview/FFilePreview.vue +125 -0
  125. package/src/components/molecules/FFormField/FFormField.stories.js +149 -0
  126. package/src/components/molecules/FFormField/FFormField.test.ts +85 -0
  127. package/src/components/molecules/FFormField/FFormField.vue +107 -0
  128. package/src/components/molecules/FListItem/FListItem.stories.js +158 -0
  129. package/src/components/molecules/FListItem/FListItem.test.ts +93 -0
  130. package/src/components/molecules/FListItem/FListItem.vue +113 -0
  131. package/src/components/molecules/FPagination/FPagination.stories.js +132 -0
  132. package/src/components/molecules/FPagination/FPagination.test.ts +79 -0
  133. package/src/components/molecules/FPagination/FPagination.vue +206 -0
  134. package/src/components/molecules/FSearchBar/FSearchBar.stories.js +129 -0
  135. package/src/components/molecules/FSearchBar/FSearchBar.test.ts +81 -0
  136. package/src/components/molecules/FSearchBar/FSearchBar.vue +180 -0
  137. package/src/components/molecules/FSelect/FSelect.stories.js +333 -0
  138. package/src/components/molecules/FSelect/FSelect.test.ts +478 -0
  139. package/src/components/molecules/FSelect/FSelect.vue +551 -0
  140. package/src/components/molecules/FStatCard/FStatCard.stories.js +144 -0
  141. package/src/components/molecules/FStatCard/FStatCard.test.ts +78 -0
  142. package/src/components/molecules/FStatCard/FStatCard.vue +106 -0
  143. package/src/components/molecules/FTabs/FTab.vue +63 -0
  144. package/src/components/molecules/FTabs/FTabs.stories.js +277 -0
  145. package/src/components/molecules/FTabs/FTabs.test.ts +264 -0
  146. package/src/components/molecules/FTabs/FTabs.vue +273 -0
  147. package/src/components/molecules/FToast/FToast.stories.js +150 -0
  148. package/src/components/molecules/FToast/FToast.test.ts +157 -0
  149. package/src/components/molecules/FToast/FToast.vue +283 -0
  150. package/src/components/molecules/index.ts +37 -0
  151. package/src/components/organisms/FActivityFeed/FActivityFeed.stories.js +217 -0
  152. package/src/components/organisms/FActivityFeed/FActivityFeed.test.ts +134 -0
  153. package/src/components/organisms/FActivityFeed/FActivityFeed.vue +589 -0
  154. package/src/components/organisms/FDataTable/FDataTable.stories.js +370 -0
  155. package/src/components/organisms/FDataTable/FDataTable.test.ts +248 -0
  156. package/src/components/organisms/FDataTable/FDataTable.vue +808 -0
  157. package/src/components/organisms/FDrawer/FDrawer.stories.js +296 -0
  158. package/src/components/organisms/FDrawer/FDrawer.test.ts +142 -0
  159. package/src/components/organisms/FDrawer/FDrawer.vue +303 -0
  160. package/src/components/organisms/FFileUpload/FFileUpload.stories.js +162 -0
  161. package/src/components/organisms/FFileUpload/FFileUpload.test.ts +103 -0
  162. package/src/components/organisms/FFileUpload/FFileUpload.vue +616 -0
  163. package/src/components/organisms/FFilterSidebar/FFilterSidebar.stories.js +161 -0
  164. package/src/components/organisms/FFilterSidebar/FFilterSidebar.test.ts +92 -0
  165. package/src/components/organisms/FFilterSidebar/FFilterSidebar.vue +458 -0
  166. package/src/components/organisms/FForm/FForm.stories.js +270 -0
  167. package/src/components/organisms/FForm/FForm.test.ts +63 -0
  168. package/src/components/organisms/FForm/FForm.vue +19 -0
  169. package/src/components/organisms/FModal/FModal.stories.js +227 -0
  170. package/src/components/organisms/FModal/FModal.test.ts +181 -0
  171. package/src/components/organisms/FModal/FModal.vue +319 -0
  172. package/src/components/organisms/FNavigationSidebar/FNavigationSidebar.stories.js +176 -0
  173. package/src/components/organisms/FNavigationSidebar/FNavigationSidebar.test.ts +95 -0
  174. package/src/components/organisms/FNavigationSidebar/FNavigationSidebar.vue +577 -0
  175. package/src/components/organisms/FOnboardingStepper/FOnboardingStepper.stories.js +197 -0
  176. package/src/components/organisms/FOnboardingStepper/FOnboardingStepper.test.ts +114 -0
  177. package/src/components/organisms/FOnboardingStepper/FOnboardingStepper.vue +212 -0
  178. package/src/components/organisms/FOnboardingStepper/FStepperProgress.stories.js +122 -0
  179. package/src/components/organisms/FOnboardingStepper/FStepperProgress.test.ts +130 -0
  180. package/src/components/organisms/FOnboardingStepper/FStepperProgress.vue +146 -0
  181. package/src/components/organisms/FPageHeader/FPageHeader.stories.js +142 -0
  182. package/src/components/organisms/FPageHeader/FPageHeader.test.ts +83 -0
  183. package/src/components/organisms/FPageHeader/FPageHeader.vue +241 -0
  184. package/src/components/organisms/FProfileSection/FProfileSection.stories.js +190 -0
  185. package/src/components/organisms/FProfileSection/FProfileSection.test.ts +85 -0
  186. package/src/components/organisms/FProfileSection/FProfileSection.vue +562 -0
  187. package/src/components/organisms/FToastProvider/FToastProvider.stories.js +290 -0
  188. package/src/components/organisms/FToastProvider/FToastProvider.test.ts +215 -0
  189. package/src/components/organisms/FToastProvider/FToastProvider.vue +214 -0
  190. package/src/components/organisms/FUserMenu/FUserMenu.stories.js +170 -0
  191. package/src/components/organisms/FUserMenu/FUserMenu.test.ts +102 -0
  192. package/src/components/organisms/FUserMenu/FUserMenu.vue +407 -0
  193. package/src/components/organisms/index.ts +29 -0
  194. package/src/components/utils/FThemeProvider.stories.js +236 -0
  195. package/src/components/utils/FThemeProvider.test.ts +244 -0
  196. package/src/components/utils/FThemeProvider.vue +191 -0
  197. package/src/components/utils/index.ts +3 -0
  198. package/src/components.d.ts +602 -0
  199. package/src/composables/README.md +233 -0
  200. package/src/composables/index.ts +25 -0
  201. package/src/composables/useDataTableState.test.ts +378 -0
  202. package/src/composables/useDataTableState.ts +361 -0
  203. package/src/composables/useFormValidation.test.ts +198 -0
  204. package/src/composables/useFormValidation.ts +178 -0
  205. package/src/composables/useSidebarState.test.ts +307 -0
  206. package/src/composables/useSidebarState.ts +201 -0
  207. package/src/env.d.ts +14 -0
  208. package/src/index.ts +167 -0
  209. package/src/styles/tailwind.css +173 -0
  210. package/src/types.ts +740 -0
@@ -0,0 +1,305 @@
1
+ import FDatePicker from './FDatePicker.vue';
2
+
3
+ export default {
4
+ title: 'Molecules/FDatePicker',
5
+ component: FDatePicker,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ value: {
9
+ control: 'object',
10
+ description:
11
+ 'Valeur du sélecteur (Date ou Array de dates pour le mode range)'
12
+ },
13
+ mode: {
14
+ control: { type: 'select' },
15
+ options: ['single', 'range'],
16
+ description: 'Mode de sélection (single ou range)'
17
+ },
18
+ placeholder: {
19
+ control: 'text',
20
+ description: 'Texte de placeholder'
21
+ },
22
+ format: {
23
+ control: 'text',
24
+ description: 'Format de date (DD/MM/YYYY par défaut)'
25
+ },
26
+ size: {
27
+ control: { type: 'select' },
28
+ options: ['small', 'medium', 'large'],
29
+ description: 'Taille du champ'
30
+ },
31
+ disabled: {
32
+ control: 'boolean',
33
+ description: 'État désactivé'
34
+ },
35
+ readonly: {
36
+ control: 'boolean',
37
+ description: 'Lecture seule'
38
+ },
39
+ error: {
40
+ control: 'boolean',
41
+ description: "État d'erreur"
42
+ },
43
+ showTimePicker: {
44
+ control: 'boolean',
45
+ description: "Afficher le sélecteur d'heure"
46
+ },
47
+ minDate: {
48
+ control: 'date',
49
+ description: 'Date minimale autorisée'
50
+ },
51
+ maxDate: {
52
+ control: 'date',
53
+ description: 'Date maximale autorisée'
54
+ },
55
+ disabledDates: {
56
+ control: 'object',
57
+ description: 'Tableau de dates désactivées'
58
+ },
59
+ monthNames: {
60
+ control: 'object',
61
+ description: 'Noms personnalisés des mois'
62
+ },
63
+ dayNames: {
64
+ control: 'object',
65
+ description: 'Noms personnalisés des jours de la semaine'
66
+ },
67
+ firstDayOfWeek: {
68
+ control: { type: 'number', min: 0, max: 6 },
69
+ description: 'Premier jour de la semaine (0 = Dimanche, 1 = Lundi)'
70
+ }
71
+ }
72
+ };
73
+
74
+ const Template = (args, { argTypes }) => ({
75
+ components: { FDatePicker },
76
+ props: Object.keys(argTypes),
77
+ data() {
78
+ return {
79
+ selectedDate: args.value || null
80
+ };
81
+ },
82
+ template: `
83
+ <div class="p-4">
84
+ <FDatePicker v-bind="$props" v-model="selectedDate" />
85
+ <div v-if="selectedDate" class="mt-4 p-3 bg-neutral-100 rounded">
86
+ <p class="text-sm font-medium text-neutral-700">Date sélectionnée :</p>
87
+ <p class="text-sm text-neutral-600">{{ selectedDate }}</p>
88
+ </div>
89
+ </div>
90
+ `
91
+ });
92
+
93
+ export const Default = Template.bind({});
94
+ Default.args = {
95
+ placeholder: 'Sélectionner une date'
96
+ };
97
+
98
+ export const WithValue = Template.bind({});
99
+ WithValue.args = {
100
+ value: new Date(2024, 11, 15),
101
+ placeholder: 'Sélectionner une date'
102
+ };
103
+
104
+ export const DateRange = Template.bind({});
105
+ DateRange.args = {
106
+ mode: 'range',
107
+ placeholder: 'Sélectionner une plage de dates'
108
+ };
109
+
110
+ export const WithTimePicker = Template.bind({});
111
+ WithTimePicker.args = {
112
+ showTimePicker: true,
113
+ placeholder: 'Sélectionner une date et heure'
114
+ };
115
+
116
+ export const WithMinMaxDates = Template.bind({});
117
+ WithMinMaxDates.args = {
118
+ minDate: new Date(2024, 11, 1),
119
+ maxDate: new Date(2024, 11, 31),
120
+ placeholder: 'Sélectionner une date en décembre 2024'
121
+ };
122
+
123
+ export const WithDisabledDates = Template.bind({});
124
+ WithDisabledDates.args = {
125
+ disabledDates: [
126
+ new Date(2024, 11, 10),
127
+ new Date(2024, 11, 15),
128
+ new Date(2024, 11, 20),
129
+ new Date(2024, 11, 25)
130
+ ],
131
+ placeholder: 'Certaines dates sont désactivées'
132
+ };
133
+
134
+ export const Sizes = () => ({
135
+ components: { FDatePicker },
136
+ data() {
137
+ return {
138
+ small: null,
139
+ medium: null,
140
+ large: null
141
+ };
142
+ },
143
+ template: `
144
+ <div class="flex flex-col gap-4 p-4">
145
+ <div>
146
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Petit</label>
147
+ <FDatePicker v-model="small" size="small" placeholder="Taille small" />
148
+ </div>
149
+ <div>
150
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Moyen</label>
151
+ <FDatePicker v-model="medium" size="medium" placeholder="Taille medium" />
152
+ </div>
153
+ <div>
154
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Grand</label>
155
+ <FDatePicker v-model="large" size="large" placeholder="Taille large" />
156
+ </div>
157
+ </div>
158
+ `
159
+ });
160
+
161
+ export const States = () => ({
162
+ components: { FDatePicker },
163
+ data() {
164
+ return {
165
+ normal: null,
166
+ disabled: new Date(),
167
+ readonly: new Date(),
168
+ error: null
169
+ };
170
+ },
171
+ template: `
172
+ <div class="flex flex-col gap-4 p-4">
173
+ <div>
174
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Normal</label>
175
+ <FDatePicker v-model="normal" placeholder="État normal" />
176
+ </div>
177
+ <div>
178
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Désactivé</label>
179
+ <FDatePicker v-model="disabled" placeholder="État désactivé" disabled />
180
+ </div>
181
+ <div>
182
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Lecture seule</label>
183
+ <FDatePicker v-model="readonly" placeholder="Lecture seule" readonly />
184
+ </div>
185
+ <div>
186
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Erreur</label>
187
+ <FDatePicker v-model="error" placeholder="État d'erreur" error />
188
+ </div>
189
+ </div>
190
+ `
191
+ });
192
+
193
+ export const CustomLocalization = Template.bind({});
194
+ CustomLocalization.args = {
195
+ monthNames: [
196
+ 'Jan',
197
+ 'Feb',
198
+ 'Mar',
199
+ 'Apr',
200
+ 'May',
201
+ 'Jun',
202
+ 'Jul',
203
+ 'Aug',
204
+ 'Sep',
205
+ 'Oct',
206
+ 'Nov',
207
+ 'Dec'
208
+ ],
209
+ dayNames: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
210
+ firstDayOfWeek: 0,
211
+ placeholder: 'Select a date (English)'
212
+ };
213
+
214
+ export const DateRangeWithTime = Template.bind({});
215
+ DateRangeWithTime.args = {
216
+ mode: 'range',
217
+ showTimePicker: true,
218
+ placeholder: 'Sélectionner une plage de dates avec heure'
219
+ };
220
+
221
+ export const CustomFormat = () => ({
222
+ components: { FDatePicker },
223
+ data() {
224
+ return {
225
+ date1: null,
226
+ date2: null,
227
+ date3: null
228
+ };
229
+ },
230
+ template: `
231
+ <div class="flex flex-col gap-4 p-4">
232
+ <div>
233
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Format: DD/MM/YYYY (par défaut)</label>
234
+ <FDatePicker v-model="date1" format="DD/MM/YYYY" />
235
+ </div>
236
+ <div>
237
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Format: YYYY-MM-DD</label>
238
+ <FDatePicker v-model="date2" format="YYYY-MM-DD" />
239
+ </div>
240
+ <div>
241
+ <label class="block text-sm font-medium text-neutral-700 mb-1">Format: MM/DD/YYYY</label>
242
+ <FDatePicker v-model="date3" format="MM/DD/YYYY" />
243
+ </div>
244
+ </div>
245
+ `
246
+ });
247
+
248
+ export const InForm = () => ({
249
+ components: { FDatePicker },
250
+ data() {
251
+ return {
252
+ formData: {
253
+ startDate: null,
254
+ endDate: null,
255
+ appointmentDate: null
256
+ }
257
+ };
258
+ },
259
+ methods: {
260
+ handleSubmit() {
261
+ alert(JSON.stringify(this.formData, null, 2));
262
+ }
263
+ },
264
+ template: `
265
+ <div class="max-w-md p-4">
266
+ <form @submit.prevent="handleSubmit" class="space-y-4">
267
+ <div>
268
+ <label class="block text-sm font-medium text-neutral-700 mb-1">
269
+ Date de début <span class="text-danger-500">*</span>
270
+ </label>
271
+ <FDatePicker
272
+ v-model="formData.startDate"
273
+ placeholder="Sélectionner la date de début"
274
+ />
275
+ </div>
276
+ <div>
277
+ <label class="block text-sm font-medium text-neutral-700 mb-1">
278
+ Date de fin <span class="text-danger-500">*</span>
279
+ </label>
280
+ <FDatePicker
281
+ v-model="formData.endDate"
282
+ :minDate="formData.startDate"
283
+ placeholder="Sélectionner la date de fin"
284
+ />
285
+ </div>
286
+ <div>
287
+ <label class="block text-sm font-medium text-neutral-700 mb-1">
288
+ Rendez-vous
289
+ </label>
290
+ <FDatePicker
291
+ v-model="formData.appointmentDate"
292
+ showTimePicker
293
+ placeholder="Sélectionner date et heure du rendez-vous"
294
+ />
295
+ </div>
296
+ <button
297
+ type="submit"
298
+ class="w-full px-4 py-2 bg-primary-500 text-white rounded hover:bg-primary-600 transition-colors"
299
+ >
300
+ Soumettre
301
+ </button>
302
+ </form>
303
+ </div>
304
+ `
305
+ });
@@ -0,0 +1,282 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+ import FDatePicker from './FDatePicker.vue';
4
+
5
+ describe('FDatePicker', () => {
6
+ let wrapper;
7
+
8
+ beforeEach(() => {
9
+ wrapper = mount(FDatePicker);
10
+ });
11
+
12
+ it('renders correctly with default props', () => {
13
+ expect(wrapper.find('input').exists()).toBe(true);
14
+ expect(wrapper.find('.relative').exists()).toBe(true);
15
+ });
16
+
17
+ it('displays placeholder', () => {
18
+ const customPlaceholder = 'Choisir une date';
19
+ wrapper = mount(FDatePicker, {
20
+ propsData: { placeholder: customPlaceholder }
21
+ });
22
+ expect(wrapper.find('input').attributes('placeholder')).toBe(
23
+ customPlaceholder
24
+ );
25
+ });
26
+
27
+ it('opens calendar when input is clicked', async () => {
28
+ const input = wrapper.find('input');
29
+ await input.trigger('click');
30
+ expect(wrapper.vm.isOpen).toBe(true);
31
+ expect(wrapper.find('[role="dialog"]').isVisible()).toBe(true);
32
+ });
33
+
34
+ it('closes calendar on escape key', async () => {
35
+ const input = wrapper.find('input');
36
+ await input.trigger('click');
37
+ expect(wrapper.vm.isOpen).toBe(true);
38
+
39
+ await wrapper.trigger('keydown.escape');
40
+ expect(wrapper.vm.isOpen).toBe(false);
41
+ });
42
+
43
+ it('applies disabled state', () => {
44
+ wrapper = mount(FDatePicker, {
45
+ propsData: { disabled: true }
46
+ });
47
+ expect(wrapper.find('input').attributes('disabled')).toBeDefined();
48
+ expect(wrapper.find('input').classes()).toContain('cursor-not-allowed');
49
+ });
50
+
51
+ it('applies readonly state', () => {
52
+ wrapper = mount(FDatePicker, {
53
+ propsData: { readonly: true }
54
+ });
55
+ expect(wrapper.find('input').attributes('readonly')).toBeDefined();
56
+ });
57
+
58
+ it('applies error styles', () => {
59
+ wrapper = mount(FDatePicker, {
60
+ propsData: { error: true }
61
+ });
62
+ expect(wrapper.find('input').classes().join(' ')).toContain(
63
+ 'border-danger'
64
+ );
65
+ });
66
+
67
+ it('initializes with provided date value in single mode', () => {
68
+ const testDate = new Date(2024, 0, 15);
69
+ wrapper = mount(FDatePicker, {
70
+ propsData: {
71
+ value: testDate,
72
+ mode: 'single'
73
+ }
74
+ });
75
+ expect(wrapper.vm.selectedDate).toBeTruthy();
76
+ expect(wrapper.vm.selectedDate.getDate()).toBe(15);
77
+ expect(wrapper.vm.selectedDate.getMonth()).toBe(0);
78
+ expect(wrapper.vm.selectedDate.getFullYear()).toBe(2024);
79
+ });
80
+
81
+ it('initializes with provided date range in range mode', () => {
82
+ const startDate = new Date(2024, 0, 10);
83
+ const endDate = new Date(2024, 0, 20);
84
+ wrapper = mount(FDatePicker, {
85
+ propsData: {
86
+ value: [startDate, endDate],
87
+ mode: 'range'
88
+ }
89
+ });
90
+ expect(wrapper.vm.selectedRangeStart).toBeTruthy();
91
+ expect(wrapper.vm.selectedRangeEnd).toBeTruthy();
92
+ });
93
+
94
+ it('formats date according to format prop', () => {
95
+ const testDate = new Date(2024, 0, 15);
96
+ wrapper = mount(FDatePicker, {
97
+ propsData: {
98
+ value: testDate,
99
+ format: 'DD/MM/YYYY'
100
+ }
101
+ });
102
+ expect(wrapper.vm.displayValue).toBe('15/01/2024');
103
+ });
104
+
105
+ it('displays time picker when showTimePicker is true', async () => {
106
+ wrapper = mount(FDatePicker, {
107
+ propsData: { showTimePicker: true }
108
+ });
109
+ const input = wrapper.find('input');
110
+ await input.trigger('click');
111
+ await wrapper.vm.$nextTick();
112
+
113
+ expect(wrapper.text()).toContain('Heures');
114
+ expect(wrapper.text()).toContain('Minutes');
115
+ });
116
+
117
+ it('navigates to previous month', async () => {
118
+ const input = wrapper.find('input');
119
+ await input.trigger('click');
120
+ await wrapper.vm.$nextTick();
121
+
122
+ const initialMonth = wrapper.vm.displayMonth;
123
+ wrapper.vm.previousMonth();
124
+ await wrapper.vm.$nextTick();
125
+
126
+ expect(wrapper.vm.displayMonth).not.toBe(initialMonth);
127
+ });
128
+
129
+ it('navigates to next month', async () => {
130
+ const input = wrapper.find('input');
131
+ await input.trigger('click');
132
+ await wrapper.vm.$nextTick();
133
+
134
+ const initialMonth = wrapper.vm.displayMonth;
135
+ wrapper.vm.nextMonth();
136
+ await wrapper.vm.$nextTick();
137
+
138
+ expect(wrapper.vm.displayMonth).not.toBe(initialMonth);
139
+ });
140
+
141
+ it('disables dates before minDate', () => {
142
+ const minDate = new Date(2024, 0, 15);
143
+ wrapper = mount(FDatePicker, {
144
+ propsData: { minDate }
145
+ });
146
+
147
+ const testDay = {
148
+ date: 10,
149
+ month: 0,
150
+ year: 2024,
151
+ isCurrentMonth: true
152
+ };
153
+
154
+ expect(wrapper.vm.isDayDisabled(testDay)).toBe(true);
155
+ });
156
+
157
+ it('disables dates after maxDate', () => {
158
+ const maxDate = new Date(2024, 0, 15);
159
+ wrapper = mount(FDatePicker, {
160
+ propsData: { maxDate }
161
+ });
162
+
163
+ const testDay = {
164
+ date: 20,
165
+ month: 0,
166
+ year: 2024,
167
+ isCurrentMonth: true
168
+ };
169
+
170
+ expect(wrapper.vm.isDayDisabled(testDay)).toBe(true);
171
+ });
172
+
173
+ it('disables specific dates from disabledDates array', () => {
174
+ const disabledDates = [new Date(2024, 0, 15)];
175
+ wrapper = mount(FDatePicker, {
176
+ propsData: { disabledDates }
177
+ });
178
+
179
+ const testDay = {
180
+ date: 15,
181
+ month: 0,
182
+ year: 2024,
183
+ isCurrentMonth: true
184
+ };
185
+
186
+ expect(wrapper.vm.isDayDisabled(testDay)).toBe(true);
187
+ });
188
+
189
+ it('emits input event when date is selected in single mode', async () => {
190
+ const input = wrapper.find('input');
191
+ await input.trigger('click');
192
+
193
+ const testDay = {
194
+ date: 15,
195
+ month: 0,
196
+ year: 2024,
197
+ isCurrentMonth: true
198
+ };
199
+
200
+ wrapper.vm.selectDate(testDay);
201
+ await wrapper.vm.$nextTick();
202
+
203
+ expect(wrapper.emitted('input')).toBeTruthy();
204
+ expect(wrapper.emitted('change')).toBeTruthy();
205
+ });
206
+
207
+ it('handles range selection correctly', async () => {
208
+ wrapper = mount(FDatePicker, {
209
+ propsData: { mode: 'range' }
210
+ });
211
+
212
+ const input = wrapper.find('input');
213
+ await input.trigger('click');
214
+
215
+ const startDay = {
216
+ date: 10,
217
+ month: 0,
218
+ year: 2024,
219
+ isCurrentMonth: true
220
+ };
221
+
222
+ const endDay = {
223
+ date: 20,
224
+ month: 0,
225
+ year: 2024,
226
+ isCurrentMonth: true
227
+ };
228
+
229
+ wrapper.vm.selectDate(startDay);
230
+ expect(wrapper.vm.selectedRangeStart).toBeTruthy();
231
+ expect(wrapper.vm.selectedRangeEnd).toBeFalsy();
232
+
233
+ wrapper.vm.selectDate(endDay);
234
+ expect(wrapper.vm.selectedRangeStart).toBeTruthy();
235
+ expect(wrapper.vm.selectedRangeEnd).toBeTruthy();
236
+ });
237
+
238
+ it('uses custom month and day names', () => {
239
+ const customMonthNames = [
240
+ 'Jan',
241
+ 'Fév',
242
+ 'Mar',
243
+ 'Avr',
244
+ 'Mai',
245
+ 'Jui',
246
+ 'Jul',
247
+ 'Aoû',
248
+ 'Sep',
249
+ 'Oct',
250
+ 'Nov',
251
+ 'Déc'
252
+ ];
253
+ const customDayNames = ['L', 'M', 'M', 'J', 'V', 'S', 'D'];
254
+
255
+ wrapper = mount(FDatePicker, {
256
+ propsData: {
257
+ monthNames: customMonthNames,
258
+ dayNames: customDayNames
259
+ }
260
+ });
261
+
262
+ expect(wrapper.vm.monthNames).toEqual(customMonthNames);
263
+ expect(wrapper.vm.dayNames).toEqual(customDayNames);
264
+ });
265
+
266
+ it('respects firstDayOfWeek prop', () => {
267
+ wrapper = mount(FDatePicker, {
268
+ propsData: { firstDayOfWeek: 0 } // Sunday
269
+ });
270
+
271
+ expect(wrapper.vm.firstDayOfWeek).toBe(0);
272
+ });
273
+
274
+ it('generates calendar days correctly', () => {
275
+ wrapper.vm.displayMonth = 0; // January
276
+ wrapper.vm.displayYear = 2024;
277
+ wrapper.vm.updateCalendar();
278
+
279
+ expect(wrapper.vm.calendarDays.length).toBeGreaterThan(0);
280
+ expect(wrapper.vm.calendarDays.length).toBe(42); // 6 weeks * 7 days
281
+ });
282
+ });