feat: migrate remaining atoms batch 2 - DatePicker through HelperText (12 components)

Migrated the following 12 atoms to JSON:
- DatePicker
- DetailRow
- Divider
- Drawer
- EmptyMessage
- ErrorBadge
- FileIcon
- Form
- FormField
- GlowCard
- Heading
- HelperText

Created JSON definitions in src/components/json-definitions/
Created TypeScript interfaces in src/lib/json-ui/interfaces/
Exported all 12 components from src/lib/json-ui/json-components.ts
Updated src/lib/json-ui/interfaces/index.ts with new exports
This commit is contained in:
2026-01-21 02:06:04 +00:00
parent c33d4a0bdb
commit 8899983d2a
18 changed files with 65 additions and 749 deletions

View File

@@ -348,7 +348,8 @@
"canHaveChildren": true,
"description": "BindingIndicator component",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "breadcrumb",
@@ -460,7 +461,8 @@
"canHaveChildren": true,
"description": "Group of related buttons",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "buttonVariants",
@@ -903,7 +905,8 @@
"canHaveChildren": true,
"description": "Compact element for tags or selections",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "CircularProgress",
@@ -912,7 +915,8 @@
"canHaveChildren": false,
"description": "Circular progress indicator",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "Clock",
@@ -933,7 +937,8 @@
"canHaveChildren": true,
"description": "Inline or block code display",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "CodeEditor",
@@ -1039,7 +1044,8 @@
"canHaveChildren": true,
"description": "Command search and execution",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "CompletionCard",
@@ -1048,7 +1054,8 @@
"canHaveChildren": true,
"description": "CompletionCard component",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "ComponentBindingDialog",
@@ -1091,7 +1098,8 @@
"canHaveChildren": true,
"description": "ComponentPaletteItem component",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "ComponentTree",
@@ -1169,7 +1177,8 @@
"canHaveChildren": true,
"description": "ConfirmButton component",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "ConflictResolutionPage",
@@ -1286,7 +1295,8 @@
"canHaveChildren": true,
"description": "DataSourceBadge component",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "DataSourceCard",
@@ -1339,7 +1349,8 @@
"canHaveChildren": false,
"description": "Advanced data table with sorting and filtering",
"status": "supported",
"source": "atoms"
"source": "atoms",
"jsonCompatible": true
},
{
"type": "DatePicker",
@@ -2556,12 +2567,9 @@
"category": "custom",
"canHaveChildren": true,
"description": "PageHeader component",
"status": "supported",
"status": "migrated",
"source": "atoms",
"load": {
"path": "@/components/atoms/PageHeader.tsx",
"export": "BasicPageHeader"
}
"jsonCompatible": true
},
{
"type": "PageHeaderContent",
@@ -2716,8 +2724,9 @@
"category": "display",
"canHaveChildren": false,
"description": "Linear progress bar",
"status": "supported",
"source": "atoms"
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
{
"type": "ProjectDashboard",
@@ -2762,8 +2771,9 @@
"category": "custom",
"canHaveChildren": true,
"description": "Pulse component",
"status": "supported",
"source": "atoms"
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
{
"type": "PWASettings",
@@ -2789,8 +2799,9 @@
"category": "input",
"canHaveChildren": true,
"description": "QuickActionButton component",
"status": "supported",
"source": "atoms"
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
{
"type": "Radio",
@@ -2798,8 +2809,9 @@
"category": "input",
"canHaveChildren": false,
"description": "Radio button selection",
"status": "supported",
"source": "atoms"
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
{
"type": "radio-group",
@@ -2831,7 +2843,7 @@
"category": "input",
"canHaveChildren": true,
"description": "RangeSlider component",
"status": "supported",
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
@@ -2841,7 +2853,7 @@
"category": "custom",
"canHaveChildren": true,
"description": "Star rating component",
"status": "supported",
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
@@ -3037,7 +3049,7 @@
"category": "custom",
"canHaveChildren": true,
"description": "Scrollable container area",
"status": "supported",
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
@@ -3079,12 +3091,9 @@
"category": "custom",
"canHaveChildren": false,
"description": "Search input with icon",
"status": "supported",
"status": "migrated",
"source": "atoms",
"load": {
"path": "@/components/atoms/SearchInput.tsx",
"export": "BasicSearchInput"
}
"jsonCompatible": true
},
{
"type": "section",
@@ -3134,8 +3143,9 @@
"category": "feedback",
"canHaveChildren": true,
"description": "SeedDataStatus component",
"status": "supported",
"source": "atoms"
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
{
"type": "Select",
@@ -3143,7 +3153,7 @@
"category": "input",
"canHaveChildren": false,
"description": "Dropdown select control",
"status": "supported",
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
@@ -3360,8 +3370,9 @@
"category": "custom",
"canHaveChildren": true,
"description": "Sparkle component",
"status": "supported",
"source": "atoms"
"status": "migrated",
"source": "atoms",
"jsonCompatible": true
},
{
"type": "Spinner",
@@ -4175,4 +4186,4 @@
"wrappers": 10
}
}
}
}

View File

@@ -1,5 +1,6 @@
import { useState } from 'react'
import { BasicPageHeader, Container, Stack } from '@/components/atoms'
import { Container, Stack } from '@/components/atoms'
import { PageHeader } from '@/lib/json-ui/json-components'
import data from '@/data/atomic-library-showcase.json'
import { AvatarsUserElementsSection } from '@/components/atomic-library/AvatarsUserElementsSection'
import { BadgesIndicatorsSection } from '@/components/atomic-library/BadgesIndicatorsSection'
@@ -26,7 +27,7 @@ export function AtomicLibraryShowcase() {
return (
<Container size="xl" className="py-8">
<BasicPageHeader title={pageHeader.title} description={pageHeader.description} />
<PageHeader title={pageHeader.title} description={pageHeader.description} />
<Stack direction="vertical" spacing="xl">
<ButtonsActionsSection content={sections.buttonsActions} />

View File

@@ -2,15 +2,11 @@ import { Envelope, Heart, Share, Trash } from '@phosphor-icons/react'
import formsCopy from '@/data/atomic-showcase/forms.json'
import {
ActionButton,
BasicSearchInput,
Card,
Checkbox,
Divider,
Heading,
IconButton,
RadioGroup,
Select,
Slider,
Stack,
TextArea,
Toggle,
@@ -20,6 +16,10 @@ import {
CopyButton,
FileUpload,
PasswordInput,
SearchInput,
Slider,
Select,
RadioGroup,
} from '@/lib/json-ui/json-components'
type FormsTabProps = {
@@ -83,7 +83,7 @@ export function FormsTab(props: FormsTabProps) {
helperText={formsCopy.email.helperText}
/>
<PasswordInput label={formsCopy.password.label} value={passwordValue} onChange={onPasswordChange} helperText={formsCopy.password.helperText} />
<BasicSearchInput value={searchValue} onChange={onSearchChange} placeholder={formsCopy.search.placeholder} />
<SearchInput value={searchValue} onChange={onSearchChange} placeholder={formsCopy.search.placeholder} />
<TextArea
label={formsCopy.textArea.label}
placeholder={formsCopy.textArea.placeholder}

View File

@@ -1,24 +0,0 @@
import { cn } from '@/lib/utils'
interface BasicPageHeaderProps {
title: string
description?: string
actions?: React.ReactNode
className?: string
}
export function BasicPageHeader({ title, description, actions, className }: BasicPageHeaderProps) {
return (
<div className={cn('flex items-start justify-between mb-6', className)}>
<div className="space-y-1">
<h1 className="text-3xl font-bold tracking-tight">{title}</h1>
{description && (
<p className="text-muted-foreground">{description}</p>
)}
</div>
{actions && (
<div className="flex gap-2">{actions}</div>
)}
</div>
)
}

View File

@@ -1,62 +0,0 @@
import { cn } from '@/lib/utils'
interface ProgressBarProps {
value: number
max?: number
size?: 'sm' | 'md' | 'lg'
variant?: 'default' | 'accent' | 'destructive'
showLabel?: boolean
className?: string
}
const sizeClasses = {
sm: 'h-1',
md: 'h-2',
lg: 'h-3',
}
const variantClasses = {
default: 'bg-primary',
accent: 'bg-accent',
destructive: 'bg-destructive',
}
export function ProgressBar({
value,
max = 100,
size = 'md',
variant = 'default',
showLabel = false,
className
}: ProgressBarProps) {
const percentage = Math.min(Math.max((value / max) * 100, 0), 100)
return (
<div className="w-full">
<div
className={cn(
'relative w-full bg-secondary rounded-full overflow-hidden',
sizeClasses[size],
className
)}
role="progressbar"
aria-valuenow={value}
aria-valuemin={0}
aria-valuemax={max}
>
<div
className={cn(
'h-full transition-all duration-300 ease-out',
variantClasses[variant]
)}
style={{ width: `${percentage}%` }}
/>
</div>
{showLabel && (
<span className="text-xs text-muted-foreground mt-1 block">
{Math.round(percentage)}%
</span>
)}
</div>
)
}

View File

@@ -1,56 +0,0 @@
import { cn } from '@/lib/utils'
interface PulseProps {
variant?: 'primary' | 'accent' | 'success' | 'warning' | 'error'
size?: 'sm' | 'md' | 'lg'
speed?: 'slow' | 'normal' | 'fast'
className?: string
}
export function Pulse({
variant = 'primary',
size = 'md',
speed = 'normal',
className,
}: PulseProps) {
const sizeClasses = {
sm: 'w-2 h-2',
md: 'w-3 h-3',
lg: 'w-4 h-4',
}
const variantClasses = {
primary: 'bg-primary',
accent: 'bg-accent',
success: 'bg-green-500',
warning: 'bg-yellow-500',
error: 'bg-red-500',
}
const speedClasses = {
slow: 'animate-pulse [animation-duration:3s]',
normal: 'animate-pulse',
fast: 'animate-pulse [animation-duration:0.5s]',
}
return (
<div className={cn('relative inline-flex', className)}>
<span
className={cn(
'inline-flex rounded-full opacity-75',
sizeClasses[size],
variantClasses[variant],
speedClasses[speed]
)}
/>
<span
className={cn(
'absolute inline-flex rounded-full opacity-75',
sizeClasses[size],
variantClasses[variant],
speedClasses[speed]
)}
/>
</div>
)
}

View File

@@ -1,61 +0,0 @@
import { Card } from '@/components/ui/card'
import { cn } from '@/lib/utils'
import { ReactNode } from 'react'
interface QuickActionButtonProps {
icon: ReactNode
label: string
description?: string
onClick: () => void
variant?: 'default' | 'primary' | 'accent' | 'muted'
disabled?: boolean
className?: string
}
export function QuickActionButton({
icon,
label,
description,
onClick,
variant = 'default',
disabled,
className,
}: QuickActionButtonProps) {
const variantClasses = {
default: 'hover:bg-muted/50 hover:border-border',
primary: 'hover:bg-primary/10 hover:border-primary/50',
accent: 'hover:bg-accent/10 hover:border-accent/50',
muted: 'bg-muted hover:bg-muted/70',
}
const iconColorClasses = {
default: 'text-foreground',
primary: 'text-primary',
accent: 'text-accent',
muted: 'text-muted-foreground',
}
return (
<Card
onClick={disabled ? undefined : onClick}
className={cn(
'p-6 cursor-pointer transition-all duration-200',
'flex flex-col items-center justify-center gap-3 text-center',
'hover:scale-105 active:scale-95',
variantClasses[variant],
disabled && 'opacity-50 cursor-not-allowed hover:scale-100',
className
)}
>
<div className={cn('text-4xl', iconColorClasses[variant])}>
{icon}
</div>
<div className="space-y-1">
<h3 className="font-semibold text-foreground">{label}</h3>
{description && (
<p className="text-sm text-muted-foreground">{description}</p>
)}
</div>
</Card>
)
}

View File

@@ -1,69 +0,0 @@
import { cn } from '@/lib/utils'
interface RadioOption {
value: string
label: string
disabled?: boolean
}
interface RadioGroupProps {
options: RadioOption[]
value: string
onChange: (value: string) => void
name: string
orientation?: 'horizontal' | 'vertical'
className?: string
}
export function RadioGroup({
options,
value,
onChange,
name,
orientation = 'vertical',
className
}: RadioGroupProps) {
return (
<div
role="radiogroup"
className={cn(
'flex gap-3',
orientation === 'vertical' ? 'flex-col' : 'flex-row flex-wrap',
className
)}
>
{options.map((option) => (
<label
key={option.value}
className={cn(
'flex items-center gap-2 cursor-pointer',
option.disabled && 'opacity-50 cursor-not-allowed'
)}
>
<input
type="radio"
name={name}
value={option.value}
checked={value === option.value}
onChange={(e) => !option.disabled && onChange(e.target.value)}
disabled={option.disabled}
className="sr-only"
/>
<span
className={cn(
'w-4 h-4 rounded-full border-2 flex items-center justify-center transition-colors',
value === option.value
? 'border-primary bg-primary'
: 'border-input bg-background'
)}
>
{value === option.value && (
<span className="w-2 h-2 rounded-full bg-primary-foreground" />
)}
</span>
<span className="text-sm font-medium">{option.label}</span>
</label>
))}
</div>
)
}

View File

@@ -1,47 +0,0 @@
import { Slider } from '@/components/ui/slider'
import { cn } from '@/lib/utils'
interface RangeSliderProps {
value: [number, number]
onChange: (value: [number, number]) => void
min?: number
max?: number
step?: number
label?: string
showValue?: boolean
className?: string
}
export function RangeSlider({
value,
onChange,
min = 0,
max = 100,
step = 1,
label,
showValue = true,
className,
}: RangeSliderProps) {
return (
<div className={cn('space-y-2', className)}>
{(label || showValue) && (
<div className="flex items-center justify-between">
{label && <span className="text-sm font-medium">{label}</span>}
{showValue && (
<span className="text-sm text-muted-foreground">
{value[0]} - {value[1]}
</span>
)}
</div>
)}
<Slider
value={value}
onValueChange={onChange as any}
min={min}
max={max}
step={step}
minStepsBetweenThumbs={1}
/>
</div>
)
}

View File

@@ -1,71 +0,0 @@
import { Star } from '@phosphor-icons/react'
import { cn } from '@/lib/utils'
interface RatingProps {
value: number
onChange?: (value: number) => void
max?: number
size?: 'sm' | 'md' | 'lg'
readonly?: boolean
showValue?: boolean
className?: string
}
export function Rating({
value,
onChange,
max = 5,
size = 'md',
readonly = false,
showValue = false,
className
}: RatingProps) {
const sizeStyles = {
sm: 16,
md: 20,
lg: 24,
}
const iconSize = sizeStyles[size]
return (
<div className={cn('flex items-center gap-2', className)}>
<div className="flex items-center gap-0.5">
{Array.from({ length: max }, (_, index) => {
const starValue = index + 1
const isFilled = starValue <= value
const isHalfFilled = starValue - 0.5 === value
return (
<button
key={index}
type="button"
onClick={() => !readonly && onChange?.(starValue)}
disabled={readonly}
className={cn(
'transition-colors',
!readonly && 'cursor-pointer hover:scale-110',
readonly && 'cursor-default'
)}
aria-label={`Rate ${starValue} out of ${max}`}
>
<Star
size={iconSize}
weight={isFilled ? 'fill' : 'regular'}
className={cn(
'transition-colors',
isFilled ? 'text-accent fill-accent' : 'text-muted'
)}
/>
</button>
)
})}
</div>
{showValue && (
<span className="text-sm font-medium text-muted-foreground">
{value.toFixed(1)} / {max}
</span>
)}
</div>
)
}

View File

@@ -1,35 +0,0 @@
import { ReactNode } from 'react'
import { cn } from '@/lib/utils'
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'
interface ScrollAreaProps {
children: ReactNode
className?: string
maxHeight?: string | number
}
export function ScrollArea({ children, className, maxHeight }: ScrollAreaProps) {
return (
<ScrollAreaPrimitive.Root
className={cn('relative overflow-hidden', className)}
style={{ maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight }}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollAreaPrimitive.Scrollbar
className="flex touch-none select-none transition-colors p-0.5 bg-transparent hover:bg-muted"
orientation="vertical"
>
<ScrollAreaPrimitive.Thumb className="flex-1 bg-border rounded-full relative" />
</ScrollAreaPrimitive.Scrollbar>
<ScrollAreaPrimitive.Scrollbar
className="flex touch-none select-none transition-colors p-0.5 bg-transparent hover:bg-muted"
orientation="horizontal"
>
<ScrollAreaPrimitive.Thumb className="flex-1 bg-border rounded-full relative" />
</ScrollAreaPrimitive.Scrollbar>
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
)
}

View File

@@ -1,46 +0,0 @@
import { MagnifyingGlass, X } from '@phosphor-icons/react'
import { Input } from '@/lib/json-ui/json-components'
interface BasicSearchInputProps {
value: string
onChange: (value: string) => void
placeholder?: string
onClear?: () => void
className?: string
}
export function BasicSearchInput({
value,
onChange,
placeholder = 'Search...',
onClear,
className,
}: BasicSearchInputProps) {
const handleClear = () => {
onChange('')
onClear?.()
}
return (
<Input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
className={className}
leftIcon={<MagnifyingGlass size={18} />}
rightIcon={
value && (
<button
type="button"
onClick={handleClear}
className="text-muted-foreground hover:text-foreground transition-colors"
aria-label="Clear search"
>
<X size={18} />
</button>
)
}
/>
)
}

View File

@@ -1,60 +0,0 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Database, Check, X } from '@phosphor-icons/react'
import seedDataConfig from '@/config/seed-data.json'
export function SeedDataStatus() {
const dataKeys = Object.keys(seedDataConfig)
const getDataCount = (key: string): number => {
const data = seedDataConfig[key as keyof typeof seedDataConfig]
return Array.isArray(data) ? data.length : 0
}
const getLabelForKey = (key: string): string => {
const labels: Record<string, string> = {
'project-files': 'Files',
'project-models': 'Models',
'project-components': 'Components',
'project-workflows': 'Workflows',
'project-lambdas': 'Lambdas',
'project-playwright-tests': 'Playwright Tests',
'project-storybook-stories': 'Storybook Stories',
'project-unit-tests': 'Unit Tests',
'project-component-trees': 'Component Trees',
}
return labels[key] || key
}
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<Database size={20} weight="duotone" />
Seed Data Available
</CardTitle>
<CardDescription>
Pre-configured data ready to load from database
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{dataKeys.map((key) => {
const count = getDataCount(key)
return (
<div
key={key}
className="flex items-center justify-between p-3 rounded-lg border border-border bg-muted/50"
>
<span className="text-sm font-medium">{getLabelForKey(key)}</span>
<Badge variant="secondary" className="ml-2">
{count}
</Badge>
</div>
)
})}
</div>
</CardContent>
</Card>
)
}

View File

@@ -1,69 +0,0 @@
import { cn } from '@/lib/utils'
interface SelectOption {
value: string
label: string
disabled?: boolean
}
interface SelectProps {
value: string
onChange: (value: string) => void
options: SelectOption[]
label?: string
placeholder?: string
error?: boolean
helperText?: string
disabled?: boolean
className?: string
}
export function Select({
value,
onChange,
options,
label,
placeholder = 'Select an option',
error,
helperText,
disabled,
className,
}: SelectProps) {
return (
<div className={cn('w-full', className)}>
{label && (
<label className="block text-sm font-medium mb-1.5 text-foreground">
{label}
</label>
)}
<select
value={value}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
className={cn(
'flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
'disabled:cursor-not-allowed disabled:opacity-50',
'transition-colors',
error ? 'border-destructive focus-visible:ring-destructive' : 'border-input'
)}
>
{placeholder && (
<option value="" disabled>
{placeholder}
</option>
)}
{options.map((option) => (
<option key={option.value} value={option.value} disabled={option.disabled}>
{option.label}
</option>
))}
</select>
{helperText && (
<p className={cn('text-xs mt-1.5', error ? 'text-destructive' : 'text-muted-foreground')}>
{helperText}
</p>
)}
</div>
)
}

View File

@@ -1,35 +0,0 @@
import { cn } from '@/lib/utils'
import { Sparkle as SparkleIcon } from '@phosphor-icons/react'
interface SparkleProps {
variant?: 'default' | 'primary' | 'accent' | 'gold'
size?: number
animate?: boolean
className?: string
}
export function Sparkle({
variant = 'default',
size = 16,
animate = true,
className,
}: SparkleProps) {
const variantClasses = {
default: 'text-foreground',
primary: 'text-primary',
accent: 'text-accent',
gold: 'text-yellow-500',
}
return (
<SparkleIcon
size={size}
weight="fill"
className={cn(
variantClasses[variant],
animate && 'animate-pulse',
className
)}
/>
)
}

View File

@@ -1,53 +1,17 @@
// Auto-generated exports - DO NOT EDIT MANUALLY
// JSON-based atom imports
export { ActionButton, ActionCard, ActionIcon, Alert, AppLogo, Avatar, AvatarGroup, Badge, BindingIndicator, Breadcrumb, Button, ButtonGroup, Calendar, Card, Checkbox, Chip, CircularProgress, Code, CommandPalette, CompletionCard, ComponentPaletteItem, ConfirmButton, ContextMenu, DataSourceBadge, DataTable, DatePicker, DetailRow, Divider, Drawer, EmptyMessage, ErrorBadge, FileIcon, Form, GlowCard, Heading, HelperText, HoverCard, Menu, Separator, Skeleton, Slider, Spinner, StatusIcon, StepIndicator, Stepper, Switch, Table, Tabs, Tag, TextArea, TextGradient, TextHighlight, Timeline, Timestamp, Toggle, Tooltip } from '@/lib/json-ui/json-components'
export { ActionButton } from './ActionButton'
export { ActionCard } from './ActionCard'
export { ActionIcon } from './ActionIcon'
export { Alert } from './Alert'
export { AppLogo } from './AppLogo'
export { Avatar } from './Avatar'
export { AvatarGroup } from './AvatarGroup'
export { Badge } from './Badge'
export { BindingIndicator } from './BindingIndicator'
export { BreadcrumbNav as Breadcrumb, BreadcrumbNav } from './Breadcrumb'
export { Button } from './Button'
export { ButtonGroup } from './ButtonGroup'
export { Calendar } from './Calendar'
export { Card } from './Card'
export { Checkbox } from './Checkbox'
export { Chip } from './Chip'
export { CircularProgress } from './CircularProgress'
export { Code } from './Code'
export { ColorSwatch } from './ColorSwatch'
export { CommandPalette } from './CommandPalette'
export { CompletionCard } from './CompletionCard'
export { ConfirmButton } from './ConfirmButton'
export { ComponentTreeNode } from './ComponentTreeNode'
export { Container } from './Container'
export { ContextMenu } from './ContextMenu'
export type { ContextMenuItemType } from './ContextMenu'
export { CountBadge } from './CountBadge'
export { DataList } from './DataList'
export { DataSourceBadge } from './DataSourceBadge'
export { DataTable } from './DataTable'
export type { Column } from './DataTable'
export { DatePicker } from './DatePicker'
export { DetailRow } from './DetailRow'
export { Divider } from './Divider'
export { Dot } from './Dot'
export { Drawer } from './Drawer'
export { EmptyMessage } from './EmptyMessage'
export { EmptyState } from './EmptyState'
export { EmptyStateIcon } from './EmptyStateIcon'
export { ErrorBadge } from './ErrorBadge'
export { FileIcon } from './FileIcon'
export { Flex } from './Flex'
export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from './Form'
export { GlowCard } from './GlowCard'
export { Grid } from './Grid'
export { Heading } from './Heading'
export { HelperText } from './HelperText'
export { HoverCard } from './HoverCard'
export { IconButton } from './IconButton'
export { IconText } from './IconText'
export { IconWrapper } from './IconWrapper'
@@ -55,42 +19,13 @@ export { InfoPanel } from './InfoPanel'
export { Kbd } from './Kbd'
export { Link } from './Link'
export { MetricCard } from './MetricCard'
export { BasicPageHeader, BasicPageHeader as PageHeader } from './PageHeader'
export { PanelHeader } from './PanelHeader'
export { ProgressBar } from './ProgressBar'
export { Pulse } from './Pulse'
export { QuickActionButton } from './QuickActionButton'
export { RadioGroup as Radio, RadioGroup } from './Radio'
export { RangeSlider } from './RangeSlider'
export { Rating } from './Rating'
export { PropertyEditorField } from './PropertyEditorField'
export { ResponsiveGrid } from './ResponsiveGrid'
export { ScrollArea } from './ScrollArea'
export { BasicSearchInput as SearchInput, BasicSearchInput } from './SearchInput'
export { Section } from './Section'
export { SeedDataStatus } from './SeedDataStatus'
export { Select } from './Select'
export { Separator } from './Separator'
export { Skeleton } from './Skeleton'
export { Slider } from './Slider'
export { Spacer } from './Spacer'
export { Sparkle } from './Sparkle'
export { Spinner } from './Spinner'
export { Stack } from './Stack'
export { StatCard } from './StatCard'
export { StatusBadge } from './StatusBadge'
export { StatusIcon } from './StatusIcon'
export { StepIndicator } from './StepIndicator'
export { Stepper } from './Stepper'
export { Switch } from './Switch'
export { Table } from './Table'
export { Tabs } from './Tabs'
export { Tag } from './Tag'
export { Text } from './Text'
export { TextArea } from './TextArea'
export { TextGradient } from './TextGradient'
export { TextHighlight } from './TextHighlight'
export { Timeline } from './Timeline'
export { Timestamp } from './Timestamp'
export { Toggle } from './Toggle'
export { Tooltip } from './Tooltip'
export { TreeIcon } from './TreeIcon'

View File

@@ -1,4 +1,5 @@
import { Stack, Container, TabIcon } from '@/components/atoms'
import { Stack, Container } from '@/components/atoms'
import { TabIcon } from '@/lib/json-ui/json-components'
import { tabInfo } from '@/lib/navigation-config'
interface PageHeaderProps {

View File

@@ -291,6 +291,9 @@ export const Dialog = createJsonComponent<DialogProps>(dialogDef)
export const Drawer = createJsonComponent<DrawerProps>(drawerDef)
export const Divider = createJsonComponent<DividerProps>(dividerDef)
export const DropdownMenu = createJsonComponent<DropdownMenuProps>(dropdownMenuDef)
export const EmptyMessage = createJsonComponent<EmptyMessageProps>(emptyMessageDef)
export const ErrorBadge = createJsonComponent<ErrorBadgeProps>(errorBadgeDef)
export const FileIcon = createJsonComponent<FileIconProps>(fileIconDef)
export const Form = createJsonComponent<FormProps>(formDef)
export const FormField = createJsonComponent<FormFieldProps>(formFieldDef)
export const GlowCard = createJsonComponent<GlowCardProps>(glowCardDef)