@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.
- package/README.md +119 -0
- package/dist/fabric.cjs.js +18109 -0
- package/dist/fabric.css +2180 -0
- package/dist/fabric.esm.js +18062 -0
- package/dist/fabric.min.js +18112 -0
- package/dist/types/components/atoms/FAvatar/FAvatar.test.d.ts +1 -0
- package/dist/types/components/atoms/FBadge/FBadge.test.d.ts +1 -0
- package/dist/types/components/atoms/FButton/FButton.test.d.ts +1 -0
- package/dist/types/components/atoms/FCheckbox/FCheckbox.test.d.ts +1 -0
- package/dist/types/components/atoms/FDivider/FDivider.test.d.ts +1 -0
- package/dist/types/components/atoms/FIcon/FIcon.test.d.ts +1 -0
- package/dist/types/components/atoms/FInput/FInput.test.d.ts +1 -0
- package/dist/types/components/atoms/FLoader/FLoader.test.d.ts +1 -0
- package/dist/types/components/atoms/FRadio/FRadio.test.d.ts +1 -0
- package/dist/types/components/atoms/FTextarea/FTextarea.test.d.ts +1 -0
- package/dist/types/components/atoms/FToggle/FToggle.test.d.ts +1 -0
- package/dist/types/components/atoms/FTypography/FTypography.test.d.ts +1 -0
- package/dist/types/components/atoms/index.d.ts +13 -0
- package/dist/types/components/molecules/FAccordionItem/FAccordionItem.test.d.ts +1 -0
- package/dist/types/components/molecules/FAlert/FAlert.test.d.ts +1 -0
- package/dist/types/components/molecules/FBreadcrumb/FBreadcrumb.test.d.ts +1 -0
- package/dist/types/components/molecules/FButtonGroup/FButtonGroup.test.d.ts +1 -0
- package/dist/types/components/molecules/FCard/FCard.test.d.ts +1 -0
- package/dist/types/components/molecules/FDatePicker/FDatePicker.test.d.ts +1 -0
- package/dist/types/components/molecules/FEmptyState/FEmptyState.test.d.ts +1 -0
- package/dist/types/components/molecules/FFilePreview/FFilePreview.test.d.ts +1 -0
- package/dist/types/components/molecules/FFormField/FFormField.test.d.ts +1 -0
- package/dist/types/components/molecules/FListItem/FListItem.test.d.ts +1 -0
- package/dist/types/components/molecules/FPagination/FPagination.test.d.ts +1 -0
- package/dist/types/components/molecules/FSearchBar/FSearchBar.test.d.ts +1 -0
- package/dist/types/components/molecules/FSelect/FSelect.test.d.ts +1 -0
- package/dist/types/components/molecules/FStatCard/FStatCard.test.d.ts +1 -0
- package/dist/types/components/molecules/FTabs/FTabs.test.d.ts +1 -0
- package/dist/types/components/molecules/FToast/FToast.test.d.ts +1 -0
- package/dist/types/components/molecules/index.d.ts +18 -0
- package/dist/types/components/organisms/FActivityFeed/FActivityFeed.test.d.ts +1 -0
- package/dist/types/components/organisms/FDataTable/FDataTable.test.d.ts +1 -0
- package/dist/types/components/organisms/FDrawer/FDrawer.test.d.ts +1 -0
- package/dist/types/components/organisms/FFileUpload/FFileUpload.test.d.ts +1 -0
- package/dist/types/components/organisms/FFilterSidebar/FFilterSidebar.test.d.ts +1 -0
- package/dist/types/components/organisms/FForm/FForm.test.d.ts +1 -0
- package/dist/types/components/organisms/FModal/FModal.test.d.ts +1 -0
- package/dist/types/components/organisms/FNavigationSidebar/FNavigationSidebar.test.d.ts +1 -0
- package/dist/types/components/organisms/FOnboardingStepper/FOnboardingStepper.test.d.ts +1 -0
- package/dist/types/components/organisms/FOnboardingStepper/FStepperProgress.test.d.ts +1 -0
- package/dist/types/components/organisms/FPageHeader/FPageHeader.test.d.ts +1 -0
- package/dist/types/components/organisms/FProfileSection/FProfileSection.test.d.ts +1 -0
- package/dist/types/components/organisms/FToastProvider/FToastProvider.test.d.ts +1 -0
- package/dist/types/components/organisms/FUserMenu/FUserMenu.test.d.ts +1 -0
- package/dist/types/components/organisms/index.d.ts +14 -0
- package/dist/types/components/utils/FThemeProvider.test.d.ts +1 -0
- package/dist/types/components/utils/index.d.ts +2 -0
- package/dist/types/components.d.ts +602 -0
- package/dist/types/composables/index.d.ts +12 -0
- package/dist/types/composables/useDataTableState.d.ts +106 -0
- package/dist/types/composables/useDataTableState.test.d.ts +1 -0
- package/dist/types/composables/useFormValidation.d.ts +49 -0
- package/dist/types/composables/useFormValidation.test.d.ts +1 -0
- package/dist/types/composables/useSidebarState.d.ts +65 -0
- package/dist/types/composables/useSidebarState.test.d.ts +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/types.d.ts +529 -0
- package/package.json +100 -0
- package/src/components/atoms/FAvatar/FAvatar.stories.js +100 -0
- package/src/components/atoms/FAvatar/FAvatar.test.ts +95 -0
- package/src/components/atoms/FAvatar/FAvatar.vue +190 -0
- package/src/components/atoms/FBadge/FBadge.stories.js +129 -0
- package/src/components/atoms/FBadge/FBadge.test.ts +93 -0
- package/src/components/atoms/FBadge/FBadge.vue +103 -0
- package/src/components/atoms/FButton/FButton.stories.js +122 -0
- package/src/components/atoms/FButton/FButton.test.ts +98 -0
- package/src/components/atoms/FButton/FButton.vue +147 -0
- package/src/components/atoms/FCheckbox/FCheckbox.stories.js +96 -0
- package/src/components/atoms/FCheckbox/FCheckbox.test.ts +64 -0
- package/src/components/atoms/FCheckbox/FCheckbox.vue +76 -0
- package/src/components/atoms/FDivider/FDivider.stories.js +104 -0
- package/src/components/atoms/FDivider/FDivider.test.ts +80 -0
- package/src/components/atoms/FDivider/FDivider.vue +117 -0
- package/src/components/atoms/FIcon/FIcon.stories.js +189 -0
- package/src/components/atoms/FIcon/FIcon.test.ts +99 -0
- package/src/components/atoms/FIcon/FIcon.vue +192 -0
- package/src/components/atoms/FInput/FInput.stories.js +119 -0
- package/src/components/atoms/FInput/FInput.test.ts +79 -0
- package/src/components/atoms/FInput/FInput.vue +88 -0
- package/src/components/atoms/FLoader/FLoader.stories.js +109 -0
- package/src/components/atoms/FLoader/FLoader.test.ts +66 -0
- package/src/components/atoms/FLoader/FLoader.vue +97 -0
- package/src/components/atoms/FRadio/FRadio.stories.js +105 -0
- package/src/components/atoms/FRadio/FRadio.test.ts +75 -0
- package/src/components/atoms/FRadio/FRadio.vue +119 -0
- package/src/components/atoms/FTextarea/FTextarea.stories.js +126 -0
- package/src/components/atoms/FTextarea/FTextarea.test.ts +94 -0
- package/src/components/atoms/FTextarea/FTextarea.vue +156 -0
- package/src/components/atoms/FToggle/FToggle.stories.js +108 -0
- package/src/components/atoms/FToggle/FToggle.test.ts +96 -0
- package/src/components/atoms/FToggle/FToggle.vue +123 -0
- package/src/components/atoms/FTypography/FTypography.stories.js +127 -0
- package/src/components/atoms/FTypography/FTypography.test.ts +93 -0
- package/src/components/atoms/FTypography/FTypography.vue +78 -0
- package/src/components/atoms/index.ts +27 -0
- package/src/components/molecules/FAccordionItem/FAccordionItem.stories.js +71 -0
- package/src/components/molecules/FAccordionItem/FAccordionItem.test.ts +61 -0
- package/src/components/molecules/FAccordionItem/FAccordionItem.vue +105 -0
- package/src/components/molecules/FAlert/FAlert.stories.js +87 -0
- package/src/components/molecules/FAlert/FAlert.test.ts +59 -0
- package/src/components/molecules/FAlert/FAlert.vue +108 -0
- package/src/components/molecules/FBreadcrumb/FBreadcrumb.stories.js +90 -0
- package/src/components/molecules/FBreadcrumb/FBreadcrumb.test.ts +76 -0
- package/src/components/molecules/FBreadcrumb/FBreadcrumb.vue +117 -0
- package/src/components/molecules/FButtonGroup/FButtonGroup.stories.js +82 -0
- package/src/components/molecules/FButtonGroup/FButtonGroup.test.ts +44 -0
- package/src/components/molecules/FButtonGroup/FButtonGroup.vue +31 -0
- package/src/components/molecules/FCard/FCard.stories.js +136 -0
- package/src/components/molecules/FCard/FCard.test.ts +87 -0
- package/src/components/molecules/FCard/FCard.vue +75 -0
- package/src/components/molecules/FDatePicker/FDatePicker.stories.js +305 -0
- package/src/components/molecules/FDatePicker/FDatePicker.test.ts +282 -0
- package/src/components/molecules/FDatePicker/FDatePicker.vue +750 -0
- package/src/components/molecules/FEmptyState/FEmptyState.stories.js +98 -0
- package/src/components/molecules/FEmptyState/FEmptyState.test.ts +82 -0
- package/src/components/molecules/FEmptyState/FEmptyState.vue +89 -0
- package/src/components/molecules/FFilePreview/FFilePreview.stories.js +130 -0
- package/src/components/molecules/FFilePreview/FFilePreview.test.ts +70 -0
- package/src/components/molecules/FFilePreview/FFilePreview.vue +125 -0
- package/src/components/molecules/FFormField/FFormField.stories.js +149 -0
- package/src/components/molecules/FFormField/FFormField.test.ts +85 -0
- package/src/components/molecules/FFormField/FFormField.vue +107 -0
- package/src/components/molecules/FListItem/FListItem.stories.js +158 -0
- package/src/components/molecules/FListItem/FListItem.test.ts +93 -0
- package/src/components/molecules/FListItem/FListItem.vue +113 -0
- package/src/components/molecules/FPagination/FPagination.stories.js +132 -0
- package/src/components/molecules/FPagination/FPagination.test.ts +79 -0
- package/src/components/molecules/FPagination/FPagination.vue +206 -0
- package/src/components/molecules/FSearchBar/FSearchBar.stories.js +129 -0
- package/src/components/molecules/FSearchBar/FSearchBar.test.ts +81 -0
- package/src/components/molecules/FSearchBar/FSearchBar.vue +180 -0
- package/src/components/molecules/FSelect/FSelect.stories.js +333 -0
- package/src/components/molecules/FSelect/FSelect.test.ts +478 -0
- package/src/components/molecules/FSelect/FSelect.vue +551 -0
- package/src/components/molecules/FStatCard/FStatCard.stories.js +144 -0
- package/src/components/molecules/FStatCard/FStatCard.test.ts +78 -0
- package/src/components/molecules/FStatCard/FStatCard.vue +106 -0
- package/src/components/molecules/FTabs/FTab.vue +63 -0
- package/src/components/molecules/FTabs/FTabs.stories.js +277 -0
- package/src/components/molecules/FTabs/FTabs.test.ts +264 -0
- package/src/components/molecules/FTabs/FTabs.vue +273 -0
- package/src/components/molecules/FToast/FToast.stories.js +150 -0
- package/src/components/molecules/FToast/FToast.test.ts +157 -0
- package/src/components/molecules/FToast/FToast.vue +283 -0
- package/src/components/molecules/index.ts +37 -0
- package/src/components/organisms/FActivityFeed/FActivityFeed.stories.js +217 -0
- package/src/components/organisms/FActivityFeed/FActivityFeed.test.ts +134 -0
- package/src/components/organisms/FActivityFeed/FActivityFeed.vue +589 -0
- package/src/components/organisms/FDataTable/FDataTable.stories.js +370 -0
- package/src/components/organisms/FDataTable/FDataTable.test.ts +248 -0
- package/src/components/organisms/FDataTable/FDataTable.vue +808 -0
- package/src/components/organisms/FDrawer/FDrawer.stories.js +296 -0
- package/src/components/organisms/FDrawer/FDrawer.test.ts +142 -0
- package/src/components/organisms/FDrawer/FDrawer.vue +303 -0
- package/src/components/organisms/FFileUpload/FFileUpload.stories.js +162 -0
- package/src/components/organisms/FFileUpload/FFileUpload.test.ts +103 -0
- package/src/components/organisms/FFileUpload/FFileUpload.vue +616 -0
- package/src/components/organisms/FFilterSidebar/FFilterSidebar.stories.js +161 -0
- package/src/components/organisms/FFilterSidebar/FFilterSidebar.test.ts +92 -0
- package/src/components/organisms/FFilterSidebar/FFilterSidebar.vue +458 -0
- package/src/components/organisms/FForm/FForm.stories.js +270 -0
- package/src/components/organisms/FForm/FForm.test.ts +63 -0
- package/src/components/organisms/FForm/FForm.vue +19 -0
- package/src/components/organisms/FModal/FModal.stories.js +227 -0
- package/src/components/organisms/FModal/FModal.test.ts +181 -0
- package/src/components/organisms/FModal/FModal.vue +319 -0
- package/src/components/organisms/FNavigationSidebar/FNavigationSidebar.stories.js +176 -0
- package/src/components/organisms/FNavigationSidebar/FNavigationSidebar.test.ts +95 -0
- package/src/components/organisms/FNavigationSidebar/FNavigationSidebar.vue +577 -0
- package/src/components/organisms/FOnboardingStepper/FOnboardingStepper.stories.js +197 -0
- package/src/components/organisms/FOnboardingStepper/FOnboardingStepper.test.ts +114 -0
- package/src/components/organisms/FOnboardingStepper/FOnboardingStepper.vue +212 -0
- package/src/components/organisms/FOnboardingStepper/FStepperProgress.stories.js +122 -0
- package/src/components/organisms/FOnboardingStepper/FStepperProgress.test.ts +130 -0
- package/src/components/organisms/FOnboardingStepper/FStepperProgress.vue +146 -0
- package/src/components/organisms/FPageHeader/FPageHeader.stories.js +142 -0
- package/src/components/organisms/FPageHeader/FPageHeader.test.ts +83 -0
- package/src/components/organisms/FPageHeader/FPageHeader.vue +241 -0
- package/src/components/organisms/FProfileSection/FProfileSection.stories.js +190 -0
- package/src/components/organisms/FProfileSection/FProfileSection.test.ts +85 -0
- package/src/components/organisms/FProfileSection/FProfileSection.vue +562 -0
- package/src/components/organisms/FToastProvider/FToastProvider.stories.js +290 -0
- package/src/components/organisms/FToastProvider/FToastProvider.test.ts +215 -0
- package/src/components/organisms/FToastProvider/FToastProvider.vue +214 -0
- package/src/components/organisms/FUserMenu/FUserMenu.stories.js +170 -0
- package/src/components/organisms/FUserMenu/FUserMenu.test.ts +102 -0
- package/src/components/organisms/FUserMenu/FUserMenu.vue +407 -0
- package/src/components/organisms/index.ts +29 -0
- package/src/components/utils/FThemeProvider.stories.js +236 -0
- package/src/components/utils/FThemeProvider.test.ts +244 -0
- package/src/components/utils/FThemeProvider.vue +191 -0
- package/src/components/utils/index.ts +3 -0
- package/src/components.d.ts +602 -0
- package/src/composables/README.md +233 -0
- package/src/composables/index.ts +25 -0
- package/src/composables/useDataTableState.test.ts +378 -0
- package/src/composables/useDataTableState.ts +361 -0
- package/src/composables/useFormValidation.test.ts +198 -0
- package/src/composables/useFormValidation.ts +178 -0
- package/src/composables/useSidebarState.test.ts +307 -0
- package/src/composables/useSidebarState.ts +201 -0
- package/src/env.d.ts +14 -0
- package/src/index.ts +167 -0
- package/src/styles/tailwind.css +173 -0
- package/src/types.ts +740 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import FToastProvider from './FToastProvider.vue';
|
|
2
|
+
import FButton from '../../atoms/FButton/FButton.vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Organisms/FToastProvider',
|
|
6
|
+
component: FToastProvider,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
argTypes: {
|
|
9
|
+
position: {
|
|
10
|
+
control: { type: 'select' },
|
|
11
|
+
options: [
|
|
12
|
+
'top-left',
|
|
13
|
+
'top-center',
|
|
14
|
+
'top-right',
|
|
15
|
+
'bottom-left',
|
|
16
|
+
'bottom-center',
|
|
17
|
+
'bottom-right'
|
|
18
|
+
],
|
|
19
|
+
description: 'Position par défaut des toasts'
|
|
20
|
+
},
|
|
21
|
+
maxToasts: {
|
|
22
|
+
control: 'number',
|
|
23
|
+
description: 'Nombre maximum de toasts affichés simultanément'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const Default = () => ({
|
|
29
|
+
components: { FToastProvider, FButton },
|
|
30
|
+
template: `
|
|
31
|
+
<FToastProvider ref="provider">
|
|
32
|
+
<div class="p-8 space-y-4">
|
|
33
|
+
<h2 class="text-2xl font-bold mb-4">Système de Notifications Toast</h2>
|
|
34
|
+
<p class="mb-4">Cliquez sur les boutons ci-dessous pour afficher différents types de notifications.</p>
|
|
35
|
+
|
|
36
|
+
<div class="flex flex-wrap gap-3">
|
|
37
|
+
<FButton variant="success" @click="showSuccess">
|
|
38
|
+
Toast Succès
|
|
39
|
+
</FButton>
|
|
40
|
+
<FButton variant="danger" @click="showError">
|
|
41
|
+
Toast Erreur
|
|
42
|
+
</FButton>
|
|
43
|
+
<FButton variant="primary" @click="showInfo">
|
|
44
|
+
Toast Info
|
|
45
|
+
</FButton>
|
|
46
|
+
<FButton variant="warning" @click="showWarning">
|
|
47
|
+
Toast Avertissement
|
|
48
|
+
</FButton>
|
|
49
|
+
<FButton variant="outline" @click="showCustom">
|
|
50
|
+
Toast Personnalisé
|
|
51
|
+
</FButton>
|
|
52
|
+
<FButton variant="ghost" @click="clearAll">
|
|
53
|
+
Tout Effacer
|
|
54
|
+
</FButton>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</FToastProvider>
|
|
58
|
+
`,
|
|
59
|
+
methods: {
|
|
60
|
+
showSuccess() {
|
|
61
|
+
this.$refs.provider.success('Votre action a été effectuée avec succès.');
|
|
62
|
+
},
|
|
63
|
+
showError() {
|
|
64
|
+
this.$refs.provider.error(
|
|
65
|
+
"Une erreur s'est produite. Veuillez réessayer."
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
showInfo() {
|
|
69
|
+
this.$refs.provider.info(
|
|
70
|
+
'Voici une information importante à prendre en compte.'
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
showWarning() {
|
|
74
|
+
this.$refs.provider.warning(
|
|
75
|
+
'Veuillez vérifier vos informations avant de continuer.'
|
|
76
|
+
);
|
|
77
|
+
},
|
|
78
|
+
showCustom() {
|
|
79
|
+
this.$refs.provider.show({
|
|
80
|
+
variant: 'info',
|
|
81
|
+
title: 'Notification Personnalisée',
|
|
82
|
+
message: 'Ce toast a une durée personnalisée de 10 secondes.',
|
|
83
|
+
duration: 10000,
|
|
84
|
+
closable: true
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
clearAll() {
|
|
88
|
+
this.$refs.provider.clear();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export const DifferentPositions = () => ({
|
|
94
|
+
components: { FToastProvider, FButton },
|
|
95
|
+
template: `
|
|
96
|
+
<FToastProvider ref="provider">
|
|
97
|
+
<div class="p-8 space-y-4">
|
|
98
|
+
<h2 class="text-2xl font-bold mb-4">Positions des Toasts</h2>
|
|
99
|
+
<p class="mb-4">Cliquez sur les boutons pour afficher des toasts à différentes positions.</p>
|
|
100
|
+
|
|
101
|
+
<div class="grid grid-cols-3 gap-3">
|
|
102
|
+
<FButton variant="primary" @click="showTopLeft">
|
|
103
|
+
Haut Gauche
|
|
104
|
+
</FButton>
|
|
105
|
+
<FButton variant="primary" @click="showTopCenter">
|
|
106
|
+
Haut Centre
|
|
107
|
+
</FButton>
|
|
108
|
+
<FButton variant="primary" @click="showTopRight">
|
|
109
|
+
Haut Droite
|
|
110
|
+
</FButton>
|
|
111
|
+
<FButton variant="primary" @click="showBottomLeft">
|
|
112
|
+
Bas Gauche
|
|
113
|
+
</FButton>
|
|
114
|
+
<FButton variant="primary" @click="showBottomCenter">
|
|
115
|
+
Bas Centre
|
|
116
|
+
</FButton>
|
|
117
|
+
<FButton variant="primary" @click="showBottomRight">
|
|
118
|
+
Bas Droite
|
|
119
|
+
</FButton>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</FToastProvider>
|
|
123
|
+
`,
|
|
124
|
+
methods: {
|
|
125
|
+
showTopLeft() {
|
|
126
|
+
this.$refs.provider.show({
|
|
127
|
+
variant: 'info',
|
|
128
|
+
message: 'Toast en haut à gauche',
|
|
129
|
+
position: 'top-left'
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
showTopCenter() {
|
|
133
|
+
this.$refs.provider.show({
|
|
134
|
+
variant: 'info',
|
|
135
|
+
message: 'Toast en haut au centre',
|
|
136
|
+
position: 'top-center'
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
showTopRight() {
|
|
140
|
+
this.$refs.provider.show({
|
|
141
|
+
variant: 'info',
|
|
142
|
+
message: 'Toast en haut à droite',
|
|
143
|
+
position: 'top-right'
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
showBottomLeft() {
|
|
147
|
+
this.$refs.provider.show({
|
|
148
|
+
variant: 'success',
|
|
149
|
+
message: 'Toast en bas à gauche',
|
|
150
|
+
position: 'bottom-left'
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
showBottomCenter() {
|
|
154
|
+
this.$refs.provider.show({
|
|
155
|
+
variant: 'success',
|
|
156
|
+
message: 'Toast en bas au centre',
|
|
157
|
+
position: 'bottom-center'
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
showBottomRight() {
|
|
161
|
+
this.$refs.provider.show({
|
|
162
|
+
variant: 'success',
|
|
163
|
+
message: 'Toast en bas à droite',
|
|
164
|
+
position: 'bottom-right'
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
export const GlobalAPI = () => ({
|
|
171
|
+
components: { FToastProvider, FButton },
|
|
172
|
+
template: `
|
|
173
|
+
<FToastProvider>
|
|
174
|
+
<div class="p-8 space-y-4">
|
|
175
|
+
<h2 class="text-2xl font-bold mb-4">API Globale via $root.$toast</h2>
|
|
176
|
+
<p class="mb-4">Une fois le FToastProvider monté, vous pouvez accéder aux toasts via <code>this.$root.$toast</code>.</p>
|
|
177
|
+
|
|
178
|
+
<div class="flex flex-wrap gap-3">
|
|
179
|
+
<FButton variant="success" @click="$root.$toast.success('Opération réussie!')">
|
|
180
|
+
$root.$toast.success()
|
|
181
|
+
</FButton>
|
|
182
|
+
<FButton variant="danger" @click="$root.$toast.error('Erreur détectée!')">
|
|
183
|
+
$root.$toast.error()
|
|
184
|
+
</FButton>
|
|
185
|
+
<FButton variant="primary" @click="$root.$toast.info('Nouvelle information')">
|
|
186
|
+
$root.$toast.info()
|
|
187
|
+
</FButton>
|
|
188
|
+
<FButton variant="warning" @click="$root.$toast.warning('Attention requise')">
|
|
189
|
+
$root.$toast.warning()
|
|
190
|
+
</FButton>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<div class="mt-6 p-4 bg-neutral-100 rounded">
|
|
194
|
+
<h3 class="font-bold mb-2">Exemple d'utilisation dans vos composants:</h3>
|
|
195
|
+
<pre class="text-sm"><code>// Dans n'importe quel composant
|
|
196
|
+
this.$root.$toast.success('Message de succès');
|
|
197
|
+
this.$root.$toast.error('Message d\'erreur');
|
|
198
|
+
this.$root.$toast.info('Message d\'information');
|
|
199
|
+
this.$root.$toast.warning('Message d\'avertissement');
|
|
200
|
+
|
|
201
|
+
// Avec options personnalisées
|
|
202
|
+
this.$root.$toast.show({
|
|
203
|
+
variant: 'success',
|
|
204
|
+
title: 'Titre personnalisé',
|
|
205
|
+
message: 'Message personnalisé',
|
|
206
|
+
duration: 3000,
|
|
207
|
+
position: 'bottom-right'
|
|
208
|
+
});</code></pre>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</FToastProvider>
|
|
212
|
+
`
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
export const MaxToastsLimit = () => ({
|
|
216
|
+
components: { FToastProvider, FButton },
|
|
217
|
+
data() {
|
|
218
|
+
return {
|
|
219
|
+
counter: 0
|
|
220
|
+
};
|
|
221
|
+
},
|
|
222
|
+
template: `
|
|
223
|
+
<FToastProvider ref="provider" :max-toasts="3">
|
|
224
|
+
<div class="p-8 space-y-4">
|
|
225
|
+
<h2 class="text-2xl font-bold mb-4">Limite de Toasts (max: 3)</h2>
|
|
226
|
+
<p class="mb-4">Le provider est configuré pour afficher un maximum de 3 toasts. Les anciens seront automatiquement supprimés.</p>
|
|
227
|
+
|
|
228
|
+
<FButton variant="primary" @click="addToast">
|
|
229
|
+
Ajouter un Toast ({{ counter }})
|
|
230
|
+
</FButton>
|
|
231
|
+
</div>
|
|
232
|
+
</FToastProvider>
|
|
233
|
+
`,
|
|
234
|
+
methods: {
|
|
235
|
+
addToast() {
|
|
236
|
+
this.counter++;
|
|
237
|
+
this.$refs.provider.show({
|
|
238
|
+
variant: 'info',
|
|
239
|
+
title: `Toast #${this.counter}`,
|
|
240
|
+
message: `Ceci est le toast numéro ${this.counter}`,
|
|
241
|
+
duration: 0
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
export const PersistentToasts = () => ({
|
|
248
|
+
components: { FToastProvider, FButton },
|
|
249
|
+
template: `
|
|
250
|
+
<FToastProvider ref="provider">
|
|
251
|
+
<div class="p-8 space-y-4">
|
|
252
|
+
<h2 class="text-2xl font-bold mb-4">Toasts Persistants</h2>
|
|
253
|
+
<p class="mb-4">Ces toasts ne se ferment pas automatiquement (duration: 0).</p>
|
|
254
|
+
|
|
255
|
+
<div class="flex flex-wrap gap-3">
|
|
256
|
+
<FButton variant="primary" @click="showPersistent">
|
|
257
|
+
Toast Persistant
|
|
258
|
+
</FButton>
|
|
259
|
+
<FButton variant="outline" @click="showNonClosable">
|
|
260
|
+
Toast Non Fermable
|
|
261
|
+
</FButton>
|
|
262
|
+
<FButton variant="ghost" @click="$refs.provider.clear()">
|
|
263
|
+
Tout Effacer
|
|
264
|
+
</FButton>
|
|
265
|
+
</div>
|
|
266
|
+
</div>
|
|
267
|
+
</FToastProvider>
|
|
268
|
+
`,
|
|
269
|
+
methods: {
|
|
270
|
+
showPersistent() {
|
|
271
|
+
this.$refs.provider.show({
|
|
272
|
+
variant: 'info',
|
|
273
|
+
title: 'Toast Persistant',
|
|
274
|
+
message:
|
|
275
|
+
'Ce toast ne se fermera pas automatiquement, mais vous pouvez le fermer manuellement.',
|
|
276
|
+
duration: 0
|
|
277
|
+
});
|
|
278
|
+
},
|
|
279
|
+
showNonClosable() {
|
|
280
|
+
this.$refs.provider.show({
|
|
281
|
+
variant: 'warning',
|
|
282
|
+
title: 'Toast Non Fermable',
|
|
283
|
+
message:
|
|
284
|
+
'Ce toast ne peut être fermé ni automatiquement ni manuellement.',
|
|
285
|
+
duration: 0,
|
|
286
|
+
closable: false
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { mount, createLocalVue } from '@vue/test-utils';
|
|
3
|
+
import FToastProvider from './FToastProvider.vue';
|
|
4
|
+
import FToast from '../../molecules/FToast/FToast.vue';
|
|
5
|
+
|
|
6
|
+
const localVue = createLocalVue();
|
|
7
|
+
localVue.component('FToast', FToast);
|
|
8
|
+
|
|
9
|
+
describe('FToastProvider', () => {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
vi.useFakeTimers();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('renders correctly with default slot', () => {
|
|
15
|
+
const wrapper = mount(FToastProvider, {
|
|
16
|
+
localVue,
|
|
17
|
+
slots: { default: '<div>App Content</div>' }
|
|
18
|
+
});
|
|
19
|
+
expect(wrapper.text()).toContain('App Content');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('shows toast when show method is called', async () => {
|
|
23
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
24
|
+
const vm = wrapper.vm;
|
|
25
|
+
|
|
26
|
+
vm.show({
|
|
27
|
+
variant: 'success',
|
|
28
|
+
title: 'Test',
|
|
29
|
+
message: 'Test message'
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
await wrapper.vm.$nextTick();
|
|
33
|
+
expect(wrapper.findAllComponents({ name: 'FToast' }).length).toBe(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('shows success toast using success method', async () => {
|
|
37
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
38
|
+
const vm = wrapper.vm;
|
|
39
|
+
|
|
40
|
+
vm.success('Success message');
|
|
41
|
+
|
|
42
|
+
await wrapper.vm.$nextTick();
|
|
43
|
+
const toasts = wrapper.findAllComponents({ name: 'FToast' });
|
|
44
|
+
expect(toasts.length).toBe(1);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('shows error toast using error method', async () => {
|
|
48
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
49
|
+
const vm = wrapper.vm;
|
|
50
|
+
|
|
51
|
+
vm.error('Error message');
|
|
52
|
+
|
|
53
|
+
await wrapper.vm.$nextTick();
|
|
54
|
+
const toasts = wrapper.findAllComponents({ name: 'FToast' });
|
|
55
|
+
expect(toasts.length).toBe(1);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('shows info toast using info method', async () => {
|
|
59
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
60
|
+
const vm = wrapper.vm;
|
|
61
|
+
|
|
62
|
+
vm.info('Info message');
|
|
63
|
+
|
|
64
|
+
await wrapper.vm.$nextTick();
|
|
65
|
+
const toasts = wrapper.findAllComponents({ name: 'FToast' });
|
|
66
|
+
expect(toasts.length).toBe(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('shows warning toast using warning method', async () => {
|
|
70
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
71
|
+
const vm = wrapper.vm;
|
|
72
|
+
|
|
73
|
+
vm.warning('Warning message');
|
|
74
|
+
|
|
75
|
+
await wrapper.vm.$nextTick();
|
|
76
|
+
const toasts = wrapper.findAllComponents({ name: 'FToast' });
|
|
77
|
+
expect(toasts.length).toBe(1);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('removes toast when removeToast is called', async () => {
|
|
81
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
82
|
+
const vm = wrapper.vm;
|
|
83
|
+
|
|
84
|
+
const id = vm.show({
|
|
85
|
+
variant: 'info',
|
|
86
|
+
message: 'Test'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
await wrapper.vm.$nextTick();
|
|
90
|
+
expect(wrapper.findAllComponents({ name: 'FToast' }).length).toBe(1);
|
|
91
|
+
|
|
92
|
+
vm.removeToast(id);
|
|
93
|
+
await wrapper.vm.$nextTick();
|
|
94
|
+
expect(wrapper.findAllComponents({ name: 'FToast' }).length).toBe(0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('clears all toasts when clear is called', async () => {
|
|
98
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
99
|
+
const vm = wrapper.vm;
|
|
100
|
+
|
|
101
|
+
vm.show({ message: 'Toast 1' });
|
|
102
|
+
vm.show({ message: 'Toast 2' });
|
|
103
|
+
vm.show({ message: 'Toast 3' });
|
|
104
|
+
|
|
105
|
+
await wrapper.vm.$nextTick();
|
|
106
|
+
expect(wrapper.findAllComponents({ name: 'FToast' }).length).toBe(3);
|
|
107
|
+
|
|
108
|
+
vm.clear();
|
|
109
|
+
await wrapper.vm.$nextTick();
|
|
110
|
+
expect(wrapper.findAllComponents({ name: 'FToast' }).length).toBe(0);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('respects maxToasts limit', async () => {
|
|
114
|
+
const wrapper = mount(FToastProvider, {
|
|
115
|
+
localVue,
|
|
116
|
+
propsData: { maxToasts: 3 }
|
|
117
|
+
});
|
|
118
|
+
const vm = wrapper.vm;
|
|
119
|
+
|
|
120
|
+
vm.show({ message: 'Toast 1' });
|
|
121
|
+
vm.show({ message: 'Toast 2' });
|
|
122
|
+
vm.show({ message: 'Toast 3' });
|
|
123
|
+
vm.show({ message: 'Toast 4' });
|
|
124
|
+
|
|
125
|
+
await wrapper.vm.$nextTick();
|
|
126
|
+
expect(wrapper.findAllComponents({ name: 'FToast' }).length).toBe(3);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('uses default position when not specified', async () => {
|
|
130
|
+
const wrapper = mount(FToastProvider, {
|
|
131
|
+
localVue,
|
|
132
|
+
propsData: { position: 'bottom-left' }
|
|
133
|
+
});
|
|
134
|
+
const vm = wrapper.vm;
|
|
135
|
+
|
|
136
|
+
vm.show({ message: 'Test' });
|
|
137
|
+
|
|
138
|
+
await wrapper.vm.$nextTick();
|
|
139
|
+
expect(vm.toasts[0].position).toBe('bottom-left');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('uses custom position when specified', async () => {
|
|
143
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
144
|
+
const vm = wrapper.vm;
|
|
145
|
+
|
|
146
|
+
vm.show({
|
|
147
|
+
message: 'Test',
|
|
148
|
+
position: 'top-center'
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
await wrapper.vm.$nextTick();
|
|
152
|
+
expect(vm.toasts[0].position).toBe('top-center');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('emits show event when toast is shown', async () => {
|
|
156
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
157
|
+
const vm = wrapper.vm;
|
|
158
|
+
|
|
159
|
+
vm.show({ message: 'Test' });
|
|
160
|
+
|
|
161
|
+
await wrapper.vm.$nextTick();
|
|
162
|
+
expect(wrapper.emitted('show')).toBeTruthy();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('emits remove event when toast is removed', async () => {
|
|
166
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
167
|
+
const vm = wrapper.vm;
|
|
168
|
+
|
|
169
|
+
const id = vm.show({ message: 'Test' });
|
|
170
|
+
await wrapper.vm.$nextTick();
|
|
171
|
+
|
|
172
|
+
vm.removeToast(id);
|
|
173
|
+
await wrapper.vm.$nextTick();
|
|
174
|
+
expect(wrapper.emitted('remove')).toBeTruthy();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('emits clear event when all toasts are cleared', async () => {
|
|
178
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
179
|
+
const vm = wrapper.vm;
|
|
180
|
+
|
|
181
|
+
vm.show({ message: 'Test' });
|
|
182
|
+
await wrapper.vm.$nextTick();
|
|
183
|
+
|
|
184
|
+
vm.clear();
|
|
185
|
+
await wrapper.vm.$nextTick();
|
|
186
|
+
expect(wrapper.emitted('clear')).toBeTruthy();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('groups toasts by position', async () => {
|
|
190
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
191
|
+
const vm = wrapper.vm;
|
|
192
|
+
|
|
193
|
+
vm.show({ message: 'Top Left', position: 'top-left' });
|
|
194
|
+
vm.show({ message: 'Top Right', position: 'top-right' });
|
|
195
|
+
vm.show({ message: 'Bottom Center', position: 'bottom-center' });
|
|
196
|
+
|
|
197
|
+
await wrapper.vm.$nextTick();
|
|
198
|
+
|
|
199
|
+
expect(vm.toastsByPosition['top-left'].length).toBe(1);
|
|
200
|
+
expect(vm.toastsByPosition['top-right'].length).toBe(1);
|
|
201
|
+
expect(vm.toastsByPosition['bottom-center'].length).toBe(1);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('exposes global API on root instance', () => {
|
|
205
|
+
const wrapper = mount(FToastProvider, { localVue });
|
|
206
|
+
|
|
207
|
+
expect(wrapper.vm.$root.$toast).toBeDefined();
|
|
208
|
+
expect(typeof wrapper.vm.$root.$toast.show).toBe('function');
|
|
209
|
+
expect(typeof wrapper.vm.$root.$toast.success).toBe('function');
|
|
210
|
+
expect(typeof wrapper.vm.$root.$toast.error).toBe('function');
|
|
211
|
+
expect(typeof wrapper.vm.$root.$toast.info).toBe('function');
|
|
212
|
+
expect(typeof wrapper.vm.$root.$toast.warning).toBe('function');
|
|
213
|
+
expect(typeof wrapper.vm.$root.$toast.clear).toBe('function');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<slot />
|
|
4
|
+
<div v-for="pos in positions" :key="pos" :class="containerClasses(pos)">
|
|
5
|
+
<f-toast
|
|
6
|
+
v-for="toast in toastsByPosition[pos]"
|
|
7
|
+
:key="toast.id"
|
|
8
|
+
:variant="toast.variant"
|
|
9
|
+
:title="toast.title"
|
|
10
|
+
:message="toast.message"
|
|
11
|
+
:closable="toast.closable"
|
|
12
|
+
:duration="toast.duration"
|
|
13
|
+
:position="pos"
|
|
14
|
+
@close="removeToast(toast.id)"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
import FToast from '../../molecules/FToast/FToast.vue';
|
|
22
|
+
|
|
23
|
+
let toastId = 0;
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
name: 'FToastProvider',
|
|
27
|
+
components: {
|
|
28
|
+
FToast
|
|
29
|
+
},
|
|
30
|
+
props: {
|
|
31
|
+
/**
|
|
32
|
+
* Position par défaut des toasts
|
|
33
|
+
*/
|
|
34
|
+
position: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: 'top-right',
|
|
37
|
+
validator: (value) =>
|
|
38
|
+
[
|
|
39
|
+
'top-left',
|
|
40
|
+
'top-center',
|
|
41
|
+
'top-right',
|
|
42
|
+
'bottom-left',
|
|
43
|
+
'bottom-center',
|
|
44
|
+
'bottom-right'
|
|
45
|
+
].includes(value)
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Nombre maximum de toasts affichés simultanément
|
|
49
|
+
*/
|
|
50
|
+
maxToasts: {
|
|
51
|
+
type: Number,
|
|
52
|
+
default: 5
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
data() {
|
|
56
|
+
return {
|
|
57
|
+
toasts: [],
|
|
58
|
+
positions: [
|
|
59
|
+
'top-left',
|
|
60
|
+
'top-center',
|
|
61
|
+
'top-right',
|
|
62
|
+
'bottom-left',
|
|
63
|
+
'bottom-center',
|
|
64
|
+
'bottom-right'
|
|
65
|
+
]
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
computed: {
|
|
69
|
+
toastsByPosition() {
|
|
70
|
+
return this.positions.reduce((acc, position) => {
|
|
71
|
+
acc[position] = this.toasts.filter(
|
|
72
|
+
(toast) => toast.position === position
|
|
73
|
+
);
|
|
74
|
+
return acc;
|
|
75
|
+
}, {});
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
created() {
|
|
79
|
+
// Expose API globally via $root for Vue 2 compatibility
|
|
80
|
+
// Note: In Vue 3, this should be replaced with provide/inject or a plugin
|
|
81
|
+
// This approach is acceptable for Vue 2 applications for convenience
|
|
82
|
+
if (this.$root && !this.$root.$toast) {
|
|
83
|
+
this.$root.$toast = {
|
|
84
|
+
show: this.show,
|
|
85
|
+
success: this.success,
|
|
86
|
+
error: this.error,
|
|
87
|
+
info: this.info,
|
|
88
|
+
warning: this.warning,
|
|
89
|
+
clear: this.clear
|
|
90
|
+
};
|
|
91
|
+
} else if (this.$root && this.$root.$toast) {
|
|
92
|
+
// Warn if another FToastProvider is already mounted
|
|
93
|
+
console.warn(
|
|
94
|
+
'FToastProvider: Multiple instances detected. Only one FToastProvider should be mounted at a time. The global API will use the first mounted instance.'
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
beforeDestroy() {
|
|
99
|
+
// Clean up global API
|
|
100
|
+
if (this.$root && this.$root.$toast) {
|
|
101
|
+
delete this.$root.$toast;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
methods: {
|
|
105
|
+
containerClasses(position) {
|
|
106
|
+
const baseClasses =
|
|
107
|
+
'fixed z-50 flex flex-col gap-3 p-4 pointer-events-none';
|
|
108
|
+
const positionClasses = {
|
|
109
|
+
'top-left': 'top-0 left-0',
|
|
110
|
+
'top-center': 'top-0 left-1/2 -translate-x-1/2',
|
|
111
|
+
'top-right': 'top-0 right-0',
|
|
112
|
+
'bottom-left': 'bottom-0 left-0',
|
|
113
|
+
'bottom-center': 'bottom-0 left-1/2 -translate-x-1/2',
|
|
114
|
+
'bottom-right': 'bottom-0 right-0'
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return `${baseClasses} ${positionClasses[position]}`;
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* Affiche un toast avec des options personnalisées
|
|
121
|
+
*/
|
|
122
|
+
show(options) {
|
|
123
|
+
const toast = {
|
|
124
|
+
id: ++toastId,
|
|
125
|
+
variant: options.variant || 'info',
|
|
126
|
+
title: options.title || '',
|
|
127
|
+
message: options.message || '',
|
|
128
|
+
closable: options.closable !== undefined ? options.closable : true,
|
|
129
|
+
duration: options.duration !== undefined ? options.duration : 5000,
|
|
130
|
+
position: options.position || this.position
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Limit the number of toasts
|
|
134
|
+
if (this.toasts.length >= this.maxToasts) {
|
|
135
|
+
this.toasts.shift();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.toasts.push(toast);
|
|
139
|
+
this.$emit('show', toast);
|
|
140
|
+
|
|
141
|
+
return toast.id;
|
|
142
|
+
},
|
|
143
|
+
/**
|
|
144
|
+
* Affiche un toast de succès
|
|
145
|
+
*/
|
|
146
|
+
success(message, title = 'Succès', options = {}) {
|
|
147
|
+
return this.show({
|
|
148
|
+
variant: 'success',
|
|
149
|
+
title,
|
|
150
|
+
message,
|
|
151
|
+
...options
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Affiche un toast d'erreur
|
|
156
|
+
*/
|
|
157
|
+
error(message, title = 'Erreur', options = {}) {
|
|
158
|
+
return this.show({
|
|
159
|
+
variant: 'error',
|
|
160
|
+
title,
|
|
161
|
+
message,
|
|
162
|
+
...options
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
/**
|
|
166
|
+
* Affiche un toast d'information
|
|
167
|
+
*/
|
|
168
|
+
info(message, title = 'Information', options = {}) {
|
|
169
|
+
return this.show({
|
|
170
|
+
variant: 'info',
|
|
171
|
+
title,
|
|
172
|
+
message,
|
|
173
|
+
...options
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
/**
|
|
177
|
+
* Affiche un toast d'avertissement
|
|
178
|
+
*/
|
|
179
|
+
warning(message, title = 'Avertissement', options = {}) {
|
|
180
|
+
return this.show({
|
|
181
|
+
variant: 'warning',
|
|
182
|
+
title,
|
|
183
|
+
message,
|
|
184
|
+
...options
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
/**
|
|
188
|
+
* Supprime un toast spécifique
|
|
189
|
+
*/
|
|
190
|
+
removeToast(id) {
|
|
191
|
+
const index = this.toasts.findIndex((t) => t.id === id);
|
|
192
|
+
if (index !== -1) {
|
|
193
|
+
const toast = this.toasts[index];
|
|
194
|
+
this.toasts.splice(index, 1);
|
|
195
|
+
this.$emit('remove', toast);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
/**
|
|
199
|
+
* Supprime tous les toasts
|
|
200
|
+
*/
|
|
201
|
+
clear() {
|
|
202
|
+
this.toasts = [];
|
|
203
|
+
this.$emit('clear');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
</script>
|
|
208
|
+
|
|
209
|
+
<style scoped>
|
|
210
|
+
/* Ensure toasts are clickable */
|
|
211
|
+
.fixed > * {
|
|
212
|
+
pointer-events: auto;
|
|
213
|
+
}
|
|
214
|
+
</style>
|