@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,156 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="wrapperClasses">
|
|
3
|
+
<label v-if="label" :for="inputId" :class="labelClasses">
|
|
4
|
+
{{ label }}
|
|
5
|
+
</label>
|
|
6
|
+
<textarea
|
|
7
|
+
:id="inputId"
|
|
8
|
+
:class="textareaClasses"
|
|
9
|
+
:value="value"
|
|
10
|
+
:placeholder="placeholder"
|
|
11
|
+
:disabled="disabled"
|
|
12
|
+
:readonly="readonly"
|
|
13
|
+
:rows="rows"
|
|
14
|
+
:maxlength="maxlength"
|
|
15
|
+
:aria-invalid="error"
|
|
16
|
+
:aria-describedby="errorMessage ? errorId : undefined"
|
|
17
|
+
@input="handleInput"
|
|
18
|
+
@focus="$emit('focus', $event)"
|
|
19
|
+
@blur="$emit('blur', $event)"
|
|
20
|
+
></textarea>
|
|
21
|
+
<div v-if="hasCounter || errorMessage" :class="footerClasses">
|
|
22
|
+
<span v-if="errorMessage" :id="errorId" :class="errorMessageClasses">
|
|
23
|
+
{{ errorMessage }}
|
|
24
|
+
</span>
|
|
25
|
+
<span
|
|
26
|
+
v-if="hasCounter"
|
|
27
|
+
:class="[counterClasses, { 'ml-auto': !errorMessage }]"
|
|
28
|
+
>
|
|
29
|
+
{{ characterCount }}/{{ maxlength }}
|
|
30
|
+
</span>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
let idCounter = 0;
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
name: 'FTextarea',
|
|
40
|
+
props: {
|
|
41
|
+
value: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: ''
|
|
44
|
+
},
|
|
45
|
+
label: {
|
|
46
|
+
type: String,
|
|
47
|
+
default: ''
|
|
48
|
+
},
|
|
49
|
+
placeholder: {
|
|
50
|
+
type: String,
|
|
51
|
+
default: ''
|
|
52
|
+
},
|
|
53
|
+
rows: {
|
|
54
|
+
type: [Number, String],
|
|
55
|
+
default: 3
|
|
56
|
+
},
|
|
57
|
+
disabled: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
default: false
|
|
60
|
+
},
|
|
61
|
+
readonly: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
default: false
|
|
64
|
+
},
|
|
65
|
+
error: {
|
|
66
|
+
type: Boolean,
|
|
67
|
+
default: false
|
|
68
|
+
},
|
|
69
|
+
errorMessage: {
|
|
70
|
+
type: String,
|
|
71
|
+
default: ''
|
|
72
|
+
},
|
|
73
|
+
maxlength: {
|
|
74
|
+
type: [Number, String],
|
|
75
|
+
default: null
|
|
76
|
+
},
|
|
77
|
+
showCounter: {
|
|
78
|
+
type: Boolean,
|
|
79
|
+
default: false
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
data() {
|
|
83
|
+
const id = ++idCounter;
|
|
84
|
+
return {
|
|
85
|
+
inputId: `ftextarea-${id}`,
|
|
86
|
+
errorId: `ftextarea-error-${id}`
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
computed: {
|
|
90
|
+
wrapperClasses() {
|
|
91
|
+
return 'flex flex-col';
|
|
92
|
+
},
|
|
93
|
+
labelClasses() {
|
|
94
|
+
const baseClasses = 'font-sans text-sm text-neutral-700 mb-1';
|
|
95
|
+
const errorClasses = this.error ? 'text-danger-500' : '';
|
|
96
|
+
|
|
97
|
+
return [baseClasses, errorClasses].filter(Boolean).join(' ');
|
|
98
|
+
},
|
|
99
|
+
textareaClasses() {
|
|
100
|
+
const baseClasses =
|
|
101
|
+
'block w-full font-sans border rounded box-border focus:outline-none focus:ring-2 resize-y';
|
|
102
|
+
|
|
103
|
+
const transitionClasses =
|
|
104
|
+
'transition-all duration-[var(--transition-duration-base)] ease-[var(--transition-easing-standard)]';
|
|
105
|
+
|
|
106
|
+
const stateClasses = this.error
|
|
107
|
+
? 'border-danger-500 focus:border-danger-500 focus:ring-danger-500/20'
|
|
108
|
+
: 'border-neutral-300 focus:border-primary-500 focus:ring-primary-500/20';
|
|
109
|
+
|
|
110
|
+
const disabledClasses = this.disabled
|
|
111
|
+
? 'bg-neutral-100 cursor-not-allowed opacity-70'
|
|
112
|
+
: '';
|
|
113
|
+
|
|
114
|
+
const paddingClasses = 'py-2.5 px-3.5 text-sm';
|
|
115
|
+
|
|
116
|
+
return [
|
|
117
|
+
baseClasses,
|
|
118
|
+
transitionClasses,
|
|
119
|
+
paddingClasses,
|
|
120
|
+
stateClasses,
|
|
121
|
+
disabledClasses
|
|
122
|
+
]
|
|
123
|
+
.filter(Boolean)
|
|
124
|
+
.join(' ');
|
|
125
|
+
},
|
|
126
|
+
footerClasses() {
|
|
127
|
+
return 'flex justify-between items-center mt-1';
|
|
128
|
+
},
|
|
129
|
+
errorMessageClasses() {
|
|
130
|
+
return 'font-sans text-xs text-danger-500';
|
|
131
|
+
},
|
|
132
|
+
counterClasses() {
|
|
133
|
+
const baseClasses = 'font-sans text-xs';
|
|
134
|
+
const stateClasses = this.isOverLimit
|
|
135
|
+
? 'text-danger-500'
|
|
136
|
+
: 'text-neutral-500';
|
|
137
|
+
|
|
138
|
+
return [baseClasses, stateClasses].filter(Boolean).join(' ');
|
|
139
|
+
},
|
|
140
|
+
characterCount() {
|
|
141
|
+
return this.value ? this.value.length : 0;
|
|
142
|
+
},
|
|
143
|
+
isOverLimit() {
|
|
144
|
+
return this.maxlength && this.characterCount > Number(this.maxlength);
|
|
145
|
+
},
|
|
146
|
+
hasCounter() {
|
|
147
|
+
return this.showCounter && this.maxlength;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
methods: {
|
|
151
|
+
handleInput(event) {
|
|
152
|
+
this.$emit('input', event.target.value);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
</script>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import FToggle from './FToggle.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Atoms/FToggle',
|
|
5
|
+
component: FToggle,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
argTypes: {
|
|
8
|
+
value: {
|
|
9
|
+
control: 'boolean',
|
|
10
|
+
description: 'État du toggle (activé/désactivé)'
|
|
11
|
+
},
|
|
12
|
+
label: {
|
|
13
|
+
control: 'text',
|
|
14
|
+
description: 'Libellé du toggle'
|
|
15
|
+
},
|
|
16
|
+
disabled: {
|
|
17
|
+
control: 'boolean',
|
|
18
|
+
description: 'État désactivé'
|
|
19
|
+
},
|
|
20
|
+
color: {
|
|
21
|
+
control: { type: 'select' },
|
|
22
|
+
options: ['blue', 'green', 'red', 'orange', 'purple'],
|
|
23
|
+
description: 'Couleur du toggle'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const Template = (args, { argTypes }) => ({
|
|
29
|
+
components: { FToggle },
|
|
30
|
+
props: Object.keys(argTypes),
|
|
31
|
+
data() {
|
|
32
|
+
return { isEnabled: args.value || false };
|
|
33
|
+
},
|
|
34
|
+
template: '<FToggle v-bind="$props" v-model="isEnabled" />'
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const Default = Template.bind({});
|
|
38
|
+
Default.args = {
|
|
39
|
+
label: 'Activer les notifications'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Enabled = Template.bind({});
|
|
43
|
+
Enabled.args = {
|
|
44
|
+
label: 'Notifications activées',
|
|
45
|
+
value: true
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Disabled = Template.bind({});
|
|
49
|
+
Disabled.args = {
|
|
50
|
+
label: 'Option désactivée',
|
|
51
|
+
disabled: true
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const DisabledOn = Template.bind({});
|
|
55
|
+
DisabledOn.args = {
|
|
56
|
+
label: 'Option activée (désactivée)',
|
|
57
|
+
value: true,
|
|
58
|
+
disabled: true
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const Colors = () => ({
|
|
62
|
+
components: { FToggle },
|
|
63
|
+
data() {
|
|
64
|
+
return {
|
|
65
|
+
blue: true,
|
|
66
|
+
green: true,
|
|
67
|
+
red: true,
|
|
68
|
+
orange: true,
|
|
69
|
+
purple: true
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
template: `
|
|
73
|
+
<div class="flex flex-col gap-4">
|
|
74
|
+
<FToggle v-model="blue" color="blue" label="Bleu (défaut)" />
|
|
75
|
+
<FToggle v-model="green" color="green" label="Vert" />
|
|
76
|
+
<FToggle v-model="red" color="red" label="Rouge" />
|
|
77
|
+
<FToggle v-model="orange" color="orange" label="Orange" />
|
|
78
|
+
<FToggle v-model="purple" color="purple" label="Violet" />
|
|
79
|
+
</div>
|
|
80
|
+
`
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const WithoutLabel = Template.bind({});
|
|
84
|
+
WithoutLabel.args = {};
|
|
85
|
+
|
|
86
|
+
export const Interactive = () => ({
|
|
87
|
+
components: { FToggle },
|
|
88
|
+
data() {
|
|
89
|
+
return {
|
|
90
|
+
darkMode: false,
|
|
91
|
+
notifications: true,
|
|
92
|
+
autoSave: true
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
template: `
|
|
96
|
+
<div class="flex flex-col gap-4 p-4 border rounded-lg">
|
|
97
|
+
<h3 class="font-semibold text-neutral-800">Paramètres</h3>
|
|
98
|
+
<FToggle v-model="darkMode" label="Mode sombre" />
|
|
99
|
+
<FToggle v-model="notifications" label="Notifications push" />
|
|
100
|
+
<FToggle v-model="autoSave" label="Sauvegarde automatique" />
|
|
101
|
+
<div class="mt-4 text-sm text-neutral-500">
|
|
102
|
+
<p>Mode sombre: {{ darkMode ? 'Activé' : 'Désactivé' }}</p>
|
|
103
|
+
<p>Notifications: {{ notifications ? 'Activées' : 'Désactivées' }}</p>
|
|
104
|
+
<p>Auto-save: {{ autoSave ? 'Activé' : 'Désactivé' }}</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
`
|
|
108
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import FToggle from './FToggle.vue';
|
|
4
|
+
|
|
5
|
+
describe('FToggle', () => {
|
|
6
|
+
it('renders correctly with default props', () => {
|
|
7
|
+
const wrapper = mount(FToggle);
|
|
8
|
+
expect(wrapper.find('button[role="switch"]').exists()).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('displays label when provided', () => {
|
|
12
|
+
const wrapper = mount(FToggle, {
|
|
13
|
+
propsData: { label: 'Enable notifications' }
|
|
14
|
+
});
|
|
15
|
+
expect(wrapper.text()).toContain('Enable notifications');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('is off by default', () => {
|
|
19
|
+
const wrapper = mount(FToggle);
|
|
20
|
+
expect(wrapper.find('button').attributes('aria-checked')).toBe('false');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('respects value prop', () => {
|
|
24
|
+
const wrapper = mount(FToggle, {
|
|
25
|
+
propsData: { value: true }
|
|
26
|
+
});
|
|
27
|
+
expect(wrapper.find('button').attributes('aria-checked')).toBe('true');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('emits input event when toggled', async () => {
|
|
31
|
+
const wrapper = mount(FToggle, {
|
|
32
|
+
propsData: { value: false }
|
|
33
|
+
});
|
|
34
|
+
await wrapper.find('button').trigger('click');
|
|
35
|
+
expect(wrapper.emitted('input')).toBeTruthy();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('emits change event when toggled', async () => {
|
|
39
|
+
const wrapper = mount(FToggle, {
|
|
40
|
+
propsData: { value: false }
|
|
41
|
+
});
|
|
42
|
+
await wrapper.find('button').trigger('click');
|
|
43
|
+
expect(wrapper.emitted('change')).toBeTruthy();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('has disabled attribute on button when disabled', () => {
|
|
47
|
+
const wrapper = mount(FToggle, {
|
|
48
|
+
propsData: { disabled: true }
|
|
49
|
+
});
|
|
50
|
+
expect(wrapper.find('button').attributes('disabled')).toBeDefined();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('applies correct color classes', () => {
|
|
54
|
+
const colors = ['blue', 'green', 'red', 'orange', 'purple'] as const;
|
|
55
|
+
colors.forEach((color) => {
|
|
56
|
+
const wrapper = mount(FToggle, {
|
|
57
|
+
propsData: { color, value: true }
|
|
58
|
+
});
|
|
59
|
+
expect(wrapper.find('button').exists()).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('toggles when Space key is pressed', async () => {
|
|
64
|
+
const wrapper = mount(FToggle, {
|
|
65
|
+
propsData: { value: false }
|
|
66
|
+
});
|
|
67
|
+
await wrapper.find('button').trigger('keydown.space');
|
|
68
|
+
expect(wrapper.emitted('input')).toBeTruthy();
|
|
69
|
+
expect(wrapper.emitted('input')?.[0]).toEqual([true]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('toggles when Enter key is pressed', async () => {
|
|
73
|
+
const wrapper = mount(FToggle, {
|
|
74
|
+
propsData: { value: false }
|
|
75
|
+
});
|
|
76
|
+
await wrapper.find('button').trigger('keydown.enter');
|
|
77
|
+
expect(wrapper.emitted('input')).toBeTruthy();
|
|
78
|
+
expect(wrapper.emitted('input')?.[0]).toEqual([true]);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('does not toggle when disabled and Space is pressed', async () => {
|
|
82
|
+
const wrapper = mount(FToggle, {
|
|
83
|
+
propsData: { value: false, disabled: true }
|
|
84
|
+
});
|
|
85
|
+
await wrapper.find('button').trigger('keydown.space');
|
|
86
|
+
expect(wrapper.emitted('input')).toBeFalsy();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not toggle when disabled and Enter is pressed', async () => {
|
|
90
|
+
const wrapper = mount(FToggle, {
|
|
91
|
+
propsData: { value: false, disabled: true }
|
|
92
|
+
});
|
|
93
|
+
await wrapper.find('button').trigger('keydown.enter');
|
|
94
|
+
expect(wrapper.emitted('input')).toBeFalsy();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<label :class="containerClasses">
|
|
3
|
+
<button
|
|
4
|
+
type="button"
|
|
5
|
+
role="switch"
|
|
6
|
+
:class="switchClasses"
|
|
7
|
+
:aria-checked="String(value)"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
@click="handleToggle"
|
|
10
|
+
@keydown.space.prevent="handleToggle"
|
|
11
|
+
@keydown.enter.prevent="handleToggle"
|
|
12
|
+
@focus="$emit('focus', $event)"
|
|
13
|
+
@blur="$emit('blur', $event)"
|
|
14
|
+
>
|
|
15
|
+
<span :class="thumbClasses" aria-hidden="true" />
|
|
16
|
+
</button>
|
|
17
|
+
<span v-if="label" :class="labelClasses">
|
|
18
|
+
{{ label }}
|
|
19
|
+
</span>
|
|
20
|
+
</label>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
export default {
|
|
25
|
+
name: 'FToggle',
|
|
26
|
+
props: {
|
|
27
|
+
value: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false
|
|
30
|
+
},
|
|
31
|
+
label: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: ''
|
|
34
|
+
},
|
|
35
|
+
disabled: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
default: false
|
|
38
|
+
},
|
|
39
|
+
color: {
|
|
40
|
+
type: String,
|
|
41
|
+
default: 'blue',
|
|
42
|
+
validator: (value) =>
|
|
43
|
+
['blue', 'green', 'red', 'orange', 'purple'].includes(value)
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
computed: {
|
|
47
|
+
containerClasses() {
|
|
48
|
+
const baseClasses = 'inline-flex items-center cursor-pointer font-sans';
|
|
49
|
+
const disabledClasses = this.disabled
|
|
50
|
+
? 'cursor-not-allowed opacity-50'
|
|
51
|
+
: '';
|
|
52
|
+
|
|
53
|
+
return [baseClasses, disabledClasses].filter(Boolean).join(' ');
|
|
54
|
+
},
|
|
55
|
+
switchClasses() {
|
|
56
|
+
const baseClasses =
|
|
57
|
+
'relative inline-flex items-center h-6 w-11 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 flex-shrink-0';
|
|
58
|
+
|
|
59
|
+
const transitionClasses =
|
|
60
|
+
'transition-colors duration-[var(--transition-duration-base)] ease-[var(--transition-easing-standard)]';
|
|
61
|
+
|
|
62
|
+
const colorClasses = {
|
|
63
|
+
blue: this.value
|
|
64
|
+
? 'bg-primary-500 focus:ring-primary-500/20'
|
|
65
|
+
: 'bg-neutral-300 focus:ring-primary-500/20',
|
|
66
|
+
green: this.value
|
|
67
|
+
? 'bg-success-500 focus:ring-success-500/20'
|
|
68
|
+
: 'bg-neutral-300 focus:ring-success-500/20',
|
|
69
|
+
red: this.value
|
|
70
|
+
? 'bg-danger-500 focus:ring-danger-500/20'
|
|
71
|
+
: 'bg-neutral-300 focus:ring-danger-500/20',
|
|
72
|
+
orange: this.value
|
|
73
|
+
? 'bg-warning-500 focus:ring-warning-500/20'
|
|
74
|
+
: 'bg-neutral-300 focus:ring-warning-500/20',
|
|
75
|
+
purple: this.value
|
|
76
|
+
? 'bg-primary-500 focus:ring-primary-500/20'
|
|
77
|
+
: 'bg-neutral-300 focus:ring-primary-500/20'
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const disabledClasses = this.disabled
|
|
81
|
+
? 'cursor-not-allowed'
|
|
82
|
+
: 'cursor-pointer';
|
|
83
|
+
|
|
84
|
+
return [
|
|
85
|
+
baseClasses,
|
|
86
|
+
transitionClasses,
|
|
87
|
+
colorClasses[this.color],
|
|
88
|
+
disabledClasses
|
|
89
|
+
]
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
.join(' ');
|
|
92
|
+
},
|
|
93
|
+
thumbClasses() {
|
|
94
|
+
const baseClasses =
|
|
95
|
+
'inline-block w-4 h-4 rounded-full bg-white shadow transform';
|
|
96
|
+
|
|
97
|
+
const transitionClasses =
|
|
98
|
+
'transition-transform duration-[var(--transition-duration-base)] ease-[var(--transition-easing-standard)]';
|
|
99
|
+
|
|
100
|
+
const positionClasses = this.value ? 'translate-x-6' : 'translate-x-1';
|
|
101
|
+
|
|
102
|
+
return [baseClasses, transitionClasses, positionClasses]
|
|
103
|
+
.filter(Boolean)
|
|
104
|
+
.join(' ');
|
|
105
|
+
},
|
|
106
|
+
labelClasses() {
|
|
107
|
+
const baseClasses = 'ml-2 text-sm text-neutral-800 select-none';
|
|
108
|
+
|
|
109
|
+
const disabledClasses = this.disabled ? 'text-neutral-400' : '';
|
|
110
|
+
|
|
111
|
+
return [baseClasses, disabledClasses].filter(Boolean).join(' ');
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
methods: {
|
|
115
|
+
handleToggle() {
|
|
116
|
+
if (!this.disabled) {
|
|
117
|
+
this.$emit('input', !this.value);
|
|
118
|
+
this.$emit('change', !this.value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
</script>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import FTypography from './FTypography.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Atoms/FTypography',
|
|
5
|
+
component: FTypography,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
argTypes: {
|
|
8
|
+
variant: {
|
|
9
|
+
control: { type: 'select' },
|
|
10
|
+
options: [
|
|
11
|
+
'h1',
|
|
12
|
+
'h2',
|
|
13
|
+
'h3',
|
|
14
|
+
'h4',
|
|
15
|
+
'h5',
|
|
16
|
+
'h6',
|
|
17
|
+
'body',
|
|
18
|
+
'caption',
|
|
19
|
+
'overline'
|
|
20
|
+
],
|
|
21
|
+
description: 'Variante typographique'
|
|
22
|
+
},
|
|
23
|
+
tag: {
|
|
24
|
+
control: 'text',
|
|
25
|
+
description: 'Balise HTML personnalisée'
|
|
26
|
+
},
|
|
27
|
+
truncate: {
|
|
28
|
+
control: 'boolean',
|
|
29
|
+
description: 'Tronquer le texte avec ellipse'
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const Template = (args, { argTypes }) => ({
|
|
35
|
+
components: { FTypography },
|
|
36
|
+
props: Object.keys(argTypes),
|
|
37
|
+
data() {
|
|
38
|
+
return { content: args.content || 'Texte exemple' };
|
|
39
|
+
},
|
|
40
|
+
template: '<FTypography v-bind="$props">{{ content }}</FTypography>'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const Default = Template.bind({});
|
|
44
|
+
Default.args = {
|
|
45
|
+
content: 'Texte par défaut (body)'
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Headings = () => ({
|
|
49
|
+
components: { FTypography },
|
|
50
|
+
template: `
|
|
51
|
+
<div class="flex flex-col gap-4">
|
|
52
|
+
<FTypography variant="h1">Titre H1</FTypography>
|
|
53
|
+
<FTypography variant="h2">Titre H2</FTypography>
|
|
54
|
+
<FTypography variant="h3">Titre H3</FTypography>
|
|
55
|
+
<FTypography variant="h4">Titre H4</FTypography>
|
|
56
|
+
<FTypography variant="h5">Titre H5</FTypography>
|
|
57
|
+
<FTypography variant="h6">Titre H6</FTypography>
|
|
58
|
+
</div>
|
|
59
|
+
`
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const Body = Template.bind({});
|
|
63
|
+
Body.args = {
|
|
64
|
+
variant: 'body',
|
|
65
|
+
content:
|
|
66
|
+
'Ceci est un paragraphe de texte standard. Il utilise la variante body qui est adaptée au contenu principal.'
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const Caption = Template.bind({});
|
|
70
|
+
Caption.args = {
|
|
71
|
+
variant: 'caption',
|
|
72
|
+
content: 'Texte de légende ou note secondaire'
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const Overline = Template.bind({});
|
|
76
|
+
Overline.args = {
|
|
77
|
+
variant: 'overline',
|
|
78
|
+
content: 'TEXTE EN SURTITRE'
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const Truncate = () => ({
|
|
82
|
+
components: { FTypography },
|
|
83
|
+
template: `
|
|
84
|
+
<div class="w-64 border border-neutral-200 rounded p-4">
|
|
85
|
+
<FTypography variant="body" truncate>
|
|
86
|
+
Ce texte est très long et sera tronqué avec une ellipse car il dépasse la largeur du conteneur.
|
|
87
|
+
</FTypography>
|
|
88
|
+
</div>
|
|
89
|
+
`
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const CustomTag = () => ({
|
|
93
|
+
components: { FTypography },
|
|
94
|
+
template: `
|
|
95
|
+
<div class="flex flex-col gap-4">
|
|
96
|
+
<FTypography variant="h1" tag="div">H1 rendu comme div</FTypography>
|
|
97
|
+
<FTypography variant="body" tag="span">Body rendu comme span</FTypography>
|
|
98
|
+
</div>
|
|
99
|
+
`
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
export const AllVariants = () => ({
|
|
103
|
+
components: { FTypography },
|
|
104
|
+
template: `
|
|
105
|
+
<div class="flex flex-col gap-6">
|
|
106
|
+
<div>
|
|
107
|
+
<FTypography variant="overline">SECTION</FTypography>
|
|
108
|
+
<FTypography variant="h1">Titre Principal H1</FTypography>
|
|
109
|
+
</div>
|
|
110
|
+
<div>
|
|
111
|
+
<FTypography variant="h2">Sous-titre H2</FTypography>
|
|
112
|
+
<FTypography variant="body">
|
|
113
|
+
Paragraphe de texte standard avec la variante body. Ce style est utilisé pour le contenu principal de la page.
|
|
114
|
+
</FTypography>
|
|
115
|
+
</div>
|
|
116
|
+
<div>
|
|
117
|
+
<FTypography variant="h3">Section H3</FTypography>
|
|
118
|
+
<FTypography variant="body">
|
|
119
|
+
Un autre paragraphe de texte qui explique quelque chose d'important.
|
|
120
|
+
</FTypography>
|
|
121
|
+
<FTypography variant="caption">
|
|
122
|
+
Note: Ceci est un texte de légende ou une note secondaire.
|
|
123
|
+
</FTypography>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
`
|
|
127
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import FTypography from './FTypography.vue';
|
|
4
|
+
|
|
5
|
+
describe('FTypography', () => {
|
|
6
|
+
it('renders correctly with default props', () => {
|
|
7
|
+
const wrapper = mount(FTypography, {
|
|
8
|
+
slots: {
|
|
9
|
+
default: 'Text content'
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
expect(wrapper.text()).toContain('Text content');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('renders as p tag by default (body variant)', () => {
|
|
16
|
+
const wrapper = mount(FTypography, {
|
|
17
|
+
slots: { default: 'Paragraph' }
|
|
18
|
+
});
|
|
19
|
+
expect(wrapper.find('p').exists()).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('renders correct heading tags for h variants', () => {
|
|
23
|
+
const headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const;
|
|
24
|
+
headings.forEach((variant) => {
|
|
25
|
+
const wrapper = mount(FTypography, {
|
|
26
|
+
propsData: { variant },
|
|
27
|
+
slots: { default: 'Heading' }
|
|
28
|
+
});
|
|
29
|
+
expect(wrapper.find(variant).exists()).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('renders span for caption variant', () => {
|
|
34
|
+
const wrapper = mount(FTypography, {
|
|
35
|
+
propsData: { variant: 'caption' },
|
|
36
|
+
slots: { default: 'Caption text' }
|
|
37
|
+
});
|
|
38
|
+
expect(wrapper.find('span').exists()).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('renders span for overline variant', () => {
|
|
42
|
+
const wrapper = mount(FTypography, {
|
|
43
|
+
propsData: { variant: 'overline' },
|
|
44
|
+
slots: { default: 'Overline text' }
|
|
45
|
+
});
|
|
46
|
+
expect(wrapper.find('span').exists()).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('uses custom tag when specified', () => {
|
|
50
|
+
const wrapper = mount(FTypography, {
|
|
51
|
+
propsData: { tag: 'div' },
|
|
52
|
+
slots: { default: 'Content' }
|
|
53
|
+
});
|
|
54
|
+
expect(wrapper.find('div').exists()).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('applies truncate classes when truncate prop is true', () => {
|
|
58
|
+
const wrapper = mount(FTypography, {
|
|
59
|
+
propsData: { truncate: true },
|
|
60
|
+
slots: { default: 'Long text that might be truncated' }
|
|
61
|
+
});
|
|
62
|
+
const classString = wrapper.classes().join(' ');
|
|
63
|
+
expect(classString).toContain('overflow-hidden');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('applies correct variant classes', () => {
|
|
67
|
+
const variants = [
|
|
68
|
+
'h1',
|
|
69
|
+
'h2',
|
|
70
|
+
'h3',
|
|
71
|
+
'h4',
|
|
72
|
+
'h5',
|
|
73
|
+
'h6',
|
|
74
|
+
'body',
|
|
75
|
+
'caption',
|
|
76
|
+
'overline'
|
|
77
|
+
] as const;
|
|
78
|
+
variants.forEach((variant) => {
|
|
79
|
+
const wrapper = mount(FTypography, {
|
|
80
|
+
propsData: { variant },
|
|
81
|
+
slots: { default: 'Text' }
|
|
82
|
+
});
|
|
83
|
+
expect(wrapper.exists()).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('applies base font classes', () => {
|
|
88
|
+
const wrapper = mount(FTypography, {
|
|
89
|
+
slots: { default: 'Text' }
|
|
90
|
+
});
|
|
91
|
+
expect(wrapper.classes()).toContain('font-sans');
|
|
92
|
+
});
|
|
93
|
+
});
|