@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
package/src/main.tsx DELETED
@@ -1,48 +0,0 @@
1
- import { StrictMode } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
4
- import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
5
- import { AuthProvider } from './features/auth'
6
- import { SidebarProvider } from './molecules/layout'
7
- import './index.css'
8
- import App from './App.tsx'
9
-
10
- // Suppress browser extension errors in development
11
- if (import.meta.env.DEV) {
12
- const originalError = console.error;
13
- console.error = (...args) => {
14
- const message = args[0];
15
- if (
16
- typeof message === 'string' &&
17
- (message.includes('Deprecated API for given entry type') ||
18
- message.includes('message channel closed before a response was received') ||
19
- message.includes('Extension context invalidated'))
20
- ) {
21
- return; // Suppress extension-related errors
22
- }
23
- originalError(...args);
24
- };
25
- }
26
-
27
- const queryClient = new QueryClient({
28
- defaultOptions: {
29
- queries: {
30
- retry: 1,
31
- refetchOnWindowFocus: false,
32
- staleTime: 5 * 60 * 1000, // 5 minutes
33
- },
34
- },
35
- })
36
-
37
- createRoot(document.getElementById('root')!).render(
38
- <StrictMode>
39
- <QueryClientProvider client={queryClient}>
40
- <AuthProvider>
41
- <SidebarProvider>
42
- <App />
43
- </SidebarProvider>
44
- </AuthProvider>
45
- <ReactQueryDevtools initialIsOpen={false} />
46
- </QueryClientProvider>
47
- </StrictMode>,
48
- )
File without changes
@@ -1,75 +0,0 @@
1
- import React from 'react';
2
- import { cn } from '../../atoms/utils/utils';
3
-
4
- export interface FormGroupProps {
5
- /** Group title */
6
- title?: string;
7
- /** Group description */
8
- description?: string;
9
- /** Group content */
10
- children: React.ReactNode;
11
- /** Visual variant */
12
- variant?: 'default' | 'card' | 'section';
13
- /** Additional CSS classes */
14
- className?: string;
15
- /** Category-based styling */
16
- category?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
17
- }
18
-
19
- export const FormGroup: React.FC<FormGroupProps> = ({
20
- title,
21
- description,
22
- children,
23
- variant = 'default',
24
- className,
25
- category
26
- }) => {
27
- const variantClasses = {
28
- default: 'space-y-4',
29
- card: 'space-y-4 p-6 bg-card border border-border rounded-lg',
30
- section: 'space-y-6 pb-6 border-b border-border last:border-b-0 last:pb-0'
31
- };
32
-
33
- const titleClasses = {
34
- default: 'text-lg font-semibold text-foreground',
35
- card: 'text-lg font-semibold text-foreground',
36
- section: 'text-xl font-semibold text-foreground'
37
- };
38
-
39
- return (
40
- <div
41
- className={cn(
42
- variantClasses[variant],
43
- category && variant === 'card' && `border-category-${category}/20`,
44
- className
45
- )}
46
- data-component-name="FormGroup"
47
- >
48
- {/* Header */}
49
- {(title || description) && (
50
- <div className="space-y-1">
51
- {title && (
52
- <h3
53
- className={cn(
54
- titleClasses[variant],
55
- category && `text-category-${category}`
56
- )}
57
- >
58
- {title}
59
- </h3>
60
- )}
61
- {description && (
62
- <p className="text-sm text-muted-foreground">
63
- {description}
64
- </p>
65
- )}
66
- </div>
67
- )}
68
-
69
- {/* Content */}
70
- <div className="space-y-4">
71
- {children}
72
- </div>
73
- </div>
74
- );
75
- };
@@ -1,259 +0,0 @@
1
- import React, { useState, useRef, useEffect } from 'react';
2
- import { Search, X, Loader2 } from 'lucide-react';
3
- import { cn } from '../../atoms/utils/utils';
4
- import { Input } from '../../atoms/ui/input';
5
- import { Button } from '../../atoms/ui/button';
6
- import { getAnimationClasses, animationPresets } from '../../atoms/utils/animations';
7
-
8
- export interface SearchResult {
9
- id: string;
10
- label: string;
11
- description?: string;
12
- category?: string;
13
- icon?: React.ReactNode;
14
- }
15
-
16
- export interface SearchInputProps {
17
- /** Search placeholder text */
18
- placeholder?: string;
19
- /** Current search value */
20
- value?: string;
21
- /** Value change handler */
22
- onChange?: (value: string) => void;
23
- /** Search results */
24
- results?: SearchResult[];
25
- /** Loading state */
26
- loading?: boolean;
27
- /** Result selection handler */
28
- onSelect?: (result: SearchResult) => void;
29
- /** Search debounce delay in ms */
30
- debounceMs?: number;
31
- /** Whether to show clear button */
32
- clearable?: boolean;
33
- /** Additional CSS classes */
34
- className?: string;
35
- /** Category-based styling */
36
- category?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
37
- /** Maximum results to show */
38
- maxResults?: number;
39
- /** No results message */
40
- noResultsText?: string;
41
- }
42
-
43
- export const SearchInput: React.FC<SearchInputProps> = ({
44
- placeholder = 'Search...',
45
- value = '',
46
- onChange,
47
- results = [],
48
- loading = false,
49
- onSelect,
50
- debounceMs = 300,
51
- clearable = true,
52
- className,
53
- category = 1,
54
- maxResults = 10,
55
- noResultsText = 'No results found'
56
- }) => {
57
- const [internalValue, setInternalValue] = useState(value);
58
- const [isOpen, setIsOpen] = useState(false);
59
- const [highlightedIndex, setHighlightedIndex] = useState(-1);
60
-
61
- const inputRef = useRef<HTMLInputElement>(null);
62
- const resultsRef = useRef<HTMLDivElement>(null);
63
- const debounceRef = useRef<NodeJS.Timeout | undefined>(undefined);
64
-
65
- const displayResults = results.slice(0, maxResults);
66
- const showResults = isOpen && (displayResults.length > 0 || (internalValue && !loading));
67
-
68
- // Debounced search
69
- useEffect(() => {
70
- if (debounceRef.current) {
71
- clearTimeout(debounceRef.current);
72
- }
73
-
74
- debounceRef.current = setTimeout(() => {
75
- if (onChange) onChange(internalValue);
76
- }, debounceMs);
77
-
78
- return () => {
79
- if (debounceRef.current) {
80
- clearTimeout(debounceRef.current);
81
- }
82
- };
83
- }, [internalValue, onChange, debounceMs]);
84
-
85
- // Sync external value
86
- useEffect(() => {
87
- setInternalValue(value);
88
- }, [value]);
89
-
90
- // Keyboard navigation
91
- const handleKeyDown = (e: React.KeyboardEvent) => {
92
- if (!showResults) return;
93
-
94
- switch (e.key) {
95
- case 'ArrowDown':
96
- e.preventDefault();
97
- setHighlightedIndex(prev =>
98
- prev < displayResults.length - 1 ? prev + 1 : prev
99
- );
100
- break;
101
- case 'ArrowUp':
102
- e.preventDefault();
103
- setHighlightedIndex(prev => prev > 0 ? prev - 1 : prev);
104
- break;
105
- case 'Enter':
106
- e.preventDefault();
107
- if (highlightedIndex >= 0 && displayResults[highlightedIndex]) {
108
- handleSelect(displayResults[highlightedIndex]);
109
- }
110
- break;
111
- case 'Escape':
112
- setIsOpen(false);
113
- setHighlightedIndex(-1);
114
- inputRef.current?.blur();
115
- break;
116
- }
117
- };
118
-
119
- const handleSelect = (result: SearchResult) => {
120
- onSelect?.(result);
121
- setIsOpen(false);
122
- setHighlightedIndex(-1);
123
- inputRef.current?.blur();
124
- };
125
-
126
- const handleClear = () => {
127
- setInternalValue('');
128
- onChange?.('');
129
- setIsOpen(false);
130
- inputRef.current?.focus();
131
- };
132
-
133
- const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
134
- const newValue = e.target.value;
135
- setInternalValue(newValue);
136
- setIsOpen(true);
137
- setHighlightedIndex(-1);
138
- };
139
-
140
- const handleFocus = () => {
141
- if (internalValue) {
142
- setIsOpen(true);
143
- }
144
- };
145
-
146
- const handleBlur = () => {
147
- // Delay closing to allow for result clicks
148
- setTimeout(() => {
149
- if (!resultsRef.current?.contains(document.activeElement)) {
150
- setIsOpen(false);
151
- setHighlightedIndex(-1);
152
- }
153
- }, 150);
154
- };
155
-
156
- return (
157
- <div className={cn('relative w-full', className)} data-component-name="SearchInput">
158
- {/* Input container */}
159
- <div className="relative">
160
- <div className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground">
161
- {loading ? (
162
- <Loader2 className="w-4 h-4 animate-spin" />
163
- ) : (
164
- <Search className="w-4 h-4" />
165
- )}
166
- </div>
167
-
168
- <Input
169
- ref={inputRef}
170
- type="text"
171
- value={internalValue}
172
- onChange={handleInputChange}
173
- onKeyDown={handleKeyDown}
174
- onFocus={handleFocus}
175
- onBlur={handleBlur}
176
- placeholder={placeholder}
177
- className={cn(
178
- 'pl-10',
179
- clearable && internalValue && 'pr-10',
180
- showResults && `ring-2 ring-category-${category}/20`
181
- )}
182
- />
183
-
184
- {clearable && internalValue && (
185
- <Button
186
- type="button"
187
- variant="ghost"
188
- size="sm"
189
- onClick={handleClear}
190
- className="absolute right-1 top-1/2 -translate-y-1/2 h-7 w-7 p-0 hover:bg-muted"
191
- >
192
- <X className="w-4 h-4" />
193
- </Button>
194
- )}
195
- </div>
196
-
197
- {/* Results dropdown */}
198
- {showResults && (
199
- <div
200
- ref={resultsRef}
201
- className={cn(
202
- 'absolute top-full left-0 right-0 z-50 mt-1',
203
- 'bg-popover border border-border rounded-md shadow-lg',
204
- 'max-h-64 overflow-y-auto',
205
- getAnimationClasses(animationPresets.card)
206
- )}
207
- >
208
- {displayResults.length > 0 ? (
209
- <div className="py-1">
210
- {displayResults.map((result, index) => (
211
- <button
212
- key={result.id}
213
- type="button"
214
- onClick={() => handleSelect(result)}
215
- className={cn(
216
- 'w-full text-left px-3 py-2 text-sm',
217
- 'hover:bg-muted/50 focus:bg-muted/50',
218
- 'transition-colors duration-150',
219
- index === highlightedIndex && [
220
- `bg-category-${category}/10`,
221
- `text-category-${category}`
222
- ]
223
- )}
224
- >
225
- <div className="flex items-center gap-2">
226
- {result.icon && (
227
- <span className="flex-shrink-0 text-muted-foreground">
228
- {result.icon}
229
- </span>
230
- )}
231
- <div className="flex-1 min-w-0">
232
- <div className="font-medium truncate">
233
- {result.label}
234
- </div>
235
- {result.description && (
236
- <div className="text-xs text-muted-foreground truncate">
237
- {result.description}
238
- </div>
239
- )}
240
- </div>
241
- {result.category && (
242
- <span className="text-xs text-muted-foreground">
243
- {result.category}
244
- </span>
245
- )}
246
- </div>
247
- </button>
248
- ))}
249
- </div>
250
- ) : internalValue && !loading ? (
251
- <div className="px-3 py-2 text-sm text-muted-foreground">
252
- {noResultsText}
253
- </div>
254
- ) : null}
255
- </div>
256
- )}
257
- </div>
258
- );
259
- };
@@ -1,4 +0,0 @@
1
- // Form molecules - reusable form patterns and workflows
2
- // Note: FormField moved to @/atoms/composed as it is a business UI component
3
- export { FormGroup, type FormGroupProps } from './FormGroup';
4
- export { SearchInput, type SearchInputProps, type SearchResult } from './SearchInput';
@@ -1,4 +0,0 @@
1
- // Molecule layer exports - combinations of atoms and features
2
- export * from './layout';
3
- export * from './navigation';
4
- export * from './forms';
@@ -1,42 +0,0 @@
1
- import React from 'react';
2
- import { GlobalSearch, UserMenu } from '../../../atoms/composed';
3
- import { cn } from '../../../atoms/utils/utils';
4
-
5
- interface AppHeaderProps {
6
- className?: string;
7
- }
8
-
9
- export const AppHeader: React.FC<AppHeaderProps> = ({ className }) => {
10
- return (
11
- <header className={cn(
12
- "fixed top-0 left-0 right-0 z-50",
13
- "bg-card/95 backdrop-blur-sm border-b border-border",
14
- "supports-[backdrop-filter]:bg-card/95",
15
- className
16
- )}>
17
- <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
18
- <div className="flex h-16 items-center justify-between">
19
- {/* App Title */}
20
- <div className="flex items-center">
21
- <h1 className="text-xl font-bold text-foreground">
22
- Data Trust Navigator
23
- </h1>
24
- </div>
25
-
26
- {/* Centered Global Search */}
27
- <div className="flex-1 max-w-2xl mx-8">
28
- <GlobalSearch
29
- className="w-full"
30
- placeholder="Search models, tests, jobs, and components..."
31
- />
32
- </div>
33
-
34
- {/* User Menu */}
35
- <div className="flex items-center space-x-4">
36
- <UserMenu category={8} />
37
- </div>
38
- </div>
39
- </div>
40
- </header>
41
- );
42
- };
@@ -1 +0,0 @@
1
- export { AppHeader } from './AppHeader';
@@ -1,29 +0,0 @@
1
- import { Outlet } from 'react-router-dom';
2
- import { Sidebar } from './Sidebar';
3
- import { AppHeader } from './AppHeader';
4
- import { useSidebar } from './SidebarContext';
5
- import { cn } from '../../atoms/utils/utils';
6
-
7
- export const AppLayout = () => {
8
- const { isExpanded } = useSidebar();
9
-
10
- return (
11
- <div className="min-h-screen bg-background">
12
- {/* Header spans full width */}
13
- <AppHeader />
14
-
15
- {/* Sidebar positioned fixed */}
16
- <Sidebar />
17
-
18
- {/* Main content with proper spacing for fixed sidebar */}
19
- <main
20
- className={cn(
21
- "pt-16 min-h-screen transition-all duration-300 ease-in-out",
22
- isExpanded ? 'ml-64' : 'ml-16'
23
- )}
24
- >
25
- <Outlet />
26
- </main>
27
- </div>
28
- );
29
- };
@@ -1,87 +0,0 @@
1
- import React from 'react';
2
- import { cn } from '../../atoms/utils/utils';
3
- import { getAnimationClasses } from '../../atoms/utils/animations';
4
-
5
- export interface PageTemplateProps {
6
- /** Main page title */
7
- title: string;
8
- /** Optional subtitle/description */
9
- subtitle?: string;
10
- /** Optional icon element to display with title */
11
- icon?: React.ReactNode;
12
- /** Optional action buttons/controls for the header */
13
- actions?: React.ReactNode;
14
- /** Page content */
15
- children: React.ReactNode;
16
- /** Additional CSS classes for the container */
17
- className?: string;
18
- /** Whether to apply animation to the page content */
19
- animated?: boolean;
20
- }
21
-
22
- export const PageTemplate: React.FC<PageTemplateProps> = ({
23
- title,
24
- subtitle,
25
- icon,
26
- actions,
27
- children,
28
- className,
29
- animated = true
30
- }) => {
31
- return (
32
- <div
33
- className={cn(
34
- 'min-h-screen bg-background',
35
- animated && getAnimationClasses({ type: 'subtle', timing: 'slow' }),
36
- className
37
- )}
38
- data-component-name="PageTemplate"
39
- >
40
- {/* Page Header */}
41
- <header className="border-b border-border bg-card/50 backdrop-blur-sm sticky top-0 z-10">
42
- <div className="container mx-auto px-4 sm:px-6 lg:px-8">
43
- <div className="flex items-center justify-between py-6 sm:py-8">
44
- <div className="flex items-center space-x-4 min-w-0 flex-1">
45
- {icon && (
46
- <div className="flex-shrink-0 w-8 h-8 sm:w-10 sm:h-10 flex items-center justify-center rounded bg-primary/10 text-primary">
47
- {icon}
48
- </div>
49
- )}
50
-
51
- <div className="min-w-0 flex-1">
52
- <h1 className="text-2xl sm:text-3xl lg:text-4xl font-bold text-foreground tracking-tight">
53
- {title}
54
- </h1>
55
- {subtitle && (
56
- <p className="mt-2 text-base sm:text-lg text-muted-foreground max-w-3xl">
57
- {subtitle}
58
- </p>
59
- )}
60
- </div>
61
- </div>
62
-
63
- {actions && (
64
- <div className="flex-shrink-0 ml-4">
65
- <div className="flex items-center space-x-3">
66
- {actions}
67
- </div>
68
- </div>
69
- )}
70
- </div>
71
- </div>
72
- </header>
73
-
74
- {/* Page Content */}
75
- <main className="container mx-auto px-4 sm:px-6 lg:px-8 py-6 sm:py-8 lg:py-12">
76
- <div
77
- className={cn(
78
- 'space-y-8',
79
- animated && 'animate-fade-in'
80
- )}
81
- >
82
- {children}
83
- </div>
84
- </main>
85
- </div>
86
- );
87
- };
@@ -1,87 +0,0 @@
1
- import React from 'react';
2
- import { cn } from '../../../atoms/utils/utils';
3
- import { DataBadge } from '../../../atoms/composed/DataBadge';
4
-
5
- export interface SectionHeaderProps {
6
- /** Main heading text */
7
- title: string;
8
- /** Optional description text */
9
- description?: string;
10
- /** Optional subtitle text */
11
- subtitle?: string;
12
- /** Size variant */
13
- size?: 'sm' | 'md' | 'lg';
14
- /** Additional CSS classes */
15
- className?: string;
16
- /** Optional icon element */
17
- icon?: React.ReactNode;
18
- /** Optional badge configuration */
19
- badge?: {
20
- text: string;
21
- variant?: 'category' | 'status';
22
- category?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
23
- status?: 'success' | 'warning' | 'error' | 'info' | 'neutral';
24
- };
25
- }
26
-
27
- export const SectionHeader: React.FC<SectionHeaderProps> = ({
28
- title,
29
- description,
30
- subtitle,
31
- size = 'md',
32
- className,
33
- icon,
34
- badge
35
- }) => {
36
- const titleSizes = {
37
- sm: 'text-lg',
38
- md: 'text-xl',
39
- lg: 'text-2xl'
40
- };
41
-
42
- const spacingSizes = {
43
- sm: 'space-y-1',
44
- md: 'space-y-2',
45
- lg: 'space-y-3'
46
- };
47
-
48
- return (
49
- <div
50
- className={cn(
51
- 'text-center',
52
- spacingSizes[size],
53
- className
54
- )}
55
- data-component-name="SectionHeader"
56
- >
57
- <div className="flex items-center justify-center gap-3">
58
- {icon}
59
- <h3 className={cn('font-semibold text-foreground', titleSizes[size])}>
60
- {title}
61
- </h3>
62
- {badge && (
63
- <DataBadge
64
- variant={badge.variant || 'status'}
65
- status={badge.status}
66
- category={badge.category}
67
- size="sm"
68
- >
69
- {badge.text}
70
- </DataBadge>
71
- )}
72
- </div>
73
-
74
- {subtitle && (
75
- <p className="text-muted-foreground text-sm font-medium">
76
- {subtitle}
77
- </p>
78
- )}
79
-
80
- {description && (
81
- <p className="text-muted-foreground text-sm max-w-2xl mx-auto">
82
- {description}
83
- </p>
84
- )}
85
- </div>
86
- );
87
- };
@@ -1 +0,0 @@
1
- export { SectionHeader, type SectionHeaderProps } from './SectionHeader';