Files
low-code-react-app-b/src/components/AtomicComponentDemo.tsx
johndoe6345789 4dfded3533 Generated by Spark: @johndoe6345789 ➜ /workspaces/low-code-react-app-b (main) $ npm run build
> spark-template@0.0.0 prebuild
> mkdir -p /tmp/dist || true

> spark-template@0.0.0 build
> tsc -b --noCheck && vite build

vite v7.3.1 building client environment for production...
<script src="/runtime-config.js"> in "/index.html" can't be bundled without type="module" attribute
✓ 37 modules transformed.
✗ Build failed in 1.07s
error during build:
[vite]: Rollup failed to resolve import "@github/spark/hooks" from "/workspaces/low-code-react-app-b/src/hooks/use-project-state.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
    at viteLog (file:///workspaces/low-code-react-app-b/node_modules/vite/dist/node/chunks/config.js:33635:57)
    at file:///workspaces/low-code-react-app-b/node_modules/vite/dist/node/chunks/config.js:33669:73
    at onwarn (file:///workspaces/low-code-react-app-b/node_modules/@vitejs/plugin-react-swc/index.js:76:7)
    at file:///workspaces/low-code-react-app-b/node_modules/vite/dist/node/chunks/config.js:33669:28
    at onRollupLog (file:///workspaces/low-code-react-app-b/node_modules/vite/dist/node/chunks/config.js:33664:63)
    at onLog (file:///workspaces/low-code-react-app-b/node_modules/vite/dist/node/chunks/config.js:33467:4)
    at file:///workspaces/low-code-react-app-b/node_modules/rollup/dist/es/shared/node-entry.js:20961:32
    at Object.logger [as onLog] (file:///workspaces/low-code-react-app-b/node_modules/rollup/dist/es/shared/node-entry.js:22848:9)
    at ModuleLoader.handleInvalidResolvedId (file:///workspaces/low-code-react-app-b/node_modules/rollup/dist/es/shared/node-entry.js:21592:26)
    at file:///workspaces/low-code-react-app-b/node_modules/rollup/dist/es/shared/node-entry.js:21550:26
@johndoe6345789 ➜ /workspaces/low-code-react-app-b (main) $
2026-01-17 19:39:46 +00:00

146 lines
4.3 KiB
TypeScript

import { useCRUD, useSearchFilter } from '@/hooks/data'
import { useToggle, useDialog } from '@/hooks/ui'
import { useKV } from '@/hooks/use-kv'
import { Button } from '@/components/ui/button'
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { SearchInput, DataCard, ActionBar } from '@/components/molecules'
import { Grid, Heading, StatusBadge } from '@/components/atoms'
import { Plus, Trash, Eye } from '@phosphor-icons/react'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
interface Task {
id: number
title: string
status: 'active' | 'pending' | 'success'
priority: 'high' | 'medium' | 'low'
}
export function AtomicComponentDemo() {
const [tasks, setTasks] = useKV<Task[]>('demo-tasks', [
{ id: 1, title: 'Build component library', status: 'active', priority: 'high' },
{ id: 2, title: 'Write documentation', status: 'pending', priority: 'medium' },
{ id: 3, title: 'Create examples', status: 'success', priority: 'low' },
])
const crud = useCRUD<Task>({ items: tasks, setItems: setTasks })
const { searchQuery: query, setSearchQuery: setQuery, filtered } = useSearchFilter({
items: tasks,
searchFields: ['title'],
})
const showCompleted = useToggle({ initial: true })
const addDialog = useDialog()
const displayedTasks = showCompleted.value
? filtered
: filtered.filter(t => t.status !== 'success')
const handleAddTask = () => {
crud.create({
id: Date.now(),
title: 'New Task',
status: 'pending',
priority: 'medium',
})
addDialog.close()
}
const stats = {
total: tasks.length,
active: tasks.filter(t => t.status === 'active').length,
completed: tasks.filter(t => t.status === 'success').length,
}
return (
<div className="h-full overflow-auto p-6 space-y-6">
<div>
<Heading level={1} className="mb-2">
Atomic Component Demo
</Heading>
<p className="text-muted-foreground">
Demonstrating custom hooks and atomic components
</p>
</div>
<Grid cols={3} gap={4}>
<DataCard title="Total Tasks" value={stats.total} />
<DataCard title="Active" value={stats.active} />
<DataCard title="Completed" value={stats.completed} />
</Grid>
<ActionBar
title="Tasks"
actions={[
{
label: 'Add Task',
icon: <Plus size={16} />,
onClick: addDialog.open,
variant: 'default',
},
{
label: showCompleted.value ? 'Hide Completed' : 'Show Completed',
icon: <Eye size={16} />,
onClick: showCompleted.toggle,
variant: 'outline',
},
]}
/>
<SearchInput
value={query}
onChange={setQuery}
placeholder="Search tasks..."
/>
<div className="space-y-3">
{displayedTasks.map(task => (
<Card key={task.id}>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle className="text-lg">{task.title}</CardTitle>
<div className="flex items-center gap-2">
<StatusBadge status={task.status} />
<Button
variant="ghost"
size="sm"
onClick={() => crud.delete(task.id)}
>
<Trash size={16} />
</Button>
</div>
</div>
</CardHeader>
<CardContent>
<div className="text-sm text-muted-foreground">
Priority: {task.priority}
</div>
</CardContent>
</Card>
))}
</div>
{displayedTasks.length === 0 && (
<Card>
<CardContent className="py-12 text-center text-muted-foreground">
No tasks found
</CardContent>
</Card>
)}
<Dialog open={addDialog.isOpen} onOpenChange={addDialog.setOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Add New Task</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<Button onClick={handleAddTask} className="w-full">
Add Task
</Button>
</div>
</DialogContent>
</Dialog>
</div>
)
}