@pattern-stack/frontend-patterns 0.0.1 → 0.0.3

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 (153) hide show
  1. package/README.md +6 -6
  2. package/package.json +3 -5
  3. package/src/App.css +0 -42
  4. package/src/App.tsx +0 -54
  5. package/src/__tests__/README.md +0 -221
  6. package/src/__tests__/atoms/hooks/simple-hooks.test.ts +0 -44
  7. package/src/__tests__/atoms/ui/button.test.tsx +0 -68
  8. package/src/__tests__/atoms/utils/simple.test.ts +0 -18
  9. package/src/__tests__/atoms/utils/utils.test.ts +0 -77
  10. package/src/__tests__/features/auth/simple-auth.test.tsx +0 -40
  11. package/src/__tests__/molecules/layout/simple-layout.test.tsx +0 -81
  12. package/src/__tests__/organisms/showcase/simple-showcase.test.tsx +0 -167
  13. package/src/__tests__/setup.ts +0 -51
  14. package/src/__tests__/utils.tsx +0 -123
  15. package/src/atoms/composed/Accordion/Accordion.tsx +0 -271
  16. package/src/atoms/composed/Accordion/index.ts +0 -1
  17. package/src/atoms/composed/Alert/Alert.tsx +0 -132
  18. package/src/atoms/composed/Alert/index.ts +0 -1
  19. package/src/atoms/composed/Breadcrumb/Breadcrumb.tsx +0 -83
  20. package/src/atoms/composed/Breadcrumb/index.ts +0 -1
  21. package/src/atoms/composed/Chart/Chart.tsx +0 -425
  22. package/src/atoms/composed/Chart/index.ts +0 -2
  23. package/src/atoms/composed/ColorSwatch/ColorSwatch.tsx +0 -72
  24. package/src/atoms/composed/ColorSwatch/index.ts +0 -1
  25. package/src/atoms/composed/DarkModeToggle.tsx +0 -66
  26. package/src/atoms/composed/DataBadge/DataBadge.tsx +0 -81
  27. package/src/atoms/composed/DataBadge/index.ts +0 -1
  28. package/src/atoms/composed/DataTable/DataTable.tsx +0 -394
  29. package/src/atoms/composed/DataTable/TableCellWithTooltip.tsx +0 -41
  30. package/src/atoms/composed/DataTable/index.ts +0 -2
  31. package/src/atoms/composed/DateTimePicker/DateTimePicker.tsx +0 -611
  32. package/src/atoms/composed/DateTimePicker/index.ts +0 -2
  33. package/src/atoms/composed/DetailedCard/DetailedCard.tsx +0 -181
  34. package/src/atoms/composed/DetailedCard/index.ts +0 -2
  35. package/src/atoms/composed/EmptyState/EmptyState.tsx +0 -90
  36. package/src/atoms/composed/EmptyState/index.ts +0 -1
  37. package/src/atoms/composed/FileUpload/FileUpload.tsx +0 -477
  38. package/src/atoms/composed/FileUpload/index.ts +0 -2
  39. package/src/atoms/composed/FormField/FormField.tsx +0 -92
  40. package/src/atoms/composed/FormField/index.ts +0 -1
  41. package/src/atoms/composed/GlobalSearch/GlobalSearch.tsx +0 -37
  42. package/src/atoms/composed/GlobalSearch/index.ts +0 -1
  43. package/src/atoms/composed/IconBadge/IconBadge.tsx +0 -95
  44. package/src/atoms/composed/IconBadge/index.ts +0 -2
  45. package/src/atoms/composed/Modal/Modal.tsx +0 -223
  46. package/src/atoms/composed/Modal/index.ts +0 -2
  47. package/src/atoms/composed/PaletteSwitcher.tsx +0 -386
  48. package/src/atoms/composed/ProgressBar/ProgressBar.tsx +0 -116
  49. package/src/atoms/composed/ProgressBar/index.ts +0 -1
  50. package/src/atoms/composed/StatCard/StatCard.tsx +0 -219
  51. package/src/atoms/composed/StatCard/index.ts +0 -1
  52. package/src/atoms/composed/StyleGuide.tsx +0 -717
  53. package/src/atoms/composed/Toast/Toast.tsx +0 -219
  54. package/src/atoms/composed/Toast/index.ts +0 -1
  55. package/src/atoms/composed/Tooltip/Tooltip.tsx +0 -213
  56. package/src/atoms/composed/Tooltip/index.ts +0 -1
  57. package/src/atoms/composed/UserAvatar/UserAvatar.tsx +0 -139
  58. package/src/atoms/composed/UserAvatar/index.ts +0 -1
  59. package/src/atoms/composed/UserMenu/UserMenu.tsx +0 -16
  60. package/src/atoms/composed/UserMenu/index.ts +0 -1
  61. package/src/atoms/composed/index.ts +0 -29
  62. package/src/atoms/hooks/useApi.ts +0 -80
  63. package/src/atoms/hooks/useHealth.ts +0 -17
  64. package/src/atoms/index.ts +0 -13
  65. package/src/atoms/services/api/client.ts +0 -134
  66. package/src/atoms/services/auth-service.ts +0 -248
  67. package/src/atoms/services/health.ts +0 -15
  68. package/src/atoms/services/index.ts +0 -3
  69. package/src/atoms/shared/config/constants.ts +0 -17
  70. package/src/atoms/shared/config/dashboard-sizes.ts +0 -111
  71. package/src/atoms/shared/config/environment.ts +0 -10
  72. package/src/atoms/shared/index.ts +0 -4
  73. package/src/atoms/shared/styles/color-palettes.css +0 -566
  74. package/src/atoms/types/auth.ts +0 -62
  75. package/src/atoms/types/generated.ts +0 -1469
  76. package/src/atoms/types/index.ts +0 -4
  77. package/src/atoms/types/loading.ts +0 -28
  78. package/src/atoms/ui/Badge.tsx +0 -30
  79. package/src/atoms/ui/ErrorBoundary.tsx +0 -59
  80. package/src/atoms/ui/Select.tsx +0 -53
  81. package/src/atoms/ui/Switch.tsx +0 -42
  82. package/src/atoms/ui/Tabs.tsx +0 -118
  83. package/src/atoms/ui/avatar.tsx +0 -48
  84. package/src/atoms/ui/button.tsx +0 -70
  85. package/src/atoms/ui/card.tsx +0 -76
  86. package/src/atoms/ui/dropdown-menu.tsx +0 -199
  87. package/src/atoms/ui/index.ts +0 -39
  88. package/src/atoms/ui/input.tsx +0 -23
  89. package/src/atoms/ui/label.tsx +0 -23
  90. package/src/atoms/ui/skeleton.tsx +0 -13
  91. package/src/atoms/ui/spinner.tsx +0 -49
  92. package/src/atoms/ui/table.tsx +0 -116
  93. package/src/atoms/utils/animations.ts +0 -135
  94. package/src/atoms/utils/tooltip-helpers.ts +0 -140
  95. package/src/atoms/utils/utils.ts +0 -9
  96. package/src/features/auth/components/LoginForm.tsx +0 -168
  97. package/src/features/auth/components/LogoutButton.tsx +0 -19
  98. package/src/features/auth/components/ProtectedRoute.tsx +0 -60
  99. package/src/features/auth/components/index.ts +0 -4
  100. package/src/features/auth/hooks/index.ts +0 -2
  101. package/src/features/auth/hooks/useAuth.tsx +0 -205
  102. package/src/features/auth/hooks/usePermissions.ts +0 -35
  103. package/src/features/auth/index.ts +0 -2
  104. package/src/features/index.ts +0 -2
  105. package/src/index.css +0 -704
  106. package/src/index.ts +0 -13
  107. package/src/main.tsx +0 -48
  108. package/src/molecules/.gitkeep +0 -0
  109. package/src/molecules/forms/FormGroup.tsx +0 -75
  110. package/src/molecules/forms/SearchInput.tsx +0 -259
  111. package/src/molecules/forms/index.ts +0 -4
  112. package/src/molecules/index.ts +0 -4
  113. package/src/molecules/layout/AppHeader/AppHeader.tsx +0 -42
  114. package/src/molecules/layout/AppHeader/index.ts +0 -1
  115. package/src/molecules/layout/AppLayout.tsx +0 -29
  116. package/src/molecules/layout/PageTemplate.tsx +0 -87
  117. package/src/molecules/layout/SectionHeader/SectionHeader.tsx +0 -87
  118. package/src/molecules/layout/SectionHeader/index.ts +0 -1
  119. package/src/molecules/layout/ShowcaseSection.tsx +0 -57
  120. package/src/molecules/layout/Sidebar.tsx +0 -144
  121. package/src/molecules/layout/SidebarButton/SidebarButton.tsx +0 -99
  122. package/src/molecules/layout/SidebarButton/index.ts +0 -1
  123. package/src/molecules/layout/SidebarContext.tsx +0 -31
  124. package/src/molecules/layout/index.ts +0 -7
  125. package/src/molecules/navigation/NavMenu.tsx +0 -188
  126. package/src/molecules/navigation/Pagination.tsx +0 -172
  127. package/src/molecules/navigation/index.ts +0 -4
  128. package/src/organisms/index.ts +0 -5
  129. package/src/organisms/showcase/ComponentShowcasePage.tsx +0 -2496
  130. package/src/organisms/showcase/index.ts +0 -1
  131. package/src/pages/AdminShowcase/AdminCRUDShowcase.tsx +0 -242
  132. package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +0 -171
  133. package/src/pages/AdminShowcase/AdminDetailShowcase.tsx +0 -385
  134. package/src/pages/AdminShowcase/index.tsx +0 -3
  135. package/src/pages/ComponentShowcase/BadgesShowcase.tsx +0 -188
  136. package/src/pages/ComponentShowcase/CardsShowcase.tsx +0 -392
  137. package/src/pages/ComponentShowcase/PalettesShowcase.tsx +0 -207
  138. package/src/pages/ComponentShowcase/StatesShowcase.tsx +0 -485
  139. package/src/pages/ComponentShowcase/TablesShowcase.tsx +0 -134
  140. package/src/pages/ComponentShowcase/TypographyShowcase.tsx +0 -255
  141. package/src/pages/ComponentShowcase/index.tsx +0 -188
  142. package/src/pages/index.ts +0 -2
  143. package/src/templates/AuthTemplate.tsx +0 -216
  144. package/src/templates/ComponentShowcaseTemplate.tsx +0 -173
  145. package/src/templates/DashboardTemplate.tsx +0 -232
  146. package/src/templates/DataTemplate.tsx +0 -319
  147. package/src/templates/admin/AdminCRUDTemplate.tsx +0 -630
  148. package/src/templates/admin/AdminDashboardTemplate.tsx +0 -351
  149. package/src/templates/admin/AdminDetailTemplate.tsx +0 -563
  150. package/src/templates/admin/index.ts +0 -29
  151. package/src/templates/factory.tsx +0 -169
  152. package/src/templates/index.ts +0 -37
  153. package/src/vite-env.d.ts +0 -1
@@ -1,386 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
- import { Card } from '../ui/card';
3
- import { Button } from '../ui/button';
4
- import { Badge } from '../ui/Badge';
5
- import { cn } from '../utils/utils';
6
- import {
7
- Palette,
8
- Sun,
9
- Moon,
10
- Waves,
11
- Zap,
12
- TreePine,
13
- Sparkles,
14
- Sunset,
15
- Square,
16
- Building2
17
- } from 'lucide-react';
18
-
19
- interface ColorPalette {
20
- id: string;
21
- name: string;
22
- description: string;
23
- className: string;
24
- icon: React.ReactNode;
25
- category: 'vibrant' | 'natural' | 'professional' | 'mystical';
26
- preview: {
27
- primary: string;
28
- secondary: string;
29
- accent: string;
30
- background: string;
31
- };
32
- }
33
-
34
- const colorPalettes: ColorPalette[] = [
35
- {
36
- id: 'default',
37
- name: 'Default',
38
- description: 'Clean, professional design system',
39
- className: '',
40
- icon: <Square className="w-4 h-4" />,
41
- category: 'professional',
42
- preview: {
43
- primary: 'hsl(222.2 47.4% 11.2%)',
44
- secondary: 'hsl(210 40% 96%)',
45
- accent: 'hsl(210 40% 96%)',
46
- background: 'hsl(0 0% 100%)'
47
- }
48
- },
49
- {
50
- id: 'ocean-depth',
51
- name: 'Ocean Depth',
52
- description: 'Deep blues with vibrant cyan and coral accents',
53
- className: 'palette-ocean-depth',
54
- icon: <Waves className="w-4 h-4" />,
55
- category: 'vibrant',
56
- preview: {
57
- primary: 'hsl(195 100% 65%)',
58
- secondary: 'hsl(220 20% 25%)',
59
- accent: 'hsl(280 100% 70%)',
60
- background: 'hsl(220 26% 14%)'
61
- }
62
- },
63
- {
64
- id: 'neon-cyber',
65
- name: 'Neon Cyber',
66
- description: 'Vibrant cyberpunk aesthetics with electric colors',
67
- className: 'palette-neon-cyber',
68
- icon: <Zap className="w-4 h-4" />,
69
- category: 'vibrant',
70
- preview: {
71
- primary: 'hsl(320 100% 70%)',
72
- secondary: 'hsl(260 20% 18%)',
73
- accent: 'hsl(180 100% 70%)',
74
- background: 'hsl(260 15% 8%)'
75
- }
76
- },
77
- {
78
- id: 'earth-tones',
79
- name: 'Earth Tones',
80
- description: 'Warm, organic colors inspired by nature',
81
- className: 'palette-earth-tones',
82
- icon: <TreePine className="w-4 h-4" />,
83
- category: 'natural',
84
- preview: {
85
- primary: 'hsl(25 70% 45%)',
86
- secondary: 'hsl(35 20% 88%)',
87
- accent: 'hsl(200 60% 55%)',
88
- background: 'hsl(35 25% 96%)'
89
- }
90
- },
91
- {
92
- id: 'aurora',
93
- name: 'Aurora Borealis',
94
- description: 'Mystical greens and blues like the northern lights',
95
- className: 'palette-aurora',
96
- icon: <Sparkles className="w-4 h-4" />,
97
- category: 'mystical',
98
- preview: {
99
- primary: 'hsl(160 80% 65%)',
100
- secondary: 'hsl(220 20% 20%)',
101
- accent: 'hsl(280 90% 75%)',
102
- background: 'hsl(220 30% 8%)'
103
- }
104
- },
105
- {
106
- id: 'sunset',
107
- name: 'Sunset Gradient',
108
- description: 'Warm oranges, pinks, and purples',
109
- className: 'palette-sunset',
110
- icon: <Sunset className="w-4 h-4" />,
111
- category: 'natural',
112
- preview: {
113
- primary: 'hsl(25 85% 60%)',
114
- secondary: 'hsl(15 25% 88%)',
115
- accent: 'hsl(320 85% 65%)',
116
- background: 'hsl(15 30% 95%)'
117
- }
118
- },
119
- {
120
- id: 'monochrome',
121
- name: 'Monochrome Elite',
122
- description: 'Sophisticated grayscale with blue accents',
123
- className: 'palette-monochrome',
124
- icon: <Square className="w-4 h-4" />,
125
- category: 'professional',
126
- preview: {
127
- primary: 'hsl(240 100% 50%)',
128
- secondary: 'hsl(0 0% 90%)',
129
- accent: 'hsl(240 100% 50%)',
130
- background: 'hsl(0 0% 98%)'
131
- }
132
- },
133
- {
134
- id: 'corporate-elite',
135
- name: 'Corporate Elite',
136
- description: 'Executive boardroom sophistication with navy and gold',
137
- className: 'palette-corporate-elite',
138
- icon: <Building2 className="w-4 h-4" />,
139
- category: 'professional',
140
- preview: {
141
- primary: 'hsl(224 65% 25%)',
142
- secondary: 'hsl(220 10% 88%)',
143
- accent: 'hsl(45 85% 55%)',
144
- background: 'hsl(220 15% 97%)'
145
- }
146
- }
147
- ];
148
-
149
- const categoryColors = {
150
- vibrant: 'bg-category-1',
151
- natural: 'bg-category-6',
152
- professional: 'bg-category-4',
153
- mystical: 'bg-category-5'
154
- };
155
-
156
- interface PaletteSwitcherProps {
157
- className?: string;
158
- onPaletteChange?: (paletteId: string) => void;
159
- }
160
-
161
- export const PaletteSwitcher = ({
162
- className,
163
- onPaletteChange
164
- }: PaletteSwitcherProps) => {
165
- const [activePalette, setActivePalette] = useState('default');
166
- const [isDarkMode, setIsDarkMode] = useState(false);
167
-
168
- // Define applyPalette function with useCallback to prevent recreation on each render
169
- const applyPalette = useCallback((paletteId: string) => {
170
- const palette = colorPalettes.find(p => p.id === paletteId);
171
- if (!palette) return;
172
-
173
- // Remove all existing palette classes
174
- colorPalettes.forEach(p => {
175
- if (p.className) {
176
- document.documentElement.classList.remove(p.className);
177
- }
178
- });
179
-
180
- // Apply new palette class
181
- if (palette.className) {
182
- document.documentElement.classList.add(palette.className);
183
- }
184
-
185
- // Save to localStorage
186
- localStorage.setItem('selected-palette', paletteId);
187
-
188
- // Notify parent component
189
- onPaletteChange?.(paletteId);
190
- }, [onPaletteChange]);
191
-
192
- // Load saved palette from localStorage
193
- useEffect(() => {
194
- const saved = localStorage.getItem('selected-palette');
195
- const savedDark = localStorage.getItem('dark-mode') === 'true';
196
-
197
- if (saved && colorPalettes.find(p => p.id === saved)) {
198
- setActivePalette(saved);
199
- applyPalette(saved);
200
- }
201
-
202
- setIsDarkMode(savedDark);
203
- if (savedDark) {
204
- document.documentElement.classList.add('dark');
205
- }
206
- }, [applyPalette]);
207
-
208
- const handlePaletteChange = (paletteId: string) => {
209
- setActivePalette(paletteId);
210
- applyPalette(paletteId);
211
- };
212
-
213
- const toggleDarkMode = () => {
214
- const newDarkMode = !isDarkMode;
215
- setIsDarkMode(newDarkMode);
216
-
217
- if (newDarkMode) {
218
- document.documentElement.classList.add('dark');
219
- } else {
220
- document.documentElement.classList.remove('dark');
221
- }
222
-
223
- localStorage.setItem('dark-mode', newDarkMode.toString());
224
- };
225
-
226
- const groupedPalettes = colorPalettes.reduce((groups, palette) => {
227
- const category = palette.category;
228
- if (!groups[category]) {
229
- groups[category] = [];
230
- }
231
- groups[category].push(palette);
232
- return groups;
233
- }, {} as Record<string, ColorPalette[]>);
234
-
235
- return (
236
- <div className={cn("space-y-6", className)} data-component-name="PaletteSwitcher">
237
- {/* Header */}
238
- <div className="flex items-center justify-between">
239
- <div className="flex items-center gap-2">
240
- <Palette className="w-5 h-5 text-primary" data-component-name="PaletteSwitcherIcon" />
241
- <h3 className="text-lg font-semibold">Color Palettes</h3>
242
- </div>
243
-
244
- <Button
245
- variant="outline"
246
- size="sm"
247
- onClick={toggleDarkMode}
248
- className="flex items-center gap-2"
249
- >
250
- {isDarkMode ? <Sun className="w-4 h-4" /> : <Moon className="w-4 h-4" />}
251
- {isDarkMode ? 'Light' : 'Dark'}
252
- </Button>
253
- </div>
254
-
255
- {/* Active Palette Info */}
256
- <Card className="p-4" data-component-name="CategoryColorPreview">
257
- <div className="flex items-center gap-3">
258
- <div className="p-2 rounded bg-primary/10 text-primary">
259
- {colorPalettes.find(p => p.id === activePalette)?.icon}
260
- </div>
261
- <div className="flex-1">
262
- <h4 className="font-medium">
263
- {colorPalettes.find(p => p.id === activePalette)?.name}
264
- </h4>
265
- <p className="text-sm text-muted-foreground">
266
- {colorPalettes.find(p => p.id === activePalette)?.description}
267
- </p>
268
- </div>
269
- <Badge
270
- variant="secondary"
271
- className={cn(
272
- "text-xs",
273
- categoryColors[colorPalettes.find(p => p.id === activePalette)?.category || 'professional']
274
- )}
275
- >
276
- {colorPalettes.find(p => p.id === activePalette)?.category}
277
- </Badge>
278
- </div>
279
- </Card>
280
-
281
- {/* Palette Grid by Category */}
282
- <div className="space-y-6">
283
- {Object.entries(groupedPalettes).map(([category, palettes]) => (
284
- <div key={category}>
285
- <h4 className="text-sm font-medium text-muted-foreground uppercase tracking-wide mb-3">
286
- {category}
287
- </h4>
288
-
289
- <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
290
- {palettes.map((palette) => (
291
- <Card
292
- key={palette.id}
293
- className={cn(
294
- "p-4 cursor-pointer transition-all hover:shadow",
295
- activePalette === palette.id && "ring-2 ring-primary bg-primary/5"
296
- )}
297
- onClick={() => handlePaletteChange(palette.id)}
298
- data-component-name="PaletteCard"
299
- data-active={activePalette === palette.id}
300
- >
301
- <div className="flex items-center gap-3">
302
- <div className="p-2 rounded bg-muted text-muted-foreground">
303
- {palette.icon}
304
- </div>
305
-
306
- <div className="flex-1 min-w-0">
307
- <div className="font-medium truncate">{palette.name}</div>
308
- <div className="text-sm text-muted-foreground truncate">
309
- {palette.description}
310
- </div>
311
- </div>
312
-
313
- {/* Color Preview */}
314
- <div className="flex gap-1">
315
- <div
316
- className="w-3 h-3 rounded-full border border-border"
317
- style={{ backgroundColor: palette.preview.primary }}
318
- data-component-name="PaletteColorPreview"
319
- />
320
- <div
321
- className="w-3 h-3 rounded-full border border-border"
322
- style={{ backgroundColor: palette.preview.accent }}
323
- data-component-name="PaletteColorPreview"
324
- />
325
- <div
326
- className="w-3 h-3 rounded-full border border-border"
327
- style={{ backgroundColor: palette.preview.secondary }}
328
- data-component-name="PaletteColorPreview"
329
- />
330
- </div>
331
- </div>
332
- </Card>
333
- ))}
334
- </div>
335
- </div>
336
- ))}
337
- </div>
338
-
339
- {/* Category Color Preview */}
340
- <Card className="p-4" data-component-name="CategoryColorPreview">
341
- <h4 className="text-sm font-medium mb-3">Category Colors Preview</h4>
342
- <div className="grid grid-cols-4 md:grid-cols-8 gap-2">
343
- {[1, 2, 3, 4, 5, 6, 7, 8].map(num => (
344
- <div key={num} className="text-center">
345
- <div
346
- className={cn(
347
- "w-8 h-8 rounded mx-auto mb-1 border border-border",
348
- `bg-category-${num}`
349
- )}
350
- data-component-name="ColorSwatch"
351
- data-category={num}
352
- />
353
- <div className="text-xs text-muted-foreground">{num}</div>
354
- </div>
355
- ))}
356
- </div>
357
- </Card>
358
-
359
- {/* Status Colors Preview */}
360
- <Card className="p-4" data-component-name="StatusColorPreview">
361
- <h4 className="text-sm font-medium mb-3">Status Colors Preview</h4>
362
- <div className="grid grid-cols-5 gap-2">
363
- {[
364
- { name: 'Success', class: 'bg-status-success' },
365
- { name: 'Warning', class: 'bg-status-warning' },
366
- { name: 'Error', class: 'bg-status-error' },
367
- { name: 'Info', class: 'bg-status-info' },
368
- { name: 'Neutral', class: 'bg-status-neutral' }
369
- ].map(status => (
370
- <div key={status.name} className="text-center">
371
- <div
372
- className={cn(
373
- "w-8 h-8 rounded mx-auto mb-1 border border-border",
374
- status.class
375
- )}
376
- data-component-name="StatusSwatch"
377
- data-status={status.name.toLowerCase()}
378
- />
379
- <div className="text-xs text-muted-foreground">{status.name}</div>
380
- </div>
381
- ))}
382
- </div>
383
- </Card>
384
- </div>
385
- );
386
- };
@@ -1,116 +0,0 @@
1
- import React from 'react';
2
- import { cn } from '../../utils/utils';
3
- import { getAnimationClasses, animationPresets } from '../../utils/animations';
4
-
5
- export interface ProgressBarProps {
6
- /** Progress value (0-100) */
7
- value: number;
8
- /** Maximum value */
9
- max?: number;
10
- /** Status-based coloring */
11
- status?: 'success' | 'warning' | 'error' | 'info' | 'neutral';
12
- /** Category-based coloring */
13
- category?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
14
- /** Size variant */
15
- size?: 'sm' | 'md' | 'lg';
16
- /** Show percentage label */
17
- showLabel?: boolean;
18
- /** Custom label */
19
- label?: string;
20
- /** Progress bar variant */
21
- variant?: 'default' | 'striped' | 'animated';
22
- /** Additional CSS classes */
23
- className?: string;
24
- /** Accessible label */
25
- 'aria-label'?: string;
26
- }
27
-
28
- export const ProgressBar: React.FC<ProgressBarProps> = ({
29
- value,
30
- max = 100,
31
- status,
32
- category,
33
- size = 'md',
34
- showLabel = false,
35
- label,
36
- variant = 'default',
37
- className,
38
- 'aria-label': ariaLabel
39
- }) => {
40
- const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
41
-
42
- const sizeClasses = {
43
- sm: 'h-2',
44
- md: 'h-3',
45
- lg: 'h-4'
46
- };
47
-
48
- const trackClasses = 'w-full bg-muted rounded-full overflow-hidden';
49
-
50
- const getBarClasses = () => {
51
- let baseClasses = 'h-full transition-all duration-500 ease-out';
52
-
53
- // Color classes
54
- if (status) {
55
- baseClasses += ` bg-status-${status}`;
56
- } else if (category) {
57
- baseClasses += ` bg-category-${category}`;
58
- } else {
59
- baseClasses += ' bg-primary';
60
- }
61
-
62
- // Variant classes
63
- if (variant === 'striped') {
64
- baseClasses += ' bg-gradient-to-r from-current via-current/80 to-current';
65
- baseClasses += ' bg-[length:1rem_1rem]';
66
- baseClasses += ' bg-repeat-x';
67
- }
68
-
69
- if (variant === 'animated') {
70
- baseClasses += ' bg-gradient-to-r from-current via-current/60 to-current';
71
- baseClasses += ' bg-[length:2rem_100%]';
72
- baseClasses += ' animate-pulse';
73
- }
74
-
75
- return baseClasses;
76
- };
77
-
78
- const displayLabel = label || (showLabel ? `${Math.round(percentage)}%` : undefined);
79
-
80
- return (
81
- <div
82
- className={cn('w-full', className)}
83
- data-component-name="ProgressBar"
84
- >
85
- {displayLabel && (
86
- <div className="flex justify-between items-center mb-2 text-sm">
87
- <span className="text-foreground font-medium">
88
- {displayLabel}
89
- </span>
90
- {showLabel && !label && (
91
- <span className="text-muted-foreground">
92
- {value}/{max}
93
- </span>
94
- )}
95
- </div>
96
- )}
97
-
98
- <div
99
- className={cn(trackClasses, sizeClasses[size])}
100
- role="progressbar"
101
- aria-valuenow={value}
102
- aria-valuemin={0}
103
- aria-valuemax={max}
104
- aria-label={ariaLabel || `Progress: ${percentage.toFixed(1)}%`}
105
- >
106
- <div
107
- className={cn(
108
- getBarClasses(),
109
- getAnimationClasses(animationPresets.subtle)
110
- )}
111
- style={{ width: `${percentage}%` }}
112
- />
113
- </div>
114
- </div>
115
- );
116
- };
@@ -1 +0,0 @@
1
- export { ProgressBar, type ProgressBarProps } from './ProgressBar';