Files
metabuilder/components/index.tsx
johndoe6345789 8fcc71d530 refactor: Consolidate frontends/nextjs into root hooks and components
Hooks consolidation:
- frontends/nextjs now imports from @metabuilder/hooks
- Deleted empty directories (data/, use-dbal/, __tests__/)
- Deleted outdated documentation
- Added @metabuilder/hooks dependency to package.json
- Kept NextJS-specific auth hooks locally (have @/lib/* dependencies)
- Added missing useWorkflowExecutions export to root hooks

Components consolidation:
- Deleted duplicates: Skeleton, LoadingIndicator, EmptyState, ErrorBoundary, AccessDenied
- Created new /components/vanilla/access-denied/ component
- Updated /components exports and package.json
- frontends/nextjs/src/components/index.ts now re-exports from @metabuilder/components
- Updated imports in LoadingSkeleton, EmptyStateShowcase, page.tsx

Organization principle: Project-specific code is fine in root folders
as long as it's well organized.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:37:35 +00:00

157 lines
3.9 KiB
TypeScript

/**
* @metabuilder/components
*
* Shared React components for MetaBuilder projects.
* Organized by UI library dependency:
*
* - vanilla/ - Pure React components (no external UI library)
* - radix/ - Radix UI based components (shadcn style)
* - fakemui/ - FakeMUI based components (Material Design 3)
*/
// =============================================================================
// VANILLA COMPONENTS (Pure React, no external UI library)
// =============================================================================
// Loading components
export {
LoadingIndicator,
InlineLoader,
AsyncLoading,
loadingStyles,
type LoadingIndicatorProps,
type InlineLoaderProps,
type AsyncLoadingProps,
} from './vanilla/loading'
// Error handling components
export {
ErrorBoundary,
withErrorBoundary,
ErrorDisplay,
type ErrorBoundaryProps,
type ErrorReporter,
type ErrorDisplayProps,
} from './vanilla/error'
// Empty state components
export {
EmptyState,
NoDataFound,
NoResultsFound,
NoItemsYet,
AccessDeniedState,
ErrorState,
NoConnectionState,
LoadingCompleteState,
emptyStateStyles,
type EmptyStateProps,
} from './vanilla/empty-state'
// Skeleton components
export {
Skeleton,
TableSkeleton,
CardSkeleton,
ListSkeleton,
FormSkeleton,
AvatarSkeleton,
TextSkeleton,
skeletonStyles,
type SkeletonProps,
type TableSkeletonProps,
type CardSkeletonProps,
type ListSkeletonProps,
type FormSkeletonProps,
type AvatarSkeletonProps,
type TextSkeletonProps,
} from './vanilla/skeleton'
// Access denied component
export {
AccessDenied,
accessDeniedStyles,
type AccessDeniedProps,
} from './vanilla/access-denied'
// =============================================================================
// RADIX COMPONENTS (Built on @radix-ui primitives)
// =============================================================================
// Add Radix component exports here as they are created
// export * from './radix'
// =============================================================================
// FAKEMUI COMPONENTS (Built on @metabuilder/fakemui)
// =============================================================================
// Add FakeMUI component exports here as they are created
// export * from './fakemui'
// =============================================================================
// COMBINED STYLES
// =============================================================================
/**
* Combined styles for all components
* Inject these into your global CSS or use a style tag
*
* @example
* // In your app's entry point:
* import { allStyles } from '@metabuilder/components'
*
* // Option 1: Inject via style tag
* const styleTag = document.createElement('style')
* styleTag.textContent = allStyles
* document.head.appendChild(styleTag)
*
* // Option 2: Import from a CSS file that includes these styles
*/
export const allStyles = `
/* Loading animations */
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes pulse-animation {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(0.8); }
}
@keyframes progress-animation {
0% { width: 0%; }
50% { width: 70%; }
100% { width: 100%; }
}
@keyframes dots-animation {
0%, 80%, 100% { opacity: 0; transform: scale(0); }
40% { opacity: 1; transform: scale(1); }
}
/* Empty state animations */
.empty-state-animated {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Skeleton animations */
@keyframes skeleton-pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
.skeleton-animate {
animation: skeleton-pulse 1.5s ease-in-out infinite;
}
/* Accessibility: respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
.empty-state-animated,
.skeleton-animate,
.loading-spinner {
animation: none;
}
}
`