@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,78 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+ import FStatCard from './FStatCard.vue';
4
+
5
+ describe('FStatCard', () => {
6
+ it('renders correctly with required props', () => {
7
+ const wrapper = mount(FStatCard, {
8
+ propsData: { label: 'Total Users', value: 1234 }
9
+ });
10
+ expect(wrapper.exists()).toBe(true);
11
+ });
12
+
13
+ it('displays label', () => {
14
+ const wrapper = mount(FStatCard, {
15
+ propsData: { label: 'Revenue', value: 5000 }
16
+ });
17
+ expect(wrapper.text()).toContain('Revenue');
18
+ });
19
+
20
+ it('displays value', () => {
21
+ const wrapper = mount(FStatCard, {
22
+ propsData: { label: 'Count', value: 42 }
23
+ });
24
+ expect(wrapper.text()).toContain('42');
25
+ });
26
+
27
+ it('displays string value', () => {
28
+ const wrapper = mount(FStatCard, {
29
+ propsData: { label: 'Status', value: 'Active' }
30
+ });
31
+ expect(wrapper.text()).toContain('Active');
32
+ });
33
+
34
+ it('displays icon', () => {
35
+ const wrapper = mount(FStatCard, {
36
+ propsData: { label: 'Test', value: 100, icon: 'user' }
37
+ });
38
+ expect(wrapper.findComponent({ name: 'FIcon' }).exists()).toBe(true);
39
+ });
40
+
41
+ it('applies correct variant classes', () => {
42
+ const variants = ['primary', 'success', 'danger', 'info'] as const;
43
+ variants.forEach((variant) => {
44
+ const wrapper = mount(FStatCard, {
45
+ propsData: { label: 'Test', value: 100, variant }
46
+ });
47
+ expect(wrapper.exists()).toBe(true);
48
+ });
49
+ });
50
+
51
+ it('applies horizontal layout by default', () => {
52
+ const wrapper = mount(FStatCard, {
53
+ propsData: { label: 'Test', value: 100 }
54
+ });
55
+ expect(wrapper.classes()).toContain('flex');
56
+ });
57
+
58
+ it('applies vertical layout when specified', () => {
59
+ const wrapper = mount(FStatCard, {
60
+ propsData: { label: 'Test', value: 100, layout: 'vertical' }
61
+ });
62
+ expect(wrapper.classes()).toContain('flex-col');
63
+ });
64
+
65
+ it('applies border by default', () => {
66
+ const wrapper = mount(FStatCard, {
67
+ propsData: { label: 'Test', value: 100 }
68
+ });
69
+ expect(wrapper.classes()).toContain('border');
70
+ });
71
+
72
+ it('removes border when bordered is false', () => {
73
+ const wrapper = mount(FStatCard, {
74
+ propsData: { label: 'Test', value: 100, bordered: false }
75
+ });
76
+ expect(wrapper.classes()).not.toContain('border');
77
+ });
78
+ });
@@ -0,0 +1,106 @@
1
+ <template>
2
+ <div :class="cardClasses">
3
+ <div :class="iconContainerClasses">
4
+ <f-icon :name="icon" size="md" :decorative="true" />
5
+ </div>
6
+ <div :class="contentClasses">
7
+ <f-typography variant="caption" :class="labelClasses">
8
+ {{ label }}
9
+ </f-typography>
10
+ <f-typography variant="h4" :class="valueClasses">
11
+ {{ value }}
12
+ </f-typography>
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ import FIcon from '../../atoms/FIcon/FIcon.vue';
19
+ import FTypography from '../../atoms/FTypography/FTypography.vue';
20
+
21
+ const VARIANT_COLORS = {
22
+ primary: {
23
+ iconContainer: 'bg-primary-100 text-primary-600'
24
+ },
25
+ success: {
26
+ iconContainer: 'bg-success-100 text-success-600'
27
+ },
28
+ danger: {
29
+ iconContainer: 'bg-danger-100 text-danger-600'
30
+ },
31
+ info: {
32
+ iconContainer: 'bg-primary-100 text-primary-600'
33
+ }
34
+ };
35
+
36
+ export default {
37
+ name: 'FStatCard',
38
+ components: {
39
+ FIcon,
40
+ FTypography
41
+ },
42
+ props: {
43
+ icon: {
44
+ type: String,
45
+ default: 'info'
46
+ },
47
+ label: {
48
+ type: String,
49
+ required: true
50
+ },
51
+ value: {
52
+ type: [String, Number],
53
+ required: true
54
+ },
55
+ variant: {
56
+ type: String,
57
+ default: 'primary',
58
+ validator: (value) =>
59
+ ['primary', 'success', 'danger', 'info'].includes(value)
60
+ },
61
+ layout: {
62
+ type: String,
63
+ default: 'horizontal',
64
+ validator: (value) => ['horizontal', 'vertical'].includes(value)
65
+ },
66
+ bordered: {
67
+ type: Boolean,
68
+ default: true
69
+ }
70
+ },
71
+ computed: {
72
+ variantColors() {
73
+ return VARIANT_COLORS[this.variant];
74
+ },
75
+ cardClasses() {
76
+ const baseClasses = 'bg-white rounded-lg p-4';
77
+ const borderedClasses = this.bordered ? 'border border-neutral-200' : '';
78
+ const layoutClasses =
79
+ this.layout === 'vertical'
80
+ ? 'flex flex-col items-center text-center'
81
+ : 'flex items-center gap-4';
82
+
83
+ return [baseClasses, borderedClasses, layoutClasses]
84
+ .filter(Boolean)
85
+ .join(' ');
86
+ },
87
+ iconContainerClasses() {
88
+ const baseClasses =
89
+ 'flex items-center justify-center rounded-lg w-12 h-12 flex-shrink-0';
90
+ return `${baseClasses} ${this.variantColors.iconContainer}`;
91
+ },
92
+ contentClasses() {
93
+ const baseClasses = 'min-w-0';
94
+ const verticalClasses = this.layout === 'vertical' ? 'mt-3' : '';
95
+
96
+ return [baseClasses, verticalClasses].filter(Boolean).join(' ');
97
+ },
98
+ labelClasses() {
99
+ return 'text-neutral-500';
100
+ },
101
+ valueClasses() {
102
+ return 'text-neutral-900 font-bold';
103
+ }
104
+ }
105
+ };
106
+ </script>
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <div
3
+ v-show="isActive"
4
+ :id="panelId"
5
+ role="tabpanel"
6
+ :aria-labelledby="tabId"
7
+ class="focus:outline-none"
8
+ tabindex="0"
9
+ >
10
+ <slot />
11
+ </div>
12
+ </template>
13
+
14
+ <script>
15
+ export default {
16
+ name: 'FTab',
17
+ inject: ['tabsProvider'],
18
+ props: {
19
+ /**
20
+ * Label displayed in the tab button
21
+ */
22
+ label: {
23
+ type: String,
24
+ required: true
25
+ },
26
+ /**
27
+ * Unique identifier for the tab
28
+ */
29
+ name: {
30
+ type: String,
31
+ required: true
32
+ },
33
+ /**
34
+ * Whether the tab is disabled
35
+ */
36
+ disabled: {
37
+ type: Boolean,
38
+ default: false
39
+ }
40
+ },
41
+ computed: {
42
+ isActive() {
43
+ return this.tabsProvider.isActive(this.name);
44
+ },
45
+ tabId() {
46
+ return this.tabsProvider.getTabId(this.name);
47
+ },
48
+ panelId() {
49
+ return this.tabsProvider.getPanelId(this.name);
50
+ }
51
+ },
52
+ created() {
53
+ this.tabsProvider.registerTab({
54
+ name: this.name,
55
+ label: this.label,
56
+ disabled: this.disabled
57
+ });
58
+ },
59
+ beforeDestroy() {
60
+ this.tabsProvider.unregisterTab(this.name);
61
+ }
62
+ };
63
+ </script>
@@ -0,0 +1,277 @@
1
+ import FTabs from './FTabs.vue';
2
+ import FTab from './FTab.vue';
3
+
4
+ export default {
5
+ title: 'Molecules/FTabs',
6
+ component: FTabs,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ value: {
10
+ control: 'text',
11
+ description: 'Onglet actif (v-model)'
12
+ },
13
+ variant: {
14
+ control: { type: 'select' },
15
+ options: ['default', 'pills', 'underline'],
16
+ description: 'Variante visuelle des onglets'
17
+ },
18
+ position: {
19
+ control: { type: 'select' },
20
+ options: ['top', 'bottom'],
21
+ description: "Position des boutons d'onglet"
22
+ },
23
+ ariaLabel: {
24
+ control: 'text',
25
+ description: "Label accessible pour la liste d'onglets"
26
+ }
27
+ }
28
+ };
29
+
30
+ export const Default = () => ({
31
+ components: { FTabs, FTab },
32
+ template: `
33
+ <FTabs>
34
+ <FTab name="profile" label="Profil">
35
+ <div class="p-4">
36
+ <h3 class="text-lg font-semibold mb-2">Profil utilisateur</h3>
37
+ <p class="text-neutral-600">Gérez vos informations personnelles et vos préférences de compte.</p>
38
+ </div>
39
+ </FTab>
40
+ <FTab name="settings" label="Paramètres">
41
+ <div class="p-4">
42
+ <h3 class="text-lg font-semibold mb-2">Paramètres</h3>
43
+ <p class="text-neutral-600">Configurez les paramètres de votre application.</p>
44
+ </div>
45
+ </FTab>
46
+ <FTab name="notifications" label="Notifications">
47
+ <div class="p-4">
48
+ <h3 class="text-lg font-semibold mb-2">Notifications</h3>
49
+ <p class="text-neutral-600">Gérez vos préférences de notification.</p>
50
+ </div>
51
+ </FTab>
52
+ </FTabs>
53
+ `
54
+ });
55
+
56
+ export const Pills = () => ({
57
+ components: { FTabs, FTab },
58
+ template: `
59
+ <FTabs variant="pills">
60
+ <FTab name="all" label="Tous">
61
+ <div class="p-4">
62
+ <p class="text-neutral-600">Affichage de tous les éléments.</p>
63
+ </div>
64
+ </FTab>
65
+ <FTab name="active" label="Actifs">
66
+ <div class="p-4">
67
+ <p class="text-neutral-600">Affichage des éléments actifs uniquement.</p>
68
+ </div>
69
+ </FTab>
70
+ <FTab name="archived" label="Archivés">
71
+ <div class="p-4">
72
+ <p class="text-neutral-600">Affichage des éléments archivés.</p>
73
+ </div>
74
+ </FTab>
75
+ </FTabs>
76
+ `
77
+ });
78
+
79
+ export const Underline = () => ({
80
+ components: { FTabs, FTab },
81
+ template: `
82
+ <FTabs variant="underline">
83
+ <FTab name="overview" label="Vue d'ensemble">
84
+ <div class="p-4">
85
+ <h3 class="text-lg font-semibold mb-2">Vue d'ensemble</h3>
86
+ <p class="text-neutral-600">Tableau de bord général de votre compte.</p>
87
+ </div>
88
+ </FTab>
89
+ <FTab name="analytics" label="Analytiques">
90
+ <div class="p-4">
91
+ <h3 class="text-lg font-semibold mb-2">Analytiques</h3>
92
+ <p class="text-neutral-600">Statistiques et métriques détaillées.</p>
93
+ </div>
94
+ </FTab>
95
+ <FTab name="reports" label="Rapports">
96
+ <div class="p-4">
97
+ <h3 class="text-lg font-semibold mb-2">Rapports</h3>
98
+ <p class="text-neutral-600">Générez et consultez vos rapports.</p>
99
+ </div>
100
+ </FTab>
101
+ </FTabs>
102
+ `
103
+ });
104
+
105
+ export const WithDisabledTab = () => ({
106
+ components: { FTabs, FTab },
107
+ template: `
108
+ <FTabs>
109
+ <FTab name="info" label="Informations">
110
+ <div class="p-4">
111
+ <p class="text-neutral-600">Contenu des informations.</p>
112
+ </div>
113
+ </FTab>
114
+ <FTab name="security" label="Sécurité" disabled>
115
+ <div class="p-4">
116
+ <p class="text-neutral-600">Cet onglet est désactivé.</p>
117
+ </div>
118
+ </FTab>
119
+ <FTab name="billing" label="Facturation">
120
+ <div class="p-4">
121
+ <p class="text-neutral-600">Informations de facturation.</p>
122
+ </div>
123
+ </FTab>
124
+ </FTabs>
125
+ `
126
+ });
127
+
128
+ export const BottomPosition = () => ({
129
+ components: { FTabs, FTab },
130
+ template: `
131
+ <FTabs position="bottom">
132
+ <FTab name="tab1" label="Premier">
133
+ <div class="p-4">
134
+ <p class="text-neutral-600">Contenu du premier onglet.</p>
135
+ </div>
136
+ </FTab>
137
+ <FTab name="tab2" label="Deuxième">
138
+ <div class="p-4">
139
+ <p class="text-neutral-600">Contenu du deuxième onglet.</p>
140
+ </div>
141
+ </FTab>
142
+ <FTab name="tab3" label="Troisième">
143
+ <div class="p-4">
144
+ <p class="text-neutral-600">Contenu du troisième onglet.</p>
145
+ </div>
146
+ </FTab>
147
+ </FTabs>
148
+ `
149
+ });
150
+
151
+ export const ControlledWithVModel = () => ({
152
+ components: { FTabs, FTab },
153
+ data() {
154
+ return {
155
+ activeTab: 'settings'
156
+ };
157
+ },
158
+ template: `
159
+ <div>
160
+ <div class="mb-4 p-4 bg-neutral-50 rounded">
161
+ <p class="text-sm text-neutral-600">Onglet actif : <strong>{{ activeTab }}</strong></p>
162
+ <div class="mt-2 flex gap-2">
163
+ <button
164
+ @click="activeTab = 'profile'"
165
+ class="px-3 py-1 text-sm bg-primary-500 text-white rounded hover:bg-primary-600"
166
+ >
167
+ Aller à Profil
168
+ </button>
169
+ <button
170
+ @click="activeTab = 'settings'"
171
+ class="px-3 py-1 text-sm bg-primary-500 text-white rounded hover:bg-primary-600"
172
+ >
173
+ Aller à Paramètres
174
+ </button>
175
+ <button
176
+ @click="activeTab = 'notifications'"
177
+ class="px-3 py-1 text-sm bg-primary-500 text-white rounded hover:bg-primary-600"
178
+ >
179
+ Aller à Notifications
180
+ </button>
181
+ </div>
182
+ </div>
183
+ <FTabs v-model="activeTab" @change="handleTabChange">
184
+ <FTab name="profile" label="Profil">
185
+ <div class="p-4">
186
+ <h3 class="text-lg font-semibold mb-2">Profil</h3>
187
+ <p class="text-neutral-600">Informations de profil.</p>
188
+ </div>
189
+ </FTab>
190
+ <FTab name="settings" label="Paramètres">
191
+ <div class="p-4">
192
+ <h3 class="text-lg font-semibold mb-2">Paramètres</h3>
193
+ <p class="text-neutral-600">Paramètres de l'application.</p>
194
+ </div>
195
+ </FTab>
196
+ <FTab name="notifications" label="Notifications">
197
+ <div class="p-4">
198
+ <h3 class="text-lg font-semibold mb-2">Notifications</h3>
199
+ <p class="text-neutral-600">Préférences de notification.</p>
200
+ </div>
201
+ </FTab>
202
+ </FTabs>
203
+ </div>
204
+ `,
205
+ methods: {
206
+ handleTabChange(tabName) {
207
+ console.log('Tab changed to:', tabName);
208
+ }
209
+ }
210
+ });
211
+
212
+ export const RichContent = () => ({
213
+ components: { FTabs, FTab },
214
+ template: `
215
+ <FTabs variant="pills">
216
+ <FTab name="dashboard" label="Tableau de bord">
217
+ <div class="p-4 space-y-4">
218
+ <div class="grid grid-cols-3 gap-4">
219
+ <div class="p-4 bg-primary-50 rounded-lg">
220
+ <p class="text-sm text-neutral-600">Utilisateurs</p>
221
+ <p class="text-2xl font-bold text-primary-600">1,234</p>
222
+ </div>
223
+ <div class="p-4 bg-success-50 rounded-lg">
224
+ <p class="text-sm text-neutral-600">Revenus</p>
225
+ <p class="text-2xl font-bold text-success-600">45,678 €</p>
226
+ </div>
227
+ <div class="p-4 bg-warning-50 rounded-lg">
228
+ <p class="text-sm text-neutral-600">En attente</p>
229
+ <p class="text-2xl font-bold text-warning-600">12</p>
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </FTab>
234
+ <FTab name="users" label="Utilisateurs">
235
+ <div class="p-4">
236
+ <table class="w-full">
237
+ <thead>
238
+ <tr class="border-b">
239
+ <th class="text-left p-2">Nom</th>
240
+ <th class="text-left p-2">Email</th>
241
+ <th class="text-left p-2">Statut</th>
242
+ </tr>
243
+ </thead>
244
+ <tbody>
245
+ <tr class="border-b">
246
+ <td class="p-2">Jean Dupont</td>
247
+ <td class="p-2">jean.dupont@example.com</td>
248
+ <td class="p-2"><span class="px-2 py-1 bg-success-100 text-success-700 rounded text-xs">Actif</span></td>
249
+ </tr>
250
+ <tr class="border-b">
251
+ <td class="p-2">Marie Martin</td>
252
+ <td class="p-2">marie.martin@example.com</td>
253
+ <td class="p-2"><span class="px-2 py-1 bg-success-100 text-success-700 rounded text-xs">Actif</span></td>
254
+ </tr>
255
+ </tbody>
256
+ </table>
257
+ </div>
258
+ </FTab>
259
+ <FTab name="settings" label="Configuration">
260
+ <div class="p-4 space-y-4">
261
+ <div class="flex items-center justify-between p-3 bg-neutral-50 rounded">
262
+ <span class="font-medium">Notifications par email</span>
263
+ <input type="checkbox" checked class="h-4 w-4" />
264
+ </div>
265
+ <div class="flex items-center justify-between p-3 bg-neutral-50 rounded">
266
+ <span class="font-medium">Mode sombre</span>
267
+ <input type="checkbox" class="h-4 w-4" />
268
+ </div>
269
+ <div class="flex items-center justify-between p-3 bg-neutral-50 rounded">
270
+ <span class="font-medium">Sauvegardes automatiques</span>
271
+ <input type="checkbox" checked class="h-4 w-4" />
272
+ </div>
273
+ </div>
274
+ </FTab>
275
+ </FTabs>
276
+ `
277
+ });